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 *
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
gda_oracle_provider_class_init(GdaOracleProviderClass * klass)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
gda_oracle_provider_init(GdaOracleProvider * oracle_prv,G_GNUC_UNUSED GdaOracleProviderClass * klass)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
gda_oracle_provider_get_type(void)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 *
gda_oracle_provider_get_name(G_GNUC_UNUSED GdaServerProvider * provider)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 *
gda_oracle_provider_get_version(G_GNUC_UNUSED GdaServerProvider * provider)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
execute_raw_command(GdaConnection * cnc,const gchar * sql)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
gda_oracle_provider_open_connection(GdaServerProvider * provider,GdaConnection * cnc,GdaQuarkList * params,GdaQuarkList * auth,G_GNUC_UNUSED guint * task_id,GdaServerProviderAsyncCallback async_cb,G_GNUC_UNUSED gpointer cb_data)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
gda_oracle_provider_close_connection(GdaServerProvider * provider,GdaConnection * cnc)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 *
gda_oracle_provider_get_server_version(GdaServerProvider * provider,GdaConnection * cnc)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 *
gda_oracle_provider_get_database(GdaServerProvider * provider,GdaConnection * cnc)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
gda_oracle_provider_supports_operation(GdaServerProvider * provider,GdaConnection * cnc,GdaServerOperationType type,G_GNUC_UNUSED GdaSet * options)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 *
gda_oracle_provider_create_operation(GdaServerProvider * provider,GdaConnection * cnc,GdaServerOperationType type,G_GNUC_UNUSED GdaSet * options,GError ** error)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 *
gda_oracle_provider_render_operation(GdaServerProvider * provider,GdaConnection * cnc,GdaServerOperation * op,GError ** error)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
gda_oracle_provider_perform_operation(GdaServerProvider * provider,GdaConnection * cnc,GdaServerOperation * op,G_GNUC_UNUSED guint * task_id,GdaServerProviderAsyncCallback async_cb,G_GNUC_UNUSED gpointer cb_data,GError ** error)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
gda_oracle_provider_begin_transaction(GdaServerProvider * provider,GdaConnection * cnc,const gchar * name,GdaTransactionIsolation level,GError ** error)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
gda_oracle_provider_commit_transaction(GdaServerProvider * provider,GdaConnection * cnc,const gchar * name,GError ** error)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
gda_oracle_provider_rollback_transaction(GdaServerProvider * provider,GdaConnection * cnc,const gchar * name,GError ** error)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
gda_oracle_provider_add_savepoint(GdaServerProvider * provider,GdaConnection * cnc,const gchar * name,GError ** error)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
gda_oracle_provider_rollback_savepoint(GdaServerProvider * provider,GdaConnection * cnc,const gchar * name,GError ** error)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
gda_oracle_provider_delete_savepoint(GdaServerProvider * provider,GdaConnection * cnc,const gchar * name,GError ** error)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
gda_oracle_provider_supports_feature(GdaServerProvider * provider,GdaConnection * cnc,GdaConnectionFeature feature)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 *
gda_oracle_provider_get_data_handler(GdaServerProvider * provider,GdaConnection * cnc,GType type,const gchar * dbms_type)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*
gda_oracle_provider_get_default_dbms_type(GdaServerProvider * provider,GdaConnection * cnc,GType type)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 *
gda_oracle_provider_create_parser(GdaServerProvider * provider,GdaConnection * cnc)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 *
gda_oracle_provider_statement_to_sql(GdaServerProvider * provider,GdaConnection * cnc,GdaStatement * stmt,GdaSet * params,GdaStatementSqlFlag flags,GSList ** params_used,GError ** error)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 *
oracle_render_select_target(GdaSqlSelectTarget * target,GdaSqlRenderingContext * context,GError ** error)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 *
oracle_render_select(GdaSqlStatementSelect * stmt,GdaSqlRenderingContext * context,GError ** error)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 *
oracle_render_expr(GdaSqlExpr * expr,GdaSqlRenderingContext * context,gboolean * is_default,gboolean * is_null,GError ** error)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
gda_oracle_provider_statement_prepare(GdaServerProvider * provider,GdaConnection * cnc,GdaStatement * stmt,GError ** error)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
clear_ora_values_list(GSList * oravalues_list)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 *
gda_oracle_provider_statement_execute(GdaServerProvider * provider,GdaConnection * cnc,GdaStatement * stmt,GdaSet * params,GdaStatementModelUsage model_usage,GType * col_types,GdaSet ** last_inserted_row,guint * task_id,GdaServerProviderExecCallback async_cb,gpointer cb_data,GError ** error)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 *
gda_oracle_statement_rewrite(GdaServerProvider * provider,GdaConnection * cnc,GdaStatement * stmt,GdaSet * params,GError ** error)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
gda_oracle_provider_xa_start(GdaServerProvider * provider,GdaConnection * cnc,const GdaXaTransactionId * xid,GError ** error)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
gda_oracle_provider_xa_end(GdaServerProvider * provider,GdaConnection * cnc,const GdaXaTransactionId * xid,GError ** error)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
gda_oracle_provider_xa_prepare(GdaServerProvider * provider,GdaConnection * cnc,const GdaXaTransactionId * xid,GError ** error)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
gda_oracle_provider_xa_commit(GdaServerProvider * provider,GdaConnection * cnc,const GdaXaTransactionId * xid,GError ** error)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
gda_oracle_provider_xa_rollback(GdaServerProvider * provider,GdaConnection * cnc,const GdaXaTransactionId * xid,GError ** error)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 *
gda_oracle_provider_xa_recover(GdaServerProvider * provider,GdaConnection * cnc,GError ** error)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 *
identifier_add_quotes(const gchar * str)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
_sql_identifier_needs_quotes(const gchar * str)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 *
ora_remove_quotes(gchar * str)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 *
gda_oracle_identifier_quote(GdaServerProvider * provider,GdaConnection * cnc,const gchar * id,gboolean for_meta_store,gboolean force_quotes)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
gda_oracle_free_cnc_data(OracleConnectionData * cdata)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