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 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 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 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 (®istering); 314 if (type == 0) 315 type = g_type_register_static (GDA_TYPE_SERVER_PROVIDER, "GdaJdbcProvider", &info, 0); 316 g_mutex_unlock (®istering); 317 } 318 319 return type; 320 } 321 322 323 /* 324 * Get provider name request 325 */ 326 static const gchar * 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 * 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 * 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 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 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 * 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 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 * 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 * 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 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 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 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 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 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 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 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 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 * 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* 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 * 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 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, ¶ms, 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 * 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 * 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 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 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 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 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 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 * 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 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 * 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