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