1 /*
2  * Copyright (C) 2008 - 2011 Murray Cumming <murrayc@murrayc.com>
3  * Copyright (C) 2008 - 2013 Vivien Malerba <malerba@gnome-db.org>
4  * Copyright (C) 2009 Bas Driessen <bas.driessen@xobas.com>
5  * Copyright (C) 2010 David King <davidk@openismus.com>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA  02110-1301, USA.
21  */
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <errno.h>
26 #include <string.h>
27 #include <glib/gi18n-lib.h>
28 #include <glib/gstdio.h>
29 #include <libgda/libgda.h>
30 #include <libgda/gda-data-model-private.h>
31 #include <libgda/gda-server-provider-extra.h>
32 #include <libgda/binreloc/gda-binreloc.h>
33 #include <libgda/gda-statement-extra.h>
34 #include <sql-parser/gda-sql-parser.h>
35 #include "gda-jdbc.h"
36 #include "gda-jdbc-provider.h"
37 #include "gda-jdbc-recordset.h"
38 #include "gda-jdbc-ddl.h"
39 #include "gda-jdbc-meta.h"
40 #include "gda-jdbc-util.h"
41 #include "jni-wrapper.h"
42 #include "jni-globals.h"
43 #include "jdbc-resources.h"
44 #include <libgda/gda-debug-macros.h>
45 
46 #define _GDA_PSTMT(x) ((GdaPStmt*)(x))
47 
48 /*
49  * GObject methods
50  */
51 static void gda_jdbc_provider_class_init (GdaJdbcProviderClass *klass);
52 static void gda_jdbc_provider_init       (GdaJdbcProvider *provider,
53 					  GdaJdbcProviderClass *klass);
54 static GObjectClass *parent_class = NULL;
55 
56 /*
57  * GdaServerProvider's virtual methods
58  */
59 /* connection management */
60 static gboolean            gda_jdbc_provider_open_connection (GdaServerProvider *provider, GdaConnection *cnc,
61 							      GdaQuarkList *params, GdaQuarkList *auth,
62 							      guint *task_id, GdaServerProviderAsyncCallback async_cb, gpointer cb_data);
63 static gboolean            gda_jdbc_provider_close_connection (GdaServerProvider *provider, GdaConnection *cnc);
64 static const gchar        *gda_jdbc_provider_get_server_version (GdaServerProvider *provider, GdaConnection *cnc);
65 
66 /* DDL operations */
67 static gboolean            gda_jdbc_provider_supports_operation (GdaServerProvider *provider, GdaConnection *cnc,
68 								 GdaServerOperationType type, GdaSet *options);
69 static GdaServerOperation *gda_jdbc_provider_create_operation (GdaServerProvider *provider, GdaConnection *cnc,
70 							       GdaServerOperationType type,
71 							       GdaSet *options, GError **error);
72 static gchar              *gda_jdbc_provider_render_operation (GdaServerProvider *provider, GdaConnection *cnc,
73 							       GdaServerOperation *op, GError **error);
74 
75 static gboolean            gda_jdbc_provider_perform_operation (GdaServerProvider *provider, GdaConnection *cnc,
76 								GdaServerOperation *op, guint *task_id,
77 								GdaServerProviderAsyncCallback async_cb, gpointer cb_data,
78 								GError **error);
79 /* transactions */
80 static gboolean            gda_jdbc_provider_begin_transaction (GdaServerProvider *provider, GdaConnection *cnc,
81 								const gchar *name, GdaTransactionIsolation level, GError **error);
82 static gboolean            gda_jdbc_provider_commit_transaction (GdaServerProvider *provider, GdaConnection *cnc,
83 								 const gchar *name, GError **error);
84 static gboolean            gda_jdbc_provider_rollback_transaction (GdaServerProvider *provider, GdaConnection * cnc,
85 								   const gchar *name, GError **error);
86 static gboolean            gda_jdbc_provider_add_savepoint (GdaServerProvider *provider, GdaConnection *cnc,
87 							    const gchar *name, GError **error);
88 static gboolean            gda_jdbc_provider_rollback_savepoint (GdaServerProvider *provider, GdaConnection *cnc,
89 								 const gchar *name, GError **error);
90 static gboolean            gda_jdbc_provider_delete_savepoint (GdaServerProvider *provider, GdaConnection *cnc,
91 							       const gchar *name, GError **error);
92 
93 /* information retrieval */
94 static const gchar        *gda_jdbc_provider_get_version (GdaServerProvider *provider);
95 static gboolean            gda_jdbc_provider_supports_feature (GdaServerProvider *provider, GdaConnection *cnc,
96 							       GdaConnectionFeature feature);
97 
98 static const gchar        *gda_jdbc_provider_get_name (GdaServerProvider *provider);
99 
100 static GdaDataHandler     *gda_jdbc_provider_get_data_handler (GdaServerProvider *provider, GdaConnection *cnc,
101 							       GType g_type, const gchar *dbms_type);
102 
103 static const gchar*        gda_jdbc_provider_get_default_dbms_type (GdaServerProvider *provider, GdaConnection *cnc,
104 								    GType type);
105 /* statements */
106 static gchar               *gda_jdbc_provider_statement_to_sql  (GdaServerProvider *provider, GdaConnection *cnc,
107 								 GdaStatement *stmt, GdaSet *params,
108 								 GdaStatementSqlFlag flags,
109 								 GSList **params_used, GError **error);
110 static gboolean             gda_jdbc_provider_statement_prepare (GdaServerProvider *provider, GdaConnection *cnc,
111 								 GdaStatement *stmt, GError **error);
112 static GObject             *gda_jdbc_provider_statement_execute (GdaServerProvider *provider, GdaConnection *cnc,
113 								 GdaStatement *stmt, GdaSet *params,
114 								 GdaStatementModelUsage model_usage,
115 								 GType *col_types, GdaSet **last_inserted_row,
116 								 guint *task_id, GdaServerProviderExecCallback async_cb,
117 								 gpointer cb_data, GError **error);
118 static GdaSqlStatement     *gda_jdbc_statement_rewrite          (GdaServerProvider *provider, GdaConnection *cnc,
119 								 GdaStatement *stmt, GdaSet *params, GError **error);
120 
121 
122 /* distributed transactions */
123 static gboolean gda_jdbc_provider_xa_start    (GdaServerProvider *provider, GdaConnection *cnc,
124 						   const GdaXaTransactionId *xid, GError **error);
125 
126 static gboolean gda_jdbc_provider_xa_end      (GdaServerProvider *provider, GdaConnection *cnc,
127 						   const GdaXaTransactionId *xid, GError **error);
128 static gboolean gda_jdbc_provider_xa_prepare  (GdaServerProvider *provider, GdaConnection *cnc,
129 						   const GdaXaTransactionId *xid, GError **error);
130 
131 static gboolean gda_jdbc_provider_xa_commit   (GdaServerProvider *provider, GdaConnection *cnc,
132 						   const GdaXaTransactionId *xid, GError **error);
133 static gboolean gda_jdbc_provider_xa_rollback (GdaServerProvider *provider, GdaConnection *cnc,
134 						   const GdaXaTransactionId *xid, GError **error);
135 
136 static GList   *gda_jdbc_provider_xa_recover  (GdaServerProvider *provider, GdaConnection *cnc,
137 						   GError **error);
138 
139 /*
140  * private connection data destroy
141  */
142 static void gda_jdbc_free_cnc_data (JdbcConnectionData *cdata);
143 
144 
145 /*
146  * Prepared internal statements
147  * TO_ADD: any prepared statement to be used internally by the provider should be
148  *         declared here, as constants and as SQL statements
149  */
150 static GMutex init_mutex;
151 static GdaStatement **internal_stmt = NULL;
152 
153 typedef enum {
154 	INTERNAL_STMT1
155 } InternalStatementItem;
156 
157 static gchar *internal_sql[] = {
158 	"SQL for INTERNAL_STMT1"
159 };
160 
161 /*
162  * GdaJdbcProvider class implementation
163  */
164 static void
gda_jdbc_provider_class_init(GdaJdbcProviderClass * klass)165 gda_jdbc_provider_class_init (GdaJdbcProviderClass *klass)
166 {
167 	GdaServerProviderClass *provider_class = GDA_SERVER_PROVIDER_CLASS (klass);
168 
169 	parent_class = g_type_class_peek_parent (klass);
170 
171 	provider_class->get_version = gda_jdbc_provider_get_version;
172 	provider_class->get_server_version = gda_jdbc_provider_get_server_version;
173 	provider_class->get_name = gda_jdbc_provider_get_name;
174 	provider_class->supports_feature = gda_jdbc_provider_supports_feature;
175 
176 	provider_class->get_data_handler = gda_jdbc_provider_get_data_handler;
177 	provider_class->get_def_dbms_type = gda_jdbc_provider_get_default_dbms_type;
178 
179 	provider_class->open_connection = gda_jdbc_provider_open_connection;
180 	provider_class->close_connection = gda_jdbc_provider_close_connection;
181 	provider_class->get_database = NULL;
182 
183 	provider_class->supports_operation = gda_jdbc_provider_supports_operation;
184         provider_class->create_operation = gda_jdbc_provider_create_operation;
185         provider_class->render_operation = gda_jdbc_provider_render_operation;
186         provider_class->perform_operation = gda_jdbc_provider_perform_operation;
187 
188 	provider_class->begin_transaction = gda_jdbc_provider_begin_transaction;
189 	provider_class->commit_transaction = gda_jdbc_provider_commit_transaction;
190 	provider_class->rollback_transaction = gda_jdbc_provider_rollback_transaction;
191 	provider_class->add_savepoint = gda_jdbc_provider_add_savepoint;
192         provider_class->rollback_savepoint = gda_jdbc_provider_rollback_savepoint;
193         provider_class->delete_savepoint = gda_jdbc_provider_delete_savepoint;
194 
195 	provider_class->create_parser = NULL;
196 	provider_class->statement_to_sql = NULL; /* don't use gda_jdbc_provider_statement_to_sql()
197 						  * because it only calls gda_statement_to_sql_extended() */
198 	provider_class->statement_prepare = gda_jdbc_provider_statement_prepare;
199 	provider_class->statement_execute = gda_jdbc_provider_statement_execute;
200 	provider_class->statement_rewrite = gda_jdbc_statement_rewrite;
201 
202 	provider_class->is_busy = NULL;
203 	provider_class->cancel = NULL;
204 	provider_class->create_connection = NULL;
205 
206 	memset (&(provider_class->meta_funcs), 0, sizeof (GdaServerProviderMeta));
207 	provider_class->meta_funcs._info = _gda_jdbc_meta__info;
208 	provider_class->meta_funcs._btypes = _gda_jdbc_meta__btypes;
209 	provider_class->meta_funcs._udt = _gda_jdbc_meta__udt;
210 	provider_class->meta_funcs.udt = _gda_jdbc_meta_udt;
211 	provider_class->meta_funcs._udt_cols = _gda_jdbc_meta__udt_cols;
212 	provider_class->meta_funcs.udt_cols = _gda_jdbc_meta_udt_cols;
213 	provider_class->meta_funcs._enums = _gda_jdbc_meta__enums;
214 	provider_class->meta_funcs.enums = _gda_jdbc_meta_enums;
215 	provider_class->meta_funcs._domains = _gda_jdbc_meta__domains;
216 	provider_class->meta_funcs.domains = _gda_jdbc_meta_domains;
217 	provider_class->meta_funcs._constraints_dom = _gda_jdbc_meta__constraints_dom;
218 	provider_class->meta_funcs.constraints_dom = _gda_jdbc_meta_constraints_dom;
219 	provider_class->meta_funcs._el_types = _gda_jdbc_meta__el_types;
220 	provider_class->meta_funcs.el_types = _gda_jdbc_meta_el_types;
221 	provider_class->meta_funcs._collations = _gda_jdbc_meta__collations;
222 	provider_class->meta_funcs.collations = _gda_jdbc_meta_collations;
223 	provider_class->meta_funcs._character_sets = _gda_jdbc_meta__character_sets;
224 	provider_class->meta_funcs.character_sets = _gda_jdbc_meta_character_sets;
225 	provider_class->meta_funcs._schemata = _gda_jdbc_meta__schemata;
226 	provider_class->meta_funcs.schemata = _gda_jdbc_meta_schemata;
227 	provider_class->meta_funcs._tables_views = _gda_jdbc_meta__tables_views;
228 	provider_class->meta_funcs.tables_views = _gda_jdbc_meta_tables_views;
229 	provider_class->meta_funcs._columns = _gda_jdbc_meta__columns;
230 	provider_class->meta_funcs.columns = _gda_jdbc_meta_columns;
231 	provider_class->meta_funcs._view_cols = _gda_jdbc_meta__view_cols;
232 	provider_class->meta_funcs.view_cols = _gda_jdbc_meta_view_cols;
233 	provider_class->meta_funcs._constraints_tab = _gda_jdbc_meta__constraints_tab;
234 	provider_class->meta_funcs.constraints_tab = _gda_jdbc_meta_constraints_tab;
235 	provider_class->meta_funcs._constraints_ref = _gda_jdbc_meta__constraints_ref;
236 	provider_class->meta_funcs.constraints_ref = _gda_jdbc_meta_constraints_ref;
237 	provider_class->meta_funcs._key_columns = _gda_jdbc_meta__key_columns;
238 	provider_class->meta_funcs.key_columns = _gda_jdbc_meta_key_columns;
239 	provider_class->meta_funcs._check_columns = _gda_jdbc_meta__check_columns;
240 	provider_class->meta_funcs.check_columns = _gda_jdbc_meta_check_columns;
241 	provider_class->meta_funcs._triggers = _gda_jdbc_meta__triggers;
242 	provider_class->meta_funcs.triggers = _gda_jdbc_meta_triggers;
243 	provider_class->meta_funcs._routines = _gda_jdbc_meta__routines;
244 	provider_class->meta_funcs.routines = _gda_jdbc_meta_routines;
245 	provider_class->meta_funcs._routine_col = _gda_jdbc_meta__routine_col;
246 	provider_class->meta_funcs.routine_col = _gda_jdbc_meta_routine_col;
247 	provider_class->meta_funcs._routine_par = _gda_jdbc_meta__routine_par;
248 	provider_class->meta_funcs.routine_par = _gda_jdbc_meta_routine_par;
249 	provider_class->meta_funcs._indexes_tab = _gda_jdbc_meta__indexes_tab;
250         provider_class->meta_funcs.indexes_tab = _gda_jdbc_meta_indexes_tab;
251         provider_class->meta_funcs._index_cols = _gda_jdbc_meta__index_cols;
252         provider_class->meta_funcs.index_cols = _gda_jdbc_meta_index_cols;
253 
254 	/* distributed transactions: if not supported, then provider_class->xa_funcs should be set to NULL */
255 	provider_class->xa_funcs = g_new0 (GdaServerProviderXa, 1);
256 	provider_class->xa_funcs->xa_start = gda_jdbc_provider_xa_start;
257 	provider_class->xa_funcs->xa_end = gda_jdbc_provider_xa_end;
258 	provider_class->xa_funcs->xa_prepare = gda_jdbc_provider_xa_prepare;
259 	provider_class->xa_funcs->xa_commit = gda_jdbc_provider_xa_commit;
260 	provider_class->xa_funcs->xa_rollback = gda_jdbc_provider_xa_rollback;
261 	provider_class->xa_funcs->xa_recover = gda_jdbc_provider_xa_recover;
262 
263 	/* not limiting to current thread */
264 	provider_class->limiting_thread = NULL;
265 }
266 
267 extern JavaVM *_jdbc_provider_java_vm;
268 
269 static void
gda_jdbc_provider_init(GdaJdbcProvider * jdbc_prv,G_GNUC_UNUSED GdaJdbcProviderClass * klass)270 gda_jdbc_provider_init (GdaJdbcProvider *jdbc_prv, G_GNUC_UNUSED GdaJdbcProviderClass *klass)
271 {
272 	g_mutex_lock (&init_mutex);
273 
274 	if (!internal_stmt) {
275 		InternalStatementItem i;
276 		GdaSqlParser *parser;
277 
278 		parser = gda_server_provider_internal_get_parser ((GdaServerProvider*) jdbc_prv);
279 		internal_stmt = g_new0 (GdaStatement *, sizeof (internal_sql) / sizeof (gchar*));
280 		for (i = INTERNAL_STMT1; i < sizeof (internal_sql) / sizeof (gchar*); i++) {
281 			internal_stmt[i] = gda_sql_parser_parse_string (parser, internal_sql[i], NULL, NULL);
282 			if (!internal_stmt[i])
283 				g_error ("Could not parse internal statement: %s\n", internal_sql[i]);
284 		}
285 	}
286 
287 	/* meta data init */
288 	_gda_jdbc_provider_meta_init ((GdaServerProvider*) jdbc_prv);
289 
290 	/* TO_ADD: any other provider's init should be added here */
291 
292 	g_mutex_unlock (&init_mutex);
293 }
294 
295 GType
gda_jdbc_provider_get_type(void)296 gda_jdbc_provider_get_type (void)
297 {
298 	static GType type = 0;
299 
300 	if (G_UNLIKELY (type == 0)) {
301 		static GMutex registering;
302 		static GTypeInfo info = {
303 			sizeof (GdaJdbcProviderClass),
304 			(GBaseInitFunc) NULL,
305 			(GBaseFinalizeFunc) NULL,
306 			(GClassInitFunc) gda_jdbc_provider_class_init,
307 			NULL, NULL,
308 			sizeof (GdaJdbcProvider),
309 			0,
310 			(GInstanceInitFunc) gda_jdbc_provider_init,
311 			0
312 		};
313 		g_mutex_lock (&registering);
314 		if (type == 0)
315 			type = g_type_register_static (GDA_TYPE_SERVER_PROVIDER, "GdaJdbcProvider", &info, 0);
316 		g_mutex_unlock (&registering);
317 	}
318 
319 	return type;
320 }
321 
322 
323 /*
324  * Get provider name request
325  */
326 static const gchar *
gda_jdbc_provider_get_name(GdaServerProvider * provider)327 gda_jdbc_provider_get_name (GdaServerProvider *provider)
328 {
329 	return GDA_JDBC_PROVIDER (provider)->jdbc_driver;
330 }
331 
332 /*
333  * Get provider's version, no need to change this
334  */
335 static const gchar *
gda_jdbc_provider_get_version(G_GNUC_UNUSED GdaServerProvider * provider)336 gda_jdbc_provider_get_version (G_GNUC_UNUSED GdaServerProvider *provider)
337 {
338 	return PACKAGE_VERSION;
339 }
340 
341 /*
342  * make_url_from_params:
343  *
344  * Creates the URL to pass to the JDBC driver to open a connection. It uses the
345  * jdbc_mappings.xml file
346  *
347  * Returns: a new string, or %NULL if not enough information found to create the connection URL
348  */
349 static gchar *
make_url_from_params(GdaServerProvider * provider,GdaConnection * cnc,GdaQuarkList * params,G_GNUC_UNUSED GdaQuarkList * auth)350 make_url_from_params (GdaServerProvider *provider, GdaConnection *cnc,
351 		      GdaQuarkList *params, G_GNUC_UNUSED GdaQuarkList *auth)
352 {
353 	GBytes *data;
354 	const gchar *xmlstr;
355 	gsize data_size = 0;
356 	_jdbc_register_resource ();
357 	data = g_resources_lookup_data ("/jdbc/jdbc-mappings.xml", G_RESOURCE_LOOKUP_FLAGS_NONE, NULL);
358 	g_assert (data);
359 	xmlstr = g_bytes_get_data (data, &data_size);
360 
361 	xmlDocPtr doc;
362 	doc = xmlParseMemory (xmlstr, data_size);
363 	g_bytes_unref (data);
364 	_jdbc_unregister_resource ();
365 
366         if (!doc)
367 		return NULL;
368 
369 	xmlNodePtr root, node;
370 	GString *url = NULL;
371 	root = xmlDocGetRootElement (doc);
372 	if (strcmp ((gchar*) root->name, "jdbc-mappings"))
373 		goto out;
374 
375 	for (node = root->children; node; node = node->next) {
376                 if (strcmp ((gchar *) node->name, "driver"))
377                         continue;
378 		xmlChar *prop;
379 		prop = xmlGetProp (node, BAD_CAST "name");
380 		if (!prop)
381 			continue;
382 		if (!strcmp ((gchar*) prop, gda_server_provider_get_name (provider))) {
383 			xmlFree (prop);
384 			break;
385 		}
386 		xmlFree (prop);
387         }
388 	if (!node)
389 		goto out;
390 
391 	url = g_string_new ("");
392 	for (node = node->children; node; node = node->next) {
393                 if (!strcmp ((gchar *) node->name, "prefix")) {
394 			xmlChar *contents;
395 			contents = xmlNodeGetContent (node);
396 			if (contents && *contents)
397 				g_string_append (url, (gchar*) contents);
398 		}
399 		else if (!strcmp ((gchar *) node->name, "part")) {
400 			xmlChar *prop;
401 			const gchar *cvarvalue = NULL;
402 			gchar *varvalue = NULL;
403 			gboolean opt = FALSE;
404 			prop = xmlGetProp (node, BAD_CAST "variable");
405 			if (prop) {
406 				cvarvalue = gda_quark_list_find (params, (gchar*) prop);
407 				xmlFree (prop);
408 			}
409 			prop = xmlGetProp (node, BAD_CAST "optional");
410 			if (prop) {
411 				if ((*prop == 't') || (*prop == 'T'))
412 					opt = TRUE;
413 				xmlFree (prop);
414 			}
415 
416 			prop = xmlGetProp (node, BAD_CAST "if");
417 			if (prop) {
418 				if (!strcmp ((gchar*) prop, "CncReadOnly")) {
419 					if (gda_connection_get_options (cnc) & GDA_CONNECTION_OPTIONS_READ_ONLY) {
420 						xmlFree (prop);
421 						prop = xmlGetProp (node, BAD_CAST "value");
422 						if (prop)
423 							varvalue = g_strdup ((gchar*) prop);
424 					}
425 				}
426 				if (prop)
427 					xmlFree (prop);
428 			}
429 
430 			if (cvarvalue || varvalue) {
431 				prop = xmlGetProp (node, BAD_CAST "prefix");
432 				if (prop) {
433 					g_string_append (url, (gchar*) prop);
434 					xmlFree (prop);
435 				}
436 				g_string_append (url, varvalue ? varvalue : cvarvalue);
437 				g_free (varvalue);
438 			}
439 			else if (!varvalue && !cvarvalue && !opt) {
440 				/* missing parameter */
441 				g_string_free (url, TRUE);
442 				url = NULL;
443 				goto out;
444 			}
445 		}
446         }
447 
448  out:
449 	xmlFreeDoc (doc);
450 	if (url)
451 		return g_string_free (url, FALSE);
452 	else
453 		return NULL;
454 }
455 
456 /*
457  * Open connection request
458  *
459  * In this function, the following _must_ be done:
460  *   - check for the presence and validify of the parameters required to actually open a connection,
461  *     using @params
462  *   - open the real connection to the database using the parameters previously checked
463  *   - create a JdbcConnectionData structure and associate it to @cnc
464  *
465  * Returns: TRUE if no error occurred, or FALSE otherwise (and an ERROR gonnection event must be added to @cnc)
466  */
467 static gboolean
gda_jdbc_provider_open_connection(GdaServerProvider * provider,GdaConnection * cnc,GdaQuarkList * params,GdaQuarkList * auth,G_GNUC_UNUSED guint * task_id,GdaServerProviderAsyncCallback async_cb,G_GNUC_UNUSED gpointer cb_data)468 gda_jdbc_provider_open_connection (GdaServerProvider *provider, GdaConnection *cnc,
469 				   GdaQuarkList *params, GdaQuarkList *auth,
470 				   G_GNUC_UNUSED guint *task_id, GdaServerProviderAsyncCallback async_cb,
471 				   G_GNUC_UNUSED gpointer cb_data)
472 {
473 	GdaJdbcProvider *jprov;
474 	g_return_val_if_fail (GDA_IS_JDBC_PROVIDER (provider), FALSE);
475 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
476 	jprov = (GdaJdbcProvider*) provider;
477 
478 	/* If asynchronous connection opening is not supported, then exit now */
479 	if (async_cb) {
480 		gda_connection_add_event_string (cnc, _("Provider does not support asynchronous connection open"));
481                 return FALSE;
482 	}
483 
484 	/* Check for connection parameters */
485 	gchar *url;
486 	const gchar *cstr;
487 	cstr = gda_quark_list_find (params, "URL");
488 	if (cstr)
489 		url = g_strdup (cstr);
490 	else {
491 		url = make_url_from_params (provider, cnc, params, auth);
492 		if (!url) {
493 			gda_connection_add_event_string (cnc,
494 							 _("Missing parameters to open database connection"));
495 			return FALSE;
496 		}
497 	}
498 
499 	/* Check for username / password */
500 	const gchar *username = NULL, *password = NULL;
501 	if (auth) {
502 		username = gda_quark_list_find (auth, "USERNAME");
503 		password = gda_quark_list_find (auth, "PASSWORD");
504 	}
505 
506 	/* open the real connection to the database */
507 	g_assert (jprov->jprov_obj);
508 	GValue *obj_value;
509 	jstring jstr, jstr1, jstr2;
510 	JNIEnv *env;
511 	GError *error = NULL;
512 	gint error_code;
513 	gchar *sql_state;
514 	gboolean jni_detach;
515 
516 	env = _gda_jdbc_get_jenv (&jni_detach, &error);
517 
518 	if (!env) {
519 		gda_connection_add_event_string (cnc, "%s",
520 						 error && error->message ? error->message : _("No detail"));
521 		if (error)
522 			g_error_free (error);
523 		g_free (url);
524 		return FALSE;
525 	}
526 
527 	jstr = (*env)->NewStringUTF (env, url);
528 	/*g_print ("URL = [%s] USERNAME = [%s] PASSWORD = [%s]\n", url, username, password);*/
529 	g_free (url);
530 	url = NULL;
531 	if (username)
532 		jstr1 = (*env)->NewStringUTF (env, username);
533 	else
534 		jstr1 = NULL;
535 	if (password)
536 		jstr2 = (*env)->NewStringUTF (env, password);
537 	else
538 		jstr2 = NULL;
539 
540 	obj_value = jni_wrapper_method_call (env, GdaJProvider__openConnection,
541 					     jprov->jprov_obj, &error_code, &sql_state, &error,
542 					     jstr, jstr1, jstr2);
543 	(*env)->DeleteLocalRef(env, jstr);
544 	if (jstr1)
545 		(*env)->DeleteLocalRef(env, jstr1);
546 	if (jstr2)
547 		(*env)->DeleteLocalRef(env, jstr2);
548 
549 	if (!obj_value) {
550 		_gda_jdbc_make_error (cnc, error_code, sql_state, error);
551 		_gda_jdbc_release_jenv (jni_detach);
552 		return FALSE;
553 	}
554 
555 	/* Create a new instance of the provider specific data associated to a connection (JdbcConnectionData),
556 	 * and set its contents */
557 	JdbcConnectionData *cdata;
558 	cdata = g_new0 (JdbcConnectionData, 1);
559 	gda_connection_internal_set_provider_data (cnc, cdata, (GDestroyNotify) gda_jdbc_free_cnc_data);
560 	cdata->jcnc_obj = obj_value;
561 
562 	_gda_jdbc_release_jenv (jni_detach);
563 	return TRUE;
564 }
565 
566 /*
567  * Close connection request
568  *
569  * In this function, the following _must_ be done:
570  *   - Actually close the connection to the database using @cnc's associated JdbcConnectionData structure
571  *   - Free the JdbcConnectionData structure and its contents
572  *
573  * Returns: TRUE if no error occurred, or FALSE otherwise (and an ERROR gonnection event must be added to @cnc)
574  */
575 static gboolean
gda_jdbc_provider_close_connection(GdaServerProvider * provider,GdaConnection * cnc)576 gda_jdbc_provider_close_connection (GdaServerProvider *provider, GdaConnection *cnc)
577 {
578 	JdbcConnectionData *cdata;
579 
580 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
581 	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
582 
583 	/* Close the connection using the C API */
584 	cdata = (JdbcConnectionData*) gda_connection_internal_get_provider_data (cnc);
585 	if (!cdata)
586 		return FALSE;
587 
588 	/* Free the JdbcConnectionData structure and its contents */
589 	gda_jdbc_free_cnc_data (cdata);
590 	gda_connection_internal_set_provider_data (cnc, NULL, NULL);
591 
592 	return TRUE;
593 }
594 
595 /*
596  * Server version request
597  *
598  * Returns the server version as a string
599  */
600 static const gchar *
gda_jdbc_provider_get_server_version(GdaServerProvider * provider,GdaConnection * cnc)601 gda_jdbc_provider_get_server_version (GdaServerProvider *provider, GdaConnection *cnc)
602 {
603 	JdbcConnectionData *cdata;
604 
605 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
606 	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
607 
608 	cdata = (JdbcConnectionData*) gda_connection_internal_get_provider_data (cnc);
609 	if (!cdata)
610 		return FALSE;
611 
612 	if (! cdata->server_version && cdata->jcnc_obj) {
613 		JNIEnv *jenv = NULL;
614 		gboolean jni_detach;
615 		GError *error = NULL;
616 
617 		jenv = _gda_jdbc_get_jenv (&jni_detach, &error);
618 		if (!jenv) {
619 			g_warning ("%s", error->message);
620 			g_error_free (error);
621 		}
622 		else {
623 			GValue *res;
624 			res = jni_wrapper_method_call (jenv, GdaJConnection__getServerVersion,
625 						       cdata->jcnc_obj, NULL, NULL, NULL);
626 			if (res) {
627 				cdata->server_version = g_value_dup_string (res);
628 				gda_value_free (res);
629 			}
630 			_gda_jdbc_release_jenv (jni_detach);
631 		}
632 	}
633 
634 	return cdata->server_version;
635 }
636 
637 /*
638  * Support operation request
639  *
640  * Tells what the implemented server operations are. To add support for an operation, the following steps are required:
641  *   - create a jdbc_specs_....xml.in file describing the required and optional parameters for the operation
642  *   - add it to the Makefile.am
643  *   - make this method return TRUE for the operation type
644  *   - implement the gda_jdbc_provider_render_operation() and gda_jdbc_provider_perform_operation() methods
645  *
646  */
647 static gboolean
gda_jdbc_provider_supports_operation(GdaServerProvider * provider,GdaConnection * cnc,G_GNUC_UNUSED GdaServerOperationType type,G_GNUC_UNUSED GdaSet * options)648 gda_jdbc_provider_supports_operation (GdaServerProvider *provider, GdaConnection *cnc,
649 				      G_GNUC_UNUSED GdaServerOperationType type,
650 				      G_GNUC_UNUSED GdaSet *options)
651 {
652 	if (cnc) {
653 		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
654 		g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
655 	}
656 
657 	/* use native provider for help */
658 	TO_IMPLEMENT;
659 
660 	return FALSE;
661 }
662 
663 /*
664  * Create operation request
665  *
666  * Creates a #GdaServerOperation. The following code is generic and should only be changed
667  * if some further initialization is required, or if operation's contents is dependent on @cnc
668  */
669 static GdaServerOperation *
gda_jdbc_provider_create_operation(GdaServerProvider * provider,GdaConnection * cnc,G_GNUC_UNUSED GdaServerOperationType type,G_GNUC_UNUSED GdaSet * options,G_GNUC_UNUSED GError ** error)670 gda_jdbc_provider_create_operation (GdaServerProvider *provider, GdaConnection *cnc,
671 				    G_GNUC_UNUSED GdaServerOperationType type, G_GNUC_UNUSED GdaSet *options,
672 				    G_GNUC_UNUSED GError **error)
673 {
674 	if (cnc) {
675 		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
676 		g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
677 	}
678 
679 	/* use native provider for help */
680 	TO_IMPLEMENT;
681 
682 	return NULL;
683 }
684 
685 /*
686  * Render operation request
687  */
688 static gchar *
gda_jdbc_provider_render_operation(GdaServerProvider * provider,GdaConnection * cnc,G_GNUC_UNUSED GdaServerOperation * op,G_GNUC_UNUSED GError ** error)689 gda_jdbc_provider_render_operation (GdaServerProvider *provider, GdaConnection *cnc,
690 				    G_GNUC_UNUSED GdaServerOperation *op, G_GNUC_UNUSED GError **error)
691 {
692 	if (cnc) {
693 		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
694 		g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
695 	}
696 
697 	/* use native provider for help */
698 	TO_IMPLEMENT;
699 
700 	return NULL;
701 }
702 
703 /*
704  * Perform operation request
705  */
706 static gboolean
gda_jdbc_provider_perform_operation(GdaServerProvider * provider,GdaConnection * cnc,G_GNUC_UNUSED GdaServerOperation * op,G_GNUC_UNUSED guint * task_id,GdaServerProviderAsyncCallback async_cb,G_GNUC_UNUSED gpointer cb_data,GError ** error)707 gda_jdbc_provider_perform_operation (GdaServerProvider *provider, GdaConnection *cnc,
708 				     G_GNUC_UNUSED GdaServerOperation *op, G_GNUC_UNUSED guint *task_id,
709 				     GdaServerProviderAsyncCallback async_cb, G_GNUC_UNUSED gpointer cb_data,
710 				     GError **error)
711 {
712 	/* If asynchronous connection opening is not supported, then exit now */
713 	if (async_cb) {
714 		g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_METHOD_NON_IMPLEMENTED_ERROR,
715 			     "%s", _("Provider does not support asynchronous server operation"));
716                 return FALSE;
717 	}
718 
719 	if (cnc) {
720 		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
721 		g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
722 	}
723 
724 	/* use native provider for help */
725 	TO_IMPLEMENT;
726 	return FALSE;
727 }
728 
729 /*
730  * Begin transaction request
731  */
732 static gboolean
gda_jdbc_provider_begin_transaction(GdaServerProvider * provider,GdaConnection * cnc,G_GNUC_UNUSED const gchar * name,G_GNUC_UNUSED GdaTransactionIsolation level,GError ** error)733 gda_jdbc_provider_begin_transaction (GdaServerProvider *provider, GdaConnection *cnc,
734 				     G_GNUC_UNUSED const gchar *name,
735 				     G_GNUC_UNUSED GdaTransactionIsolation level, GError **error)
736 {
737 	JdbcConnectionData *cdata;
738 	GValue *jexec_res;
739 	GError *lerror = NULL;
740 	JNIEnv *jenv = NULL;
741 	gboolean jni_detach;
742 	gint error_code;
743 	gchar *sql_state;
744 
745 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
746 	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
747 
748 	cdata = (JdbcConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error);
749 	if (!cdata)
750 		return FALSE;
751 
752 	jenv = _gda_jdbc_get_jenv (&jni_detach, error);
753 	if (!jenv)
754 		return FALSE;
755 
756 	jexec_res = jni_wrapper_method_call (jenv, GdaJConnection__begin,
757 					     cdata->jcnc_obj, &error_code, &sql_state, &lerror);
758 	if (!jexec_res) {
759 		if (error && lerror)
760 			*error = g_error_copy (lerror);
761 		_gda_jdbc_make_error (cnc, error_code, sql_state, lerror);
762 		_gda_jdbc_release_jenv (jni_detach);
763 		return FALSE;
764 	}
765 	gda_value_free (jexec_res);
766 	_gda_jdbc_release_jenv (jni_detach);
767 
768 	return TRUE;
769 }
770 
771 /*
772  * Commit transaction request
773  */
774 static gboolean
gda_jdbc_provider_commit_transaction(GdaServerProvider * provider,GdaConnection * cnc,G_GNUC_UNUSED const gchar * name,GError ** error)775 gda_jdbc_provider_commit_transaction (GdaServerProvider *provider, GdaConnection *cnc,
776 				      G_GNUC_UNUSED const gchar *name, GError **error)
777 {
778 	JdbcConnectionData *cdata;
779 	GValue *jexec_res;
780 	GError *lerror = NULL;
781 	JNIEnv *jenv = NULL;
782 	gboolean jni_detach;
783 	gint error_code;
784 	gchar *sql_state;
785 
786 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
787 	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
788 
789 	cdata = (JdbcConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error);
790 	if (!cdata)
791 		return FALSE;
792 
793 	jenv = _gda_jdbc_get_jenv (&jni_detach, error);
794 	if (!jenv)
795 		return FALSE;
796 
797 	jexec_res = jni_wrapper_method_call (jenv, GdaJConnection__commit,
798 					     cdata->jcnc_obj, &error_code, &sql_state, &lerror);
799 	if (!jexec_res) {
800 		if (error && lerror)
801 			*error = g_error_copy (lerror);
802 		_gda_jdbc_make_error (cnc, error_code, sql_state, lerror);
803 		_gda_jdbc_release_jenv (jni_detach);
804 		return FALSE;
805 	}
806 	gda_value_free (jexec_res);
807 	_gda_jdbc_release_jenv (jni_detach);
808 
809 	return TRUE;
810 }
811 
812 /*
813  * Rollback transaction request
814  */
815 static gboolean
gda_jdbc_provider_rollback_transaction(GdaServerProvider * provider,GdaConnection * cnc,G_GNUC_UNUSED const gchar * name,GError ** error)816 gda_jdbc_provider_rollback_transaction (GdaServerProvider *provider, GdaConnection *cnc,
817 					G_GNUC_UNUSED const gchar *name, GError **error)
818 {
819 	JdbcConnectionData *cdata;
820 	GValue *jexec_res;
821 	GError *lerror = NULL;
822 	JNIEnv *jenv = NULL;
823 	gboolean jni_detach;
824 	gint error_code;
825 	gchar *sql_state;
826 
827 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
828 	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
829 
830 	cdata = (JdbcConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error);
831 	if (!cdata)
832 		return FALSE;
833 
834 	jenv = _gda_jdbc_get_jenv (&jni_detach, error);
835 	if (!jenv)
836 		return FALSE;
837 
838 	jexec_res = jni_wrapper_method_call (jenv, GdaJConnection__rollback,
839 					     cdata->jcnc_obj, &error_code, &sql_state, &lerror);
840 	if (!jexec_res) {
841 		if (error && lerror)
842 			*error = g_error_copy (lerror);
843 		_gda_jdbc_make_error (cnc, error_code, sql_state, lerror);
844 		_gda_jdbc_release_jenv (jni_detach);
845 		return FALSE;
846 	}
847 	gda_value_free (jexec_res);
848 	_gda_jdbc_release_jenv (jni_detach);
849 
850 	return TRUE;
851 }
852 
853 /*
854  * Add savepoint request
855  */
856 static gboolean
gda_jdbc_provider_add_savepoint(GdaServerProvider * provider,GdaConnection * cnc,const gchar * name,GError ** error)857 gda_jdbc_provider_add_savepoint (GdaServerProvider *provider, GdaConnection *cnc,
858 				 const gchar *name, GError **error)
859 {
860 	JdbcConnectionData *cdata;
861 	GValue *jexec_res;
862 	GError *lerror = NULL;
863 	JNIEnv *jenv = NULL;
864 	gboolean jni_detach;
865 	gint error_code;
866 	gchar *sql_state;
867 	jstring jname;
868 
869 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
870 	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
871 
872 	cdata = (JdbcConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error);
873 	if (!cdata)
874 		return FALSE;
875 
876 	jenv = _gda_jdbc_get_jenv (&jni_detach, error);
877 	if (!jenv)
878 		return FALSE;
879 
880 	if (name)
881 		jname = (*jenv)->NewStringUTF (jenv, name);
882 	else
883 		jname = (*jenv)->NewStringUTF (jenv, "");
884 	if ((*jenv)->ExceptionCheck (jenv)) {
885 		_gda_jdbc_release_jenv (jni_detach);
886 		return FALSE;
887 	}
888 
889 	jexec_res = jni_wrapper_method_call (jenv, GdaJConnection__addSavepoint,
890 					     cdata->jcnc_obj, &error_code, &sql_state, &lerror, jname);
891 	(*jenv)->DeleteLocalRef (jenv, jname);
892 	if (!jexec_res) {
893 		if (error && lerror)
894 			*error = g_error_copy (lerror);
895 		_gda_jdbc_make_error (cnc, error_code, sql_state, lerror);
896 		_gda_jdbc_release_jenv (jni_detach);
897 		return FALSE;
898 	}
899 	gda_value_free (jexec_res);
900 	_gda_jdbc_release_jenv (jni_detach);
901 
902 	return TRUE;
903 }
904 
905 /*
906  * Rollback savepoint request
907  */
908 static gboolean
gda_jdbc_provider_rollback_savepoint(GdaServerProvider * provider,GdaConnection * cnc,const gchar * name,GError ** error)909 gda_jdbc_provider_rollback_savepoint (GdaServerProvider *provider, GdaConnection *cnc,
910 				      const gchar *name, GError **error)
911 {
912 	JdbcConnectionData *cdata;
913 	GValue *jexec_res;
914 	GError *lerror = NULL;
915 	JNIEnv *jenv = NULL;
916 	gboolean jni_detach;
917 	gint error_code;
918 	gchar *sql_state;
919 	jstring jname;
920 
921 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
922 	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
923 
924 	cdata = (JdbcConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error);
925 	if (!cdata)
926 		return FALSE;
927 
928 	jenv = _gda_jdbc_get_jenv (&jni_detach, error);
929 	if (!jenv)
930 		return FALSE;
931 
932 	if (name)
933 		jname = (*jenv)->NewStringUTF (jenv, name);
934 	else
935 		jname = (*jenv)->NewStringUTF (jenv, "");
936 	if ((*jenv)->ExceptionCheck (jenv)) {
937 		_gda_jdbc_release_jenv (jni_detach);
938 		return FALSE;
939 	}
940 
941 	jexec_res = jni_wrapper_method_call (jenv, GdaJConnection__rollbackSavepoint,
942 					     cdata->jcnc_obj, &error_code, &sql_state, &lerror, jname);
943 	(*jenv)->DeleteLocalRef (jenv, jname);
944 	if (!jexec_res) {
945 		if (error && lerror)
946 			*error = g_error_copy (lerror);
947 		_gda_jdbc_make_error (cnc, error_code, sql_state, lerror);
948 		_gda_jdbc_release_jenv (jni_detach);
949 		return FALSE;
950 	}
951 	gda_value_free (jexec_res);
952 	_gda_jdbc_release_jenv (jni_detach);
953 
954 	return TRUE;
955 }
956 
957 /*
958  * Delete savepoint request
959  */
960 static gboolean
gda_jdbc_provider_delete_savepoint(GdaServerProvider * provider,GdaConnection * cnc,const gchar * name,GError ** error)961 gda_jdbc_provider_delete_savepoint (GdaServerProvider *provider, GdaConnection *cnc,
962 				    const gchar *name, GError **error)
963 {
964 	JdbcConnectionData *cdata;
965 	GValue *jexec_res;
966 	GError *lerror = NULL;
967 	JNIEnv *jenv = NULL;
968 	gboolean jni_detach;
969 	gint error_code;
970 	gchar *sql_state;
971 	jstring jname;
972 
973 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
974 	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
975 
976 	cdata = (JdbcConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error);
977 	if (!cdata)
978 		return FALSE;
979 
980 	jenv = _gda_jdbc_get_jenv (&jni_detach, error);
981 	if (!jenv)
982 		return FALSE;
983 
984 	if (name)
985 		jname = (*jenv)->NewStringUTF (jenv, name);
986 	else
987 		jname = (*jenv)->NewStringUTF (jenv, "");
988 	if ((*jenv)->ExceptionCheck (jenv)) {
989 		_gda_jdbc_release_jenv (jni_detach);
990 		return FALSE;
991 	}
992 
993 	jexec_res = jni_wrapper_method_call (jenv, GdaJConnection__releaseSavepoint,
994 					     cdata->jcnc_obj, &error_code, &sql_state, &lerror, jname);
995 	(*jenv)->DeleteLocalRef (jenv, jname);
996 	if (!jexec_res) {
997 		if (error && lerror)
998 			*error = g_error_copy (lerror);
999 		_gda_jdbc_make_error (cnc, error_code, sql_state, lerror);
1000 		_gda_jdbc_release_jenv (jni_detach);
1001 		return FALSE;
1002 	}
1003 	gda_value_free (jexec_res);
1004 	_gda_jdbc_release_jenv (jni_detach);
1005 
1006 	return TRUE;
1007 }
1008 
1009 /*
1010  * Feature support request
1011  */
1012 static gboolean
gda_jdbc_provider_supports_feature(GdaServerProvider * provider,GdaConnection * cnc,GdaConnectionFeature feature)1013 gda_jdbc_provider_supports_feature (GdaServerProvider *provider, GdaConnection *cnc, GdaConnectionFeature feature)
1014 {
1015 	if (cnc) {
1016 		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
1017 		g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
1018 	}
1019 
1020 	switch (feature) {
1021 	case GDA_CONNECTION_FEATURE_SQL :
1022 		return TRUE;
1023 	default:
1024 		return FALSE;
1025 	}
1026 }
1027 
1028 /*
1029  * Get data handler request
1030  *
1031  * This method allows one to obtain a pointer to a #GdaDataHandler object specific to @type or @dbms_type (@dbms_type
1032  * must be considered only if @type is not a valid GType).
1033  *
1034  * A data handler allows one to convert a value between its different representations which are a human readable string,
1035  * an SQL representation and a GValue.
1036  *
1037  * The recommended method is to create GdaDataHandler objects only when they are needed and to keep a reference to them
1038  * for further usage, using the gda_server_provider_handler_declare() method.
1039  *
1040  * The implementation shown here does not define any specific data handler, but there should be some for at least
1041  * binary and time related types.
1042  */
1043 static GdaDataHandler *
gda_jdbc_provider_get_data_handler(GdaServerProvider * provider,GdaConnection * cnc,GType type,const gchar * dbms_type)1044 gda_jdbc_provider_get_data_handler (GdaServerProvider *provider, GdaConnection *cnc,
1045 				    GType type, const gchar *dbms_type)
1046 {
1047 	GdaDataHandler *dh;
1048 	if (cnc) {
1049 		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
1050 		g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
1051 	}
1052 
1053 	if (type == G_TYPE_INVALID) {
1054 		TO_IMPLEMENT; /* use @dbms_type */
1055 		dh = NULL;
1056 	}
1057 	/*
1058 	else if ((type == GDA_TYPE_BINARY) ||
1059 		 (type == GDA_TYPE_BLOB)) {
1060 		dh = gda_server_provider_handler_find (provider, cnc, type, NULL);
1061                 if (!dh) {
1062                         dh = gda_postgres_handler_bin_new (cnc);
1063                         if (dh) {
1064                                 gda_server_provider_handler_declare (provider, dh, cnc, GDA_TYPE_BINARY, NULL);
1065                                 gda_server_provider_handler_declare (provider, dh, cnc, GDA_TYPE_BLOB, NULL);
1066                                 g_object_unref (dh);
1067                         }
1068                 }
1069 	}
1070 	*/
1071 	else if ((type == GDA_TYPE_TIME) ||
1072 		 (type == GDA_TYPE_TIMESTAMP) ||
1073 		 (type == G_TYPE_DATE)) {
1074 		dh = gda_server_provider_handler_find (provider, NULL, type, NULL);
1075                 if (!dh) {
1076                         dh = gda_handler_time_new ();
1077                         gda_handler_time_set_sql_spec ((GdaHandlerTime *) dh, G_DATE_YEAR,
1078 						       G_DATE_MONTH, G_DATE_DAY, '-', FALSE);
1079                         gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_DATE, NULL);
1080                         gda_server_provider_handler_declare (provider, dh, NULL, GDA_TYPE_TIME, NULL);
1081                         gda_server_provider_handler_declare (provider, dh, NULL, GDA_TYPE_TIMESTAMP, NULL);
1082                         g_object_unref (dh);
1083                 }
1084 	}
1085 	else
1086 		dh = gda_server_provider_handler_use_default (provider, type);
1087 
1088 	return dh;
1089 }
1090 
1091 /*
1092  * Get default DBMS type request
1093  *
1094  * This method returns the "preferred" DBMS type for GType
1095  */
1096 static const gchar*
gda_jdbc_provider_get_default_dbms_type(GdaServerProvider * provider,GdaConnection * cnc,GType type)1097 gda_jdbc_provider_get_default_dbms_type (GdaServerProvider *provider, GdaConnection *cnc, GType type)
1098 {
1099 	if (cnc) {
1100 		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
1101 		g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
1102 	}
1103 
1104 	TO_IMPLEMENT;
1105 
1106 	if ((type == G_TYPE_INT64) ||
1107 	    (type == G_TYPE_INT) ||
1108 	    (type == GDA_TYPE_SHORT) ||
1109 	    (type == GDA_TYPE_USHORT) ||
1110 	    (type == G_TYPE_CHAR) ||
1111 	    (type == G_TYPE_UCHAR) ||
1112 	    (type == G_TYPE_ULONG) ||
1113 	    (type == G_TYPE_UINT) ||
1114 	    (type == G_TYPE_UINT64))
1115 		return "integer";
1116 
1117 	if ((type == GDA_TYPE_BINARY) ||
1118 	    (type == GDA_TYPE_BLOB))
1119 		return "blob";
1120 
1121 	if (type == G_TYPE_BOOLEAN)
1122 		return "boolean";
1123 
1124 	if ((type == G_TYPE_DATE) ||
1125 	    (type == GDA_TYPE_GEOMETRIC_POINT) ||
1126 	    (type == G_TYPE_OBJECT) ||
1127 	    (type == G_TYPE_STRING) ||
1128 	    (type == GDA_TYPE_TIME) ||
1129 	    (type == GDA_TYPE_TIMESTAMP) ||
1130 	    (type == G_TYPE_GTYPE))
1131 		return "string";
1132 
1133 	if ((type == G_TYPE_DOUBLE) ||
1134 	    (type == GDA_TYPE_NUMERIC) ||
1135 	    (type == G_TYPE_FLOAT))
1136 		return "real";
1137 
1138 	if (type == GDA_TYPE_TIME)
1139 		return "time";
1140 	if (type == GDA_TYPE_TIMESTAMP)
1141 		return "timestamp";
1142 	if (type == G_TYPE_DATE)
1143 		return "date";
1144 
1145 	if ((type == GDA_TYPE_NULL) ||
1146 	    (type == G_TYPE_GTYPE))
1147 		return NULL;
1148 
1149 	return "text";
1150 }
1151 
1152 /*
1153  * GdaStatement to SQL request
1154  *
1155  * This method renders a #GdaStatement into its SQL representation.
1156  *
1157  * The implementation show here simply calls gda_statement_to_sql_extended() but the rendering
1158  * can be specialized to the database's SQL dialect, see the implementation of gda_statement_to_sql_extended()
1159  * and SQLite's specialized rendering for more details
1160  *
1161  * NOTE: This implementation MUST NOT call gda_statement_to_sql_extended() if it is
1162  *       the GdaServerProvider::statement_to_sql() virtual method's implementation
1163  */
1164 static gchar *
gda_jdbc_provider_statement_to_sql(GdaServerProvider * provider,GdaConnection * cnc,GdaStatement * stmt,GdaSet * params,GdaStatementSqlFlag flags,GSList ** params_used,GError ** error)1165 gda_jdbc_provider_statement_to_sql (GdaServerProvider *provider, GdaConnection *cnc,
1166 				    GdaStatement *stmt, GdaSet *params, GdaStatementSqlFlag flags,
1167 				    GSList **params_used, GError **error)
1168 {
1169 	g_return_val_if_fail (GDA_IS_STATEMENT (stmt), NULL);
1170 	if (cnc) {
1171 		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
1172 		g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
1173 	}
1174 
1175 	return gda_statement_to_sql_extended (stmt, cnc, params, flags, params_used, error);
1176 }
1177 
1178 /*
1179  * Statement prepare request
1180  *
1181  * This methods "converts" @stmt into a prepared statement. A prepared statement is a notion
1182  * specific in its implementation details to the C API used here. If successfull, it must create
1183  * a new #GdaJdbcPStmt object and declare it to @cnc.
1184  */
1185 static gboolean
gda_jdbc_provider_statement_prepare(GdaServerProvider * provider,GdaConnection * cnc,GdaStatement * stmt,GError ** error)1186 gda_jdbc_provider_statement_prepare (GdaServerProvider *provider, GdaConnection *cnc,
1187 				     GdaStatement *stmt, GError **error)
1188 {
1189 	GdaJdbcPStmt *ps;
1190 	JdbcConnectionData *cdata;
1191 	gboolean retval = FALSE;
1192 
1193 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
1194 	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
1195 	g_return_val_if_fail (GDA_IS_STATEMENT (stmt), FALSE);
1196 
1197 	/* fetch prepares stmt if already done */
1198 	ps = (GdaJdbcPStmt *) gda_connection_get_prepared_statement (cnc, stmt);
1199 	if (ps)
1200 		return TRUE;
1201 
1202 	/* Get private data */
1203 	cdata = (JdbcConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error);
1204 	if (!cdata)
1205 		return FALSE;
1206 
1207 	/* render as SQL understood by JDBC */
1208 	GdaSet *params = NULL;
1209 	gchar *sql;
1210 	GSList *used_params = NULL;
1211 	if (! gda_statement_get_parameters (stmt, &params, error))
1212                 return FALSE;
1213         sql = gda_jdbc_provider_statement_to_sql (provider, cnc, stmt, params, GDA_STATEMENT_SQL_PARAMS_AS_UQMARK,
1214 						  &used_params, error);
1215 
1216 	JNIEnv *jenv = NULL;
1217         if (!sql)
1218 		goto out;
1219 
1220 	/* prepare @stmt using the C API, creates @ps */
1221 	GValue *pstmt_obj;
1222 	gboolean jni_detach = FALSE;
1223 	jstring jsql;
1224 
1225 	jenv = _gda_jdbc_get_jenv (&jni_detach, error);
1226 	if (!jenv)
1227 		goto out;
1228 
1229 	jsql = (*jenv)->NewStringUTF (jenv, sql);
1230 	pstmt_obj = jni_wrapper_method_call (jenv, GdaJConnection__prepareStatement,
1231 					     cdata->jcnc_obj, NULL, NULL, error, jsql);
1232 	(*jenv)->DeleteLocalRef (jenv, jsql);
1233 	if (!pstmt_obj)
1234 		goto out;
1235 
1236 	/* make a list of the parameter names used in the statement */
1237 	GSList *param_ids = NULL;
1238         if (used_params) {
1239                 GSList *list;
1240 		jbyte *ctypes;
1241 		gint i, nparams;
1242 
1243 		nparams = g_slist_length (used_params);
1244 		ctypes = g_new (jbyte, nparams);
1245 
1246                 for (i = 0, list = used_params;
1247 		     list;
1248 		     i++, list = list->next) {
1249                         const gchar *cid;
1250                         cid = gda_holder_get_id (GDA_HOLDER (list->data));
1251                         if (cid) {
1252                                 param_ids = g_slist_append (param_ids, g_strdup (cid));
1253 				ctypes [i] = _gda_jdbc_gtype_to_proto_type (gda_holder_get_g_type ((GdaHolder*) list->data));
1254 				/* g_print ("PREPARATION: param ID: %s\n", cid);*/
1255                         }
1256                         else {
1257                                 g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_PREPARE_STMT_ERROR,
1258                                              "%s", _("Unnamed parameter is not allowed in prepared statements"));
1259                                 g_slist_foreach (param_ids, (GFunc) g_free, NULL);
1260                                 g_slist_free (param_ids);
1261 				g_free (ctypes);
1262                                 goto out;
1263                         }
1264                 }
1265 
1266 		/* inform JDBC of the parameters' data types */
1267 		jbyteArray jtypes;
1268 		jtypes = (*jenv)->NewByteArray (jenv, nparams);
1269 		if (jni_wrapper_handle_exception (jenv, NULL, NULL, error)) {
1270 			g_free (ctypes);
1271 			g_slist_foreach (param_ids, (GFunc) g_free, NULL);
1272 			g_slist_free (param_ids);
1273 			goto out;
1274 		}
1275 
1276 		(*jenv)->SetByteArrayRegion (jenv, jtypes, 0, nparams, ctypes);
1277 		if (jni_wrapper_handle_exception (jenv, NULL, NULL, error)) {
1278 			g_free (ctypes);
1279 			(*jenv)->DeleteLocalRef (jenv, jtypes);
1280 			g_slist_foreach (param_ids, (GFunc) g_free, NULL);
1281 			g_slist_free (param_ids);
1282 			goto out;
1283 		}
1284 
1285 		GValue *jexec_res;
1286 		jexec_res = jni_wrapper_method_call (jenv, GdaJPStmt__declareParamTypes,
1287 						     pstmt_obj, NULL, NULL, error, jni_cpointer_to_jlong (cnc), jtypes);
1288 		(*jenv)->DeleteLocalRef (jenv, jtypes);
1289 		g_free (ctypes);
1290 
1291 		if (!jexec_res) {
1292 			g_slist_foreach (param_ids, (GFunc) g_free, NULL);
1293 			g_slist_free (param_ids);
1294 			goto out;
1295 		}
1296 		gda_value_free (jexec_res);
1297         }
1298 
1299 	/* create a prepared statement object */
1300 	ps = gda_jdbc_pstmt_new (pstmt_obj);
1301 	gda_pstmt_set_gda_statement (_GDA_PSTMT (ps), stmt);
1302         _GDA_PSTMT (ps)->param_ids = param_ids;
1303         _GDA_PSTMT (ps)->sql = sql;
1304 
1305 	gda_connection_add_prepared_statement (cnc, stmt, (GdaPStmt *) ps);
1306 	g_object_unref (ps);
1307 	retval = TRUE;
1308 
1309  out:
1310 	if (used_params)
1311                 g_slist_free (used_params);
1312         if (params)
1313                 g_object_unref (params);
1314 	if (jenv)
1315 		_gda_jdbc_release_jenv (jni_detach);
1316 
1317 	return retval;
1318 }
1319 
1320 /*
1321  * Execute statement request
1322  *
1323  * Executes a statement. This method should do the following:
1324  *    - try to prepare the statement if not yet done
1325  *    - optionnally reset the prepared statement
1326  *    - bind the variables's values (which are in @params)
1327  *    - add a connection event to log the execution
1328  *    - execute the prepared statement
1329  *
1330  * If @stmt is an INSERT statement and @last_inserted_row is not NULL then additional actions must be taken to return the
1331  * actual inserted row
1332  */
1333 static GObject *
gda_jdbc_provider_statement_execute(GdaServerProvider * provider,GdaConnection * cnc,GdaStatement * stmt,GdaSet * params,GdaStatementModelUsage model_usage,GType * col_types,GdaSet ** last_inserted_row,guint * task_id,GdaServerProviderExecCallback async_cb,gpointer cb_data,GError ** error)1334 gda_jdbc_provider_statement_execute (GdaServerProvider *provider, GdaConnection *cnc,
1335 				     GdaStatement *stmt, GdaSet *params,
1336 				     GdaStatementModelUsage model_usage,
1337 				     GType *col_types, GdaSet **last_inserted_row,
1338 				     guint *task_id,
1339 				     GdaServerProviderExecCallback async_cb, gpointer cb_data, GError **error)
1340 {
1341 	GdaJdbcPStmt *ps;
1342 	JdbcConnectionData *cdata;
1343 	gboolean allow_noparam;
1344         gboolean empty_rs = FALSE; /* TRUE when @allow_noparam is TRUE and there is a problem with @params
1345                                       => resulting data model will be empty (0 row) */
1346 	JNIEnv *jenv = NULL;
1347 	gboolean jni_detach;
1348 
1349 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
1350 	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
1351 	g_return_val_if_fail (GDA_IS_STATEMENT (stmt), NULL);
1352 
1353 	/* If asynchronous connection opening is not supported, then exit now */
1354 	if (async_cb) {
1355 		g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_METHOD_NON_IMPLEMENTED_ERROR,
1356 			     "%s", _("Provider does not support asynchronous statement execution"));
1357                 return NULL;
1358 	}
1359 
1360 	if (! (model_usage & GDA_STATEMENT_MODEL_RANDOM_ACCESS) &&
1361             ! (model_usage & GDA_STATEMENT_MODEL_CURSOR_FORWARD))
1362                 model_usage |= GDA_STATEMENT_MODEL_RANDOM_ACCESS;
1363 
1364         allow_noparam = (model_usage & GDA_STATEMENT_MODEL_ALLOW_NOPARAM) &&
1365                 (gda_statement_get_statement_type (stmt) == GDA_SQL_STATEMENT_SELECT);
1366 
1367         if (last_inserted_row)
1368                 *last_inserted_row = NULL;
1369 
1370 	/* Get private data */
1371 	cdata = (JdbcConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error);
1372 	if (!cdata)
1373 		return NULL;
1374 
1375 	jenv = _gda_jdbc_get_jenv (&jni_detach, error);
1376 	if (!jenv)
1377 		return NULL;
1378 
1379 	/* get/create new prepared statement */
1380 	ps = (GdaJdbcPStmt *) gda_connection_get_prepared_statement (cnc, stmt);
1381 	if (!ps) {
1382 		if (!gda_jdbc_provider_statement_prepare (provider, cnc, stmt, NULL)) {
1383 			/* this case can appear for example if some variables are used in places
1384 			 * where the C API cannot allow them (for example if the variable is the table name
1385 			 * in a SELECT statement). The action here is to get the actual SQL code for @stmt,
1386 			 * and use that SQL instead of @stmt to create another GdaJdbcPStmt object.
1387 			 */
1388 			gchar *sql;
1389 			jstring jsql;
1390 			GValue *pstmt_obj;
1391 
1392                         sql = gda_jdbc_provider_statement_to_sql (provider, cnc, stmt, params, 0, NULL, error);
1393                         if (!sql) {
1394 				_gda_jdbc_release_jenv (jni_detach);
1395                                 return NULL;
1396 			}
1397 
1398 			jsql = (*jenv)->NewStringUTF (jenv, sql);
1399 			pstmt_obj = jni_wrapper_method_call (jenv, GdaJConnection__prepareStatement,
1400 							     cdata->jcnc_obj, NULL, NULL, error, jsql);
1401 			(*jenv)->DeleteLocalRef (jenv, jsql);
1402                         g_free (sql);
1403 
1404                         if (!pstmt_obj) {
1405 				_gda_jdbc_release_jenv (jni_detach);
1406                                 return NULL;
1407 			}
1408 
1409 			ps = gda_jdbc_pstmt_new (pstmt_obj);
1410 		}
1411 		else {
1412 			ps = (GdaJdbcPStmt *) gda_connection_get_prepared_statement (cnc, stmt);
1413 			g_object_ref (ps);
1414 		}
1415 	}
1416 	else
1417 		g_object_ref (ps);
1418 	g_assert (ps);
1419 
1420 	/* reset the prepared statement's parameters */
1421 	GValue *jexec_res;
1422 	jexec_res = jni_wrapper_method_call (jenv, GdaJPStmt__clearParameters,
1423 					     ps->pstmt_obj, NULL, NULL, error);
1424 	if (!jexec_res) {
1425 		g_object_unref (ps);
1426 		_gda_jdbc_release_jenv (jni_detach);
1427 		return NULL;
1428 	}
1429 	gda_value_free (jexec_res);
1430 
1431 	/* bind statement's parameters */
1432 	GSList *list;
1433 	GdaConnectionEvent *event = NULL;
1434 	int i;
1435 	for (i = 0, list = _GDA_PSTMT (ps)->param_ids; list; list = list->next, i++) {
1436 		const gchar *pname = (gchar *) list->data;
1437 		GdaHolder *h;
1438 		GError *lerror = NULL;
1439 
1440 		/* find requested parameter */
1441 		if (!params) {
1442 			event = gda_connection_point_available_event (cnc, GDA_CONNECTION_EVENT_ERROR);
1443 			gda_connection_event_set_description (event, _("Missing parameter(s) to execute query"));
1444 			g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
1445 				     GDA_SERVER_PROVIDER_MISSING_PARAM_ERROR,
1446 				     "%s", _("Missing parameter(s) to execute query"));
1447 			break;
1448 		}
1449 
1450 		h = gda_set_get_holder (params, pname);
1451 		if (!h) {
1452 			gchar *tmp = gda_alphanum_to_text (g_strdup (pname + 1));
1453 			if (tmp) {
1454 				h = gda_set_get_holder (params, tmp);
1455 				g_free (tmp);
1456 			}
1457 		}
1458 		if (!h) {
1459 			if (allow_noparam) {
1460                                 /* bind param to NULL */
1461 				jexec_res = jni_wrapper_method_call (jenv, GdaJPStmt__setParameterValue,
1462 								     ps->pstmt_obj, NULL, NULL, &lerror, i, 0);
1463 				if (!jexec_res) {
1464 					event = gda_connection_point_available_event (cnc, GDA_CONNECTION_EVENT_ERROR);
1465 					if (lerror)
1466 						gda_connection_event_set_description (event,
1467 						lerror->message ? lerror->message : _("No detail"));
1468 					g_propagate_error (error, lerror);
1469 					break;
1470 				}
1471 				gda_value_free (jexec_res);
1472                                 empty_rs = TRUE;
1473                                 continue;
1474 			}
1475 			else {
1476 				gchar *str;
1477 				str = g_strdup_printf (_("Missing parameter '%s' to execute query"), pname);
1478 				event = gda_connection_point_available_event (cnc, GDA_CONNECTION_EVENT_ERROR);
1479 				gda_connection_event_set_description (event, str);
1480 				g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
1481 					     GDA_SERVER_PROVIDER_MISSING_PARAM_ERROR, "%s", str);
1482 				g_free (str);
1483 				break;
1484                         }
1485 
1486 		}
1487 		if (!gda_holder_is_valid (h)) {
1488 			if (allow_noparam) {
1489                                 /* bind param to NULL */
1490 				jexec_res = jni_wrapper_method_call (jenv, GdaJPStmt__setParameterValue,
1491 								     ps->pstmt_obj, NULL, NULL, &lerror, i, 0);
1492 				if (!jexec_res) {
1493 					event = gda_connection_point_available_event (cnc, GDA_CONNECTION_EVENT_ERROR);
1494 					if (lerror)
1495 						gda_connection_event_set_description (event,
1496 						lerror->message ? lerror->message : _("No detail"));
1497 					g_propagate_error (error, lerror);
1498 					break;
1499 				}
1500 				gda_value_free (jexec_res);
1501                                 empty_rs = TRUE;
1502                                 continue;
1503 			}
1504 			else {
1505 				gchar *str;
1506 				str = g_strdup_printf (_("Parameter '%s' is invalid"), pname);
1507 				event = gda_connection_point_available_event (cnc, GDA_CONNECTION_EVENT_ERROR);
1508 				gda_connection_event_set_description (event, str);
1509 				g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
1510 					     GDA_SERVER_PROVIDER_MISSING_PARAM_ERROR, "%s", str);
1511 				g_free (str);
1512 				break;
1513                         }
1514 		}
1515 		else if (gda_holder_value_is_default (h) && !gda_holder_get_value (h)) {
1516 			/* create a new GdaStatement to handle all default values and execute it instead */
1517 			GdaSqlStatement *sqlst;
1518 			GError *lerror = NULL;
1519 			sqlst = gda_statement_rewrite_for_default_values (stmt, params, TRUE, &lerror);
1520 			if (!sqlst) {
1521 				event = gda_connection_point_available_event (cnc,
1522 									      GDA_CONNECTION_EVENT_ERROR);
1523 				gda_connection_event_set_description (event, lerror && lerror->message ?
1524 								      lerror->message :
1525 								      _("Can't rewrite statement handle default values"));
1526 				g_propagate_error (error, lerror);
1527 				break;
1528 			}
1529 
1530 			GdaStatement *rstmt;
1531 			GObject *res;
1532 			rstmt = g_object_new (GDA_TYPE_STATEMENT, "structure", sqlst, NULL);
1533 			gda_sql_statement_free (sqlst);
1534 			g_object_unref (ps);
1535 			_gda_jdbc_release_jenv (jni_detach);
1536 			res = gda_jdbc_provider_statement_execute (provider, cnc,
1537 								   rstmt, params,
1538 								   model_usage,
1539 								   col_types, last_inserted_row,
1540 								   task_id,
1541 								   async_cb, cb_data, error);
1542 			g_object_unref (rstmt);
1543 			return res;
1544 		}
1545 
1546 		/* actual binding using the C API, for parameter at position @i */
1547 		const GValue *value = gda_holder_get_value (h);
1548 		if (!value || gda_value_is_null (value)) {
1549 			GdaStatement *rstmt;
1550 			if (! gda_rewrite_statement_for_null_parameters (stmt, params, &rstmt, error)) {
1551 				jexec_res = jni_wrapper_method_call (jenv, GdaJPStmt__setParameterValue,
1552 								     ps->pstmt_obj, NULL, NULL, &lerror, i,
1553 								     (G_VALUE_TYPE (value) == GDA_TYPE_NULL) ? (glong) 0 : (glong) value);
1554 				if (!jexec_res) {
1555 					event = gda_connection_point_available_event (cnc, GDA_CONNECTION_EVENT_ERROR);
1556 					if (lerror)
1557 						gda_connection_event_set_description (event,
1558 										      lerror->message ? lerror->message : _("No detail"));
1559 
1560 					g_propagate_error (error, lerror);
1561 					break;
1562 				}
1563 				gda_value_free (jexec_res);
1564 			}
1565 			else if (!rstmt)
1566 				return NULL;
1567 			else {
1568 				_gda_jdbc_release_jenv (jni_detach);
1569 
1570 				/* The strategy here is to execute @rstmt using its prepared
1571 				 * statement, but with common data from @ps. Beware that
1572 				 * the @param_ids attribute needs to be retained (i.e. it must not
1573 				 * be the one copied from @ps) */
1574 				GObject *obj;
1575 				GdaJdbcPStmt *tps;
1576 				GdaPStmt *gtps;
1577 				GSList *prep_param_ids, *copied_param_ids;
1578 				if (!gda_jdbc_provider_statement_prepare (provider, cnc,
1579 									  rstmt, error))
1580 					return NULL;
1581 				tps = (GdaJdbcPStmt *)
1582 					gda_connection_get_prepared_statement (cnc, rstmt);
1583 				gtps = (GdaPStmt *) tps;
1584 
1585 				/* keep @param_ids to avoid being cleared by gda_pstmt_copy_contents() */
1586 				prep_param_ids = gtps->param_ids;
1587 				gtps->param_ids = NULL;
1588 
1589 				/* actual copy */
1590 				gda_pstmt_copy_contents ((GdaPStmt *) ps, (GdaPStmt *) tps);
1591 
1592 				/* restore previous @param_ids */
1593 				copied_param_ids = gtps->param_ids;
1594 				gtps->param_ids = prep_param_ids;
1595 
1596 				/* execute */
1597 				obj = gda_jdbc_provider_statement_execute (provider, cnc,
1598 									   rstmt, params,
1599 									   model_usage,
1600 									   col_types,
1601 									   last_inserted_row,
1602 									   task_id, async_cb,
1603 									   cb_data, error);
1604 				/* clear original @param_ids and restore copied one */
1605 				g_slist_foreach (prep_param_ids, (GFunc) g_free, NULL);
1606 				g_slist_free (prep_param_ids);
1607 
1608 				gtps->param_ids = copied_param_ids;
1609 
1610 				/*if (GDA_IS_DATA_MODEL (obj))
1611 				  gda_data_model_dump ((GdaDataModel*) obj, NULL);*/
1612 
1613 				g_object_unref (rstmt);
1614 				g_object_unref (ps);
1615 				return obj;
1616 			}
1617 		}
1618 		else {
1619 			jexec_res = jni_wrapper_method_call (jenv, GdaJPStmt__setParameterValue,
1620 							     ps->pstmt_obj, NULL, NULL, &lerror, i,
1621 							     (G_VALUE_TYPE (value) == GDA_TYPE_NULL) ? (glong) 0 : (glong) value);
1622 			if (!jexec_res) {
1623 				event = gda_connection_point_available_event (cnc, GDA_CONNECTION_EVENT_ERROR);
1624 				if (lerror)
1625 					gda_connection_event_set_description (event,
1626 									      lerror->message ? lerror->message : _("No detail"));
1627 
1628 				g_propagate_error (error, lerror);
1629 				break;
1630 			}
1631 			gda_value_free (jexec_res);
1632 		}
1633 	}
1634 
1635 	if (event) {
1636 		gda_connection_add_event (cnc, event);
1637 		g_object_unref (ps);
1638 		_gda_jdbc_release_jenv (jni_detach);
1639 		return NULL;
1640 	}
1641 
1642 	/* add a connection event for the execution */
1643 	event = gda_connection_point_available_event (cnc, GDA_CONNECTION_EVENT_COMMAND);
1644         gda_connection_event_set_description (event, _GDA_PSTMT (ps)->sql);
1645         gda_connection_add_event (cnc, event);
1646 
1647 	if (empty_rs) {
1648 		/* There are some missing parameters, so the SQL can't be executed but we still want
1649 		 * to execute something to get the columns correctly. A possibility is to actually
1650 		 * execute another SQL which is the code shown here.
1651 		 *
1652 		 * To adapt depending on the C API and its features */
1653 		GdaStatement *estmt;
1654                 gchar *esql;
1655 		jstring jsql;
1656                 estmt = gda_select_alter_select_for_empty (stmt, error);
1657                 if (!estmt) {
1658 			g_object_unref (ps);
1659 			_gda_jdbc_release_jenv (jni_detach);
1660                         return NULL;
1661 		}
1662                 esql = gda_statement_to_sql (estmt, NULL, error);
1663                 g_object_unref (estmt);
1664                 if (!esql) {
1665 			g_object_unref (ps);
1666 			_gda_jdbc_release_jenv (jni_detach);
1667                         return NULL;
1668 		}
1669 
1670 		/* Execute the 'esql' SQL code */
1671 		jsql = (*jenv)->NewStringUTF (jenv, esql);
1672                 g_free (esql);
1673 		jexec_res = jni_wrapper_method_call (jenv, GdaJConnection__executeDirectSQL,
1674 						     cdata->jcnc_obj, NULL, NULL, error, jsql);
1675 		(*jenv)->DeleteLocalRef (jenv, jsql);
1676 		if (!jexec_res) {
1677 			g_object_unref (ps);
1678 			_gda_jdbc_release_jenv (jni_detach);
1679 			return NULL;
1680 		}
1681 	}
1682 	else {
1683 		/* Execute the _GDA_PSTMT (ps)->sql SQL code */
1684 		gboolean is_rs;
1685 		jexec_res = jni_wrapper_method_call (jenv, GdaJPStmt__execute,
1686 						     ps->pstmt_obj, NULL, NULL, error);
1687 		if (!jexec_res) {
1688 			g_object_unref (ps);
1689 			_gda_jdbc_release_jenv (jni_detach);
1690 			return NULL;
1691 		}
1692 
1693 		is_rs = g_value_get_boolean (jexec_res);
1694 		gda_value_free (jexec_res);
1695 		if (is_rs) {
1696 			jexec_res = jni_wrapper_method_call (jenv, GdaJPStmt__getResultSet,
1697 							     ps->pstmt_obj, NULL, NULL, error);
1698 			if (!jexec_res) {
1699 				g_object_unref (ps);
1700 				_gda_jdbc_release_jenv (jni_detach);
1701 				return NULL;
1702 			}
1703 		}
1704 		else {
1705 			jexec_res = jni_wrapper_method_call (jenv, GdaJPStmt__getImpactedRows,
1706 							     ps->pstmt_obj, NULL, NULL, error);
1707 			if (!jexec_res) {
1708 				g_object_unref (ps);
1709 				_gda_jdbc_release_jenv (jni_detach);
1710 				return NULL;
1711 			}
1712 		}
1713 	}
1714 
1715 	if (G_VALUE_TYPE (jexec_res) == GDA_TYPE_JNI_OBJECT) {
1716 		/* Note: at this point jexec_res must contain a GdaJResultSet JAVA object */
1717 		GObject *data_model;
1718 		GdaDataModelAccessFlags flags;
1719 
1720 		if (model_usage & GDA_STATEMENT_MODEL_RANDOM_ACCESS)
1721 			flags = GDA_DATA_MODEL_ACCESS_RANDOM;
1722 		else
1723 			flags = GDA_DATA_MODEL_ACCESS_CURSOR_FORWARD;
1724 
1725                 data_model = (GObject *) gda_jdbc_recordset_new (cnc, ps, params, jenv, jexec_res, flags, col_types);
1726 		gda_connection_internal_statement_executed (cnc, stmt, params, NULL); /* required: help @cnc keep some stats */
1727 
1728 		g_object_unref (ps);
1729 		_gda_jdbc_release_jenv (jni_detach);
1730 		return data_model;
1731         }
1732 	else {
1733 		GdaSet *set = NULL;
1734 
1735 		/*
1736 		gchar *str;
1737 		GdaConnectionEvent *event;
1738 
1739 		event = gda_connection_point_available_event (cnc, GDA_CONNECTION_EVENT_NOTICE);
1740 		str = g_strdup (PQcmdStatus (pg_res));
1741 		gda_connection_event_set_description (event, str);
1742 		g_free (str);
1743 		gda_connection_add_event (cnc, event);
1744 		*/
1745 
1746 		set = gda_set_new_inline (1, "IMPACTED_ROWS", G_TYPE_INT, g_value_get_int (jexec_res));
1747 		gda_value_free (jexec_res);
1748 
1749 		/*
1750 		if ((PQoidValue (pg_res) != InvalidOid) && last_inserted_row)
1751 			*last_inserted_row = make_last_inserted_set (cnc, stmt, PQoidValue (pg_res));
1752 			*/
1753 		gda_connection_internal_statement_executed (cnc, stmt, params, event); /* required: help @cnc keep some stats */
1754 		g_object_unref (ps);
1755 		_gda_jdbc_release_jenv (jni_detach);
1756 		return (GObject*) set;
1757 	}
1758 }
1759 
1760 /*
1761  * Rewrites a statement in case some parameters in @params are set to DEFAULT, for INSERT or UPDATE statements
1762  *
1763  * Safely removes any default value inserted or updated
1764  */
1765 static GdaSqlStatement *
gda_jdbc_statement_rewrite(GdaServerProvider * provider,GdaConnection * cnc,GdaStatement * stmt,GdaSet * params,GError ** error)1766 gda_jdbc_statement_rewrite (GdaServerProvider *provider, GdaConnection *cnc,
1767 			    GdaStatement *stmt, GdaSet *params, GError **error)
1768 {
1769 	if (cnc) {
1770 		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
1771 		g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
1772 	}
1773 	return gda_statement_rewrite_for_default_values (stmt, params, TRUE, error);
1774 }
1775 
1776 /*
1777  * starts a distributed transaction: put the XA transaction in the ACTIVE state
1778  */
1779 static gboolean
gda_jdbc_provider_xa_start(GdaServerProvider * provider,GdaConnection * cnc,const GdaXaTransactionId * xid,G_GNUC_UNUSED GError ** error)1780 gda_jdbc_provider_xa_start (GdaServerProvider *provider, GdaConnection *cnc,
1781 				const GdaXaTransactionId *xid, G_GNUC_UNUSED GError **error)
1782 {
1783 	JdbcConnectionData *cdata;
1784 
1785 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
1786 	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
1787 	g_return_val_if_fail (xid, FALSE);
1788 
1789 	cdata = (JdbcConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error);
1790 	if (!cdata)
1791 		return FALSE;
1792 
1793 	/*
1794 	 * see Sun's Java Transaction API:
1795 	 * http://java.sun.com/javaee/technologies/jta/index.jsp
1796 	 */
1797 	TO_IMPLEMENT;
1798 	return FALSE;
1799 }
1800 
1801 /*
1802  * put the XA transaction in the IDLE state: the connection won't accept any more modifications.
1803  * This state is required by some database providers before actually going to the PREPARED state
1804  */
1805 static gboolean
gda_jdbc_provider_xa_end(GdaServerProvider * provider,GdaConnection * cnc,const GdaXaTransactionId * xid,G_GNUC_UNUSED GError ** error)1806 gda_jdbc_provider_xa_end (GdaServerProvider *provider, GdaConnection *cnc,
1807 			      const GdaXaTransactionId *xid, G_GNUC_UNUSED GError **error)
1808 {
1809 	JdbcConnectionData *cdata;
1810 
1811 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
1812 	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
1813 	g_return_val_if_fail (xid, FALSE);
1814 
1815 	cdata = (JdbcConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error);
1816 	if (!cdata)
1817 		return FALSE;
1818 
1819 	TO_IMPLEMENT;
1820 	return FALSE;
1821 }
1822 
1823 /*
1824  * prepares the distributed transaction: put the XA transaction in the PREPARED state
1825  */
1826 static gboolean
gda_jdbc_provider_xa_prepare(GdaServerProvider * provider,GdaConnection * cnc,const GdaXaTransactionId * xid,G_GNUC_UNUSED GError ** error)1827 gda_jdbc_provider_xa_prepare (GdaServerProvider *provider, GdaConnection *cnc,
1828 				  const GdaXaTransactionId *xid, G_GNUC_UNUSED GError **error)
1829 {
1830 	JdbcConnectionData *cdata;
1831 
1832 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
1833 	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
1834 	g_return_val_if_fail (xid, FALSE);
1835 
1836 	cdata = (JdbcConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error);
1837 	if (!cdata)
1838 		return FALSE;
1839 
1840 	TO_IMPLEMENT;
1841 	return FALSE;
1842 }
1843 
1844 /*
1845  * commits the distributed transaction: actually write the prepared data to the database and
1846  * terminates the XA transaction
1847  */
1848 static gboolean
gda_jdbc_provider_xa_commit(GdaServerProvider * provider,GdaConnection * cnc,const GdaXaTransactionId * xid,G_GNUC_UNUSED GError ** error)1849 gda_jdbc_provider_xa_commit (GdaServerProvider *provider, GdaConnection *cnc,
1850 				 const GdaXaTransactionId *xid, G_GNUC_UNUSED GError **error)
1851 {
1852 	JdbcConnectionData *cdata;
1853 
1854 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
1855 	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
1856 	g_return_val_if_fail (xid, FALSE);
1857 
1858 	cdata = (JdbcConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error);
1859 	if (!cdata)
1860 		return FALSE;
1861 
1862 	TO_IMPLEMENT;
1863 	return FALSE;
1864 }
1865 
1866 /*
1867  * Rolls back an XA transaction, possible only if in the ACTIVE, IDLE or PREPARED state
1868  */
1869 static gboolean
gda_jdbc_provider_xa_rollback(GdaServerProvider * provider,GdaConnection * cnc,const GdaXaTransactionId * xid,G_GNUC_UNUSED GError ** error)1870 gda_jdbc_provider_xa_rollback (GdaServerProvider *provider, GdaConnection *cnc,
1871 				   const GdaXaTransactionId *xid, G_GNUC_UNUSED GError **error)
1872 {
1873 	JdbcConnectionData *cdata;
1874 
1875 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
1876 	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
1877 	g_return_val_if_fail (xid, FALSE);
1878 
1879 	cdata = (JdbcConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error);
1880 	if (!cdata)
1881 		return FALSE;
1882 
1883 	TO_IMPLEMENT;
1884 	return FALSE;
1885 }
1886 
1887 /*
1888  * Lists all XA transactions that are in the PREPARED state
1889  *
1890  * Returns: a list of GdaXaTransactionId structures, which will be freed by the caller
1891  */
1892 static GList *
gda_jdbc_provider_xa_recover(GdaServerProvider * provider,GdaConnection * cnc,G_GNUC_UNUSED GError ** error)1893 gda_jdbc_provider_xa_recover (GdaServerProvider *provider, GdaConnection *cnc,
1894 				  G_GNUC_UNUSED GError **error)
1895 {
1896 	JdbcConnectionData *cdata;
1897 
1898 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
1899 	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
1900 
1901 	cdata = (JdbcConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error);
1902 	if (!cdata)
1903 		return NULL;
1904 
1905 	TO_IMPLEMENT;
1906 	return NULL;
1907 }
1908 
1909 /*
1910  * Free connection's specific data
1911  */
1912 static void
gda_jdbc_free_cnc_data(JdbcConnectionData * cdata)1913 gda_jdbc_free_cnc_data (JdbcConnectionData *cdata)
1914 {
1915 	if (!cdata)
1916 		return;
1917 
1918 	g_free (cdata->server_version);
1919 
1920 	if (cdata->jcnc_obj) {
1921 		/* force the connection to be closed */
1922 		JNIEnv *jenv = NULL;
1923 		gboolean jni_detach;
1924 		GError *error = NULL;
1925 
1926 		jenv = _gda_jdbc_get_jenv (&jni_detach, &error);
1927 		if (!jenv) {
1928 			g_warning ("%s", error->message);
1929 			g_error_free (error);
1930 		}
1931 		else {
1932 			GValue *res;
1933 			res = jni_wrapper_method_call (jenv, GdaJConnection__close,
1934 						       cdata->jcnc_obj, NULL, NULL, &error);
1935 			if (res) {
1936 #ifdef GDA_DEBUG
1937 				g_print ("Connection closed!\n");
1938 #endif
1939 				gda_value_free (res);
1940 			}
1941 			else {
1942 				g_warning ("Could not propertly close JDBC connection (will be done by the garbage collector): %s",
1943 					   error && error->message ? error->message : "No detail");
1944 				if (error)
1945 					g_error_free (error);
1946 			}
1947 			_gda_jdbc_release_jenv (jni_detach);
1948 		}
1949 		gda_value_free (cdata->jcnc_obj);
1950 		cdata->jcnc_obj = NULL;
1951 	}
1952 
1953 	if (cdata->jmeta_obj)
1954 		gda_value_free (cdata->jmeta_obj);
1955 
1956 	g_free (cdata);
1957 }
1958 
1959 /**
1960  * gda_jdbc_provider_new
1961  * @jdbc_driver: the JDBC driver to use (such as "sun.jdbc.odbc.JdbcOdbcDriver")
1962  * @error: a place to store errors, or %NULL
1963  *
1964  * Returns: a new #GdaServerProvider for that JDBC driver, or %NULL if an error occurred
1965  */
1966 GdaServerProvider *
gda_jdbc_provider_new(const gchar * jdbc_driver,GError ** error)1967 gda_jdbc_provider_new (const gchar *jdbc_driver, GError **error)
1968 {
1969 	GdaServerProvider *prov;
1970 	g_return_val_if_fail (jdbc_driver, NULL);
1971 
1972 	if (!_jdbc_provider_java_vm) {
1973 		g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_INTERNAL_ERROR,
1974 			     "%s", "No JVM runtime identified (this should not happen at this point)!");
1975 		return NULL;
1976 	}
1977 
1978 	/* create a JAVA's GdaJProvider object */
1979 	JNIEnv *env;
1980 	GValue *obj_value;
1981 	jstring jstr;
1982 	gboolean detach_jni;
1983 
1984 	env = _gda_jdbc_get_jenv (&detach_jni, error);
1985 	if (!env)
1986 		return NULL;
1987 
1988 	jstr = (*env)->NewStringUTF(env, jdbc_driver);
1989 	obj_value = jni_wrapper_instantiate_object (env, GdaJProvider_class, "(Ljava/lang/String;)V", error, jstr);
1990 	(*env)->DeleteLocalRef(env, jstr);
1991 	if (!obj_value) {
1992 		_gda_jdbc_release_jenv (detach_jni);
1993 		return NULL;
1994 	}
1995 
1996 	prov = (GdaServerProvider*) g_object_new (GDA_TYPE_JDBC_PROVIDER, NULL);
1997 	GDA_JDBC_PROVIDER (prov)->jprov_obj = obj_value;
1998 	_gda_jdbc_release_jenv (detach_jni);
1999 
2000 	GDA_JDBC_PROVIDER (prov)->jdbc_driver = g_strdup (jdbc_driver);
2001 
2002 	return prov;
2003 }
2004