[libgda] Set up new oracle provider structure



commit e07be9c86404d8ccdf507b1a507914e58f6b05b0
Author: Vivien Malerba <malerba gnome-db org>
Date:   Mon Apr 20 23:12:01 2009 +0200

    Set up new oracle provider structure
---
 ChangeLog                                         |    6 +
 configure.in                                      |   17 +-
 providers/Makefile.am                             |    4 +-
 providers/oracle/Makefile.am                      |   69 +-
 providers/oracle/gda-oracle-blob-op.c             |  244 +--
 providers/oracle/gda-oracle-blob-op.h             |   16 +-
 providers/oracle/gda-oracle-ddl.c                 |  191 +-
 providers/oracle/gda-oracle-ddl.h                 |   28 +-
 providers/oracle/gda-oracle-meta.c                |  488 ++++
 providers/oracle/gda-oracle-meta.h                |  197 ++
 providers/oracle/gda-oracle-parser.c              |   84 +
 providers/oracle/gda-oracle-parser.h              |   59 +
 providers/oracle/gda-oracle-provider.c            | 2908 +++++++--------------
 providers/oracle/gda-oracle-provider.h            |   49 +-
 providers/oracle/gda-oracle-pstmt.c               |   96 +
 providers/oracle/gda-oracle-pstmt.h               |   57 +
 providers/oracle/gda-oracle-recordset.c           |  843 ++-----
 providers/oracle/gda-oracle-recordset.h           |   39 +-
 providers/oracle/gda-oracle.h                     |   74 +-
 providers/oracle/gen_def.c                        |  188 ++
 providers/oracle/libmain.c                        |   35 +-
 providers/oracle/oracle_specs_create_table.xml.in |   26 +
 providers/oracle/oracle_specs_dsn.xml.in          |    2 +-
 providers/oracle/parser.y                         | 1008 +++++++
 providers/oracle/utils.c                          |  550 ----
 25 files changed, 3778 insertions(+), 3500 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 58157e2..cbb3804 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2009-04-20  Vivien Malerba <malerba gnome-db org>
+
+	* configure.in:
+	* providers/Makefile.am:
+	* providers/oracle/*: set up new oracle provider structure
+
 2009-04-19  Vivien Malerba <malerba gnome-db org>
 
 	* libgda-report/RML/trml2html/Makefile.am:
diff --git a/configure.in b/configure.in
index ba138b2..8e38710 100644
--- a/configure.in
+++ b/configure.in
@@ -858,7 +858,7 @@ fi
 dnl test for ORACLE
 try_oracle=true
 AC_ARG_WITH(oracle,
-[  --with-oracle=<directory>	use ORACLE backend in <directoty>],[
+[  --with-oracle=<directory>	use ORACLE backend in <directory>],[
 if test $withval = no
 then
 	try_oracle=false
@@ -878,7 +878,16 @@ then
 		then
 			AC_MSG_RESULT(found ORACLE in $d)
 			oracledir=$d
+			oraclelibdir=$lib
 			break
+		else
+			if test -f $d/lib/libclntsh.so
+			then
+				AC_MSG_RESULT(found ORACLE in $d)
+				oracledir=$d
+				oraclelibdir="lib"
+				break
+			fi
 		fi
 	done
 	if test x$oracledir = x
@@ -887,7 +896,7 @@ then
 	else
 		AC_DEFINE(HAVE_ORACLE, 1, [Have ORACLE])
 		ORACLE_CFLAGS=" -I$oracledir/include/oracle/client -I$oracledir/rdbms/demo -I${ORACLE_HOME}/rdbms/public -I${ORACLE_HOME}/plsql/public -I$oracledir/network/public"
-		ORACLE_LIBS="-L$oracledir/lib -lm -ldl -lclntsh"
+		ORACLE_LIBS="-L$oracledir/$oraclelibdir -lm -ldl -lclntsh"
 	fi
 fi
 
@@ -1493,6 +1502,8 @@ providers/mdb/Makefile
 providers/mdb/libgda-mdb-4.0.pc
 providers/mysql/Makefile
 providers/mysql/libgda-mysql-4.0.pc
+providers/oracle/Makefile
+providers/oracle/libgda-oracle-4.0.pc
 providers/postgres/Makefile
 providers/postgres/libgda-postgres-4.0.pc
 providers/sqlite/Makefile
@@ -1544,7 +1555,7 @@ echo "      MDB (MS Access) = `if test x$mdbdir != x; then echo yes; else echo n
 echo "      MySQL = `if test x$mysqldir != x; then echo yes; else echo no; fi`"
 dnl echo "      mSQL = `if test x$msqldir != x; then echo yes; else echo no; fi`"
 dnl echo "      ODBC = `if test x$odbcdir != x; then echo yes; else echo no; fi`"
-dnl echo "      Oracle = `if test x$oracledir != x; then echo yes; else echo no; fi`"
+echo "      Oracle = `if test x$oracledir != x; then echo yes; else echo no; fi`"
 echo "      PostgreSQL = `if test x$postgresdir != x; then echo yes; else echo no; fi`"
 echo "      SQLite = yes `if test x$have_sqlite = xyes; then echo '(from system installation)'; else echo '(embedded)'; fi`"
 dnl echo "      Sybase = `if test x$sybasedir != x; then echo yes; else echo no; fi`"
diff --git a/providers/Makefile.am b/providers/Makefile.am
index 2244c69..cf5c18f 100644
--- a/providers/Makefile.am
+++ b/providers/Makefile.am
@@ -61,13 +61,13 @@ SUBDIRS = \
 	$(GDA_MDB_SERVER) \
 	$(GDA_POSTGRES_SERVER) \
 	$(GDA_MYSQL_SERVER) \
-	$(GDA_JAVA_SERVER)
+	$(GDA_JAVA_SERVER) \
+	$(GDA_ORACLE_SERVER)
 #	$(GDA_FREETDS_SERVER) \
 #	$(GDA_IBMDB2_SERVER) \
 #	$(GDA_FIREBIRD_SERVER) \
 #       $(GDA_MSQL_SERVER) \
 #	$(GDA_ODBC_SERVER) \
-#	$(GDA_ORACLE_SERVER) \
 #	$(GDA_SYBASE_SERVER) \
 #	$(GDA_XBASE_SERVER) \
 #	$(GDA_LDAP_SERVER) 
diff --git a/providers/oracle/Makefile.am b/providers/oracle/Makefile.am
index b2b4f63..f419a9e 100644
--- a/providers/oracle/Makefile.am
+++ b/providers/oracle/Makefile.am
@@ -1,66 +1,67 @@
-# GDA Oracle provider
-# Copyright (C) 1998 - 2007 The GNOME Foundation
-#
-# AUTHORS:
-#	Rodrigo Moya <rodrigo gnome-db org>
-#	Vivien Malerba <malerba gnome-db org>
-#	Bas Driessen <bas driessen xobas com>
-#
-# This Library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Library General Public License as
-# published by the Free Software Foundation; either version 2 of the
-# License, or (at your option) any later version.
-#
-# This Library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# Library General Public License for more details.
-#
-# You should have received a copy of the GNU Library General Public
-# License along with this Library; see the file COPYING.LIB.  If not,
-# write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-#
-
 providerdir=$(libdir)/libgda-$(GDA_ABI_MAJOR_VERSION).$(GDA_ABI_MINOR_VERSION)/providers
 provider_LTLIBRARIES = libgda-oracle.la
 
+#Rem: ORACLE_CFLAGS and ORACLE_LIBS are the compile and link flags necessary to use the
+# C API. It is specific to the API and should be computed in the configure.in script.
+
 AM_CPPFLAGS = \
 	-I$(top_srcdir) \
 	-I$(top_srcdir)/libgda \
 	-I$(top_builddir) \
 	$(LIBGDA_CFLAGS) \
-	$(ORACLE_CFLAGS)
+	$(ORACLE_CFLAGS) 
+
+# parser generation
+parser.c parser.h: parser.y $(top_builddir)/libgda/sql-parser/lemon$(EXEEXT_FOR_BUILD)
+	- $(top_builddir)/libgda/sql-parser/lemon$(EXEEXT_FOR_BUILD) -q -d $(srcdir)/parser.y $(top_srcdir)/libgda/sql-parser/lempar.c
+
+gen_def$(EXEEXT_FOR_BUILD): gen_def.c
+	$(CC_FOR_BUILD) -o gen_def$(EXEEXT_FOR_BUILD) -DIMPOSED_HEADER=\""$(top_srcdir)/libgda/sql-parser/token_types.h"\" $(srcdir)/gen_def.c
+
+oracle_token_types.h: gen_def$(EXEEXT_FOR_BUILD) parser.h
+	./gen_def$(EXEEXT_FOR_BUILD) > oracle_token_types.h
+
+$(OBJECTS) $(libgda_oracle_la_OBJECTS): oracle_token_types.h
 
 libgda_oracle_la_SOURCES = \
 	gda-oracle-blob-op.c \
 	gda-oracle-blob-op.h \
 	gda-oracle-ddl.c \
 	gda-oracle-ddl.h \
+	gda-oracle-parser.c \
+	gda-oracle-parser.h \
 	gda-oracle-provider.c \
 	gda-oracle-provider.h \
+	gda-oracle-pstmt.h \
+	gda-oracle-pstmt.c \
+	gda-oracle-meta.c \
+	gda-oracle-meta.h \
 	gda-oracle-recordset.c \
 	gda-oracle-recordset.h \
 	gda-oracle.h \
 	libmain.c \
-	utils.c
-libgda_oracle_la_LDFLAGS = -export-dynamic -module -avoid-version $(NO_UNDEFINED)
+	parser.h \
+        parser.c \
+        oracle_token_types.h
+
+libgda_oracle_la_LDFLAGS = -export-dynamic -module -avoid-version $(NO_UNDEFINED) $(LIBTOOL_PROV_EXPORT_OPTIONS)
 libgda_oracle_la_LIBADD = \
 	$(top_builddir)/libgda/libgda-4.0.la \
-	$(LIBGDA_LIBS) \
-	$(ORACLE_LIBS)
+	$(LIBGDA_LIBS) $(ORACLE_LIBS)
 
 xmldir   = $(datadir)/libgda-4.0
-xml_in_files =	oracle_specs_dsn.xml.in \
-		oracle_specs_drop_table.xml.in \
-		oracle_specs_drop_index.xml.in
+xml_in_files = \
+	oracle_specs_dsn.xml.in \
+	oracle_specs_create_table.xml.in 
 
 @INTLTOOL_XML_RULE@
 
-xml_DATA = $(xml_in_files:.xml.in=.xml)
+xml_DATA = $(xml_in_files:.xml.in=.xml) 
 
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libgda-oracle-4.0.pc
 
-EXTRA_DIST = $(xml_in_files) libgda-oracle-4.0.pc.in
+EXTRA_DIST = $(xml_in_files) libgda-oracle-4.0.pc.in parser.y gen_def.c
 DISTCLEANFILES = $(xml_DATA)
+
+CLEANFILES = parser.h parser.c parser.out oracle_token_types.h gen_def$(EXEEXT_FOR_BUILD)
diff --git a/providers/oracle/gda-oracle-blob-op.c b/providers/oracle/gda-oracle-blob-op.c
index 85478cb..04dc562 100644
--- a/providers/oracle/gda-oracle-blob-op.c
+++ b/providers/oracle/gda-oracle-blob-op.c
@@ -1,8 +1,8 @@
-/* GDA Postgres blob
- * Copyright (C) 2007 The GNOME Foundation
+/* GDA Oracle provider
+ * Copyright (C) 2008 The GNOME Foundation
  *
  * AUTHORS:
- *      Vivien Malerba <malerba gnome-db org>
+ *      TO_ADD: your name and email
  *
  * This Library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public License as
@@ -22,29 +22,23 @@
 
 #include <glib/gi18n-lib.h>
 #include <string.h>
+#include <libgda/libgda.h>
 #include "gda-oracle.h"
 #include "gda-oracle-blob-op.h"
 
-#ifdef PARENT_TYPE
-#undef PARENT_TYPE
-#endif
-
-#define PARENT_TYPE GDA_TYPE_BLOB_OP
-
 struct _GdaOracleBlobOpPrivate {
 	GdaConnection *cnc;
-	OCILobLocator *lobl;
+	/* TO_ADD: specific information describing a Blob in the C API */
 };
 
 static void gda_oracle_blob_op_class_init (GdaOracleBlobOpClass *klass);
 static void gda_oracle_blob_op_init       (GdaOracleBlobOp *blob,
-					  GdaOracleBlobOpClass *klass);
+					 GdaOracleBlobOpClass *klass);
 static void gda_oracle_blob_op_finalize   (GObject *object);
 
 static glong gda_oracle_blob_op_get_length (GdaBlobOp *op);
 static glong gda_oracle_blob_op_read       (GdaBlobOp *op, GdaBlob *blob, glong offset, glong size);
 static glong gda_oracle_blob_op_write      (GdaBlobOp *op, GdaBlob *blob, glong offset);
-static gboolean gda_oracle_blob_op_write_all (GdaBlobOp *op, GdaBlob *blob);
 
 static GObjectClass *parent_class = NULL;
 
@@ -57,6 +51,7 @@ gda_oracle_blob_op_get_type (void)
 	static GType type = 0;
 
 	if (G_UNLIKELY (type == 0)) {
+		static GStaticMutex registering = G_STATIC_MUTEX_INIT;
 		static const GTypeInfo info = {
 			sizeof (GdaOracleBlobOpClass),
 			(GBaseInitFunc) NULL,
@@ -68,7 +63,10 @@ gda_oracle_blob_op_get_type (void)
 			0,
 			(GInstanceInitFunc) gda_oracle_blob_op_init
 		};
-		type = g_type_register_static (PARENT_TYPE, "GdaOracleBlobOp", &info, 0);
+		g_static_mutex_lock (&registering);
+		if (type == 0)
+			type = g_type_register_static (GDA_TYPE_BLOB_OP, "GdaOracleBlobOp", &info, 0);
+		g_static_mutex_unlock (&registering);
 	}
 	return type;
 }
@@ -80,7 +78,9 @@ gda_oracle_blob_op_init (GdaOracleBlobOp *op,
 	g_return_if_fail (GDA_IS_ORACLE_BLOB_OP (op));
 
 	op->priv = g_new0 (GdaOracleBlobOpPrivate, 1);
-	op->priv->lobl = NULL;
+
+	/* initialize specific structure */
+	TO_IMPLEMENT;
 }
 
 static void
@@ -95,204 +95,132 @@ gda_oracle_blob_op_class_init (GdaOracleBlobOpClass *klass)
 	blob_class->get_length = gda_oracle_blob_op_get_length;
 	blob_class->read = gda_oracle_blob_op_read;
 	blob_class->write = gda_oracle_blob_op_write;
-	blob_class->write_all = gda_oracle_blob_op_write_all;
-}
-
-static GdaOracleConnectionData *
-get_conn_data (GdaConnection *cnc)
-{
-	GdaOracleConnectionData *priv_data;
-
-	priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
-	if (!priv_data) {
-		gda_connection_add_event_string (cnc, _("Invalid Oracle handle"));
-		return NULL;
-	}
-
-	return priv_data;
 }
 
 static void
 gda_oracle_blob_op_finalize (GObject * object)
 {
-	GdaOracleBlobOp *op = (GdaOracleBlobOp *) object;
+	GdaOracleBlobOp *bop = (GdaOracleBlobOp *) object;
 
-	g_return_if_fail (GDA_IS_ORACLE_BLOB_OP (op));
+	g_return_if_fail (GDA_IS_ORACLE_BLOB_OP (bop));
 
-	if (op->priv->lobl) {
-		GdaOracleConnectionData *priv_data = get_conn_data (op->priv->cnc);
-		g_assert (priv_data);
+	/* free specific information */
+	TO_IMPLEMENT;
 
-		OCILobClose (priv_data->hservice, priv_data->herr, op->priv->lobl);
-	}
-	g_free (op->priv);
-	op->priv = NULL;
+	g_free (bop->priv);
+	bop->priv = NULL;
 
 	parent_class->finalize (object);
 }
 
 GdaBlobOp *
-gda_oracle_blob_op_new (GdaConnection *cnc, OCILobLocator *lobloc)
+gda_oracle_blob_op_new (GdaConnection *cnc)
 {
-	GdaOracleBlobOp *blob;
+	GdaOracleBlobOp *bop;
 
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-	g_return_val_if_fail (lobloc, NULL);
 
-	blob = g_object_new (GDA_TYPE_ORACLE_BLOB_OP, NULL);
-	blob->priv->cnc = cnc;
-	blob->priv->lobl = lobloc;
+	bop = g_object_new (GDA_TYPE_ORACLE_BLOB_OP, NULL);
+	bop->priv->cnc = cnc;
 	
-	return GDA_BLOB_OP (blob);
+	return GDA_BLOB_OP (bop);
 }
 
-
 /*
- * Virtual functions
+ * Get length request
  */
 static glong
 gda_oracle_blob_op_get_length (GdaBlobOp *op)
 {
-	GdaOracleBlobOp *oraop;
-	ub4 loblen = 0;
+	GdaOracleBlobOp *bop;
 
 	g_return_val_if_fail (GDA_IS_ORACLE_BLOB_OP (op), -1);
-	oraop = GDA_ORACLE_BLOB_OP (op);
-	g_return_val_if_fail (oraop->priv, -1);
-	g_return_val_if_fail (GDA_IS_CONNECTION (oraop->priv->cnc), -1);
-
-	if (oraop->priv->lobl) {
-		gint result;
-		GdaConnectionEvent *error;
-		GdaOracleConnectionData *priv_data = get_conn_data (oraop->priv->cnc);
-		g_assert (priv_data);
-
-		result = OCILobGetLength (priv_data->hservice, priv_data->herr, oraop->priv->lobl, &loblen);
-		error = gda_oracle_check_result (result, oraop->priv->cnc, priv_data, OCI_HTYPE_ERROR,
-						 _("Could not get the length of LOB object"));
-		if (!error)
-			return loblen;
-	}
+	bop = GDA_ORACLE_BLOB_OP (op);
+	g_return_val_if_fail (bop->priv, -1);
+	g_return_val_if_fail (GDA_IS_CONNECTION (bop->priv->cnc), -1);
+
+	TO_IMPLEMENT;
 	return -1;
 }
 
+/*
+ * Blob read request
+ */
 static glong
 gda_oracle_blob_op_read (GdaBlobOp *op, GdaBlob *blob, glong offset, glong size)
 {
-	GdaOracleBlobOp *oraop;
+	GdaOracleBlobOp *bop;
 	GdaBinary *bin;
 
 	g_return_val_if_fail (GDA_IS_ORACLE_BLOB_OP (op), -1);
-	oraop = GDA_ORACLE_BLOB_OP (op);
-	g_return_val_if_fail (oraop->priv, -1);
-	g_return_val_if_fail (GDA_IS_CONNECTION (oraop->priv->cnc), -1);
+	bop = GDA_ORACLE_BLOB_OP (op);
+	g_return_val_if_fail (bop->priv, -1);
+	g_return_val_if_fail (GDA_IS_CONNECTION (bop->priv->cnc), -1);
+	if (offset >= G_MAXINT)
+		return -1;
 	g_return_val_if_fail (blob, -1);
 
 	bin = (GdaBinary *) blob;
-	if (bin->data) {
+	if (bin->data) 
 		g_free (bin->data);
-		bin->data = NULL;
-		bin->binary_length = 0;
-	}
+	bin->data = g_new0 (guchar, size);
+	bin->binary_length = 0;
 
-	if (oraop->priv->lobl) {
-		sword result;
-		ub4 nbbytes;
-		GdaOracleConnectionData *priv_data = get_conn_data (oraop->priv->cnc);
-		ub4 loblen = 0;
-		ub1 *buf;
-		g_assert (priv_data);
-
-		result = OCILobGetLength (priv_data->hservice, priv_data->herr, oraop->priv->lobl, &loblen);
-		if (gda_oracle_check_result (result, oraop->priv->cnc, priv_data, OCI_HTYPE_ERROR,
-					     _("Could not get the length of LOB object")))
-			return -1;
-
-		nbbytes = (size > loblen) ? loblen : size;
-		buf = g_new (ub1, nbbytes);
-		/*result = OCILobRead2 (priv_data->hservice, priv_data->herr, oraop->priv->lobl, &nbbytes, 0,
-				      offset + 1, (dvoid *) buf, nbbytes, OCI_ONE_PIECE, 
-				      NULL, NULL, 0, SQLCS_IMPLICIT);*/
-		result = OCILobRead (priv_data->hservice, priv_data->herr, oraop->priv->lobl, &nbbytes,
-				      offset + 1, (dvoid *) buf, nbbytes, 
-				      NULL, NULL, 0, SQLCS_IMPLICIT);
-		if (gda_oracle_check_result (result, oraop->priv->cnc, priv_data, OCI_HTYPE_ERROR,
-					     _("Could not read from LOB object"))) {
-			g_free (buf);
-			return -1;
-		}
-		bin->data = buf;
-		bin->binary_length = nbbytes;
-		return bin->binary_length;
-	}
+	/* fetch blob data using C API into bin->data, and set bin->binary_length */
+	TO_IMPLEMENT;
 
-	return -1;
+	return bin->binary_length;
 }
 
+/*
+ * Blob write request
+ */
 static glong
 gda_oracle_blob_op_write (GdaBlobOp *op, GdaBlob *blob, glong offset)
 {
-	GdaOracleBlobOp *oraop;
+	GdaOracleBlobOp *bop;
 	GdaBinary *bin;
+	glong nbwritten = -1;
 
 	g_return_val_if_fail (GDA_IS_ORACLE_BLOB_OP (op), -1);
-	oraop = GDA_ORACLE_BLOB_OP (op);
-	g_return_val_if_fail (oraop->priv, -1);
-	g_return_val_if_fail (GDA_IS_CONNECTION (oraop->priv->cnc), -1);
+	bop = GDA_ORACLE_BLOB_OP (op);
+	g_return_val_if_fail (bop->priv, -1);
+	g_return_val_if_fail (GDA_IS_CONNECTION (bop->priv->cnc), -1);
 	g_return_val_if_fail (blob, -1);
 
-	bin = (GdaBinary *) blob;
-
-	if (oraop->priv->lobl) {
-		sword result;
-		ub4 nbbytes;
-		GdaOracleConnectionData *priv_data = get_conn_data (oraop->priv->cnc);
-		g_assert (priv_data);
-
-		nbbytes = bin->binary_length;
-		result = OCILobWrite (priv_data->hservice, priv_data->herr, oraop->priv->lobl, &nbbytes, (ub4) offset + 1,
-				      (dvoid *) bin->data, bin->binary_length,
-				      OCI_ONE_PIECE, NULL, NULL, 0, SQLCS_IMPLICIT);
-		if (gda_oracle_check_result (result, oraop->priv->cnc, priv_data, OCI_HTYPE_ERROR,
-					     _("Could not write to LOB object"))) {
-			return -1;
+	if (blob->op && (blob->op != op)) {
+		/* use data through blob->op */
+		#define buf_size 16384
+		gint nread = 0;
+		GdaBlob *tmpblob = g_new0 (GdaBlob, 1);
+		tmpblob->op = blob->op;
+
+		nbwritten = 0;
+
+		for (nread = gda_blob_op_read (tmpblob->op, tmpblob, nbwritten, buf_size);
+		     nread > 0;
+		     nread = gda_blob_op_read (tmpblob->op, tmpblob, nbwritten, buf_size)) {
+			glong tmp_written;
+
+			tmp_written = -1; TO_IMPLEMENT;
+			
+			if (tmp_written < 0) {
+				/* treat error */
+				gda_blob_free ((gpointer) tmpblob);
+				return -1;
+			}
+			nbwritten += tmp_written;
+			if (nread < buf_size)
+				/* nothing more to read */
+				break;
 		}
-		return nbbytes;
+		gda_blob_free ((gpointer) tmpblob);
 	}
-
-	return -1;
-}
-
-static gboolean
-gda_oracle_blob_op_write_all (GdaBlobOp *op, GdaBlob *blob)
-{
-	GdaOracleBlobOp *oraop;
-	GdaBinary *bin;
-
-	g_return_val_if_fail (GDA_IS_ORACLE_BLOB_OP (op), FALSE);
-	oraop = GDA_ORACLE_BLOB_OP (op);
-	g_return_val_if_fail (oraop->priv, FALSE);
-	g_return_val_if_fail (GDA_IS_CONNECTION (oraop->priv->cnc), FALSE);
-	g_return_val_if_fail (blob, FALSE);
-
-	bin = (GdaBinary *) blob;
-	if (oraop->priv->lobl) {
-		sword result;
-		GdaOracleConnectionData *priv_data = get_conn_data (oraop->priv->cnc);
-		g_assert (priv_data);
-
-		if (gda_oracle_blob_op_write (op, blob, 0) != bin->binary_length)
-			return FALSE;
-		else {
-			/* truncate lob at the end */
-			result = OCILobTrim (priv_data->hservice, priv_data->herr, oraop->priv->lobl, bin->binary_length);
-			if (gda_oracle_check_result (result, oraop->priv->cnc, priv_data, OCI_HTYPE_ERROR,
-						     _("Could not truncate LOB object")))
-				return FALSE;
-			else
-				return TRUE;
-		}
+	else {
+		/* write blob using bin->data and bin->binary_length */
+		bin = (GdaBinary *) blob;
+		nbwritten = -1; TO_IMPLEMENT;
 	}
 
-	return FALSE;
+	return nbwritten;
 }
diff --git a/providers/oracle/gda-oracle-blob-op.h b/providers/oracle/gda-oracle-blob-op.h
index 2ac37b9..a118316 100644
--- a/providers/oracle/gda-oracle-blob-op.h
+++ b/providers/oracle/gda-oracle-blob-op.h
@@ -1,8 +1,8 @@
-/* GDA DB Oracle Blob
- * Copyright (C) 2007 The GNOME Foundation
+/* GDA Oracle provider
+ * Copyright (C) 2008 The GNOME Foundation
  *
  * AUTHORS:
- *      Vivien Malerba <malerba gnome-db org>
+ *      TO_ADD: your name and email
  *
  * This Library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public License as
@@ -23,9 +23,7 @@
 #ifndef __GDA_ORACLE_BLOB_OP_H__
 #define __GDA_ORACLE_BLOB_OP_H__
 
-#include <libgda/gda-value.h>
 #include <libgda/gda-blob-op.h>
-#include <oci.h>
 
 G_BEGIN_DECLS
 
@@ -40,16 +38,18 @@ typedef struct _GdaOracleBlobOpClass   GdaOracleBlobOpClass;
 typedef struct _GdaOracleBlobOpPrivate GdaOracleBlobOpPrivate;
 
 struct _GdaOracleBlobOp {
-	GdaBlobOp               parent;
+	GdaBlobOp             parent;
 	GdaOracleBlobOpPrivate *priv;
 };
 
 struct _GdaOracleBlobOpClass {
-	GdaBlobOpClass          parent_class;
+	GdaBlobOpClass        parent_class;
 };
 
 GType         gda_oracle_blob_op_get_type     (void) G_GNUC_CONST;
-GdaBlobOp    *gda_oracle_blob_op_new          (GdaConnection *cnc, OCILobLocator *lobloc);
+GdaBlobOp    *gda_oracle_blob_op_new          (GdaConnection *cnc);
+
+/* TO_ADD: more convenient API to create a GdaBlobOp with some specific information as argument */
 
 G_END_DECLS
 
diff --git a/providers/oracle/gda-oracle-ddl.c b/providers/oracle/gda-oracle-ddl.c
index cf38335..28d559f 100644
--- a/providers/oracle/gda-oracle-ddl.c
+++ b/providers/oracle/gda-oracle-ddl.c
@@ -1,9 +1,8 @@
-/* GNOME DB Oracle Provider
- * Copyright (C) 2006 The GNOME Foundation
+/* GDA Oracle Provider
+ * Copyright (C) 2008 The GNOME Foundation
  *
  * AUTHORS:
- *         Vivien Malerba <malerba gnome-db org>
- *         Bas Driessen <bas driessen xobas com>
+ *      TO_ADD: your name and email
  *
  * This Library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public License as
@@ -21,111 +20,125 @@
  * Boston, MA 02111-1307, USA.
  */
 
-#include "gda-oracle-ddl.h"
 #include <glib/gi18n-lib.h>
-#include <libgda/gda-data-handler.h>
-
-gchar *
-gda_oracle_render_CREATE_DB (GdaServerProvider *provider, GdaConnection *cnc, 
-			     GdaServerOperation *op, GError **error)
-{
-	return NULL;
-}
-
-gchar *
-gda_oracle_render_DROP_DB (GdaServerProvider *provider, GdaConnection *cnc, 
-			   GdaServerOperation *op, GError **error)
-{
-	return NULL;
-}
-
+#include <libgda/libgda.h>
+#include "gda-oracle-ddl.h"
 
 gchar *
 gda_oracle_render_CREATE_TABLE (GdaServerProvider *provider, GdaConnection *cnc, 
-				GdaServerOperation *op, GError **error)
-{
-	return NULL;
-}
-
-gchar *
-gda_oracle_render_DROP_TABLE   (GdaServerProvider *provider, GdaConnection *cnc, 
-				GdaServerOperation *op, GError **error)
+			      GdaServerOperation *op, GError **error)
 {
 	GString *string;
 	const GValue *value;
+	gboolean allok = TRUE;
+	gboolean hasfields = FALSE;
+	gint nrows;
+	gint i;
+	gboolean first;
+	GSList *pkfields = NULL; /* list of GValue* composing the pkey */
+	gint nbpkfields = 0;
 	gchar *sql = NULL;
 
-	string = g_string_new ("DROP TABLE ");
+	/* CREATE TABLE */
+	string = g_string_new ("CREATE TABLE ");
 
-	value = gda_server_operation_get_value_at (op, "/TABLE_DESC_P/TABLE_NAME");
+	value = gda_server_operation_get_value_at (op, "/TABLE_DEF_P/TABLE_NAME");
 	g_assert (value && G_VALUE_HOLDS (value, G_TYPE_STRING));
 	g_string_append (string, g_value_get_string (value));
-
-	value = gda_server_operation_get_value_at (op, "/TABLE_DESC_P/REFERENCED_ACTION");
-	if (value && G_VALUE_HOLDS (value, G_TYPE_STRING)) {
-		g_string_append_c (string, ' ');
-		g_string_append (string, g_value_get_string (value));
+	g_string_append (string, " (");
+		
+	/* FIELDS */
+	if (allok) {
+		GdaServerOperationNode *node;
+
+		node = gda_server_operation_get_node_info (op, "/FIELDS_A");
+		g_assert (node);
+
+		/* finding if there is a composed primary key */
+		nrows = gda_data_model_get_n_rows (node->model);
+		for (i = 0; i < nrows; i++) {
+			value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_PKEY/%d", i);
+			if (value && G_VALUE_HOLDS (value, G_TYPE_BOOLEAN) && g_value_get_boolean (value))
+				pkfields = g_slist_append (pkfields,
+							   (GValue *) gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_NAME/%d", i));
+		}
+		nbpkfields = g_slist_length (pkfields);
+
+		/* manually defined fields */
+		first = TRUE;
+		for (i = 0; i < nrows; i++) {
+			hasfields = TRUE;
+			if (first) 
+				first = FALSE;
+			else
+				g_string_append (string, ", ");
+				
+			value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_NAME/%d", i);
+			g_string_append (string, g_value_get_string (value));
+			g_string_append_c (string, ' ');
+				
+			value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_TYPE/%d", i);
+			g_string_append (string, g_value_get_string (value));
+				
+			value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_DEFAULT/%d", i);
+			if (value && G_VALUE_HOLDS (value, G_TYPE_STRING)) {
+				const gchar *str = g_value_get_string (value);
+				if (str && *str) {
+					g_string_append (string, " DEFAULT ");
+					g_string_append (string, str);
+				}
+			}
+				
+			value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_NNUL/%d", i);
+			if (value && G_VALUE_HOLDS (value, G_TYPE_BOOLEAN) && g_value_get_boolean (value))
+				g_string_append (string, " NOT NULL");
+
+			value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_UNIQUE/%d", i);
+			if (value && G_VALUE_HOLDS (value, G_TYPE_BOOLEAN) && g_value_get_boolean (value))
+				g_string_append (string, " UNIQUE");
+				
+			if (nbpkfields == 1) {
+				value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_PKEY/%d", i);
+				if (value && G_VALUE_HOLDS (value, G_TYPE_BOOLEAN) && g_value_get_boolean (value))
+					g_string_append (string, " PRIMARY KEY");
+			}
+				
+			value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_CHECK/%d", i);
+			if (value && G_VALUE_HOLDS (value, G_TYPE_STRING)) {
+				const gchar *str = g_value_get_string (value);
+				if (str && *str) {
+					g_string_append (string, " CHECK (");
+					g_string_append (string, str);
+					g_string_append_c (string, ')');
+				}
+			}
+		}
 	}
 
-	sql = string->str;
-	g_string_free (string, FALSE);
-
-	return sql;
-}
-
-gchar *
-gda_oracle_render_RENAME_TABLE (GdaServerProvider *provider, GdaConnection *cnc, 
-				GdaServerOperation *op, GError **error)
-{
-	return NULL;
-}
-
-
-gchar *
-gda_oracle_render_ADD_COLUMN   (GdaServerProvider *provider, GdaConnection *cnc, 
-				GdaServerOperation *op, GError **error)
-{
-	return NULL;
-}
-
-gchar *
-gda_oracle_render_DROP_COLUMN  (GdaServerProvider *provider, GdaConnection *cnc, 
-				  GdaServerOperation *op, GError **error)
-{
-	return NULL;
-}
-
-
-gchar *
-gda_oracle_render_CREATE_INDEX (GdaServerProvider *provider, GdaConnection *cnc, 
-				GdaServerOperation *op, GError **error)
-{
-	return NULL;
-}
-
-gchar *
-gda_oracle_render_DROP_INDEX   (GdaServerProvider *provider, GdaConnection *cnc, 
-				GdaServerOperation *op, GError **error)
-{
-	GString *string;
-	const GValue *value;
-	gchar *sql = NULL;
-
-	string = g_string_new ("DROP INDEX ");
+	/* composed primary key */
+	if (nbpkfields > 1) {
+		GSList *list = pkfields;
+
+		g_string_append (string, ", PRIMARY KEY (");
+		while (list) {
+			if (list != pkfields)
+				g_string_append (string, ", ");
+			g_string_append (string, g_value_get_string ((GValue*) list->data));
+			list = list->next;
+		}
+		g_string_append_c (string, ')');
+	}
 
-	value = gda_server_operation_get_value_at (op, "/INDEX_DESC_P/INDEX_NAME");
-	g_assert (value && G_VALUE_HOLDS (value, G_TYPE_STRING));
-	g_string_append (string, g_value_get_string (value));
+	g_string_append (string, ")");
 
-	value = gda_server_operation_get_value_at (op, "/INDEX_DESC_P/REFERENCED_ACTION");
-	if (value && G_VALUE_HOLDS (value, G_TYPE_STRING)) {
-		g_string_append_c (string, ' ');
-		g_string_append (string, g_value_get_string (value));
+	if (!hasfields) {
+		allok = FALSE;
+		g_set_error (error, 0, 0, "%s", _("Table to create must have at least one row"));
 	}
+	g_slist_free (pkfields);
 
 	sql = string->str;
 	g_string_free (string, FALSE);
 
 	return sql;
 }
-
diff --git a/providers/oracle/gda-oracle-ddl.h b/providers/oracle/gda-oracle-ddl.h
index 94af629..0f14318 100644
--- a/providers/oracle/gda-oracle-ddl.h
+++ b/providers/oracle/gda-oracle-ddl.h
@@ -1,9 +1,8 @@
-/* GDA Oracle Provider
- * Copyright (C) 2006 The GNOME Foundation
+/* GDA Oracle provider
+ * Copyright (C) 2008 The GNOME Foundation
  *
  * AUTHORS:
- *         Vivien Malerba <malerba gnome-db org>
- *         Bas Driessen <bas driessen xobas com>
+ *      TO_ADD: your name and email
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -27,25 +26,8 @@
 
 G_BEGIN_DECLS
 
-gchar *gda_oracle_render_CREATE_DB     (GdaServerProvider *provider, GdaConnection *cnc, 
-					GdaServerOperation *op, GError **error);
-gchar *gda_oracle_render_DROP_DB       (GdaServerProvider *provider, GdaConnection *cnc, 
-					GdaServerOperation *op, GError **error);
-gchar *gda_oracle_render_CREATE_TABLE  (GdaServerProvider *provider, GdaConnection *cnc, 
-					GdaServerOperation *op, GError **error);
-gchar *gda_oracle_render_RENAME_TABLE  (GdaServerProvider *provider, GdaConnection *cnc, 
-					GdaServerOperation *op, GError **error);
-gchar *gda_oracle_render_DROP_TABLE    (GdaServerProvider *provider, GdaConnection *cnc, 
-					GdaServerOperation *op, GError **error);
-gchar *gda_oracle_render_ADD_COLUMN    (GdaServerProvider *provider, GdaConnection *cnc, 
-					GdaServerOperation *op, GError **error);
-gchar *gda_oracle_render_DROP_COLUMN   (GdaServerProvider *provider, GdaConnection *cnc, 
-					GdaServerOperation *op, GError **error);
-gchar *gda_oracle_render_CREATE_INDEX  (GdaServerProvider *provider, GdaConnection *cnc, 
-					GdaServerOperation *op, GError **error);
-gchar *gda_oracle_render_DROP_INDEX    (GdaServerProvider *provider, GdaConnection *cnc, 
-					GdaServerOperation *op, GError **error);
-
+gchar *gda_oracle_render_CREATE_TABLE (GdaServerProvider *provider, GdaConnection *cnc, 
+				     GdaServerOperation *op, GError **error);
 G_END_DECLS
 
 #endif
diff --git a/providers/oracle/gda-oracle-meta.c b/providers/oracle/gda-oracle-meta.c
new file mode 100644
index 0000000..128cca6
--- /dev/null
+++ b/providers/oracle/gda-oracle-meta.c
@@ -0,0 +1,488 @@
+/* GDA oracle provider
+ * Copyright (C) 2008 The GNOME Foundation.
+ *
+ * AUTHORS:
+ *      TO_ADD: your name and email
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include "gda-oracle.h"
+#include "gda-oracle-meta.h"
+#include "gda-oracle-provider.h"
+#include <libgda/gda-meta-store.h>
+#include <libgda/sql-parser/gda-sql-parser.h>
+#include <glib/gi18n-lib.h>
+#include <libgda/gda-server-provider-extra.h>
+#include <libgda/gda-connection-private.h>
+#include <libgda/gda-data-model-array.h>
+#include <libgda/gda-set.h>
+#include <libgda/gda-holder.h>
+
+/*
+ * predefined statements' IDs
+ */
+typedef enum {
+        I_STMT_1,
+} InternalStatementItem;
+
+
+/*
+ * predefined statements' SQL
+ */
+static gchar *internal_sql[] = {
+	"SQL for I_STMT_1"
+};
+
+/*
+ * global static values, and
+ * predefined statements' GdaStatement, all initialized in _gda_oracle_provider_meta_init()
+ */
+static GdaStatement **internal_stmt;
+static GdaSet        *i_set;
+static GdaSqlParser  *internal_parser = NULL;
+/* TO_ADD: other static values */
+
+
+/*
+ * Meta initialization
+ */
+void
+_gda_oracle_provider_meta_init (GdaServerProvider *provider)
+{
+	static GStaticMutex init_mutex = G_STATIC_MUTEX_INIT;
+	InternalStatementItem i;
+
+	g_static_mutex_lock (&init_mutex);
+
+        internal_parser = gda_server_provider_internal_get_parser (provider);
+        internal_stmt = g_new0 (GdaStatement *, sizeof (internal_sql) / sizeof (gchar*));
+        for (i = I_STMT_1; i < sizeof (internal_sql) / sizeof (gchar*); i++) {
+                internal_stmt[i] = gda_sql_parser_parse_string (internal_parser, internal_sql[i], NULL, NULL);
+                if (!internal_stmt[i])
+                        g_error ("Could not parse internal statement: %s\n", internal_sql[i]);
+        }
+
+	/* initialize static values here */
+	i_set = gda_set_new_inline (4, "cat", G_TYPE_STRING, "", 
+				    "name", G_TYPE_STRING, "",
+				    "schema", G_TYPE_STRING, "",
+				    "name2", G_TYPE_STRING, "");
+
+	g_static_mutex_unlock (&init_mutex);
+}
+
+gboolean
+_gda_oracle_meta__info (GdaServerProvider *prov, GdaConnection *cnc, 
+		      GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	GdaDataModel *model;
+	gboolean retval;
+
+	TO_IMPLEMENT;
+	/* fill in @model, with something like:
+	 * model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_1], NULL, 
+	 *                                                  error);
+	 */
+	if (!model)
+		return FALSE;
+	retval = gda_meta_store_modify_with_context (store, context, model, error);
+	g_object_unref (model);
+		
+	return retval;
+}
+
+gboolean
+_gda_oracle_meta__btypes (GdaServerProvider *prov, GdaConnection *cnc, 
+			GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__udt (GdaServerProvider *prov, GdaConnection *cnc, 
+		     GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_udt (GdaServerProvider *prov, GdaConnection *cnc, 
+		    GdaMetaStore *store, GdaMetaContext *context, GError **error,
+		    const GValue *udt_catalog, const GValue *udt_schema)
+{
+	GdaDataModel *model;
+	gboolean retval = TRUE;
+
+	/* set internal holder's values from the arguments */
+	if (! gda_holder_set_value (gda_set_get_holder (i_set, "cat"), udt_catalog, error))
+		return FALSE;
+	if (! gda_holder_set_value (gda_set_get_holder (i_set, "schema"), udt_schema, error))
+		return FALSE;
+
+	TO_IMPLEMENT;
+	/* fill in @model, with something like:
+	 * model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_UDT], i_set, error);
+	 */
+	if (!model)
+		return FALSE;
+	retval = gda_meta_store_modify_with_context (store, context, model, error);
+	g_object_unref (model);
+
+	return retval;
+}
+
+
+gboolean
+_gda_oracle_meta__udt_cols (GdaServerProvider *prov, GdaConnection *cnc, 
+			  GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;	
+}
+
+gboolean
+_gda_oracle_meta_udt_cols (GdaServerProvider *prov, GdaConnection *cnc, 
+			 GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			 const GValue *udt_catalog, const GValue *udt_schema, const GValue *udt_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;	
+}
+
+gboolean
+_gda_oracle_meta__enums (GdaServerProvider *prov, GdaConnection *cnc, 
+		       GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;	
+}
+
+gboolean
+_gda_oracle_meta_enums (GdaServerProvider *prov, GdaConnection *cnc, 
+		      GdaMetaStore *store, GdaMetaContext *context, GError **error,
+		      const GValue *udt_catalog, const GValue *udt_schema, const GValue *udt_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+
+gboolean
+_gda_oracle_meta__domains (GdaServerProvider *prov, GdaConnection *cnc, 
+			 GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_domains (GdaServerProvider *prov, GdaConnection *cnc, 
+			GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			const GValue *domain_catalog, const GValue *domain_schema)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__constraints_dom (GdaServerProvider *prov, GdaConnection *cnc, 
+				 GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_constraints_dom (GdaServerProvider *prov, GdaConnection *cnc, 
+				GdaMetaStore *store, GdaMetaContext *context, GError **error,
+				const GValue *domain_catalog, const GValue *domain_schema, 
+				const GValue *domain_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__el_types (GdaServerProvider *prov, GdaConnection *cnc, 
+			  GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_el_types (GdaServerProvider *prov, GdaConnection *cnc, 
+			 GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			 const GValue *specific_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__collations (GdaServerProvider *prov, GdaConnection *cnc, 
+			    GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_collations (GdaServerProvider *prov, GdaConnection *cnc, 
+			   GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			   const GValue *collation_catalog, const GValue *collation_schema, 
+			   const GValue *collation_name_n)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__character_sets (GdaServerProvider *prov, GdaConnection *cnc, 
+				GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_character_sets (GdaServerProvider *prov, GdaConnection *cnc, 
+			       GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			       const GValue *chset_catalog, const GValue *chset_schema, 
+			       const GValue *chset_name_n)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__schemata (GdaServerProvider *prov, GdaConnection *cnc, 
+			  GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_schemata (GdaServerProvider *prov, GdaConnection *cnc, 
+			 GdaMetaStore *store, GdaMetaContext *context, GError **error, 
+			 const GValue *catalog_name, const GValue *schema_name_n)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__tables_views (GdaServerProvider *prov, GdaConnection *cnc, 
+			      GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_tables_views (GdaServerProvider *prov, GdaConnection *cnc, 
+			     GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			     const GValue *table_catalog, const GValue *table_schema, 
+			     const GValue *table_name_n)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__columns (GdaServerProvider *prov, GdaConnection *cnc, 
+			 GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_columns (GdaServerProvider *prov, GdaConnection *cnc, 
+			GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			const GValue *table_catalog, const GValue *table_schema, 
+			const GValue *table_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__view_cols (GdaServerProvider *prov, GdaConnection *cnc, 
+			   GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_view_cols (GdaServerProvider *prov, GdaConnection *cnc, 
+			  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			  const GValue *view_catalog, const GValue *view_schema, 
+			  const GValue *view_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__constraints_tab (GdaServerProvider *prov, GdaConnection *cnc, 
+				 GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_constraints_tab (GdaServerProvider *prov, GdaConnection *cnc, 
+				GdaMetaStore *store, GdaMetaContext *context, GError **error, 
+				const GValue *table_catalog, const GValue *table_schema, 
+				const GValue *table_name, const GValue *constraint_name_n)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__constraints_ref (GdaServerProvider *prov, GdaConnection *cnc, 
+				 GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_constraints_ref (GdaServerProvider *prov, GdaConnection *cnc, 
+				GdaMetaStore *store, GdaMetaContext *context, GError **error,
+				const GValue *table_catalog, const GValue *table_schema, const GValue *table_name, 
+				const GValue *constraint_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__key_columns (GdaServerProvider *prov, GdaConnection *cnc, 
+			     GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_key_columns (GdaServerProvider *prov, GdaConnection *cnc, 
+			    GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			    const GValue *table_catalog, const GValue *table_schema, 
+			    const GValue *table_name, const GValue *constraint_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__check_columns (GdaServerProvider *prov, GdaConnection *cnc, 
+			       GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_check_columns (GdaServerProvider *prov, GdaConnection *cnc, 
+			      GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			      const GValue *table_catalog, const GValue *table_schema, 
+			      const GValue *table_name, const GValue *constraint_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__triggers (GdaServerProvider *prov, GdaConnection *cnc, 
+			  GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_triggers (GdaServerProvider *prov, GdaConnection *cnc, 
+			 GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			 const GValue *table_catalog, const GValue *table_schema, 
+			 const GValue *table_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__routines (GdaServerProvider *prov, GdaConnection *cnc, 
+			  GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_routines (GdaServerProvider *prov, GdaConnection *cnc, 
+			 GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			 const GValue *routine_catalog, const GValue *routine_schema, 
+			 const GValue *routine_name_n)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__routine_col (GdaServerProvider *prov, GdaConnection *cnc, 
+			     GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_routine_col (GdaServerProvider *prov, GdaConnection *cnc, 
+			    GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			    const GValue *rout_catalog, const GValue *rout_schema, 
+			    const GValue *rout_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__routine_par (GdaServerProvider *prov, GdaConnection *cnc, 
+			     GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_routine_par (GdaServerProvider *prov, GdaConnection *cnc, 
+			    GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			    const GValue *rout_catalog, const GValue *rout_schema, 
+			    const GValue *rout_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
diff --git a/providers/oracle/gda-oracle-meta.h b/providers/oracle/gda-oracle-meta.h
new file mode 100644
index 0000000..0850505
--- /dev/null
+++ b/providers/oracle/gda-oracle-meta.h
@@ -0,0 +1,197 @@
+/* GDA oracle provider
+ * Copyright (C) 2008 The GNOME Foundation.
+ *
+ * AUTHORS:
+ *      TO_ADD: your name and email
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __GDA_ORACLE_META_H__
+#define __GDA_ORACLE_META_H__
+
+#include <libgda/gda-server-provider.h>
+
+G_BEGIN_DECLS
+
+void     _gda_oracle_provider_meta_init    (GdaServerProvider *provider);
+
+/* _information_schema_catalog_name */
+gboolean _gda_oracle_meta__info            (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+
+/* _builtin_data_types */
+gboolean _gda_oracle_meta__btypes          (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+
+/* _udt */
+gboolean _gda_oracle_meta__udt             (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_udt              (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *udt_catalog, const GValue *udt_schema);
+
+/* _udt_columns */
+gboolean _gda_oracle_meta__udt_cols        (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_udt_cols         (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *udt_catalog, const GValue *udt_schema, const GValue *udt_name);
+
+/* _enums */
+gboolean _gda_oracle_meta__enums           (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_enums            (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *udt_catalog, const GValue *udt_schema, const GValue *udt_name);
+
+/* _domains */
+gboolean _gda_oracle_meta__domains         (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_domains          (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *domain_catalog, const GValue *domain_schema);
+
+/* _domain_constraints */
+gboolean _gda_oracle_meta__constraints_dom (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_constraints_dom  (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *domain_catalog, const GValue *domain_schema, 
+					  const GValue *domain_name);
+
+/* _element_types */
+gboolean _gda_oracle_meta__el_types        (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_el_types         (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *specific_name);
+
+/* _collations */
+gboolean _gda_oracle_meta__collations      (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_collations       (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *collation_catalog, const GValue *collation_schema, 
+					  const GValue *collation_name_n);
+
+/* _character_sets */
+gboolean _gda_oracle_meta__character_sets  (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_character_sets   (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *chset_catalog, const GValue *chset_schema, 
+					  const GValue *chset_name_n);
+
+/* _schemata */
+gboolean _gda_oracle_meta__schemata        (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_schemata         (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error, 
+					  const GValue *catalog_name, const GValue *schema_name_n);
+
+/* _tables or _views */
+gboolean _gda_oracle_meta__tables_views    (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_tables_views     (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *table_catalog, const GValue *table_schema, 
+					  const GValue *table_name_n);
+
+/* _columns */
+gboolean _gda_oracle_meta__columns         (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_columns          (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *table_catalog, const GValue *table_schema, 
+					  const GValue *table_name);
+
+/* _view_column_usage */
+gboolean _gda_oracle_meta__view_cols       (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_view_cols        (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *view_catalog, const GValue *view_schema, 
+					  const GValue *view_name);
+
+/* _table_constraints */
+gboolean _gda_oracle_meta__constraints_tab (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_constraints_tab  (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error, 
+					  const GValue *table_catalog, const GValue *table_schema, 
+					  const GValue *table_name, const GValue *constraint_name_n);
+
+/* _referential_constraints */
+gboolean _gda_oracle_meta__constraints_ref (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_constraints_ref  (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *table_catalog, const GValue *table_schema, const GValue *table_name, 
+					  const GValue *constraint_name);
+
+/* _key_column_usage */
+gboolean _gda_oracle_meta__key_columns     (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_key_columns      (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *table_catalog, const GValue *table_schema, 
+					  const GValue *table_name, const GValue *constraint_name);
+
+/* _check_column_usage */
+gboolean _gda_oracle_meta__check_columns   (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_check_columns    (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *table_catalog, const GValue *table_schema, 
+					  const GValue *table_name, const GValue *constraint_name);
+
+/* _triggers */
+gboolean _gda_oracle_meta__triggers        (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_triggers         (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *table_catalog, const GValue *table_schema, 
+					  const GValue *table_name);
+
+/* _routines */
+gboolean _gda_oracle_meta__routines       (GdaServerProvider *prov, GdaConnection *cnc, 
+					 GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_routines        (GdaServerProvider *prov, GdaConnection *cnc, 
+					 GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					 const GValue *routine_catalog, const GValue *routine_schema, 
+					 const GValue *routine_name_n);
+
+/* _routine_columns */
+gboolean _gda_oracle_meta__routine_col     (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_routine_col      (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *rout_catalog, const GValue *rout_schema, 
+					  const GValue *rout_name);
+
+/* _parameters */
+gboolean _gda_oracle_meta__routine_par     (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_routine_par      (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *rout_catalog, const GValue *rout_schema, 
+					  const GValue *rout_name);
+
+
+G_END_DECLS
+
+#endif
+
diff --git a/providers/oracle/gda-oracle-parser.c b/providers/oracle/gda-oracle-parser.c
new file mode 100644
index 0000000..0568732
--- /dev/null
+++ b/providers/oracle/gda-oracle-parser.c
@@ -0,0 +1,84 @@
+/* GDA Oracle provider
+ *
+ * Copyright (C) 2008 The GNOME Foundation
+ *
+ * AUTHORS:
+ *      TO_ADD: your name and email
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "gda-oracle-parser.h"
+#include "oracle_token_types.h"
+#include <string.h>
+
+/* 
+ * Main static functions 
+ */
+static void gda_oracle_parser_class_init (GdaOracleParserClass *klass);
+static void gda_oracle_parser_init (GdaOracleParser *stmt);
+
+GType
+gda_oracle_parser_get_type (void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY (type == 0)) {
+		static GStaticMutex registering = G_STATIC_MUTEX_INIT;
+		static const GTypeInfo info = {
+			sizeof (GdaOracleParserClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) gda_oracle_parser_class_init,
+			NULL,
+			NULL,
+			sizeof (GdaOracleParser),
+			0,
+			(GInstanceInitFunc) gda_oracle_parser_init
+		};
+		
+		g_static_mutex_lock (&registering);
+		if (type == 0)
+			type = g_type_register_static (GDA_TYPE_SQL_PARSER, "GdaOracleParser", &info, 0);
+		g_static_mutex_unlock (&registering);
+	}
+	return type;
+}
+
+/*
+ * The interface to the LEMON-generated parser
+ */
+void *gda_lemon_oracle_parserAlloc (void*(*)(size_t));
+void gda_lemon_oracle_parserFree (void*, void(*)(void*));
+void gda_lemon_oracle_parserTrace (void*, char *);
+void gda_lemon_oracle_parser (void*, int, GValue *, GdaSqlParserIface *);
+
+static void
+gda_oracle_parser_class_init (GdaOracleParserClass * klass)
+{
+	GdaSqlParserClass *pclass = GDA_SQL_PARSER_CLASS (klass);
+
+	pclass->parser_alloc = gda_lemon_oracle_parserAlloc;
+	pclass->parser_free = gda_lemon_oracle_parserFree;
+	pclass->parser_trace = gda_lemon_oracle_parserTrace;
+	pclass->parser_parse = gda_lemon_oracle_parser;
+	pclass->parser_tokens_trans = oracle_parser_tokens;
+}
+
+static void
+gda_oracle_parser_init (GdaOracleParser *parser)
+{
+}
diff --git a/providers/oracle/gda-oracle-parser.h b/providers/oracle/gda-oracle-parser.h
new file mode 100644
index 0000000..088bc49
--- /dev/null
+++ b/providers/oracle/gda-oracle-parser.h
@@ -0,0 +1,59 @@
+/* GDA Oracle provider
+ *
+ * Copyright (C) 2008 The GNOME Foundation
+ *
+ * AUTHORS:
+ *      TO_ADD: your name and email
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __GDA_ORACLE_PARSER_H_
+#define __GDA_ORACLE_PARSER_H_
+
+#include <sql-parser/gda-sql-parser.h>
+
+G_BEGIN_DECLS
+
+#define GDA_TYPE_ORACLE_PARSER            (gda_oracle_parser_get_type())
+#define GDA_ORACLE_PARSER(obj)            (G_TYPE_CHECK_INSTANCE_CAST (obj, GDA_TYPE_ORACLE_PARSER, GdaOracleParser))
+#define GDA_ORACLE_PARSER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST (klass, GDA_TYPE_ORACLE_PARSER, GdaOracleParserClass))
+#define GDA_IS_ORACLE_PARSER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE (obj, GDA_TYPE_ORACLE_PARSER))
+#define GDA_IS_ORACLE_PARSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDA_TYPE_ORACLE_PARSER))
+
+typedef struct _GdaOracleParser GdaOracleParser;
+typedef struct _GdaOracleParserClass GdaOracleParserClass;
+typedef struct _GdaOracleParserPrivate GdaOracleParserPrivate;
+
+/* struct for the object's data */
+struct _GdaOracleParser
+{
+	GdaSqlParser          object;
+	GdaOracleParserPrivate *priv;
+};
+
+/* struct for the object's class */
+struct _GdaOracleParserClass
+{
+	GdaSqlParserClass      parent_class;
+};
+
+GType gda_oracle_parser_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif
diff --git a/providers/oracle/gda-oracle-provider.c b/providers/oracle/gda-oracle-provider.c
index a2cf04f..296dc1a 100644
--- a/providers/oracle/gda-oracle-provider.c
+++ b/providers/oracle/gda-oracle-provider.c
@@ -1,11 +1,8 @@
 /* GDA Oracle provider
- * Copyright (C) 2000 - 2007 The GNOME Foundation.
+ * Copyright (C) 2008 The GNOME Foundation.
  *
  * AUTHORS:
- *	Rodrigo Moya <rodrigo gnome-db org>
- *	Tim Coleman <tim timcoleman com>
- *      Vivien Malerba <malerba gnome-db org>
- *      Bas Driessen <bas driessen xobas com>
+ *      TO_ADD: your name and email
  *
  * This Library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public License as
@@ -23,182 +20,251 @@
  * Boston, MA 02111-1307, USA.
  */
 
-#include <libgda/gda-row.h>
-#include <libgda/gda-query.h>
-#include <libgda/gda-parameter-list.h>
-#include <libgda/gda-parameter-util.h>
-#include <libgda/gda-data-model-array.h>
-#include <libgda/gda-data-model-private.h>
-#include <libgda/gda-server-provider-extra.h>
-#include <libgda/gda-renderer.h>
-#include <glib/gi18n-lib.h>
+#include <stdio.h>
 #include <stdlib.h>
+#include <errno.h>
 #include <string.h>
+#include <glib/gi18n-lib.h>
+#include <glib/gstdio.h>
+#include <libgda/libgda.h>
+#include <libgda/gda-data-model-private.h>
+#include <libgda/gda-server-provider-extra.h>
+#include <libgda/binreloc/gda-binreloc.h>
+#include <libgda/gda-statement-extra.h>
+#include <sql-parser/gda-sql-parser.h>
 #include "gda-oracle.h"
 #include "gda-oracle-provider.h"
 #include "gda-oracle-recordset.h"
 #include "gda-oracle-ddl.h"
-#include <libgda/gda-connection-private.h>
-
-#include <libgda/handlers/gda-handler-numerical.h>
-#include <libgda/handlers/gda-handler-bin.h>
-#include <libgda/handlers/gda-handler-boolean.h>
-#include <libgda/handlers/gda-handler-time.h>
-#include <libgda/handlers/gda-handler-string.h>
-#include <libgda/handlers/gda-handler-type.h>
-
-#include <libgda/sql-parser/gda-sql-parser.h>
-#include <libgda/sql-delimiter/gda-sql-delimiter.h>
-#include <libgda/binreloc/gda-binreloc.h>
-
-#define PARENT_TYPE GDA_TYPE_SERVER_PROVIDER
+#include "gda-oracle-meta.h"
+#define _GDA_PSTMT(x) ((GdaPStmt*)(x))
 
+/*
+ * GObject methods
+ */
 static void gda_oracle_provider_class_init (GdaOracleProviderClass *klass);
 static void gda_oracle_provider_init       (GdaOracleProvider *provider,
-					    GdaOracleProviderClass *klass);
-static void gda_oracle_provider_finalize   (GObject *object);
-
-static const gchar *gda_oracle_provider_get_version (GdaServerProvider *provider);
-static gboolean gda_oracle_provider_open_connection (GdaServerProvider *provider,
-						     GdaConnection *cnc,
-						     GdaQuarkList *params,
-						     const gchar *username,
-						     const gchar *password);
-static gboolean gda_oracle_provider_close_connection (GdaServerProvider *provider,
-						      GdaConnection *cnc);
-static const gchar *gda_oracle_provider_get_server_version (GdaServerProvider *provider,
-							    GdaConnection *cnc);
-static const gchar *gda_oracle_provider_get_database (GdaServerProvider *provider,
-						      GdaConnection *cnc);
-static gboolean gda_oracle_provider_supports_operation (GdaServerProvider *provider, GdaConnection *cnc,
-							GdaServerOperationType type, GdaParameterList *options);
+					  GdaOracleProviderClass *klass);
+static GObjectClass *parent_class = NULL;
+
+/*
+ * GdaServerProvider's virtual methods
+ */
+/* connection management */
+static gboolean            gda_oracle_provider_open_connection (GdaServerProvider *provider, GdaConnection *cnc,
+							      GdaQuarkList *params, GdaQuarkList *auth,
+							      guint *task_id, GdaServerProviderAsyncCallback async_cb, gpointer cb_data);
+static gboolean            gda_oracle_provider_close_connection (GdaServerProvider *provider, GdaConnection *cnc);
+static const gchar        *gda_oracle_provider_get_server_version (GdaServerProvider *provider, GdaConnection *cnc);
+static const gchar        *gda_oracle_provider_get_database (GdaServerProvider *provider, GdaConnection *cnc);
+
+/* DDL operations */
+static gboolean            gda_oracle_provider_supports_operation (GdaServerProvider *provider, GdaConnection *cnc,
+								 GdaServerOperationType type, GdaSet *options);
 static GdaServerOperation *gda_oracle_provider_create_operation (GdaServerProvider *provider, GdaConnection *cnc,
-								 GdaServerOperationType type,
-								 GdaParameterList *options, GError **error);
-static gchar *gda_oracle_provider_render_operation (GdaServerProvider *provider, GdaConnection *cnc,
-					            GdaServerOperation *op, GError **error);
-static gboolean gda_oracle_provider_perform_operation (GdaServerProvider *provider, GdaConnection *cnc,
-                                                       GdaServerOperation *op, GError **error);
-static GList *gda_oracle_provider_execute_command (GdaServerProvider *provider,
-						   GdaConnection *cnc,
-						   GdaCommand *cmd,
-						   GdaParameterList *params);
-static GdaObject *gda_oracle_provider_execute_query (GdaServerProvider *provider,
-						     GdaConnection *cnc,
-						     GdaQuery *query,
-						     GdaParameterList *params);
-
-static gboolean gda_oracle_provider_begin_transaction (GdaServerProvider *provider,
-						       GdaConnection *cnc,
-						       const gchar *name, GdaTransactionIsolation level,
-						       GError **error);
-static gboolean gda_oracle_provider_commit_transaction (GdaServerProvider *provider,
-							GdaConnection *cnc,
-							const gchar *name, GError **error);
-static gboolean gda_oracle_provider_rollback_transaction (GdaServerProvider *provider,
-							  GdaConnection *cnc,
-							  const gchar *name, GError **error);
-static gboolean gda_oracle_provider_supports (GdaServerProvider *provider,
-					      GdaConnection *cnc,
-					      GdaConnectionFeature feature);
-
-static GdaServerProviderInfo *gda_oracle_provider_get_info (GdaServerProvider *provider,
-							    GdaConnection *cnc);
-
-static GdaDataHandler *gda_oracle_provider_get_data_handler (GdaServerProvider *provider,
-							     GdaConnection *cnc,
-							     GType g_type,
-							     const gchar *dbms_type);
-
-static GdaDataModel *gda_oracle_provider_get_schema (GdaServerProvider *provider,
-						     GdaConnection *cnc,
-						     GdaConnectionSchema schema,
-						     GdaParameterList *params);
-
-static const gchar* gda_oracle_provider_get_default_dbms_type (GdaServerProvider *provider,
-							      GdaConnection *cnc,
-							      GType type);
-
-static GdaSqlParser *gda_oracle_provider_create_parser (GdaServerProvider *provider, GdaConnection *cnc);
-
-static GList *process_sql_commands (GList *reclist, GdaConnection *cnc, 
-				    const gchar *sql, GdaParameterList *params, 
-				    GdaCommandOptions options, GArray *col_size_array);
+							       GdaServerOperationType type,
+							       GdaSet *options, GError **error);
+static gchar              *gda_oracle_provider_render_operation (GdaServerProvider *provider, GdaConnection *cnc,
+							       GdaServerOperation *op, GError **error);
+
+static gboolean            gda_oracle_provider_perform_operation (GdaServerProvider *provider, GdaConnection *cnc,
+								GdaServerOperation *op, guint *task_id, 
+								GdaServerProviderAsyncCallback async_cb, gpointer cb_data,
+								GError **error);
+/* transactions */
+static gboolean            gda_oracle_provider_begin_transaction (GdaServerProvider *provider, GdaConnection *cnc,
+								const gchar *name, GdaTransactionIsolation level, GError **error);
+static gboolean            gda_oracle_provider_commit_transaction (GdaServerProvider *provider, GdaConnection *cnc,
+								 const gchar *name, GError **error);
+static gboolean            gda_oracle_provider_rollback_transaction (GdaServerProvider *provider, GdaConnection * cnc,
+								   const gchar *name, GError **error);
+static gboolean            gda_oracle_provider_add_savepoint (GdaServerProvider *provider, GdaConnection *cnc,
+							    const gchar *name, GError **error);
+static gboolean            gda_oracle_provider_rollback_savepoint (GdaServerProvider *provider, GdaConnection *cnc,
+								 const gchar *name, GError **error);
+static gboolean            gda_oracle_provider_delete_savepoint (GdaServerProvider *provider, GdaConnection *cnc,
+							       const gchar *name, GError **error);
+
+/* information retreival */
+static const gchar        *gda_oracle_provider_get_version (GdaServerProvider *provider);
+static gboolean            gda_oracle_provider_supports_feature (GdaServerProvider *provider, GdaConnection *cnc,
+							       GdaConnectionFeature feature);
+
+static const gchar        *gda_oracle_provider_get_name (GdaServerProvider *provider);
+
+static GdaDataHandler     *gda_oracle_provider_get_data_handler (GdaServerProvider *provider, GdaConnection *cnc,
+							       GType g_type, const gchar *dbms_type);
+
+static const gchar*        gda_oracle_provider_get_default_dbms_type (GdaServerProvider *provider, GdaConnection *cnc,
+								    GType type);
+/* statements */
+static GdaSqlParser        *gda_oracle_provider_create_parser (GdaServerProvider *provider, GdaConnection *cnc);
+static gchar               *gda_oracle_provider_statement_to_sql  (GdaServerProvider *provider, GdaConnection *cnc,
+								 GdaStatement *stmt, GdaSet *params, 
+								 GdaStatementSqlFlag flags,
+								 GSList **params_used, GError **error);
+static gboolean             gda_oracle_provider_statement_prepare (GdaServerProvider *provider, GdaConnection *cnc,
+								 GdaStatement *stmt, GError **error);
+static GObject             *gda_oracle_provider_statement_execute (GdaServerProvider *provider, GdaConnection *cnc,
+								 GdaStatement *stmt, GdaSet *params,
+								 GdaStatementModelUsage model_usage, 
+								 GType *col_types, GdaSet **last_inserted_row, 
+								 guint *task_id, GdaServerProviderExecCallback async_cb, 
+								 gpointer cb_data, GError **error);
+
+/* distributed transactions */
+static gboolean gda_oracle_provider_xa_start    (GdaServerProvider *provider, GdaConnection *cnc, 
+						   const GdaXaTransactionId *xid, GError **error);
+
+static gboolean gda_oracle_provider_xa_end      (GdaServerProvider *provider, GdaConnection *cnc, 
+						   const GdaXaTransactionId *xid, GError **error);
+static gboolean gda_oracle_provider_xa_prepare  (GdaServerProvider *provider, GdaConnection *cnc, 
+						   const GdaXaTransactionId *xid, GError **error);
+
+static gboolean gda_oracle_provider_xa_commit   (GdaServerProvider *provider, GdaConnection *cnc, 
+						   const GdaXaTransactionId *xid, GError **error);
+static gboolean gda_oracle_provider_xa_rollback (GdaServerProvider *provider, GdaConnection *cnc, 
+						   const GdaXaTransactionId *xid, GError **error);
+
+static GList   *gda_oracle_provider_xa_recover  (GdaServerProvider *provider, GdaConnection *cnc, 
+						   GError **error);
 
-static GObjectClass *parent_class = NULL;
+/* 
+ * private connection data destroy 
+ */
+static void gda_oracle_free_cnc_data (OracleConnectionData *cdata);
 
-typedef struct {
-	gboolean primary_key;
-	gboolean unique;
-	gchar *references;
-} GdaOracleIndexData;
 
 /*
- * GdaOracleProvider class implementation
+ * Prepared internal statements
+ * TO_ADD: any prepared statement to be used internally by the provider should be
+ *         declared here, as constants and as SQL statements
  */
+static GdaStatement **internal_stmt;
 
+typedef enum {
+	INTERNAL_STMT1
+} InternalStatementItem;
+
+static gchar *internal_sql[] = {
+	"SQL for INTERNAL_STMT1"
+};
+
+/*
+ * GdaOracleProvider class implementation
+ */
 static void
 gda_oracle_provider_class_init (GdaOracleProviderClass *klass)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 	GdaServerProviderClass *provider_class = GDA_SERVER_PROVIDER_CLASS (klass);
 
 	parent_class = g_type_class_peek_parent (klass);
 
-	object_class->finalize = gda_oracle_provider_finalize;
-
 	provider_class->get_version = gda_oracle_provider_get_version;
 	provider_class->get_server_version = gda_oracle_provider_get_server_version;
-	provider_class->get_info = gda_oracle_provider_get_info;
-	provider_class->supports_feature = gda_oracle_provider_supports;
-	provider_class->get_schema = gda_oracle_provider_get_schema;
+	provider_class->get_name = gda_oracle_provider_get_name;
+	provider_class->supports_feature = gda_oracle_provider_supports_feature;
 
 	provider_class->get_data_handler = gda_oracle_provider_get_data_handler;
-	provider_class->string_to_value = NULL;
 	provider_class->get_def_dbms_type = gda_oracle_provider_get_default_dbms_type;
 
-	provider_class->create_connection = NULL;
 	provider_class->open_connection = gda_oracle_provider_open_connection;
 	provider_class->close_connection = gda_oracle_provider_close_connection;
 	provider_class->get_database = gda_oracle_provider_get_database;
-	provider_class->change_database = NULL;
 
 	provider_class->supports_operation = gda_oracle_provider_supports_operation;
         provider_class->create_operation = gda_oracle_provider_create_operation;
         provider_class->render_operation = gda_oracle_provider_render_operation;
         provider_class->perform_operation = gda_oracle_provider_perform_operation;
 
-	provider_class->execute_command = gda_oracle_provider_execute_command;
-	provider_class->execute_query = gda_oracle_provider_execute_query;
-	provider_class->get_last_insert_id = NULL;
-
 	provider_class->begin_transaction = gda_oracle_provider_begin_transaction;
 	provider_class->commit_transaction = gda_oracle_provider_commit_transaction;
 	provider_class->rollback_transaction = gda_oracle_provider_rollback_transaction;
-	provider_class->add_savepoint = NULL;
-	provider_class->rollback_savepoint = NULL;
-	provider_class->delete_savepoint = NULL;
+	provider_class->add_savepoint = gda_oracle_provider_add_savepoint;
+        provider_class->rollback_savepoint = gda_oracle_provider_rollback_savepoint;
+        provider_class->delete_savepoint = gda_oracle_provider_delete_savepoint;
 
 	provider_class->create_parser = gda_oracle_provider_create_parser;
-        provider_class->statement_to_sql = NULL;
-        provider_class->statement_prepare = NULL;
-        provider_class->statement_execute = NULL;
-}
+	provider_class->statement_to_sql = gda_oracle_provider_statement_to_sql;
+	provider_class->statement_prepare = gda_oracle_provider_statement_prepare;
+	provider_class->statement_execute = gda_oracle_provider_statement_execute;
 
-static void
-gda_oracle_provider_init (GdaOracleProvider *myprv, GdaOracleProviderClass *klass)
-{
+	provider_class->is_busy = NULL;
+	provider_class->cancel = NULL;
+	provider_class->create_connection = NULL;
+
+	memset (&(provider_class->meta_funcs), 0, sizeof (GdaServerProviderMeta));
+	provider_class->meta_funcs._info = _gda_oracle_meta__info;
+	provider_class->meta_funcs._btypes = _gda_oracle_meta__btypes;
+	provider_class->meta_funcs._udt = _gda_oracle_meta__udt;
+	provider_class->meta_funcs.udt = _gda_oracle_meta_udt;
+	provider_class->meta_funcs._udt_cols = _gda_oracle_meta__udt_cols;
+	provider_class->meta_funcs.udt_cols = _gda_oracle_meta_udt_cols;
+	provider_class->meta_funcs._enums = _gda_oracle_meta__enums;
+	provider_class->meta_funcs.enums = _gda_oracle_meta_enums;
+	provider_class->meta_funcs._domains = _gda_oracle_meta__domains;
+	provider_class->meta_funcs.domains = _gda_oracle_meta_domains;
+	provider_class->meta_funcs._constraints_dom = _gda_oracle_meta__constraints_dom;
+	provider_class->meta_funcs.constraints_dom = _gda_oracle_meta_constraints_dom;
+	provider_class->meta_funcs._el_types = _gda_oracle_meta__el_types;
+	provider_class->meta_funcs.el_types = _gda_oracle_meta_el_types;
+	provider_class->meta_funcs._collations = _gda_oracle_meta__collations;
+	provider_class->meta_funcs.collations = _gda_oracle_meta_collations;
+	provider_class->meta_funcs._character_sets = _gda_oracle_meta__character_sets;
+	provider_class->meta_funcs.character_sets = _gda_oracle_meta_character_sets;
+	provider_class->meta_funcs._schemata = _gda_oracle_meta__schemata;
+	provider_class->meta_funcs.schemata = _gda_oracle_meta_schemata;
+	provider_class->meta_funcs._tables_views = _gda_oracle_meta__tables_views;
+	provider_class->meta_funcs.tables_views = _gda_oracle_meta_tables_views;
+	provider_class->meta_funcs._columns = _gda_oracle_meta__columns;
+	provider_class->meta_funcs.columns = _gda_oracle_meta_columns;
+	provider_class->meta_funcs._view_cols = _gda_oracle_meta__view_cols;
+	provider_class->meta_funcs.view_cols = _gda_oracle_meta_view_cols;
+	provider_class->meta_funcs._constraints_tab = _gda_oracle_meta__constraints_tab;
+	provider_class->meta_funcs.constraints_tab = _gda_oracle_meta_constraints_tab;
+	provider_class->meta_funcs._constraints_ref = _gda_oracle_meta__constraints_ref;
+	provider_class->meta_funcs.constraints_ref = _gda_oracle_meta_constraints_ref;
+	provider_class->meta_funcs._key_columns = _gda_oracle_meta__key_columns;
+	provider_class->meta_funcs.key_columns = _gda_oracle_meta_key_columns;
+	provider_class->meta_funcs._check_columns = _gda_oracle_meta__check_columns;
+	provider_class->meta_funcs.check_columns = _gda_oracle_meta_check_columns;
+	provider_class->meta_funcs._triggers = _gda_oracle_meta__triggers;
+	provider_class->meta_funcs.triggers = _gda_oracle_meta_triggers;
+	provider_class->meta_funcs._routines = _gda_oracle_meta__routines;
+	provider_class->meta_funcs.routines = _gda_oracle_meta_routines;
+	provider_class->meta_funcs._routine_col = _gda_oracle_meta__routine_col;
+	provider_class->meta_funcs.routine_col = _gda_oracle_meta_routine_col;
+	provider_class->meta_funcs._routine_par = _gda_oracle_meta__routine_par;
+	provider_class->meta_funcs.routine_par = _gda_oracle_meta_routine_par;
+
+	/* distributed transactions: if not supported, then provider_class->xa_funcs should be set to NULL */
+	provider_class->xa_funcs = g_new0 (GdaServerProviderXa, 1);
+	provider_class->xa_funcs->xa_start = gda_oracle_provider_xa_start;
+	provider_class->xa_funcs->xa_end = gda_oracle_provider_xa_end;
+	provider_class->xa_funcs->xa_prepare = gda_oracle_provider_xa_prepare;
+	provider_class->xa_funcs->xa_commit = gda_oracle_provider_xa_commit;
+	provider_class->xa_funcs->xa_rollback = gda_oracle_provider_xa_rollback;
+	provider_class->xa_funcs->xa_recover = gda_oracle_provider_xa_recover;
 }
 
 static void
-gda_oracle_provider_finalize (GObject *object)
+gda_oracle_provider_init (GdaOracleProvider *oracle_prv, GdaOracleProviderClass *klass)
 {
-	GdaOracleProvider *myprv = (GdaOracleProvider *) object;
+	InternalStatementItem i;
+	GdaSqlParser *parser;
+
+	parser = gda_server_provider_internal_get_parser ((GdaServerProvider*) oracle_prv);
+	internal_stmt = g_new0 (GdaStatement *, sizeof (internal_sql) / sizeof (gchar*));
+	for (i = INTERNAL_STMT1; i < sizeof (internal_sql) / sizeof (gchar*); i++) {
+		internal_stmt[i] = gda_sql_parser_parse_string (parser, internal_sql[i], NULL, NULL);
+		if (!internal_stmt[i]) 
+			g_error ("Could not parse internal statement: %s\n", internal_sql[i]);
+	}
 
-	g_return_if_fail (GDA_IS_ORACLE_PROVIDER (myprv));
+	/* meta data init */
+	_gda_oracle_provider_meta_init ((GdaServerProvider*) oracle_prv);
 
-	/* chain to parent class */
-	parent_class->finalize (object);
+	/* TO_ADD: any other provider's init should be added here */
 }
 
 GType
@@ -207,6 +273,7 @@ gda_oracle_provider_get_type (void)
 	static GType type = 0;
 
 	if (G_UNLIKELY (type == 0)) {
+		static GStaticMutex registering = G_STATIC_MUTEX_INIT;
 		static GTypeInfo info = {
 			sizeof (GdaOracleProviderClass),
 			(GBaseInitFunc) NULL,
@@ -217,2018 +284,1051 @@ gda_oracle_provider_get_type (void)
 			0,
 			(GInstanceInitFunc) gda_oracle_provider_init
 		};
-		type = g_type_register_static (PARENT_TYPE, "GdaOracleProvider", &info, 0);
+		g_static_mutex_lock (&registering);
+		if (type == 0)
+			type = g_type_register_static (GDA_TYPE_SERVER_PROVIDER, "GdaOracleProvider", &info, 0);
+		g_static_mutex_unlock (&registering);
 	}
 
 	return type;
 }
 
-GdaServerProvider *
-gda_oracle_provider_new (void)
-{
-	GdaOracleProvider *provider;
 
-	provider = g_object_new (gda_oracle_provider_get_type (), NULL);
-	return GDA_SERVER_PROVIDER (provider);
+/*
+ * Get provider name request
+ */
+static const gchar *
+gda_oracle_provider_get_name (GdaServerProvider *provider)
+{
+	return ORACLE_PROVIDER_NAME;
 }
 
-/* get_version handler for the GdaOracleProvider class */
+/* 
+ * Get provider's version, no need to change this
+ */
 static const gchar *
 gda_oracle_provider_get_version (GdaServerProvider *provider)
 {
 	return PACKAGE_VERSION;
 }
 
-/* open_connection handler for the GdaOracleProvider class */
+/* 
+ * Open connection request
+ *
+ * In this function, the following _must_ be done:
+ *   - check for the presence and validify of the parameters required to actually open a connection,
+ *     using @params
+ *   - open the real connection to the database using the parameters previously checked
+ *   - create a OracleConnectionData structure and associate it to @cnc
+ *
+ * Returns: TRUE if no error occurred, or FALSE otherwise (and an ERROR gonnection event must be added to @cnc)
+ */
 static gboolean
-gda_oracle_provider_open_connection (GdaServerProvider *provider,
-				     GdaConnection *cnc,
-				     GdaQuarkList *params,
-				     const gchar *username,
-				     const gchar *password)
+gda_oracle_provider_open_connection (GdaServerProvider *provider, GdaConnection *cnc,
+				   GdaQuarkList *params, GdaQuarkList *auth,
+				   guint *task_id, GdaServerProviderAsyncCallback async_cb, gpointer cb_data)
 {
-        const gchar *tnsname;
-	gint  result;
-
-        GdaOracleProvider *ora_prv = (GdaOracleProvider *) provider;
-	GdaOracleConnectionData *priv_data;
-
-	g_return_val_if_fail (GDA_IS_ORACLE_PROVIDER (ora_prv), FALSE);
+	g_return_val_if_fail (GDA_IS_ORACLE_PROVIDER (provider), FALSE);
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
 
-	/* check we have a TNS name to connect to */
-
-	if ((tnsname = gda_quark_list_find (params, "TNSNAME")) == NULL) {
-		gda_connection_add_event_string (cnc, 
-						 _("No TNS name supplied"));
-		return FALSE;
+	/* If asynchronous connection opening is not supported, then exit now */
+	if (async_cb) {
+		gda_connection_add_event_string (cnc, _("Provider does not support asynchronous connection open"));
+                return FALSE;
 	}
 
-	priv_data = g_new0 (GdaOracleConnectionData, 1);
-
-        /* initialize Oracle */
-	result = OCIInitialize ((ub4) OCI_THREADED,
-				(dvoid *) 0,
-				(dvoid * (*)(dvoid *, size_t)) 0,
-				(dvoid * (*)(dvoid *, dvoid *, size_t)) 0,
-				(void (*)(dvoid *, dvoid *)) 0);
-
-	if (result != OCI_SUCCESS) {
-		gda_connection_add_event_string (cnc, 
-						 _("Could not initialize Oracle"));
+	/* Check for connection parameters */
+	/* TO_ADD: your own connection parameters */
+	const gchar *db_name;
+	db_name = gda_quark_list_find (params, "DB_NAME");
+	if (!db_name) {
+		gda_connection_add_event_string (cnc,
+						 _("The connection string must contain the DB_NAME values"));
 		return FALSE;
 	}
 	
-	/* initialize the Oracle environment */
-	result = OCIEnvInit ((OCIEnv **) & priv_data->henv, 
-			     (ub4) OCI_DEFAULT, 
-			     (size_t) 0, 
-			     (dvoid **) 0);
-	if (result != OCI_SUCCESS) {
-		gda_connection_add_event_string (cnc, 
-						 _("Could not initialize the Oracle environment"));
-		return FALSE;
-	}
-
-	/* create the service context */
-	result = OCIHandleAlloc ((dvoid *) priv_data->henv,
-				 (dvoid **) &priv_data->hservice,
-				 (ub4) OCI_HTYPE_SVCCTX,
-				 (size_t) 0,
-				 (dvoid **) 0);
-	if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ENV,
-				     _("Could not allocate the Oracle service handle")))
-		return FALSE;
-
-	/* create the error handle */
-	result = OCIHandleAlloc ((dvoid *) priv_data->henv, 
-				 (dvoid **) &(priv_data->herr), 
-				 (ub4) OCI_HTYPE_ERROR, 
-				 (size_t) 0, 
-				 (dvoid **) 0);
-	if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ENV,
-				     _("Could not allocate the Oracle error handle"))) {
-		OCIHandleFree ((dvoid *) priv_data->hservice, OCI_HTYPE_SVCCTX);
-		return FALSE;
-	}
-			
-	/* we use the Multiple Sessions/Connections OCI paradigm for this server */
-	result = OCIHandleAlloc ((dvoid *) priv_data->henv,
-				 (dvoid **) & priv_data->hserver,
-				 (ub4) OCI_HTYPE_SERVER, 
-				 (size_t) 0,
-				 (dvoid **) 0);
-	if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ENV,
-				     _("Could not allocate the Oracle server handle"))) {
-		OCIHandleFree ((dvoid *) priv_data->herr, OCI_HTYPE_ERROR);
-		OCIHandleFree ((dvoid *) priv_data->hservice, OCI_HTYPE_SVCCTX);
-		return FALSE;
-	}
+	/* open the real connection to the database */
+	/* TO_ADD: C API specific function calls;
+	 * if it fails, add a connection event and return FALSE */
+	TO_IMPLEMENT;
 
-	/* create the session handle */
-	result = OCIHandleAlloc ((dvoid *) priv_data->henv,
-				 (dvoid **) &priv_data->hsession,
-				 (ub4) OCI_HTYPE_SESSION,
-				 (size_t) 0,
-				 (dvoid **) 0);
-	if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ENV,
-				     _("Could not allocate the Oracle session handle"))) {
-		OCIHandleFree ((dvoid *) priv_data->hserver, OCI_HTYPE_SERVER);
-		OCIHandleFree ((dvoid *) priv_data->herr, OCI_HTYPE_ERROR);
-		OCIHandleFree ((dvoid *) priv_data->hservice, OCI_HTYPE_SVCCTX);
-		return FALSE;
-	}
-
-	/* if the username isn't provided, try to find it in the DSN */
-
-	if (username == NULL || *username == '\0') {
-		username = gda_quark_list_find (params, "USER");
-		if (username == NULL)
-			username="";
-	}
+	/* Create a new instance of the provider specific data associated to a connection (OracleConnectionData),
+	 * and set its contents */
+	OracleConnectionData *cdata;
+	cdata = g_new0 (OracleConnectionData, 1);
+	gda_connection_internal_set_provider_data (cnc, cdata, (GDestroyNotify) gda_oracle_free_cnc_data);
+	TO_IMPLEMENT; /* cdata->... = ... */
 
-	/* if the password isn't provided, try to find it in the DSN */
-	if (password == NULL || *password == '\0') {
-		password = gda_quark_list_find (params, "PASSWORD");
-		if (password == NULL)
-			password="";
-	}
-
-        /* attach to Oracle server */
-	result = OCIServerAttach (priv_data->hserver,
-				  priv_data->herr,
-				  (text *) tnsname,
-				  (ub4) strlen (tnsname),
-				  OCI_DEFAULT);
-	if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-				     _("Could not attach to the Oracle server"))) {
-		OCIHandleFree ((dvoid *) priv_data->hsession, OCI_HTYPE_SESSION);
-		OCIHandleFree ((dvoid *) priv_data->hserver, OCI_HTYPE_SERVER);
-		OCIHandleFree ((dvoid *) priv_data->herr, OCI_HTYPE_ERROR);
-		OCIHandleFree ((dvoid *) priv_data->hservice, OCI_HTYPE_SVCCTX);
-		return FALSE;
-	}
-
-	/* set the server attribute in the service context */
-	result = OCIAttrSet ((dvoid *) priv_data->hservice, 
-			     (ub4) OCI_HTYPE_SVCCTX,
-			     (dvoid *) priv_data->hserver, 
-			     (ub4) 0,
-			     (ub4) OCI_ATTR_SERVER, 
-			     priv_data->herr);
-	if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-				     _("Could not set the Oracle server attribute in the service context"))) {
-		OCIHandleFree ((dvoid *) priv_data->hsession, OCI_HTYPE_SESSION);
-		OCIHandleFree ((dvoid *) priv_data->hserver, OCI_HTYPE_SERVER);
-		OCIHandleFree ((dvoid *) priv_data->herr, OCI_HTYPE_ERROR);
-		OCIHandleFree ((dvoid *) priv_data->hservice, OCI_HTYPE_SVCCTX);
-		return FALSE;
-	}
-	
-	/* set the username attribute */
-	result = OCIAttrSet ((dvoid *) priv_data->hsession, 
-			     (ub4) OCI_HTYPE_SESSION, 
-			     (dvoid *) username,
-			     (ub4) strlen (username),
-			     (ub4) OCI_ATTR_USERNAME,
-			     priv_data->herr);
-	if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-				     _("Could not set the Oracle username attribute"))) {
-		OCIHandleFree ((dvoid *) priv_data->hsession, OCI_HTYPE_SESSION);
-		OCIHandleFree ((dvoid *) priv_data->hserver, OCI_HTYPE_SERVER);
-		OCIHandleFree ((dvoid *) priv_data->herr, OCI_HTYPE_ERROR);
-		OCIHandleFree ((dvoid *) priv_data->hservice, OCI_HTYPE_SVCCTX);
-		return FALSE;
-	}
-
-	/* set the password attribute */
-	result = OCIAttrSet ((dvoid *) priv_data->hsession, 
-			     (ub4) OCI_HTYPE_SESSION, 
-			     (dvoid *) password,
-			     (ub4) strlen (password), 
-			     (ub4) OCI_ATTR_PASSWORD,
-			     priv_data->herr);
-	if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-				     _("Could not set the Oracle password attribute"))) {
-		OCIHandleFree ((dvoid *) priv_data->hsession, OCI_HTYPE_SESSION);
-		OCIHandleFree ((dvoid *) priv_data->hserver, OCI_HTYPE_SERVER);
-		OCIHandleFree ((dvoid *) priv_data->herr, OCI_HTYPE_ERROR);
-		OCIHandleFree ((dvoid *) priv_data->hservice, OCI_HTYPE_SVCCTX);
-		return FALSE;
-	}
-
-	/* begin the session */
-	result = OCISessionBegin (priv_data->hservice,
-				  priv_data->herr,
-				  priv_data->hsession,
-				  (ub4) OCI_CRED_RDBMS,
-				  (ub4) OCI_DEFAULT);
-	if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-				     _("Could not begin the Oracle session"))) {
-		OCIServerDetach (priv_data->hserver, priv_data->herr, OCI_DEFAULT);
-		OCIHandleFree ((dvoid *) priv_data->hsession, OCI_HTYPE_SESSION);
-		OCIHandleFree ((dvoid *) priv_data->hserver, OCI_HTYPE_SERVER);
-		OCIHandleFree ((dvoid *) priv_data->herr, OCI_HTYPE_ERROR);
-		OCIHandleFree ((dvoid *) priv_data->hservice, OCI_HTYPE_SVCCTX);
-		priv_data->hsession = NULL;
-		return FALSE;
-	}
-
-	/* set the session attribute in the service context */
-	result = OCIAttrSet ((dvoid *) priv_data->hservice,
-			     (ub4) OCI_HTYPE_SVCCTX,
-			     (dvoid *) priv_data->hsession,
-			     (ub4) 0, 
-			     (ub4) OCI_ATTR_SESSION,
-			     priv_data->herr);
-	if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-				     _("Could not set the Oracle session attribute in the service context"))) {
-		OCIServerDetach (priv_data->hserver, priv_data->herr, OCI_DEFAULT);
-		OCIHandleFree ((dvoid *) priv_data->hsession, OCI_HTYPE_SESSION);
-		OCIHandleFree ((dvoid *) priv_data->hserver, OCI_HTYPE_SERVER);
-		OCIHandleFree ((dvoid *) priv_data->herr, OCI_HTYPE_ERROR);
-		OCIHandleFree ((dvoid *) priv_data->hservice, OCI_HTYPE_SVCCTX);
-		return FALSE;
-	}
-
-	priv_data->schema = g_ascii_strup (username, -1);
-	
-	/* attach the oracle connection data to the gda connection object */
-	g_object_set_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE, priv_data);
-
-	/* set sessions parameters */
-	GList *reclist;
-
-	reclist = process_sql_commands (NULL, cnc, 
-					"ALTER SESSION SET NLS_DATE_FORMAT = 'MM/DD/YYYY';"
-					"ALTER SESSION SET NLS_NUMERIC_CHARACTERS = \". \";",
-					NULL, GDA_COMMAND_OPTION_STOP_ON_ERRORS, NULL);
-
-	g_list_foreach (reclist, (GFunc) g_object_unref, NULL);
-	g_list_free (reclist);	
+	/* Optionnally set some attributes for the newly opened connection (encoding to UTF-8 for example )*/
+	TO_IMPLEMENT;
 
 	return TRUE;
 }
 
-/* close_connection handler for the GdaOracleProvider class */
+/* 
+ * Close connection request
+ *
+ * In this function, the following _must_ be done:
+ *   - Actually close the connection to the database using @cnc's associated OracleConnectionData structure
+ *   - Free the OracleConnectionData structure and its contents
+ *
+ * Returns: TRUE if no error occurred, or FALSE otherwise (and an ERROR gonnection event must be added to @cnc)
+ */
 static gboolean
 gda_oracle_provider_close_connection (GdaServerProvider *provider, GdaConnection *cnc)
 {
-	GdaOracleConnectionData *priv_data;
-	GdaOracleProvider *ora_prv = (GdaOracleProvider *) provider;
-	gint result;
+	OracleConnectionData *cdata;
 
-	g_return_val_if_fail (GDA_IS_ORACLE_PROVIDER (ora_prv), FALSE);
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
 
-	priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
-	if (!priv_data)
-		return FALSE;
-
-	/* end the session */
-	if ((result =
-	     OCISessionEnd (priv_data->hservice,
-			    priv_data->herr,
-			    priv_data->hsession,
-			    OCI_DEFAULT))) {
-		gda_connection_add_event (cnc, 
-					  gda_oracle_make_error (priv_data->herr, OCI_HTYPE_ERROR, __FILE__, __LINE__));
+	/* Close the connection using the C API */
+	cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
 		return FALSE;
-	}
+	TO_IMPLEMENT;
 
-	/* free all of the handles */
-        if (priv_data->hsession)
-		OCIHandleFree ((dvoid *) priv_data->hsession, OCI_HTYPE_SESSION);
-	if (priv_data->hservice)
-		OCIHandleFree ((dvoid *) priv_data->hservice, OCI_HTYPE_SVCCTX);
-	if (priv_data->hserver)
-		OCIHandleFree ((dvoid *) priv_data->hserver, OCI_HTYPE_SERVER);
-	if (priv_data->herr)
-		OCIHandleFree ((dvoid *) priv_data->herr, OCI_HTYPE_ERROR);
-	if (priv_data->henv)
-		OCIHandleFree ((dvoid *) priv_data->henv, OCI_HTYPE_ENV);
-	if (priv_data->schema)
-		g_free(priv_data->schema);
-
-	g_free (priv_data);
-	g_object_set_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE, NULL);
+	/* Free the OracleConnectionData structure and its contents*/
+	gda_oracle_free_cnc_data (cdata);
+	gda_connection_internal_set_provider_data (cnc, NULL, NULL);
 
 	return TRUE;
 }
 
-/* get_server_version handler for the GdaOracleProvider class */
-static const gchar *
-gda_oracle_provider_get_server_version (GdaServerProvider *provider,
-					GdaConnection *cnc)
-{
-	GdaOracleConnectionData *priv_data;
-	static guchar version[512];
-
-	if (cnc)
-		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-	else
-		return NULL;
-
-	/* Get the OracleConnectionData */
-	priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
-	if (!priv_data) {
-		gda_connection_add_event_string (cnc, _("Invalid Oracle handle"));
-		return NULL;
-	}
-
-	OCIServerVersion (priv_data->hservice, priv_data->herr, version, 255, OCI_HTYPE_SVCCTX);
-
-	return (const gchar *) version;
-}
-
-/* 
- * prepare_oracle_statement prepares the Oracle statement handle for use 
- *
- * Its parameters are the connection object, a list of parameters to be bound,
- * and the SQL statement to be prepared.
- *
- * It's generally good style to name your parameters beginning with a colon (:)
- * i.e. :parameter_name.  This will avoid confusion.
+/*
+ * Server version request
  *
- * IMPORTANT: If you pass in a parameter in this list that isn't in the statement
- * it will still try to perform a bind anyway.
+ * Returns the server version as a string, which should be stored in @cnc's associated OracleConnectionData structure
  */
-static OCIStmt *
-prepare_oracle_statement (GdaConnection *cnc, GdaParameterList *params, gchar *sql)
+static const gchar *
+gda_oracle_provider_get_server_version (GdaServerProvider *provider, GdaConnection *cnc)
 {
-	GdaOracleConnectionData *priv_data;
-	OCIStmt *stmthp = (OCIStmt *) 0;
-	gint result;
-
-	/* Get the OracleConnectionData */
-	priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
-	if (!priv_data) {
-		gda_connection_add_event_string (cnc, _("Invalid Oracle handle"));
-		return NULL;
-	}
+	OracleConnectionData *cdata;
 
-	/* Allocate an oracle statement handle */
-	result = OCIHandleAlloc ((dvoid *) priv_data->henv,
-				 (dvoid **) &stmthp,
-				 (ub4) OCI_HTYPE_STMT,
-				 (size_t) 0,
-				 (dvoid **) 0);
-	if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ENV,
-				     _("Could not allocate the Oracle statement handle")))
-		return NULL;
-	
-	/* Prepare the statement */
-	result = OCIStmtPrepare ((dvoid *) stmthp,
-				 (dvoid *) priv_data->herr,
-				 (text *) sql,
-				 (ub4) strlen(sql),
-				 (ub4) OCI_NTV_SYNTAX,
-				 (ub4) OCI_DEFAULT);
-	if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-				     _("Could not prepare the Oracle statement"))) {
-		OCIHandleFree ((dvoid *) stmthp, OCI_HTYPE_STMT);
-		return NULL;
-	}
+	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
 
-	/* Bind parameters */
-	if (params != NULL) {
-		/* loop through parameters and bind by name */
-		GSList *parm_list = params->parameters;
-
-		for (parm_list = params->parameters; parm_list; parm_list = parm_list->next) {
-			gchar *parm_name = gda_parameter_get_alphanum_name (GDA_PARAMETER (parm_list->data));
-			const GValue *gda_value = gda_parameter_get_value (GDA_PARAMETER (parm_list->data));
-			GdaOracleValue *ora_value = gda_value_to_oracle_value (gda_value);
-			OCIBind *bindpp = (OCIBind *) 0;
-
-			result = OCIBindByName ((dvoid *) stmthp,
-						(OCIBind **) &bindpp,
-						(OCIError *) priv_data->herr,
-						(text *) parm_name,
-						(sb4) strlen (parm_name),
-						(dvoid *) ora_value->value,
-						(sb4) ora_value->defined_size,
-						(ub2) ora_value->sql_type,
-						(dvoid *) &ora_value->indicator,
-						(ub2 *) 0,
-						(ub2) 0,
-						(ub4) 0,
-						(ub4 *) 0,
-						(ub4) OCI_DEFAULT);
-			g_free (parm_name);
-			if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-						     _("Could not bind the Oracle statement parameter"))) {
-				OCIHandleFree ((dvoid *) stmthp, OCI_HTYPE_STMT);
-				return NULL;
-			}
-		}
-	}
-	return stmthp;
+	cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
+		return FALSE;
+	TO_IMPLEMENT;
+	return NULL;
 }
 
 /*
- * executes @stmthp and returns a GdaDataModel or a GdaParameterList
+ * Get database request
  *
- * WARNING: don't use stmthp afterwards.
+ * Returns the database name as a string, which should be stored in @cnc's associated OracleConnectionData structure
  */
-static GdaObject *
-process_oci_statement (OCIStmt *stmthp, const gchar *sql, GdaConnection *cnc, GArray *col_size_array)
-{
-	GdaObject *retval = NULL;
-	gint result;
-	GdaOracleConnectionData *priv_data;
-	GdaConnectionEvent *error = NULL;
-	ub2 stmt_type;
-
-	priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
-	if (!priv_data) {
-		gda_connection_add_event_string (cnc, _("Invalid Oracle handle"));
-		return NULL;
-	}
-	
-	result = OCIAttrGet (stmthp, OCI_HTYPE_STMT,
-			     (dvoid *) &stmt_type, NULL,
-			     OCI_ATTR_STMT_TYPE, priv_data->herr);
-	error = gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-					 _("Could not get the Oracle statement type"));
-	if (!error) {
-		ub4 prefetch = 200;
-		result = OCIAttrSet (stmthp, OCI_HTYPE_STMT,
-				     &prefetch, 0,
-				     OCI_ATTR_PREFETCH_ROWS, priv_data->herr);
-		error = gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-						 _("Could not set the Oracle statement pre-fetch row count"));
-		if (!error) {
-			GdaConnectionEvent *event;
-			event = gda_connection_event_new (GDA_CONNECTION_EVENT_COMMAND);
-			gda_connection_event_set_description (event, sql);
-			gda_connection_add_event (cnc, event);
-
-			result = OCIStmtExecute (priv_data->hservice,
-						 stmthp,
-						 priv_data->herr,
-						 (ub4) ((stmt_type == OCI_STMT_SELECT) ? 0 : 1),
-						 (ub4) 0,
-						 (CONST OCISnapshot *) NULL,
-						 (OCISnapshot *) NULL,
-						 OCI_DEFAULT); /* not OCI_COMMIT_ON_SUCCESS because transactions are
-								  handled separately */
-					
-			error = gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-							 _("Could not execute the Oracle statement"));
-		}
-	}
-	gda_connection_internal_treat_sql (cnc, sql, error);
-	if (error) {
-		OCIHandleFree ((dvoid *) stmthp, OCI_HTYPE_STMT);
-		return NULL;
-	}
-
-	if (stmt_type != OCI_STMT_SELECT) { 
-		/* get the number of affected rows */
-		int nrows;
-
-		result = OCIAttrGet (stmthp, OCI_HTYPE_STMT,
-				     (dvoid *) &stmt_type, NULL,
-				     OCI_ATTR_SQLFNCODE, priv_data->herr);
-		if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-					     _("Could not get the Oracle statement type"))) {
-			OCIHandleFree ((dvoid *) stmthp, OCI_HTYPE_STMT);
-			return NULL;
-		}
-		result = OCIAttrGet (stmthp, OCI_HTYPE_STMT,
-				     (dvoid *) &nrows, NULL,
-				     OCI_ATTR_ROW_COUNT, priv_data->herr);
-		if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-					     _("Could not get the number of affected rows"))) {
-			OCIHandleFree ((dvoid *) stmthp, OCI_HTYPE_STMT);
-			return NULL;
-		}
-
-		retval = GDA_OBJECT (gda_parameter_list_new_inline (NULL, "IMPACTED_ROWS", G_TYPE_INT, nrows, NULL));
-
-		/* handle the attached transaction */
-		OCITrans *txnhp = NULL;
-		result = OCIAttrGet ((dvoid *) priv_data->hservice,
-				     OCI_HTYPE_SVCCTX,
-				     (dvoid **) &txnhp,
-				     0,
-				     OCI_ATTR_TRANS,
-				     priv_data->herr);
-		if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-					     _("Could not get the attached transaction from the service context")))
-			return NULL;
-
-		if (!txnhp) {
-			/* Commit local transaction (no global transaction) */
-			result = OCITransCommit (priv_data->hservice, priv_data->herr, 0);
-			if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-						     _("Could not execute the Oracle statement"))) {
-				OCIHandleFree ((dvoid *) stmthp, OCI_HTYPE_STMT);
-				return NULL;
-			}
-		}
-		/*else
-		  g_print ("Don't commit local transaction (there is a global transaction)\n");*/
-	}
-	else {
-		GList *columns = NULL;
-		ub4 ncolumns;
-		ub4 i;
-
-		/* get the number of columns in the result set */
-		result = OCIAttrGet ((dvoid *) stmthp,
-				     (ub4) OCI_HTYPE_STMT,
-				     (dvoid *) &ncolumns,
-				     (ub4 *) 0,
-				     (ub4) OCI_ATTR_PARAM_COUNT,
-				     priv_data->herr);
-		if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-					     _("Could not get the number of columns in the result set"))) {
-			OCIHandleFree ((dvoid *) stmthp, OCI_HTYPE_STMT);
-			return NULL;
-		}
-		
-		for (i = 0; i < ncolumns; i += 1) {
-			text *pgchar_dummy = (text *) 0;
-			ub4 col_name_len;
-			OCIParam *pard = (OCIParam *) 0;
-			gchar *name_buffer;
-			
-			result = OCIParamGet ((dvoid *) stmthp,
-					      OCI_HTYPE_STMT,
-					      priv_data->herr,
-					      (dvoid **) &pard,
-					      (ub4) i + 1);
-			if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-						     _("Could not get the parameter descripter in the result set"))) {
-				OCIHandleFree ((dvoid *) stmthp, OCI_HTYPE_STMT);
-				return NULL;
-			}
-			
-			result = OCIAttrGet ((dvoid *) pard,
-					     (ub4) OCI_DTYPE_PARAM,
-					     (dvoid **) &pgchar_dummy,
-					     (ub4 *) &col_name_len,
-					     (ub4) OCI_ATTR_NAME,
-					     (OCIError *) priv_data->herr);
-			if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-						     _("Could not get the column name in the result set"))) {
-				OCIHandleFree ((dvoid *) stmthp, OCI_HTYPE_STMT);
-				return NULL;
-			}
-			
-			name_buffer = g_malloc0 (col_name_len + 1);
-			memcpy (name_buffer, pgchar_dummy, col_name_len);
-			name_buffer[col_name_len] = '\0';
-			columns = g_list_append (columns, name_buffer);
-		}
-
-		retval = GDA_OBJECT (gda_oracle_recordset_new (cnc, priv_data, stmthp, 
-							       col_size_array));
-		stmthp = NULL;
-		GList *l;
-		g_object_set (G_OBJECT (retval), 
-			      "command_text", sql,
-			      "command_type", GDA_COMMAND_TYPE_SQL, NULL);
-		
-		for (i = 0, l = columns; l; l = l->next, i++) {
-			gchar *col_name = (gchar *) l->data;
-			gda_data_model_set_column_title ((GdaDataModel *) retval, i, col_name);
-		}
-		
-		/*gda_data_model_dump (recset, stdout);*/
-		g_list_free (columns);
-	}
-
-	return retval;
-}
-
-static GList *
-process_sql_commands (GList *reclist, GdaConnection *cnc, 
-		      const gchar *sql, GdaParameterList *params, 
-		      GdaCommandOptions options, GArray *col_size_array)
-{
-	gchar **arr;
-
-	/* parse SQL string, which can contain several commands, separated by ';' */
-	arr = gda_delimiter_split_sql (sql);
-	if (arr) {
-		gint n;
-
-		for (n = 0; arr[n]; n++) {
-			GdaObject *obj;
-			OCIStmt *stmthp;
-
-			stmthp = prepare_oracle_statement (cnc, params, arr[n]);
-			obj = process_oci_statement (stmthp, arr[n], cnc, col_size_array);
-			reclist = g_list_append (reclist, obj);			
-		}
-		
-		g_strfreev (arr);
-	}
-
-	return reclist;
-}
-
-/* get_database handler for the GdaOracleProvider class */
 static const gchar *
-gda_oracle_provider_get_database (GdaServerProvider *provider,
-				  GdaConnection *cnc)
+gda_oracle_provider_get_database (GdaServerProvider *provider, GdaConnection *cnc)
 {
-	GdaOracleConnectionData *priv_data;
-	GdaOracleProvider *ora_prv = (GdaOracleProvider *) provider;
+	OracleConnectionData *cdata;
 
-	g_return_val_if_fail (GDA_IS_ORACLE_PROVIDER (ora_prv), NULL);
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
 
-	priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
-	if (!priv_data) {
-		gda_connection_add_event_string (cnc, _("Invalid Oracle handle"));
-		return FALSE;
-	}
-
-	/* don't know what to do here yet. */
+	cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
+		return NULL;
+	TO_IMPLEMENT;
 	return NULL;
 }
 
+/*
+ * Support operation request
+ *
+ * Tells what the implemented server operations are. To add support for an operation, the following steps are required:
+ *   - create a oracle_specs_....xml.in file describing the required and optional parameters for the operation
+ *   - add it to the Makefile.am
+ *   - make this method return TRUE for the operation type
+ *   - implement the gda_oracle_provider_render_operation() and gda_oracle_provider_perform_operation() methods
+ *
+ * In this example, the GDA_SERVER_OPERATION_CREATE_TABLE is implemented
+ */
 static gboolean
 gda_oracle_provider_supports_operation (GdaServerProvider *provider, GdaConnection *cnc,
-                                        GdaServerOperationType type, GdaParameterList *options)
+				      GdaServerOperationType type, GdaSet *options)
 {
-	switch (type) {
-	case GDA_SERVER_OPERATION_CREATE_DB:
-	case GDA_SERVER_OPERATION_DROP_DB:
-
-	case GDA_SERVER_OPERATION_CREATE_TABLE:
-	case GDA_SERVER_OPERATION_DROP_TABLE:
-	case GDA_SERVER_OPERATION_RENAME_TABLE:
+	if (cnc) {
+		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+		g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
+	}
 
-	case GDA_SERVER_OPERATION_ADD_COLUMN:
-	case GDA_SERVER_OPERATION_DROP_COLUMN:
+        switch (type) {
+        case GDA_SERVER_OPERATION_CREATE_DB:
+        case GDA_SERVER_OPERATION_DROP_DB:
+		return FALSE;
 
-	case GDA_SERVER_OPERATION_CREATE_INDEX:
-	case GDA_SERVER_OPERATION_DROP_INDEX:
+        case GDA_SERVER_OPERATION_CREATE_TABLE:
 		return TRUE;
-	default:
-		return FALSE;
-	}
+        case GDA_SERVER_OPERATION_DROP_TABLE:
+        case GDA_SERVER_OPERATION_RENAME_TABLE:
+
+        case GDA_SERVER_OPERATION_ADD_COLUMN:
+
+        case GDA_SERVER_OPERATION_CREATE_INDEX:
+        case GDA_SERVER_OPERATION_DROP_INDEX:
+
+        case GDA_SERVER_OPERATION_CREATE_VIEW:
+        case GDA_SERVER_OPERATION_DROP_VIEW:
+        default:
+                return FALSE;
+        }
 }
+
+/*
+ * Create operation request
+ *
+ * Creates a #GdaServerOperation. The following code is generic and should only be changed
+ * if some further initialization is required, or if operation's contents is dependant on @cnc
+ */
 static GdaServerOperation *
 gda_oracle_provider_create_operation (GdaServerProvider *provider, GdaConnection *cnc,
-                                      GdaServerOperationType type,
-                                      GdaParameterList *options, GError **error)
+				    GdaServerOperationType type, GdaSet *options, GError **error)
 {
-	gchar *file;
-	GdaServerOperation *op;
-	gchar *str;
+        gchar *file;
+        GdaServerOperation *op;
+        gchar *str;
 	gchar *dir;
 
-	file = g_utf8_strdown (gda_server_operation_op_type_to_string (type), -1);
-	str = g_strdup_printf ("oracle_specs_%s.xml", file);
-	g_free (file);
+	if (cnc) {
+		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+		g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
+	}
+
+        file = g_utf8_strdown (gda_server_operation_op_type_to_string (type), -1);
+        str = g_strdup_printf ("oracle_specs_%s.xml", file);
+        g_free (file);
 
 	dir = gda_gbr_get_file_path (GDA_DATA_DIR, LIBGDA_ABI_NAME, NULL);
-	file = gda_server_provider_find_file (provider, dir, str);
+        file = gda_server_provider_find_file (provider, dir, str);
 	g_free (dir);
-	g_free (str);
 
-	if (! file) {
-		g_set_error (error, 0, 0, _("Missing spec. file '%s'"), file);
-		return NULL;
-	}
+        if (! file) {
+                g_set_error (error, 0, 0, _("Missing spec. file '%s'"), str);
+		g_free (str);
+                return NULL;
+        }
+        g_free (str);
 
-	op = gda_server_operation_new (type, file);
-	g_free (file);
+        op = gda_server_operation_new (type, file);
+        g_free (file);
 
-	return op;
+        return op;
 }
 
+/*
+ * Render operation request
+ */
 static gchar *
-gda_oracle_provider_render_operation (GdaServerProvider *provider, GdaConnection *cnc, 
-				      GdaServerOperation *op, GError **error)
+gda_oracle_provider_render_operation (GdaServerProvider *provider, GdaConnection *cnc,
+				    GdaServerOperation *op, GError **error)
 {
-	gchar *sql = NULL;
-	gchar *file;
-	gchar *str;
+        gchar *sql = NULL;
+        gchar *file;
+        gchar *str;
 	gchar *dir;
 
-	file = g_utf8_strdown (gda_server_operation_op_type_to_string (gda_server_operation_get_op_type (op)), -1);
-	str = g_strdup_printf ("oracle_specs_%s.xml", file);
-	g_free (file);
-	
+	if (cnc) {
+		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+		g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
+	}
+
+	/* test @op's validity */
+        file = g_utf8_strdown (gda_server_operation_op_type_to_string (gda_server_operation_get_op_type (op)), -1);
+        str = g_strdup_printf ("oracle_specs_%s.xml", file);
+        g_free (file);
+
 	dir = gda_gbr_get_file_path (GDA_DATA_DIR, LIBGDA_ABI_NAME, NULL);
-	file = gda_server_provider_find_file (provider, dir, str);
+        file = gda_server_provider_find_file (provider, dir, str);
 	g_free (dir);
-	g_free (str);
 
-	if (! file) {
-		g_set_error (error, 0, 0, _("Missing spec. file '%s'"), file);
-		return NULL;
-	}
-	if (!gda_server_operation_is_valid (op, file, error)) {
-		g_free (file);
-		return NULL;
-	}
-	g_free (file);
-
-	switch (gda_server_operation_get_op_type (op)) {
-	case GDA_SERVER_OPERATION_CREATE_DB:
-		sql = gda_oracle_render_CREATE_DB (provider, cnc, op, error);
-		break;
-	case GDA_SERVER_OPERATION_DROP_DB:
-		sql = gda_oracle_render_DROP_DB (provider, cnc, op, error);
-		break;
-	case GDA_SERVER_OPERATION_CREATE_TABLE:
-		sql = gda_oracle_render_CREATE_TABLE (provider, cnc, op, error);
-		break;
-	case GDA_SERVER_OPERATION_DROP_TABLE:
-		sql = gda_oracle_render_DROP_TABLE (provider, cnc, op, error);
-		break;
-	case GDA_SERVER_OPERATION_RENAME_TABLE:
-		sql = gda_oracle_render_RENAME_TABLE (provider, cnc, op, error);
-		break;
-	case GDA_SERVER_OPERATION_ADD_COLUMN:
-		sql = gda_oracle_render_ADD_COLUMN (provider, cnc, op, error);
-		break;
-	case GDA_SERVER_OPERATION_DROP_COLUMN:
-		sql = gda_oracle_render_DROP_COLUMN (provider, cnc, op, error);
-		break;
-	case GDA_SERVER_OPERATION_CREATE_INDEX:
-		sql = gda_oracle_render_CREATE_INDEX (provider, cnc, op, error);
-		break;
-	case GDA_SERVER_OPERATION_DROP_INDEX:
-		sql = gda_oracle_render_DROP_INDEX (provider, cnc, op, error);
-		break;
-	default:
-		g_assert_not_reached ();
-	}
-	return sql;
+        if (! file) {
+                g_set_error (error, 0, 0, _("Missing spec. file '%s'"), str);
+		g_free (str);
+                return NULL;
+        }
+        g_free (str);
+        if (!gda_server_operation_is_valid (op, file, error)) {
+                g_free (file);
+                return NULL;
+        }
+        g_free (file);
+
+	/* actual rendering */
+        switch (gda_server_operation_get_op_type (op)) {
+        case GDA_SERVER_OPERATION_CREATE_DB:
+        case GDA_SERVER_OPERATION_DROP_DB:
+		sql = NULL;
+                break;
+        case GDA_SERVER_OPERATION_CREATE_TABLE:
+                sql = gda_oracle_render_CREATE_TABLE (provider, cnc, op, error);
+                break;
+        case GDA_SERVER_OPERATION_DROP_TABLE:
+        case GDA_SERVER_OPERATION_RENAME_TABLE:
+        case GDA_SERVER_OPERATION_ADD_COLUMN:
+        case GDA_SERVER_OPERATION_CREATE_INDEX:
+        case GDA_SERVER_OPERATION_DROP_INDEX:
+        case GDA_SERVER_OPERATION_CREATE_VIEW:
+        case GDA_SERVER_OPERATION_DROP_VIEW:
+                sql = NULL;
+                break;
+        default:
+                g_assert_not_reached ();
+        }
+        return sql;
 }
 
+/*
+ * Perform operation request
+ */
 static gboolean
-gda_oracle_provider_perform_operation (GdaServerProvider *provider, GdaConnection *cnc, 
-				       GdaServerOperation *op, GError **error)
+gda_oracle_provider_perform_operation (GdaServerProvider *provider, GdaConnection *cnc,
+				     GdaServerOperation *op, guint *task_id, 
+				     GdaServerProviderAsyncCallback async_cb, gpointer cb_data, GError **error)
 {
-	GdaServerOperationType optype;
+        GdaServerOperationType optype;
 
-	optype = gda_server_operation_get_op_type (op);
-	if (!cnc && 
-	    ((optype == GDA_SERVER_OPERATION_CREATE_DB) ||
-	     (optype == GDA_SERVER_OPERATION_DROP_DB))) {
+	/* If asynchronous connection opening is not supported, then exit now */
+	if (async_cb) {
+		g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_METHOD_NON_IMPLEMENTED_ERROR,
+			     "%s", _("Provider does not support asynchronous server operation"));
+                return FALSE;
+	}
 
-		/* Not yet implemented */
-		return FALSE;
+	if (cnc) {
+		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+		g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
 	}
-	else {
+        optype = gda_server_operation_get_op_type (op);
+	switch (optype) {
+	case GDA_SERVER_OPERATION_CREATE_DB: 
+	case GDA_SERVER_OPERATION_DROP_DB: 
+        default: 
 		/* use the SQL from the provider to perform the action */
-		gchar *sql;
-		GdaCommand *cmd;
-		
-		sql = gda_server_provider_render_operation (provider, cnc, op, error);
-		if (!sql)
-			return FALSE;
-		
-		cmd = gda_command_new (sql, GDA_COMMAND_TYPE_SQL, GDA_COMMAND_OPTION_STOP_ON_ERRORS);
-		g_free (sql);
-
-		if (gda_connection_execute_non_select_command (cnc, cmd, NULL, error) != -1) {
-                        gda_command_free (cmd);
-                        return TRUE;
-                }
-                else {
-                        gda_command_free (cmd);
-                        return FALSE;
-                }
+		return gda_server_provider_perform_operation_default (provider, cnc, op, error);
 	}
 }
 
-/* execute_command handler */
-static GList *
-gda_oracle_provider_execute_command (GdaServerProvider *provider,
-				     GdaConnection *cnc,
-				     GdaCommand *cmd,
-				     GdaParameterList *params)
+/*
+ * Begin transaction request
+ */
+static gboolean
+gda_oracle_provider_begin_transaction (GdaServerProvider *provider, GdaConnection *cnc,
+				     const gchar *name, GdaTransactionIsolation level,
+				     GError **error)
 {
-	GList *reclist = NULL;
-	gchar *str;
-	GdaOracleProvider *ora_prv = (GdaOracleProvider *) provider;
-	GdaOracleConnectionData *priv_data;
+	OracleConnectionData *cdata;
 
-	GdaCommandOptions options;
-
-	g_return_val_if_fail (GDA_IS_ORACLE_PROVIDER (ora_prv), NULL);
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-	g_return_val_if_fail (cmd != NULL, NULL);
+	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
 
-	priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
-	if (!priv_data) {
-		gda_connection_add_event_string (cnc, _("Invalid Oracle handle"));
+	cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
 		return FALSE;
-	}
-
-	options = gda_command_get_options (cmd);
 
-	switch (gda_command_get_command_type (cmd)) {
-	case GDA_COMMAND_TYPE_SQL:
-		reclist = process_sql_commands (reclist, cnc, gda_command_get_text (cmd), NULL, options, NULL);
-		break;
-	case GDA_COMMAND_TYPE_TABLE:
-		str = g_strdup_printf ("SELECT * FROM %s", gda_command_get_text (cmd));
-		reclist = process_sql_commands (reclist, cnc, str, NULL, options, NULL);
-		g_free (str);
-		break;
-	default:
-		break;
-	}
+	TO_IMPLEMENT;
 
-	return reclist;
+	return FALSE;
 }
 
-static GdaObject *
-gda_oracle_provider_execute_query (GdaServerProvider *provider,
-				   GdaConnection *cnc,
-				   GdaQuery *query,
-				   GdaParameterList *params)
+/*
+ * Commit transaction request
+ */
+static gboolean
+gda_oracle_provider_commit_transaction (GdaServerProvider *provider, GdaConnection *cnc,
+				      const gchar *name, GError **error)
 {
-	GdaObject *retval = NULL;
-	gchar *pseudo_sql;
-	GError *error = NULL;
-	GdaOracleProvider *ora_prv = (GdaOracleProvider *) provider;
-	GdaOracleConnectionData *priv_data;
-	GSList *used_params = NULL;
-
-	g_return_val_if_fail (GDA_IS_ORACLE_PROVIDER (ora_prv), NULL);
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-	g_return_val_if_fail (GDA_IS_QUERY (query), NULL);
+	OracleConnectionData *cdata;
 
-	priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
-	if (!priv_data) {
-		gda_connection_add_event_string (cnc, _("Invalid Oracle handle"));
-		return NULL;
-	}
-
-	pseudo_sql = gda_renderer_render_as_sql (GDA_RENDERER (query), params, &used_params, 
-						 GDA_RENDERER_PARAMS_AS_COLON, &error);
-	if (!pseudo_sql) {
-		GdaConnectionEvent *event;
-		event = gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR);
-		gda_connection_event_set_description (event, error && error->message ? 
-						      error->message : _("No detail"));
-		g_error_free (error);
-		gda_connection_add_event (cnc, event);
-		return NULL;
-	}
+	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
 
-	OCIStmt *stmthp;
+	cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
+		return FALSE;
 
-	stmthp = prepare_oracle_statement (cnc, params, pseudo_sql);
-	retval = process_oci_statement (stmthp, pseudo_sql, cnc, NULL);
-	g_free (pseudo_sql);
+	TO_IMPLEMENT;
 
-	return retval;
+	return FALSE;
 }
 
-
-/* begin_transaction handler for the GdaOracleProvider class */
+/*
+ * Rollback transaction request
+ */
 static gboolean
-gda_oracle_provider_begin_transaction (GdaServerProvider *provider,
-				       GdaConnection *cnc,
-				       const gchar *name, GdaTransactionIsolation level,
-				       GError **error)
+gda_oracle_provider_rollback_transaction (GdaServerProvider *provider, GdaConnection *cnc,
+					const gchar *name, GError **error)
 {
-	GdaOracleConnectionData *priv_data;
-	GdaOracleProvider *ora_prv = (GdaOracleProvider *) provider;
-	gint result;
-	OCITrans *txnhp;
+	OracleConnectionData *cdata;
 
-	g_return_val_if_fail (GDA_IS_ORACLE_PROVIDER (ora_prv), FALSE);
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
 
-	priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
-	if (!priv_data) {
-		gda_connection_add_event_string (cnc, _("Invalid Oracle handle"));
-		return FALSE;
-	}
-
-	if (gda_connection_get_options (cnc) & GDA_CONNECTION_OPTIONS_READ_ONLY) {
-		gda_connection_add_event_string (cnc, _("Transactions are not supported in read-only mode"));
+	cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
 		return FALSE;
-	}
 
-	/* allocate the Oracle transaction handle */
-	result = OCIHandleAlloc ((dvoid *) priv_data->henv,
-				 (dvoid **) &txnhp,
-				 (ub4) OCI_HTYPE_TRANS,
-				 (size_t) 0,
-				 (dvoid **) 0);
-	if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ENV,
-				     _("Could not allocate the Oracle transaction handle")))
-		return FALSE;
+	TO_IMPLEMENT;
 
-	/* set the transaction name if applicable */
-	if (name) {
-		result = OCIAttrSet ((dvoid *) txnhp,
-				     OCI_HTYPE_TRANS,
-				     (text *) name,
-				     strlen (name),
-				     OCI_ATTR_TRANS_NAME,
-				     priv_data->herr);
-		if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-					     _("Could not set the Oracle transaction name"))) {
-			OCIHandleFree ((dvoid *) txnhp, OCI_HTYPE_TRANS);
-			return FALSE;
-		}
-	}
-	
-	/* attach the transaction to the service context */
-	result = OCIAttrSet ((dvoid *) priv_data->hservice,
-			     OCI_HTYPE_SVCCTX,
-			     (dvoid *) txnhp,
-			     0,
-			     OCI_ATTR_TRANS,
-			     priv_data->herr);
-	if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-				     _("Could not attach the transaction to the service context"))) {
-		OCIHandleFree ((dvoid *) txnhp, OCI_HTYPE_TRANS);
-		return FALSE;
-	}
-
-	/* start the transaction */
-	result = OCITransStart (priv_data->hservice, 
-				priv_data->herr, 
-				60, 
-				OCI_TRANS_NEW);
-	if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-				     _("Could not start the Oracle transaction"))) {
-		OCIAttrSet ((dvoid *) priv_data->hservice,
-			    OCI_HTYPE_SVCCTX,
-			    (dvoid *) NULL,
-			    0,
-			    OCI_ATTR_TRANS,
-			    priv_data->herr);
-		OCIHandleFree ((dvoid *) txnhp, OCI_HTYPE_TRANS);
-		return FALSE; 
-	}
-
-	/* help the GdaConnection keep track of the transaction status */
-	gda_connection_internal_transaction_started (cnc, NULL, name, GDA_TRANSACTION_ISOLATION_UNKNOWN);
-
-	return TRUE;
+	return FALSE;
 }
 
-/* commit_transaction handler for the GdaOracleProvider class */
+/*
+ * Add savepoint request
+ */
 static gboolean
-gda_oracle_provider_commit_transaction (GdaServerProvider *provider,
-					GdaConnection *cnc,
-					const gchar *name, GError **error)
+gda_oracle_provider_add_savepoint (GdaServerProvider *provider, GdaConnection *cnc,
+				 const gchar *name, GError **error)
 {
-	GdaOracleConnectionData *priv_data;
-	GdaOracleProvider *ora_prv = (GdaOracleProvider *) provider;
-	gint result;
-	OCITrans *txnhp = NULL;
+	OracleConnectionData *cdata;
 
-	g_return_val_if_fail (GDA_IS_ORACLE_PROVIDER (ora_prv), FALSE);
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
 
-	priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
-	if (!priv_data) {
-		gda_connection_add_event_string (cnc, _("Invalid Oracle handle"));
-		return FALSE;
-	}
-
-	result = OCIAttrGet ((dvoid *) priv_data->hservice,
-			     OCI_HTYPE_SVCCTX,
-			     (dvoid **) &txnhp,
-			     0,
-			     OCI_ATTR_TRANS,
-			     priv_data->herr);
-	if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-				     _("Could not get the attached transaction from the service context")))
-		return FALSE;
-
-	if (gda_connection_get_options (cnc) & GDA_CONNECTION_OPTIONS_READ_ONLY) {
-		gda_connection_add_event_string (cnc, _("Transactions are not supported in read-only mode"));
-		return FALSE;
-	}
-
-	/* commit */
-	result = OCITransCommit (priv_data->hservice, 
-				 priv_data->herr, 
-				 OCI_DEFAULT);
-	if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-				     _("Could not commit the Oracle transaction")))
+	cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
 		return FALSE;
 
-	/* get rid of transaction handle */
-	result = OCIAttrSet ((dvoid *) priv_data->hservice,
-			     OCI_HTYPE_SVCCTX,
-			     (dvoid *) NULL,
-			     0,
-			     OCI_ATTR_TRANS,
-			     priv_data->herr);
-	gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-				 _("Could not de-attach the transaction to the service context"));
-	if (txnhp)
-		OCIHandleFree ((dvoid *) txnhp, OCI_HTYPE_TRANS);
-
-	/* help the GdaConnection keep track of the transaction status */
-	gda_connection_internal_transaction_committed (cnc, name);
-
-	return TRUE;
+	TO_IMPLEMENT;
 
+	return FALSE;
 }
 
-/* rollback_transaction handler for the GdaOracleProvider class */
+/*
+ * Rollback savepoint request
+ */
 static gboolean
-gda_oracle_provider_rollback_transaction (GdaServerProvider *provider,
-					  GdaConnection *cnc,
-					  const gchar *name, GError **error)
+gda_oracle_provider_rollback_savepoint (GdaServerProvider *provider, GdaConnection *cnc,
+				      const gchar *name, GError **error)
 {
-	GdaOracleConnectionData *priv_data;
-	GdaOracleProvider *ora_prv = (GdaOracleProvider *) provider;
-	gint result;
-	OCITrans *txnhp = NULL;
+	OracleConnectionData *cdata;
 
-	g_return_val_if_fail (GDA_IS_ORACLE_PROVIDER (ora_prv), FALSE);
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
 
-	priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
-	if (!priv_data) {
-		gda_connection_add_event_string (cnc, _("Invalid Oracle handle"));
+	cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
 		return FALSE;
-	}
 
-	result = OCIAttrGet ((dvoid *) priv_data->hservice,
-			     OCI_HTYPE_SVCCTX,
-			     (dvoid **) &txnhp,
-			     0,
-			     OCI_ATTR_TRANS,
-			     priv_data->herr);
-	if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-				     _("Could not get the attached transaction from the service context")))
-		return FALSE;
+	TO_IMPLEMENT;
 
-	if (gda_connection_get_options (cnc) & GDA_CONNECTION_OPTIONS_READ_ONLY) {
-		gda_connection_add_event_string (cnc, _("Transactions are not supported in read-only mode"));
-		return FALSE;
-	}
+	return FALSE;
+}
+
+/*
+ * Delete savepoint request
+ */
+static gboolean
+gda_oracle_provider_delete_savepoint (GdaServerProvider *provider, GdaConnection *cnc,
+				    const gchar *name, GError **error)
+{
+	OracleConnectionData *cdata;
+
+	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
 
-	/* attach the transaction to the service context */
-	result = OCITransRollback (priv_data->hservice, 
-				   priv_data->herr, 
-				   OCI_DEFAULT);
-	if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-				     _("Could not rollback the Oracle transaction")))
+	cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
 		return FALSE;
 
-	/* get rid of transaction handle */
-	result = OCIAttrSet ((dvoid *) priv_data->hservice,
-			     OCI_HTYPE_SVCCTX,
-			     (dvoid *) NULL,
-			     0,
-			     OCI_ATTR_TRANS,
-			     priv_data->herr);
-	gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-				 _("Could not de-attach the transaction to the service context"));
-	if (txnhp)
-		OCIHandleFree ((dvoid *) txnhp, OCI_HTYPE_TRANS);
-
-	/* help the GdaConnection keep track of the transaction status */
-	gda_connection_internal_transaction_rolledback (cnc, name);
+	TO_IMPLEMENT;
 
-	return TRUE;
+	return FALSE;
 }
 
-/* supports handler for the GdaOracleProvider class */
+/*
+ * Feature support request
+ */
 static gboolean
-gda_oracle_provider_supports (GdaServerProvider *provider,
-			      GdaConnection *cnc,
-			      GdaConnectionFeature feature)
+gda_oracle_provider_supports_feature (GdaServerProvider *provider, GdaConnection *cnc, GdaConnectionFeature feature)
 {
-	GdaOracleProvider *ora_prv = (GdaOracleProvider *) provider;
-
-	g_return_val_if_fail (GDA_IS_ORACLE_PROVIDER (ora_prv), FALSE);
+	if (cnc) {
+		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+		g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
+	}
 
 	switch (feature) {
-        case GDA_CONNECTION_FEATURE_AGGREGATES :
-	case GDA_CONNECTION_FEATURE_INDEXES :
-	case GDA_CONNECTION_FEATURE_PROCEDURES :
-	case GDA_CONNECTION_FEATURE_SEQUENCES :
 	case GDA_CONNECTION_FEATURE_SQL :
-	case GDA_CONNECTION_FEATURE_TRANSACTIONS :
-	case GDA_CONNECTION_FEATURE_TRIGGERS :
-	case GDA_CONNECTION_FEATURE_USERS :
-	case GDA_CONNECTION_FEATURE_VIEWS :
-	case GDA_CONNECTION_FEATURE_BLOBS :
 		return TRUE;
-	default :
-		break;
+	default: 
+		return FALSE;
 	}
-
-	return FALSE;
-}
-
-static GdaServerProviderInfo *
-gda_oracle_provider_get_info (GdaServerProvider *provider, GdaConnection *cnc)
-{
-	static GdaServerProviderInfo info = {
-		"Oracle",
-		TRUE, 
-		TRUE,
-		FALSE,
-		TRUE,
-		TRUE,
-		TRUE
-	};
-	
-	return &info;
 }
 
-typedef struct
-{
-	const gchar *name;
-	const gchar *uid;
-	const gchar *args;
-} gda_oracle_aggregate_t;
-
-static gda_oracle_aggregate_t aggregate_tab[] =
-{
-	{ "AVG",             "SYS_AGG01", "NUMBER"        },
-	{ "COLLECT",         "SYS_AGG33", "-" },
-	{ "CORR",            "SYS_AGG02", "NUMBER NUMBER" },
-	{ "COUNT",           "SYS_AGG03", "-"             },
-	{ "COVAR_POP",       "SYS_AGG04", "NUMBER NUMBER" },
-	{ "COVAR_SAMP",      "SYS_AGG05", "NUMBER NUMBER" },
-	{ "CUME_DIST",       "SYS_AGG06", "NUMBER"        },
-	{ "FIRST",           "SYS_AGG35", "NUMBER"        },
-	{ "DENSE_RANK",      "SYS_AGG07", "NUMBER"        },
-	{ "GROUP_ID",        "SYS_AGG08", ""              },
-	{ "GROUPING",        "SYS_AGG09", "-"             },
-	{ "GROUPING_ID",     "SYS_AGG10", "-"             },
-	{ "LAST",            "SYS_AGG34", "NUMBER"        },
-	{ "MAX",             "SYS_AGG11", "NUMBER"        },
-	{ "MIN",             "SYS_AGG12", "NUMBER"        },
-	{ "PERCENTILE_CONT", "SYS_AGG13", "NUMBER"        },
-	{ "PERCENTILE_DISC", "SYS_AGG14", "NUMBER"        },
-	{ "PERCENT_RANK",    "SYS_AGG15", "NUMBER"        },
-	{ "RANK",            "SYS_AGG16", "NUMBER"        },
-	{ "REGR_SLOPE",      "SYS_AGG17", "NUMBER NUMBER" },
-	{ "REGR_INTERCEPT",  "SYS_AGG18", "NUMBER NUMBER" },
-	{ "REGR_COUNT",      "SYS_AGG19", "NUMBER NUMBER" },
-	{ "REGR_R2",         "SYS_AGG20", "NUMBER NUMBER" },
-	{ "REGR_AVGX",       "SYS_AGG21", "NUMBER NUMBER" },
-	{ "REGR_AVGY",       "SYS_AGG22", "NUMBER NUMBER" },
-	{ "REGR_SXX",        "SYS_AGG23", "NUMBER NUMBER" },
-	{ "REGR_SYY",        "SYS_AGG24", "NUMBER NUMBER" },
-	{ "REGR_SXY",        "SYS_AGG25", "NUMBER NUMBER" },
-	{ "STDDEV",          "SYS_AGG26", "NUMBER"        },
-	{ "STDDEV_POP",      "SYS_AGG27", "NUMBER"        },
-	{ "STDDEV_SAMP",     "SYS_AGG28", "NUMBER"        },
-	{ "SUM",             "SYS_AGG29", "NUMBER"        },
-	{ "VAR_POP",         "SYS_AGG30", "NUMBER"        },
-	{ "VAR_SAMP",        "SYS_AGG31", "NUMBER"        },
-	{ "VARIANCE",        "SYS_AGG32", "NUMBER"        }
-};
-static const gda_oracle_aggregate_t
-*aggregate_end = aggregate_tab + (sizeof(aggregate_tab)/sizeof(gda_oracle_aggregate_t));
-
-static GdaDataModel *
-get_oracle_aggregates (GdaConnection *cnc, GdaParameterList *params)
+/*
+ * Get data handler request
+ *
+ * This method allows one to obtain a pointer to a #GdaDataHandler object specific to @type or @dbms_type (@dbms_type
+ * must be considered only if @type is not a valid GType).
+ *
+ * A data handler allows one to convert a value between its different representations which are a human readable string,
+ * an SQL representation and a GValue.
+ *
+ * The recommended method is to create GdaDataHandler objects only when they are needed and to keep a reference to them
+ * for further usage, using the gda_server_provider_handler_declare() method.
+ *
+ * The implementation shown here does not define any specific data handler, but there should be some for at least 
+ * binary and time related types.
+ */
+static GdaDataHandler *
+gda_oracle_provider_get_data_handler (GdaServerProvider *provider, GdaConnection *cnc,
+				    GType type, const gchar *dbms_type)
 {
-	GdaOracleConnectionData *priv_data;
-	GdaDataModelArray *recset;
-	GdaParameter *par = NULL;
-	gchar *uc_name = NULL;
-	gda_oracle_aggregate_t *row;
-
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-	priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
-	if (!priv_data) {
-		gda_connection_add_event_string (cnc, _("Invalid Oracle handle"));
-		return NULL;
+	GdaDataHandler *dh;
+	if (cnc) {
+		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+		g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
 	}
 
-	/* create the recordset */
-	recset = GDA_DATA_MODEL_ARRAY (gda_data_model_array_new 
-				       (gda_server_provider_get_schema_nb_columns (GDA_CONNECTION_SCHEMA_AGGREGATES)));
-	gda_server_provider_init_schema_model (GDA_DATA_MODEL (recset), GDA_CONNECTION_SCHEMA_AGGREGATES);
-
-	if (params)
-		par = gda_parameter_list_find_param (params, "name");
-	if (par) {
-		gchar *name;
-		name = (gchar *) g_value_get_string ((GValue *) gda_parameter_get_value (par));
-		uc_name = g_ascii_strup (name, -1);
-	} 
-
-	for (row = aggregate_tab; row < aggregate_end; row++) {
-		GList *list;
-		GValue *tmpval;
-		
-		if (uc_name && strcmp (row->name, uc_name))
-			continue;
-
-		/* 1st the name */
-		g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), row->name);
-		list = g_list_append (NULL, tmpval);
-		/* 2nd the unique id */
-		g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), row->uid);
-		list = g_list_append (list, tmpval);
-		/* 3rd the owner */
-		g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), "SYS");
-		list = g_list_append (list, tmpval);
-		/* 4th the comments */
-		list = g_list_append (list, gda_value_new_null ());
-		/* 5th the return type */
-		g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), "NUMBER");
-		list = g_list_append (list, tmpval);
-		/* 6th the argument type */
-		g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), row->args);
-		list = g_list_append (list, tmpval);
-		/* 7th the SQL definition */
-		list = g_list_append (list, gda_value_new_null ());
-		
-		gda_data_model_append_values (GDA_DATA_MODEL (recset), list, NULL);
-		
-		g_list_foreach (list, (GFunc) gda_value_free, NULL);
-		g_list_free (list);
+	if (type == G_TYPE_INVALID) {
+		TO_IMPLEMENT; /* use @dbms_type */
+		dh = NULL;
 	}
+	else if ((type == GDA_TYPE_BINARY) ||
+		 (type == GDA_TYPE_BLOB)) {
+		TO_IMPLEMENT; /* define data handlers for these types */
+		dh = NULL;
+	}
+	else if ((type == GDA_TYPE_TIME) ||
+		 (type == GDA_TYPE_TIMESTAMP) ||
+		 (type == G_TYPE_DATE)) {
+		TO_IMPLEMENT; /* define data handlers for these types */
+		dh = NULL;
+	}
+	else
+		dh = gda_server_provider_get_data_handler_default (provider, cnc, type, dbms_type);
 
-	g_free (uc_name);
-	return GDA_DATA_MODEL (recset);
-}
-
-static GString *
-g_string_right_trim (GString * input)
-{
-	gint i;
-
-	for (i = input->len - 1; i >= 0; i -= 1)
-		if (input->str[i] != ' ')
-			return g_string_truncate (input, i+1);
-
-	return g_string_truncate (input, 0);
+	return dh;
 }
 
-static GHashTable *
-get_oracle_index_data (GdaConnection *cnc, const gchar *owner, const gchar *tblname)
+/*
+ * Get default DBMS type request
+ *
+ * This method returns the "preferred" DBMS type for GType
+ */
+static const gchar*
+gda_oracle_provider_get_default_dbms_type (GdaServerProvider *provider, GdaConnection *cnc, GType type)
 {
-	gchar *sql;
-	GList *reclist;
-	GdaDataModel *recset;
-	GdaOracleIndexData *index_data;
-	GdaParameter *param;
-	GdaParameterList *query_params = gda_parameter_list_new (NULL);
-	GString *references;
-	gint nrows;
-	GString *colname;
-	GString *newcolname;
-	GHashTable *h_table = g_hash_table_new (g_str_hash, g_str_equal);
-	GValue *value;
-	gint i;
-
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-
-	sql = g_strdup ("SELECT c1.column_name column_name, "
-			"con.constraint_type constraint_type, "
-			"'' uniqueness, "
-			"c2.table_name reference "
-			"FROM all_cons_columns c1, all_cons_columns c2, all_constraints con "
-			"WHERE con.constraint_name = c1.constraint_name " 
-			"AND con.constraint_type = 'R' "
-			"AND con.constraint_type IS NOT NULL "
-			"AND c1.table_name = upper (:TBLNAME) "
-			"AND c1.owner = upper (:OWNER) "
-			"AND con.r_constraint_name = c2.constraint_name "
-			"UNION ALL "
-			"SELECT c.column_name column_name, "
-			"t.constraint_type constraint_type, "
-			"substr (i.uniqueness, 1, 6) uniqueness, "
-			"'' reference "
-			"FROM all_indexes i, all_ind_columns c, all_constraints t "
-			"WHERE i.table_name = upper (:TBLNAME) "
-			"AND i.table_owner = upper (:OWNER) "
-			"AND t.constraint_type != 'R' "
-			"AND i.index_name = c.index_name "
-			"AND i.index_name = t.constraint_name "
-			"ORDER BY 1" );
-
-	param = gda_parameter_new_string (":OWNER", owner);
-	gda_parameter_list_add_param (query_params, param);
-	g_object_unref (param);
-
-	param = gda_parameter_new_string (":TBLNAME", tblname);
-	gda_parameter_list_add_param (query_params, param);
-	g_object_unref (param);
-
-	reclist = process_sql_commands (NULL, cnc, sql, 
-					query_params, GDA_COMMAND_OPTION_STOP_ON_ERRORS, NULL);
-	if (!reclist)
-		return NULL;
-
-	recset = GDA_DATA_MODEL (reclist->data);
-	g_list_free (reclist);
-
-	nrows = gda_data_model_get_n_rows (recset);
-
-	if (nrows == 0) {
-		g_object_unref(recset);		
-		return NULL;
+	if (cnc) {
+		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+		g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
 	}
 
-	index_data = g_new0 (GdaOracleIndexData, 1);
-	references = g_string_new ("");
-
-	value = (GValue *)gda_data_model_get_value_at (recset, 0, 0);
-	colname = g_string_right_trim (g_string_new (g_value_get_string (value)));
-
-	for (i = 0; i < nrows; i += 1) {
-		gchar *constraint_type = "";
-
-		value = (GValue *)gda_data_model_get_value_at (recset, 1, i);
-		if (!value)
-			continue;
-		if (gda_value_is_null (value))
-			continue;
-
-		constraint_type = g_strdup (g_value_get_string (value));
-
-		if (!strcmp (constraint_type, "P"))
-			index_data->primary_key = TRUE;
-
-		value = (GValue *)gda_data_model_get_value_at (recset, 2, i);
-		if (value) 
-			if (!gda_value_is_null (value))
-				if (!strcmp (g_value_get_string (value), "UNIQUE"))  
-					index_data->unique = TRUE;
-
-		if (!strcmp (constraint_type, "R")) {
-			value = (GValue *)gda_data_model_get_value_at (recset, 3, i);
-			if (value)
-				if (!gda_value_is_null (value)) {
-					if (references->len > 0) 
-						references = g_string_append (references, ", ");
-					references = g_string_right_trim (g_string_append (references, g_value_get_string (value)));
-				}
-		}
+	TO_IMPLEMENT;
 
-		if (i == nrows - 1) {
-			index_data->references = g_strdup (references->str);
-			g_hash_table_insert (h_table, colname->str, index_data);
-			break;
-		}
+	if ((type == G_TYPE_INT64) ||
+	    (type == G_TYPE_INT) ||
+	    (type == GDA_TYPE_SHORT) ||
+	    (type == GDA_TYPE_USHORT) ||
+	    (type == G_TYPE_CHAR) ||
+	    (type == G_TYPE_UCHAR) ||
+	    (type == G_TYPE_ULONG) ||
+	    (type == G_TYPE_UINT) ||
+	    (type == G_TYPE_UINT64))
+		return "integer";
 
-		value = (GValue *)gda_data_model_get_value_at (recset, 0, i+1);
-		newcolname = g_string_right_trim (g_string_new (g_value_get_string (value)));
+	if ((type == GDA_TYPE_BINARY) ||
+	    (type == GDA_TYPE_BLOB))
+		return "blob";
 
-		if (strcmp (colname->str, newcolname->str)) {
-			index_data->references = g_strdup (references->str);
-			g_hash_table_insert (h_table, colname->str, index_data);
+	if (type == G_TYPE_BOOLEAN)
+		return "boolean";
+	
+	if ((type == G_TYPE_DATE) || 
+	    (type == GDA_TYPE_GEOMETRIC_POINT) ||
+	    (type == G_TYPE_OBJECT) ||
+	    (type == GDA_TYPE_LIST) ||
+	    (type == G_TYPE_STRING) ||
+	    (type == GDA_TYPE_TIME) ||
+	    (type == GDA_TYPE_TIMESTAMP) ||
+	    (type == G_TYPE_INVALID) ||
+	    (type == G_TYPE_GTYPE))
+		return "string";
+
+	if ((type == G_TYPE_DOUBLE) ||
+	    (type == GDA_TYPE_NUMERIC) ||
+	    (type == G_TYPE_FLOAT))
+		return "real";
+	
+	if (type == GDA_TYPE_TIME)
+		return "time";
+	if (type == GDA_TYPE_TIMESTAMP)
+		return "timestamp";
+	if (type == G_TYPE_DATE)
+		return "date";
 
-			index_data = g_new0 (GdaOracleIndexData, 1);
-			index_data->unique = FALSE;
-			index_data->primary_key = FALSE;
-			index_data->references = g_strdup ("");
-			references = g_string_new ("");
-			colname = g_string_new (newcolname->str);
-		}
-	}
-	g_object_unref(recset);
-	return h_table;
+	return "text";
 }
 
-
-
-static GdaDataModel *
-get_oracle_users (GdaConnection *cnc, GdaParameterList *params)
+/*
+ * Create parser request
+ *
+ * This method is responsible for creating a #GdaSqlParser object specific to the SQL dialect used
+ * by the database. See the PostgreSQL provider implementation for an example.
+ */
+static GdaSqlParser *
+gda_oracle_provider_create_parser (GdaServerProvider *provider, GdaConnection *cnc)
 {
-	GList *reclist;
-	GdaDataModel *recset;
-
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-
-	reclist = process_sql_commands (NULL, cnc, "SELECT USERNAME FROM USER_USERS",
-					NULL, GDA_COMMAND_OPTION_STOP_ON_ERRORS, NULL);
-
-	if (!reclist)
-		return NULL;
-
-	recset = GDA_DATA_MODEL (reclist->data);
-	g_list_free (reclist);
-
-	/* Set it here instead of the SQL query to allow i18n */
-	if (recset)
-		gda_server_provider_init_schema_model (recset, GDA_CONNECTION_SCHEMA_USERS);
-
-	return recset;
+	TO_IMPLEMENT;
+	return NULL;
 }
 
-static GdaDataModel *
-get_oracle_databases (GdaConnection *cnc, GdaParameterList *params)
+/*
+ * GdaStatement to SQL request
+ * 
+ * This method renders a #GdaStatement into its SQL representation.
+ *
+ * The implementation show here simply calls gda_statement_to_sql_extended() but the rendering
+ * can be specialized to the database's SQL dialect, see the implementation of gda_statement_to_sql_extended()
+ * and SQLite's specialized rendering for more details
+ */
+static gchar *
+gda_oracle_provider_statement_to_sql (GdaServerProvider *provider, GdaConnection *cnc,
+				    GdaStatement *stmt, GdaSet *params, GdaStatementSqlFlag flags,
+				    GSList **params_used, GError **error)
 {
-	GList *reclist;
-	GdaDataModel *recset;
-        gchar *sql = g_strdup ("SELECT TABLESPACE_NAME FROM USER_TABLESPACES");
-
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-
-	reclist = process_sql_commands (NULL, cnc, sql, NULL, 
-					GDA_COMMAND_OPTION_STOP_ON_ERRORS, NULL);
+	g_return_val_if_fail (GDA_IS_STATEMENT (stmt), NULL);
+	if (cnc) {
+		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+		g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
+	}
 
-	g_free (sql);
+	return gda_statement_to_sql_extended (stmt, cnc, params, flags, params_used, error);
+}
 
-	if (!reclist)
-		return NULL;
+/*
+ * Statement prepare request
+ *
+ * This methods "converts" @stmt into a prepared statement. A prepared statement is a notion
+ * specific in its implementation details to the C API used here. If successfull, it must create
+ * a new #GdaOraclePStmt object and declare it to @cnc.
+ */
+static gboolean
+gda_oracle_provider_statement_prepare (GdaServerProvider *provider, GdaConnection *cnc,
+				     GdaStatement *stmt, GError **error)
+{
+	GdaOraclePStmt *ps;
+	gboolean retval = FALSE;
 
-	recset = GDA_DATA_MODEL (reclist->data);
-	g_list_free (reclist);
+	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
+	g_return_val_if_fail (GDA_IS_STATEMENT (stmt), FALSE);
 
-	/* Set it here instead of the SQL query to allow i18n */
-	if (recset)
-		gda_server_provider_init_schema_model (recset, GDA_CONNECTION_SCHEMA_DATABASES);	
+	/* fetch prepares stmt if already done */
+	ps = (GdaOraclePStmt *) gda_connection_get_prepared_statement (cnc, stmt);
+	if (ps)
+		return TRUE;
 
-	return recset;
+	/* render as SQL understood by the provider */
+	GdaSet *params = NULL;
+	gchar *sql;
+	GSList *used_params = NULL;
+	if (! gda_statement_get_parameters (stmt, &params, error))
+                return FALSE;
+        sql = gda_oracle_provider_statement_to_sql (provider, cnc, stmt, params, GDA_STATEMENT_SQL_PARAMS_AS_UQMARK,
+						  &used_params, error);
+        if (!sql) 
+		goto out;
+
+	/* prepare @stmt using the C API, creates @ps */
+	TO_IMPLEMENT;
+
+	/* make a list of the parameter names used in the statement */
+	GSList *param_ids = NULL;
+        if (used_params) {
+                GSList *list;
+                for (list = used_params; list; list = list->next) {
+                        const gchar *cid;
+                        cid = gda_holder_get_id (GDA_HOLDER (list->data));
+                        if (cid) {
+                                param_ids = g_slist_append (param_ids, g_strdup (cid));
+                                /*g_print ("PREPARATION: param ID: %s\n", cid);*/
+                        }
+                        else {
+                                g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_PREPARE_STMT_ERROR,
+                                             "%s", _("Unnamed parameter is not allowed in prepared statements"));
+                                g_slist_foreach (param_ids, (GFunc) g_free, NULL);
+                                g_slist_free (param_ids);
+                                goto out;
+                        }
+                }
+        }
+	
+	/* create a prepared statement object */
+	/*ps = gda_oracle_pstmt_new (...);*/
+	gda_pstmt_set_gda_statement (_GDA_PSTMT (ps), stmt);
+        _GDA_PSTMT (ps)->param_ids = param_ids;
+        _GDA_PSTMT (ps)->sql = sql;
+
+	gda_connection_add_prepared_statement (cnc, stmt, (GdaPStmt *) ps);
+	g_object_unref (ps);
+
+	retval = TRUE;
+
+ out:
+	if (used_params)
+                g_slist_free (used_params);
+        if (params)
+                g_object_unref (params);
+	return retval;
 }
 
-static GdaDataModel *
-get_oracle_tables (GdaConnection *cnc, GdaParameterList *params)
+/*
+ * Execute statement request
+ *
+ * Executes a statement. This method should do the following:
+ *    - try to prepare the statement if not yet done
+ *    - optionnally reset the prepared statement
+ *    - bind the variables's values (which are in @params)
+ *    - add a connection event to log the execution
+ *    - execute the prepared statement
+ *
+ * If @stmt is an INSERT statement and @last_inserted_row is not NULL then additional actions must be taken to return the
+ * actual inserted row
+ */
+static GObject *
+gda_oracle_provider_statement_execute (GdaServerProvider *provider, GdaConnection *cnc,
+				     GdaStatement *stmt, GdaSet *params,
+				     GdaStatementModelUsage model_usage, 
+				     GType *col_types, GdaSet **last_inserted_row, 
+				     guint *task_id, 
+				     GdaServerProviderExecCallback async_cb, gpointer cb_data, GError **error)
 {
-	GdaDataModel *recset;
-	GdaParameter *par = NULL;
-	gchar *upc_namespace = NULL;
-	GList *reclist;
-	gchar *sql;
-	GdaOracleConnectionData *priv_data;
+	GdaOraclePStmt *ps;
+	OracleConnectionData *cdata;
+	gboolean allow_noparam;
+        gboolean empty_rs = FALSE; /* TRUE when @allow_noparam is TRUE and there is a problem with @params
+                                      => resulting data model will be empty (0 row) */
 
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-	priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
-	if (!priv_data)
-		return FALSE;
-
-	if (params) 
-		par = gda_parameter_list_find_param (params, "namespace");
+	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
+	g_return_val_if_fail (GDA_IS_STATEMENT (stmt), NULL);
 
-	if (par) {
-		const gchar  *namespace;
-		namespace = g_value_get_string ((GValue *) gda_parameter_get_value (par));
-		upc_namespace = g_ascii_strup (namespace, -1);
+	/* If asynchronous connection opening is not supported, then exit now */
+	if (async_cb) {
+		g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_METHOD_NON_IMPLEMENTED_ERROR,
+			     "%s", _("Provider does not support asynchronous statement execution"));
+                return NULL;
 	}
-	else
-		upc_namespace = g_ascii_strup (priv_data->schema, -1);
-	sql = g_strdup_printf ("SELECT t.table_name, t.owner, c.comments, NULL FROM ALL_TABLES t join ALL_TAB_COMMENTS c on (t.table_name=c.table_name AND t.owner=c.owner) WHERE t.OWNER='%s' ORDER BY TABLE_NAME",
-			       upc_namespace);
-	g_free (upc_namespace);
-	    
-	reclist = process_sql_commands (NULL, cnc, sql, NULL, 
-					GDA_COMMAND_OPTION_STOP_ON_ERRORS, NULL);
-	g_free (sql);
-
-	if (!reclist)
-		return NULL;
+
+        allow_noparam = (model_usage & GDA_STATEMENT_MODEL_ALLOW_NOPARAM) &&
+                (gda_statement_get_statement_type (stmt) == GDA_SQL_STATEMENT_SELECT);
 	
-	recset = GDA_DATA_MODEL (reclist->data);
-	g_list_free (reclist);
+        if (last_inserted_row)
+                *last_inserted_row = NULL;
 
-	/* Set it here instead of the SQL query to allow i18n */
-	if (recset)
-		gda_server_provider_init_schema_model (recset, GDA_CONNECTION_SCHEMA_TABLES);
+	/* Get private data */
+	cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
+		return FALSE;
 
-	return recset;
-}
 
-static GdaDataModel *
-get_oracle_views (GdaConnection *cnc, GdaParameterList *params)
-{
-	GdaDataModel *recset;
-	GdaParameter *par = NULL;
-	gchar *upc_namespace = NULL;
-	GList *reclist;
-	gchar *sql;
-	GdaOracleConnectionData *priv_data;
-	GArray *col_size_array = NULL;
+	/* get/create new prepared statement */
+	ps = (GdaOraclePStmt *) gda_connection_get_prepared_statement (cnc, stmt);
+	if (!ps) {
+		if (!gda_oracle_provider_statement_prepare (provider, cnc, stmt, NULL)) {
+			/* this case can appear for example if some variables are used in places
+			 * where the C API cannot allow them (for example if the variable is the table name
+			 * in a SELECT statement). The action here is to get the actual SQL code for @stmt,
+			 * and use that SQL instead of @stmt to create another GdaOraclePStmt object.
+			 *
+			 * Don't call gda_connection_add_prepared_statement() with this new prepared statement
+			 * as it will be destroyed once used.
+			 */
+			TO_IMPLEMENT;
+			return NULL;
+		}
+		else {
+			ps = (GdaOraclePStmt *) gda_connection_get_prepared_statement (cnc, stmt);
+			g_object_ref (ps);
+		}
+	}
+	else
+		g_object_ref (ps);
+	g_assert (ps);
 
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-	priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
-	if (!priv_data)
-		return FALSE;
+	/* optionnally reset the prepared statement if required by the API */
+	TO_IMPLEMENT;
 	
-	if (params) 
-		par = gda_parameter_list_find_param (params, "namespace");
+	/* bind statement's parameters */
+	GSList *list;
+	GdaConnectionEvent *event = NULL;
+	int i;
+	for (i = 1, list = _GDA_PSTMT (ps)->param_ids; list; list = list->next, i++) {
+		const gchar *pname = (gchar *) list->data;
+		GdaHolder *h;
+		
+		/* find requested parameter */
+		if (!params) {
+			event = gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR);
+			gda_connection_event_set_description (event, _("Missing parameter(s) to execute query"));
+			g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+				     GDA_SERVER_PROVIDER_MISSING_PARAM_ERROR,
+				     "%s", _("Missing parameter(s) to execute query"));
+			break;
+		}
 
-	if (par) {
-		const gchar  *namespace;
-		namespace = g_value_get_string ((GValue *) gda_parameter_get_value (par));
-		upc_namespace = g_ascii_strup (namespace, -1);
-	}
-	else
-		upc_namespace = g_ascii_strup (priv_data->schema, -1);
-
-	/* get the max size of the "text" column */
-	sql = g_strdup_printf ("SELECT max (v.text_length) FROM all_views v WHERE v.owner= '%s'", 
-			       upc_namespace);
-	reclist = process_sql_commands (NULL, cnc, sql, NULL, GDA_COMMAND_OPTION_STOP_ON_ERRORS, NULL);
-	g_free (sql);
-
-	if (reclist) {
-		GdaDataModel *recset = (GdaDataModel *) reclist->data;
-		if (GDA_IS_DATA_MODEL (recset)) {
-			if (gda_data_model_get_n_rows (recset) == 1) {
-				const GValue *val;
-				val = gda_data_model_get_value_at (recset, 0, 0);
-				if (val) {
-					const GdaNumeric *num;
-					ub2 size;
-
-					num = gda_value_get_numeric (val);
-					col_size_array = g_array_sized_new (FALSE, TRUE, sizeof (ub2), 4);
-					size = atoi (num->number);
-					g_array_set_size (col_size_array, 4);
-					g_array_insert_vals (col_size_array, 3, &size, 1);
-				}
+		h = gda_set_get_holder (params, pname);
+		if (!h) {
+			gchar *tmp = gda_alphanum_to_text (g_strdup (pname + 1));
+			if (tmp) {
+				h = gda_set_get_holder (params, tmp);
+				g_free (tmp);
 			}
 		}
-		g_object_unref (recset);
-		g_list_free (reclist);
-	}
-
-	/* real SQL */
-	sql = g_strdup_printf ("SELECT v.view_name, v.owner, NULL, v.text FROM ALL_VIEWS v WHERE v.OWNER='%s' ORDER BY VIEW_NAME",
-			       upc_namespace);
-	g_free (upc_namespace);
+		if (!h) {
+			if (! allow_noparam) {
+				gchar *str;
+				str = g_strdup_printf (_("Missing parameter '%s' to execute query"), pname);
+				event = gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR);
+				gda_connection_event_set_description (event, str);
+				g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+					     GDA_SERVER_PROVIDER_MISSING_PARAM_ERROR, "%s", str);
+				g_free (str);
+				break;
+			}
+			else {
+                                /* bind param to NULL */
+                                TO_IMPLEMENT;
+                                empty_rs = TRUE;
+                                continue;
+                        }
 
-	reclist = process_sql_commands (NULL, cnc, sql, NULL, 
-					GDA_COMMAND_OPTION_STOP_ON_ERRORS, col_size_array);
-	if (col_size_array)
-		g_array_free (col_size_array, TRUE);
-	g_free (sql);
+		}
+		if (!gda_holder_is_valid (h)) {
+			if (! allow_noparam) {
+				gchar *str;
+				str = g_strdup_printf (_("Parameter '%s' is invalid"), pname);
+				event = gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR);
+				gda_connection_event_set_description (event, str);
+				g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+					     GDA_SERVER_PROVIDER_MISSING_PARAM_ERROR, "%s", str);
+				g_free (str);
+				break;
+			}
+			else {
+                                /* bind param to NULL */
+				TO_IMPLEMENT;
+                                empty_rs = TRUE;
+                                continue;
+                        }
+		}
 
-	if (!reclist)
+		/* actual binding using the C API, for parameter at position @i */
+		const GValue *value = gda_holder_get_value (h);
+		TO_IMPLEMENT;
+	}
+		
+	if (event) {
+		gda_connection_add_event (cnc, event);
+		g_object_unref (ps);
 		return NULL;
+	}
 	
-	recset = GDA_DATA_MODEL (reclist->data);
-	g_list_free (reclist);
+	/* add a connection event for the execution */
+	event = gda_connection_event_new (GDA_CONNECTION_EVENT_COMMAND);
+        gda_connection_event_set_description (event, _GDA_PSTMT (ps)->sql);
+        gda_connection_add_event (cnc, event);
+
+	if (empty_rs) {
+		/* There are some missing parameters, so the SQL can't be executed but we still want
+		 * to execute something to get the columns correctly. A possibility is to actually
+		 * execute another SQL which is the code shown here.
+		 *
+		 * To adapt depending on the C API and its features */
+		GdaStatement *estmt;
+                gchar *esql;
+                estmt = gda_select_alter_select_for_empty (stmt, error);
+                if (!estmt) {
+			g_object_unref (ps);
+                        return NULL;
+		}
+                esql = gda_statement_to_sql (estmt, NULL, error);
+                g_object_unref (estmt);
+                if (!esql) {
+			g_object_unref (ps);
+                        return NULL;
+		}
 
-	/* Set it here instead of the SQL query to allow i18n */
-	if (recset)
-		gda_server_provider_init_schema_model (recset, GDA_CONNECTION_SCHEMA_VIEWS);	
+		/* Execute the 'esql' SQL code */
+                g_free (esql);
 
-	return recset;
+		TO_IMPLEMENT;
+	}
+	else {
+		/* Execute the _GDA_PSTMT (ps)->sql SQL code */
+		TO_IMPLEMENT;
+	}
+	
+	/* execute prepared statement using C API depending on its kind */
+	if (! g_ascii_strncasecmp (_GDA_PSTMT (ps)->sql, "SELECT", 6) ||
+            ! g_ascii_strncasecmp (_GDA_PSTMT (ps)->sql, "EXPLAIN", 7)) {
+		GObject *data_model;
+		GdaDataModelAccessFlags flags;
+
+		if (model_usage & GDA_STATEMENT_MODEL_RANDOM_ACCESS)
+			flags = GDA_DATA_MODEL_ACCESS_RANDOM;
+		else
+			flags = GDA_DATA_MODEL_ACCESS_CURSOR_FORWARD;
+
+                data_model = (GObject *) gda_oracle_recordset_new (cnc, ps, params, flags, col_types);
+		gda_connection_internal_statement_executed (cnc, stmt, params, NULL); /* required: help @cnc keep some stats */
+		g_object_unref (ps);
+		return data_model;
+        }
+	else {
+		GdaSet *set = NULL;
+
+		TO_IMPLEMENT;
+                /* Create a #GdaSet containing "IMPACTED_ROWS" */
+		/* Create GdaConnectionEvent notice with the type of command and impacted rows */
+
+		gda_connection_internal_statement_executed (cnc, stmt, params, event); /* required: help @cnc keep some stats */
+		g_object_unref (ps);
+		return (GObject*) set;
+	}
 }
 
 /*
- * get_oracle_objects
- *
- * This function gets the objects of the given schema type from the
- * database.  This is done by quering against the USER_OBJECTS
- * table which the OBJECT_TYPE parameter set to the appropriate
- * value.  This makes use of parameter binding, so it is a good
- * test to see if that is working for strings
- *
- * We effectively ignore the GdaParameterList we are given
- * because I don't want to rely on it being empty, and I can't
- * see any use for any user passed parameters at this point.
+ * starts a distributed transaction: put the XA transaction in the ACTIVE state
  */
-static GdaDataModel *
-get_oracle_objects (GdaConnection *cnc, GdaParameterList *params, GdaConnectionSchema schema, gint nargs, const gchar *title)
+static gboolean
+gda_oracle_provider_xa_start (GdaServerProvider *provider, GdaConnection *cnc, 
+				const GdaXaTransactionId *xid, GError **error)
 {
-	GList *reclist;
-	GdaDataModel *recset;
-	gint cnt;
-	GdaParameterList *query_params = gda_parameter_list_new (NULL);
-	GdaParameter *param;
-        GString *sql;
+	OracleConnectionData *cdata;
 
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
+	g_return_val_if_fail (xid, FALSE);
 
-	sql = g_string_new ("SELECT OBJECT_NAME");
-	for (cnt = 1; cnt < nargs; cnt++)
-		sql = g_string_append (sql, ", NULL");
-
-	sql = g_string_append (sql, " FROM USER_OBJECTS WHERE OBJECT_TYPE=:OBJ_TYPE");
-
-	/* add the object type parameter */
-	switch (schema) {
-	case GDA_CONNECTION_SCHEMA_INDEXES:
-		param = gda_parameter_new_string (":OBJ_TYPE", "INDEX");		
-		gda_parameter_list_add_param (query_params, param);
-		g_object_unref (param);
-		break;
-	case GDA_CONNECTION_SCHEMA_PROCEDURES:
-		param = gda_parameter_new_string (":OBJ_TYPE", "PROCEDURE");
-		gda_parameter_list_add_param (query_params, param);
-		g_object_unref (param);
-		break;
-	case GDA_CONNECTION_SCHEMA_SEQUENCES:
-		param = gda_parameter_new_string (":OBJ_TYPE", "SEQUENCE");
-		gda_parameter_list_add_param (query_params, param);
-		g_object_unref (param);
-		break;
-	case GDA_CONNECTION_SCHEMA_TRIGGERS:
-		param = gda_parameter_new_string (":OBJ_TYPE", "TRIGGER");
-		gda_parameter_list_add_param (query_params, param);
-		g_object_unref (param);
-		break;
-	case GDA_CONNECTION_SCHEMA_VIEWS:
-		param = gda_parameter_new_string (":OBJ_TYPE", "VIEW");
-		gda_parameter_list_add_param (query_params, param);
-		g_object_unref (param);
-		break;
-	default:
-		return NULL;
-	}
+	cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
+		return FALSE;
 
-	reclist = process_sql_commands (NULL, cnc, sql->str, query_params,
-					GDA_COMMAND_OPTION_STOP_ON_ERRORS, NULL);
+	TO_IMPLEMENT;
+	return FALSE;
+}
 
-	g_object_unref (query_params);
-	g_string_free (sql, TRUE);
+/*
+ * put the XA transaction in the IDLE state: the connection won't accept any more modifications.
+ * This state is required by some database providers before actually going to the PREPARED state
+ */
+static gboolean
+gda_oracle_provider_xa_end (GdaServerProvider *provider, GdaConnection *cnc, 
+			      const GdaXaTransactionId *xid, GError **error)
+{
+	OracleConnectionData *cdata;
 
-	if (!reclist)
-		return NULL;
-	recset = GDA_DATA_MODEL (reclist->data);
+	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
+	g_return_val_if_fail (xid, FALSE);
 
-	/* Set it here instead of the SQL query to allow i18n */
-	if (recset)
-		gda_server_provider_init_schema_model (recset, schema);
+	cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
+		return FALSE;
 
-	g_list_free (reclist);
-	
-	return recset;
+	TO_IMPLEMENT;
+	return FALSE;
 }
 
-typedef struct
+/*
+ * prepares the distributed transaction: put the XA transaction in the PREPARED state
+ */
+static gboolean
+gda_oracle_provider_xa_prepare (GdaServerProvider *provider, GdaConnection *cnc, 
+				  const GdaXaTransactionId *xid, GError **error)
 {
-	const gchar  *name;
-	GType         type;
-	const gchar  *synonyms;
-	const gchar  *comments;
-} ora_native_type;
+	OracleConnectionData *cdata;
 
+	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
+	g_return_val_if_fail (xid, FALSE);
 
-static GdaDataModel *
-get_oracle_types (GdaConnection *cnc, GdaParameterList *params)
-{
-	GdaDataModelArray *recset;
-	ora_native_type   *otp;
-	GList             *value_list;
-	GValue *tmpval;
-
-	ora_native_type ora_type_tab[] = {
-		{"BFILE",     GDA_TYPE_BLOB, NULL, "Pointer to binary file on disk"},
-		{"BLOB",      GDA_TYPE_BLOB, NULL, "Binary Large Object"},
-		{"CHAR",      G_TYPE_STRING, "CHARACTER", "Fixed length character data of length size bytes. This should be used for fixed length data. Such as codes A100, B102..."},
-		{"NCHAR",     G_TYPE_STRING, NULL, "Fixed length national character set data of length size bytes. This should be used for fixed length data. Such as codes A100, B102..."},
-		{"CLOB",      G_TYPE_STRING, NULL, "Character Large Object"},
-		{"NCLOB",     GDA_TYPE_BLOB, NULL, "National Character Large Object"},
-		{"DATE",      G_TYPE_DATE, NULL, "Valid date range"},
-		{"NUMBER",    GDA_TYPE_NUMERIC, "INTEGER,SMALLINT,INT,DEC,DECIMAL,NUMERIC,DOUBLE PRECISION,FLOAT,REAL", "Number having precision p and scale s."},
-		{"LONG",      G_TYPE_STRING, NULL, "Character data of variable length (A bigger version the VARCHAR2 datatype)"},
-		{"LONG RAW",  GDA_TYPE_BLOB, NULL, "Raw binary data of variable length. (not intrepreted by PL/SQL)"},
-		{"RAW",       GDA_TYPE_BLOB, NULL, "Raw binary data of length size bytes (size must be specified)"},
-		{"ROWID",     G_TYPE_STRING, NULL, "Hexadecimal string representing the unique address of a row in its table (primarily for values returned by the ROWID pseudocolumn.)"},
-		{"UROWID",    G_TYPE_STRING, NULL, "Hex string representing the logical address of a row of an index-organized table"},
-		{"TIMESTAMP", GDA_TYPE_TIMESTAMP, NULL, "the number of digits in the fractional part of the SECOND datetime field"},
-		{"VARCHAR2",  G_TYPE_STRING, "VARCHAR,STRING", "Variable length character string having maximum length size bytes (size must be specified)"},
-		{"NVARCHAR2", G_TYPE_STRING, NULL, "Variable length national character set string having maximum length size bytes (size must be specified)"},
-		{"XMLType", G_TYPE_STRING, NULL, "XML data)"},
-	};
-	ora_native_type *ora_type_end = ora_type_tab+sizeof(ora_type_tab)/sizeof(ora_native_type);
-
-	/* create the recordset */
-	recset = GDA_DATA_MODEL_ARRAY (gda_data_model_array_new 
-				       (gda_server_provider_get_schema_nb_columns (GDA_CONNECTION_SCHEMA_TYPES)));
-	gda_server_provider_init_schema_model (GDA_DATA_MODEL (recset), GDA_CONNECTION_SCHEMA_TYPES);
-
-	/* fill the recordset */
-	for (otp = ora_type_tab; otp < ora_type_end; otp++) {
-		value_list = NULL;
-
-		g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), otp->name);
-		value_list = g_list_append (value_list, tmpval);
-
-		g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), "SYS");
-		value_list = g_list_append (value_list, tmpval);
-
-		g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), otp->comments);
-		value_list = g_list_append (value_list, tmpval);
-
-		g_value_set_ulong (tmpval = gda_value_new (G_TYPE_ULONG), otp->type);
-		value_list = g_list_append (value_list, tmpval);
-
-		g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), otp->synonyms);
-		value_list = g_list_append (value_list, tmpval);
-		
-		gda_data_model_append_values (GDA_DATA_MODEL (recset), value_list, NULL);
-		g_list_foreach (value_list, (GFunc) gda_value_free, NULL);
-		g_list_free (value_list);
-	}
-	return GDA_DATA_MODEL (recset);
+	cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
+		return FALSE;
+
+	TO_IMPLEMENT;
+	return FALSE;
 }
 
-static GdaDataModel *
-get_oracle_fields_metadata (GdaConnection *cnc, GdaParameterList *params)
+/*
+ * commits the distributed transaction: actually write the prepared data to the database and
+ * terminates the XA transaction
+ */
+static gboolean
+gda_oracle_provider_xa_commit (GdaServerProvider *provider, GdaConnection *cnc, 
+				 const GdaXaTransactionId *xid, GError **error)
 {
-	GdaParameter *par;
-	const gchar *tblname;
-	gchar *upc_tblname;
-	GList *reclist;
-	gchar *sql;
-	GdaOracleConnectionData *priv_data;
-	GArray *col_size_array = NULL;
+	OracleConnectionData *cdata;
 
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-	g_return_val_if_fail (params, NULL);
+	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
+	g_return_val_if_fail (xid, FALSE);
 
-	/* look up the table name to get the fully qualified name. */
-	priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
-	if (!priv_data)
+	cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
 		return FALSE;
 
-	par = gda_parameter_list_find_param (params, "name");
-	g_return_val_if_fail (par, NULL);
-	
-	tblname = g_value_get_string ((GValue *) gda_parameter_get_value (par));
-	g_return_val_if_fail (tblname, NULL);
-	upc_tblname = g_ascii_strup (tblname, -1);
-
-	/* get the max size of the "default value" column */
-	sql = g_strdup_printf ("SELECT max (t.default_length) FROM all_tab_columns t WHERE t.owner= '%s' and t.table_name= '%s'", priv_data->schema, upc_tblname);
-	reclist = process_sql_commands (NULL, cnc, sql, NULL, GDA_COMMAND_OPTION_STOP_ON_ERRORS, NULL);
-	g_free (sql);
-
-	if (reclist) {
-		GdaDataModel *recset = (GdaDataModel *) reclist->data;
-		if (GDA_IS_DATA_MODEL (recset)) {
-			if (gda_data_model_get_n_rows (recset) == 1) {
-				const GValue *val;
-				val = gda_data_model_get_value_at (recset, 0, 0);
-				if (val) {
-					const GdaNumeric *num;
-					ub2 size;
-
-					num = gda_value_get_numeric (val);
-					col_size_array = g_array_sized_new (FALSE, TRUE, sizeof (ub2), 9);
-					size = atoi (num->number);
-					g_array_set_size (col_size_array, 9);
-					g_array_insert_vals (col_size_array, 8, &size, 1);
-				}
-			}
-		}
-		g_object_unref (recset);
-		g_list_free (reclist);
-	}
-
-	/* real SQL */
-	sql = g_strdup_printf ("select t.column_name \"Column\", t.data_type \"DataType\", CASE t.char_used WHEN 'B' THEN t.data_length ELSE t.data_precision END \"Size\", t.data_scale, CASE t.nullable WHEN 'N' THEN 1 ELSE 0 END \"NotNull\", CASE WHEN c1.column_name IS NOT NULL THEN 1 ELSE 0 END \"pkey\", CASE WHEN c2.column_name IS NOT NULL OR c1.column_name IS NOT NULL THEN 1 ELSE 0 END \"uindex\", NULL, t.data_default, NULL FROM all_tab_columns t left join (SELECT i.column_name, ac.owner FROM all_constraints ac join all_ind_columns i ON (i.index_name=ac.index_name AND i.table_name=ac.table_name) where ac.constraint_type= 'P' AND ac.table_name= '%s' ) c1 on (c1.column_name=t.column_name AND c1.owner=t.owner) left join (SELECT i.column_name, ac.owner FROM all_constraints ac join all_ind_columns i ON (i.index_name=ac.index_name AND i.table_name=ac.table_name) where ac.constraint_type= 'U' AND ac.table_name= '%s' ) c2 on (c2.column_name=t.column_name AND c2.owner=t.owner) where t.ta
 ble_name= '%s' AND t.owner='%s' order by t.column_id",
-			       upc_tblname, upc_tblname, upc_tblname, priv_data->schema);
-	
-	g_free(upc_tblname);
-	reclist = process_sql_commands (NULL, cnc, sql, NULL, 
-					GDA_COMMAND_OPTION_STOP_ON_ERRORS, col_size_array);
-	if (col_size_array)
-		g_array_free (col_size_array, TRUE);
-	g_free (sql);
-
-	if (!reclist)
-		return NULL;
-	else {
-		GdaDataModelArray *recset;
-		GdaDataModel *tmprecset;
-		GError *error = NULL;
-
-		tmprecset = GDA_DATA_MODEL (reclist->data);
-
-		recset = GDA_DATA_MODEL_ARRAY (gda_data_model_array_new 
-					       (gda_server_provider_get_schema_nb_columns (GDA_CONNECTION_SCHEMA_FIELDS)));
-		gda_server_provider_init_schema_model (GDA_DATA_MODEL (recset), GDA_CONNECTION_SCHEMA_FIELDS);
-		if (!gda_data_model_import_from_model (GDA_DATA_MODEL (recset), tmprecset, FALSE, NULL, &error)) {
-			gda_data_model_dump (tmprecset, stdout);
-			g_warning (_("Can't convert model for fields schema: %s"),
-				   error && error->message ?  error->message : _("No detail"));
-			g_error_free (error);
-			g_object_unref (recset);
-			recset = NULL;
-		}
-
-		g_object_unref (tmprecset);
-		g_list_free (reclist);
-		return GDA_DATA_MODEL (recset);
-	}
+	TO_IMPLEMENT;
+	return FALSE;
 }
 
-
-/* get_schema handler for the GdaOracleProvider class */
-static GdaDataModel *
-gda_oracle_provider_get_schema (GdaServerProvider *provider,
-				GdaConnection *cnc,
-				GdaConnectionSchema schema,
-				GdaParameterList *params)
+/*
+ * Rolls back an XA transaction, possible only if in the ACTIVE, IDLE or PREPARED state
+ */
+static gboolean
+gda_oracle_provider_xa_rollback (GdaServerProvider *provider, GdaConnection *cnc, 
+				   const GdaXaTransactionId *xid, GError **error)
 {
-	GdaDataModel *recset;
+	OracleConnectionData *cdata;
 
-	if (cnc)
-		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-	else
-		return NULL;
-
-	switch (schema) {
-	case GDA_CONNECTION_SCHEMA_AGGREGATES :
-		recset = get_oracle_aggregates (cnc, params);
-		break;
-	case GDA_CONNECTION_SCHEMA_FIELDS :
-		recset = get_oracle_fields_metadata (cnc, params);
-		break;
-	case GDA_CONNECTION_SCHEMA_TYPES :
-		recset = get_oracle_types (cnc, params);
-		break;
-	case GDA_CONNECTION_SCHEMA_USERS :
-		recset = get_oracle_users (cnc, params);
-		break;
-	case GDA_CONNECTION_SCHEMA_DATABASES :
-		recset = get_oracle_databases (cnc, params);
-		break;
-	case GDA_CONNECTION_SCHEMA_INDEXES :
-		recset = get_oracle_objects (cnc, params, schema, 1, _("Indexes"));
-		break;
-	case GDA_CONNECTION_SCHEMA_PROCEDURES :
-		recset = get_oracle_objects (cnc, params, schema, 8, _("Procedures"));
-		break;
-	case GDA_CONNECTION_SCHEMA_SEQUENCES :
-		recset = get_oracle_objects (cnc, params, schema, 4, _("Sequences"));
-		break;
-	case GDA_CONNECTION_SCHEMA_TABLES :
-		recset = get_oracle_tables (cnc, params);
-		break;
-	case GDA_CONNECTION_SCHEMA_TRIGGERS :
-		recset = get_oracle_objects (cnc, params, schema, 1, _("Triggers"));
-		break;
-	case GDA_CONNECTION_SCHEMA_VIEWS :
-		recset = get_oracle_views (cnc, params);
-		break;
-	default :
-		recset = NULL;
-	}
-	return recset;
-}
+	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
+	g_return_val_if_fail (xid, FALSE);
 
-/*
-  Local Variables:
-  mode:C
-  c-basic-offset: 8
-  End:
-*/
+	cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
+		return FALSE;
 
-static const gchar*
-gda_oracle_provider_get_default_dbms_type (GdaServerProvider *provider,
-					   GdaConnection *cnc,
-					   GType type)
-{
-	g_return_val_if_fail (GDA_IS_SERVER_PROVIDER (provider), NULL);
-
-	if (type == G_TYPE_INT64)
-		return "NUMBER(38)";
-	if (type == G_TYPE_UINT64)
-		return "NUMBER(38)";
-	if (type == GDA_TYPE_BLOB)
-		return "BLOB";
-	if (type == G_TYPE_BOOLEAN)
-		return "NUMBER(1)";
-	if (type == G_TYPE_DATE)
-		return "DATE";
-	if (type == G_TYPE_DOUBLE)
-		return "NUMBER";
-	if (type == GDA_TYPE_GEOMETRIC_POINT)
-		return "SDO_GEOMETRY";
-	if (type == G_TYPE_OBJECT)
-		return "CLOB";
-	if (type == G_TYPE_INT)
-		return "NUMBER(38)";
-	if (type == GDA_TYPE_LIST)
-		return "CLOB";
-	if (type == GDA_TYPE_NUMERIC)
-		return "NUMBER";
-	if (type == G_TYPE_FLOAT)
-		return "NUMBER";
-	if (type == GDA_TYPE_SHORT)
-		return "NUMBER(38)";
-	if (type == GDA_TYPE_USHORT)
-		return "NUMBER(38)";
-	if (type == G_TYPE_STRING)
-		return "VARCHAR2";
-	if (type == GDA_TYPE_TIME)
-		return "DATE";
-	if (type == GDA_TYPE_TIMESTAMP)
-		return "TIMESTAMP";
-	if (type == G_TYPE_CHAR)
-		return "CHAR";
-	if (type == G_TYPE_UCHAR)
-		return "CHAR";
-	if (type == G_TYPE_ULONG)
-		return "NUMBER(38)";
-        if (type == G_TYPE_UINT)
-		return "NUMBER(38)";
-	if (type == G_TYPE_INVALID)
-		return "CLOB";
-
-	return "CLOB";
+	TO_IMPLEMENT;
+	return FALSE;
 }
 
-static GdaDataHandler *
-gda_oracle_provider_get_data_handler (GdaServerProvider *provider,
-				      GdaConnection *cnc,
-				      GType type,
-				      const gchar *dbms_type)
+/*
+ * Lists all XA transactions that are in the PREPARED state
+ *
+ * Returns: a list of GdaXaTransactionId structures, which will be freed by the caller
+ */
+static GList *
+gda_oracle_provider_xa_recover (GdaServerProvider *provider, GdaConnection *cnc,
+				  GError **error)
 {
-	GdaDataHandler *dh = NULL;
+	OracleConnectionData *cdata;
 
-	/* REM: bin and blob types can't be translated to and from SQL in oracle, you must use
-	 * provider's specific virtual methods */
+	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
 
-	g_return_val_if_fail (GDA_IS_SERVER_PROVIDER (provider), FALSE);
-	if (cnc) 
-		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
-	
-        if ((type == G_TYPE_INT64) ||
-	    (type == G_TYPE_UINT64) ||
-	    (type == G_TYPE_DOUBLE) ||
-	    (type == G_TYPE_INT) ||
-	    (type == GDA_TYPE_NUMERIC) ||
-	    (type == G_TYPE_FLOAT) ||
-	    (type == GDA_TYPE_SHORT) ||
-	    (type == GDA_TYPE_USHORT) ||
-	    (type == G_TYPE_CHAR) ||
-	    (type == G_TYPE_UCHAR) ||
-	    (type == G_TYPE_UINT)) {
-		dh = gda_server_provider_handler_find (provider, NULL, type, NULL);
-		if (!dh) {
-			dh = gda_handler_numerical_new ();
-			gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_INT64, NULL);
-			gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_UINT64, NULL);
-			gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_DOUBLE, NULL);
-			gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_INT, NULL);
-			gda_server_provider_handler_declare (provider, dh, NULL, GDA_TYPE_NUMERIC, NULL);
-			gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_FLOAT, NULL);
-			gda_server_provider_handler_declare (provider, dh, NULL, GDA_TYPE_SHORT, NULL);
-			gda_server_provider_handler_declare (provider, dh, NULL, GDA_TYPE_USHORT, NULL);
-			gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_CHAR, NULL);
-			gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_UCHAR, NULL);
-			gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_UINT, NULL);
-			g_object_unref (dh);
-		}
-	}
-        else if (type == G_TYPE_BOOLEAN) {
-		dh = gda_server_provider_handler_find (provider, NULL, type, NULL);
-		if (!dh) {
-			dh = gda_handler_boolean_new ();
-			gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_BOOLEAN, NULL);
-			g_object_unref (dh);
-		}
-	}
-	else if ((type == G_TYPE_DATE) ||
-		 (type == GDA_TYPE_TIME) ||
-		 (type == GDA_TYPE_TIMESTAMP)) {
-		dh = gda_server_provider_handler_find (provider, NULL, type, NULL);
-		if (!dh) {
-			dh = gda_handler_time_new ();
-			gda_handler_time_set_sql_spec (GDA_HANDLER_TIME (dh), 
-						       G_DATE_MONTH, G_DATE_DAY,G_DATE_YEAR,
-						       '/', FALSE);
-			gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_DATE, NULL);
-			gda_server_provider_handler_declare (provider, dh, NULL, GDA_TYPE_TIME, NULL);
-			gda_server_provider_handler_declare (provider, dh, NULL, GDA_TYPE_TIMESTAMP, NULL);
-			g_object_unref (dh);
-		}
-	}
-	else if (type == G_TYPE_STRING) {
-		dh = gda_server_provider_handler_find (provider, NULL, type, NULL);
-		if (!dh) {
-			dh = gda_handler_string_new ();
-			gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_STRING, NULL);
-			g_object_unref (dh);
-		}
-	}
-	else if (type == G_TYPE_ULONG) {
-		dh = gda_server_provider_handler_find (provider, NULL, type, NULL);
-		if (!dh) {
-			dh = gda_handler_type_new ();
-			gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_ULONG, NULL);
-			g_object_unref (dh);
-		}
-	}
-	else {
-		/* special case: we take into account the dbms_type argument */
-		if (dbms_type)
-			TO_IMPLEMENT;
-	}
+	cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
+		return NULL;
 
-	return dh;	
+	TO_IMPLEMENT;
+	return NULL;
 }
 
-static GdaSqlParser *
-gda_oracle_provider_create_parser (GdaServerProvider *provider, GdaConnection *cnc)
+/*
+ * Free connection's specific data
+ */
+static void
+gda_oracle_free_cnc_data (OracleConnectionData *cdata)
 {
-        g_return_val_if_fail (GDA_IS_SERVER_PROVIDER (provider), NULL);
-        return (GdaSqlParser*) g_object_new (GDA_TYPE_SQL_PARSER, "tokenizer-flavour", 
-					     GDA_SQL_PARSER_FLAVOUR_ORACLE, NULL);
+	if (!cdata)
+		return;
+
+	TO_IMPLEMENT;
+	g_free (cdata);
 }
diff --git a/providers/oracle/gda-oracle-provider.h b/providers/oracle/gda-oracle-provider.h
index c795b2f..5e0338c 100644
--- a/providers/oracle/gda-oracle-provider.h
+++ b/providers/oracle/gda-oracle-provider.h
@@ -1,30 +1,29 @@
-/* GNOME DB Oracle Provider
- * Copyright (C) 2000 - 2007 The GNOME Foundation
+/* GDA oracle provider
+ * Copyright (C) 2008 The GNOME Foundation.
  *
  * AUTHORS:
- *         Rodrigo Moya <rodrigo gnome-db org>
- *         Tim Coleman <tim timcoleman com>
+ *      TO_ADD: your name and email
  *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
  *
- * This library is distributed in the hope that it will be useful,
+ * This Library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Library General Public License for more details.
  *
  * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
  */
 
 #ifndef __GDA_ORACLE_PROVIDER_H__
 #define __GDA_ORACLE_PROVIDER_H__
 
 #include <libgda/gda-server-provider.h>
-#include <oci.h>
 
 #define GDA_TYPE_ORACLE_PROVIDER            (gda_oracle_provider_get_type())
 #define GDA_ORACLE_PROVIDER(obj)            (G_TYPE_CHECK_INSTANCE_CAST (obj, GDA_TYPE_ORACLE_PROVIDER, GdaOracleProvider))
@@ -36,39 +35,17 @@ typedef struct _GdaOracleProvider      GdaOracleProvider;
 typedef struct _GdaOracleProviderClass GdaOracleProviderClass;
 
 struct _GdaOracleProvider {
-	GdaServerProvider provider;
+	GdaServerProvider      provider;
 };
 
 struct _GdaOracleProviderClass {
 	GdaServerProviderClass parent_class;
 };
 
-/*
- * Connection data
- */
-typedef struct {
-	OCIEnv *henv;
-	OCIError *herr;
-	OCIServer *hserver;
-	OCISvcCtx *hservice;
-	OCISession *hsession;
-        gchar *schema; /* the same as the username which opened the connection */
-} GdaOracleConnectionData;
-
-
 G_BEGIN_DECLS
 
-GType                gda_oracle_provider_get_type (void) G_GNUC_CONST;
-GdaServerProvider   *gda_oracle_provider_new (void);
-
+GType gda_oracle_provider_get_type (void) G_GNUC_CONST;
 
 G_END_DECLS
 
 #endif
-
-/*
-  Local Variables:
-  mode:C
-  c-basic-offset: 8
-  End:
-*/
diff --git a/providers/oracle/gda-oracle-pstmt.c b/providers/oracle/gda-oracle-pstmt.c
new file mode 100644
index 0000000..6056e43
--- /dev/null
+++ b/providers/oracle/gda-oracle-pstmt.c
@@ -0,0 +1,96 @@
+/* GDA Oracle provider
+ * Copyright (C) 2008 The GNOME Foundation.
+ *
+ * AUTHORS:
+ *      TO_ADD: your name and email
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include <glib/gi18n-lib.h>
+#include "gda-oracle-pstmt.h"
+
+static void gda_oracle_pstmt_class_init (GdaOraclePStmtClass *klass);
+static void gda_oracle_pstmt_init       (GdaOraclePStmt *pstmt, GdaOraclePStmtClass *klass);
+static void gda_oracle_pstmt_finalize    (GObject *object);
+
+static GObjectClass *parent_class = NULL;
+
+/**
+ * gda_oracle_pstmt_get_type
+ *
+ * Returns: the #GType of GdaOraclePStmt.
+ */
+GType
+gda_oracle_pstmt_get_type (void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY (type == 0)) {
+		static GStaticMutex registering = G_STATIC_MUTEX_INIT;
+		static const GTypeInfo info = {
+			sizeof (GdaOraclePStmtClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) gda_oracle_pstmt_class_init,
+			NULL,
+			NULL,
+			sizeof (GdaOraclePStmt),
+			0,
+			(GInstanceInitFunc) gda_oracle_pstmt_init
+		};
+
+		g_static_mutex_lock (&registering);
+		if (type == 0)
+			type = g_type_register_static (GDA_TYPE_PSTMT, "GdaOraclePStmt", &info, 0);
+		g_static_mutex_unlock (&registering);
+	}
+	return type;
+}
+
+static void 
+gda_oracle_pstmt_class_init (GdaOraclePStmtClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	parent_class = g_type_class_peek_parent (klass);
+
+	/* virtual functions */
+	object_class->finalize = gda_oracle_pstmt_finalize;
+}
+
+static void
+gda_oracle_pstmt_init (GdaOraclePStmt *pstmt, GdaOraclePStmtClass *klass)
+{
+	g_return_if_fail (GDA_IS_PSTMT (pstmt));
+	
+	/* initialize specific parts of @pstmt */
+	TO_IMPLEMENT;
+}
+
+static void
+gda_oracle_pstmt_finalize (GObject *object)
+{
+	GdaOraclePStmt *pstmt = (GdaOraclePStmt *) object;
+
+	g_return_if_fail (GDA_IS_PSTMT (pstmt));
+
+	/* free memory */
+	TO_IMPLEMENT; /* free some specific parts of @pstmt */
+
+	/* chain to parent class */
+	parent_class->finalize (object);
+}
diff --git a/providers/oracle/gda-oracle-pstmt.h b/providers/oracle/gda-oracle-pstmt.h
new file mode 100644
index 0000000..cef1c3b
--- /dev/null
+++ b/providers/oracle/gda-oracle-pstmt.h
@@ -0,0 +1,57 @@
+/* GDA Oracle library
+ * Copyright (C) 2008 The GNOME Foundation.
+ *
+ * AUTHORS:
+ *      TO_ADD: your name and email
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GDA_ORACLE_PSTMT_H__
+#define __GDA_ORACLE_PSTMT_H__
+
+#include <providers-support/gda-pstmt.h>
+#include "gda-oracle.h"
+
+G_BEGIN_DECLS
+
+#define GDA_TYPE_ORACLE_PSTMT            (gda_oracle_pstmt_get_type())
+#define GDA_ORACLE_PSTMT(obj)            (G_TYPE_CHECK_INSTANCE_CAST (obj, GDA_TYPE_ORACLE_PSTMT, GdaOraclePStmt))
+#define GDA_ORACLE_PSTMT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST (klass, GDA_TYPE_ORACLE_PSTMT, GdaOraclePStmtClass))
+#define GDA_IS_ORACLE_PSTMT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE(obj, GDA_TYPE_ORACLE_PSTMT))
+#define GDA_IS_ORACLE_PSTMT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GDA_TYPE_ORACLE_PSTMT))
+
+typedef struct _GdaOraclePStmt        GdaOraclePStmt;
+typedef struct _GdaOraclePStmtClass   GdaOraclePStmtClass;
+
+struct _GdaOraclePStmt {
+	GdaPStmt        object;
+
+	/* TO_ADD: this structure holds any information necessary to reference a prepared statement, usually a connection
+         * handle from the C or C++ API
+         */
+};
+
+struct _GdaOraclePStmtClass {
+	GdaPStmtClass  parent_class;
+};
+
+GType         gda_oracle_pstmt_get_type  (void) G_GNUC_CONST;
+/* TO_ADD: helper function to create a GdaOraclePStmt such as gda_oracle_pstmt_new() with some specific arguments */
+
+G_END_DECLS
+
+#endif
diff --git a/providers/oracle/gda-oracle-recordset.c b/providers/oracle/gda-oracle-recordset.c
index 86c45b6..450b0ad 100644
--- a/providers/oracle/gda-oracle-recordset.c
+++ b/providers/oracle/gda-oracle-recordset.c
@@ -1,9 +1,8 @@
 /* GDA Oracle provider
- * Copyright (C) 1998 - 2007 The GNOME Foundation.
+ * Copyright (C) 2008 The GNOME Foundation.
  *
  * AUTHORS:
- * 	Tim Coleman <tim timcoleman com>
- *      Vivien Malerba <malerba gnome-db org>
+ *      TO_ADD: your name and email
  *
  * This Library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public License as
@@ -21,681 +20,331 @@
  * Boston, MA 02111-1307, USA.
  */
 
-#include <glib/gi18n-lib.h>
-#include <stdlib.h>
+#include <stdarg.h>
 #include <string.h>
+#include <glib/gi18n-lib.h>
+#include <libgda/gda-util.h>
+#include <libgda/gda-connection-private.h>
 #include "gda-oracle.h"
 #include "gda-oracle-recordset.h"
 #include "gda-oracle-provider.h"
-#include <libgda/gda-data-model.h>
-#include <oci.h>
-#include <libgda/gda-data-model-private.h>
-
-#define PARENT_TYPE GDA_TYPE_DATA_MODEL_ROW
-
-struct _GdaOracleRecordsetPrivate {
-	GdaConnection           *cnc;
-	GdaOracleConnectionData *cdata;
-
-	GList                   *ora_values;
-	GPtrArray               *rows;
-	OCIStmt                 *hstmt;
-
-	gint                     ncolumns;
-	gint                     nrows;
-};
 
+#define _GDA_PSTMT(x) ((GdaPStmt*)(x))
 
 static void gda_oracle_recordset_class_init (GdaOracleRecordsetClass *klass);
 static void gda_oracle_recordset_init       (GdaOracleRecordset *recset,
-					    GdaOracleRecordsetClass *klass);
-static void gda_oracle_recordset_finalize   (GObject *object);
-
-static GObjectClass *parent_class = NULL;
-
-/*
- * Private functions
- */
+					     GdaOracleRecordsetClass *klass);
+static void gda_oracle_recordset_dispose   (GObject *object);
 
-static GList *
-define_columns (GdaOracleRecordsetPrivate *priv, GArray *col_size_array)
-{
-	GList *fields = NULL;
-	gint i;
-	gint result;
-	ub2 fake_type;
-
-	for (i = 0; i < priv->ncolumns; i ++) {
-		GdaOracleValue *ora_value = g_new0 (GdaOracleValue, 1);
-
-		result = OCIParamGet (priv->hstmt,
-				      OCI_HTYPE_STMT,
-				      priv->cdata->herr,
-				      (dvoid **) &(ora_value->pard),
-				      (ub4) i+1);
-		if (gda_oracle_check_result (result, priv->cnc, priv->cdata, OCI_HTYPE_ERROR,
-					     _("Could not get the Oracle parameter")))
-			return NULL;
-
-		result = OCIAttrGet ((dvoid *) (ora_value->pard),
-				     OCI_DTYPE_PARAM,
-				     &(ora_value->defined_size),
-				     0,
-				     OCI_ATTR_DATA_SIZE,
-				     priv->cdata->herr);
-		if (gda_oracle_check_result (result, priv->cnc, priv->cdata, OCI_HTYPE_ERROR,
-					     _("Could not get the parameter defined size"))) {
-			OCIDescriptorFree ((dvoid *) ora_value->pard, OCI_DTYPE_PARAM);
-			return NULL;
-		}
-		
-		result = OCIAttrGet ((dvoid *) (ora_value->pard),
-				     OCI_DTYPE_PARAM,
-				     &(ora_value->sql_type),
-				     0,
-				     OCI_ATTR_DATA_TYPE,
-				     priv->cdata->herr);
-		
-		if (gda_oracle_check_result (result, priv->cnc, priv->cdata, OCI_HTYPE_ERROR,
-					     _("Could not get the parameter data type"))) {
-			OCIDescriptorFree ((dvoid *) ora_value->pard, OCI_DTYPE_PARAM);
-			return NULL;
-		}
-		
-		/* for data fetching  */
-		fake_type = ora_value->sql_type;
-		switch (ora_value->sql_type) {
-                case SQLT_NUM: /* Numerics are coerced to string */
-                        fake_type = SQLT_CHR;
-                        break;
-                case SQLT_DAT: /* Convert SQLT_DAT to OCIDate */
-                        fake_type = SQLT_ODT;
-                        break;
-                }
-
-		ora_value->g_type = oracle_sqltype_to_g_type (ora_value->sql_type);
-		if (col_size_array && (i < col_size_array->len)) {
-			ub2 size;
-			
-			size = g_array_index (col_size_array, ub2, i);
-			if (size > 0)
-				ora_value->defined_size = size;
-		}
-		if (ora_value->g_type == GDA_TYPE_BLOB) {
-			/* allocate a Lob locator */
-			OCILobLocator *lob;
-
-			result = OCIDescriptorAlloc ((dvoid *) priv->cdata->henv, (dvoid **) &lob, 
-						     (ub4) gda_oracle_blob_type (ora_value->sql_type), (size_t) 0, (dvoid **) 0);
-			if (gda_oracle_check_result (result, priv->cnc, priv->cdata, OCI_HTYPE_ERROR,
-						     _("Could not allocate Lob locator")))
-				return NULL;
-			ora_value->value = lob;
-			ora_value->defined_size = 0;
-		}
-		else if (ora_value->defined_size == 0)
-			ora_value->value = NULL;
-		else {
-			ora_value->defined_size++;
-			ora_value->value = g_malloc0 (ora_value->defined_size);
-		}
+/* virtual methods */
+static gint     gda_oracle_recordset_fetch_nb_rows (GdaDataSelect *model);
+static gboolean gda_oracle_recordset_fetch_random (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error);
+static gboolean gda_oracle_recordset_fetch_next (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error);
+static gboolean gda_oracle_recordset_fetch_prev (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error);
+static gboolean gda_oracle_recordset_fetch_at (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error);
 
-		ora_value->hdef = (OCIDefine *) 0;
-		ora_value->indicator = 0;
-		result = OCIDefineByPos ((OCIStmt *) priv->hstmt,
-					 (OCIDefine **) &(ora_value->hdef),
-					 (OCIError *) priv->cdata->herr,
-					 (ub4) i + 1,
-					 ora_value->value,
-					 ora_value->defined_size,
-					 (ub2) fake_type,
-					 (dvoid *) &(ora_value->indicator),
-					 (ub2 *) 0,
-					 (ub2 *) 0, 
-					 (ub4) OCI_DEFAULT);
-		if (gda_oracle_check_result (result, priv->cnc, priv->cdata, OCI_HTYPE_ERROR,
-					     _("Could not define by position"))) {
-			OCIDescriptorFree ((dvoid *) ora_value->pard, OCI_DTYPE_PARAM);
-			return NULL;
-		}
-		
-		fields = g_list_append (fields, ora_value);
-	}
-	return fields;
-}
 
+struct _GdaOracleRecordsetPrivate {
+	GdaConnection *cnc;
+	/* TO_ADD: specific information */
+};
+static GObjectClass *parent_class = NULL;
 
 /*
- * GdaOracleRecordset class implementation
+ * Object init and finalize
  */
-
 static void
-gda_oracle_recordset_describe_column (GdaDataModel *model, gint col)
+gda_oracle_recordset_init (GdaOracleRecordset *recset,
+			   GdaOracleRecordsetClass *klass)
 {
-	GdaOracleRecordset *recset = (GdaOracleRecordset *) model;
-	GdaOracleRecordsetPrivate *priv_data;
-	GdaColumn *field_attrs;
-	OCIParam *pard;
-	gchar *pgchar_dummy;
-	glong col_name_len;
-
-	gchar name_buffer[ORA_NAME_BUFFER_SIZE + 1];
-	ub2 sql_type;
-	sb1 scale;
-	ub1 nullable;
-	ub2 defined_size;
-	gint result;
-
 	g_return_if_fail (GDA_IS_ORACLE_RECORDSET (recset));
-	g_return_if_fail (recset->priv != NULL);
-	
-	priv_data = recset->priv;
-	
-	if (!priv_data->cdata) {
-		gda_connection_add_event_string (priv_data->cnc, 
-						 _("Invalid Oracle handle"));
-		return;
-	}
-	
-	if (col >= priv_data->ncolumns) {
-		gda_connection_add_event_string (priv_data->cnc, 
-						 _("Column out of range"));
-		return;
-	}
-	
-	field_attrs = gda_data_model_describe_column (model, col);
-	
-	result = OCIParamGet ((dvoid *) priv_data->hstmt,
-			      (ub4) OCI_HTYPE_STMT,
-			      (OCIError *) priv_data->cdata->herr,
-			      (dvoid **) &pard,
-			      (ub4) col + 1);
-	if (gda_oracle_check_result (result, priv_data->cnc, priv_data->cdata, OCI_HTYPE_ERROR,
-				     _("Could not get the Oracle parameter information")))
-		return;
-
-	result = OCIAttrGet ((dvoid *) pard,
-			     (ub4) OCI_DTYPE_PARAM,
-			     (dvoid **) &pgchar_dummy,
-			     (ub4 *) & col_name_len,
-			     (ub4) OCI_ATTR_NAME,
-			     (OCIError *) priv_data->cdata->herr);
-	if (gda_oracle_check_result (result, priv_data->cnc, priv_data->cdata, OCI_HTYPE_ERROR,
-				     _("Could not get the Oracle column name"))) {
-		OCIDescriptorFree ((dvoid *) pard, OCI_DTYPE_PARAM);
-		return;
-	}
-	
-	if (col_name_len > ORA_NAME_BUFFER_SIZE)
-		col_name_len = ORA_NAME_BUFFER_SIZE;
-		
-	memcpy (name_buffer, pgchar_dummy, col_name_len);
-	name_buffer[col_name_len] = '\0';
-	
-	result = OCIAttrGet ((dvoid *) pard,
-			     (ub4) OCI_DTYPE_PARAM,
-			     (dvoid *) &sql_type,
-			     (ub4 *) 0,
-			     (ub4) OCI_ATTR_DATA_TYPE,
-			     (OCIError *) priv_data->cdata->herr);
-	if (gda_oracle_check_result (result, priv_data->cnc, priv_data->cdata, OCI_HTYPE_ERROR,
-				     _("Could not get the Oracle column data type"))) {
-		OCIDescriptorFree ((dvoid *) pard, OCI_DTYPE_PARAM);
-		return;
-	}
-	
-	result = OCIAttrGet ((dvoid *) pard,
-			     (ub4) OCI_DTYPE_PARAM,
-			     (sb1 *) &scale,
-			     (ub4 *) 0,
-			     (ub4) OCI_ATTR_SCALE,
-			     (OCIError *) priv_data->cdata->herr);
-	if (gda_oracle_check_result (result, priv_data->cnc, priv_data->cdata, OCI_HTYPE_ERROR,
-				     _("Could not get the Oracle column scale"))) {
-		OCIDescriptorFree ((dvoid *) pard, OCI_DTYPE_PARAM);
-		return;
-	}
-	
-	result = OCIAttrGet ((dvoid *) pard,
-			     (ub4) OCI_DTYPE_PARAM,
-			     (ub1 *) &nullable,
-			     (ub4 *) 0,
-			     (ub4) OCI_ATTR_IS_NULL,
-			     (OCIError *) priv_data->cdata->herr);
-	if (gda_oracle_check_result (result, priv_data->cnc, priv_data->cdata, OCI_HTYPE_ERROR,
-				     _("Could not get the Oracle column nullable attribute"))) {
-		OCIDescriptorFree ((dvoid *) pard, OCI_DTYPE_PARAM);
-		return;
-	}
-	
-	result = OCIAttrGet ((dvoid *) pard,
-			     OCI_DTYPE_PARAM,
-			     &defined_size,
-			     0,
-			     OCI_ATTR_DATA_SIZE,
-			     priv_data->cdata->herr);
-	if (gda_oracle_check_result (result, priv_data->cnc, priv_data->cdata, OCI_HTYPE_ERROR,
-				     _("Could not get the Oracle defined size"))) {
-		OCIDescriptorFree ((dvoid *) pard, OCI_DTYPE_PARAM);
-		return;
-	}
-	
-	gda_column_set_name (field_attrs, name_buffer);
-	gda_column_set_scale (field_attrs, scale);
-	gda_column_set_g_type (field_attrs, oracle_sqltype_to_g_type (sql_type));
-	gda_column_set_defined_size (field_attrs, defined_size);
-	
-	/* FIXME */
-	gda_column_set_references (field_attrs, "");
-	
-	/* FIXME */
-	gda_column_set_primary_key (field_attrs, FALSE); 
-	
-	/* FIXME */
-	gda_column_set_unique_key (field_attrs, FALSE);
+	recset->priv = g_new0 (GdaOracleRecordsetPrivate, 1);
+	recset->priv->cnc = NULL;
 
-	gda_column_set_allow_null (field_attrs, !(nullable == 0));
-	
-	OCIDescriptorFree ((dvoid *) pard, OCI_DTYPE_PARAM);
+	/* initialize specific information */
+	TO_IMPLEMENT;
 }
 
-static gint
-gda_oracle_recordset_get_n_rows (GdaDataModelRow *model)
+static void
+gda_oracle_recordset_class_init (GdaOracleRecordsetClass *klass)
 {
-	GdaOracleRecordset *recset = (GdaOracleRecordset *) model;
-	GdaOracleRecordsetPrivate *priv_data;
-	gint result = OCI_SUCCESS;
-	gint nrows = -1;
-
-	g_return_val_if_fail (GDA_IS_ORACLE_RECORDSET (model), 0);
-	g_return_val_if_fail (recset->priv != NULL, 0);
-
-	priv_data = recset->priv;
-
-	if (priv_data->nrows >= 0) 
-		return priv_data->nrows;
-
-	while (result == OCI_SUCCESS) {
-		nrows += 1;
-		result = OCIStmtFetch (priv_data->hstmt,
-				       priv_data->cdata->herr,
-				       (ub4) 1,
-				       (ub2) OCI_FETCH_NEXT,
-				       (ub4) OCI_DEFAULT);
-	}
-
-	/* reset the result set to the beginning */
-	result = OCIStmtExecute (priv_data->cdata->hservice,
-				 priv_data->hstmt,
-				 priv_data->cdata->herr,
-				 (ub4) 0,
-				 (ub4) 0,
-				 (CONST OCISnapshot *) NULL,
-				 (OCISnapshot *) NULL,
-				 OCI_DEFAULT);
-	
-	if (gda_oracle_check_result (result, priv_data->cnc, priv_data->cdata, 
-				     OCI_HTYPE_ERROR, "Could not execute Oracle statement")) 
-		return 0;
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	GdaDataSelectClass *pmodel_class = GDA_DATA_SELECT_CLASS (klass);
 
-	return nrows;
-}
+	parent_class = g_type_class_peek_parent (klass);
 
-static gint
-gda_oracle_recordset_get_n_columns (GdaDataModelRow *model)
-{
-	GdaOracleRecordset *recset = (GdaOracleRecordset *) model;
-	g_return_val_if_fail (GDA_IS_ORACLE_RECORDSET (model), 0);
-	g_return_val_if_fail (recset->priv != NULL, 0);
+	object_class->dispose = gda_oracle_recordset_dispose;
+	pmodel_class->fetch_nb_rows = gda_oracle_recordset_fetch_nb_rows;
+	pmodel_class->fetch_random = gda_oracle_recordset_fetch_random;
 
-	return recset->priv->ncolumns;
+	pmodel_class->fetch_next = gda_oracle_recordset_fetch_next;
+	pmodel_class->fetch_prev = gda_oracle_recordset_fetch_prev;
+	pmodel_class->fetch_at = gda_oracle_recordset_fetch_at;
 }
 
-static GdaRow *
-fetch_row (GdaOracleRecordset *recset, gint rownum)
+static void
+gda_oracle_recordset_dispose (GObject *object)
 {
-	GdaRow *row;
-	gint i;
-	gchar *id;
-	GdaOracleRecordsetPrivate *priv;
-	GList *node;
-	gint result;
+	GdaOracleRecordset *recset = (GdaOracleRecordset *) object;
 
-	g_return_val_if_fail (GDA_IS_ORACLE_RECORDSET (recset), NULL);
-	g_return_val_if_fail (recset->priv != NULL, NULL);
+	g_return_if_fail (GDA_IS_ORACLE_RECORDSET (recset));
 
-	priv = recset->priv;
+	if (recset->priv) {
+		if (recset->priv->cnc) 
+			g_object_unref (recset->priv->cnc);
 
-	row = gda_row_new (GDA_DATA_MODEL (recset), priv->ncolumns);
+		/* free specific information */
+		TO_IMPLEMENT;
+		g_free (recset->priv);
+		recset->priv = NULL;
+	}
 
-	result = OCIStmtFetch ((OCIStmt *) priv->hstmt,
-			       (OCIError *) priv->cdata->herr,
-			       (ub4) 1,
-			       (ub2) OCI_FETCH_NEXT,
-			       (ub4) OCI_DEFAULT); 
-	if (result == OCI_NO_DATA) 
-		return NULL;
+	parent_class->dispose (object);
+}
 
-	if (gda_oracle_check_result (result, priv->cnc, priv->cdata, OCI_HTYPE_ERROR,
-				     _("Could not fetch a row"))) 
-		return NULL;
+/*
+ * Public functions
+ */
 
-	i = 0;
-	for (node = priv->ora_values; node;  node = node->next) {
-		GdaOracleValue *ora_value = (GdaOracleValue *) node->data;
-		GValue *value = gda_row_get_value (row, i);
-		gda_oracle_set_value (value, ora_value, priv->cnc);
-		i += 1;
+GType
+gda_oracle_recordset_get_type (void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY (type == 0)) {
+		static GStaticMutex registering = G_STATIC_MUTEX_INIT;
+		static const GTypeInfo info = {
+			sizeof (GdaOracleRecordsetClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) gda_oracle_recordset_class_init,
+			NULL,
+			NULL,
+			sizeof (GdaOracleRecordset),
+			0,
+			(GInstanceInitFunc) gda_oracle_recordset_init
+		};
+		g_static_mutex_lock (&registering);
+		if (type == 0)
+			type = g_type_register_static (GDA_TYPE_DATA_SELECT, "GdaOracleRecordset", &info, 0);
+		g_static_mutex_unlock (&registering);
 	}
 
-	id = g_strdup_printf ("%d", rownum);
-	gda_row_set_id (row, id);
-	g_free (id);
-	return row;
+	return type;
 }
 
-static GdaRow *
-gda_oracle_recordset_get_row (GdaDataModelRow *model, gint row, GError **error)
+/*
+ * the @ps struct is modified and transfered to the new data model created in
+ * this function
+ */
+GdaDataModel *
+gda_oracle_recordset_new (GdaConnection *cnc, GdaOraclePStmt *ps, GdaSet *exec_params,
+			GdaDataModelAccessFlags flags, GType *col_types)
 {
-	GdaOracleRecordset *recset = (GdaOracleRecordset *) model;
-	GdaOracleRecordsetPrivate *priv_data;
-	GdaRow *fields = NULL;
-	gint fetched_rows;
-	gint i;
-
-	g_return_val_if_fail (GDA_IS_ORACLE_RECORDSET (recset), NULL);
-	g_return_val_if_fail (recset->priv != NULL, 0);
+	GdaOracleRecordset *model;
+        OracleConnectionData *cdata;
+        gint i;
+	GdaDataModelAccessFlags rflags;
 
-	priv_data = recset->priv;
+        g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+        g_return_val_if_fail (ps != NULL, NULL);
 
-	if (!priv_data->cdata) {
-		gda_connection_add_event_string (priv_data->cnc,
-						_("Invalid Oracle handle"));
+	cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata)
 		return NULL;
-	}
 
-	fetched_rows = priv_data->rows->len;
-
-	if (row >= priv_data->nrows && priv_data->nrows >= 0)
-		return NULL;
+	/* make sure @ps reports the correct number of columns using the API*/
+        if (_GDA_PSTMT (ps)->ncols < 0)
+                /*_GDA_PSTMT (ps)->ncols = ...;*/
+		TO_IMPLEMENT;
+
+        /* completing @ps if not yet done */
+        if (!_GDA_PSTMT (ps)->types && (_GDA_PSTMT (ps)->ncols > 0)) {
+		/* create prepared statement's columns */
+		GSList *list;
+		for (i = 0; i < _GDA_PSTMT (ps)->ncols; i++)
+			_GDA_PSTMT (ps)->tmpl_columns = g_slist_prepend (_GDA_PSTMT (ps)->tmpl_columns, 
+									 gda_column_new ());
+		_GDA_PSTMT (ps)->tmpl_columns = g_slist_reverse (_GDA_PSTMT (ps)->tmpl_columns);
+
+		/* create prepared statement's types */
+		_GDA_PSTMT (ps)->types = g_new0 (GType, _GDA_PSTMT (ps)->ncols); /* all types are initialized to GDA_TYPE_NULL */
+		if (col_types) {
+			for (i = 0; ; i++) {
+				if (col_types [i] > 0) {
+					if (col_types [i] == G_TYPE_NONE)
+						break;
+					if (i >= _GDA_PSTMT (ps)->ncols)
+						g_warning (_("Column %d out of range (0-%d), ignoring its specified type"), i,
+							   _GDA_PSTMT (ps)->ncols - 1);
+					else
+						_GDA_PSTMT (ps)->types [i] = col_types [i];
+				}
+			}
+		}
+		
+		/* fill GdaColumn's data */
+		for (i=0, list = _GDA_PSTMT (ps)->tmpl_columns; 
+		     i < GDA_PSTMT (ps)->ncols; 
+		     i++, list = list->next) {
+			GdaColumn *column;
+			
+			column = GDA_COLUMN (list->data);
 
-	if (row < fetched_rows) 
-		return (GdaRow *) g_ptr_array_index (priv_data->rows, row);
+			/* use C API to set columns' information using gda_column_set_*() */
+			TO_IMPLEMENT;
+		}
+        }
 
-	gda_data_model_freeze (GDA_DATA_MODEL (recset));
+	/* determine access mode: RANDOM or CURSOR FORWARD are the only supported */
+	if (flags & GDA_DATA_MODEL_ACCESS_RANDOM)
+		rflags = GDA_DATA_MODEL_ACCESS_RANDOM;
+	else
+		rflags = GDA_DATA_MODEL_ACCESS_CURSOR_FORWARD;
 
-	for (i = fetched_rows; i <= row; i += 1) {
-		fields = fetch_row (recset, i);
-		if (!fields) 
-			return NULL;
-		g_ptr_array_add (priv_data->rows, fields);
-	}
+	/* create data model */
+        model = g_object_new (GDA_TYPE_ORACLE_RECORDSET, 
+			      "prepared-stmt", ps, 
+			      "model-usage", rflags, 
+			      "exec-params", exec_params, NULL);
+        model->priv->cnc = cnc;
+	g_object_ref (cnc);
 
-	gda_data_model_thaw (GDA_DATA_MODEL (recset));
+	/* post init specific code */
+	TO_IMPLEMENT;
 
-	return fields;
+        return GDA_DATA_MODEL (model);
 }
 
-static const GValue *
-gda_oracle_recordset_get_value_at (GdaDataModelRow *model, gint col, gint row)
-{
-	GdaOracleRecordset *recset = (GdaOracleRecordset *) model;
-	GdaOracleRecordsetPrivate *priv_data;
-	const GdaRow *fields;
 
-	g_return_val_if_fail (GDA_IS_ORACLE_RECORDSET (recset), NULL);
-	g_return_val_if_fail (recset->priv != NULL, 0);
+/*
+ * Get the number of rows in @model, if possible
+ */
+static gint
+gda_oracle_recordset_fetch_nb_rows (GdaDataSelect *model)
+{
+	GdaOracleRecordset *imodel;
 
-	priv_data = recset->priv;
+	imodel = GDA_ORACLE_RECORDSET (model);
+	if (model->advertized_nrows >= 0)
+		return model->advertized_nrows;
 
-	if (col >= priv_data->ncolumns)
-		return NULL;
+	/* use C API to determine number of rows,if possible */
+	TO_IMPLEMENT;
 
-	fields = gda_oracle_recordset_get_row (model, row, NULL);
-	return fields != NULL ? gda_row_get_value ((GdaRow *) fields, col) : NULL;
+	return model->advertized_nrows;
 }
 
-static gboolean
-gda_oracle_recordset_is_updatable (GdaDataModelRow *model)
+/*
+ * Create a new filled #GdaRow object for the row at position @rownum, and put it into *prow.
+ *
+ * WARNING: @prow will NOT be NULL, but *prow may or may not be NULL:
+ *  -  If *prow is NULL then a new #GdaRow object has to be created, 
+ *  -  and otherwise *prow contains a #GdaRow object which has already been created 
+ *     (through a call to this very function), and in this case it should not be modified
+ *     but the function may return FALSE if an error occurred.
+ *
+ * Memory management for that new GdaRow object is left to the implementation, which
+ * can use gda_data_select_take_row(). If new row objects are "given" to the GdaDataSelect implemantation
+ * using that method, then this method should detect when all the data model rows have been analysed
+ * (when model->nb_stored_rows == model->advertized_nrows) and then possibly discard the API handle
+ * as it won't be used anymore to fetch rows.
+ */
+static gboolean 
+gda_oracle_recordset_fetch_random (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
 {
-	GdaCommandType cmd_type;
-	GdaOracleRecordset *recset = (GdaOracleRecordset *) model;
+	GdaOracleRecordset *imodel;
 
-	g_return_val_if_fail (GDA_IS_ORACLE_RECORDSET (recset), FALSE);
+	imodel = GDA_ORACLE_RECORDSET (model);
 
-	g_object_get (G_OBJECT (model), "command_type", &cmd_type, NULL);
+	TO_IMPLEMENT;
 
-	return FALSE;
-	/*return cmd_type == GDA_COMMAND_TYPE_TABLE ? TRUE : FALSE;*/
+	return TRUE;
 }
 
-/* Not implemented. See bug http://bugzilla.gnome.org/show_bug.cgi?id=411811: */
-#if 0
-static GdaRow *
-gda_oracle_recordset_append_values (GdaDataModelRow *model, const GList *values, GError **error)
+/*
+ * Create and "give" filled #GdaRow object for all the rows in the model
+ */
+static gboolean
+gda_oracle_recordset_store_all (GdaDataSelect *model, GError **error)
 {
-	GString *sql;
-	GdaRow *row;
+	GdaOracleRecordset *imodel;
 	gint i;
-	GList *l;
-	GdaOracleRecordset *recset = (GdaOracleRecordset *) model;
-	GdaOracleRecordsetPrivate *priv_data;
-
-	g_return_val_if_fail (GDA_IS_ORACLE_RECORDSET (recset), NULL);
-	g_return_val_if_fail (values != NULL, NULL);
-	g_return_val_if_fail (gda_data_model_is_updatable (GDA_DATA_MODEL (model)), NULL);
-	g_return_val_if_fail (recset->priv != NULL, 0);
-
-	priv_data = recset->priv;
-
-	if (priv_data->ncolumns != g_list_length ((GList *) values)) {
-		gda_connection_add_event_string (
-			recset->priv->cnc,
-			_("Attempt to insert a row with an invalid number of columns"));
-		return NULL;
-	}
-
-	sql = g_string_new ("INSERT INTO ");
-	sql = g_string_append (sql, gda_data_model_get_command_text (GDA_DATA_MODEL (model)));
-	sql = g_string_append (sql, "(");
-
-	for (i = 0; i < priv_data->ncolumns; i += 1) {
-		GdaColumn *fa;
 
-		fa = gda_data_model_describe_column (GDA_DATA_MODEL (model), i);
-		if (!fa) {
-			gda_connection_add_event_string (
-				recset->priv->cnc,
-				_("Could not retrieve column's information"));
-			g_string_free (sql, TRUE);
-			return NULL;
-		}
+	imodel = GDA_ORACLE_RECORDSET (model);
 
-		if (i != 0) 
-			sql = g_string_append (sql, ", ");
-		sql = g_string_append (sql, gda_column_get_name (fa));
+	/* default implementation */
+	for (i = 0; i < model->advertized_nrows; i++) {
+		GdaRow *prow;
+		if (! gda_oracle_recordset_fetch_random (model, &prow, i, error))
+			return FALSE;
 	}
-	sql = g_string_append (sql, ") VALUES (");
-
-	for (l = (GList *) values, i = 0; i < priv_data->ncolumns; i += 1, l = l->next) {
-		gchar *val_str;
-		const GValue *val = (const GValue *) l->data;
-
-		if (!val) { 
-			gda_connection_add_event_string (
-				recset->priv->cnc,
-				_("Could not retrieve column's value"));
-			g_string_free (sql, TRUE);
-			return NULL;
-		}
-
-		if (i != 0) 
-			sql = g_string_append (sql, ", ");
-		val_str = gda_oracle_value_to_sql_string ((GValue*) val);
-		sql = g_string_append (sql, val_str);
-
-		g_free (val_str);
-	}
-	sql = g_string_append (sql, ")");
-
-	/* execute the UPDATE command */
-	/* not sure what to do here yet. */
-
-	g_string_free (sql, TRUE);
-
-	row = gda_row_new_from_list (GDA_DATA_MODEL (model), values);
-	g_ptr_array_add (recset->priv->rows, row);
-
-	return row;
-}
-#endif
-
-static gboolean
-gda_oracle_recordset_remove_row (GdaDataModelRow *model, GdaRow *row, GError **error)
-{
-	return FALSE;
+	return TRUE;
 }
 
-static gboolean
-gda_oracle_recordset_update_row (GdaDataModelRow *model, GdaRow *row, GError **error)
-{
-	return FALSE;
-}
-
-
 /*
- * Object init and finalize 
+ * Create a new filled #GdaRow object for the next cursor row, and put it into *prow.
+ *
+ * WARNING: @prow will NOT be NULL, but *prow may or may not be NULL:
+ *  -  If *prow is NULL then a new #GdaRow object has to be created, 
+ *  -  and otherwise *prow contains a #GdaRow object which has already been created 
+ *     (through a call to this very function), and in this case it should not be modified
+ *     but the function may return FALSE if an error occurred.
+ *
+ * Memory management for that new GdaRow object is left to the implementation, which
+ * can use gda_data_select_take_row().
  */
-static void
-gda_oracle_recordset_init (GdaOracleRecordset *recset, GdaOracleRecordsetClass *klass)
+static gboolean 
+gda_oracle_recordset_fetch_next (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
 {
-	g_return_if_fail (GDA_IS_ORACLE_RECORDSET (recset));
-        recset->priv = g_new0 (GdaOracleRecordsetPrivate, 1);
-        recset->priv->rows = g_ptr_array_new ();
-}
+	GdaOracleRecordset *imodel = (GdaOracleRecordset*) model;
 
-static void
-gda_oracle_recordset_class_init (GdaOracleRecordsetClass *klass)
-{
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	GdaDataModelRowClass *model_class = GDA_DATA_MODEL_ROW_CLASS (klass);
-
-	parent_class = g_type_class_peek_parent (klass);
-
-	object_class->finalize = gda_oracle_recordset_finalize;
-	model_class->get_n_rows = gda_oracle_recordset_get_n_rows;
-	model_class->get_n_columns = gda_oracle_recordset_get_n_columns;
-	model_class->get_row = gda_oracle_recordset_get_row;
-	model_class->get_value_at = gda_oracle_recordset_get_value_at;
-	model_class->is_updatable = gda_oracle_recordset_is_updatable;
+	TO_IMPLEMENT;
 
-        /* Not implemented. See bug http://bugzilla.gnome.org/show_bug.cgi?id=411811: */
-	model_class->append_values = /* gda_oracle_recordset_append_values */ NULL;
-
-	model_class->remove_row = gda_oracle_recordset_remove_row;
-	model_class->update_row = gda_oracle_recordset_update_row;
+	return TRUE;
 }
 
-static void 
-gda_oracle_free_values (GdaOracleValue *ora_value)
-{
-	if (ora_value->g_type == GDA_TYPE_BLOB) 
-		OCIDescriptorFree((dvoid *) ora_value->value, (ub4) gda_oracle_blob_type (ora_value->sql_type));
-	else
-		g_free (ora_value->value);
-	OCIDescriptorFree ((dvoid *) ora_value->pard, OCI_DTYPE_PARAM);
-	g_free (ora_value);
-}
-
-static void
-gda_oracle_recordset_finalize (GObject *object)
+/*
+ * Create a new filled #GdaRow object for the previous cursor row, and put it into *prow.
+ *
+ * WARNING: @prow will NOT be NULL, but *prow may or may not be NULL:
+ *  -  If *prow is NULL then a new #GdaRow object has to be created, 
+ *  -  and otherwise *prow contains a #GdaRow object which has already been created 
+ *     (through a call to this very function), and in this case it should not be modified
+ *     but the function may return FALSE if an error occurred.
+ *
+ * Memory management for that new GdaRow object is left to the implementation, which
+ * can use gda_data_select_take_row().
+ */
+static gboolean 
+gda_oracle_recordset_fetch_prev (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
 {
-	GdaOracleRecordset *recset = (GdaOracleRecordset *) object;
-	GdaOracleRecordsetPrivate *priv_data;
-
-	g_return_if_fail (recset->priv != NULL);
-
-	priv_data = recset->priv;
+	GdaOracleRecordset *imodel = (GdaOracleRecordset*) model;
 
-	if (!priv_data->cdata) {
-		gda_connection_add_event_string (priv_data->cnc, 
-						_("Invalid Oracle handle"));
-		return;
-	}
-
-	g_return_if_fail (GDA_IS_ORACLE_RECORDSET (recset));
+	TO_IMPLEMENT;
 
-	while (priv_data->rows->len > 0) {
-		GdaRow *row = (GdaRow *) g_ptr_array_index (priv_data->rows, 0);
-
-		if (row != NULL) 
-			g_object_unref (row);
-		g_ptr_array_remove_index (priv_data->rows, 0);
-	}
-	g_ptr_array_free (priv_data->rows, TRUE);
-	recset->priv->rows = NULL;
-
-	g_list_foreach (priv_data->ora_values, (GFunc) gda_oracle_free_values, NULL);
-	if (priv_data->hstmt)
-		OCIHandleFree ((dvoid *) priv_data->hstmt, OCI_HTYPE_STMT);
-	parent_class->finalize (object);
+	return TRUE;
 }
 
-
-GType
-gda_oracle_recordset_get_type (void)
+/*
+ * Create a new filled #GdaRow object for the cursor row at position @rownum, and put it into *prow.
+ *
+ * WARNING: @prow will NOT be NULL, but *prow may or may not be NULL:
+ *  -  If *prow is NULL then a new #GdaRow object has to be created, 
+ *  -  and otherwise *prow contains a #GdaRow object which has already been created 
+ *     (through a call to this very function), and in this case it should not be modified
+ *     but the function may return FALSE if an error occurred.
+ *
+ * Memory management for that new GdaRow object is left to the implementation, which
+ * can use gda_data_select_take_row().
+ */
+static gboolean 
+gda_oracle_recordset_fetch_at (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
 {
-	static GType type = 0;
-
-	if (G_UNLIKELY (type == 0)) {
-		static const GTypeInfo info = {
-			sizeof (GdaOracleRecordsetClass),
-			(GBaseInitFunc) NULL,
-			(GBaseFinalizeFunc) NULL,
-			(GClassInitFunc) gda_oracle_recordset_class_init,
-			NULL,
-			NULL,
-			sizeof (GdaOracleRecordset),
-			0,
-			(GInstanceInitFunc) gda_oracle_recordset_init
-		};
-		type = g_type_register_static (PARENT_TYPE, "GdaOracleRecordset", &info, 0);
-	}
+	GdaOracleRecordset *imodel = (GdaOracleRecordset*) model;
+	
+	TO_IMPLEMENT;
 
-	return type;
+	return TRUE;
 }
 
-GdaOracleRecordset *
-gda_oracle_recordset_new (GdaConnection *cnc, 
-			  GdaOracleConnectionData *cdata,
-			  OCIStmt *stmthp, GArray *col_size_array)
-{
-	GdaOracleRecordset *recset;
-	ub4 parcount;
-	gint i;
-
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-	g_return_val_if_fail (cdata != NULL, NULL);
-
-	OCIAttrGet ((dvoid *) stmthp,
-		    (ub4) OCI_HTYPE_STMT,
-		    (dvoid *) &parcount, 
-		    0,
-		    (ub4) OCI_ATTR_PARAM_COUNT,
-		    cdata->herr);
-
-	recset = g_object_new (GDA_TYPE_ORACLE_RECORDSET, NULL);
-	recset->priv->nrows = -1;
-	recset->priv->cnc = cnc;
-	recset->priv->cdata = cdata;
-	recset->priv->hstmt = stmthp;
-	recset->priv->ncolumns = parcount;
-	recset->priv->ora_values = define_columns (recset->priv, col_size_array);
-	recset->priv->nrows = gda_oracle_recordset_get_n_rows (GDA_DATA_MODEL_ROW (recset));
-
-	/* define GdaColumn attributes */
-	for (i = 0; i < recset->priv->ncolumns; i += 1) 
-		gda_oracle_recordset_describe_column (GDA_DATA_MODEL (recset), i);		
-
-	return recset;
-}
diff --git a/providers/oracle/gda-oracle-recordset.h b/providers/oracle/gda-oracle-recordset.h
index c23e4c4..7db421b 100644
--- a/providers/oracle/gda-oracle-recordset.h
+++ b/providers/oracle/gda-oracle-recordset.h
@@ -1,13 +1,8 @@
 /* GDA Oracle provider
- * Copyright (C) 2002 - 2004 The GNOME Foundation.
+ * Copyright (C) 2008 The GNOME Foundation.
  *
  * AUTHORS:
- * 	Tim Coleman <tim timcoleman com>
- *
- * Borrowed from mysql-oracle-recordset.h, written by
- *      Michael Lausch <michael lausch at>
- *	Rodrigo Moya <rodrigo gnome-db org>
- *      Vivien Malerba <malerba gnome-db org>
+ *      TO_ADD: your name and email
  *
  * This Library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public License as
@@ -28,9 +23,9 @@
 #ifndef __GDA_ORACLE_RECORDSET_H__
 #define __GDA_ORACLE_RECORDSET_H__
 
-#include <libgda/gda-data-model-hash.h>
-#include <libgda/gda-value.h>
-#include <oci.h>
+#include <libgda/libgda.h>
+#include <providers-support/gda-data-select-priv.h>
+#include "gda-oracle-pstmt.h"
 
 G_BEGIN_DECLS
 
@@ -40,36 +35,22 @@ G_BEGIN_DECLS
 #define GDA_IS_ORACLE_RECORDSET(obj)         (G_TYPE_CHECK_INSTANCE_TYPE (obj, GDA_TYPE_ORACLE_RECORDSET))
 #define GDA_IS_ORACLE_RECORDSET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDA_TYPE_ORACLE_RECORDSET))
 
-
 typedef struct _GdaOracleRecordset        GdaOracleRecordset;
 typedef struct _GdaOracleRecordsetClass   GdaOracleRecordsetClass;
-typedef struct _GdaOracleRecordsetField   GdaOracleRecordsetField;
 typedef struct _GdaOracleRecordsetPrivate GdaOracleRecordsetPrivate;
-typedef struct _GdaOracleValue            GdaOracleValue;
 
 struct _GdaOracleRecordset {
-	GdaDataModelRow model;
+	GdaDataSelect                model;
 	GdaOracleRecordsetPrivate *priv;
 };
 
 struct _GdaOracleRecordsetClass {
-	GdaDataModelRowClass parent_class;
+	GdaDataSelectClass             parent_class;
 };
 
-struct _GdaOracleValue {
-	OCIDefine *hdef;
-	OCIParam *pard;
-	sb2 indicator;
-	ub2 sql_type;
-	ub2 defined_size;
-	gpointer value;
-	GType g_type;
-};
-
-
-GType               gda_oracle_recordset_get_type (void) G_GNUC_CONST;
-GdaOracleRecordset *gda_oracle_recordset_new (GdaConnection *cnc, GdaOracleConnectionData *cdata, 
-					      OCIStmt *stmthp, GArray *col_size_array);
+GType         gda_oracle_recordset_get_type  (void) G_GNUC_CONST;
+GdaDataModel *gda_oracle_recordset_new       (GdaConnection *cnc, GdaOraclePStmt *ps, GdaSet *exec_params,
+					    GdaDataModelAccessFlags flags, GType *col_types);
 
 G_END_DECLS
 
diff --git a/providers/oracle/gda-oracle.h b/providers/oracle/gda-oracle.h
index dd3d9a6..f48ea10 100644
--- a/providers/oracle/gda-oracle.h
+++ b/providers/oracle/gda-oracle.h
@@ -1,13 +1,8 @@
-/* GDA Oracle provider
- * Copyright (C) 1998 - 2007 The GNOME Foundation.
+/* GDA oracle provider
+ * Copyright (C) 2008 The GNOME Foundation.
  *
  * AUTHORS:
- * 	Tim Coleman <tim timcoleman com>
- *
- * Borrowed from gda-mysql.h, written by:
- *      Michael Lausch <michael lausch at>
- *	Rodrigo Moya <rodrigo gnome-db org>
- *      Vivien Malerba <malerba gnome-db org>
+ *      TO_ADD: your name and email
  *
  * This Library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public License as
@@ -28,60 +23,21 @@
 #ifndef __GDA_ORACLE_H__
 #define __GDA_ORACLE_H__
 
-#if defined(HAVE_CONFIG_H)
-#endif
-
-#include <glib/gmacros.h>
-#include <libgda/gda-connection.h>
-#include <libgda/gda-server-provider.h>
-#include <glib/gi18n-lib.h>
-#include <libgda/gda-value.h>
-#include "gda-oracle-provider.h"
-#include "gda-oracle-recordset.h"
-#include <oci.h>
-
-#define OBJECT_DATA_ORACLE_HANDLE "GDA_Oracle_OracleHandle"
-#define GDA_ORACLE_PROVIDER_ID    "GDA Oracle provider"
-#define ORA_NAME_BUFFER_SIZE	  30
-
-#define gda_oracle_check_result(result, cnc, priv_data, type, msg) \
-	(((result) == OCI_SUCCESS || (result) == OCI_SUCCESS_WITH_INFO) \
-	 ? NULL : gda_oracle_handle_error(result, cnc, priv_data,       \
-					  type, msg, __FILE__, __LINE__))
-    
-#define gda_oracle_blob_type(sqltype) \
-	(((sqltype == SQLT_BFILEE) || (sqltype == SQLT_CFILEE)) ? OCI_DTYPE_FILE : OCI_DTYPE_LOB)
-
-G_BEGIN_DECLS
-
 /*
- * Utility functions
+ * Provider name
  */
+#define ORACLE_PROVIDER_NAME "Oracle"
 
-GdaConnectionEvent *gda_oracle_make_error (dvoid *hndlp, ub4 type,
-					   const gchar *file, gint line);
-
-void gda_oracle_set_value (GValue *value, 
-				GdaOracleValue *thevalue,
-				GdaConnection *cnc);
+/* TO_ADD: include headers necessary for the C or C++ API */
 
-gchar *gda_oracle_value_to_sql_string (GValue *value);
-
-GType  oracle_sqltype_to_g_type (const ub2 sqltype);
-
-gchar *oracle_sqltype_to_string (const ub2 sqltype);
-
-GdaOracleValue *gda_value_to_oracle_value (const GValue *value);
-
-GdaConnectionEvent *gda_oracle_handle_error (gint result, 
-					     GdaConnection *cnc, 
-					     GdaOracleConnectionData *priv_data,
-					     ub4 type, 
-					     const gchar *msg,
-					     const gchar *file,
-					     gint line);
-
-
-G_END_DECLS
+/*
+ * Provider's specific connection data
+ */
+typedef struct {
+	/* TO_ADD: this structure holds any information necessary to specialize the GdaConnection, usually a connection
+	 * handle from the C or C++ API
+	 */
+	int foo;
+} OracleConnectionData;
 
 #endif
diff --git a/providers/oracle/gen_def.c b/providers/oracle/gen_def.c
new file mode 100644
index 0000000..d3ab75f
--- /dev/null
+++ b/providers/oracle/gen_def.c
@@ -0,0 +1,188 @@
+/* 
+ * Copyright (C) 2007 Vivien Malerba
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * This program generates tokens'ID transformation because the GdaSqlParser object uses 2 Lemon generated
+ * parsers at once, but with only one tokenizer (because each Lemon generated parser generates it own IDs for
+ * tokens).
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+#define MAX_SYMBOLS 500
+#define PARSER_HEADER "parser.h"
+#define FALSE 0
+#define TRUE (!FALSE)
+
+typedef struct {
+	char *key;
+	int   parser_value;
+} HashEntry;
+
+HashEntry entries[MAX_SYMBOLS];
+int nb_entries; /* must remain < MAX_SYMBOLS */
+
+typedef enum {
+	TYPE_IMPOSED,
+	TYPE_PARSER
+} SourceType;
+
+static void parse_contents (FILE *stream, SourceType type);
+static HashEntry *find_entry_for_token (char *token);
+int 
+main (int argc,char** argv)
+{
+	int i;
+	FILE *fd_imposed;
+	FILE *fd_parser;
+	HashEntry *illegal_entry;
+
+	memset (entries, 0, sizeof (entries));
+	/* printf ("Imposed header: %s\n", IMPOSED_HEADER); */
+	fd_imposed = fopen (IMPOSED_HEADER, "r");
+	if (!fd_imposed) {
+		printf ("Can't open '%s':%s\n", IMPOSED_HEADER, strerror (errno));
+		return 1;
+	}
+	/* printf ("Parser header: %s\n", PARSER_HEADER); */
+	fd_parser = fopen (PARSER_HEADER, "r");
+	if (!fd_parser) {
+		printf ("Can't open '%s':%s\n", PARSER_HEADER, strerror (errno));
+		return 1;
+	}
+
+	nb_entries = 0;
+	parse_contents (fd_imposed, TYPE_IMPOSED);
+	parse_contents (fd_parser, TYPE_PARSER);
+
+	fclose (fd_imposed);
+	fclose (fd_parser);
+
+	/* output notice */
+	printf ("/*\n * This file is generated by the gen_def program (see the gen_def.c file \n"
+		" * for some explanations)\n"
+		" * DO NOT EDIT MANUALLY\n */\n\n\n");
+
+	/* output */
+	illegal_entry = find_entry_for_token ("ILLEGAL");
+	printf ("gint oracle_parser_tokens[] = {\n");
+	for (i = 0; i < nb_entries; i++) {
+		HashEntry *entry = &(entries[i]);
+		if (i!= 0)
+			printf (",\n");
+		if (entry->parser_value >= 0)
+			printf ("/* %03d */ %d", i, entry->parser_value);
+		else
+			printf ("/* %03d */ %d", i, illegal_entry->parser_value);
+	}
+	printf ("};\n");
+
+	return 0;
+}
+
+static HashEntry *
+find_entry_for_token (char *token) 
+{
+	int i;
+
+	for (i = 0; i < nb_entries; i++) {
+		HashEntry *e = &(entries[i]);
+		if (!strcmp (e->key, token))
+			return e;
+	}
+	return NULL;
+}
+
+
+
+static void 
+parse_line (char *line, SourceType type) 
+{
+	char *z, *token;
+	int value;
+	HashEntry *entry;
+	
+	z = line;
+	if (strncmp (z, "#define ", 8))
+		return;
+	z += 8;
+	token = z + 2;
+	for (; *z && *z != ' '; z++);
+	*z = 0;
+	z++;
+	for (; *z == ' '; z++);
+	value = atoi (z);
+	/* printf ("%d Token: /%s/, value=%d\n", type, token, value); */
+
+	entry = find_entry_for_token (token);
+	if (!entry) {
+		nb_entries++;
+		entry = &(entries[nb_entries - 1]);
+		entry->key = malloc (sizeof (char) * (strlen (token) + 1));
+		memcpy (entry->key, token, strlen (token) + 1);
+		entry->parser_value = -1;
+	}
+	if (type == TYPE_PARSER)
+		entry->parser_value = value;
+}
+
+static void
+parse_contents (FILE *stream, SourceType type)
+{
+#define BUFSIZE 500
+	char buffer[BUFSIZE];
+	int read;
+	char *end;
+
+	read = fread (buffer, 1, BUFSIZE, stream);
+	end = buffer + read;
+	while (read > 0) {
+		char *ptr;
+
+		/* read all complete lines in buffer */
+		while (end > buffer) {
+			char *hold = NULL;
+			for (ptr = buffer; (ptr < end) && *ptr && (*ptr != '\n'); ptr++);
+			if (ptr == end)
+				break;
+			if (*ptr)
+				hold = ptr+1;
+			*ptr = 0;
+
+			/* treat the line */
+			parse_line (buffer, type);
+
+			if (hold) {
+				int l = end - hold;
+				end -= hold - buffer;
+				memmove (buffer, hold, l);
+			}
+			else
+				break;
+		}
+
+		read = fread (end, 1, BUFSIZE - (end - buffer), stream);
+		end += read;
+	}
+}
+
diff --git a/providers/oracle/libmain.c b/providers/oracle/libmain.c
index d523449..82ae921 100644
--- a/providers/oracle/libmain.c
+++ b/providers/oracle/libmain.c
@@ -1,9 +1,8 @@
 /* GDA Oracle Provider
- * Copyright (C) 1998 - 2007 The GNOME Foundation
+ * Copyright (C) 2008 The GNOME Foundation
  *
  * AUTHORS:
- * 	Tim Coleman <tim timcoleman com>
- *      Vivien Malerba <malerba gnome-db org>
+ *      TO_ADD: your name and email
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -21,9 +20,11 @@
  */
 
 #include <glib/gi18n-lib.h>
-#include "gda-oracle-provider.h"
+#include <gmodule.h>
 #include <libgda/gda-server-provider-extra.h>
 #include <libgda/binreloc/gda-binreloc.h>
+#include "gda-oracle.h"
+#include "gda-oracle-provider.h"
 
 static gchar      *module_path = NULL;
 const gchar       *plugin_get_name (void);
@@ -31,6 +32,26 @@ const gchar       *plugin_get_description (void);
 gchar             *plugin_get_dsn_spec (void);
 GdaServerProvider *plugin_create_provider (void);
 
+/*
+ * Functions executed when calling g_module_open() and g_module_close()
+ */
+const gchar *
+g_module_check_init (GModule *module)
+{
+        /*g_module_make_resident (module);*/
+        return NULL;
+}
+
+void
+g_module_unload (GModule *module)
+{
+        g_free (module_path);
+        module_path = NULL;
+}
+
+/*
+ * Normal plugin functions 
+ */
 void
 plugin_init (const gchar *real_path)
 {
@@ -41,13 +62,13 @@ plugin_init (const gchar *real_path)
 const gchar *
 plugin_get_name (void)
 {
-	return "Oracle";
+	return ORACLE_PROVIDER_NAME;
 }
 
 const gchar *
 plugin_get_description (void)
 {
-	return _("Provider for Oracle databases");
+	return _("Example provider for C API databases");
 }
 
 gchar *
@@ -66,7 +87,7 @@ plugin_create_provider (void)
 {
 	GdaServerProvider *prov;
 
-        prov = gda_oracle_provider_new ();
+	prov = (GdaServerProvider*) g_object_new (GDA_TYPE_ORACLE_PROVIDER, NULL);
         g_object_set_data ((GObject *) prov, "GDA_PROVIDER_DIR", module_path);
         return prov;
 }
diff --git a/providers/oracle/oracle_specs_create_table.xml.in b/providers/oracle/oracle_specs_create_table.xml.in
new file mode 100644
index 0000000..ede3155
--- /dev/null
+++ b/providers/oracle/oracle_specs_create_table.xml.in
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<serv_op>
+  <parameters id="TABLE_DEF_P" _name="Table's description">
+    <parameter id="TABLE_NAME" _name="Name" _descr="Table's name" gdatype="gchararray" nullok="FALSE">
+      <gda_value>table_name</gda_value>
+    </parameter>
+  </parameters>
+
+  <!-- list of fields -->
+  <gda_array id="FIELDS_A" _name="Table's columns">
+    <gda_array_field id="COLUMN_NAME" _name="Field name" gdatype="gchararray" nullok="FALSE"/>
+    <gda_array_field id="COLUMN_TYPE" _name="Data type" gdatype="gchararray" hint="datatype" nullok="FALSE"/>
+    <gda_array_field id="COLUMN_NNUL" _name="Not NULL" gdatype="gboolean"/>
+    <gda_array_field id="COLUMN_UNIQUE" _name="Unique" gdatype="gboolean"/>
+    <gda_array_field id="COLUMN_PKEY" _name="Primary key" gdatype="gboolean"/>
+    <gda_array_field id="COLUMN_DEFAULT" _name="Default" _descr="Default value" gdatype="gchararray"/>
+    <gda_array_field id="COLUMN_CHECK" _name="Check" _descr="Check constraint" gdatype="gchararray"/>
+  </gda_array>
+
+  <!-- other table constraints -->
+  <sequence id="TABLE_CONSTRAINTS_S" _name="Global constraints">
+    <parameter id="CONSTRAINT_STRING" name="Constraint" gdatype="gchararray">
+      <gda_value>CHECK (column &gt; 0)</gda_value>
+    </parameter>
+  </sequence>
+</serv_op>
diff --git a/providers/oracle/oracle_specs_dsn.xml.in b/providers/oracle/oracle_specs_dsn.xml.in
index c3885bc..c8d7f9d 100644
--- a/providers/oracle/oracle_specs_dsn.xml.in
+++ b/providers/oracle/oracle_specs_dsn.xml.in
@@ -1,6 +1,6 @@
 <?xml version="1.0"?>
 <data-set-spec>
   <parameters>
-    <parameter id="TNSNAME" _name="TNS Name" _descr="Name of the TNS configuration to use when connecting" gdatype="gchararray" nullok="FALSE"/>
+    <parameter id="DB_NAME" _name="Database name" _descr="The name of a database to use" gdatype="gchararray" nullok="FALSE"/>
   </parameters>
 </data-set-spec>
diff --git a/providers/oracle/parser.y b/providers/oracle/parser.y
new file mode 100644
index 0000000..1df4145
--- /dev/null
+++ b/providers/oracle/parser.y
@@ -0,0 +1,1008 @@
+// All token codes are small integers with #defines that begin with "TK_"
+%token_prefix T_
+
+// The type of the data attached to each token is GValue.  This is also the
+// default type for non-terminals.
+//
+%token_type {GValue *}
+%default_type {GValue *}
+%token_destructor {if ($$) {
+#ifdef GDA_DEBUG_NO
+		 gchar *str = gda_sql_value_stringify ($$);
+		 g_print ("___ token destructor /%s/\n", str)
+		 g_free (str);
+#endif
+		 g_value_unset ($$); g_free ($$);}}
+
+// The generated parser function takes a 4th argument as follows:
+%extra_argument {GdaSqlParserIface *pdata}
+
+// This code runs whenever there is a syntax error
+//
+%syntax_error {
+	gda_sql_parser_set_syntax_error (pdata->parser);
+}
+%stack_overflow {
+	gda_sql_parser_set_overflow_error (pdata->parser);
+}
+
+// The name of the generated procedure that implements the parser
+// is as follows:
+%name gda_lemon_oracle_parser
+
+// The following text is included near the beginning of the C source
+// code file that implements the parser.
+//
+%include {
+#include <string.h>
+#include <glib.h>
+#include <glib-object.h>
+#include <glib/gi18n-lib.h>
+#include <libgda/sql-parser/gda-sql-parser-private.h>
+#include <libgda/sql-parser/gda-statement-struct-util.h>
+#include <libgda/sql-parser/gda-statement-struct-trans.h>
+#include <libgda/sql-parser/gda-statement-struct-insert.h>
+#include <libgda/sql-parser/gda-statement-struct-update.h>
+#include <libgda/sql-parser/gda-statement-struct-delete.h>
+#include <libgda/sql-parser/gda-statement-struct-select.h>
+#include <libgda/sql-parser/gda-statement-struct-compound.h>
+#include <libgda/sql-parser/gda-statement-struct-parts.h>
+#include <assert.h>
+
+typedef struct {
+	GValue *fname;
+	GdaSqlExpr *expr;
+} UpdateSet;
+
+typedef struct {
+	gboolean    distinct;
+	GdaSqlExpr *expr;
+} Distinct;
+
+typedef struct {
+	GdaSqlExpr *count;
+	GdaSqlExpr *offset;
+} Limit;
+
+typedef struct {
+	GSList *when_list;
+	GSList *then_list;
+} CaseBody;
+
+static GdaSqlOperatorType
+sql_operation_string_to_operator (const gchar *op)
+{
+	switch (g_ascii_toupper (*op)) {
+	case 'A':
+		return GDA_SQL_OPERATOR_TYPE_AND;
+	case 'O':
+		return GDA_SQL_OPERATOR_TYPE_OR;
+	case 'N':
+		return GDA_SQL_OPERATOR_TYPE_NOT;
+	case '=':
+		return GDA_SQL_OPERATOR_TYPE_EQ;
+	case 'I':
+		if (op[1] == 'S')
+			return GDA_SQL_OPERATOR_TYPE_IS;
+		else if (op[1] == 'N')
+			return GDA_SQL_OPERATOR_TYPE_IN;
+		break;
+	case 'L':
+		return GDA_SQL_OPERATOR_TYPE_LIKE;
+	case 'B':
+		return GDA_SQL_OPERATOR_TYPE_BETWEEN;
+	case '>':
+		if (op[1] == '=')
+			return GDA_SQL_OPERATOR_TYPE_GEQ;
+		else if (op[1] == 0)
+			return GDA_SQL_OPERATOR_TYPE_GT;
+		break;
+	case '<':
+		if (op[1] == '=')
+			return GDA_SQL_OPERATOR_TYPE_LEQ;
+		else if (op[1] == '>')
+			return GDA_SQL_OPERATOR_TYPE_DIFF;
+		else if (op[1] == 0)
+			return GDA_SQL_OPERATOR_TYPE_LT;
+		break;
+	case '!':
+		if (op[1] == '=')
+			return GDA_SQL_OPERATOR_TYPE_DIFF;
+		else if (op[1] == '~') {
+			if (op[2] == 0)
+				return GDA_SQL_OPERATOR_TYPE_NOT_REGEXP;
+			else if (op[2] == '*')
+				return GDA_SQL_OPERATOR_TYPE_NOT_REGEXP_CI;
+		}
+		break;
+	case '~':
+		if (op[1] == '*')
+			return GDA_SQL_OPERATOR_TYPE_REGEXP_CI;
+		else if (op[1] == 0)
+			return GDA_SQL_OPERATOR_TYPE_REGEXP;
+		break;
+	case 'S':
+		return GDA_SQL_OPERATOR_TYPE_SIMILAR;
+	case '|':
+		if (op[1] == '|')
+			return GDA_SQL_OPERATOR_TYPE_CONCAT;
+		else
+			return GDA_SQL_OPERATOR_TYPE_BITOR;
+	case '+':
+		return GDA_SQL_OPERATOR_TYPE_PLUS;
+	case '-':
+		return GDA_SQL_OPERATOR_TYPE_MINUS;
+	case '*':
+		return GDA_SQL_OPERATOR_TYPE_STAR;
+	case '/':
+		return GDA_SQL_OPERATOR_TYPE_DIV;
+	case '%':
+		return GDA_SQL_OPERATOR_TYPE_REM;
+	case '&':
+		return GDA_SQL_OPERATOR_TYPE_BITAND;
+	}
+	g_error ("Unhandled operator named '%s'\n", op);
+	return 0;
+}
+
+static GdaSqlOperatorType
+string_to_op_type (GValue *value)
+{
+	GdaSqlOperatorType op;
+	op = sql_operation_string_to_operator (g_value_get_string (value));
+	g_value_reset (value);
+	g_free (value);
+	return op;
+}
+
+static GdaSqlExpr *
+compose_multiple_expr (GdaSqlOperatorType op, GdaSqlExpr *left, GdaSqlExpr *right) {
+	GdaSqlExpr *ret;
+	if (left->cond && (left->cond->operator_type == op)) {
+		ret = left;
+		ret->cond->operands = g_slist_append (ret->cond->operands, right);
+	}
+	else {
+		GdaSqlOperation *cond;
+		ret = gda_sql_expr_new (NULL);
+		cond = gda_sql_operation_new (GDA_SQL_ANY_PART (ret));
+		ret->cond = cond;
+		cond->operator_type = op;
+		cond->operands = g_slist_prepend (NULL, right);
+		GDA_SQL_ANY_PART (right)->parent = GDA_SQL_ANY_PART (cond);
+		cond->operands = g_slist_prepend (cond->operands, left);
+		GDA_SQL_ANY_PART (left)->parent = GDA_SQL_ANY_PART (cond);
+	}
+	return ret;
+}
+
+static GdaSqlExpr *
+create_two_expr (GdaSqlOperatorType op, GdaSqlExpr *left, GdaSqlExpr *right) {
+	GdaSqlExpr *ret;
+	GdaSqlOperation *cond;
+	ret = gda_sql_expr_new (NULL);
+	cond = gda_sql_operation_new (GDA_SQL_ANY_PART (ret));
+	ret->cond = cond;
+	cond->operator_type = op;
+	cond->operands = g_slist_prepend (NULL, right);
+	GDA_SQL_ANY_PART (right)->parent = GDA_SQL_ANY_PART (cond);
+	cond->operands = g_slist_prepend (cond->operands, left);
+	GDA_SQL_ANY_PART (left)->parent = GDA_SQL_ANY_PART (cond);
+	return ret;
+}
+
+static GdaSqlExpr *
+create_uni_expr (GdaSqlOperatorType op, GdaSqlExpr *expr) {
+	GdaSqlExpr *ret;
+	GdaSqlOperation *cond;
+	ret = gda_sql_expr_new (NULL);
+	cond = gda_sql_operation_new (GDA_SQL_ANY_PART (ret));
+	ret->cond = cond;
+	cond->operator_type = op;
+	cond->operands = g_slist_prepend (NULL, expr);
+	GDA_SQL_ANY_PART (expr)->parent = GDA_SQL_ANY_PART (cond);
+	return ret;
+}
+
+static GdaSqlStatement *
+compose_multiple_compounds (GdaSqlStatementCompoundType ctype, GdaSqlStatement *left, GdaSqlStatement *right) {
+	GdaSqlStatement *ret;
+	GdaSqlStatementCompound *lc = (GdaSqlStatementCompound*) left->contents;
+	if (lc->compound_type == ctype) {
+		GdaSqlStatementCompound *rc = (GdaSqlStatementCompound*) right->contents;
+		if (!rc->stmt_list->next || rc->compound_type == ctype) {
+			GSList *list;
+			for (list = rc->stmt_list; list; list = list->next)
+				GDA_SQL_ANY_PART (((GdaSqlStatement*)list->data)->contents)->parent = GDA_SQL_ANY_PART (lc);
+
+			ret = left;
+			lc->stmt_list = g_slist_concat (lc->stmt_list, rc->stmt_list);
+			rc->stmt_list = NULL;
+			gda_sql_statement_free (right);
+		}
+	}
+	else {
+		ret = gda_sql_statement_new (GDA_SQL_STATEMENT_COMPOUND);
+		gda_sql_statement_compound_set_type (ret, ctype);
+		gda_sql_statement_compound_take_stmt (ret, left);
+		gda_sql_statement_compound_take_stmt (ret, right);
+	}
+	return ret;
+}
+
+}
+
+// The following directive causes tokens ABORT, AFTER, ASC, etc. to
+// fallback to ID if they will not parse as their original value.
+%fallback ID
+  ABORT AFTER ANALYZE ASC ATTACH BEFORE BEGIN CASCADE CAST CONFLICT
+  DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR
+  IGNORE IMMEDIATE INITIALLY INSTEAD LIKE MATCH PLAN
+  QUERY KEY OF OFFSET PRAGMA RAISE REPLACE RESTRICT ROW
+  TEMP TRIGGER VACUUM VIEW VIRTUAL
+  REINDEX RENAME CTIME_KW IF
+  DELIMITER COMMIT ROLLBACK ISOLATION LEVEL SERIALIZABLE READ COMMITTED 
+  UNCOMMITTED REPEATABLE WRITE ONLY SAVEPOINT RELEASE COMMENT FORCE WAIT NOWAIT BATCH.
+
+// Define operator precedence early so that this is the first occurance
+// of the operator tokens in the grammer.  Keeping the operators together
+// causes them to be assigned integer values that are close together,
+// which keeps parser tables smaller.
+%left OR.
+%left AND.
+%right NOT.
+%left IS MATCH LIKE IN ISNULL NOTNULL DIFF EQ.
+%left BETWEEN.
+%left GT LEQ LT GEQ.
+%left REGEXP REGEXP_CI NOT_REGEXP NOT_REGEXP_CI.
+%left SIMILAR.
+%right ESCAPE.
+%left BITAND BITOR LSHIFT RSHIFT.
+%left PLUS MINUS.
+%left STAR SLASH REM.
+%left CONCAT.
+%left COLLATE.
+%right UMINUS UPLUS BITNOT.
+%left LP RP.
+%left JOIN INNER NATURAL LEFT RIGHT FULL CROSS.
+%left UNION EXCEPT.
+%left INTERSECT.
+%left PGCAST.
+
+// force the declaration of the ILLEGAL and SQLCOMMENT tokens
+%nonassoc ILLEGAL.
+%nonassoc SQLCOMMENT.
+
+// Input is a single SQL command
+%type stmt {GdaSqlStatement *}
+%destructor stmt {g_print ("Statement destroyed by parser: %p\n", $$); gda_sql_statement_free ($$);}
+stmt ::= cmd(C) eos. {pdata->parsed_statement = C;}
+stmt ::= compound(C) eos. {
+	GdaSqlStatementCompound *scompound = (GdaSqlStatementCompound *) C->contents;
+	if (scompound->stmt_list->next)
+		/* real compound (multiple statements) */
+		pdata->parsed_statement = C;
+	else {
+		/* false compound (only 1 select) */
+		pdata->parsed_statement = (GdaSqlStatement*) scompound->stmt_list->data;
+		GDA_SQL_ANY_PART (pdata->parsed_statement->contents)->parent = NULL;
+		g_slist_free (scompound->stmt_list);
+		scompound->stmt_list = NULL;
+		gda_sql_statement_free (C);
+	}
+}
+cmd(C) ::= LP cmd(E) RP. {C = E;}
+compound(C) ::= LP compound(E) RP. {C = E;}
+
+eos ::= SEMI.
+eos ::= END_OF_FILE.
+
+%type cmd {GdaSqlStatement *}
+%destructor cmd {gda_sql_statement_free ($$);}
+
+//
+// Transactions
+//
+cmd(C) ::= BEGIN. {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);}
+cmd(C) ::= BEGIN TRANSACTION nm_opt(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+					 gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= BEGIN transtype(Y) TRANSACTION nm_opt(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+						      gda_sql_statement_trans_take_mode (C, Y);
+						      gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= BEGIN transtype(Y) nm_opt(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+					  gda_sql_statement_trans_take_mode (C, Y);
+					  gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= BEGIN transilev(L). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+				gda_sql_statement_trans_set_isol_level (C, L);
+}
+
+cmd(C) ::= BEGIN TRANSACTION transilev(L). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+					    gda_sql_statement_trans_set_isol_level (C, L);
+}
+
+cmd(C) ::= BEGIN TRANSACTION transtype(Y). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+					    gda_sql_statement_trans_take_mode (C, Y);
+}
+
+cmd(C) ::= BEGIN TRANSACTION transtype(Y) opt_comma transilev(L). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+								   gda_sql_statement_trans_take_mode (C, Y);
+								   gda_sql_statement_trans_set_isol_level (C, L);
+}
+
+cmd(C) ::= BEGIN TRANSACTION transilev(L) opt_comma transtype(Y). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+								   gda_sql_statement_trans_take_mode (C, Y);
+								   gda_sql_statement_trans_set_isol_level (C, L);
+}
+
+cmd(C) ::= BEGIN transtype(Y) opt_comma transilev(L). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+						       gda_sql_statement_trans_take_mode (C, Y);
+						       gda_sql_statement_trans_set_isol_level (C, L);
+}
+	
+cmd(C) ::= BEGIN transilev(L) opt_comma transtype(Y). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+						       gda_sql_statement_trans_take_mode (C, Y);
+						       gda_sql_statement_trans_set_isol_level (C, L);
+}
+
+cmd(C) ::= END trans_opt_kw nm_opt(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);
+					gda_sql_statement_trans_take_name (C, R);
+}
+	
+cmd(C) ::= COMMIT nm_opt(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);
+			      gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= COMMIT TRANSACTION nm_opt(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);
+					  gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= COMMIT FORCE STRING. {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);}
+cmd(C) ::= COMMIT FORCE STRING COMMA INTEGER. {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);}
+cmd(C) ::= COMMIT COMMENT STRING. {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);}
+cmd(C) ::= COMMIT COMMENT STRING ora_commit_write. {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);}
+cmd(C) ::= COMMIT ora_commit_write. {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);}
+
+cmd(C) ::= ROLLBACK trans_opt_kw nm_opt(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_ROLLBACK);
+					     gda_sql_statement_trans_take_name (C, R);
+}
+
+ora_commit_write ::= WRITE IMMEDIATE.
+ora_commit_write ::= WRITE BATCH.
+ora_commit_write ::= WRITE WAIT.
+ora_commit_write ::= WRITE NOWAIT.
+ora_commit_write ::= WRITE IMMEDIATE WAIT.
+ora_commit_write ::= WRITE IMMEDIATE NOWAIT.
+ora_commit_write ::= WRITE BATCH WAIT.
+ora_commit_write ::= WRITE BATCH NOWAIT.
+
+trans_opt_kw ::= .
+trans_opt_kw ::= TRANSACTION.
+
+opt_comma ::= .
+opt_comma ::= COMMA.
+
+%type transilev {GdaTransactionIsolation}
+transilev(L) ::= ISOLATION LEVEL SERIALIZABLE. {L = GDA_TRANSACTION_ISOLATION_SERIALIZABLE;}
+transilev(L) ::= ISOLATION LEVEL REPEATABLE READ. {L = GDA_TRANSACTION_ISOLATION_REPEATABLE_READ;}
+transilev(L) ::= ISOLATION LEVEL READ COMMITTED. {L = GDA_TRANSACTION_ISOLATION_READ_COMMITTED;}
+transilev(L) ::= ISOLATION LEVEL READ UNCOMMITTED. {L = GDA_TRANSACTION_ISOLATION_READ_UNCOMMITTED;}
+
+nm_opt(R) ::= . {R = NULL;}
+nm_opt(R) ::= nm(N). {R = N;}
+
+transtype(A) ::= DEFERRED(X).  {A = X;}
+transtype(A) ::= IMMEDIATE(X). {A = X;}
+transtype(A) ::= EXCLUSIVE(X). {A = X;}
+transtype(A) ::= READ WRITE. {A = g_new0 (GValue, 1);
+			      g_value_init (A, G_TYPE_STRING);
+			      g_value_set_string (A, "READ_WRITE");
+}
+transtype(A) ::= READ ONLY. {A = g_new0 (GValue, 1);
+			     g_value_init (A, G_TYPE_STRING);
+			     g_value_set_string (A, "READ_ONLY");
+}
+
+//
+// Savepoints
+//
+cmd(C) ::= SAVEPOINT nm(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_SAVEPOINT);
+				    gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= RELEASE SAVEPOINT nm(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_DELETE_SAVEPOINT);
+				     gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= RELEASE nm(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_DELETE_SAVEPOINT);
+			   gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= ROLLBACK trans_opt_kw TO nm(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_ROLLBACK_SAVEPOINT);
+					    gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= ROLLBACK trans_opt_kw TO SAVEPOINT nm(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_ROLLBACK_SAVEPOINT);
+						      gda_sql_statement_trans_take_name (C, R);
+}
+
+//
+// INSERT
+//
+cmd(C) ::= INSERT opt_on_conflict(O) INTO fullname(X) inscollist_opt(F) VALUES LP exprlist(Y) RP. {
+	C = gda_sql_statement_new (GDA_SQL_STATEMENT_INSERT);
+	gda_sql_statement_insert_take_table_name (C, X);
+	gda_sql_statement_insert_take_fields_list (C, F);
+	gda_sql_statement_insert_take_1_values_list (C, Y);
+	gda_sql_statement_insert_take_on_conflict (C, O);
+}
+
+cmd(C) ::= INSERT opt_on_conflict(O) INTO fullname(X) inscollist_opt(F) VALUES LP exprlist(Y) RP ins_extra_values(E). {
+	C = gda_sql_statement_new (GDA_SQL_STATEMENT_INSERT);
+	gda_sql_statement_insert_take_table_name (C, X);
+	gda_sql_statement_insert_take_fields_list (C, F);
+	gda_sql_statement_insert_take_1_values_list (C, Y);
+	gda_sql_statement_insert_take_extra_values_list (C, E);
+	gda_sql_statement_insert_take_on_conflict (C, O);
+}
+
+cmd(C) ::= INSERT opt_on_conflict(O) INTO fullname(X) inscollist_opt(F) compound(S). {
+        C = gda_sql_statement_new (GDA_SQL_STATEMENT_INSERT);
+        gda_sql_statement_insert_take_table_name (C, X);
+        gda_sql_statement_insert_take_fields_list (C, F);
+        gda_sql_statement_insert_take_select (C, S);
+        gda_sql_statement_insert_take_on_conflict (C, O);
+}
+
+
+opt_on_conflict(O) ::= . {O = NULL;}
+opt_on_conflict(O) ::= OR ID(V). {O = V;}
+
+%type ins_extra_values {GSList*}
+%destructor ins_extra_values {GSList *list;
+		for (list = $$; list; list = list->next) {
+			g_slist_foreach ((GSList*) list->data, (GFunc) gda_sql_field_free, NULL); 
+			g_slist_free ((GSList*) list->data);
+		}
+		g_slist_free ($$);
+}
+ins_extra_values(E) ::= ins_extra_values(A) COMMA LP exprlist(L) RP. {E = g_slist_append (A, L);}
+ins_extra_values(E) ::= COMMA LP exprlist(L) RP. {E = g_slist_append (NULL, L);}
+
+%type inscollist_opt {GSList*}
+%destructor inscollist_opt {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_field_free, NULL); g_slist_free ($$);}}
+inscollist_opt(A) ::= .                       {A = NULL;}
+inscollist_opt(A) ::= LP inscollist(X) RP.    {A = X;}
+
+%type inscollist {GSList*}
+%destructor inscollist {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_field_free, NULL); g_slist_free ($$);}}
+inscollist(A) ::= inscollist(X) COMMA fullname(Y). {GdaSqlField *field;
+						    field = gda_sql_field_new (NULL);
+						    gda_sql_field_take_name (field, Y);
+						    A = g_slist_append (X, field);
+}
+inscollist(A) ::= fullname(Y). {GdaSqlField *field = gda_sql_field_new (NULL);
+				gda_sql_field_take_name (field, Y);
+				A = g_slist_prepend (NULL, field);
+}
+
+// DELETE
+cmd(C) ::= DELETE FROM fullname(T) where_opt(X). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_DELETE); 
+						  gda_sql_statement_delete_take_table_name (C, T);
+						  gda_sql_statement_delete_take_condition (C, X);}
+
+%type where_opt {GdaSqlExpr *}
+%destructor where_opt {gda_sql_expr_free ($$);}
+where_opt(A) ::= .                    {A = NULL;}
+where_opt(A) ::= WHERE expr(X).       {A = X;}
+
+// UPDATE
+cmd(C) ::= UPDATE opt_on_conflict(O) fullname(T) SET setlist(S) where_opt(X). {
+	GSList *list;
+	C = gda_sql_statement_new (GDA_SQL_STATEMENT_UPDATE);
+	gda_sql_statement_update_take_table_name (C, T);
+	gda_sql_statement_update_take_on_conflict (C, O);
+	gda_sql_statement_update_take_condition (C, X);
+	for (list = S; list; list = list->next) {
+		UpdateSet *set = (UpdateSet*) list->data;
+		gda_sql_statement_update_take_set_value (C, set->fname, set->expr);
+		g_free (set);
+	}
+	g_slist_free (S);
+}
+
+%type setlist {GSList*}
+%destructor setlist {GSList *list;
+	for (list = $$; list; list = list->next) {
+		UpdateSet *set = (UpdateSet*) list->data;
+		g_value_reset (set->fname); g_free (set->fname);
+		gda_sql_expr_free (set->expr);
+		g_free (set);
+	}
+	g_slist_free ($$);
+}
+setlist(A) ::= setlist(Z) COMMA fullname(X) EQ expr(Y). {UpdateSet *set;
+							 set = g_new (UpdateSet, 1);
+							 set->fname = X;
+							 set->expr = Y;
+							 A = g_slist_append (Z, set);
+}
+setlist(A) ::= fullname(X) EQ expr(Y). {UpdateSet *set;
+					set = g_new (UpdateSet, 1);
+					set->fname = X;
+					set->expr = Y;
+					A = g_slist_append (NULL, set);
+}
+
+// COMPOUND SELECT
+%type compound {GdaSqlStatement *}
+%destructor compound {gda_sql_statement_free ($$);}
+//compound(C) ::= LP compound(E) RP. {C = E;}
+compound(C) ::= selectcmd(S). {
+	C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMPOUND);
+	gda_sql_statement_compound_take_stmt (C, S);
+}
+compound(C) ::= compound(L) UNION opt_compound_all(A) compound(R). {
+	C = compose_multiple_compounds (A ? GDA_SQL_STATEMENT_COMPOUND_UNION_ALL : GDA_SQL_STATEMENT_COMPOUND_UNION,
+					L, R);
+}
+
+compound(C) ::= compound(L) EXCEPT opt_compound_all(A) compound(R). {
+	C = compose_multiple_compounds (A ? GDA_SQL_STATEMENT_COMPOUND_EXCEPT_ALL : GDA_SQL_STATEMENT_COMPOUND_EXCEPT,
+					L, R);
+} 
+
+compound(C) ::= compound(L) INTERSECT opt_compound_all(A) compound(R). {
+	C = compose_multiple_compounds (A ? GDA_SQL_STATEMENT_COMPOUND_INTERSECT_ALL : GDA_SQL_STATEMENT_COMPOUND_INTERSECT,
+					L, R);
+} 
+
+%type opt_compound_all {gboolean}
+opt_compound_all(A) ::= .    {A = FALSE;}
+opt_compound_all(A) ::= ALL. {A = TRUE;}
+
+
+// SELECT
+%type selectcmd {GdaSqlStatement *}
+%destructor selectcmd {gda_sql_statement_free ($$);}
+selectcmd(C) ::= SELECT distinct(D) selcollist(W) from(F) where_opt(Y)
+	 groupby_opt(P) having_opt(Q) orderby_opt(Z) limit_opt(L). {
+	C = gda_sql_statement_new (GDA_SQL_STATEMENT_SELECT);
+	if (D) {
+		gda_sql_statement_select_take_distinct (C, D->distinct, D->expr);
+		g_free (D);
+	}
+	gda_sql_statement_select_take_expr_list (C, W);
+	gda_sql_statement_select_take_from (C, F);
+	gda_sql_statement_select_take_where_cond (C, Y);
+	gda_sql_statement_select_take_group_by (C, P);
+	gda_sql_statement_select_take_having_cond (C, Q);
+	gda_sql_statement_select_take_order_by (C, Z);
+	gda_sql_statement_select_take_limits (C, L.count, L.offset);
+}
+
+%type limit_opt {Limit}
+%destructor limit_opt {gda_sql_expr_free ($$.count); gda_sql_expr_free ($$.offset);}
+limit_opt(A) ::= .                     {A.count = NULL; A.offset = NULL;}
+limit_opt(A) ::= LIMIT expr(X).        {A.count = X; A.offset = NULL;}
+limit_opt(A) ::= LIMIT expr(X) OFFSET expr(Y). {A.count = X; A.offset = Y;}
+limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y). {A.count = X; A.offset = Y;}
+
+%type orderby_opt {GSList *}
+%destructor orderby_opt {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_select_order_free, NULL); g_slist_free ($$);}}
+orderby_opt(A) ::= .                          {A = 0;}
+orderby_opt(A) ::= ORDER BY sortlist(X).      {A = X;}
+
+%type sortlist {GSList *}
+%destructor sortlist {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_select_order_free, NULL); g_slist_free ($$);}}
+sortlist(A) ::= sortlist(X) COMMA expr(Y) sortorder(Z). {GdaSqlSelectOrder *order;
+							 order = gda_sql_select_order_new (NULL);
+							 order->expr = Y;
+							 order->asc = Z;
+							 A = g_slist_append (X, order);
+}
+sortlist(A) ::= expr(Y) sortorder(Z). {GdaSqlSelectOrder *order;
+				       order = gda_sql_select_order_new (NULL);
+				       order->expr = Y;
+				       order->asc = Z;
+				       A = g_slist_prepend (NULL, order);
+}
+
+%type sortorder {gboolean}
+sortorder(A) ::= ASC.           {A = TRUE;}
+sortorder(A) ::= DESC.          {A = FALSE;}
+sortorder(A) ::= .              {A = TRUE;}
+
+
+%type having_opt {GdaSqlExpr *}
+%destructor having_opt {gda_sql_expr_free ($$);}
+having_opt(A) ::= .                     {A = NULL;}
+having_opt(A) ::= HAVING expr(X).       {A = X;}
+
+%type groupby_opt {GSList*}
+%destructor groupby_opt {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_expr_free, NULL); g_slist_free ($$);}}
+groupby_opt(A) ::= .                      {A = 0;}
+groupby_opt(A) ::= GROUP BY nexprlist(X). {A = X;}
+
+%type from {GdaSqlSelectFrom *}
+%destructor from {gda_sql_select_from_free ($$);}
+from(F) ::= .                   {F = NULL;}
+from(F) ::= FROM seltablist(X). {F = X;}
+
+%type seltablist {GdaSqlSelectFrom *}
+%destructor seltablist {gda_sql_select_from_free ($$);}
+%type stl_prefix {GdaSqlSelectFrom *}
+%destructor stl_prefix {gda_sql_select_from_free ($$);}
+
+seltablist(L) ::= stl_prefix(P) seltarget(T) on_cond(C) using_opt(U). {
+	GSList *last;
+	if (P)
+		L = P;
+	else 
+		L = gda_sql_select_from_new (NULL);
+	gda_sql_select_from_take_new_target (L, T);
+	last = g_slist_last (L->joins);
+	if (last) {
+		GdaSqlSelectJoin *join = (GdaSqlSelectJoin *) (last->data);
+		join->expr = C;
+		join->position = g_slist_length (L->targets) - 1;
+		join->use = U;
+	}
+}
+
+%type using_opt {GSList*}
+%destructor using_opt {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_field_free, NULL); g_slist_free ($$);}}
+using_opt(U) ::= USING LP inscollist(L) RP. {U = L;}
+using_opt(U) ::= .                          {U = NULL;}
+
+stl_prefix(P) ::= . {P = NULL;}
+stl_prefix(P) ::= seltablist(L) jointype(J). {GdaSqlSelectJoin *join;
+					      P = L;
+					      join = gda_sql_select_join_new (GDA_SQL_ANY_PART (P));
+					      join->type = J;
+					      gda_sql_select_from_take_new_join (P, join);
+}
+					      
+
+%type on_cond {GdaSqlExpr *}
+%destructor on_cond {gda_sql_expr_free ($$);}
+on_cond(N) ::= ON expr(E).  {N = E;}
+on_cond(N) ::= .            {N = NULL;}
+
+%type jointype {GdaSqlSelectJoinType}
+jointype(J) ::= COMMA. {J = GDA_SQL_SELECT_JOIN_CROSS;}
+jointype(J) ::= JOIN. {J = GDA_SQL_SELECT_JOIN_INNER;}
+jointype(J) ::= CROSS JOIN. {J = GDA_SQL_SELECT_JOIN_CROSS;}
+jointype(J) ::= INNER JOIN. {J = GDA_SQL_SELECT_JOIN_INNER;}
+jointype(J) ::= NATURAL JOIN. {J = GDA_SQL_SELECT_JOIN_NATURAL;}
+jointype(J) ::= LEFT JOIN. {J = GDA_SQL_SELECT_JOIN_LEFT;}
+jointype(J) ::= LEFT OUTER JOIN. {J = GDA_SQL_SELECT_JOIN_LEFT;}
+jointype(J) ::= RIGHT JOIN. {J = GDA_SQL_SELECT_JOIN_RIGHT;}
+jointype(J) ::= RIGHT OUTER JOIN. {J = GDA_SQL_SELECT_JOIN_RIGHT;}
+jointype(J) ::= FULL JOIN. {J = GDA_SQL_SELECT_JOIN_FULL;}
+jointype(J) ::= FULL OUTER JOIN. {J = GDA_SQL_SELECT_JOIN_FULL;}
+
+
+%type seltarget {GdaSqlSelectTarget *}
+%destructor seltarget {gda_sql_select_target_free ($$);}
+seltarget(T) ::= fullname(F) as(A). {T = gda_sql_select_target_new (NULL);
+				     gda_sql_select_target_take_alias (T, A);
+				     gda_sql_select_target_take_table_name (T, F);
+}
+seltarget(T) ::= fullname(F) ID(A). {T = gda_sql_select_target_new (NULL);
+                                     gda_sql_select_target_take_alias (T, A);
+                                     gda_sql_select_target_take_table_name (T, F);
+}
+seltarget(T) ::= LP compound(S) RP as(A). {T = gda_sql_select_target_new (NULL);
+					     gda_sql_select_target_take_alias (T, A);
+					     gda_sql_select_target_take_select (T, S);
+}
+
+%type selcollist {GSList *}
+%destructor selcollist {g_slist_foreach ($$, (GFunc) gda_sql_select_field_free, NULL); g_slist_free ($$);}
+
+%type sclp {GSList *}
+%destructor sclp {g_slist_foreach ($$, (GFunc) gda_sql_select_field_free, NULL); g_slist_free ($$);}
+sclp(A) ::= selcollist(X) COMMA.             {A = X;}
+sclp(A) ::= .                                {A = NULL;}
+
+selcollist(L) ::= sclp(E) expr(X) as(A). {GdaSqlSelectField *field;
+					  field = gda_sql_select_field_new (NULL);
+					  gda_sql_select_field_take_expr (field, X);
+					  gda_sql_select_field_take_alias (field, A); 
+					  L = g_slist_append (E, field);}
+selcollist(L) ::= sclp(E) starname(X). {GdaSqlSelectField *field;
+					field = gda_sql_select_field_new (NULL);
+					gda_sql_select_field_take_star_value (field, X);
+					L = g_slist_append (E, field);}
+
+starname(S) ::= STAR(X). {S = X;}
+starname(A) ::= nm(S) DOT STAR(X). {gchar *str;
+				  str = g_strdup_printf ("%s.%s", g_value_get_string (S), g_value_get_string (X));
+				  A = g_new0 (GValue, 1);
+				  g_value_init (A, G_TYPE_STRING);
+				  g_value_take_string (A, str);
+				  g_value_reset (S); g_free (S);
+				  g_value_reset (X); g_free (X);
+}
+
+starname(A) ::= nm(C) DOT nm(S) DOT STAR(X). {gchar *str;
+				  str = g_strdup_printf ("%s.%s.%s", g_value_get_string (C), 
+							 g_value_get_string (S), g_value_get_string (X));
+				  A = g_new0 (GValue, 1);
+				  g_value_init (A, G_TYPE_STRING);
+				  g_value_take_string (A, str);
+				  g_value_reset (C); g_free (C);
+				  g_value_reset (S); g_free (S);
+				  g_value_reset (X); g_free (X);
+}
+
+as(A) ::= AS fullname(F). {A = F;}
+as(A) ::= AS value(F). {A = F;}
+as(A) ::= . {A = NULL;}
+
+%type distinct {Distinct *}
+%destructor distinct {if ($$) {if ($$->expr) gda_sql_expr_free ($$->expr); g_free ($$);}}
+distinct(E) ::= . {E = NULL;}
+distinct(E) ::= ALL. {E = NULL;}
+distinct(E) ::= DISTINCT. {E = g_new0 (Distinct, 1); E->distinct = TRUE;}
+distinct(E) ::= DISTINCT ON expr(X). [OR] {E = g_new0 (Distinct, 1); E->distinct = TRUE; E->expr = X;}
+
+// Non empty list of expressions
+%type nexprlist {GSList *}
+%destructor nexprlist {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_expr_free, NULL); g_slist_free ($$);}}
+nexprlist(L) ::= nexprlist(E) COMMA expr(X). {L = g_slist_append (E, X);}
+nexprlist(L) ::= expr(E). {L = g_slist_append (NULL, E);}
+
+// List of expressions
+%type exprlist {GSList *}
+%destructor exprlist {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_expr_free, NULL); g_slist_free ($$);}}
+exprlist(L) ::= . {L = NULL;}
+exprlist(L) ::= exprlist(E) COMMA expr(X). {L = g_slist_append (E, X);}
+exprlist(L) ::= expr(E). {L = g_slist_append (NULL, E);}
+
+// A single expression
+%type expr {GdaSqlExpr *}
+%destructor expr {gda_sql_expr_free ($$);}
+expr(E) ::= pvalue(V). {E = V;}
+expr(E) ::= value(V). {E = gda_sql_expr_new (NULL); E->value = V;}
+expr(E) ::= LP expr(X) RP. {E = X;}
+expr(E) ::= fullname(V). {E = gda_sql_expr_new (NULL); E->value = V;}
+expr(E) ::= fullname(V) LP exprlist(A) RP. {GdaSqlFunction *func;
+					    E = gda_sql_expr_new (NULL); 
+					    func = gda_sql_function_new (GDA_SQL_ANY_PART (E)); 
+					    gda_sql_function_take_name (func, V);
+					    gda_sql_function_take_args_list (func, A);
+					    E->func = func;}
+expr(E) ::= fullname(V) LP compound(S) RP. {GdaSqlFunction *func;
+					     GdaSqlExpr *expr;
+					     E = gda_sql_expr_new (NULL); 
+					     func = gda_sql_function_new (GDA_SQL_ANY_PART (E)); 
+					     gda_sql_function_take_name (func, V);
+					     expr = gda_sql_expr_new (GDA_SQL_ANY_PART (func)); 
+					     gda_sql_expr_take_select (expr, S);
+					     gda_sql_function_take_args_list (func, g_slist_prepend (NULL, expr));
+					     E->func = func;}
+expr(E) ::= fullname(V) LP starname(A) RP. {GdaSqlFunction *func;
+					    GdaSqlExpr *expr;
+					    E = gda_sql_expr_new (NULL); 
+					    func = gda_sql_function_new (GDA_SQL_ANY_PART (E));
+					    gda_sql_function_take_name (func, V);
+					    expr = gda_sql_expr_new (GDA_SQL_ANY_PART (func)); 
+					    expr->value = A;
+					    gda_sql_function_take_args_list (func, g_slist_prepend (NULL, expr));
+					    E->func = func;}
+expr(E) ::= CAST LP expr(A) AS fullname(T) RP. {E = A;
+						A->cast_as = g_value_dup_string (T);
+						g_value_reset (T);
+						g_free (T);}
+expr(E) ::= expr(A) PGCAST fullname(T). {E = A;
+					 A->cast_as = g_value_dup_string (T);
+					 g_value_reset (T);
+					 g_free (T);}
+
+expr(C) ::= expr(L) PLUS|MINUS(O) expr(R). {C = compose_multiple_expr (string_to_op_type (O), L, R);}
+expr(C) ::= expr(L) STAR expr(R). {C = compose_multiple_expr (GDA_SQL_OPERATOR_TYPE_STAR, L, R);}
+expr(C) ::= expr(L) SLASH|REM(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
+expr(C) ::= expr(L) BITAND|BITOR(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
+
+expr(C) ::= MINUS expr(X). [UMINUS] {C = create_uni_expr (GDA_SQL_OPERATOR_TYPE_MINUS, X);}
+expr(C) ::= PLUS expr(X). [UPLUS] {C = create_uni_expr (GDA_SQL_OPERATOR_TYPE_PLUS, X);}
+
+expr(C) ::= expr(L) AND expr(R). {C = compose_multiple_expr (GDA_SQL_OPERATOR_TYPE_AND, L, R);}
+expr(C) ::= expr(L) OR expr(R). {C = compose_multiple_expr (GDA_SQL_OPERATOR_TYPE_OR, L, R);}
+expr(C) ::= expr(L) CONCAT expr(R). {C = compose_multiple_expr (GDA_SQL_OPERATOR_TYPE_CONCAT, L, R);}
+
+expr(C) ::= expr(L) GT|LEQ|GEQ|LT(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
+expr(C) ::= expr(L) DIFF|EQ(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
+expr(C) ::= expr(L) LIKE expr(R). {C = create_two_expr (GDA_SQL_OPERATOR_TYPE_LIKE, L, R);}
+expr(C) ::= expr(L) REGEXP|REGEXP_CI|NOT_REGEXP|NOT_REGEXP_CI|SIMILAR(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
+expr(C) ::= expr(L) BETWEEN expr(R) AND expr(E). {GdaSqlOperation *cond;
+						  C = gda_sql_expr_new (NULL);
+						  cond = gda_sql_operation_new (GDA_SQL_ANY_PART (C));
+						  C->cond = cond;
+						  cond->operator_type = GDA_SQL_OPERATOR_TYPE_BETWEEN;
+						  cond->operands = g_slist_append (NULL, L);
+						  GDA_SQL_ANY_PART (L)->parent = GDA_SQL_ANY_PART (cond);
+						  cond->operands = g_slist_append (cond->operands, R);
+						  GDA_SQL_ANY_PART (R)->parent = GDA_SQL_ANY_PART (cond);
+						  cond->operands = g_slist_append (cond->operands, E);
+						  GDA_SQL_ANY_PART (E)->parent = GDA_SQL_ANY_PART (cond);
+}
+
+expr(C) ::= expr(L) NOT BETWEEN expr(R) AND expr(E). {GdaSqlOperation *cond;
+						      GdaSqlExpr *expr;
+						      expr = gda_sql_expr_new (NULL);
+						      cond = gda_sql_operation_new (GDA_SQL_ANY_PART (expr));
+						      expr->cond = cond;
+						      cond->operator_type = GDA_SQL_OPERATOR_TYPE_BETWEEN;
+						      cond->operands = g_slist_append (NULL, L);
+						      GDA_SQL_ANY_PART (L)->parent = GDA_SQL_ANY_PART (cond);
+						      cond->operands = g_slist_append (cond->operands, R);
+						      GDA_SQL_ANY_PART (R)->parent = GDA_SQL_ANY_PART (cond);
+						      cond->operands = g_slist_append (cond->operands, E);
+						      GDA_SQL_ANY_PART (E)->parent = GDA_SQL_ANY_PART (cond);
+
+						      C = gda_sql_expr_new (NULL);
+						      cond = gda_sql_operation_new (GDA_SQL_ANY_PART (C));
+						      C->cond = cond;
+						      cond->operator_type = GDA_SQL_OPERATOR_TYPE_NOT;
+						      cond->operands = g_slist_prepend (NULL, expr);
+						      GDA_SQL_ANY_PART (expr)->parent = GDA_SQL_ANY_PART (cond);
+}
+
+expr(C) ::= NOT expr(R). {C = create_uni_expr (GDA_SQL_OPERATOR_TYPE_NOT, R);}
+expr(C) ::= BITNOT expr(R). {C = create_uni_expr (GDA_SQL_OPERATOR_TYPE_BITNOT, R);}
+expr(C) ::= expr(R) uni_op(O) . {C = create_uni_expr (O, R);}
+
+expr(C) ::= expr(L) IS expr(R). {C = create_two_expr (GDA_SQL_OPERATOR_TYPE_IS, L, R);}
+expr(E) ::= LP compound(S) RP. {E = gda_sql_expr_new (NULL); gda_sql_expr_take_select (E, S);}
+expr(E) ::= expr(R) IN LP exprlist(L) RP. {GdaSqlOperation *cond;
+					   GSList *list;
+					   E = gda_sql_expr_new (NULL);
+					   cond = gda_sql_operation_new (GDA_SQL_ANY_PART (E));
+					   E->cond = cond;
+					   cond->operator_type = GDA_SQL_OPERATOR_TYPE_IN;
+					   cond->operands = g_slist_prepend (L, R);
+					   for (list = cond->operands; list; list = list->next)
+						   GDA_SQL_ANY_PART (list->data)->parent = GDA_SQL_ANY_PART (cond);
+}
+expr(E) ::= expr(R) IN LP compound(S) RP. {GdaSqlOperation *cond;
+					    GdaSqlExpr *expr;
+					    E = gda_sql_expr_new (NULL);
+					    cond = gda_sql_operation_new (GDA_SQL_ANY_PART (E));
+					    E->cond = cond;
+					    cond->operator_type = GDA_SQL_OPERATOR_TYPE_IN;
+					    
+					    expr = gda_sql_expr_new (GDA_SQL_ANY_PART (cond));
+					    gda_sql_expr_take_select (expr, S);
+					    cond->operands = g_slist_prepend (NULL, expr);
+					    cond->operands = g_slist_prepend (cond->operands, R);
+					    GDA_SQL_ANY_PART (R)->parent = GDA_SQL_ANY_PART (cond);
+}
+expr(E) ::= expr(R) NOT IN LP exprlist(L) RP. {GdaSqlOperation *cond;
+					       GSList *list;
+					       E = gda_sql_expr_new (NULL);
+					       cond = gda_sql_operation_new (GDA_SQL_ANY_PART (E));
+					       E->cond = cond;
+					       cond->operator_type = GDA_SQL_OPERATOR_TYPE_NOTIN;
+					       cond->operands = g_slist_prepend (L, R);
+					       for (list = cond->operands; list; list = list->next)
+						       GDA_SQL_ANY_PART (list->data)->parent = GDA_SQL_ANY_PART (cond);
+}
+expr(E) ::= expr(R) NOT IN LP compound(S) RP. {GdaSqlOperation *cond;
+					       GdaSqlExpr *expr;
+					       E = gda_sql_expr_new (NULL);
+					       cond = gda_sql_operation_new (GDA_SQL_ANY_PART (E));
+					       E->cond = cond;
+					       cond->operator_type = GDA_SQL_OPERATOR_TYPE_NOTIN;
+					       
+					       expr = gda_sql_expr_new (GDA_SQL_ANY_PART (cond));
+					       gda_sql_expr_take_select (expr, S);
+					       cond->operands = g_slist_prepend (NULL, expr);
+					       cond->operands = g_slist_prepend (cond->operands, R);
+					       GDA_SQL_ANY_PART (R)->parent = GDA_SQL_ANY_PART (cond);
+}
+expr(A) ::= CASE case_operand(X) case_exprlist(Y) case_else(Z) END. {
+	GdaSqlCase *sc;
+	GSList *list;
+	A = gda_sql_expr_new (NULL);
+	sc = gda_sql_case_new (GDA_SQL_ANY_PART (A));
+	sc->base_expr = X;
+	sc->else_expr = Z;
+	sc->when_expr_list = Y.when_list;
+	sc->then_expr_list = Y.then_list;
+	A->case_s = sc;
+	for (list = sc->when_expr_list; list; list = list->next)
+		GDA_SQL_ANY_PART (list->data)->parent = GDA_SQL_ANY_PART (sc);
+	for (list = sc->then_expr_list; list; list = list->next)
+		GDA_SQL_ANY_PART (list->data)->parent = GDA_SQL_ANY_PART (sc);
+}
+	
+%type case_operand {GdaSqlExpr*}
+%destructor case_operand {gda_sql_expr_free ($$);}
+case_operand(A) ::= expr(X).            {A = X;}
+case_operand(A) ::= .                   {A = NULL;}
+
+%type case_exprlist {CaseBody}
+%destructor case_exprlist {g_slist_foreach ($$.when_list, (GFunc) gda_sql_expr_free, NULL); g_slist_free ($$.when_list);
+	g_slist_foreach ($$.then_list, (GFunc) gda_sql_expr_free, NULL); g_slist_free ($$.then_list);}
+
+case_exprlist(A) ::= case_exprlist(X) WHEN expr(Y) THEN expr(Z). {
+	A.when_list = g_slist_append (X.when_list, Y);
+	A.then_list = g_slist_append (X.then_list, Z);
+}
+case_exprlist(A) ::= WHEN expr(Y) THEN expr(Z). {
+	A.when_list = g_slist_prepend (NULL, Y);
+	A.then_list = g_slist_prepend (NULL, Z);
+}
+
+%type case_else {GdaSqlExpr*}
+%destructor case_else {gda_sql_expr_free ($$);}
+case_else(A) ::= ELSE expr(X).       {A = X;}
+case_else(A) ::= .                   {A = NULL;}
+
+%type uni_op {GdaSqlOperatorType}
+uni_op(O) ::= ISNULL. {O = GDA_SQL_OPERATOR_TYPE_ISNULL;}
+uni_op(O) ::= IS NOTNULL. {O = GDA_SQL_OPERATOR_TYPE_ISNOTNULL;}
+
+
+// Values: for all constants (G_TYPE_STRING GValue)
+value(V) ::= NULL. {V = NULL;}
+value(V) ::= STRING(S). {V = S;}
+//value(V) ::= TEXTUAL(T). {V = T;}
+value(V) ::= INTEGER(I). {V = I;}
+value(V) ::= FLOAT(F). {V = F;}
+
+// pvalue: values which are parameters (GdaSqlExpr)
+%type pvalue {GdaSqlExpr *}
+%destructor pvalue {gda_sql_expr_free ($$);}
+pvalue(E) ::= UNSPECVAL LSBRACKET paramspec(P) RSBRACKET. {E = gda_sql_expr_new (NULL); E->param_spec = P;}
+pvalue(E) ::= value(V) LSBRACKET paramspec(P) RSBRACKET. {E = gda_sql_expr_new (NULL); E->value = V; E->param_spec = P;}
+pvalue(E) ::= SIMPLEPARAM(S). {E = gda_sql_expr_new (NULL); E->param_spec = gda_sql_param_spec_new (S);}
+
+// paramspec: parameter's specifications
+%type paramspec {GdaSqlParamSpec *}
+%destructor paramspec {gda_sql_param_spec_free ($$);}
+paramspec(P) ::= . {P = NULL;}
+paramspec(P) ::= paramspec(E) PNAME(N). {if (!E) P = gda_sql_param_spec_new (NULL); else P = E; 
+					 gda_sql_param_spec_take_name (P, N);}
+paramspec(P) ::= paramspec(E) PDESCR(N). {if (!E) P = gda_sql_param_spec_new (NULL); else P = E; 
+					 gda_sql_param_spec_take_descr (P, N);}
+paramspec(P) ::= paramspec(E) PTYPE(N). {if (!E) P = gda_sql_param_spec_new (NULL); else P = E; 
+					 gda_sql_param_spec_take_type (P, N);}
+paramspec(P) ::= paramspec(E) PNULLOK(N). {if (!E) P = gda_sql_param_spec_new (NULL); else P = E; 
+					   gda_sql_param_spec_take_nullok (P, N);}
+
+// The name of a column or table can be any of the following:
+//
+nm(A) ::= JOIN(X).       {A = X;}
+nm(A) ::= ID(X).       {A = X;}
+nm(A) ::= TEXTUAL(X). {A = X;}
+
+// Fully qualified name
+fullname(A) ::= nm(X). {A = X;}
+fullname(A) ::= nm(S) DOT nm(X). {gchar *str;
+				  str = g_strdup_printf ("%s.%s", g_value_get_string (S), g_value_get_string (X));
+				  A = g_new0 (GValue, 1);
+				  g_value_init (A, G_TYPE_STRING);
+				  g_value_take_string (A, str);
+				  g_value_reset (S); g_free (S);
+				  g_value_reset (X); g_free (X);
+}
+
+fullname(A) ::= nm(C) DOT nm(S) DOT nm(X). {gchar *str;
+				  str = g_strdup_printf ("%s.%s.%s", g_value_get_string (C), 
+							 g_value_get_string (S), g_value_get_string (X));
+				  A = g_new0 (GValue, 1);
+				  g_value_init (A, G_TYPE_STRING);
+				  g_value_take_string (A, str);
+				  g_value_reset (C); g_free (C);
+				  g_value_reset (S); g_free (S);
+				  g_value_reset (X); g_free (X);
+}
diff --git a/providers/oracle/utils.c b/providers/oracle/utils.c
deleted file mode 100644
index b776e23..0000000
--- a/providers/oracle/utils.c
+++ /dev/null
@@ -1,550 +0,0 @@
-/* GDA Oracle provider
- * Copyright (C) 2002 - 2007 The GNOME Foundation.
- *
- * AUTHORS:
- * 	Tim Coleman <tim timcoleman com>
- *      Vivien Malerba <malerba gnome-db org>
- *
- * Borrowed from Mysql utils.c, written by:
- *      Michael Lausch <michael lausch at>
- *	Rodrigo Moya <rodrigo gnome-db org>
- *      Vivien Malerba <malerba gnome-db org>
- *
- * This Library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This Library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this Library; see the file COPYING.LIB.  If not,
- * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include <glib/gi18n-lib.h>
-#include <stdlib.h>
-#include <string.h>
-#include "gda-oracle.h"
-#include "gda-oracle-provider.h"
-#include "gda-oracle-blob-op.h"
-
-/* 
- * gda_oracle_make_error
- * This function uses OCIErrorGet to get a description of the error to
- * display.  The parameters are one of an OCIError or a OCIEnv handle
- * depending on the type, which is either OCI_HTYPE_ERROR or OCI_HTYPE_ENV.
- * Read the documentation on OCIErrorGet to understand why this is
- *
- * If the handle is NULL, which is an unhappy situation, it will set the
- * error description to "NO DESCRIPTION".
- *
- * The error number is set to the Oracle error code.
- */
-GdaConnectionEvent *
-gda_oracle_make_error (dvoid *hndlp, ub4 type, const gchar *file, gint line)
-{
-	GdaConnectionEvent *error;
-	gchar errbuf[512];
-	ub4 errcode;
-	gchar *source;
-
-	error = gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR);
-
-	if (hndlp != NULL) {
-		OCIErrorGet ((dvoid *) hndlp,
-			     (ub4) 1, 
-			     (text *) NULL, 
-			     &errcode, 
-				errbuf, 
-			     (ub4) sizeof (errbuf), 
-			     (ub4) type);
-	
-		gda_connection_event_set_description (error, errbuf);
-		/*g_warning ("Oracle error:%s", errbuf);*/
-	} 
-	else 
-		gda_connection_event_set_description (error, _("NO DESCRIPTION"));
-	
-	gda_connection_event_set_code (error, errcode);
-	source = g_strdup_printf ("gda-oracle:%s:%d", file, line);
-	gda_connection_event_set_source (error, source);
-	g_free(source);
-	
-	return error;
-}
-
-/* 
- * gda_oracle_check_result
- * This function is used for checking the result of an OCI
- * call.  The result itself is the return value, and we
- * need the GdaConnection and GdaOracleConnectionData to do
- * our thing.  The type is OCI_HTYPE_ENV or OCI_HTYPE_ERROR
- * as described for OCIErrorGet.
- *
- * The return value is true if there is no error, or false otherwise
- *
- * If the return value is OCI_SUCCESS or OCI_SUCCESS_WITH_INFO,
- * we return TRUE.  Otherwise, if it is OCI_ERROR, try to get the
- * Oracle error message using gda_oracle_make_error.  Otherwise,
- * make an error using the given message.
- */
-GdaConnectionEvent * 
-gda_oracle_handle_error (gint result, GdaConnection *cnc, 
-			 GdaOracleConnectionData *priv_data,
-			 ub4 type, const gchar *msg,
-			 const gchar *file, gint line)
-{
-	GdaConnectionEvent *error = NULL;
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
-
-	switch (result) {
-	case OCI_SUCCESS:
-	case OCI_SUCCESS_WITH_INFO:
-		return NULL;
-	case OCI_ERROR:
-		switch(type) {
-		case OCI_HTYPE_ERROR:
-			error = gda_oracle_make_error (priv_data->herr, type, file, line);
-			gda_connection_add_event (cnc, error);
-			break;
-		case OCI_HTYPE_ENV:
-			error = gda_oracle_make_error (priv_data->henv, type, file, line);
-			gda_connection_add_event (cnc, error);
-			break;
-		default:
-			break;
-		}
-		break;
-	default:
-		error = gda_connection_add_event_string (cnc, msg);
-	}
-
-	return error;
-}
-
-GType 
-oracle_sqltype_to_g_type (const ub2 sqltype)
-{
-	/* an incomplete list of all the oracle types */
-	switch (sqltype) {
-	case SQLT_CHR:
-	case SQLT_STR:
-	case SQLT_VCS:
-	case SQLT_RID:
-	case SQLT_LNG:
-	case SQLT_LVC:
-	case SQLT_AFC:
-	case SQLT_AVC:
-	case SQLT_LAB:
-	case SQLT_VST:
-		return G_TYPE_STRING;
-	case SQLT_NUM:
-		return GDA_TYPE_NUMERIC;
-	case SQLT_INT:
-		return G_TYPE_INT;
-	case SQLT_UIN:
-		return G_TYPE_UINT;
-	case SQLT_FLT:
-		return G_TYPE_FLOAT;
-	case SQLT_VBI:
-	case SQLT_BIN:
-	case SQLT_LBI:
-	case SQLT_LVB:
-	case SQLT_BLOB:
-	case SQLT_BFILEE:
-	case SQLT_CFILEE:
-	case SQLT_CLOB:
-		return GDA_TYPE_BLOB;
-	case SQLT_DAT:
-	case SQLT_ODT:
-	case SQLT_DATE:
-		return G_TYPE_DATE;
-	case SQLT_TIME:
-	case SQLT_TIME_TZ:
-		return GDA_TYPE_TIME;
-	case SQLT_TIMESTAMP:
-	case SQLT_TIMESTAMP_TZ:
-	case SQLT_TIMESTAMP_LTZ:
-		return GDA_TYPE_TIMESTAMP;
-	case SQLT_SLS:
-	case SQLT_CUR:
-	case SQLT_RDD:
-	case SQLT_OSL:
-	case SQLT_NTY:
-	case SQLT_REF:
-	case SQLT_RSET:
-	case SQLT_NCO:
-	case SQLT_INTERVAL_YM:
-	case SQLT_INTERVAL_DS:
-	case SQLT_VNU:
-	case SQLT_PDN:
-	case SQLT_NON:
-	default:
-		return G_TYPE_INVALID;
-	}
-}
-
-gchar * 
-oracle_sqltype_to_string (const ub2 sqltype)
-{
-	/* an incomplete list of all the oracle types */
-	switch (sqltype) {
-	case SQLT_CHR:
-		return "VARCHAR2";
-	case SQLT_NUM:
-		return "NUMBER";
-	case SQLT_INT:
-		return "INTEGER";
-	case SQLT_FLT:
-		return "FLOAT";
-	case SQLT_STR:
-		return "STRING";
-	case SQLT_VNU:
-		return "VARNUM";
-	case SQLT_PDN:
-		return "";
-	case SQLT_LNG:
-		return "LONG";
-	case SQLT_VCS:
-		return "VARCHAR";
-	case SQLT_NON:
-		return "";
-	case SQLT_RID:
-		return "ROWID";
-	case SQLT_DAT:
-		return "DATE";
-	case SQLT_VBI:
-		return "VARRAW";
-	case SQLT_BIN:
-		return "RAW";
-	case SQLT_LBI:
-		return "LONG RAW";
-	case SQLT_UIN:
-		return "UNSIGNED INT";
-	case SQLT_SLS:
-		return "";
-	case SQLT_LVC:
-		return "LONG VARCHAR";
-	case SQLT_LVB:
-		return "LONG VARRAW";
-	case SQLT_AFC:
-		return "CHAR";
-	case SQLT_AVC:
-		return "CHARZ";
-	case SQLT_CUR:
-		return "CURSOR";
-	case SQLT_RDD:
-		return "ROWID";
-	case SQLT_LAB:
-		return "LABEL";
-	case SQLT_OSL:
-		return "OSLABEL";
-	case SQLT_NTY:
-		return "";
-	case SQLT_REF:
-		return "";
-	case SQLT_CLOB:
-		return "CLOB";
-	case SQLT_BLOB:
-		return "BLOB";
-	case SQLT_BFILEE:
-		return "BFILE";
-	case SQLT_CFILEE:
-		return "CFILE";
-	case SQLT_RSET:
-		return "RESULT SET";
-	case SQLT_NCO:
-		return "";
-	case SQLT_VST:
-		return "";
-	case SQLT_ODT:
-		return "OCI DATE";
-	case SQLT_DATE:
-		return "ANSI DATE";
-	case SQLT_TIME:
-		return "TIME";
-	case SQLT_TIME_TZ:
-		return "TIME WITH TIME ZONE";
-	case SQLT_TIMESTAMP:
-		return "TIMESTAMP";
-	case SQLT_TIMESTAMP_TZ:
-		return "TIMESTAMP WITH TIME ZONE";
-	case SQLT_INTERVAL_YM:
-		return "INTERVAL YEAR TO MONTH";
-	case SQLT_INTERVAL_DS:
-		return "INTERVAL DAY TO SECOND";
-	case SQLT_TIMESTAMP_LTZ:
-		return "TIMESTAMP WITH LOCAL TIME ZONE";
-	default:
-		return "UNKNOWN";
-	}
-}
-
-gchar *
-gda_oracle_value_to_sql_string (GValue *value)
-{
-	gchar *val_str;
-	gchar *ret;
-	GType type;
-
-	g_return_val_if_fail (value != NULL, NULL);
-
-	val_str = gda_value_stringify (value);
-	if (!val_str)
-		return NULL;
-
-	type = G_VALUE_TYPE (value);
-	if ((type == G_TYPE_INT64) ||
-	    (type == G_TYPE_DOUBLE) ||
-	    (type == G_TYPE_INT) ||
-	    (type == GDA_TYPE_NUMERIC) ||
-	    (type == G_TYPE_FLOAT) ||
-	    (type == GDA_TYPE_SHORT) ||
-	    (type == G_TYPE_CHAR))
-		ret = val_str;
-	else {
-		ret = g_strdup_printf ("\"%s\"", val_str);
-		g_free(val_str);
-	}
-	
-	return ret;
-}
-
-GdaOracleValue *
-gda_value_to_oracle_value (const GValue *value)
-{
-	GdaOracleValue *ora_value;
-	OCIDate *oci_date;
-	GType type;
-
-	ora_value = g_new0 (GdaOracleValue, 1);
-
-	ora_value->g_type = G_VALUE_TYPE (value);
-	ora_value->indicator = 0;
-	ora_value->hdef = (OCIDefine *) 0;
-	ora_value->pard = (OCIParam *) 0;
-	type = ora_value->g_type;
-
-	if (type == GDA_TYPE_NULL)
-		ora_value->indicator = -1;
-	else if ((type == G_TYPE_INT64) ||
-		 (type == G_TYPE_DOUBLE) ||
-		 (type == G_TYPE_INT) ||
-		 (type == GDA_TYPE_NUMERIC) ||
-		 (type == G_TYPE_FLOAT) ||
-		 (type == GDA_TYPE_SHORT) ||
-		 (type == G_TYPE_CHAR)) {
-		gchar *val_str;
-		val_str = gda_value_stringify ((GValue *) value);
-		if (!val_str)
-			return NULL;
-		
-		ora_value->sql_type = SQLT_NUM;
-		ora_value->value = (void *) val_str;
-		ora_value->defined_size = strlen (val_str);
-	}
-	else if (type == G_TYPE_DATE) {
-		GDate *gda_date;
-		ora_value->sql_type = SQLT_ODT;
-		gda_date = (GDate*) g_value_get_boxed (value);
-		oci_date = g_new0(OCIDate, 1);
-		OCIDateSetDate(oci_date, gda_date->year, gda_date->month, gda_date->day);
-		ora_value->defined_size = sizeof (OCIDate);
-		ora_value->value = oci_date;
-	}
-	else if (type == GDA_TYPE_TIME) {
-		GdaTime *gda_time;
-		ora_value->sql_type = SQLT_ODT;
-		gda_time = (GdaTime *) gda_value_get_time ((GValue *) value);
-		oci_date = g_new0(OCIDate, 1);
-		OCIDateSetTime(oci_date, gda_time->hour, gda_time->minute, gda_time->second);
-		ora_value->defined_size = sizeof (OCIDate);
-		ora_value->value = oci_date;
-	}
-	else if (type == GDA_TYPE_TIMESTAMP) {
-		GdaTimestamp *gda_timestamp;
-		ora_value->sql_type = SQLT_ODT;
-		gda_timestamp = (GdaTimestamp *) gda_value_get_timestamp ((GValue *) value);
-		oci_date = g_new0(OCIDate, 1);
-		OCIDateSetDate(oci_date, gda_timestamp->year, gda_timestamp->month, gda_timestamp->day);
-		OCIDateSetTime(oci_date, gda_timestamp->hour, gda_timestamp->minute, gda_timestamp->second);
-		ora_value->defined_size = sizeof (OCIDate);
-		ora_value->value = oci_date;
-	}
-	else if (type == GDA_TYPE_BLOB) {
-		GdaBinary *bin;
-
-		bin = (GdaBinary *) gda_value_get_blob ((GValue *) value);
-		if (bin) {
-			ora_value->sql_type = SQLT_LNG;
-			ora_value->value = bin->data;
-			ora_value->defined_size = bin->binary_length;
-		}
-		else {
-			ora_value->sql_type = SQLT_CHR;
-			ora_value->value = g_strdup ("");
-			ora_value->defined_size = 0;
-		}
-	}
-	else {
-		gchar *val_str;
-		val_str = gda_value_stringify ((GValue *) value);
-		if (!val_str)
-			return NULL;
-
-		ora_value->sql_type = SQLT_CHR;
-		ora_value->value = val_str;
-		ora_value->defined_size = strlen (val_str);
-	}
-
-	return ora_value;
-}
-
-void
-gda_oracle_set_value (GValue *value, 
-		      GdaOracleValue *ora_value,
-		      GdaConnection *cnc)
-{
-	GdaTime gtime;
-	GdaTimestamp timestamp;
-	GdaNumeric numeric;
-	sb2 year;
-	ub1 month;
-	ub1 day;
-	ub1 hour;
-	ub1 min;
-	ub1 sec;
-	GType type;
-	gchar *string_buffer, *tmp;
-
-	if (-1 == (ora_value->indicator)) {
-		gda_value_set_null (value);
-		return;
-	}
-
-	type = ora_value->g_type;
-	gda_value_reset_with_type (value, type);
-	if (type == G_TYPE_BOOLEAN) 
-		g_value_set_boolean (value, (atoi (ora_value->value)) ? TRUE: FALSE);
-	else if (type == G_TYPE_STRING) {
-		string_buffer = g_malloc0 (ora_value->defined_size+1);
-		memcpy (string_buffer, ora_value->value, ora_value->defined_size);
-		string_buffer[ora_value->defined_size] = '\0';
-		g_strchomp(string_buffer);
-		tmp = g_locale_to_utf8 (string_buffer, -1, NULL, NULL, NULL);
-		g_value_set_string (value, tmp);
-		g_free (tmp);
-		g_free (string_buffer);
-	}
-	else if (type == G_TYPE_INT64)
-		g_value_set_int64 (value, atoll (ora_value->value));
-	else if (type == G_TYPE_INT)
-		g_value_set_int (value, atol (ora_value->value));
-	else if (type == G_TYPE_UINT)
-		g_value_set_uint (value, atol (ora_value->value));
-	else if (type == GDA_TYPE_SHORT)
-		gda_value_set_short (value, atoi (ora_value->value));
-	else if (type == G_TYPE_FLOAT)
-		g_value_set_float (value, atof (ora_value->value));
-	else if (type == G_TYPE_DOUBLE)
-		g_value_set_double (value, atof (ora_value->value));
-	else if (type == GDA_TYPE_NUMERIC) {
-		string_buffer = g_malloc0 (ora_value->defined_size+1);
-		memcpy (string_buffer, ora_value->value, ora_value->defined_size);
-		string_buffer [ora_value->defined_size] = '\0';
-		g_strchomp (string_buffer);
-		numeric.number = string_buffer;
-		numeric.precision = 0; /* FIXME */
-		numeric.width = 0; /* FIXME */
-		gda_value_set_numeric (value, &numeric);
-		g_free (string_buffer);
-	}
-	else if (type == G_TYPE_DATE) {
-		GDate *date;
-		OCIDateGetDate ((CONST OCIDate *) ora_value->value,
-				(sb2 *) &year,
-				(ub1 *) &month,
-				(ub1 *) &day);
-		date = g_date_new_dmy (day, month, year);
-		g_value_take_boxed (value, date);
-	}
-	else if (type == GDA_TYPE_GEOMETRIC_POINT) {}
-	else if (type == GDA_TYPE_NULL)
-		gda_value_set_null (value);
-	else if (type == GDA_TYPE_TIMESTAMP) {
-		OCIDateGetDate ((CONST OCIDate *) ora_value->value,
-				(sb2 *) &year,
-				(ub1 *) &month,
-				(ub1 *) &day);
-		OCIDateGetTime ((CONST OCIDate *) ora_value->value,
-				(ub1 *) &hour,
-				(ub1 *) &min,
-				(ub1 *) &sec);
-		timestamp.year = year;
-		timestamp.month = month;
-		timestamp.day = day;
-		timestamp.hour = hour;
-		timestamp.minute = min;
-		timestamp.second = sec;
-		timestamp.fraction = 0;
-		timestamp.timezone = 0;
-		gda_value_set_timestamp(value, &timestamp);
-	}
-	else if (type == GDA_TYPE_TIME) {
-		OCIDateGetTime ((CONST OCIDate *) ora_value->value,
-				(ub1 *) &hour,
-				(ub1 *) &min,
-				(ub1 *) &sec);
-		gtime.hour = hour;
-		gtime.minute = min;
-		gtime.second = sec;
-		gda_value_set_time (value, &gtime);
-	}
-	else if (type == GDA_TYPE_BINARY) {
-		g_warning ("GdaBinary type is not supported by Oracle");
-	}
-	else if (type == GDA_TYPE_BLOB) {
-		GdaBlob *blob;
-		GdaBlobOp *op;
-		OCILobLocator *lobloc;
-		GdaOracleConnectionData *priv_data;
-		gint result;
-
-		/* REM: we need to make a "copy" of the lob locator to give to the GdaOracleblobOp object */
-		priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
-		if (!priv_data) {
-			gda_connection_add_event_string (cnc, _("Invalid Oracle handle"));
-			gda_value_set_null (value);
-			return;
-		}
-
-		result = OCIDescriptorAlloc ((dvoid *) priv_data->henv, (dvoid **) &lobloc, 
-					     (ub4) gda_oracle_blob_type (ora_value->sql_type), (size_t) 0, (dvoid **) 0);
-		if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-					     _("Could not allocate Lob locator"))) {
-			gda_value_set_null (value);
-			return;
-		}
-
-		result = OCILobAssign ((dvoid *) priv_data->henv, (dvoid *) priv_data->herr, ora_value->value, &lobloc);
-		if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-					     _("Could not copy Lob locator"))) {
-			gda_value_set_null (value);
-			return;
-		}
-
-		blob = g_new0 (GdaBlob, 1);
-		op = gda_oracle_blob_op_new (cnc, lobloc);
-		gda_blob_set_op (blob, op);
-		g_object_unref (op);
-
-		gda_value_take_blob (value, blob);
-	}
-	else
-		g_value_set_string (value, ora_value->value);
-}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]