1 /* 2 * Copyright (C) 2001 - 2003 Rodrigo Moya <rodrigo@gnome-db.org> 3 * Copyright (C) 2002 - 2003 Gonzalo Paniagua Javier <gonzalo@gnome-db.org> 4 * Copyright (C) 2002 Tim Coleman <tim@timcoleman.com> 5 * Copyright (C) 2003 Christian Neumair <cneumair@src.gnome.org> 6 * Copyright (C) 2003 Steve Fosdick <fozzy@src.gnome.org> 7 * Copyright (C) 2004 Julio M. Merino Vidal <jmmv@menta.net> 8 * Copyright (C) 2005 Magnus Bergman <magnus.bergman@observer.net> 9 * Copyright (C) 2005 - 2013 Vivien Malerba <malerba@gnome-db.org> 10 * Copyright (C) 2006 - 2009 Bas Driessen <bas.driessen@xobas.com> 11 * Copyright (C) 2007 Murray Cumming <murrayc@murrayc.com> 12 * Camellia_cbc_encrypt(const unsigned char * in,unsigned char * out,size_t len,const CAMELLIA_KEY * key,unsigned char * ivec,const int enc)13 * This library is free software; you can redistribute it and/or 14 * modify it under the terms of the GNU Lesser General Public 15 * License as published by the Free Software Foundation; either 16 * version 2 of the License, or (at your option) any later version. 17 * 18 * This library is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 * Lesser General Public License for more details. 22 * 23 * You should have received a copy of the GNU Lesser General Public 24 * License along with this library; if not, write to the 25 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 26 * Boston, MA 02110-1301, USA. 27 */ 28 29 #undef GDA_DISABLE_DEPRECATED 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <errno.h> 33 #include <string.h> 34 #include <glib/gi18n-lib.h> 35 #include <glib/gstdio.h> 36 #include <libgda/libgda.h> 37 #include <libgda/gda-data-model-private.h> 38 #include <libgda/gda-server-provider-extra.h> 39 #include <libgda/binreloc/gda-binreloc.h> 40 #include <libgda/gda-statement-extra.h> 41 #include <sql-parser/gda-sql-parser.h> 42 #include "gda-oracle.h" 43 #include "gda-oracle-provider.h" 44 #include "gda-oracle-recordset.h" 45 #include "gda-oracle-ddl.h" 46 #include "gda-oracle-meta.h" 47 #include "gda-oracle-util.h" 48 #include "gda-oracle-parser.h" 49 #include <libgda/gda-debug-macros.h> 50 51 #define _GDA_PSTMT(x) ((GdaPStmt*)(x)) 52 53 /* 54 * GObject methods 55 */ 56 static void gda_oracle_provider_class_init (GdaOracleProviderClass *klass); 57 static void gda_oracle_provider_init (GdaOracleProvider *provider, 58 GdaOracleProviderClass *klass); 59 static GObjectClass *parent_class = NULL; 60 61 /* 62 * GdaServerProvider's virtual methods 63 */ 64 /* connection management */ 65 static gboolean gda_oracle_provider_open_connection (GdaServerProvider *provider, GdaConnection *cnc, 66 GdaQuarkList *params, GdaQuarkList *auth, 67 guint *task_id, GdaServerProviderAsyncCallback async_cb, gpointer cb_data); 68 static gboolean gda_oracle_provider_close_connection (GdaServerProvider *provider, GdaConnection *cnc); 69 static const gchar *gda_oracle_provider_get_server_version (GdaServerProvider *provider, GdaConnection *cnc); 70 static const gchar *gda_oracle_provider_get_database (GdaServerProvider *provider, GdaConnection *cnc); 71 72 /* DDL operations */ 73 static gboolean gda_oracle_provider_supports_operation (GdaServerProvider *provider, GdaConnection *cnc, 74 GdaServerOperationType type, GdaSet *options); 75 static GdaServerOperation *gda_oracle_provider_create_operation (GdaServerProvider *provider, GdaConnection *cnc, 76 GdaServerOperationType type, 77 GdaSet *options, GError **error); 78 static gchar *gda_oracle_provider_render_operation (GdaServerProvider *provider, GdaConnection *cnc, 79 GdaServerOperation *op, GError **error); 80 81 static gboolean gda_oracle_provider_perform_operation (GdaServerProvider *provider, GdaConnection *cnc, 82 GdaServerOperation *op, guint *task_id, 83 GdaServerProviderAsyncCallback async_cb, gpointer cb_data, 84 GError **error); 85 /* transactions */ 86 static gboolean gda_oracle_provider_begin_transaction (GdaServerProvider *provider, GdaConnection *cnc, 87 const gchar *name, GdaTransactionIsolation level, GError **error); 88 static gboolean gda_oracle_provider_commit_transaction (GdaServerProvider *provider, GdaConnection *cnc, 89 const gchar *name, GError **error); 90 static gboolean gda_oracle_provider_rollback_transaction (GdaServerProvider *provider, GdaConnection * cnc, 91 const gchar *name, GError **error); 92 static gboolean gda_oracle_provider_add_savepoint (GdaServerProvider *provider, GdaConnection *cnc, 93 const gchar *name, GError **error); 94 static gboolean gda_oracle_provider_rollback_savepoint (GdaServerProvider *provider, GdaConnection *cnc, 95 const gchar *name, GError **error); 96 static gboolean gda_oracle_provider_delete_savepoint (GdaServerProvider *provider, GdaConnection *cnc, 97 const gchar *name, GError **error); 98 99 /* information retrieval */ 100 static const gchar *gda_oracle_provider_get_version (GdaServerProvider *provider); 101 static gboolean gda_oracle_provider_supports_feature (GdaServerProvider *provider, GdaConnection *cnc, 102 GdaConnectionFeature feature); 103 104 static const gchar *gda_oracle_provider_get_name (GdaServerProvider *provider); 105 106 static GdaDataHandler *gda_oracle_provider_get_data_handler (GdaServerProvider *provider, GdaConnection *cnc, 107 GType g_type, const gchar *dbms_type); 108 109 static const gchar* gda_oracle_provider_get_default_dbms_type (GdaServerProvider *provider, GdaConnection *cnc, 110 GType type); 111 /* statements */ 112 static GdaSqlParser *gda_oracle_provider_create_parser (GdaServerProvider *provider, GdaConnection *cnc); 113 static gchar *gda_oracle_provider_statement_to_sql (GdaServerProvider *provider, GdaConnection *cnc, 114 GdaStatement *stmt, GdaSet *params, 115 GdaStatementSqlFlag flags, 116 GSList **params_used, GError **error); 117 static gboolean gda_oracle_provider_statement_prepare (GdaServerProvider *provider, GdaConnection *cnc, 118 GdaStatement *stmt, GError **error); 119 static GObject *gda_oracle_provider_statement_execute (GdaServerProvider *provider, GdaConnection *cnc, 120 GdaStatement *stmt, GdaSet *params, 121 GdaStatementModelUsage model_usage, 122 GType *col_types, GdaSet **last_inserted_row, 123 guint *task_id, GdaServerProviderExecCallback async_cb, 124 gpointer cb_data, GError **error); 125 static GdaSqlStatement *gda_oracle_statement_rewrite (GdaServerProvider *provider, GdaConnection *cnc, 126 GdaStatement *stmt, GdaSet *params, GError **error); 127 128 /* Quoting */ 129 static gchar *gda_oracle_identifier_quote (GdaServerProvider *provider, GdaConnection *cnc, 130 const gchar *id, 131 gboolean meta_store_convention, gboolean force_quotes); 132 133 /* distributed transactions */ 134 static gboolean gda_oracle_provider_xa_start (GdaServerProvider *provider, GdaConnection *cnc, 135 const GdaXaTransactionId *xid, GError **error); 136 137 static gboolean gda_oracle_provider_xa_end (GdaServerProvider *provider, GdaConnection *cnc, 138 const GdaXaTransactionId *xid, GError **error); 139 static gboolean gda_oracle_provider_xa_prepare (GdaServerProvider *provider, GdaConnection *cnc, 140 const GdaXaTransactionId *xid, GError **error); 141 142 static gboolean gda_oracle_provider_xa_commit (GdaServerProvider *provider, GdaConnection *cnc, 143 const GdaXaTransactionId *xid, GError **error); 144 static gboolean gda_oracle_provider_xa_rollback (GdaServerProvider *provider, GdaConnection *cnc, 145 const GdaXaTransactionId *xid, GError **error); 146 147 static GList *gda_oracle_provider_xa_recover (GdaServerProvider *provider, GdaConnection *cnc, 148 GError **error); 149 150 /* 151 * private connection data destroy 152 */ 153 static void gda_oracle_free_cnc_data (OracleConnectionData *cdata); 154 155 156 /* 157 * Prepared internal statements 158 * TO_ADD: any prepared statement to be used internally by the provider should be 159 * declared here, as constants and as SQL statements 160 */ 161 static GMutex init_mutex; 162 static GdaStatement **internal_stmt = NULL; 163 164 typedef enum { 165 INTERNAL_STMT1 166 } InternalStatementItem; 167 168 static gchar *internal_sql[] = { 169 "SQL for INTERNAL_STMT1" 170 }; 171 172 /* 173 * GdaOracleProvider class implementation 174 */ 175 static void 176 gda_oracle_provider_class_init (GdaOracleProviderClass *klass) 177 { 178 GdaServerProviderClass *provider_class = GDA_SERVER_PROVIDER_CLASS (klass); 179 180 parent_class = g_type_class_peek_parent (klass); 181 182 provider_class->get_version = gda_oracle_provider_get_version; 183 provider_class->get_server_version = gda_oracle_provider_get_server_version; 184 provider_class->get_name = gda_oracle_provider_get_name; 185 provider_class->supports_feature = gda_oracle_provider_supports_feature; 186 187 provider_class->get_data_handler = gda_oracle_provider_get_data_handler; 188 provider_class->get_def_dbms_type = gda_oracle_provider_get_default_dbms_type; 189 190 provider_class->open_connection = gda_oracle_provider_open_connection; 191 provider_class->close_connection = gda_oracle_provider_close_connection; 192 provider_class->get_database = gda_oracle_provider_get_database; 193 194 provider_class->supports_operation = gda_oracle_provider_supports_operation; 195 provider_class->create_operation = gda_oracle_provider_create_operation; 196 provider_class->render_operation = gda_oracle_provider_render_operation; 197 provider_class->perform_operation = gda_oracle_provider_perform_operation; 198 199 provider_class->begin_transaction = gda_oracle_provider_begin_transaction; 200 provider_class->commit_transaction = gda_oracle_provider_commit_transaction; 201 provider_class->rollback_transaction = gda_oracle_provider_rollback_transaction; 202 provider_class->add_savepoint = gda_oracle_provider_add_savepoint; 203 provider_class->rollback_savepoint = gda_oracle_provider_rollback_savepoint; 204 provider_class->delete_savepoint = gda_oracle_provider_delete_savepoint; 205 206 provider_class->create_parser = gda_oracle_provider_create_parser; 207 provider_class->statement_to_sql = gda_oracle_provider_statement_to_sql; 208 provider_class->statement_prepare = gda_oracle_provider_statement_prepare; 209 provider_class->statement_execute = gda_oracle_provider_statement_execute; 210 provider_class->statement_rewrite = gda_oracle_statement_rewrite; 211 212 provider_class->is_busy = NULL; 213 provider_class->cancel = NULL; 214 provider_class->create_connection = NULL; 215 provider_class->identifier_quote = gda_oracle_identifier_quote; 216 217 memset (&(provider_class->meta_funcs), 0, sizeof (GdaServerProviderMeta)); 218 provider_class->meta_funcs._info = _gda_oracle_meta__info; 219 provider_class->meta_funcs._btypes = _gda_oracle_meta__btypes; 220 provider_class->meta_funcs._udt = _gda_oracle_meta__udt; 221 provider_class->meta_funcs.udt = _gda_oracle_meta_udt; 222 provider_class->meta_funcs._udt_cols = _gda_oracle_meta__udt_cols; 223 provider_class->meta_funcs.udt_cols = _gda_oracle_meta_udt_cols; 224 provider_class->meta_funcs._enums = _gda_oracle_meta__enums; 225 provider_class->meta_funcs.enums = _gda_oracle_meta_enums; 226 provider_class->meta_funcs._domains = _gda_oracle_meta__domains; 227 provider_class->meta_funcs.domains = _gda_oracle_meta_domains; 228 provider_class->meta_funcs._constraints_dom = _gda_oracle_meta__constraints_dom; 229 provider_class->meta_funcs.constraints_dom = _gda_oracle_meta_constraints_dom; 230 provider_class->meta_funcs._el_types = _gda_oracle_meta__el_types; 231 provider_class->meta_funcs.el_types = _gda_oracle_meta_el_types; 232 provider_class->meta_funcs._collations = _gda_oracle_meta__collations; 233 provider_class->meta_funcs.collations = _gda_oracle_meta_collations; 234 provider_class->meta_funcs._character_sets = _gda_oracle_meta__character_sets; 235 provider_class->meta_funcs.character_sets = _gda_oracle_meta_character_sets; 236 provider_class->meta_funcs._schemata = _gda_oracle_meta__schemata; 237 provider_class->meta_funcs.schemata = _gda_oracle_meta_schemata; 238 provider_class->meta_funcs._tables_views = _gda_oracle_meta__tables_views; 239 provider_class->meta_funcs.tables_views = _gda_oracle_meta_tables_views; 240 provider_class->meta_funcs._columns = _gda_oracle_meta__columns; 241 provider_class->meta_funcs.columns = _gda_oracle_meta_columns; 242 provider_class->meta_funcs._view_cols = _gda_oracle_meta__view_cols; 243 provider_class->meta_funcs.view_cols = _gda_oracle_meta_view_cols; 244 provider_class->meta_funcs._constraints_tab = _gda_oracle_meta__constraints_tab; 245 provider_class->meta_funcs.constraints_tab = _gda_oracle_meta_constraints_tab; 246 provider_class->meta_funcs._constraints_ref = _gda_oracle_meta__constraints_ref; 247 provider_class->meta_funcs.constraints_ref = _gda_oracle_meta_constraints_ref; 248 provider_class->meta_funcs._key_columns = _gda_oracle_meta__key_columns; 249 provider_class->meta_funcs.key_columns = _gda_oracle_meta_key_columns; 250 provider_class->meta_funcs._check_columns = _gda_oracle_meta__check_columns; 251 provider_class->meta_funcs.check_columns = _gda_oracle_meta_check_columns; 252 provider_class->meta_funcs._triggers = _gda_oracle_meta__triggers; 253 provider_class->meta_funcs.triggers = _gda_oracle_meta_triggers; 254 provider_class->meta_funcs._routines = _gda_oracle_meta__routines; 255 provider_class->meta_funcs.routines = _gda_oracle_meta_routines; 256 provider_class->meta_funcs._routine_col = _gda_oracle_meta__routine_col; 257 provider_class->meta_funcs.routine_col = _gda_oracle_meta_routine_col; 258 provider_class->meta_funcs._routine_par = _gda_oracle_meta__routine_par; 259 provider_class->meta_funcs.routine_par = _gda_oracle_meta_routine_par; 260 provider_class->meta_funcs._indexes_tab = _gda_oracle_meta__indexes_tab; 261 provider_class->meta_funcs.indexes_tab = _gda_oracle_meta_indexes_tab; 262 provider_class->meta_funcs._index_cols = _gda_oracle_meta__index_cols; 263 provider_class->meta_funcs.index_cols = _gda_oracle_meta_index_cols; 264 265 /* distributed transactions: if not supported, then provider_class->xa_funcs should be set to NULL */ 266 provider_class->xa_funcs = g_new0 (GdaServerProviderXa, 1); 267 provider_class->xa_funcs->xa_start = gda_oracle_provider_xa_start; 268 provider_class->xa_funcs->xa_end = gda_oracle_provider_xa_end; 269 provider_class->xa_funcs->xa_prepare = gda_oracle_provider_xa_prepare; 270 provider_class->xa_funcs->xa_commit = gda_oracle_provider_xa_commit; 271 provider_class->xa_funcs->xa_rollback = gda_oracle_provider_xa_rollback; 272 provider_class->xa_funcs->xa_recover = gda_oracle_provider_xa_recover; 273 274 /* thread safe */ 275 provider_class->limiting_thread = NULL; 276 277 /* static types */ 278 static_types = g_new (GType, GDA_STYPE_NULL + 1); 279 static_types[GDA_STYPE_INT] = G_TYPE_INT; 280 static_types[GDA_STYPE_STRING] = G_TYPE_STRING; 281 static_types[GDA_STYPE_BOOLEAN] = G_TYPE_BOOLEAN; 282 static_types[GDA_STYPE_DATE] = G_TYPE_DATE; 283 static_types[GDA_STYPE_TIME] = GDA_TYPE_TIME; 284 static_types[GDA_STYPE_TIMESTAMP] = GDA_TYPE_TIMESTAMP; 285 static_types[GDA_STYPE_INT64] = G_TYPE_INT64; 286 static_types[GDA_STYPE_UINT64] = G_TYPE_UINT64; 287 static_types[GDA_STYPE_UINT] = G_TYPE_UINT; 288 static_types[GDA_STYPE_FLOAT] = G_TYPE_FLOAT; 289 static_types[GDA_STYPE_DOUBLE] = G_TYPE_DOUBLE; 290 static_types[GDA_STYPE_LONG] = G_TYPE_LONG; 291 static_types[GDA_STYPE_ULONG] = G_TYPE_ULONG; 292 static_types[GDA_STYPE_NUMERIC] = GDA_TYPE_NUMERIC; 293 static_types[GDA_STYPE_BINARY] = GDA_TYPE_BINARY; 294 static_types[GDA_STYPE_BLOB] = GDA_TYPE_BLOB; 295 static_types[GDA_STYPE_CHAR] = G_TYPE_CHAR; 296 static_types[GDA_STYPE_SHORT] = GDA_TYPE_SHORT; 297 static_types[GDA_STYPE_GTYPE] = G_TYPE_GTYPE; 298 static_types[GDA_STYPE_GEOMETRIC_POINT] = GDA_TYPE_GEOMETRIC_POINT; 299 static_types[GDA_STYPE_NULL] = GDA_TYPE_NULL; 300 } 301 302 static void 303 gda_oracle_provider_init (GdaOracleProvider *oracle_prv, G_GNUC_UNUSED GdaOracleProviderClass *klass) 304 { 305 g_mutex_lock (&init_mutex); 306 307 if (!internal_stmt) { 308 InternalStatementItem i; 309 GdaSqlParser *parser; 310 311 parser = gda_server_provider_internal_get_parser ((GdaServerProvider*) oracle_prv); 312 internal_stmt = g_new0 (GdaStatement *, sizeof (internal_sql) / sizeof (gchar*)); 313 for (i = INTERNAL_STMT1; i < sizeof (internal_sql) / sizeof (gchar*); i++) { 314 internal_stmt[i] = gda_sql_parser_parse_string (parser, internal_sql[i], NULL, NULL); 315 if (!internal_stmt[i]) 316 g_error ("Could not parse internal statement: %s\n", internal_sql[i]); 317 } 318 } 319 320 /* meta data init */ 321 _gda_oracle_provider_meta_init ((GdaServerProvider*) oracle_prv); 322 323 g_mutex_unlock (&init_mutex); 324 } 325 326 GType 327 gda_oracle_provider_get_type (void) 328 { 329 static GType type = 0; 330 331 if (G_UNLIKELY (type == 0)) { 332 static GMutex registering; 333 static GTypeInfo info = { 334 sizeof (GdaOracleProviderClass), 335 (GBaseInitFunc) NULL, 336 (GBaseFinalizeFunc) NULL, 337 (GClassInitFunc) gda_oracle_provider_class_init, 338 NULL, NULL, 339 sizeof (GdaOracleProvider), 340 0, 341 (GInstanceInitFunc) gda_oracle_provider_init, 342 NULL 343 }; 344 g_mutex_lock (®istering); 345 if (type == 0) 346 type = g_type_register_static (GDA_TYPE_SERVER_PROVIDER, "GdaOracleProvider", &info, 0); 347 g_mutex_unlock (®istering); 348 } 349 350 return type; 351 } 352 353 354 /* 355 * Get provider name request 356 */ 357 static const gchar * 358 gda_oracle_provider_get_name (G_GNUC_UNUSED GdaServerProvider *provider) 359 { 360 return ORACLE_PROVIDER_NAME; 361 } 362 363 /* 364 * Get provider's version, no need to change this 365 */ 366 static const gchar * 367 gda_oracle_provider_get_version (G_GNUC_UNUSED GdaServerProvider *provider) 368 { 369 return PACKAGE_VERSION; 370 } 371 372 /* 373 * NOT FOR SELECT statements! 374 */ 375 static gboolean 376 execute_raw_command (GdaConnection *cnc, const gchar *sql) 377 { 378 OracleConnectionData *cdata; 379 OCIStmt *hstmt = NULL; 380 int result; 381 382 cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc); 383 if (!cdata) 384 return FALSE; 385 386 result = OCIHandleAlloc ((dvoid *) cdata->henv, 387 (dvoid **) &hstmt, 388 (ub4) OCI_HTYPE_STMT, 389 (size_t) 0, 390 (dvoid **) 0); 391 if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ENV, 392 _("Could not allocate the Oracle statement handle"))) 393 return FALSE; 394 395 result = OCIStmtPrepare ((dvoid *) hstmt, 396 (dvoid *) cdata->herr, 397 (text *) sql, 398 (ub4) strlen(sql), 399 (ub4) OCI_NTV_SYNTAX, 400 (ub4) OCI_DEFAULT); 401 if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR, 402 _("Could not prepare the Oracle statement"))) { 403 OCIHandleFree ((dvoid *) hstmt, OCI_HTYPE_STMT); 404 return FALSE; 405 } 406 407 #ifdef GDA_DEBUG 408 ub2 stmt_type; 409 result = OCIAttrGet (hstmt, OCI_HTYPE_STMT, 410 (dvoid *) &stmt_type, NULL, 411 OCI_ATTR_STMT_TYPE, cdata->herr); 412 if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR, 413 _("Could not get the Oracle statement type"))) { 414 OCIHandleFree ((dvoid *) hstmt, OCI_HTYPE_STMT); 415 return FALSE; 416 } 417 if (stmt_type == OCI_STMT_SELECT) { 418 g_warning ("Internal implementation error: the %s() function can't be used to execute SELECT commands\n", 419 __FUNCTION__); 420 OCIHandleFree ((dvoid *) hstmt, OCI_HTYPE_STMT); 421 return FALSE; 422 } 423 #endif 424 result = OCIStmtExecute (cdata->hservice, 425 hstmt, 426 cdata->herr, 427 (ub4) 1, 428 (ub4) 0, 429 (CONST OCISnapshot *) NULL, 430 (OCISnapshot *) NULL, 431 OCI_DEFAULT); 432 if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR, 433 _("Could not execute the Oracle statement"))) { 434 OCIHandleFree ((dvoid *) hstmt, OCI_HTYPE_STMT); 435 return FALSE; 436 } 437 438 OCIHandleFree ((dvoid *) hstmt, OCI_HTYPE_STMT); 439 return TRUE; 440 } 441 442 /* 443 * Open connection request 444 * 445 * In this function, the following _must_ be done: 446 * - check for the presence and validify of the parameters required to actually open a connection, 447 * using @params 448 * - open the real connection to the database using the parameters previously checked 449 * - create a OracleConnectionData structure and associate it to @cnc 450 * 451 * Returns: TRUE if no error occurred, or FALSE otherwise (and an ERROR gonnection event must be added to @cnc) 452 */ 453 static gboolean 454 gda_oracle_provider_open_connection (GdaServerProvider *provider, GdaConnection *cnc, 455 GdaQuarkList *params, GdaQuarkList *auth, 456 G_GNUC_UNUSED guint *task_id, GdaServerProviderAsyncCallback async_cb, 457 G_GNUC_UNUSED gpointer cb_data) 458 { 459 OracleConnectionData *cdata; 460 g_return_val_if_fail (GDA_IS_ORACLE_PROVIDER (provider), FALSE); 461 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 462 463 /* If asynchronous connection opening is not supported, then exit now */ 464 if (async_cb) { 465 gda_connection_add_event_string (cnc, _("Provider does not support asynchronous connection open")); 466 return FALSE; 467 } 468 469 /* Check for connection parameters */ 470 const gchar *tnsname, *username, *password, *schema; 471 gchar *easy = NULL; 472 tnsname = gda_quark_list_find (params, "TNSNAME"); 473 if (!tnsname) { 474 const gchar *host, *port, *dbname; 475 host = gda_quark_list_find (params, "HOST"); 476 dbname = gda_quark_list_find (params, "DB_NAME"); 477 port = gda_quark_list_find (params, "PORT"); 478 if (host) { 479 GString *string; 480 string = g_string_new (host); 481 if (port) 482 g_string_append_printf (string, ":%s", port); 483 if (dbname) 484 g_string_append_printf (string, "/%s", dbname); 485 easy = g_string_free (string, FALSE); 486 } 487 else { 488 gda_connection_add_event_string (cnc, 489 _("The connection string must contain the TNSNAME or the HOST values")); 490 return FALSE; 491 } 492 } 493 username = gda_quark_list_find (auth, "USERNAME"); 494 if (!username) 495 username = g_get_user_name (); 496 password = gda_quark_list_find (auth, "PASSWORD"); 497 schema = gda_quark_list_find (params, "SCHEMA"); 498 499 /* open the real connection to the database */ 500 gint result; 501 result = OCIInitialize ((ub4) OCI_THREADED, 502 (dvoid *) 0, 503 (dvoid * (*)(dvoid *, size_t)) 0, 504 (dvoid * (*)(dvoid *, dvoid *, size_t)) 0, 505 (void (*)(dvoid *, dvoid *)) 0); 506 507 if (result != OCI_SUCCESS) { 508 gda_connection_add_event_string (cnc, 509 _("Could not initialize Oracle")); 510 return FALSE; 511 } 512 513 /* initialize the Oracle environment */ 514 cdata = g_new0 (OracleConnectionData, 1); 515 cdata->autocommit = TRUE; 516 result = OCIEnvInit ((OCIEnv **) & cdata->henv, 517 (ub4) OCI_DEFAULT, 518 (size_t) 0, 519 (dvoid **) 0); 520 if (result != OCI_SUCCESS) { 521 gda_connection_add_event_string (cnc, 522 _("Could not initialize the Oracle environment")); 523 gda_oracle_free_cnc_data (cdata); 524 return FALSE; 525 } 526 527 /* create the service context */ 528 result = OCIHandleAlloc ((dvoid *) cdata->henv, 529 (dvoid **) &cdata->hservice, 530 (ub4) OCI_HTYPE_SVCCTX, 531 (size_t) 0, 532 (dvoid **) 0); 533 if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ENV, 534 _("Could not allocate the Oracle service handle"))) { 535 gda_oracle_free_cnc_data (cdata); 536 return FALSE; 537 } 538 539 /* create the error handle */ 540 result = OCIHandleAlloc ((dvoid *) cdata->henv, 541 (dvoid **) &(cdata->herr), 542 (ub4) OCI_HTYPE_ERROR, 543 (size_t) 0, 544 (dvoid **) 0); 545 if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ENV, 546 _("Could not allocate the Oracle error handle"))) { 547 OCIHandleFree ((dvoid *) cdata->hservice, OCI_HTYPE_SVCCTX); 548 gda_oracle_free_cnc_data (cdata); 549 return FALSE; 550 } 551 552 /* we use the Multiple Sessions/Connections OCI paradigm for this server */ 553 result = OCIHandleAlloc ((dvoid *) cdata->henv, 554 (dvoid **) & cdata->hserver, 555 (ub4) OCI_HTYPE_SERVER, 556 (size_t) 0, 557 (dvoid **) 0); 558 if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ENV, 559 _("Could not allocate the Oracle server handle"))) { 560 OCIHandleFree ((dvoid *) cdata->herr, OCI_HTYPE_ERROR); 561 OCIHandleFree ((dvoid *) cdata->hservice, OCI_HTYPE_SVCCTX); 562 gda_oracle_free_cnc_data (cdata); 563 return FALSE; 564 } 565 566 /* create the session handle */ 567 result = OCIHandleAlloc ((dvoid *) cdata->henv, 568 (dvoid **) &cdata->hsession, 569 (ub4) OCI_HTYPE_SESSION, 570 (size_t) 0, 571 (dvoid **) 0); 572 if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ENV, 573 _("Could not allocate the Oracle session handle"))) { 574 OCIHandleFree ((dvoid *) cdata->hserver, OCI_HTYPE_SERVER); 575 OCIHandleFree ((dvoid *) cdata->herr, OCI_HTYPE_ERROR); 576 OCIHandleFree ((dvoid *) cdata->hservice, OCI_HTYPE_SVCCTX); 577 gda_oracle_free_cnc_data (cdata); 578 return FALSE; 579 } 580 581 /* attach to Oracle server */ 582 result = OCIServerAttach (cdata->hserver, 583 cdata->herr, 584 (text *) (tnsname ? tnsname : easy), 585 (ub4) strlen (tnsname ? tnsname : easy), 586 OCI_DEFAULT); 587 g_free (easy); 588 589 if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR, 590 _("Could not attach to the Oracle server"))) { 591 OCIHandleFree ((dvoid *) cdata->hsession, OCI_HTYPE_SESSION); 592 OCIHandleFree ((dvoid *) cdata->hserver, OCI_HTYPE_SERVER); 593 OCIHandleFree ((dvoid *) cdata->herr, OCI_HTYPE_ERROR); 594 OCIHandleFree ((dvoid *) cdata->hservice, OCI_HTYPE_SVCCTX); 595 gda_oracle_free_cnc_data (cdata); 596 return FALSE; 597 } 598 599 /* set the server attribute in the service context */ 600 result = OCIAttrSet ((dvoid *) cdata->hservice, 601 (ub4) OCI_HTYPE_SVCCTX, 602 (dvoid *) cdata->hserver, 603 (ub4) 0, 604 (ub4) OCI_ATTR_SERVER, 605 cdata->herr); 606 if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR, 607 _("Could not set the Oracle server attribute in the service context"))) { 608 OCIHandleFree ((dvoid *) cdata->hsession, OCI_HTYPE_SESSION); 609 OCIHandleFree ((dvoid *) cdata->hserver, OCI_HTYPE_SERVER); 610 OCIHandleFree ((dvoid *) cdata->herr, OCI_HTYPE_ERROR); 611 OCIHandleFree ((dvoid *) cdata->hservice, OCI_HTYPE_SVCCTX); 612 gda_oracle_free_cnc_data (cdata); 613 return FALSE; 614 } 615 616 /* set the username attribute */ 617 result = OCIAttrSet ((dvoid *) cdata->hsession, 618 (ub4) OCI_HTYPE_SESSION, 619 (dvoid *) username, 620 (ub4) strlen (username), 621 (ub4) OCI_ATTR_USERNAME, 622 cdata->herr); 623 if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR, 624 _("Could not set the Oracle username attribute"))) { 625 OCIHandleFree ((dvoid *) cdata->hsession, OCI_HTYPE_SESSION); 626 OCIHandleFree ((dvoid *) cdata->hserver, OCI_HTYPE_SERVER); 627 OCIHandleFree ((dvoid *) cdata->herr, OCI_HTYPE_ERROR); 628 OCIHandleFree ((dvoid *) cdata->hservice, OCI_HTYPE_SVCCTX); 629 gda_oracle_free_cnc_data (cdata); 630 return FALSE; 631 } 632 633 /* set the password attribute */ 634 if (password) { 635 result = OCIAttrSet ((dvoid *) cdata->hsession, 636 (ub4) OCI_HTYPE_SESSION, 637 (dvoid *) password, 638 (ub4) strlen (password), 639 (ub4) OCI_ATTR_PASSWORD, 640 cdata->herr); 641 if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR, 642 _("Could not set the Oracle password attribute"))) { 643 OCIHandleFree ((dvoid *) cdata->hsession, OCI_HTYPE_SESSION); 644 OCIHandleFree ((dvoid *) cdata->hserver, OCI_HTYPE_SERVER); 645 OCIHandleFree ((dvoid *) cdata->herr, OCI_HTYPE_ERROR); 646 OCIHandleFree ((dvoid *) cdata->hservice, OCI_HTYPE_SVCCTX); 647 gda_oracle_free_cnc_data (cdata); 648 return FALSE; 649 } 650 } 651 652 /* begin the session */ 653 result = OCISessionBegin (cdata->hservice, 654 cdata->herr, 655 cdata->hsession, 656 (ub4) OCI_CRED_RDBMS, 657 (ub4) OCI_STMT_CACHE); 658 if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR, 659 _("Could not begin the Oracle session"))) { 660 OCIServerDetach (cdata->hserver, cdata->herr, OCI_DEFAULT); 661 OCIHandleFree ((dvoid *) cdata->hsession, OCI_HTYPE_SESSION); 662 OCIHandleFree ((dvoid *) cdata->hserver, OCI_HTYPE_SERVER); 663 OCIHandleFree ((dvoid *) cdata->herr, OCI_HTYPE_ERROR); 664 OCIHandleFree ((dvoid *) cdata->hservice, OCI_HTYPE_SVCCTX); 665 gda_oracle_free_cnc_data (cdata); 666 cdata->hsession = NULL; 667 return FALSE; 668 } 669 670 /* set the session attribute in the service context */ 671 result = OCIAttrSet ((dvoid *) cdata->hservice, 672 (ub4) OCI_HTYPE_SVCCTX, 673 (dvoid *) cdata->hsession, 674 (ub4) 0, 675 (ub4) OCI_ATTR_SESSION, 676 cdata->herr); 677 if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR, 678 _("Could not set the Oracle session attribute in the service context"))) { 679 OCIServerDetach (cdata->hserver, cdata->herr, OCI_DEFAULT); 680 OCIHandleFree ((dvoid *) cdata->hsession, OCI_HTYPE_SESSION); 681 OCIHandleFree ((dvoid *) cdata->hserver, OCI_HTYPE_SERVER); 682 OCIHandleFree ((dvoid *) cdata->herr, OCI_HTYPE_ERROR); 683 OCIHandleFree ((dvoid *) cdata->hservice, OCI_HTYPE_SVCCTX); 684 gda_oracle_free_cnc_data (cdata); 685 return FALSE; 686 } 687 688 /* Create a new instance of the provider specific data associated to a connection (OracleConnectionData), 689 * and set its contents */ 690 if (schema) 691 cdata->schema = g_ascii_strup (schema, -1); 692 else 693 cdata->schema = g_ascii_strup (username, -1); 694 695 gda_connection_internal_set_provider_data (cnc, cdata, (GDestroyNotify) gda_oracle_free_cnc_data); 696 697 /* get version */ 698 gchar version [512]; 699 cdata->version = NULL; 700 cdata->major_version = 8; 701 cdata->minor_version = 0; 702 result = OCIServerVersion (cdata->hservice, cdata->herr, (text*) version, 511, OCI_HTYPE_SVCCTX); 703 if ((result == OCI_SUCCESS) || (result = OCI_SUCCESS_WITH_INFO)) { 704 cdata->version = g_strdup (version); 705 gchar *tmp, *ptr; 706 tmp = g_ascii_strdown (version, -1); 707 ptr = strstr (tmp, "release"); 708 if (ptr) { 709 for (ptr += 7; *ptr; ptr++) { 710 if (! g_ascii_isspace (*ptr)) 711 break; 712 } 713 if (g_ascii_isdigit (*ptr)) { 714 cdata->major_version = *ptr - '0'; 715 ptr++; 716 if (*ptr) { 717 ptr++; 718 if (g_ascii_isdigit (*ptr)) 719 cdata->minor_version = *ptr - '0'; 720 } 721 } 722 } 723 g_free (tmp); 724 } 725 726 /* Optionnally set some attributes for the newly opened connection (encoding to UTF-8 for example )*/ 727 if (! execute_raw_command (cnc, "ALTER SESSION SET NLS_DATE_FORMAT = 'MM/DD/YYYY'") || 728 ! execute_raw_command (cnc, "ALTER SESSION SET NLS_NUMERIC_CHARACTERS = \". \"") || 729 (schema && ! execute_raw_command (cnc, g_strdup_printf ("ALTER SESSION SET CURRENT_SCHEMA = \"%s\"", schema)))) { 730 gda_connection_internal_set_provider_data (cnc, NULL, NULL); 731 gda_oracle_free_cnc_data (cdata); 732 return FALSE; 733 } 734 735 return TRUE; 736 } 737 738 739 /* 740 * Close connection request 741 * 742 * In this function, the following _must_ be done: 743 * - Actually close the connection to the database using @cnc's associated OracleConnectionData structure 744 * - Free the OracleConnectionData structure and its contents 745 * 746 * Returns: TRUE if no error occurred, or FALSE otherwise (and an ERROR connection event must be added to @cnc) 747 */ 748 static gboolean 749 gda_oracle_provider_close_connection (GdaServerProvider *provider, GdaConnection *cnc) 750 { 751 OracleConnectionData *cdata; 752 753 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 754 g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE); 755 756 /* Close the connection using the C API */ 757 cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc); 758 if (!cdata) 759 return FALSE; 760 761 /* end the session */ 762 int result; 763 if ((result = OCISessionEnd (cdata->hservice, 764 cdata->herr, 765 cdata->hsession, 766 OCI_DEFAULT))) { 767 gda_connection_add_event (cnc, 768 _gda_oracle_make_error (cnc, cdata->herr, OCI_HTYPE_ERROR, __FILE__, __LINE__)); 769 return FALSE; 770 } 771 772 /* Free the OracleConnectionData structure and its contents*/ 773 gda_oracle_free_cnc_data (cdata); 774 gda_connection_internal_set_provider_data (cnc, NULL, NULL); 775 776 return TRUE; 777 } 778 779 /* 780 * Server version request 781 * 782 * Returns the server version as a string, which should be stored in @cnc's associated OracleConnectionData structure 783 */ 784 static const gchar * 785 gda_oracle_provider_get_server_version (GdaServerProvider *provider, GdaConnection *cnc) 786 { 787 OracleConnectionData *cdata; 788 789 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 790 g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL); 791 792 cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc); 793 if (!cdata) 794 return NULL; 795 796 return cdata->version; 797 } 798 799 /* 800 * Get database request 801 * 802 * Returns the database name as a string, which should be stored in @cnc's associated OracleConnectionData structure 803 */ 804 static const gchar * 805 gda_oracle_provider_get_database (GdaServerProvider *provider, GdaConnection *cnc) 806 { 807 OracleConnectionData *cdata; 808 809 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 810 g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL); 811 812 cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc); 813 if (!cdata) 814 return NULL; 815 TO_IMPLEMENT; 816 return NULL; 817 } 818 819 /* 820 * Support operation request 821 * 822 * Tells what the implemented server operations are. To add support for an operation, the following steps are required: 823 * - create a oracle_specs_....xml.in file describing the required and optional parameters for the operation 824 * - add it to the Makefile.am 825 * - make this method return TRUE for the operation type 826 * - implement the gda_oracle_provider_render_operation() and gda_oracle_provider_perform_operation() methods 827 * 828 * In this example, the GDA_SERVER_OPERATION_CREATE_TABLE is implemented 829 */ 830 static gboolean 831 gda_oracle_provider_supports_operation (GdaServerProvider *provider, GdaConnection *cnc, 832 GdaServerOperationType type, G_GNUC_UNUSED GdaSet *options) 833 { 834 if (cnc) { 835 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 836 g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE); 837 } 838 839 switch (type) { 840 case GDA_SERVER_OPERATION_CREATE_DB: 841 case GDA_SERVER_OPERATION_DROP_DB: 842 return FALSE; 843 844 case GDA_SERVER_OPERATION_CREATE_TABLE: 845 return TRUE; 846 case GDA_SERVER_OPERATION_DROP_TABLE: 847 case GDA_SERVER_OPERATION_RENAME_TABLE: 848 849 case GDA_SERVER_OPERATION_ADD_COLUMN: 850 851 case GDA_SERVER_OPERATION_CREATE_INDEX: 852 case GDA_SERVER_OPERATION_DROP_INDEX: 853 854 case GDA_SERVER_OPERATION_CREATE_VIEW: 855 case GDA_SERVER_OPERATION_DROP_VIEW: 856 default: 857 return FALSE; 858 } 859 } 860 861 /* 862 * Create operation request 863 * 864 * Creates a #GdaServerOperation. The following code is generic and should only be changed 865 * if some further initialization is required, or if operation's contents is dependent on @cnc 866 */ 867 static GdaServerOperation * 868 gda_oracle_provider_create_operation (GdaServerProvider *provider, GdaConnection *cnc, 869 GdaServerOperationType type, G_GNUC_UNUSED GdaSet *options, GError **error) 870 { 871 gchar *file; 872 GdaServerOperation *op; 873 gchar *str; 874 gchar *dir; 875 876 if (cnc) { 877 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 878 g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE); 879 } 880 881 file = g_utf8_strdown (gda_server_operation_op_type_to_string (type), -1); 882 str = g_strdup_printf ("oracle_specs_%s.xml", file); 883 g_free (file); 884 885 dir = gda_gbr_get_file_path (GDA_DATA_DIR, LIBGDA_ABI_NAME, NULL); 886 file = gda_server_provider_find_file (provider, dir, str); 887 g_free (dir); 888 889 if (! file) { 890 g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_FILE_NOT_FOUND_ERROR, 891 _("Missing spec. file '%s'"), str); 892 g_free (str); 893 return NULL; 894 } 895 g_free (str); 896 897 op = gda_server_operation_new (type, file); 898 g_free (file); 899 900 return op; 901 } 902 903 /* 904 * Render operation request 905 */ 906 static gchar * 907 gda_oracle_provider_render_operation (GdaServerProvider *provider, GdaConnection *cnc, 908 GdaServerOperation *op, GError **error) 909 { 910 gchar *sql = NULL; 911 gchar *file; 912 gchar *str; 913 gchar *dir; 914 915 if (cnc) { 916 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 917 g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE); 918 } 919 920 /* test @op's validity */ 921 file = g_utf8_strdown (gda_server_operation_op_type_to_string (gda_server_operation_get_op_type (op)), -1); 922 str = g_strdup_printf ("oracle_specs_%s.xml", file); 923 g_free (file); 924 925 dir = gda_gbr_get_file_path (GDA_DATA_DIR, LIBGDA_ABI_NAME, NULL); 926 file = gda_server_provider_find_file (provider, dir, str); 927 g_free (dir); 928 929 if (! file) { 930 g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_FILE_NOT_FOUND_ERROR, 931 _("Missing spec. file '%s'"), str); 932 g_free (str); 933 return NULL; 934 } 935 g_free (str); 936 if (!gda_server_operation_is_valid (op, file, error)) { 937 g_free (file); 938 return NULL; 939 } 940 g_free (file); 941 942 /* actual rendering */ 943 switch (gda_server_operation_get_op_type (op)) { 944 case GDA_SERVER_OPERATION_CREATE_DB: 945 case GDA_SERVER_OPERATION_DROP_DB: 946 sql = NULL; 947 break; 948 case GDA_SERVER_OPERATION_CREATE_TABLE: 949 sql = gda_oracle_render_CREATE_TABLE (provider, cnc, op, error); 950 break; 951 case GDA_SERVER_OPERATION_DROP_TABLE: 952 case GDA_SERVER_OPERATION_RENAME_TABLE: 953 case GDA_SERVER_OPERATION_ADD_COLUMN: 954 case GDA_SERVER_OPERATION_CREATE_INDEX: 955 case GDA_SERVER_OPERATION_DROP_INDEX: 956 case GDA_SERVER_OPERATION_CREATE_VIEW: 957 case GDA_SERVER_OPERATION_DROP_VIEW: 958 sql = NULL; 959 break; 960 default: 961 g_assert_not_reached (); 962 } 963 return sql; 964 } 965 966 /* 967 * Perform operation request 968 */ 969 static gboolean 970 gda_oracle_provider_perform_operation (GdaServerProvider *provider, GdaConnection *cnc, 971 GdaServerOperation *op, G_GNUC_UNUSED guint *task_id, 972 GdaServerProviderAsyncCallback async_cb, G_GNUC_UNUSED gpointer cb_data, 973 GError **error) 974 { 975 GdaServerOperationType optype; 976 977 /* If asynchronous connection opening is not supported, then exit now */ 978 if (async_cb) { 979 g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_METHOD_NON_IMPLEMENTED_ERROR, 980 "%s", _("Provider does not support asynchronous server operation")); 981 return FALSE; 982 } 983 984 if (cnc) { 985 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 986 g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE); 987 } 988 optype = gda_server_operation_get_op_type (op); 989 switch (optype) { 990 case GDA_SERVER_OPERATION_CREATE_DB: 991 case GDA_SERVER_OPERATION_DROP_DB: 992 default: 993 /* use the SQL from the provider to perform the action */ 994 return gda_server_provider_perform_operation_default (provider, cnc, op, error); 995 } 996 } 997 998 /* 999 * Begin transaction request 1000 */ 1001 static gboolean 1002 gda_oracle_provider_begin_transaction (GdaServerProvider *provider, GdaConnection *cnc, 1003 const gchar *name, GdaTransactionIsolation level, 1004 GError **error) 1005 { 1006 OracleConnectionData *cdata; 1007 1008 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 1009 g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE); 1010 1011 cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error); 1012 if (!cdata) 1013 return FALSE; 1014 1015 TO_IMPLEMENT; 1016 1017 cdata->autocommit = FALSE; 1018 return FALSE; 1019 } 1020 1021 /* 1022 * Commit transaction request 1023 */ 1024 static gboolean 1025 gda_oracle_provider_commit_transaction (GdaServerProvider *provider, GdaConnection *cnc, 1026 const gchar *name, GError **error) 1027 { 1028 OracleConnectionData *cdata; 1029 1030 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 1031 g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE); 1032 1033 cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error); 1034 if (!cdata) 1035 return FALSE; 1036 1037 TO_IMPLEMENT; 1038 1039 cdata->autocommit = TRUE; 1040 return FALSE; 1041 } 1042 1043 /* 1044 * Rollback transaction request 1045 */ 1046 static gboolean 1047 gda_oracle_provider_rollback_transaction (GdaServerProvider *provider, GdaConnection *cnc, 1048 const gchar *name, GError **error) 1049 { 1050 OracleConnectionData *cdata; 1051 1052 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 1053 g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE); 1054 1055 cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error); 1056 if (!cdata) 1057 return FALSE; 1058 1059 TO_IMPLEMENT; 1060 1061 cdata->autocommit = TRUE; 1062 return FALSE; 1063 } 1064 1065 /* 1066 * Add savepoint request 1067 */ 1068 static gboolean 1069 gda_oracle_provider_add_savepoint (GdaServerProvider *provider, GdaConnection *cnc, 1070 const gchar *name, GError **error) 1071 { 1072 OracleConnectionData *cdata; 1073 1074 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 1075 g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE); 1076 1077 cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error); 1078 if (!cdata) 1079 return FALSE; 1080 1081 TO_IMPLEMENT; 1082 1083 return FALSE; 1084 } 1085 1086 /* 1087 * Rollback savepoint request 1088 */ 1089 static gboolean 1090 gda_oracle_provider_rollback_savepoint (GdaServerProvider *provider, GdaConnection *cnc, 1091 const gchar *name, GError **error) 1092 { 1093 OracleConnectionData *cdata; 1094 1095 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 1096 g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE); 1097 1098 cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error); 1099 if (!cdata) 1100 return FALSE; 1101 1102 TO_IMPLEMENT; 1103 1104 return FALSE; 1105 } 1106 1107 /* 1108 * Delete savepoint request 1109 */ 1110 static gboolean 1111 gda_oracle_provider_delete_savepoint (GdaServerProvider *provider, GdaConnection *cnc, 1112 const gchar *name, GError **error) 1113 { 1114 OracleConnectionData *cdata; 1115 1116 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 1117 g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE); 1118 1119 cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error); 1120 if (!cdata) 1121 return FALSE; 1122 1123 TO_IMPLEMENT; 1124 1125 return FALSE; 1126 } 1127 1128 /* 1129 * Feature support request 1130 */ 1131 static gboolean 1132 gda_oracle_provider_supports_feature (GdaServerProvider *provider, GdaConnection *cnc, GdaConnectionFeature feature) 1133 { 1134 if (cnc) { 1135 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 1136 g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE); 1137 } 1138 1139 switch (feature) { 1140 case GDA_CONNECTION_FEATURE_SQL : 1141 return TRUE; 1142 default: 1143 return FALSE; 1144 } 1145 } 1146 1147 /* 1148 * Get data handler request 1149 * 1150 * This method allows one to obtain a pointer to a #GdaDataHandler object specific to @type or @dbms_type (@dbms_type 1151 * must be considered only if @type is not a valid GType). 1152 * 1153 * A data handler allows one to convert a value between its different representations which are a human readable string, 1154 * an SQL representation and a GValue. 1155 * 1156 * The recommended method is to create GdaDataHandler objects only when they are needed and to keep a reference to them 1157 * for further usage, using the gda_server_provider_handler_declare() method. 1158 * 1159 * The implementation shown here does not define any specific data handler, but there should be some for at least 1160 * binary and time related types. 1161 */ 1162 static GdaDataHandler * 1163 gda_oracle_provider_get_data_handler (GdaServerProvider *provider, GdaConnection *cnc, 1164 GType type, const gchar *dbms_type) 1165 { 1166 GdaDataHandler *dh; 1167 if (cnc) { 1168 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 1169 g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE); 1170 } 1171 1172 if (type == G_TYPE_INVALID) { 1173 TO_IMPLEMENT; /* use @dbms_type */ 1174 dh = NULL; 1175 } 1176 else if ((type == GDA_TYPE_BINARY) || 1177 (type == GDA_TYPE_BLOB)) { 1178 TO_IMPLEMENT; /* define data handlers for these types */ 1179 dh = NULL; 1180 } 1181 else if ((type == GDA_TYPE_TIME) || 1182 (type == GDA_TYPE_TIMESTAMP) || 1183 (type == G_TYPE_DATE)) { 1184 TO_IMPLEMENT; /* define data handlers for these types */ 1185 dh = NULL; 1186 } 1187 else 1188 dh = gda_server_provider_handler_use_default (provider, type); 1189 1190 return dh; 1191 } 1192 1193 /* 1194 * Get default DBMS type request 1195 * 1196 * This method returns the "preferred" DBMS type for GType 1197 */ 1198 static const gchar* 1199 gda_oracle_provider_get_default_dbms_type (GdaServerProvider *provider, GdaConnection *cnc, GType type) 1200 { 1201 if (cnc) { 1202 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 1203 g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL); 1204 } 1205 1206 TO_IMPLEMENT; 1207 1208 if ((type == G_TYPE_INT64) || 1209 (type == G_TYPE_INT) || 1210 (type == GDA_TYPE_SHORT) || 1211 (type == GDA_TYPE_USHORT) || 1212 (type == G_TYPE_CHAR) || 1213 (type == G_TYPE_UCHAR) || 1214 (type == G_TYPE_ULONG) || 1215 (type == G_TYPE_UINT) || 1216 (type == G_TYPE_UINT64)) 1217 return "NUMBER"; 1218 1219 if ((type == GDA_TYPE_BINARY) || 1220 (type == GDA_TYPE_BLOB)) 1221 return "BLOB"; 1222 1223 if (type == G_TYPE_BOOLEAN) 1224 return "BOOLEAN"; 1225 1226 if ((type == G_TYPE_DATE) || 1227 (type == GDA_TYPE_GEOMETRIC_POINT) || 1228 (type == G_TYPE_OBJECT) || 1229 (type == G_TYPE_STRING) || 1230 (type == GDA_TYPE_TIME) || 1231 (type == GDA_TYPE_TIMESTAMP) || 1232 (type == G_TYPE_GTYPE)) 1233 return "VARCHAR2"; 1234 1235 if ((type == G_TYPE_DOUBLE) || 1236 (type == GDA_TYPE_NUMERIC) || 1237 (type == G_TYPE_FLOAT)) 1238 return "FLOAT"; 1239 1240 if (type == GDA_TYPE_TIME) 1241 return "TIME"; 1242 if (type == GDA_TYPE_TIMESTAMP) 1243 return "TIMESTAMP"; 1244 if (type == G_TYPE_DATE) 1245 return "DATE"; 1246 1247 if ((type == GDA_TYPE_NULL) || 1248 (type == G_TYPE_GTYPE)) 1249 return NULL; 1250 1251 return "VARCHAR2"; 1252 } 1253 1254 /* 1255 * Create parser request 1256 * 1257 * This method is responsible for creating a #GdaSqlParser object specific to the SQL dialect used 1258 * by the database. See the PostgreSQL provider implementation for an example. 1259 */ 1260 static GdaSqlParser * 1261 gda_oracle_provider_create_parser (GdaServerProvider *provider, GdaConnection *cnc) 1262 { 1263 return (GdaSqlParser*) g_object_new (GDA_TYPE_ORACLE_PARSER, "tokenizer-flavour", 1264 GDA_SQL_PARSER_FLAVOUR_ORACLE, NULL); 1265 } 1266 1267 /* 1268 * GdaStatement to SQL request 1269 * 1270 * This method renders a #GdaStatement into its SQL representation. 1271 * 1272 * The implementation show here simply calls gda_statement_to_sql_extended() but the rendering 1273 * can be specialized to the database's SQL dialect, see the implementation of gda_statement_to_sql_extended() 1274 * and SQLite's specialized rendering for more details 1275 */ 1276 static gchar *oracle_render_select (GdaSqlStatementSelect *stmt, GdaSqlRenderingContext *context, GError **error); 1277 static gchar *oracle_render_select_target (GdaSqlSelectTarget *target, GdaSqlRenderingContext *context, GError **error); 1278 static gchar *oracle_render_expr (GdaSqlExpr *expr, GdaSqlRenderingContext *context, 1279 gboolean *is_default, gboolean *is_null, 1280 GError **error); 1281 1282 static gchar * 1283 gda_oracle_provider_statement_to_sql (GdaServerProvider *provider, GdaConnection *cnc, 1284 GdaStatement *stmt, GdaSet *params, GdaStatementSqlFlag flags, 1285 GSList **params_used, GError **error) 1286 { 1287 gchar *str; 1288 GdaSqlRenderingContext context; 1289 1290 g_return_val_if_fail (GDA_IS_STATEMENT (stmt), NULL); 1291 if (cnc) { 1292 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 1293 g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL); 1294 } 1295 1296 memset (&context, 0, sizeof (context)); 1297 context.provider = provider; 1298 context.cnc = cnc; 1299 context.params = params; 1300 context.flags = flags; 1301 context.render_select = (GdaSqlRenderingFunc) oracle_render_select; 1302 context.render_select_target = (GdaSqlRenderingFunc) oracle_render_select_target; 1303 context.render_expr = oracle_render_expr; /* render "FALSE" as 0 and TRUE as 1 */ 1304 1305 str = gda_statement_to_sql_real (stmt, &context, error); 1306 1307 if (str) { 1308 if (params_used) 1309 *params_used = context.params_used; 1310 else 1311 g_slist_free (context.params_used); 1312 } 1313 else { 1314 if (params_used) 1315 *params_used = NULL; 1316 g_slist_free (context.params_used); 1317 } 1318 return str; 1319 } 1320 1321 /* the difference from the common implementation is to avoid rendering the "AS" in target alias */ 1322 static gchar * 1323 oracle_render_select_target (GdaSqlSelectTarget *target, GdaSqlRenderingContext *context, GError **error) 1324 { 1325 GString *string; 1326 gchar *str; 1327 1328 g_return_val_if_fail (target, NULL); 1329 g_return_val_if_fail (GDA_SQL_ANY_PART (target)->type == GDA_SQL_ANY_SQL_SELECT_TARGET, NULL); 1330 1331 /* can't have: target->expr == NULL */ 1332 if (!gda_sql_any_part_check_structure (GDA_SQL_ANY_PART (target), error)) return NULL; 1333 1334 if (! target->expr->value || (G_VALUE_TYPE (target->expr->value) != G_TYPE_STRING)) { 1335 str = context->render_expr (target->expr, context, NULL, NULL, error); 1336 if (!str) 1337 return NULL; 1338 string = g_string_new (str); 1339 g_free (str); 1340 } 1341 else { 1342 gboolean tmp; 1343 tmp = target->expr->value_is_ident; 1344 target->expr->value_is_ident = TRUE; 1345 str = context->render_expr (target->expr, context, NULL, NULL, error); 1346 target->expr->value_is_ident = tmp; 1347 string = g_string_new (str); 1348 g_free (str); 1349 } 1350 1351 if (target->as) { 1352 g_string_append_c (string, ' '); 1353 g_string_append (string, target->as); 1354 } 1355 1356 str = string->str; 1357 g_string_free (string, FALSE); 1358 return str; 1359 } 1360 1361 static gchar * 1362 oracle_render_select (GdaSqlStatementSelect *stmt, GdaSqlRenderingContext *context, GError **error) 1363 { 1364 GString *string; 1365 gchar *str; 1366 GSList *list; 1367 1368 g_return_val_if_fail (stmt, NULL); 1369 g_return_val_if_fail (GDA_SQL_ANY_PART (stmt)->type == GDA_SQL_ANY_STMT_SELECT, NULL); 1370 1371 string = g_string_new ("SELECT "); 1372 /* distinct */ 1373 if (stmt->distinct) { 1374 g_string_append (string, "DISTINCT "); 1375 if (stmt->distinct_expr) { 1376 str = context->render_expr (stmt->distinct_expr, context, NULL, NULL, error); 1377 if (!str) goto err; 1378 g_string_append (string, "ON "); 1379 g_string_append (string, str); 1380 g_string_append_c (string, ' '); 1381 g_free (str); 1382 } 1383 } 1384 1385 /* selected expressions */ 1386 for (list = stmt->expr_list; list; list = list->next) { 1387 str = context->render_select_field (GDA_SQL_ANY_PART (list->data), context, error); 1388 if (!str) goto err; 1389 if (list != stmt->expr_list) 1390 g_string_append (string, ", "); 1391 g_string_append (string, str); 1392 g_free (str); 1393 } 1394 1395 /* FROM */ 1396 if (stmt->from) { 1397 str = context->render_select_from (GDA_SQL_ANY_PART (stmt->from), context, error); 1398 if (!str) goto err; 1399 g_string_append_c (string, ' '); 1400 g_string_append (string, str); 1401 g_free (str); 1402 } 1403 else { 1404 g_string_append (string, " FROM DUAL"); 1405 } 1406 1407 /* WHERE */ 1408 if (stmt->where_cond) { 1409 g_string_append (string, " WHERE "); 1410 str = context->render_expr (stmt->where_cond, context, NULL, NULL, error); 1411 if (!str) goto err; 1412 g_string_append (string, str); 1413 g_free (str); 1414 } 1415 1416 /* LIMIT */ 1417 if (stmt->limit_count) { 1418 if (stmt->where_cond) 1419 g_string_append (string, " AND"); 1420 else 1421 g_string_append (string, " WHERE"); 1422 1423 if (stmt->limit_offset) { 1424 g_set_error (error, GDA_STATEMENT_ERROR, GDA_STATEMENT_SYNTAX_ERROR, 1425 "%s", _("Oracle does not support the offset with a limit")); 1426 goto err; 1427 } 1428 else { 1429 g_string_append (string, " ROWNUM <= ("); 1430 str = context->render_expr (stmt->limit_count, context, NULL, NULL, error); 1431 if (!str) goto err; 1432 g_string_append (string, str); 1433 g_free (str); 1434 g_string_append_c (string, ')'); 1435 } 1436 } 1437 1438 /* GROUP BY */ 1439 for (list = stmt->group_by; list; list = list->next) { 1440 str = context->render_expr (list->data, context, NULL, NULL, error); 1441 if (!str) goto err; 1442 if (list != stmt->group_by) 1443 g_string_append (string, ", "); 1444 else 1445 g_string_append (string, " GROUP BY "); 1446 g_string_append (string, str); 1447 g_free (str); 1448 } 1449 1450 /* HAVING */ 1451 if (stmt->having_cond) { 1452 g_string_append (string, " HAVING "); 1453 str = context->render_expr (stmt->having_cond, context, NULL, NULL, error); 1454 if (!str) goto err; 1455 g_string_append (string, str); 1456 g_free (str); 1457 } 1458 1459 /* ORDER BY */ 1460 for (list = stmt->order_by; list; list = list->next) { 1461 str = context->render_select_order (GDA_SQL_ANY_PART (list->data), context, error); 1462 if (!str) goto err; 1463 if (list != stmt->order_by) 1464 g_string_append (string, ", "); 1465 else 1466 g_string_append (string, " ORDER BY "); 1467 g_string_append (string, str); 1468 g_free (str); 1469 } 1470 1471 str = string->str; 1472 g_string_free (string, FALSE); 1473 return str; 1474 1475 err: 1476 g_string_free (string, TRUE); 1477 return NULL; 1478 } 1479 1480 /* 1481 * The difference with the default implementation is to render TRUE and FALSE as 0 and 1 1482 */ 1483 static gchar * 1484 oracle_render_expr (GdaSqlExpr *expr, GdaSqlRenderingContext *context, gboolean *is_default, 1485 gboolean *is_null, GError **error) 1486 { 1487 GString *string; 1488 gchar *str = NULL; 1489 1490 g_return_val_if_fail (expr, NULL); 1491 g_return_val_if_fail (GDA_SQL_ANY_PART (expr)->type == GDA_SQL_ANY_EXPR, NULL); 1492 1493 if (is_default) 1494 *is_default = FALSE; 1495 if (is_null) 1496 *is_null = FALSE; 1497 1498 /* can't have: 1499 * - expr->cast_as && expr->param_spec 1500 */ 1501 if (!gda_sql_any_part_check_structure (GDA_SQL_ANY_PART (expr), error)) return NULL; 1502 1503 string = g_string_new (""); 1504 if (expr->param_spec) { 1505 str = context->render_param_spec (expr->param_spec, expr, context, is_default, is_null, error); 1506 if (!str) goto err; 1507 } 1508 else if (expr->value) { 1509 if (G_VALUE_TYPE (expr->value) == G_TYPE_STRING) { 1510 /* specific treatment for strings, see documentation about GdaSqlExpr's value attribute */ 1511 const gchar *vstr; 1512 vstr = g_value_get_string (expr->value); 1513 if (vstr) { 1514 if (expr->value_is_ident) { 1515 gchar **ids_array; 1516 gint i; 1517 GString *string = NULL; 1518 GdaConnectionOptions cncoptions = 0; 1519 if (context->cnc) 1520 g_object_get (G_OBJECT (context->cnc), "options", &cncoptions, NULL); 1521 ids_array = gda_sql_identifier_split (vstr); 1522 if (!ids_array) 1523 str = g_strdup (vstr); 1524 else if (!(ids_array[0])) goto err; 1525 else { 1526 for (i = 0; ids_array[i]; i++) { 1527 gchar *tmp; 1528 if (!string) 1529 string = g_string_new (""); 1530 else 1531 g_string_append_c (string, '.'); 1532 tmp = gda_sql_identifier_quote (ids_array[i], context->cnc, 1533 context->provider, FALSE, 1534 cncoptions & GDA_CONNECTION_OPTIONS_SQL_IDENTIFIERS_CASE_SENSITIVE); 1535 g_string_append (string, tmp); 1536 g_free (tmp); 1537 } 1538 g_strfreev (ids_array); 1539 str = g_string_free (string, FALSE); 1540 } 1541 } 1542 else { 1543 /* we don't have an identifier */ 1544 if (!g_ascii_strcasecmp (vstr, "default")) { 1545 if (is_default) 1546 *is_default = TRUE; 1547 str = g_strdup ("DEFAULT"); 1548 } 1549 else if (!g_ascii_strcasecmp (vstr, "FALSE")) { 1550 g_free (str); 1551 str = g_strdup ("0"); 1552 } 1553 else if (!g_ascii_strcasecmp (vstr, "TRUE")) { 1554 g_free (str); 1555 str = g_strdup ("1"); 1556 } 1557 else 1558 str = g_strdup (vstr); 1559 } 1560 } 1561 else { 1562 str = g_strdup ("NULL"); 1563 if (is_null) 1564 *is_null = TRUE; 1565 } 1566 } 1567 if (!str) { 1568 /* use a GdaDataHandler to render the value as valid SQL */ 1569 GdaDataHandler *dh; 1570 if (context->cnc) { 1571 GdaServerProvider *prov; 1572 prov = gda_connection_get_provider (context->cnc); 1573 dh = gda_server_provider_get_data_handler_g_type (prov, context->cnc, 1574 G_VALUE_TYPE (expr->value)); 1575 if (!dh) goto err; 1576 } 1577 else 1578 dh = gda_data_handler_get_default (G_VALUE_TYPE (expr->value)); 1579 1580 if (dh) 1581 str = gda_data_handler_get_sql_from_value (dh, expr->value); 1582 else 1583 str = gda_value_stringify (expr->value); 1584 if (!str) goto err; 1585 } 1586 } 1587 else if (expr->func) { 1588 str = context->render_function (GDA_SQL_ANY_PART (expr->func), context, error); 1589 if (!str) goto err; 1590 } 1591 else if (expr->cond) { 1592 gchar *tmp; 1593 tmp = context->render_operation (GDA_SQL_ANY_PART (expr->cond), context, error); 1594 if (!tmp) goto err; 1595 str = NULL; 1596 if (GDA_SQL_ANY_PART (expr)->parent) { 1597 if (GDA_SQL_ANY_PART (expr)->parent->type == GDA_SQL_ANY_STMT_SELECT) { 1598 GdaSqlStatementSelect *selst; 1599 selst = (GdaSqlStatementSelect*) (GDA_SQL_ANY_PART (expr)->parent); 1600 if ((expr == selst->where_cond) || 1601 (expr == selst->having_cond)) 1602 str = tmp; 1603 } 1604 else if (GDA_SQL_ANY_PART (expr)->parent->type == GDA_SQL_ANY_STMT_DELETE) { 1605 GdaSqlStatementDelete *delst; 1606 delst = (GdaSqlStatementDelete*) (GDA_SQL_ANY_PART (expr)->parent); 1607 if (expr == delst->cond) 1608 str = tmp; 1609 } 1610 else if (GDA_SQL_ANY_PART (expr)->parent->type == GDA_SQL_ANY_STMT_UPDATE) { 1611 GdaSqlStatementUpdate *updst; 1612 updst = (GdaSqlStatementUpdate*) (GDA_SQL_ANY_PART (expr)->parent); 1613 if (expr == updst->cond) 1614 str = tmp; 1615 } 1616 } 1617 1618 if (!str) { 1619 str = g_strconcat ("(", tmp, ")", NULL); 1620 g_free (tmp); 1621 } 1622 } 1623 else if (expr->select) { 1624 gchar *str1; 1625 if (GDA_SQL_ANY_PART (expr->select)->type == GDA_SQL_ANY_STMT_SELECT) 1626 str1 = context->render_select (GDA_SQL_ANY_PART (expr->select), context, error); 1627 else if (GDA_SQL_ANY_PART (expr->select)->type == GDA_SQL_ANY_STMT_COMPOUND) 1628 str1 = context->render_compound (GDA_SQL_ANY_PART (expr->select), context, error); 1629 else 1630 g_assert_not_reached (); 1631 if (!str1) goto err; 1632 1633 if (! GDA_SQL_ANY_PART (expr)->parent || 1634 (GDA_SQL_ANY_PART (expr)->parent->type != GDA_SQL_ANY_SQL_FUNCTION)) { 1635 str = g_strconcat ("(", str1, ")", NULL); 1636 g_free (str1); 1637 } 1638 else 1639 str = str1; 1640 } 1641 else if (expr->case_s) { 1642 str = context->render_case (GDA_SQL_ANY_PART (expr->case_s), context, error); 1643 if (!str) goto err; 1644 } 1645 else { 1646 if (is_null) 1647 *is_null = TRUE; 1648 str = g_strdup ("NULL"); 1649 } 1650 1651 if (!str) goto err; 1652 1653 if (expr->cast_as) 1654 g_string_append_printf (string, "CAST (%s AS %s)", str, expr->cast_as); 1655 else 1656 g_string_append (string, str); 1657 g_free (str); 1658 1659 str = string->str; 1660 g_string_free (string, FALSE); 1661 return str; 1662 1663 err: 1664 g_string_free (string, TRUE); 1665 return NULL; 1666 } 1667 1668 /* 1669 * Statement prepare request 1670 * 1671 * This methods "converts" @stmt into a prepared statement. A prepared statement is a notion 1672 * specific in its implementation details to the C API used here. If successfull, it must create 1673 * a new #GdaOraclePStmt object and declare it to @cnc. 1674 */ 1675 static gboolean 1676 gda_oracle_provider_statement_prepare (GdaServerProvider *provider, GdaConnection *cnc, 1677 GdaStatement *stmt, GError **error) 1678 { 1679 GdaOraclePStmt *ps; 1680 gboolean retval = FALSE; 1681 OracleConnectionData *cdata; 1682 GdaConnectionEvent *event; 1683 1684 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 1685 g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE); 1686 g_return_val_if_fail (GDA_IS_STATEMENT (stmt), FALSE); 1687 1688 /* fetch prepares stmt if already done */ 1689 ps = (GdaOraclePStmt *) gda_connection_get_prepared_statement (cnc, stmt); 1690 if (ps) 1691 return TRUE; 1692 1693 /* render as SQL understood by the provider */ 1694 GdaSet *params = NULL; 1695 gchar *sql; 1696 GSList *used_params = NULL; 1697 if (! gda_statement_get_parameters (stmt, ¶ms, error)) 1698 return FALSE; 1699 sql = gda_oracle_provider_statement_to_sql (provider, cnc, stmt, params, GDA_STATEMENT_SQL_PARAMS_AS_COLON, 1700 &used_params, error); 1701 if (!sql) 1702 goto out; 1703 1704 /* prepare @stmt using the C API, creates @ps */ 1705 OCIStmt *hstmt; 1706 int result; 1707 1708 cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error); 1709 if (!cdata) 1710 return FALSE; 1711 1712 result = OCIHandleAlloc ((dvoid *) cdata->henv, 1713 (dvoid **) &hstmt, 1714 (ub4) OCI_HTYPE_STMT, 1715 (size_t) 0, 1716 (dvoid **) NULL); 1717 if ((event = gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ENV, 1718 _("Could not allocate the Oracle statement handle")))) { 1719 g_free (sql); 1720 g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_PREPARE_STMT_ERROR, 1721 "%s", gda_connection_event_get_description (event)); 1722 return FALSE; 1723 } 1724 1725 /*g_print ("Really PREPARED: %s\n", sql);*/ 1726 result = OCIStmtPrepare2 (cdata->hservice, 1727 &hstmt, 1728 (dvoid *) cdata->herr, 1729 (text *) sql, 1730 (ub4) strlen (sql), 1731 (text *) sql, 1732 (ub4) strlen (sql), 1733 (ub4) OCI_NTV_SYNTAX, 1734 (ub4) OCI_DEFAULT); 1735 if ((event = gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR, 1736 _("Could not prepare the Oracle statement")))) { 1737 OCIStmtRelease ((dvoid *) hstmt, cdata->herr, NULL, 0, result ? OCI_STRLS_CACHE_DELETE : OCI_DEFAULT); 1738 g_free (sql); 1739 g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_PREPARE_STMT_ERROR, 1740 "%s", gda_connection_event_get_description (event)); 1741 return FALSE; 1742 } 1743 1744 /* make a list of the parameter names used in the statement */ 1745 GSList *param_ids = NULL; 1746 if (used_params) { 1747 GSList *list; 1748 for (list = used_params; list; list = list->next) { 1749 const gchar *cid; 1750 cid = gda_holder_get_id (GDA_HOLDER (list->data)); 1751 if (cid) { 1752 param_ids = g_slist_append (param_ids, g_strdup (cid)); 1753 /*g_print ("PREPARATION: param ID: %s\n", cid);*/ 1754 } 1755 else { 1756 g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_PREPARE_STMT_ERROR, 1757 "%s", _("Unnamed parameter is not allowed in prepared statements")); 1758 g_slist_foreach (param_ids, (GFunc) g_free, NULL); 1759 g_slist_free (param_ids); 1760 goto out; 1761 } 1762 } 1763 } 1764 1765 /* create a prepared statement object */ 1766 ps = gda_oracle_pstmt_new (hstmt); 1767 gda_pstmt_set_gda_statement (_GDA_PSTMT (ps), stmt); 1768 _GDA_PSTMT (ps)->param_ids = param_ids; 1769 _GDA_PSTMT (ps)->sql = sql; 1770 1771 gda_connection_add_prepared_statement (cnc, stmt, (GdaPStmt *) ps); 1772 g_object_unref (ps); 1773 1774 retval = TRUE; 1775 1776 out: 1777 if (used_params) 1778 g_slist_free (used_params); 1779 if (params) 1780 g_object_unref (params); 1781 return retval; 1782 } 1783 1784 static void 1785 clear_ora_values_list (GSList *oravalues_list) 1786 { 1787 if (oravalues_list) { 1788 g_slist_foreach (oravalues_list, (GFunc) _gda_oracle_value_free, NULL); 1789 g_slist_free (oravalues_list); 1790 oravalues_list = NULL; 1791 } 1792 } 1793 1794 /* 1795 * Execute statement request 1796 * 1797 * Executes a statement. This method should do the following: 1798 * - try to prepare the statement if not yet done 1799 * - optionnally reset the prepared statement 1800 * - bind the variables's values (which are in @params) 1801 * - add a connection event to log the execution 1802 * - execute the prepared statement 1803 * 1804 * If @stmt is an INSERT statement and @last_inserted_row is not NULL then additional actions must be taken to return the 1805 * actual inserted row 1806 */ 1807 static GObject * 1808 gda_oracle_provider_statement_execute (GdaServerProvider *provider, GdaConnection *cnc, 1809 GdaStatement *stmt, GdaSet *params, 1810 GdaStatementModelUsage model_usage, 1811 GType *col_types, GdaSet **last_inserted_row, 1812 guint *task_id, 1813 GdaServerProviderExecCallback async_cb, gpointer cb_data, GError **error) 1814 { 1815 GdaOraclePStmt *ps; 1816 OracleConnectionData *cdata; 1817 gboolean allow_noparam; 1818 gboolean empty_rs = FALSE; /* TRUE when @allow_noparam is TRUE and there is a problem with @params 1819 => resulting data model will be empty (0 row) */ 1820 1821 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 1822 g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL); 1823 g_return_val_if_fail (GDA_IS_STATEMENT (stmt), NULL); 1824 1825 /* If asynchronous connection opening is not supported, then exit now */ 1826 if (async_cb) { 1827 g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_METHOD_NON_IMPLEMENTED_ERROR, 1828 "%s", _("Provider does not support asynchronous statement execution")); 1829 return NULL; 1830 } 1831 1832 allow_noparam = (model_usage & GDA_STATEMENT_MODEL_ALLOW_NOPARAM) && 1833 (gda_statement_get_statement_type (stmt) == GDA_SQL_STATEMENT_SELECT); 1834 1835 if (last_inserted_row) 1836 *last_inserted_row = NULL; 1837 1838 /* Get private data */ 1839 cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error); 1840 if (!cdata) 1841 return FALSE; 1842 1843 /* get/create new prepared statement */ 1844 ps = (GdaOraclePStmt *) gda_connection_get_prepared_statement (cnc, stmt); 1845 if (!ps) { 1846 GError *lerror = NULL; 1847 if (!gda_oracle_provider_statement_prepare (provider, cnc, stmt, &lerror)) { 1848 if (lerror && (lerror->domain == GDA_STATEMENT_ERROR) && 1849 (lerror->code == GDA_STATEMENT_SYNTAX_ERROR)) { 1850 g_propagate_error (error, lerror); 1851 return NULL; 1852 } 1853 /* this case can appear for example if some variables are used in places 1854 * where the C API cannot allow them (for example if the variable is the table name 1855 * in a SELECT statement). The action here is to get the actual SQL code for @stmt, 1856 * and use that SQL instead of @stmt to create another GdaOraclePStmt object. 1857 * 1858 * Don't call gda_connection_add_prepared_statement() with this new prepared statement 1859 * as it will be destroyed once used. 1860 */ 1861 1862 TO_IMPLEMENT; 1863 return NULL; 1864 } 1865 else { 1866 ps = (GdaOraclePStmt *) gda_connection_get_prepared_statement (cnc, stmt); 1867 g_object_ref (ps); 1868 } 1869 } 1870 else 1871 g_object_ref (ps); 1872 g_assert (ps); 1873 1874 /* bind statement's parameters */ 1875 GSList *list, *oravalues_list; 1876 GdaConnectionEvent *event = NULL; 1877 int i; 1878 for (i = 1, list = _GDA_PSTMT (ps)->param_ids, oravalues_list = NULL; 1879 list; 1880 list = list->next, i++) { 1881 const gchar *pname = (gchar *) list->data; 1882 gchar *real_pname = NULL; 1883 GdaHolder *h; 1884 GdaOracleValue *ora_value = NULL; 1885 1886 /* find requested parameter */ 1887 if (!params) { 1888 event = gda_connection_point_available_event (cnc, GDA_CONNECTION_EVENT_ERROR); 1889 gda_connection_event_set_description (event, _("Missing parameter(s) to execute query")); 1890 g_set_error (error, GDA_SERVER_PROVIDER_ERROR, 1891 GDA_SERVER_PROVIDER_MISSING_PARAM_ERROR, 1892 "%s", _("Missing parameter(s) to execute query")); 1893 break; 1894 } 1895 1896 h = gda_set_get_holder (params, pname); 1897 if (!h) { 1898 gchar *tmp = gda_alphanum_to_text (g_strdup (pname + 1)); 1899 if (tmp) { 1900 h = gda_set_get_holder (params, tmp); 1901 if (h) 1902 real_pname = tmp; 1903 else 1904 g_free (tmp); 1905 } 1906 } 1907 if (!h) { 1908 if (allow_noparam) { 1909 /* bind param to NULL */ 1910 /* Hint: Indicator Variables, see p. 118 */ 1911 ora_value = g_new0 (GdaOracleValue, 1); 1912 ora_value->indicator = -1; 1913 empty_rs = TRUE; 1914 } 1915 else { 1916 gchar *str; 1917 str = g_strdup_printf (_("Missing parameter '%s' to execute query"), pname); 1918 event = gda_connection_point_available_event (cnc, GDA_CONNECTION_EVENT_ERROR); 1919 gda_connection_event_set_description (event, str); 1920 g_set_error (error, GDA_SERVER_PROVIDER_ERROR, 1921 GDA_SERVER_PROVIDER_MISSING_PARAM_ERROR, "%s", str); 1922 g_free (str); 1923 break; 1924 } 1925 } 1926 else if (!gda_holder_is_valid (h)) { 1927 if (allow_noparam) { 1928 /* bind param to NULL */ 1929 ora_value = g_new0 (GdaOracleValue, 1); 1930 ora_value->indicator = -1; 1931 empty_rs = TRUE; 1932 } 1933 else { 1934 gchar *str; 1935 str = g_strdup_printf (_("Parameter '%s' is invalid"), pname); 1936 event = gda_connection_point_available_event (cnc, GDA_CONNECTION_EVENT_ERROR); 1937 gda_connection_event_set_description (event, str); 1938 g_set_error (error, GDA_SERVER_PROVIDER_ERROR, 1939 GDA_SERVER_PROVIDER_MISSING_PARAM_ERROR, "%s", str); 1940 g_free (str); 1941 break; 1942 } 1943 } 1944 else if (gda_holder_value_is_default (h) && !gda_holder_get_value (h)) { 1945 /* create a new GdaStatement to handle all default values and execute it instead */ 1946 GdaSqlStatement *sqlst; 1947 GError *lerror = NULL; 1948 sqlst = gda_statement_rewrite_for_default_values (stmt, params, FALSE, &lerror); 1949 if (!sqlst) { 1950 event = gda_connection_point_available_event (cnc, 1951 GDA_CONNECTION_EVENT_ERROR); 1952 gda_connection_event_set_description (event, lerror && lerror->message ? 1953 lerror->message : 1954 _("Can't rewrite statement handle default values")); 1955 g_propagate_error (error, lerror); 1956 break; 1957 } 1958 1959 GdaStatement *rstmt; 1960 GObject *res; 1961 rstmt = g_object_new (GDA_TYPE_STATEMENT, "structure", sqlst, NULL); 1962 gda_sql_statement_free (sqlst); 1963 g_object_unref (ps); 1964 res = gda_oracle_provider_statement_execute (provider, cnc, 1965 rstmt, params, 1966 model_usage, 1967 col_types, last_inserted_row, 1968 task_id, 1969 async_cb, cb_data, error); 1970 g_object_unref (rstmt); 1971 return res; 1972 } 1973 1974 /* actual binding using the C API, for parameter at position @i */ 1975 const GValue *value = gda_holder_get_value (h); 1976 if (!ora_value) 1977 ora_value = _gda_value_to_oracle_value (value); 1978 1979 if (!value || gda_value_is_null (value)) { 1980 GdaStatement *rstmt; 1981 if (! gda_rewrite_statement_for_null_parameters (stmt, params, &rstmt, error)) { 1982 OCIBind *bindpp = (OCIBind *) 0; 1983 int result; 1984 result = OCIBindByName ((dvoid *) ps->hstmt, 1985 (OCIBind **) &bindpp, 1986 (OCIError *) cdata->herr, 1987 /* param name */ 1988 (text *) (real_pname ? real_pname : pname), 1989 (sb4) strlen (real_pname ? real_pname : pname), 1990 /* bound value */ 1991 (dvoid *) ora_value->value, 1992 (sb4) ora_value->defined_size, 1993 (ub2) ora_value->sql_type, 1994 (dvoid *) &ora_value->indicator, 1995 (ub2 *) 0, 1996 (ub2) 0, 1997 (ub4) 0, 1998 (ub4 *) 0, 1999 (ub4) OCI_DEFAULT); 2000 2001 oravalues_list = g_slist_prepend (oravalues_list, ora_value); 2002 if ((event = gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR, 2003 _("Could not bind the Oracle statement parameter")))) 2004 break; 2005 } 2006 else if (!rstmt) 2007 return NULL; 2008 else { 2009 /* The strategy here is to execute @rstmt using its prepared 2010 * statement, but with common data from @ps. Beware that 2011 * the @param_ids attribute needs to be retained (i.e. it must not 2012 * be the one copied from @ps) */ 2013 GObject *obj; 2014 GdaOraclePStmt *tps; 2015 GdaPStmt *gtps; 2016 GSList *prep_param_ids, *copied_param_ids; 2017 if (!gda_oracle_provider_statement_prepare (provider, cnc, 2018 rstmt, error)) 2019 return NULL; 2020 tps = (GdaOraclePStmt *) 2021 gda_connection_get_prepared_statement (cnc, rstmt); 2022 gtps = (GdaPStmt *) tps; 2023 2024 /* keep @param_ids to avoid being cleared by gda_pstmt_copy_contents() */ 2025 prep_param_ids = gtps->param_ids; 2026 gtps->param_ids = NULL; 2027 2028 /* actual copy */ 2029 gda_pstmt_copy_contents ((GdaPStmt *) ps, (GdaPStmt *) tps); 2030 2031 /* restore previous @param_ids */ 2032 copied_param_ids = gtps->param_ids; 2033 gtps->param_ids = prep_param_ids; 2034 2035 /* execute */ 2036 obj = gda_oracle_provider_statement_execute (provider, cnc, 2037 rstmt, params, 2038 model_usage, 2039 col_types, 2040 last_inserted_row, 2041 task_id, async_cb, 2042 cb_data, error); 2043 /* clear original @param_ids and restore copied one */ 2044 g_slist_foreach (prep_param_ids, (GFunc) g_free, NULL); 2045 g_slist_free (prep_param_ids); 2046 2047 gtps->param_ids = copied_param_ids; 2048 2049 /*if (GDA_IS_DATA_MODEL (obj)) 2050 gda_data_model_dump ((GdaDataModel*) obj, NULL);*/ 2051 2052 g_object_unref (rstmt); 2053 g_object_unref (ps); 2054 return obj; 2055 } 2056 } 2057 else { 2058 OCIBind *bindpp = (OCIBind *) 0; 2059 int result; 2060 result = OCIBindByName ((dvoid *) ps->hstmt, 2061 (OCIBind **) &bindpp, 2062 (OCIError *) cdata->herr, 2063 /* param name */ 2064 (text *) (real_pname ? real_pname : pname), 2065 (sb4) strlen (real_pname ? real_pname : pname), 2066 /* bound value */ 2067 (dvoid *) ora_value->value, 2068 (sb4) ora_value->defined_size, 2069 (ub2) ora_value->sql_type, 2070 (dvoid *) &ora_value->indicator, 2071 (ub2 *) 0, 2072 (ub2) 0, 2073 (ub4) 0, 2074 (ub4 *) 0, 2075 (ub4) OCI_DEFAULT); 2076 2077 oravalues_list = g_slist_prepend (oravalues_list, ora_value); 2078 if ((event = gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR, 2079 _("Could not bind the Oracle statement parameter")))) 2080 break; 2081 } 2082 } 2083 2084 if (event) { 2085 gda_connection_add_event (cnc, event); 2086 g_object_unref (ps); 2087 clear_ora_values_list (oravalues_list); 2088 return NULL; 2089 } 2090 2091 /* add a connection event for the execution */ 2092 event = gda_connection_point_available_event (cnc, GDA_CONNECTION_EVENT_COMMAND); 2093 gda_connection_event_set_description (event, _GDA_PSTMT (ps)->sql); 2094 gda_connection_add_event (cnc, event); 2095 event = NULL; 2096 2097 /* get statement type */ 2098 ub2 stmt_type = 0; 2099 int result; 2100 result = OCIAttrGet (ps->hstmt, OCI_HTYPE_STMT, 2101 (dvoid *) &stmt_type, NULL, 2102 OCI_ATTR_STMT_TYPE, cdata->herr); 2103 event = gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR, 2104 _("Could not get the Oracle statement type")); 2105 if (event) { 2106 clear_ora_values_list (oravalues_list); 2107 return NULL; 2108 } 2109 2110 if (empty_rs) { 2111 /* There are some missing parameters, so the SQL can't be executed but we still want 2112 * to execute something to get the columns correctly. A possibility is to actually 2113 * execute another SQL which is the code shown here. 2114 * 2115 * To adapt depending on the C API and its features */ 2116 2117 /* HINT: use the OCIStmtExecute()' OCI_DESCRIBE_ONLY flag */ 2118 2119 GdaStatement *estmt; 2120 gchar *esql; 2121 estmt = gda_select_alter_select_for_empty (stmt, error); 2122 if (!estmt) { 2123 g_object_unref (ps); 2124 clear_ora_values_list (oravalues_list); 2125 return NULL; 2126 } 2127 esql = gda_statement_to_sql (estmt, NULL, error); 2128 g_object_unref (estmt); 2129 if (!esql) { 2130 g_object_unref (ps); 2131 clear_ora_values_list (oravalues_list); 2132 return NULL; 2133 } 2134 2135 /* Execute the 'esql' SQL code */ 2136 g_free (esql); 2137 2138 TO_IMPLEMENT; 2139 } 2140 else { 2141 /* Execute the @ps prepared statement */ 2142 result = OCIStmtExecute (cdata->hservice, 2143 ps->hstmt, 2144 cdata->herr, 2145 (ub4) ((stmt_type == OCI_STMT_SELECT) ? 0 : 1), 2146 (ub4) 0, 2147 (CONST OCISnapshot *) NULL, 2148 (OCISnapshot *) NULL, 2149 OCI_DEFAULT); 2150 /* or OCI_STMT_SCROLLABLE_READONLY, not OCI_COMMIT_ON_SUCCESS because transactions are 2151 handled separately */ 2152 2153 event = gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR, 2154 _("Could not execute the Oracle statement")); 2155 } 2156 2157 clear_ora_values_list (oravalues_list); 2158 if (event) { 2159 g_object_unref (ps); 2160 g_set_error (error, GDA_SERVER_PROVIDER_ERROR, 2161 GDA_SERVER_PROVIDER_STATEMENT_EXEC_ERROR, "%s", 2162 gda_connection_event_get_description (event)); 2163 return NULL; 2164 } 2165 2166 /* execute prepared statement using C API depending on its kind */ 2167 if (stmt_type == OCI_STMT_SELECT) { 2168 GdaDataModel *data_model; 2169 GdaDataModelAccessFlags flags; 2170 GList *columns = NULL; 2171 ub4 ncolumns; 2172 ub4 i; 2173 2174 if (model_usage & GDA_STATEMENT_MODEL_RANDOM_ACCESS) 2175 flags = GDA_DATA_MODEL_ACCESS_RANDOM; 2176 else 2177 flags = GDA_DATA_MODEL_ACCESS_CURSOR_FORWARD; 2178 2179 /* get the number of columns in the result set */ 2180 result = OCIAttrGet ((dvoid *) ps->hstmt, 2181 (ub4) OCI_HTYPE_STMT, 2182 (dvoid *) &ncolumns, 2183 (ub4 *) 0, 2184 (ub4) OCI_ATTR_PARAM_COUNT, 2185 cdata->herr); 2186 if ((event = gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR, 2187 _("Could not get the number of columns in the result set")))) { 2188 g_object_unref (ps); 2189 g_set_error (error, GDA_SERVER_PROVIDER_ERROR, 2190 GDA_SERVER_PROVIDER_STATEMENT_EXEC_ERROR, "%s", 2191 gda_connection_event_get_description (event)); 2192 return NULL; 2193 } 2194 2195 for (i = 0; i < ncolumns; i += 1) { 2196 text *dummy = (text *) 0; 2197 ub4 col_name_len; 2198 OCIParam *pard = (OCIParam *) 0; 2199 gchar *name_buffer; 2200 2201 result = OCIParamGet ((dvoid *) ps->hstmt, 2202 OCI_HTYPE_STMT, 2203 cdata->herr, 2204 (dvoid **) &pard, 2205 (ub4) i + 1); 2206 if ((event = gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR, 2207 _("Could not get the parameter descripter in the result set")))) { 2208 g_object_unref (ps); 2209 g_set_error (error, GDA_SERVER_PROVIDER_ERROR, 2210 GDA_SERVER_PROVIDER_STATEMENT_EXEC_ERROR, "%s", 2211 gda_connection_event_get_description (event)); 2212 return NULL; 2213 } 2214 2215 result = OCIAttrGet ((dvoid *) pard, 2216 (ub4) OCI_DTYPE_PARAM, 2217 (dvoid **) &dummy, 2218 (ub4 *) &col_name_len, 2219 (ub4) OCI_ATTR_NAME, 2220 (OCIError *) cdata->herr); 2221 if ((event = gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR, 2222 _("Could not get the column name in the result set")))) { 2223 g_object_unref (ps); 2224 g_set_error (error, GDA_SERVER_PROVIDER_ERROR, 2225 GDA_SERVER_PROVIDER_STATEMENT_EXEC_ERROR, "%s", 2226 gda_connection_event_get_description (event)); 2227 return NULL; 2228 } 2229 2230 name_buffer = g_malloc0 (col_name_len + 1); 2231 memcpy (name_buffer, dummy, col_name_len); 2232 name_buffer[col_name_len] = '\0'; 2233 columns = g_list_append (columns, name_buffer); 2234 } 2235 2236 data_model = gda_oracle_recordset_new (cnc, ps, params, flags, col_types); 2237 if (data_model) 2238 gda_connection_internal_statement_executed (cnc, stmt, params, NULL); /* required: help @cnc keep some stats */ 2239 g_object_unref (ps); 2240 return (GObject*) data_model; 2241 } 2242 else { 2243 GdaSet *set = NULL; 2244 int nrows = -2; /* number of rows non reported */ 2245 2246 result = OCIAttrGet (ps->hstmt, OCI_HTYPE_STMT, 2247 (dvoid *) &nrows, NULL, 2248 OCI_ATTR_ROW_COUNT, cdata->herr); 2249 if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR, 2250 _("Could not get the number of affected rows"))) 2251 nrows = -2; 2252 2253 if (cdata->autocommit) { 2254 result = OCITransCommit (cdata->hservice, cdata->herr, OCI_DEFAULT); 2255 if ((event = gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR, 2256 _("Error auto-commiting transaction")))) { 2257 g_set_error (error, GDA_SERVER_PROVIDER_ERROR, 2258 GDA_SERVER_PROVIDER_STATEMENT_EXEC_ERROR, "%s", 2259 gda_connection_event_get_description (event)); 2260 return NULL; 2261 } 2262 } 2263 2264 set = gda_set_new_inline (1, "IMPACTED_ROWS", G_TYPE_INT, nrows); 2265 2266 if (nrows >= 0) { 2267 gchar *str = NULL; 2268 switch (stmt_type) { 2269 case OCI_STMT_UPDATE: 2270 str = g_strdup_printf ("UPDATE %d", nrows); 2271 break; 2272 case OCI_STMT_DELETE: 2273 str = g_strdup_printf ("DELETE %d", nrows); 2274 break; 2275 case OCI_STMT_INSERT: 2276 str = g_strdup_printf ("INSERT %d", nrows); 2277 break; 2278 default: 2279 break; 2280 } 2281 if (str) { 2282 event = gda_connection_point_available_event (cnc, GDA_CONNECTION_EVENT_NOTICE); 2283 gda_connection_event_set_description (event, str); 2284 g_free (str); 2285 gda_connection_add_event (cnc, event); 2286 } 2287 } 2288 2289 gda_connection_internal_statement_executed (cnc, stmt, params, NULL); /* required: help @cnc keep some stats */ 2290 g_object_unref (ps); 2291 return (GObject*) set; 2292 } 2293 } 2294 2295 /* 2296 * Rewrites a statement in case some parameters in @params are set to DEFAULT, for INSERT or UPDATE statements 2297 * 2298 * Uses the DEFAULT keyword 2299 */ 2300 static GdaSqlStatement * 2301 gda_oracle_statement_rewrite (GdaServerProvider *provider, GdaConnection *cnc, 2302 GdaStatement *stmt, GdaSet *params, GError **error) 2303 { 2304 if (cnc) { 2305 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 2306 g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL); 2307 } 2308 return gda_statement_rewrite_for_default_values (stmt, params, FALSE, error); 2309 } 2310 2311 /* 2312 * starts a distributed transaction: put the XA transaction in the ACTIVE state 2313 */ 2314 static gboolean 2315 gda_oracle_provider_xa_start (GdaServerProvider *provider, GdaConnection *cnc, 2316 const GdaXaTransactionId *xid, GError **error) 2317 { 2318 OracleConnectionData *cdata; 2319 2320 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 2321 g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE); 2322 g_return_val_if_fail (xid, FALSE); 2323 2324 cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error); 2325 if (!cdata) 2326 return FALSE; 2327 2328 TO_IMPLEMENT; 2329 return FALSE; 2330 } 2331 2332 /* 2333 * put the XA transaction in the IDLE state: the connection won't accept any more modifications. 2334 * This state is required by some database providers before actually going to the PREPARED state 2335 */ 2336 static gboolean 2337 gda_oracle_provider_xa_end (GdaServerProvider *provider, GdaConnection *cnc, 2338 const GdaXaTransactionId *xid, GError **error) 2339 { 2340 OracleConnectionData *cdata; 2341 2342 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 2343 g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE); 2344 g_return_val_if_fail (xid, FALSE); 2345 2346 cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error); 2347 if (!cdata) 2348 return FALSE; 2349 2350 TO_IMPLEMENT; 2351 return FALSE; 2352 } 2353 2354 /* 2355 * prepares the distributed transaction: put the XA transaction in the PREPARED state 2356 */ 2357 static gboolean 2358 gda_oracle_provider_xa_prepare (GdaServerProvider *provider, GdaConnection *cnc, 2359 const GdaXaTransactionId *xid, GError **error) 2360 { 2361 OracleConnectionData *cdata; 2362 2363 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 2364 g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE); 2365 g_return_val_if_fail (xid, FALSE); 2366 2367 cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error); 2368 if (!cdata) 2369 return FALSE; 2370 2371 TO_IMPLEMENT; 2372 return FALSE; 2373 } 2374 2375 /* 2376 * commits the distributed transaction: actually write the prepared data to the database and 2377 * terminates the XA transaction 2378 */ 2379 static gboolean 2380 gda_oracle_provider_xa_commit (GdaServerProvider *provider, GdaConnection *cnc, 2381 const GdaXaTransactionId *xid, GError **error) 2382 { 2383 OracleConnectionData *cdata; 2384 2385 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 2386 g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE); 2387 g_return_val_if_fail (xid, FALSE); 2388 2389 cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error); 2390 if (!cdata) 2391 return FALSE; 2392 2393 TO_IMPLEMENT; 2394 return FALSE; 2395 } 2396 2397 /* 2398 * Rolls back an XA transaction, possible only if in the ACTIVE, IDLE or PREPARED state 2399 */ 2400 static gboolean 2401 gda_oracle_provider_xa_rollback (GdaServerProvider *provider, GdaConnection *cnc, 2402 const GdaXaTransactionId *xid, GError **error) 2403 { 2404 OracleConnectionData *cdata; 2405 2406 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 2407 g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE); 2408 g_return_val_if_fail (xid, FALSE); 2409 2410 cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error); 2411 if (!cdata) 2412 return FALSE; 2413 2414 TO_IMPLEMENT; 2415 return FALSE; 2416 } 2417 2418 /* 2419 * Lists all XA transactions that are in the PREPARED state 2420 * 2421 * Returns: a list of GdaXaTransactionId structures, which will be freed by the caller 2422 */ 2423 static GList * 2424 gda_oracle_provider_xa_recover (GdaServerProvider *provider, GdaConnection *cnc, 2425 GError **error) 2426 { 2427 OracleConnectionData *cdata; 2428 2429 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 2430 g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL); 2431 2432 cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error); 2433 if (!cdata) 2434 return NULL; 2435 2436 TO_IMPLEMENT; 2437 return NULL; 2438 } 2439 2440 static gchar * 2441 identifier_add_quotes (const gchar *str) 2442 { 2443 gchar *retval, *rptr; 2444 const gchar *sptr; 2445 gint len; 2446 2447 if (!str) 2448 return NULL; 2449 2450 len = strlen (str); 2451 retval = g_new (gchar, 2*len + 3); 2452 *retval = '"'; 2453 for (rptr = retval+1, sptr = str; *sptr; sptr++, rptr++) { 2454 if (*sptr == '"') { 2455 *rptr = '\\'; 2456 rptr++; 2457 *rptr = *sptr; 2458 } 2459 else 2460 *rptr = *sptr; 2461 } 2462 *rptr = '"'; 2463 rptr++; 2464 *rptr = 0; 2465 return retval; 2466 } 2467 2468 static gboolean 2469 _sql_identifier_needs_quotes (const gchar *str) 2470 { 2471 const gchar *ptr; 2472 2473 g_return_val_if_fail (str, FALSE); 2474 for (ptr = str; *ptr; ptr++) { 2475 /* quote if 1st char is a number */ 2476 if ((*ptr <= '9') && (*ptr >= '0')) { 2477 if (ptr == str) 2478 return TRUE; 2479 continue; 2480 } 2481 if (((*ptr >= 'A') && (*ptr <= 'Z')) || 2482 ((*ptr >= 'a') && (*ptr <= 'z'))) 2483 continue; 2484 2485 if ((*ptr != '$') && (*ptr != '_') && (*ptr != '#')) 2486 return TRUE; 2487 } 2488 return FALSE; 2489 } 2490 2491 /* Returns: @str */ 2492 static gchar * 2493 ora_remove_quotes (gchar *str) 2494 { 2495 glong total; 2496 gchar *ptr; 2497 glong offset = 0; 2498 char delim; 2499 2500 if (!str) 2501 return NULL; 2502 delim = *str; 2503 if ((delim != '\'') && (delim != '"')) 2504 return str; 2505 2506 2507 total = strlen (str); 2508 if (str[total-1] == delim) { 2509 /* string is correctly terminated */ 2510 memmove (str, str+1, total-2); 2511 total -=2; 2512 } 2513 else { 2514 /* string is _not_ correctly terminated */ 2515 memmove (str, str+1, total-1); 2516 total -=1; 2517 } 2518 str[total] = 0; 2519 2520 ptr = (gchar *) str; 2521 while (offset < total) { 2522 /* we accept the "''" as a synonym of "\'" */ 2523 if (*ptr == delim) { 2524 if (*(ptr+1) == delim) { 2525 memmove (ptr+1, ptr+2, total - offset); 2526 offset += 2; 2527 } 2528 else { 2529 *str = 0; 2530 return str; 2531 } 2532 } 2533 if (*ptr == '\\') { 2534 if (*(ptr+1) == '\\') { 2535 memmove (ptr+1, ptr+2, total - offset); 2536 offset += 2; 2537 } 2538 else { 2539 if (*(ptr+1) == delim) { 2540 *ptr = delim; 2541 memmove (ptr+1, ptr+2, total - offset); 2542 offset += 2; 2543 } 2544 else { 2545 *str = 0; 2546 return str; 2547 } 2548 } 2549 } 2550 else 2551 offset ++; 2552 2553 ptr++; 2554 } 2555 2556 return str; 2557 } 2558 2559 static gchar * 2560 gda_oracle_identifier_quote (GdaServerProvider *provider, GdaConnection *cnc, 2561 const gchar *id, 2562 gboolean for_meta_store, gboolean force_quotes) 2563 { 2564 GdaSqlReservedKeywordsFunc kwfunc; 2565 OracleConnectionData *cdata = NULL; 2566 2567 if (cnc) 2568 cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc); 2569 2570 kwfunc = _gda_oracle_get_reserved_keyword_func (cdata); 2571 2572 if (for_meta_store) { 2573 gchar *tmp, *ptr; 2574 tmp = ora_remove_quotes (g_strdup (id)); 2575 if (kwfunc (tmp)) { 2576 ptr = gda_sql_identifier_force_quotes (tmp); 2577 g_free (tmp); 2578 return ptr; 2579 } 2580 else if (force_quotes) { 2581 /* quote if non UC characters or digits at the 1st char or non allowed characters */ 2582 for (ptr = tmp; *ptr; ptr++) { 2583 if (((*ptr >= 'A') && (*ptr <= 'Z')) || 2584 ((*ptr >= '0') && (*ptr <= '9') && (ptr != tmp)) || 2585 (*ptr == '_')) 2586 continue; 2587 else { 2588 ptr = gda_sql_identifier_force_quotes (tmp); 2589 g_free (tmp); 2590 return ptr; 2591 } 2592 } 2593 for (ptr = tmp; *ptr; ptr++) { 2594 if ((*ptr >= 'A') && (*ptr <= 'Z')) 2595 *ptr += 'a' - 'A'; 2596 } 2597 return tmp; 2598 } 2599 else { 2600 for (ptr = tmp; *ptr; ptr++) { 2601 if (*id == '"') { 2602 if (((*ptr >= 'A') && (*ptr <= 'Z')) || 2603 ((*ptr >= '0') && (*ptr <= '9') && (ptr != tmp)) || 2604 (*ptr == '_')) 2605 continue; 2606 else { 2607 ptr = gda_sql_identifier_force_quotes (tmp); 2608 g_free (tmp); 2609 return ptr; 2610 } 2611 } 2612 else if ((*ptr >= 'A') && (*ptr <= 'Z')) 2613 *ptr += 'a' - 'A'; 2614 else if ((*ptr >= '0') && (*ptr <= '9') && (ptr == tmp)) { 2615 ptr = gda_sql_identifier_force_quotes (tmp); 2616 g_free (tmp); 2617 return ptr; 2618 } 2619 } 2620 if (*id == '"') { 2621 for (ptr = tmp; *ptr; ptr++) { 2622 if ((*ptr >= 'A') && (*ptr <= 'Z')) 2623 *ptr += 'a' - 'A'; 2624 } 2625 } 2626 return tmp; 2627 } 2628 } 2629 else { 2630 if (*id == '"') { 2631 /* there are already some quotes */ 2632 return g_strdup (id); 2633 } 2634 if (kwfunc (id) || _sql_identifier_needs_quotes (id) || force_quotes) 2635 return identifier_add_quotes (id); 2636 2637 /* nothing to do */ 2638 return g_strdup (id); 2639 } 2640 } 2641 2642 2643 /* 2644 * Free connection's specific data 2645 */ 2646 static void 2647 gda_oracle_free_cnc_data (OracleConnectionData *cdata) 2648 { 2649 if (!cdata) 2650 return; 2651 2652 if (cdata->hsession) 2653 OCIHandleFree ((dvoid *) cdata->hsession, OCI_HTYPE_SESSION); 2654 if (cdata->hservice) 2655 OCIHandleFree ((dvoid *) cdata->hservice, OCI_HTYPE_SVCCTX); 2656 if (cdata->hserver) 2657 OCIHandleFree ((dvoid *) cdata->hserver, OCI_HTYPE_SERVER); 2658 if (cdata->herr) 2659 OCIHandleFree ((dvoid *) cdata->herr, OCI_HTYPE_ERROR); 2660 if (cdata->henv) 2661 OCIHandleFree ((dvoid *) cdata->henv, OCI_HTYPE_ENV); 2662 2663 g_free (cdata->schema); 2664 g_free (cdata->version); 2665 2666 g_free (cdata); 2667 } 2668