libgda r3167 - in trunk: . providers/firebird providers/mysql



Author: vivien
Date: Thu Jun 19 20:40:28 2008
New Revision: 3167
URL: http://svn.gnome.org/viewvc/libgda?rev=3167&view=rev

Log:
2008-06-19  Vivien Malerba <malerba gnome-db org>

	* providers/firebird: started re-write of Firebird provider
	* providers/mysql: more work (mainly on the meta data) from
	Carlos Savoretti


Modified:
   trunk/ChangeLog
   trunk/providers/firebird/Makefile.am
   trunk/providers/firebird/firebird_specs_dsn.xml.in
   trunk/providers/firebird/gda-firebird-blob-op.c
   trunk/providers/firebird/gda-firebird-blob-op.h
   trunk/providers/firebird/gda-firebird-provider.c
   trunk/providers/firebird/gda-firebird-provider.h
   trunk/providers/firebird/gda-firebird-recordset.c
   trunk/providers/firebird/gda-firebird-recordset.h
   trunk/providers/firebird/libgda-firebird-4.0.pc.in
   trunk/providers/firebird/libmain.c
   trunk/providers/mysql/gda-mysql-blob-op.c
   trunk/providers/mysql/gda-mysql-meta.c
   trunk/providers/mysql/gda-mysql-parser.c
   trunk/providers/mysql/gda-mysql-provider.c
   trunk/providers/mysql/gda-mysql-pstmt.c
   trunk/providers/mysql/gda-mysql-recordset.c
   trunk/providers/mysql/gda-mysql-util.c

Modified: trunk/providers/firebird/Makefile.am
==============================================================================
--- trunk/providers/firebird/Makefile.am	(original)
+++ trunk/providers/firebird/Makefile.am	Thu Jun 19 20:40:28 2008
@@ -1,40 +1,68 @@
 providerdir=$(libdir)/libgda-$(GDA_ABI_MAJOR_VERSION).$(GDA_ABI_MINOR_VERSION)/providers
 provider_LTLIBRARIES = libgda-firebird.la
 
+#Rem: FIREBIRD_CFLAGS and FIREBIRD_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) \
-	$(FIREBIRD_CFLAGS)
+	$(LIBGDA_CFLAGS) #$(FIREBIRD_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/parser_tokens.h"\" $(srcdir)/gen_def.c
+
+firebird_token_types.h: gen_def$(EXEEXT_FOR_BUILD) parser.h
+	./gen_def$(EXEEXT_FOR_BUILD) > firebird_token_types.h
+
+$(OBJECTS) $(libgda_firebird_la_OBJECTS): firebird_token_types.h
 
 libgda_firebird_la_SOURCES = \
 	gda-firebird-blob-op.c \
 	gda-firebird-blob-op.h \
+	gda-firebird-ddl.c \
+	gda-firebird-ddl.h \
+	gda-firebird-parser.c \
+	gda-firebird-parser.h \
 	gda-firebird-provider.c \
 	gda-firebird-provider.h \
+	gda-firebird-pstmt.h \
+	gda-firebird-pstmt.c \
+	gda-firebird-meta.c \
+	gda-firebird-meta.h \
 	gda-firebird-recordset.c \
 	gda-firebird-recordset.h \
-	libmain.c
+	gda-firebird-util.c \
+	gda-firebird-util.h \
+	gda-firebird.h \
+	libmain.c \
+	parser.h \
+        parser.c \
+        firebird_token_types.h
 
 libgda_firebird_la_LDFLAGS = -export-dynamic -module -avoid-version $(NO_UNDEFINED)
 libgda_firebird_la_LIBADD = \
 	$(top_builddir)/libgda/libgda-4.0.la \
-	$(LIBGDA_LIBS) \
-	$(FIREBIRD_LIBS)
+	$(LIBGDA_LIBS) #$(FIREBIRD_LIBS)
 
 xmldir   = $(datadir)/libgda-4.0
-xml_in_files = firebird_specs_dsn.xml.in
+xml_in_files = \
+	firebird_specs_dsn.xml.in \
+	firebird_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-firebird-4.0.pc
 
-EXTRA_DIST = $(xml_in_files) libgda-firebird-4.0.pc.in
+EXTRA_DIST = $(xml_in_files) libgda-firebird-4.0.pc.in parser.y gen_def.c
 DISTCLEANFILES = $(xml_DATA)
 
-
-
+CLEANFILES = parser.h parser.c parser.out firebird_token_types.h gen_def$(EXEEXT_FOR_BUILD)

Modified: trunk/providers/firebird/firebird_specs_dsn.xml.in
==============================================================================
--- trunk/providers/firebird/firebird_specs_dsn.xml.in	(original)
+++ trunk/providers/firebird/firebird_specs_dsn.xml.in	Thu Jun 19 20:40:28 2008
@@ -1,10 +1,12 @@
 <?xml version="1.0"?>
 <data-set-spec>
   <parameters>
-    <parameter id="DATABASE" _name="Database name" _descr="The name of a database to connect to" gdatype="gchararray" nullok="FALSE"/>
+    <parameter id="DB_NAME" _name="Database name" _descr="The name of a database to connect to" gdatype="gchararray" nullok="FALSE"/>
     <parameter id="CHARACTER_SET" _name="Character Set" _descr="Character set to be used during the connection" gdatype="gchararray"/>
     <!-- FIXME: pre-set values for the SQL_DIALECT values with human readable values -->
+    <!--
     <parameter id="SQL_DIALECT" _name="SQL Dialect" _descr="SQL dialect to use during the connection" gdatype="gint"/>
     <parameter id="PAGE_SIZE" _name="Page Size" _descr="Page size to use on the database" gdatype="gint"/>
+    -->
   </parameters>
 </data-set-spec>

Modified: trunk/providers/firebird/gda-firebird-blob-op.c
==============================================================================
--- trunk/providers/firebird/gda-firebird-blob-op.c	(original)
+++ trunk/providers/firebird/gda-firebird-blob-op.c	Thu Jun 19 20:40:28 2008
@@ -1,8 +1,8 @@
-/* GDA Firebird blob
- * Copyright (C) 2007 The GNOME Foundation
+/* GDA Firebird 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,38 +22,23 @@
 
 #include <glib/gi18n-lib.h>
 #include <string.h>
+#include <libgda/libgda.h>
+#include "gda-firebird.h"
 #include "gda-firebird-blob-op.h"
-#include "gda-firebird-recordset.h"
-#include "gda-firebird-provider.h"
-
-#ifdef PARENT_TYPE
-#undef PARENT_TYPE
-#endif
-
-#define PARENT_TYPE GDA_TYPE_BLOB_OP
-#define INFO_BUFFER_SIZE 32
 
 struct _GdaFirebirdBlobOpPrivate {
-	GdaConnection  *cnc;
-	ISC_QUAD        blob_id;
-	isc_blob_handle blob_handle; /* NULL if blob not opened */
-	
-	ISC_LONG        nb_segments;
-	ISC_LONG        max_segment_size;
-	ISC_LONG        blob_length;
-	int             blob_is_stream;
-
-	gpointer        trans_status;  /* initial transaction status when blob was created */
-	gboolean        trans_changed; /* if TRUE, then reading BLOB won't be possible anymore */
+	GdaConnection *cnc;
+	/* TO_ADD: specific information describing a Blob in the C API */
 };
 
 static void gda_firebird_blob_op_class_init (GdaFirebirdBlobOpClass *klass);
 static void gda_firebird_blob_op_init       (GdaFirebirdBlobOp *blob,
-					  GdaFirebirdBlobOpClass *klass);
+					 GdaFirebirdBlobOpClass *klass);
 static void gda_firebird_blob_op_finalize   (GObject *object);
 
 static glong gda_firebird_blob_op_get_length (GdaBlobOp *op);
 static glong gda_firebird_blob_op_read       (GdaBlobOp *op, GdaBlob *blob, glong offset, glong size);
+static glong gda_firebird_blob_op_write      (GdaBlobOp *op, GdaBlob *blob, glong offset);
 
 static GObjectClass *parent_class = NULL;
 
@@ -77,7 +62,7 @@
 			0,
 			(GInstanceInitFunc) gda_firebird_blob_op_init
 		};
-		type = g_type_register_static (PARENT_TYPE, "GdaFirebirdBlobOp", &info, 0);
+		type = g_type_register_static (GDA_TYPE_BLOB_OP, "GdaFirebirdBlobOp", &info, 0);
 	}
 	return type;
 }
@@ -89,14 +74,9 @@
 	g_return_if_fail (GDA_IS_FIREBIRD_BLOB_OP (op));
 
 	op->priv = g_new0 (GdaFirebirdBlobOpPrivate, 1);
-	op->priv->blob_handle = NULL;
-	memset (&(op->priv->blob_id), 0, sizeof (ISC_QUAD));
-	op->priv->max_segment_size = 0;
-	op->priv->blob_length = 0;
-	op->priv->nb_segments = 0;
-	op->priv->blob_is_stream = FALSE;
-	op->priv->trans_status = NULL;
-	op->priv->trans_changed = FALSE;
+
+	/* initialize specific structure */
+	TO_IMPLEMENT;
 }
 
 static void
@@ -110,144 +90,21 @@
 	object_class->finalize = gda_firebird_blob_op_finalize;
 	blob_class->get_length = gda_firebird_blob_op_get_length;
 	blob_class->read = gda_firebird_blob_op_read;
-	blob_class->write = NULL; /* to write to a BLOB, one must create another BLOB and do an UPDATE query */
-}
-
-static GdaFirebirdConnection *
-get_fcnc (GdaConnection *cnc)
-{
-	GdaFirebirdConnection *fcnc;
-
-	fcnc = g_object_get_data (G_OBJECT (cnc), CONNECTION_DATA);
-	if (!fcnc) 
-		gda_connection_add_event_string (cnc, _("Invalid FirebirdQL handle"));
-
-	return fcnc;
-}
-
-static gboolean
-blob_op_open (GdaFirebirdBlobOp *blobop)
-{
-	GdaFirebirdConnection *fcnc;
-	isc_tr_handle *ftr;
-
-	if (blobop->priv->blob_handle)
-		return TRUE;
-
-	fcnc = get_fcnc (blobop->priv->cnc);
-	ftr = g_object_get_data (G_OBJECT (blobop->priv->cnc), TRANSACTION_DATA);
-
-	if (isc_open_blob2 (fcnc->status, &(fcnc->handle), ftr, &(blobop->priv->blob_handle),
-			    &(blobop->priv->blob_id),
-			    0,        /* BPB length = 0; no filter will be used */
-			    NULL      /* NULL BPB, since no filter will be used */)) {
-		gda_firebird_connection_make_error (blobop->priv->cnc, 0);
-                return FALSE;
-	}
-
-	return TRUE;
-}
-
-static void
-blob_op_close (GdaFirebirdBlobOp *blobop)
-{
-	GdaFirebirdConnection *fcnc;
-	if (!blobop->priv->blob_handle)
-		return;
-
-	fcnc = get_fcnc (blobop->priv->cnc);
-	isc_close_blob (fcnc->status, &(blobop->priv->blob_handle));
-	blobop->priv->blob_handle = NULL;
-}
-
-static gboolean
-gda_firebird_blob_op_get_blob_attrs (GdaFirebirdBlobOp *blobop)
-{	
-	if (blobop->priv->max_segment_size > 0)
-		return TRUE; /* attributes already computed */
-
-	if (blobop->priv->trans_changed) {
-		gda_connection_add_event_string (blobop->priv->cnc, _("Transaction changed, BLOB can't be accessed"));
-		return FALSE;
-	}
-
-	if (!blob_op_open (blobop))
-		return FALSE;
-
-	char blob_items[]= {isc_info_blob_max_segment, isc_info_blob_total_length, 
-			    isc_info_blob_num_segments, isc_info_blob_type };
-	char res_buffer[INFO_BUFFER_SIZE], *res_buffer_ptr;
-	GdaFirebirdConnection *fcnc;
-
-	fcnc = get_fcnc (blobop->priv->cnc);
-
-	/* Get blob info */
-	if (isc_blob_info (fcnc->status, &(blobop->priv->blob_handle),
-			   sizeof (blob_items), blob_items,
-			   sizeof (res_buffer), res_buffer)) {
-		gda_firebird_connection_make_error (blobop->priv->cnc, 0);
-		blob_op_close (blobop);
-                return FALSE;
-	}
-
-	/* Parse blob info data */
-	for (res_buffer_ptr= res_buffer; *res_buffer_ptr != isc_info_end; ) {
-                char item= *res_buffer_ptr++;
-                if (item == isc_info_blob_max_segment) {
-			int length= isc_vax_integer (res_buffer_ptr, 2);
-			res_buffer_ptr+= 2;
-			blobop->priv->max_segment_size = isc_vax_integer (res_buffer_ptr, length);
-			res_buffer_ptr+= length;
-                }
-		else if (item == isc_info_blob_total_length) {
-			int length= isc_vax_integer (res_buffer_ptr, 2);
-			res_buffer_ptr+= 2;
-			blobop->priv->blob_length = isc_vax_integer (res_buffer_ptr, length);
-			res_buffer_ptr+= length;
-                }
-		else if (item == isc_info_blob_num_segments) {
-			int length= isc_vax_integer (res_buffer_ptr, 2);
-			res_buffer_ptr+= 2;
-			blobop->priv->nb_segments = isc_vax_integer (res_buffer_ptr, length);
-			res_buffer_ptr+= length;
-                }
-		else if (item == isc_info_blob_type) {
-			int length= isc_vax_integer (res_buffer_ptr, 2);
-			res_buffer_ptr+= 2;
-			blobop->priv->blob_is_stream = isc_vax_integer (res_buffer_ptr, length) ? TRUE : FALSE;
-			res_buffer_ptr+= length;
-			if (blobop->priv->blob_is_stream)
-				g_warning ("Stream BLOBs are not currently handled");
-                }
-	}
-
-	blob_op_close (blobop);
-	return TRUE;
-}
-
-static void
-cnc_transaction_status_changed_cb (GdaConnection *cnc, GdaFirebirdBlobOp *blobop)
-{
-	GdaTransactionStatus *ts;
-
-	ts = gda_connection_get_transaction_status (cnc);
-	if (ts != blobop->priv->trans_status)
-		blobop->priv->trans_changed = TRUE;
+	blob_class->write = gda_firebird_blob_op_write;
 }
 
 static void
 gda_firebird_blob_op_finalize (GObject * object)
 {
-	GdaFirebirdBlobOp *blobop = (GdaFirebirdBlobOp *) object;
+	GdaFirebirdBlobOp *pgop = (GdaFirebirdBlobOp *) object;
 
-	g_return_if_fail (GDA_IS_FIREBIRD_BLOB_OP (blobop));
+	g_return_if_fail (GDA_IS_FIREBIRD_BLOB_OP (pgop));
 
-	g_signal_handlers_disconnect_by_func (G_OBJECT (blobop->priv->cnc),
-					      G_CALLBACK (cnc_transaction_status_changed_cb), blobop);
-	blob_op_close (blobop);
+	/* free specific information */
+	TO_IMPLEMENT;
 
-	g_free (blobop->priv);
-	blobop->priv = NULL;
+	g_free (pgop->priv);
+	pgop->priv = NULL;
 
 	parent_class->finalize (object);
 }
@@ -255,178 +112,80 @@
 GdaBlobOp *
 gda_firebird_blob_op_new (GdaConnection *cnc)
 {
-	GdaFirebirdBlobOp *blobop;
+	GdaFirebirdBlobOp *pgop;
 
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
 
-	blobop = g_object_new (GDA_TYPE_FIREBIRD_BLOB_OP, NULL);
-	blobop->priv->cnc = cnc;
-	blobop->priv->trans_status = gda_connection_get_transaction_status (cnc);
-
-	g_signal_connect (G_OBJECT (cnc), "transaction-status-changed",
-			  G_CALLBACK (cnc_transaction_status_changed_cb), blobop);
+	pgop = g_object_new (GDA_TYPE_FIREBIRD_BLOB_OP, NULL);
+	pgop->priv->cnc = cnc;
 	
-	return GDA_BLOB_OP (blobop);
-}
-
-GdaBlobOp *
-gda_firebird_blob_op_new_with_id (GdaConnection *cnc, const ISC_QUAD *blob_id)
-{
-	GdaFirebirdBlobOp *blobop;
-
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-	blobop = g_object_new (GDA_TYPE_FIREBIRD_BLOB_OP, NULL);
-
-	blobop->priv->blob_id = *blob_id;
-	blobop->priv->cnc = cnc;
-	blobop->priv->trans_status = gda_connection_get_transaction_status (cnc);
-
-	g_signal_connect (G_OBJECT (cnc), "transaction-status-changed",
-			  G_CALLBACK (cnc_transaction_status_changed_cb), blobop);
-
-	return GDA_BLOB_OP (blobop);
+	return GDA_BLOB_OP (pgop);
 }
 
 /*
- * Virtual functions
+ * Get length request
  */
 static glong
 gda_firebird_blob_op_get_length (GdaBlobOp *op)
 {
-	GdaFirebirdBlobOp *blobop;
+	GdaFirebirdBlobOp *pgop;
 
 	g_return_val_if_fail (GDA_IS_FIREBIRD_BLOB_OP (op), -1);
-	blobop = GDA_FIREBIRD_BLOB_OP (op);
-	g_return_val_if_fail (blobop->priv, -1);
-	g_return_val_if_fail (GDA_IS_CONNECTION (blobop->priv->cnc), -1);
-	
-	/* use value if already computed */
-	if (blobop->priv->blob_length > 0)
-		return blobop->priv->blob_length;
-
-	if (gda_firebird_blob_op_get_blob_attrs (blobop))
-		return blobop->priv->blob_length;
-	else
-		return -1;
+	pgop = GDA_FIREBIRD_BLOB_OP (op);
+	g_return_val_if_fail (pgop->priv, -1);
+	g_return_val_if_fail (GDA_IS_CONNECTION (pgop->priv->cnc), -1);
+
+	TO_IMPLEMENT;
+	return -1;
 }
 
 /*
- * Reads a complete segment from the BLOB
- * Returns: a new GdaBinary structure
+ * Blob read request
  */
-static GdaBinary *
-blob_op_read_segment (GdaFirebirdBlobOp *blobop, GdaFirebirdConnection *fcnc, unsigned short segment_size)
-{
-	GdaBinary *bin;
-	char *blob_segment;
-	unsigned short actual_seg_length;
-
-	bin = g_new0 (GdaBinary, 1);
-
-	blob_segment = g_new0 (char, segment_size);
-	if (isc_get_segment (fcnc->status, &(blobop->priv->blob_handle),
-			     &actual_seg_length, /* length of segment read */
-			     segment_size, /* length of segment buffer */
-			     blob_segment/* segment buffer */)) {
-		gda_firebird_connection_make_error (blobop->priv->cnc, 0);
-		g_free (blob_segment);
-		g_free (bin);
-		blob_op_close (blobop);
-                return NULL;
-	}
-	if (fcnc->status[1] == isc_segment) {
-                /* isc_get_segment returns 0 if a segment was successfully read. */
-                /* status_vector[1] is set to isc_segment if only part of a */
-                /* segment was read due to the buffer (blob_segment) not being */
-		/* large enough. In that case, the following calls to */
-		/* isc_get_segment() read the rest of the buffer. */
-		/* SHOULD NOT HAPPEN HERE since we should have a big enough buffer */
-		TO_IMPLEMENT;
-	}
-	bin->data = blob_segment;
-	bin->binary_length = actual_seg_length;
-	return bin;
-}
-
-
 static glong
 gda_firebird_blob_op_read (GdaBlobOp *op, GdaBlob *blob, glong offset, glong size)
 {
-	GdaFirebirdBlobOp *blobop;
+	GdaFirebirdBlobOp *pgop;
 	GdaBinary *bin;
-	GdaFirebirdConnection *fcnc;
 
 	g_return_val_if_fail (GDA_IS_FIREBIRD_BLOB_OP (op), -1);
-	blobop = GDA_FIREBIRD_BLOB_OP (op);
-	g_return_val_if_fail (blobop->priv, -1);
-	g_return_val_if_fail (GDA_IS_CONNECTION (blobop->priv->cnc), -1);
+	pgop = GDA_FIREBIRD_BLOB_OP (op);
+	g_return_val_if_fail (pgop->priv, -1);
+	g_return_val_if_fail (GDA_IS_CONNECTION (pgop->priv->cnc), -1);
 	if (offset >= G_MAXINT)
 		return -1;
 	g_return_val_if_fail (blob, -1);
 
-	if (blobop->priv->trans_changed) {
-		gda_connection_add_event_string (blobop->priv->cnc, _("Transaction changed, BLOB can't be accessed"));
-		return -1;
-	}
-
 	bin = (GdaBinary *) blob;
 	if (bin->data) 
 		g_free (bin->data);
-	bin->data = NULL;
+	bin->data = g_new0 (guchar, size);
 	bin->binary_length = 0;
 
-	fcnc = get_fcnc (blobop->priv->cnc);	
+	/* fetch blob data using C API into bin->data, and set bin->binary_length */
+	TO_IMPLEMENT;
 
-	/* get the blob's segment size */
-	if (!gda_firebird_blob_op_get_blob_attrs (blobop))
-		return -1;
+	return bin->binary_length;
+}
 
-	if (!blob_op_open (blobop))
-		return -1;
+/*
+ * Blob write request
+ */
+static glong
+gda_firebird_blob_op_write (GdaBlobOp *op, GdaBlob *blob, glong offset)
+{
+	GdaFirebirdBlobOp *pgop;
+	GdaBinary *bin;
 
-	/* set at offset */
-	if (offset > 0) {
-		TO_IMPLEMENT;
-		blob_op_close (blobop);
-		return -1;
-	}
+	g_return_val_if_fail (GDA_IS_FIREBIRD_BLOB_OP (op), -1);
+	pgop = GDA_FIREBIRD_BLOB_OP (op);
+	g_return_val_if_fail (pgop->priv, -1);
+	g_return_val_if_fail (GDA_IS_CONNECTION (pgop->priv->cnc), -1);
+	g_return_val_if_fail (blob, -1);
 
-	/* read a segment */
-	glong remaining_to_read;
-	ISC_LONG nb_segments_read = 0;
-	for (remaining_to_read = size; 
-	     (remaining_to_read > 0) && (nb_segments_read < blobop->priv->nb_segments); 
-	     nb_segments_read++) {
-		GdaBinary *seg_bin;
-
-		seg_bin = blob_op_read_segment (blobop, fcnc, blobop->priv->max_segment_size);
-		if (!seg_bin) {
-			if (bin->data) 
-				g_free (bin->data);
-			bin->data = NULL;
-			bin->binary_length = 0;
-			return -1;
-		}
-		if (!bin->data) {
-			if (size <= seg_bin->binary_length) {
-				bin->data = seg_bin->data;
-				bin->binary_length = size;
-
-				seg_bin->data = NULL;
-				seg_bin->binary_length = 0;
-				gda_binary_free (seg_bin);
-				break; /* end of for() */
-			}
-			else
-				bin->data = g_new (guchar, size);
-		}
-		memcpy (bin->data + (size - remaining_to_read), seg_bin->data, 
-			MIN (remaining_to_read, seg_bin->binary_length));
-		bin->binary_length += MIN (remaining_to_read, seg_bin->binary_length);
-		remaining_to_read -= MIN (remaining_to_read, seg_bin->binary_length);
-		gda_binary_free (seg_bin);
-	}
+	/* write blob using bin->data and bin->binary_length */
+	bin = (GdaBinary *) blob;
+	TO_IMPLEMENT;
 
-	blob_op_close (blobop);
-	return bin->binary_length;
+	return -1;
 }

Modified: trunk/providers/firebird/gda-firebird-blob-op.h
==============================================================================
--- trunk/providers/firebird/gda-firebird-blob-op.h	(original)
+++ trunk/providers/firebird/gda-firebird-blob-op.h	Thu Jun 19 20:40:28 2008
@@ -1,8 +1,8 @@
-/* GDA DB Firebird Blob
- * Copyright (C) 2007 The GNOME Foundation
+/* GDA Firebird 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_FIREBIRD_BLOB_OP_H__
 #define __GDA_FIREBIRD_BLOB_OP_H__
 
-#include <libgda/gda-value.h>
 #include <libgda/gda-blob-op.h>
-#include <ibase.h>
 
 G_BEGIN_DECLS
 
@@ -40,17 +38,18 @@
 typedef struct _GdaFirebirdBlobOpPrivate GdaFirebirdBlobOpPrivate;
 
 struct _GdaFirebirdBlobOp {
-	GdaBlobOp                 parent;
+	GdaBlobOp             parent;
 	GdaFirebirdBlobOpPrivate *priv;
 };
 
 struct _GdaFirebirdBlobOpClass {
-	GdaBlobOpClass            parent_class;
+	GdaBlobOpClass        parent_class;
 };
 
 GType         gda_firebird_blob_op_get_type     (void) G_GNUC_CONST;
 GdaBlobOp    *gda_firebird_blob_op_new          (GdaConnection *cnc);
-GdaBlobOp    *gda_firebird_blob_op_new_with_id  (GdaConnection *cnc, const ISC_QUAD *blob_id);
+
+/* TO_ADD: more convenient API to create a GdaBlobOp with some specific information as argument */
 
 G_END_DECLS
 

Modified: trunk/providers/firebird/gda-firebird-provider.c
==============================================================================
--- trunk/providers/firebird/gda-firebird-provider.c	(original)
+++ trunk/providers/firebird/gda-firebird-provider.c	Thu Jun 19 20:40:28 2008
@@ -1,112 +1,154 @@
-/* GDA FireBird Provider
- * Copyright (C) 1998 - 2007 The GNOME Foundation
+/* GDA Firebird provider
+ * Copyright (C) 2008 The GNOME Foundation.
  *
  * AUTHORS:
- *         Albi Jeronimo <jeronimoalbi yahoo com ar>
- *         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.
+ *      Vivien Malerba <malerba gnome-db org>
  *
- * This library is distributed in the hope that it will be useful,
+ * 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.
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
 #include <glib/gi18n-lib.h>
-#include <libgda/gda-data-model-array.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/gda-command.h>
-#include <libgda/gda-parameter-list.h>
-#include <glib/gprintf.h>
-#include <string.h>
+#include <libgda/binreloc/gda-binreloc.h>
+#include <libgda/gda-statement-extra.h>
+#include <sql-parser/gda-sql-parser.h>
+#include "gda-firebird.h"
 #include "gda-firebird-provider.h"
 #include "gda-firebird-recordset.h"
+#include "gda-firebird-ddl.h"
+#include "gda-firebird-meta.h"
+#define _GDA_PSTMT(x) ((GdaPStmt*)(x))
+
+/*
+ * GObject methods
+ */
+static void gda_firebird_provider_class_init (GdaFirebirdProviderClass *klass);
+static void gda_firebird_provider_init       (GdaFirebirdProvider *provider,
+					      GdaFirebirdProviderClass *klass);
+static GObjectClass *parent_class = NULL;
+
+/*
+ * GdaServerProvider's virtual methods
+ */
+/* connection management */
+static gboolean            gda_firebird_provider_open_connection (GdaServerProvider *provider, GdaConnection *cnc,
+								  GdaQuarkList *params, GdaQuarkList *auth,
+								  guint *task_id, GdaServerProviderAsyncCallback async_cb, gpointer cb_data);
+static gboolean            gda_firebird_provider_close_connection (GdaServerProvider *provider, GdaConnection *cnc);
+static const gchar        *gda_firebird_provider_get_server_version (GdaServerProvider *provider, GdaConnection *cnc);
+static const gchar        *gda_firebird_provider_get_database (GdaServerProvider *provider, GdaConnection *cnc);
+
+/* DDL operations */
+static gboolean            gda_firebird_provider_supports_operation (GdaServerProvider *provider, GdaConnection *cnc,
+								     GdaServerOperationType type, GdaSet *options);
+static GdaServerOperation *gda_firebird_provider_create_operation (GdaServerProvider *provider, GdaConnection *cnc,
+								   GdaServerOperationType type,
+								   GdaSet *options, GError **error);
+static gchar              *gda_firebird_provider_render_operation (GdaServerProvider *provider, GdaConnection *cnc,
+								   GdaServerOperation *op, GError **error);
+
+static gboolean            gda_firebird_provider_perform_operation (GdaServerProvider *provider, GdaConnection *cnc,
+								    GdaServerOperation *op, guint *task_id, 
+								    GdaServerProviderAsyncCallback async_cb, gpointer cb_data,
+								    GError **error);
+/* transactions */
+static gboolean            gda_firebird_provider_begin_transaction (GdaServerProvider *provider, GdaConnection *cnc,
+								    const gchar *name, GdaTransactionIsolation level, GError **error);
+static gboolean            gda_firebird_provider_commit_transaction (GdaServerProvider *provider, GdaConnection *cnc,
+								     const gchar *name, GError **error);
+static gboolean            gda_firebird_provider_rollback_transaction (GdaServerProvider *provider, GdaConnection * cnc,
+								       const gchar *name, GError **error);
+static gboolean            gda_firebird_provider_add_savepoint (GdaServerProvider *provider, GdaConnection *cnc,
+								const gchar *name, GError **error);
+static gboolean            gda_firebird_provider_rollback_savepoint (GdaServerProvider *provider, GdaConnection *cnc,
+								     const gchar *name, GError **error);
+static gboolean            gda_firebird_provider_delete_savepoint (GdaServerProvider *provider, GdaConnection *cnc,
+								   const gchar *name, GError **error);
+
+/* information retreival */
+static const gchar        *gda_firebird_provider_get_version (GdaServerProvider *provider);
+static gboolean            gda_firebird_provider_supports_feature (GdaServerProvider *provider, GdaConnection *cnc,
+								   GdaConnectionFeature feature);
+
+static const gchar        *gda_firebird_provider_get_name (GdaServerProvider *provider);
+
+static GdaDataHandler     *gda_firebird_provider_get_data_handler (GdaServerProvider *provider, GdaConnection *cnc,
+								   GType g_type, const gchar *dbms_type);
+
+static const gchar*        gda_firebird_provider_get_default_dbms_type (GdaServerProvider *provider, GdaConnection *cnc,
+									GType type);
+/* statements */
+static GdaSqlParser        *gda_firebird_provider_create_parser (GdaServerProvider *provider, GdaConnection *cnc);
+static gchar               *gda_firebird_provider_statement_to_sql  (GdaServerProvider *provider, GdaConnection *cnc,
+								     GdaStatement *stmt, GdaSet *params, 
+								     GdaStatementSqlFlag flags,
+								     GSList **params_used, GError **error);
+static gboolean             gda_firebird_provider_statement_prepare (GdaServerProvider *provider, GdaConnection *cnc,
+								     GdaStatement *stmt, GError **error);
+static GObject             *gda_firebird_provider_statement_execute (GdaServerProvider *provider, GdaConnection *cnc,
+								     GdaStatement *stmt, GdaSet *params,
+								     GdaStatementModelUsage model_usage, 
+								     GType *col_types, GdaSet **last_inserted_row, 
+								     guint *task_id, GdaServerProviderAsyncCallback async_cb, 
+								     gpointer cb_data, GError **error);
+
+/* distributed transactions */
+static gboolean gda_firebird_provider_xa_start    (GdaServerProvider *provider, GdaConnection *cnc, 
+						   const GdaXaTransactionId *xid, GError **error);
+
+static gboolean gda_firebird_provider_xa_end      (GdaServerProvider *provider, GdaConnection *cnc, 
+						   const GdaXaTransactionId *xid, GError **error);
+static gboolean gda_firebird_provider_xa_prepare  (GdaServerProvider *provider, GdaConnection *cnc, 
+						   const GdaXaTransactionId *xid, GError **error);
+
+static gboolean gda_firebird_provider_xa_commit   (GdaServerProvider *provider, GdaConnection *cnc, 
+						   const GdaXaTransactionId *xid, GError **error);
+static gboolean gda_firebird_provider_xa_rollback (GdaServerProvider *provider, GdaConnection *cnc, 
+						   const GdaXaTransactionId *xid, GError **error);
 
-#include <libgda/handlers/gda-handler-numerical.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/handlers/gda-handler-bin.h>
-
-#include <libgda/sql-delimiter/gda-sql-delimiter.h>
-#include <libgda/gda-connection-private.h>
-#include <libgda/gda-blob-op.h>
-
-static void 		gda_firebird_provider_class_init (GdaFirebirdProviderClass *klass);
-static void 		gda_firebird_provider_init (GdaFirebirdProvider *provider,
-						    GdaFirebirdProviderClass *klass);
-static void 		gda_firebird_provider_finalize (GObject *object);
-
-static const gchar 	*gda_firebird_provider_get_version (GdaServerProvider *provider);
-static gboolean 	gda_firebird_provider_open_connection (GdaServerProvider *provider,
-							       GdaConnection *cnc,
-							       GdaQuarkList *params,
-							       const gchar *username,
-							       const gchar *password);
-static gboolean		gda_firebird_provider_close_connection (GdaServerProvider *provider,
-								GdaConnection *cnc);
-static const gchar	*gda_firebird_provider_get_server_version (GdaServerProvider *provider,
-								   GdaConnection *cnc);
-static const gchar 	*gda_firebird_provider_get_database (GdaServerProvider *provider,
-							     GdaConnection *cnc);
-static gboolean		gda_firebird_provider_change_database (GdaServerProvider *provider,
-							       GdaConnection *cnc,
-							       const gchar *name);
-static GList 		*gda_firebird_provider_execute_command (GdaServerProvider *provider,
-								GdaConnection *cnc,
-								GdaCommand *cmd,
-								GdaParameterList *params);
-static gboolean 	gda_firebird_provider_begin_transaction (GdaServerProvider *provider,
-								 GdaConnection *cnc,
-								 const gchar *name, GdaTransactionIsolation level,
-								 GError **error);
-static gboolean 	gda_firebird_provider_commit_transaction (GdaServerProvider *provider,
-								  GdaConnection *cnc,
-								  const gchar *name, GError **error);
-static gboolean 	gda_firebird_provider_rollback_transaction (GdaServerProvider *provider,
-								    GdaConnection *cnc,
-								    const gchar *name, GError **error);
-static gboolean 	gda_firebird_provider_supports (GdaServerProvider *provider,
-							GdaConnection *cnc,
-							GdaConnectionFeature feature);
-
-static GdaServerProviderInfo *gda_firebird_provider_get_info (GdaServerProvider *provider,
-							      GdaConnection *cnc);
-
-static GdaDataModel	*gda_firebird_provider_get_schema (GdaServerProvider *provider,
-							   GdaConnection *cnc,
-							   GdaConnectionSchema schema,
-							   GdaParameterList *params);
-
-static GdaDataHandler *gda_firebird_provider_get_data_handler (GdaServerProvider *provider,
-							       GdaConnection *cnc,
-							       GType g_type,
-							       const gchar *dbms_type);
-static const gchar* gda_firebird_provider_get_default_dbms_type (GdaServerProvider *provider,
-								 GdaConnection *cnc,
-								 GType type);
-
-static gboolean          begin_transaction_if_not_current (GdaServerProvider *provider,
-							   GdaConnection *cnc,
-							   const gchar *name, GdaTransactionIsolation level,
-							   GError **error, gboolean *has_error);
+static GList   *gda_firebird_provider_xa_recover  (GdaServerProvider *provider, GdaConnection *cnc, 
+						   GError **error);
 
+/* 
+ * private connection data destroy 
+ */
+static void gda_firebird_free_cnc_data (FirebirdConnectionData *cdata);
 
-static GObjectClass *parent_class = NULL;
 
-static const gchar *read_string_in_blob (const GValue *value);
+/*
+ * 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
+ */
+GdaStatement **internal_stmt;
 
+typedef enum {
+	INTERNAL_STMT1
+} InternalStatementItem;
+
+gchar *internal_sql[] = {
+	"SQL for INTERNAL_STMT1"
+};
 
 /*
  * GdaFirebirdProvider class implementation
@@ -114,59 +156,116 @@
 static void
 gda_firebird_provider_class_init (GdaFirebirdProviderClass *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_firebird_provider_finalize;
 	provider_class->get_version = gda_firebird_provider_get_version;
 	provider_class->get_server_version = gda_firebird_provider_get_server_version;
-	provider_class->get_info = gda_firebird_provider_get_info;
-	provider_class->supports_feature = gda_firebird_provider_supports;
-	provider_class->get_schema = gda_firebird_provider_get_schema;
+	provider_class->get_name = gda_firebird_provider_get_name;
+	provider_class->supports_feature = gda_firebird_provider_supports_feature;
 
 	provider_class->get_data_handler = gda_firebird_provider_get_data_handler;
-	provider_class->string_to_value = NULL;
 	provider_class->get_def_dbms_type = gda_firebird_provider_get_default_dbms_type;
 
-	provider_class->create_connection = NULL;
 	provider_class->open_connection = gda_firebird_provider_open_connection;
 	provider_class->close_connection = gda_firebird_provider_close_connection;
 	provider_class->get_database = gda_firebird_provider_get_database;
-	provider_class->change_database = gda_firebird_provider_change_database;
 
-	provider_class->supports_operation = NULL;
-        provider_class->create_operation = NULL;
-        provider_class->render_operation = NULL;
-        provider_class->perform_operation = NULL;
-
-	provider_class->execute_command = gda_firebird_provider_execute_command;
-	provider_class->execute_query = NULL;
-	provider_class->get_last_insert_id = NULL;
+	provider_class->supports_operation = gda_firebird_provider_supports_operation;
+        provider_class->create_operation = gda_firebird_provider_create_operation;
+        provider_class->render_operation = gda_firebird_provider_render_operation;
+        provider_class->perform_operation = gda_firebird_provider_perform_operation;
 
 	provider_class->begin_transaction = gda_firebird_provider_begin_transaction;
 	provider_class->commit_transaction = gda_firebird_provider_commit_transaction;
 	provider_class->rollback_transaction = gda_firebird_provider_rollback_transaction;
-	provider_class->add_savepoint = NULL;
-	provider_class->rollback_savepoint = NULL;
-	provider_class->delete_savepoint = NULL;
-}
+	provider_class->add_savepoint = NULL /*gda_firebird_provider_add_savepoint*/;
+        provider_class->rollback_savepoint = NULL /*gda_firebird_provider_rollback_savepoint*/;
+        provider_class->delete_savepoint = NULL /*gda_firebird_provider_delete_savepoint*/;
+
+	provider_class->create_parser = NULL /*gda_firebird_provider_create_parser*/;
+	provider_class->statement_to_sql = NULL /*gda_firebird_provider_statement_to_sql*/;
+	provider_class->statement_prepare = NULL /*gda_firebird_provider_statement_prepare*/;
+	provider_class->statement_execute = NULL /*gda_firebird_provider_statement_execute*/;
 
-static void
-gda_firebird_provider_init (GdaFirebirdProvider *provider, GdaFirebirdProviderClass *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_firebird_meta__info;
+	provider_class->meta_funcs._btypes = _gda_firebird_meta__btypes;
+	provider_class->meta_funcs._udt = _gda_firebird_meta__udt;
+	provider_class->meta_funcs.udt = _gda_firebird_meta_udt;
+	provider_class->meta_funcs._udt_cols = _gda_firebird_meta__udt_cols;
+	provider_class->meta_funcs.udt_cols = _gda_firebird_meta_udt_cols;
+	provider_class->meta_funcs._enums = _gda_firebird_meta__enums;
+	provider_class->meta_funcs.enums = _gda_firebird_meta_enums;
+	provider_class->meta_funcs._domains = _gda_firebird_meta__domains;
+	provider_class->meta_funcs.domains = _gda_firebird_meta_domains;
+	provider_class->meta_funcs._constraints_dom = _gda_firebird_meta__constraints_dom;
+	provider_class->meta_funcs.constraints_dom = _gda_firebird_meta_constraints_dom;
+	provider_class->meta_funcs._el_types = _gda_firebird_meta__el_types;
+	provider_class->meta_funcs.el_types = _gda_firebird_meta_el_types;
+	provider_class->meta_funcs._collations = _gda_firebird_meta__collations;
+	provider_class->meta_funcs.collations = _gda_firebird_meta_collations;
+	provider_class->meta_funcs._character_sets = _gda_firebird_meta__character_sets;
+	provider_class->meta_funcs.character_sets = _gda_firebird_meta_character_sets;
+	provider_class->meta_funcs._schemata = _gda_firebird_meta__schemata;
+	provider_class->meta_funcs.schemata = _gda_firebird_meta_schemata;
+	provider_class->meta_funcs._tables_views = _gda_firebird_meta__tables_views;
+	provider_class->meta_funcs.tables_views = _gda_firebird_meta_tables_views;
+	provider_class->meta_funcs._columns = _gda_firebird_meta__columns;
+	provider_class->meta_funcs.columns = _gda_firebird_meta_columns;
+	provider_class->meta_funcs._view_cols = _gda_firebird_meta__view_cols;
+	provider_class->meta_funcs.view_cols = _gda_firebird_meta_view_cols;
+	provider_class->meta_funcs._constraints_tab = _gda_firebird_meta__constraints_tab;
+	provider_class->meta_funcs.constraints_tab = _gda_firebird_meta_constraints_tab;
+	provider_class->meta_funcs._constraints_ref = _gda_firebird_meta__constraints_ref;
+	provider_class->meta_funcs.constraints_ref = _gda_firebird_meta_constraints_ref;
+	provider_class->meta_funcs._key_columns = _gda_firebird_meta__key_columns;
+	provider_class->meta_funcs.key_columns = _gda_firebird_meta_key_columns;
+	provider_class->meta_funcs._check_columns = _gda_firebird_meta__check_columns;
+	provider_class->meta_funcs.check_columns = _gda_firebird_meta_check_columns;
+	provider_class->meta_funcs._triggers = _gda_firebird_meta__triggers;
+	provider_class->meta_funcs.triggers = _gda_firebird_meta_triggers;
+	provider_class->meta_funcs._routines = _gda_firebird_meta__routines;
+	provider_class->meta_funcs.routines = _gda_firebird_meta_routines;
+	provider_class->meta_funcs._routine_col = _gda_firebird_meta__routine_col;
+	provider_class->meta_funcs.routine_col = _gda_firebird_meta_routine_col;
+	provider_class->meta_funcs._routine_par = _gda_firebird_meta__routine_par;
+	provider_class->meta_funcs.routine_par = _gda_firebird_meta_routine_par;
+
+	/* distributed transactions: if not supported, then provider_class->xa_funcs should be set to NULL */
+	provider_class->xa_funcs = NULL;
+	/*
+	provider_class->xa_funcs = g_new0 (GdaServerProviderXa, 1);
+	provider_class->xa_funcs->xa_start = gda_firebird_provider_xa_start;
+	provider_class->xa_funcs->xa_end = gda_firebird_provider_xa_end;
+	provider_class->xa_funcs->xa_prepare = gda_firebird_provider_xa_prepare;
+	provider_class->xa_funcs->xa_commit = gda_firebird_provider_xa_commit;
+	provider_class->xa_funcs->xa_rollback = gda_firebird_provider_xa_rollback;
+	provider_class->xa_funcs->xa_recover = gda_firebird_provider_xa_recover;
+	*/
 }
 
 static void
-gda_firebird_provider_finalize (GObject *object)
+gda_firebird_provider_init (GdaFirebirdProvider *firebird_prv, GdaFirebirdProviderClass *klass)
 {
-	GdaFirebirdProvider *fbprv = (GdaFirebirdProvider *) object;
+	InternalStatementItem i;
+	GdaSqlParser *parser;
 
-	g_return_if_fail (GDA_IS_FIREBIRD_PROVIDER (fbprv));
+	parser = gda_server_provider_internal_get_parser ((GdaServerProvider*) firebird_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]);
+	}
 
-	/* chain to parent class */
-	parent_class->finalize (object);
+	/* meta data init */
+	_gda_firebird_provider_meta_init ((GdaServerProvider*) firebird_prv);
 }
 
 GType
@@ -180,1532 +279,1014 @@
 			(GBaseInitFunc) NULL,
 			(GBaseFinalizeFunc) NULL,
 			(GClassInitFunc) gda_firebird_provider_class_init,
-			NULL,
-			NULL,
+			NULL, NULL,
 			sizeof (GdaFirebirdProvider),
 			0,
 			(GInstanceInitFunc) gda_firebird_provider_init
 		};
-		type = g_type_register_static (PARENT_TYPE, "GdaFirebirdProvider", &info, 0);
+		type = g_type_register_static (GDA_TYPE_SERVER_PROVIDER, "GdaFirebirdProvider",
+					       &info, 0);
 	}
 
 	return type;
 }
 
-GdaServerProvider *
-gda_firebird_provider_new (void)
+
+/*
+ * Get provider name request
+ */
+static const gchar *
+gda_firebird_provider_get_name (GdaServerProvider *provider)
 {
-	GdaFirebirdProvider *fprv;
-	
-	fprv = g_object_new (GDA_TYPE_FIREBIRD_PROVIDER, NULL);
-	
-	return GDA_SERVER_PROVIDER (fprv);
+	return FIREBIRD_PROVIDER_NAME;
 }
 
+/* 
+ * Get provider's version, no need to change this
+ */
+static const gchar *
+gda_firebird_provider_get_version (GdaServerProvider *provider)
+{
+	return PACKAGE_VERSION;
+}
 
-/*
- *  fb_server_get_version
+/* 
+ * Open connection request
  *
- *  Gets Firebird connection's server version number
+ * 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 FirebirdConnectionData structure and associate it to @cnc
  *
- *  Returns: A string containing server version, or NULL if error
- *           String must be released after use
+ * Returns: TRUE if no error occurred, or FALSE otherwise (and an ERROR gonnection event must be added to @cnc)
  */
-static gchar *
-fb_server_get_version (GdaFirebirdConnection *fcnc)
+static gboolean
+gda_firebird_provider_open_connection (GdaServerProvider *provider, GdaConnection *cnc,
+				       GdaQuarkList *params, GdaQuarkList *auth,
+				       guint *task_id, GdaServerProviderAsyncCallback async_cb, gpointer cb_data)
 {
-	gchar buffer[254], item, *p_buffer;
-	gint length;
-	gchar fdb_info[] = {
-		isc_info_isc_version,
-		isc_info_end
-	};
-	
-	/* Try to get datbase version */
-	if (! isc_database_info (fcnc->status, &(fcnc->handle), sizeof (fdb_info), fdb_info,
-				 sizeof (buffer), buffer)) {
-		p_buffer = buffer;
-		if (*p_buffer != isc_info_end) {
-			item = *p_buffer++;
-			length = isc_vax_integer (p_buffer, 2);
-			p_buffer += 2;
-			if (item == isc_info_isc_version)
-				return g_strndup ((guchar *) &p_buffer[2], length-2);
-				
-		}		
-	}
-
-	return NULL;
-}
+	g_return_val_if_fail (GDA_IS_FIREBIRD_PROVIDER (provider), FALSE);
+	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), 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;
+	}
 
-/*
- *  fb_get_types
- *
- *  Returns: A GdaDataModel containing Firebird's data types
- */
-static GdaDataModel *
-fb_get_types (GdaConnection *cnc,
-	      GdaParameterList *params)
-{
-	GdaDataModelArray *recset;
-	GList *value_list;
-	gint i;
-	struct {
-		const gchar *name;
-		const gchar *owner;
-		const gchar *comments;
-		GType type;
-		const gchar *syns;
-	} types[] = {
-		{ "blob", "", "Binary large object (blob)", GDA_TYPE_BLOB, NULL },
-		{ "char", "", "Fixed length string", G_TYPE_STRING, "character" },
-		{ "varchar", "", "Variable length string", G_TYPE_STRING, "character varying,varying,char varying" },
-		{ "text", "", "Text", G_TYPE_STRING, NULL },
-		{ "date", "", "Date", G_TYPE_DATE, NULL },
-		{ "time", "", "Time", GDA_TYPE_TIME, NULL },
-		{ "timestamp", "", "Time stamp", GDA_TYPE_TIMESTAMP, NULL },
-		{ "smallint", "", "Signed short integer", GDA_TYPE_SHORT, "short" },
-		{ "integer", "", "Signed long integer", G_TYPE_INT, "long" },
-		{ "int64", "", "Signed integer (8 bytes)", G_TYPE_INT64, NULL },
-		{ "decimal", "", "Decimal number", GDA_TYPE_NUMERIC, NULL },
-		{ "numeric", "", "Decimal number", GDA_TYPE_NUMERIC, NULL },
-		{ "float", "", "Single precision number", G_TYPE_FLOAT, NULL },
-		{ "double", "", "Double precision number", G_TYPE_DOUBLE, "double precision" }
-	};
+	/* Check for connection parameters */
+	const gchar *fb_db, *fb_user, *fb_password, *fb_charset;
+	fb_db = (gchar *) gda_quark_list_find (params, "DB_NAME");
+        if (!fb_db) {
+                gda_connection_add_event_string (cnc, 
+						 _("The connection string must contain the DB_NAME values"));
+                return FALSE;
+        }
+        fb_charset = (gchar *) gda_quark_list_find (params, "CHARACTER_SET");
 
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-	
-	/* create the recordset */
-	recset = (GdaDataModelArray *) 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);
+	fb_user = (gchar *) gda_quark_list_find (auth, "USERNAME");
+	fb_password = (gchar *) gda_quark_list_find (auth, "PASSWORD");
 	
-	/* Fill the recordset with each of the values from the array defined above */
-	for (i = 0; i < (sizeof (types) / sizeof (types[0])); i++) {
-		value_list = NULL;
-		GValue *tmpval;
-		
-		g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), types[i].name);
-		value_list = g_list_append (value_list, tmpval);
+	/* Create a new instance of the provider specific data associated to a connection (FirebirdConnectionData),
+	 * and set its contents, and open the real connection to the database */
+	FirebirdConnectionData *cdata;
+        gchar *dpb;
 
-		g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), types[i].owner);
-		value_list = g_list_append (value_list, tmpval);
+	cdata = g_new0 (FirebirdConnectionData, 1);
 
-		g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), types[i].comments);
-		value_list = g_list_append (value_list, tmpval);
+	/* Initialize dpb_buffer */
+        dpb = fcnc->dpb_buffer;
+        *dpb++ = isc_dpb_version1;
 
-		g_value_set_ulong (tmpval = gda_value_new (G_TYPE_ULONG), types[i].type);
-		value_list = g_list_append (value_list, tmpval);
+        /* Set user name */
+        if (fb_user) {
+                *dpb++ = isc_dpb_user_name;
+                *dpb++ = strlen (fb_user);
+                strcpy (dpb, fb_user);
+                dpb += strlen (fb_user);
+        }
 
-		g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), types[i].syns);
-		value_list = g_list_append (value_list, tmpval);
+        /* Set password */
+        if (fb_password) {
+                *dpb++ = isc_dpb_password;
+                *dpb++ = strlen (fb_password);
+                strcpy (dpb, fb_password);
+                dpb += strlen (fb_password);
+        }
 
-		/* Add values to row */
-		gda_data_model_append_values (GDA_DATA_MODEL (recset), value_list, NULL);
+        /* Set character set */
+        if (fb_charset) {
+                *dpb++ = isc_dpb_lc_ctype;
+                *dpb++ = strlen (fb_charset);
+                strcpy (dpb, fb_charset);
+                dpb += strlen (fb_charset);
+        }
+
+        /* Save dpb length */
+        fcnc->dpb_length = dpb - fcnc->dpb_buffer;
 
-		/* Free temporary list of values */
-		g_list_foreach (value_list, (GFunc) gda_value_free, NULL);
-		g_list_free (value_list);
+	if (isc_attach_database (fcnc->status, strlen (fb_db), fb_db, &(fcnc->handle), fcnc->dpb_length,
+                                 fcnc->dpb_buffer)) {
+		gda_firebird_free_cnc_data (fcnc);
+		
+		return FALSE;
 	}
-	
-	return GDA_DATA_MODEL (recset);
-}
 
+	/* connection is now opened */
+	gda_connection_internal_set_provider_data (cnc, cdata, (GDestroyNotify) gda_firebird_free_cnc_data);
+	 
+        fcnc->dbname = g_strdup (fb_db);
+        fcnc->server_version = fb_server_get_version (fcnc);
 
-/*
- *  fb_get_tables
- *
- *  @show_views: If TRUE only return views, else return tables
+	return TRUE;
+}
+
+/* 
+ * Close connection request
  *
- *  Function looks for the following parameters in list:
- *    systables (gboolean)
+ * In this function, the following _must_ be done:
+ *   - Actually close the connection to the database using @cnc's associated FirebirdConnectionData structure
+ *   - Free the FirebirdConnectionData structure and its contents
  *
- *  Returns: A GdaDataModel containing Firebird's tables/views
+ * Returns: TRUE if no error occurred, or FALSE otherwise (and an ERROR gonnection event must be added to @cnc)
  */
-static GdaDataModel *
-fb_get_tables (GdaConnection *cnc,
-	       GdaParameterList *params,
-	       gboolean show_views)
+static gboolean
+gda_firebird_provider_close_connection (GdaServerProvider *provider, GdaConnection *cnc)
 {
-	GList *value_list;
-	GdaDataModel *recset = NULL;
-	GdaCommand *command;
-	const GValue *value;
-	GdaParameter *par = NULL;
-	gchar *sql, *sql_cond;
-	gint i;
-	gboolean systables = FALSE;
-	gboolean trans_started, trans_error;
+	FirebirdConnectionData *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_obj (cnc) == provider, FALSE);
 
-	/* Begin transaction if it was not already started  */
-	trans_started = begin_transaction_if_not_current (gda_connection_get_provider_obj (cnc), cnc, "temp_transaction", 
-							  GDA_TRANSACTION_ISOLATION_UNKNOWN, NULL, &trans_error);
+	/* Close the connection using the C API */
+	cdata = (FirebirdConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
+		return FALSE;
 
-	if (!trans_error) {
-		GdaDataModel *recmodel;
-		
-		/* Find parameters */
-		if (params)
-			par = gda_parameter_list_find_param (params, "systables");
-
-		/* Initialize parameter values */
-		if (par)
-			systables = g_value_get_boolean ((GValue *) gda_parameter_get_value (par));
-	
-		/* Evaluate statement conditions */	
-		if (show_views) {
-			/* Show only views */
-			sql_cond = "WHERE RDB$SYSTEM_FLAG = 0 AND RDB$VIEW_BLR IS NOT NULL";
-		}
-		else {
-			if (systables)
-				/* Only show system tables */
-				sql_cond = "WHERE RDB$SYSTEM_FLAG = 1 AND RDB$VIEW_BLR IS NULL";
-			else
-				/* Only show user tables */
-				sql_cond = "WHERE RDB$SYSTEM_FLAG = 0 AND RDB$VIEW_BLR IS NULL";
-		}
-	
-		/* Generate complete statement */
-		sql = g_strconcat ("SELECT RDB$RELATION_NAME, RDB$OWNER_NAME, RDB$VIEW_SOURCE "
-				   "FROM RDB$RELATIONS ", 
-				   sql_cond, NULL);
-		
-		/* Execute statement */
-		command = gda_command_new (sql, GDA_COMMAND_TYPE_SQL, GDA_COMMAND_OPTION_STOP_ON_ERRORS);
-		recmodel = gda_connection_execute_select_command (cnc, command, NULL, NULL);
-		if (recmodel) {
-			recset = (GdaDataModel *) gda_data_model_array_new 
-				(gda_server_provider_get_schema_nb_columns (GDA_CONNECTION_SCHEMA_TABLES));
-			gda_server_provider_init_schema_model (recset, GDA_CONNECTION_SCHEMA_TABLES);
-			for (i = 0; i < gda_data_model_get_n_rows (recmodel); i++) {
-				GValue *tmpval;
-
-				/* Get name of table */
-				value = gda_data_model_get_value_at (recmodel, 0, i);
-				value_list = g_list_append (NULL, gda_value_copy (value));
-
-				/* Get owner of table */
-				value = gda_data_model_get_value_at (recmodel, 1, i);
-				value_list = g_list_append (value_list, gda_value_copy (value));
-				
-				/* Comments FIXME */
-				g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), "");
-				value_list = g_list_append (value_list, tmpval);
-
-				/* description */
-				value = gda_data_model_get_value_at (recmodel, 2, i);
-				const gchar *cstr;
-				cstr = read_string_in_blob (value);
-				if (cstr)
-					g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), cstr);
-				else
-					g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), "");
-				value_list = g_list_append (value_list, tmpval);
-
-				gda_data_model_append_values (recset, value_list, NULL);
-				g_list_foreach (value_list, (GFunc) gda_value_free, NULL);
-				g_list_free (value_list);
-			}
+	/* detach from database */
+        isc_detach_database (fcnc->status, &(fcnc->handle));
 
-			g_object_unref (recmodel);
-		}
+	/* Free the FirebirdConnectionData structure and its contents*/
+	gda_firebird_free_cnc_data (cdata);
+	gda_connection_internal_set_provider_data (cnc, NULL, NULL);
 
-		g_free (sql);
-		if (trans_started)
-			gda_connection_rollback_transaction (cnc, "temp_transaction", NULL);
-		gda_command_free (command);
-	}
-	
-	return recset;
+	return TRUE;
 }
 
-
 /*
- *  fb_type_name_to_g_type
- *
- *  Function convert a string containing the name of Firebird's
- *  data type to it's corresponding gda data type.
+ * Server version request
  *
- *  Returns: The GType corresponding to @name Firebird's
- *           type
+ * Returns the server version as a string, which should be stored in @cnc's associated FirebirdConnectionData structure
  */
-static GType
-fb_type_name_to_g_type (const gchar *name)
+static const gchar *
+gda_firebird_provider_get_server_version (GdaServerProvider *provider, GdaConnection *cnc)
 {
-	if (!strcmp (name, "CHAR") || !strcmp (name, "VARCHAR"))
-		return G_TYPE_STRING;
-	else if (!strcmp (name, "SMALLINT"))
-		return GDA_TYPE_SHORT;
-	else if (!strcmp (name, "NUMERIC") || !strcmp (name, "DECIMAL"))
-		return GDA_TYPE_NUMERIC;
-	else if (!strcmp (name, "INTEGER"))
-		return G_TYPE_INT;
-	else if (!strcmp (name, "BLOB"))
-		return GDA_TYPE_BLOB;
-	else if (!strcmp (name, "TIMESTAMP"))
-		return GDA_TYPE_TIMESTAMP;
-	else if (!strcmp (name, "TIME"))
-		return GDA_TYPE_TIME;
-	else if (!strcmp (name, "DATE"))
-		return G_TYPE_DATE;
-	else if (!strcmp (name, "INT64"))
-		return GDA_TYPE_NUMERIC;
-	else if (!strcmp (name, "FLOAT"))
-		return G_TYPE_FLOAT;
-	else if (!strcmp (name, "DOUBLE"))
-		return G_TYPE_DOUBLE;
+	FirebirdConnectionData *cdata;
 
-	return G_TYPE_STRING;
-}
+	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+	g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, NULL);
 
+	cdata = (FirebirdConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
+		return FALSE;
+
+	return ((const gchar *) cdata->server_version);
+}
 
 /*
- *  fb_set_index_field_metadata
+ * Get database request
  *
- *  Sets primary key and unique key properties for fields
- *  in @recset.
- *  This function is called from #fb_get_fields_metadata.
+ * Returns the server version as a string, which should be stored in @cnc's associated FirebirdConnectionData structure
  */
-static void
-fb_set_index_field_metadata (GdaConnection *cnc,
-			     GdaDataModel *recset,
-			     const gchar *table_name)
-{
-	GdaCommand *command;
-	gchar *sql, *field_name, *recset_field_name;
-	gint i,j;
-	GValue *value, *recset_value;
-	gboolean trans_started, trans_error;
-	
-	g_return_if_fail (GDA_IS_CONNECTION (cnc));
-	g_return_if_fail (GDA_IS_DATA_MODEL (recset));
-
-	trans_started = begin_transaction_if_not_current (gda_connection_get_provider_obj (cnc), cnc, "tmp_transaction_mdata", 
-							  GDA_TRANSACTION_ISOLATION_UNKNOWN, NULL, &trans_error);
-
-	if (!trans_error) {
-		GdaDataModel *recmodel;
-		sql = g_strdup_printf (
-				"SELECT A.RDB$FIELD_NAME, I.RDB$UNIQUE_FLAG, B.RDB$CONSTRAINT_TYPE "
-				"FROM RDB$INDEX_SEGMENTS A, RDB$RELATION_CONSTRAINTS B, RDB$INDICES I "
-				"WHERE ((B.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY') "
-				"OR (I.RDB$UNIQUE_FLAG = 1)) AND (A.RDB$INDEX_NAME = B.RDB$INDEX_NAME) "
-				"AND (B.RDB$RELATION_NAME = '%s') AND (A.RDB$INDEX_NAME = I.RDB$INDEX_NAME) "
-				"ORDER BY A.RDB$FIELD_POSITION",
-				table_name);
-		command = gda_command_new (sql, GDA_COMMAND_TYPE_SQL, GDA_COMMAND_OPTION_STOP_ON_ERRORS);
-		recmodel = gda_connection_execute_select_command (cnc, command, NULL, NULL);
-		if (recmodel) {
-			gda_data_model_freeze (recset);
-			
-			/* For each index or unique field in statement */
-			for (i = 0; i < gda_data_model_get_n_rows (recmodel); i++) {
-				value = (GValue *) gda_data_model_get_value_at (recmodel, 0, i);
-				field_name = (gchar *) g_value_get_string (value);
-				j = -1;
-
-				/* Find column in @recset by name */
-				do {
-					j++;
-					recset_value = (GValue *) gda_data_model_get_value_at (recset, 0, j);
-					recset_field_name = (gchar *) g_value_get_string (recset_value);
-				} while (strcmp (recset_field_name, field_name) && 
-					 (j < gda_data_model_get_n_rows (recset)));
-				
-				/* Set recset values */
-				if (!strcmp (recset_field_name, field_name)) {
-					
-					/* Get primary key value from statement */
-					value = (GValue *) gda_data_model_get_value_at (recmodel,
-											  2,
-											  i);
-					
-					/* Get recorset GValue for primary key (position 5) */
-					recset_value = (GValue *) gda_data_model_get_value_at (recset, 5, j);
-
-					/* Set Primary Key mark */
-					g_value_set_boolean (recset_value, (!strcmp (
-										g_value_get_string (value),
-										"PRIMARY KEY")));
-					
-					/* Get unique index value from statement */
-					value = (GValue *) gda_data_model_get_value_at (recmodel,
-											  1,
-											  i);
-					
-					/* Get recorset GValue for unique index (position 6) */
-					recset_value = (GValue *) gda_data_model_get_value_at (recset, 6, j);
-
-					/* Set Unique Index mark */
-					g_value_set_boolean (recset_value, (gda_value_get_short (value) == 1));
-				}
-			}
-			
-			gda_data_model_thaw (recset);
-			g_object_unref (recmodel);
-		}
-		
-		g_free (sql);
-		if (trans_started)
-			gda_connection_rollback_transaction (cnc, "tmp_transaction_mdata", NULL);
-		gda_command_free (command);
-	}
-}
-
 static const gchar *
-read_string_in_blob (const GValue *value)
-{
-	gchar *str = NULL;
-	
-	if (!gda_value_is_null (value)) {
-		GdaBlob *blob;
-		blob = (GdaBlob*) gda_value_get_blob (value);
-		if (!blob)
-			g_warning ("Blob created by Firebird provider without a GdaBlob!");
-		else if (! blob->op)
-			g_warning ("Blob created by Firebird provider without a GdaBlobOp!");
-		else {
-			if (gda_blob_op_read_all (blob->op, blob)) 
-				str = (gchar *) ((GdaBinary *)blob)->data;
-			else
-				g_warning ("Can't read BLOB contents");
-		}
-	}
-	return str;
-}
-
-static GdaDataModel *
-fb_get_field_dimensions (GdaConnection *cnc, const gchar *field_name)
+gda_firebird_provider_get_database (GdaServerProvider *provider, GdaConnection *cnc)
 {
-	gboolean trans_started, trans_error;
-	GdaDataModel *model = NULL;
+	FirebirdConnectionData *cdata;
 
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-	g_return_val_if_fail (field_name, NULL);
-	
-	/* Begin transaction if it was not already started  */
-	trans_started = begin_transaction_if_not_current (gda_connection_get_provider_obj (cnc), cnc, "temp_transaction", 
-							  GDA_TRANSACTION_ISOLATION_UNKNOWN, NULL, &trans_error);
+	g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, NULL);
 
-	if (!trans_error) {
-		gchar *sql;
-		GdaCommand *command;
-		sql = g_strdup_printf (
-				"SELECT RDB$DIMENSION, RDB$LOWER_BOUND, RDB$UPPER_BOUND "
-				"FROM RDB$FIELD_DIMENSIONS WHERE RDB$FIELD_NAME='%s' ORDER BY RDB$DIMENSION",
-				field_name);
-		command = gda_command_new (sql, GDA_COMMAND_TYPE_SQL, GDA_COMMAND_OPTION_STOP_ON_ERRORS);
-		model = gda_connection_execute_select_command (cnc, command, NULL, NULL);
-		g_free (sql);
-		if (trans_started)
-			gda_connection_rollback_transaction (cnc, "temp_transaction", NULL);
-		gda_command_free (command);						
-	}
+	cdata = (FirebirdConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
+		return NULL;
 
-	return model;
+	return (const gchar *) cdata->dbname;
 }
 
 /*
- *  fb_set_field_metadata
+ * Support operation request
  *
- *  Fill a list with metadata values from @row.
- *  This function is called from #fb_get_fields_metadata.
+ * Tells what the implemented server operations are. To add support for an operation, the following steps are required:
+ *   - create a firebird_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_firebird_provider_render_operation() and gda_firebird_provider_perform_operation() methods
  *
- *  Returns: A GList of GValues
  */
-static GList *
-fb_set_field_metadata (GdaConnection *cnc, GdaDataModel *model, gint row)
+static gboolean
+gda_firebird_provider_supports_operation (GdaServerProvider *provider, GdaConnection *cnc,
+					  GdaServerOperationType type, GdaSet *options)
 {
-	GList *value_list = NULL;
-	const GValue *value;
-	GType field_gtype;
-	gshort scale, short_value;
-	GValue *tmpval;
-	const gchar *str;
-
-	/* Set field name  */
-	value = gda_data_model_get_value_at (model, 0, row);
-	value_list = g_list_append (value_list,	gda_value_copy (value));
-		
-	/* Set data type */
-	value = gda_data_model_get_value_at (model, 7, row);
-	tmpval = NULL;
-	if (!gda_value_is_null (value)) {
-		const GValue *value_type;
-
-		value_type = gda_data_model_get_value_at (model, 6, row);
-		if ((g_value_get_int (value_type) != 261) && (g_value_get_int (value_type) != 14)) { 
-			/* Not for BLOB or Char types */
-			if (g_value_get_int (value) == 1) {
-				g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), "numeric");
-				field_gtype = GDA_TYPE_NUMERIC;
-			}
-			else if (g_value_get_int (value) == 2) {
-				g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), "decimal");
-				field_gtype = GDA_TYPE_NUMERIC;
-			}
-		}
+	if (cnc) {
+		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+		g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, FALSE);
 	}
-	if (!tmpval) {
-		gchar *the_value;
-		value = gda_data_model_get_value_at (model, 1, row);
-		the_value = g_ascii_strdown (g_value_get_string (value), -1);
-		g_value_take_string (tmpval = gda_value_new (G_TYPE_STRING), g_strchomp (the_value));
-		field_gtype = fb_type_name_to_g_type (the_value);
-	}
-	value_list = g_list_append (value_list, tmpval);
-
-	/* Set size */
-	short_value = 0;
-	if (field_gtype == G_TYPE_STRING) {
-		value = gda_data_model_get_value_at (model, 2, row);
-		short_value = gda_value_get_short (value);
-	}
-	else if (field_gtype == GDA_TYPE_NUMERIC) {
-		value = gda_data_model_get_value_at (model, 3, row);
-		short_value = gda_value_get_short (value);
-	}
-	g_value_set_int (tmpval = gda_value_new (G_TYPE_INT), short_value);
-	value_list = g_list_append (value_list, tmpval);
-
-	/* Set scale (number of decimals) */
-	value = gda_data_model_get_value_at (model, 4, row);
-	if (!gda_value_is_null (value))
-		scale = gda_value_get_short (value);
-	else
-		scale = 0;
-	g_value_set_int (tmpval = gda_value_new (G_TYPE_INT), scale * -1);
-	value_list = g_list_append (value_list, tmpval);
-
-	/* Set not null indicator */
-	value = gda_data_model_get_value_at (model, 5, row);
-	if (!gda_value_is_null (value))
-		g_value_set_boolean (tmpval = gda_value_new (G_TYPE_BOOLEAN), (gda_value_get_short (value) == 1));
-	else
-		g_value_set_boolean (tmpval = gda_value_new (G_TYPE_BOOLEAN), FALSE);
-	value_list = g_list_append (value_list, tmpval);
 
-	/* Primary key ? (real value set in #fb_set_index_field_metadata) */
-	g_value_set_boolean (tmpval = gda_value_new (G_TYPE_BOOLEAN), FALSE);
-	value_list = g_list_append (value_list, tmpval);
-
-	/* Unique key ? (real value set in #fb_set_index_field_metadata) */
-	g_value_set_boolean (tmpval = gda_value_new (G_TYPE_BOOLEAN), FALSE);
-	value_list = g_list_append (value_list, tmpval);
-
-	/* FIXME: References */
-	tmpval = gda_value_new_null ();
-	value_list = g_list_append (value_list, tmpval);
-
-	/* Default value */
-	tmpval = NULL;
-	value = gda_data_model_get_value_at (model, 8, row);
-	str = read_string_in_blob (value);
-	if (str) {
-		if (!strncmp (str, "DEFAULT ", 8))
-			g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), str + 8);
-		else
-			g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), str);
-	}
-	if (!tmpval) {
-		value = gda_data_model_get_value_at (model, 9, row);
-		str = read_string_in_blob (value);
-		if (str) {
-			if (!strncmp (str, "DEFAULT ", 8))
-				g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), str + 8);
-			else
-				g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), str);
-		}
-	}
-	if (!tmpval) 
-		tmpval = gda_value_new_null ();
-	value_list = g_list_append (value_list, tmpval);
-
-	/* extra attributes FIXME: association GENERATOR <-> field name done through triggers :( */
-	tmpval = NULL;
-	value = gda_data_model_get_value_at (model, 10, row);
-	if (!gda_value_is_null (value) && (g_value_get_int (value) > 0)) {
-		/* here is an array */
-		GString *string = NULL;
-
-		tmpval = (GValue*) gda_data_model_get_value_at (model, 11, row);
-		if (gda_value_is_null (tmpval))
-			g_warning ("Firebird provider unexpected NULL RDB$FIELD_NAME");
-		else {
-			GdaDataModel *dims;
-			gint i, nrows;
-
-			string = g_string_new ("");
-			dims = fb_get_field_dimensions (cnc, g_value_get_string (tmpval));
-			nrows = gda_data_model_get_n_rows (dims);
-			for (i = 0; i < nrows; i++) {
-				if (i > 0)
-					g_string_append_c (string, ',');
-				value = gda_data_model_get_value_at (dims, 1, i);
-				if (!gda_value_is_null (value) && (g_value_get_long (value) > 1))
-					g_string_append_printf (string, "%ld:", g_value_get_long (value));
-				value = gda_data_model_get_value_at (dims, 2, i);
-				if (!gda_value_is_null (value))
-					g_string_append_printf (string, "%ld", g_value_get_long (value));
-			}
-			g_object_unref (dims);
-		}
-		if (string) {
-			tmpval = gda_value_new (G_TYPE_STRING);
-			gchar *str = g_strdup_printf ("ARRAY [%s]", string->str);
-			g_value_take_string (tmpval, str);
-			g_string_free (string, TRUE);
-		}
-		else
-			tmpval = NULL;
-	}
-	if (!tmpval)
-		tmpval = gda_value_new_null ();
-	value_list = g_list_append (value_list, tmpval);
+	return FALSE;
+
+        switch (type) {
+        case GDA_SERVER_OPERATION_CREATE_DB:
+        case GDA_SERVER_OPERATION_DROP_DB:
+		return FALSE;
 
-	return value_list;
+        case GDA_SERVER_OPERATION_CREATE_TABLE:
+		return TRUE;
+        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;
+        }
 }
 
 /*
- *  fb_get_fields_metadata
- *
- *  @params must contain a parameter named "name" with
- *  name of table to describe. ... :-)
+ * Create operation request
  *
- *  Returns: A GdaDataModel containing table metad
+ * 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 GdaDataModel *
-fb_get_fields_metadata (GdaConnection *cnc,
-			GdaParameterList *params)
-{
-	GList *value_list;
-	GdaDataModelArray *recset = NULL;
-	GdaParameter *par;
-	GdaCommand *command;
-	gint i;
-	gchar *sql;
-	const gchar *table_name;
-	gboolean trans_started, trans_error;
-
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-	g_return_val_if_fail (params != NULL, NULL);
-	
-	par = gda_parameter_list_find_param (params, "name");
-	if (!par) {
-		gda_connection_add_event_string (cnc,
-				_("Table name is needed but none specified in parameter list"));
-		return NULL;
-	}
+static GdaServerOperation *
+gda_firebird_provider_create_operation (GdaServerProvider *provider, GdaConnection *cnc,
+					GdaServerOperationType type, GdaSet *options, GError **error)
+{
+        gchar *file;
+        GdaServerOperation *op;
+        gchar *str;
+	gchar *dir;
+
+	if (cnc) {
+		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+		g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, FALSE);
+	}
+
+        file = g_utf8_strdown (gda_server_operation_op_type_to_string (type), -1);
+        str = g_strdup_printf ("firebird_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);
+	g_free (dir);
+        g_free (str);
+
+        if (! file) {
+                g_set_error (error, 0, 0, _("Missing spec. file '%s'"), file);
+                return NULL;
+        }
 
-	table_name = g_value_get_string ((GValue *) gda_parameter_get_value (par));
-	if (!table_name) {
-		gda_connection_add_event_string (cnc,
-				_("Table name is needed but none specified in parameter list"));
-		return NULL;
-	}
-	
-	/* Begin transaction if it was not already started  */
-	trans_started = begin_transaction_if_not_current (gda_connection_get_provider_obj (cnc), cnc, "temp_transaction", 
-							  GDA_TRANSACTION_ISOLATION_UNKNOWN, NULL, &trans_error);
-
-	if (!trans_error) {
-		GdaDataModel *recmodel;
-		sql = g_strdup_printf (
-				"SELECT A.RDB$FIELD_NAME, C.RDB$TYPE_NAME, B.RDB$FIELD_LENGTH, "
-				"B.RDB$FIELD_PRECISION, B.RDB$FIELD_SCALE, A.RDB$NULL_FLAG, "
-				"B.RDB$FIELD_TYPE, B.RDB$FIELD_SUB_TYPE, A.RDB$DEFAULT_SOURCE, B.RDB$DEFAULT_SOURCE, "
-				"B.RDB$DIMENSIONS, B.RDB$FIELD_NAME "
-				"FROM RDB$RELATION_FIELDS A, RDB$FIELDS B, RDB$TYPES C "
-				"WHERE (A.RDB$RELATION_NAME = '%s') AND (A.RDB$FIELD_SOURCE = B.RDB$FIELD_NAME)"
-				" AND (C.RDB$FIELD_NAME = 'RDB$FIELD_TYPE') AND (C.RDB$TYPE = B.RDB$FIELD_TYPE)"
-				" ORDER BY A.RDB$FIELD_POSITION",
-				table_name);
-		command = gda_command_new (sql, GDA_COMMAND_TYPE_SQL, GDA_COMMAND_OPTION_STOP_ON_ERRORS);
-		recmodel = gda_connection_execute_select_command (cnc, command, NULL, NULL);
-		if (recmodel) {
-			/* Create and fill recordset to be returned */
-			recset = (GdaDataModelArray *) 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);
-			
-			gint nrows;
-			nrows = gda_data_model_get_n_rows (recmodel);
-			for (i = 0; i < nrows; i++) {
-				/* Set field metdata for row, and append to recordset */
-				value_list = fb_set_field_metadata (cnc, recmodel, i);
-				GError *er = NULL;
-				if (gda_data_model_append_values (GDA_DATA_MODEL (recset), value_list, &er) < 0)
-					g_print ("==ERR: %s\n", er->message);
-				
-				/* Free temp list of values */
-				g_list_foreach (value_list, (GFunc) gda_value_free, NULL);
-				g_list_free (value_list);
-			}
-			
-			fb_set_index_field_metadata (cnc, (GdaDataModel *) recset, table_name);
-			g_object_unref (recmodel);
-		}
+        op = gda_server_operation_new (type, file);
+        g_free (file);
 
-		g_free (sql);
-		if (trans_started)
-			gda_connection_rollback_transaction (cnc, "temp_transaction", NULL);
-		gda_command_free (command);						
-	}
-
-	return GDA_DATA_MODEL (recset);
+        return op;
 }
 
-static void
-fb_add_aggregate_row (GdaDataModelArray *recset,
-		      const gchar *str,
-		      const gchar *comments)
-{
-	GList *list;
-	GValue *tmpval;
-
-	g_return_if_fail (GDA_IS_DATA_MODEL_ARRAY (recset));
-
-	/* 1st the name */
-	g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), str);
-	list = g_list_append (NULL, tmpval);
-	/* 2nd the unique id */
-	g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), str);
-	list = g_list_append (list, tmpval);
-	/* 3rd the owner */
-	g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), "SYSDBA");
-	list = g_list_append (list, tmpval);
-	/* 4th the comments */
-	g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), comments);
-	list = g_list_append (list, tmpval);
-	/* 5th the return type */
-	g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), _("UNKNOWN"));
-	list = g_list_append (list, tmpval);
-	/* 6th the argument type */
-	g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), _("UNKNOWN"));
-	list = g_list_append (list, tmpval);
-	/* 7th the SQL definition */
-	tmpval = gda_value_new_null ();
-	list = g_list_append (list, tmpval);
-
-	gda_data_model_append_values (GDA_DATA_MODEL (recset), list, NULL);
-
-	g_list_foreach (list, (GFunc) gda_value_free, NULL);
-	g_list_free (list);
-}
-
-static GdaDataModel *
-fb_get_aggregates (GdaConnection *cnc,
-		   GdaParameterList *params)
+/*
+ * Render operation request
+ */
+static gchar *
+gda_firebird_provider_render_operation (GdaServerProvider *provider, GdaConnection *cnc,
+					GdaServerOperation *op, GError **error)
 {
-	GdaDataModelArray *recset;
-
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+        gchar *sql = NULL;
+        gchar *file;
+        gchar *str;
+	gchar *dir;
+
+	if (cnc) {
+		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+		g_return_val_if_fail (gda_connection_get_provider_obj (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 ("firebird_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);
+	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);
 
-	/* Create recordset */
-	recset = (GdaDataModelArray *) 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);
-
-	/* Fill recordset */
-	/*FIXME: Add user defined fuctions (Stored in systables) and set parameters */
-	fb_add_aggregate_row (recset, "abs", "comments");
-	fb_add_aggregate_row (recset, "acos","comments");
-	fb_add_aggregate_row (recset, "ascii_char", "comments");
-	fb_add_aggregate_row (recset, "ascii_val", "comments");
-	fb_add_aggregate_row (recset, "asin", "comments");
-	fb_add_aggregate_row (recset, "atan", "comments");
-	fb_add_aggregate_row (recset, "atan2", "comments");
-	fb_add_aggregate_row (recset, "bin_and", "comments");
-	fb_add_aggregate_row (recset, "bin_or", "comments");
-	fb_add_aggregate_row (recset, "bin_xor", "comments");
-	fb_add_aggregate_row (recset, "ceiling", "comments");
-	fb_add_aggregate_row (recset, "cos", "comments");
-	fb_add_aggregate_row (recset, "cosh", "comments");
-	fb_add_aggregate_row (recset, "cot", "comments");
-	fb_add_aggregate_row (recset, "div", "comments");
-	fb_add_aggregate_row (recset, "floor", "comments");
-	fb_add_aggregate_row (recset, "ln", "comments");
-	fb_add_aggregate_row (recset, "log", "comments");
-	fb_add_aggregate_row (recset, "log10", "comments");
-	fb_add_aggregate_row (recset, "lower", "comments");
-	fb_add_aggregate_row (recset, "ltrim", "comments");
-	fb_add_aggregate_row (recset, "mod", "comments");
-	fb_add_aggregate_row (recset, "pi", "comments");
-	fb_add_aggregate_row (recset, "rand", "comments");
-	fb_add_aggregate_row (recset, "rtrim", "comments");
-	fb_add_aggregate_row (recset, "sign", "comments");
-	fb_add_aggregate_row (recset, "sin", "comments");
-	fb_add_aggregate_row (recset, "sinh", "comments");
-	fb_add_aggregate_row (recset, "sqrt", "comments");
-	fb_add_aggregate_row (recset, "strlen", "comments");
-	fb_add_aggregate_row (recset, "substr", "comments");
-	fb_add_aggregate_row (recset, "tan", "comments");
-	fb_add_aggregate_row (recset, "tanh", "comments");	
+	/* 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_firebird_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;
+}
 
-	return GDA_DATA_MODEL (recset);
+/*
+ * Perform operation request
+ */
+static gboolean
+gda_firebird_provider_perform_operation (GdaServerProvider *provider, GdaConnection *cnc,
+					 GdaServerOperation *op, guint *task_id, 
+					 GdaServerProviderAsyncCallback async_cb, gpointer cb_data, GError **error)
+{
+        GdaServerOperationType optype;
+
+	/* 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,
+			     _("Provider does not support asynchronous server operation"));
+                return FALSE;
+	}
+
+	if (cnc) {
+		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+		g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, FALSE);
+	}
+        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 */
+		return gda_server_provider_perform_operation_default (provider, cnc, op, error);
+	}
 }
 
 /*
- *  fb_sqlerror_get_description
- *
- *  Returns: A message containing a description from a Firebird error
+ * Begin transaction request
  */
-static gchar *
-fb_sqlerror_get_description (GdaFirebirdConnection *fcnc,
-			     const gint statement_type)
+static gboolean
+gda_firebird_provider_begin_transaction (GdaServerProvider *provider, GdaConnection *cnc,
+					 const gchar *name, GdaTransactionIsolation level,
+					 GError **error)
 {
-	gchar *tmp_msg = NULL;
-	gchar *tmp_sql_msg = NULL;
-	char buffer[512], *pmsg;
-	short sql_code;
-	long * ptr_status_vector = fcnc->status;
-
-	pmsg = buffer;
-	if ((sql_code = isc_sqlcode (ptr_status_vector)) != 0) {
-		isc_sql_interprete ((short) sql_code, pmsg, sizeof (buffer));
-		if (strncmp (buffer, "Invalid token", 13))
-			tmp_sql_msg = g_strdup (pmsg);
-        }
+	FirebirdConnectionData *cdata;
+        static char tpb[] = {
+                isc_tpb_version3,
+                isc_tpb_write,
+                isc_tpb_read_committed,
+                isc_tpb_rec_version,
+                isc_tpb_wait
+        };
 
-	while (fb_interpret (buffer, sizeof (buffer), (const ISC_STATUS**) &ptr_status_vector)) {
-		if (strncmp (buffer, "Dynamic SQL Error", 17) &&
-		    strncmp (buffer, "SQL error code =", 16)) {
-			gchar *tmp = tmp_msg;
-			if (tmp) {
-				tmp_msg = g_strconcat (tmp, ": ", pmsg, NULL);
-				g_free (tmp);
-			}
-			else
-				tmp_msg = g_strdup (pmsg);
-		}
+	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, FALSE);
+	if (level != GDA_TRANSACTION_ISOLATION_UNKNOWN) {
+		gda_connection_add_event_string (cnc, "Provider does not handle that kind of transaction");
+		return FALSE;
 	}
-	
-	if (tmp_sql_msg) {
-		gchar *tmp = tmp_msg;
-		if (tmp) {
-			tmp_msg = g_strconcat (tmp, ": ", tmp_sql_msg, NULL);
-			g_free (tmp);
-			g_free (tmp_sql_msg);
-		}
-		else
-			tmp_msg = tmp_sql_msg;
+
+	cdata = (FirebirdConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
+		return FALSE;
+
+	if (cdata->ftr) {
+		gda_connection_add_event_string (cnc, _("Transaction already started"));
+		return FALSE;
 	}
-						
-	return tmp_msg;
-}
 
-GdaConnectionEvent *
-gda_firebird_connection_make_error (GdaConnection *cnc,
-				    const gint statement_type)
-{
-	GdaConnectionEvent *error;
-	GdaFirebirdConnection *fcnc;
-	gchar *description;
+        /* start the transaction */
+        cdata->ftr = g_new0 (isc_tr_handle, 1);
+        if (isc_start_transaction (cdata->status, cdata->ftr, 1, &(cdata->handle),
+                                   (unsigned short) sizeof (tpb), &tpb)) {
+                _gda_firebird_connection_make_error (cnc, 0);
+                g_free (cdata->ftr);
+		cdata->ftr = NULL;
 
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+                return FALSE;
+        }
 
-	fcnc = g_object_get_data (G_OBJECT (cnc), CONNECTION_DATA);
-	if (!fcnc) 
-		return gda_connection_add_event_string (cnc, _("Invalid Firebird handle"));
-	
-	error = gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR);
-	gda_connection_event_set_code (error, isc_sqlcode (fcnc->status));
-	description = fb_sqlerror_get_description (fcnc, statement_type);
-	gda_connection_event_set_source (error, "[GDA Firebird]");
-	gda_connection_event_set_description (error, description);
-	gda_connection_add_event (cnc, error);	
-	g_free (description);
+        gda_connection_internal_transaction_started (cnc, NULL, name, level);
 
-	return error;
-}
-																								
-/* get_version handler for the GdaFirebirdProvider class */
-static const gchar *
-gda_firebird_provider_get_version (GdaServerProvider *provider)
-{
-	return PACKAGE_VERSION;
+        return TRUE;
 }
 
-/* open_connection handler for the GdaFirebirdProvider class */
+/*
+ * Commit transaction request
+ */
 static gboolean
-gda_firebird_provider_open_connection (GdaServerProvider *provider,
-					GdaConnection *cnc,
-					GdaQuarkList *params,
-					const gchar *username,
-					const gchar *password)
-{
-	GdaFirebirdConnection *fcnc;
-	gchar *fb_db, *fb_user, *fb_password, *fb_charset;
-	gchar *dpb;
+gda_firebird_provider_commit_transaction (GdaServerProvider *provider, GdaConnection *cnc,
+					  const gchar *name, GError **error)
+{
+	FirebirdConnectionData *cdata;
+        gboolean result;
 
-	g_return_val_if_fail (GDA_IS_FIREBIRD_PROVIDER (provider), FALSE);
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, FALSE);
 
-	/* get parameters */
-	fb_db = (gchar *) gda_quark_list_find (params, "DATABASE");
-	if (!fb_db) {
-		gda_connection_add_event_string (cnc, _("No database specified"));
+	cdata = (FirebirdConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
 		return FALSE;
-	}
-
-	if (username)
-		fb_user = (gchar *) username;
-	else
-		fb_user = (gchar *) gda_quark_list_find (params, "USERNAME");
 
-	if (password)
-		fb_password = (gchar *) password;
-	else
-		fb_password = (gchar *) gda_quark_list_find (params, "PASSWORD");
+        if (!cdata->ftr) {
+                gda_connection_add_event_string (cnc, _("Invalid transaction handle"));
+                return FALSE;
+        }
 
-	fb_charset = (gchar *) gda_quark_list_find (params, "CHARACTER_SET");
+        if (isc_commit_transaction (fcnc->status, cdata->ftr)) {
+		_gda_firebird_connection_make_error (cnc, 0);
+                result = FALSE;
+        }
+        else {
+                gda_connection_internal_transaction_committed (cnc, name);
+                result = TRUE;
+        }
 
-	fcnc = g_new0 (GdaFirebirdConnection, 1);
+        g_free (cdata->ftr);
+	cdata->ftr = NULL;
 
-	/* prepare connection to firebird server */
-	/* Initialize dpb_buffer */
-	dpb = fcnc->dpb_buffer;
-	*dpb++ = isc_dpb_version1;
+        return result;
+}
 
-	/* Set user name */
-	if (fb_user) {
-		*dpb++ = isc_dpb_user_name;
-		*dpb++ = strlen (fb_user);
-		strcpy (dpb, fb_user);
-		dpb += strlen (fb_user);
-	}
-
-	/* Set password */
-	if (fb_password) {
-		*dpb++ = isc_dpb_password;
-		*dpb++ = strlen (fb_password);
-		strcpy (dpb, fb_password);
-		dpb += strlen (fb_password);
-	}
-
-	/* Set character set */
-	if (fb_charset) {
-		*dpb++ = isc_dpb_lc_ctype;
-		*dpb++ = strlen (fb_charset);
-		strcpy (dpb, fb_charset);
-		dpb += strlen (fb_charset);
-	}
+/*
+ * Rollback transaction request
+ */
+static gboolean
+gda_firebird_provider_rollback_transaction (GdaServerProvider *provider, GdaConnection *cnc,
+					    const gchar *name, GError **error)
+{
+	FirebirdConnectionData *cdata;
 
-	/* Save dpb length */
-	fcnc->dpb_length = dpb - fcnc->dpb_buffer;
+	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, FALSE);
 
-	if (isc_attach_database (fcnc->status, strlen (fb_db), fb_db, &(fcnc->handle), fcnc->dpb_length,
-				 fcnc->dpb_buffer)) {
-		g_object_set_data (G_OBJECT (cnc), CONNECTION_DATA, fcnc);
-		gda_firebird_connection_make_error (cnc, 0);
-		g_object_set_data (G_OBJECT (cnc), CONNECTION_DATA, NULL);
-		g_free (fcnc);
-		
+	cdata = (FirebirdConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
 		return FALSE;
-	}
-
-	fcnc->dbname = g_strdup (fb_db);
-	fcnc->server_version = fb_server_get_version (fcnc);
 
-	/* attach the GdaFirebirdConnection struct to the connection */
-	g_object_set_data (G_OBJECT (cnc), CONNECTION_DATA, fcnc);
+	TO_IMPLEMENT;
 
-	return TRUE;
+	return FALSE;
 }
 
-/* close_connection handler for the GdaFirebirdProvider class */
+/*
+ * Add savepoint request
+ */
 static gboolean
-gda_firebird_provider_close_connection (GdaServerProvider *provider,
-					GdaConnection *cnc)
+gda_firebird_provider_add_savepoint (GdaServerProvider *provider, GdaConnection *cnc,
+				     const gchar *name, GError **error)
 {
-	GdaFirebirdConnection *fcnc;
+	FirebirdConnectionData *cdata;
 
-	g_return_val_if_fail (GDA_IS_FIREBIRD_PROVIDER (provider), FALSE);
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
-	
-	fcnc = g_object_get_data (G_OBJECT (cnc), CONNECTION_DATA);
-	if (!fcnc) {
-		gda_connection_add_event_string (cnc, _("Invalid Firebird handle"));
-		return FALSE;
-	}
+	g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, FALSE);
 
-	/* detach from database */
-	isc_detach_database (fcnc->status, &(fcnc->handle));
+	cdata = (FirebirdConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
+		return FALSE;
 
-	/* free memory */
-	g_free (fcnc->dbname);
-	g_free (fcnc);
-	g_object_set_data (G_OBJECT (cnc), CONNECTION_DATA, NULL);
+	TO_IMPLEMENT;
 
-	return TRUE;
+	return FALSE;
 }
 
-/* get_server_version handler for the GdaFirebirdProvider class */
-static const gchar *
-gda_firebird_provider_get_server_version (GdaServerProvider *provider,
-					  GdaConnection *cnc)
+/*
+ * Rollback savepoint request
+ */
+static gboolean
+gda_firebird_provider_rollback_savepoint (GdaServerProvider *provider, GdaConnection *cnc,
+					  const gchar *name, GError **error)
 {
-	GdaFirebirdConnection *fcnc;
-	
-	g_return_val_if_fail (GDA_IS_FIREBIRD_PROVIDER (provider), NULL);
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+	FirebirdConnectionData *cdata;
+
+	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, FALSE);
 
-	fcnc = g_object_get_data (G_OBJECT (cnc), CONNECTION_DATA);
-	if (!fcnc) {
-		gda_connection_add_event_string (cnc, _("Invalid Firebird handle"));
+	cdata = (FirebirdConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
 		return FALSE;
-	}
 
-	return ((const gchar *) fcnc->server_version); 	
+	TO_IMPLEMENT;
+
+	return FALSE;
 }
 
-/* get_database handler for the GdaFirebirdProvider class */
-static const gchar *
-gda_firebird_provider_get_database (GdaServerProvider *provider,
-				    GdaConnection *cnc)
+/*
+ * Delete savepoint request
+ */
+static gboolean
+gda_firebird_provider_delete_savepoint (GdaServerProvider *provider, GdaConnection *cnc,
+					const gchar *name, GError **error)
 {
-	GdaFirebirdConnection *fcnc;
+	FirebirdConnectionData *cdata;
 
-	g_return_val_if_fail (GDA_IS_FIREBIRD_PROVIDER (provider), NULL);
-	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_obj (cnc) == provider, FALSE);
 
-	fcnc = g_object_get_data (G_OBJECT (cnc), CONNECTION_DATA);
-	if (!fcnc) {
-		gda_connection_add_event_string (cnc, _("Invalid Firebird handle"));
-		return NULL;
-	}
+	cdata = (FirebirdConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
+		return FALSE;
 
-	return (const gchar *) fcnc->dbname;
-}
+	TO_IMPLEMENT;
 
-/* change_database handler for the GdaFirebirdProvider class */
-static gboolean
-gda_firebird_provider_change_database (GdaServerProvider *provider,
-					GdaConnection *cnc,
-					const gchar *name)
-{
 	return FALSE;
 }
 
-/* create_database_cnc handler for the GdaFirebirdProvider class */
+/*
+ * Feature support request
+ */
 static gboolean
-gda_firebird_provider_create_database_cnc (GdaServerProvider *provider,
-					   GdaConnection *cnc,
-					   const gchar *name)
-{
-	gchar *sql;
-	GdaFirebirdConnection *fcnc;
-	isc_tr_handle ftr = NULL;
-	isc_db_handle fdb = NULL;	
-	GdaQuarkList *params;
-	gchar *fb_sql_dialect, *fb_user, *fb_password;
-	gchar *fb_page_size, *fb_char_set;
-
-	g_return_val_if_fail (GDA_IS_FIREBIRD_PROVIDER (provider), FALSE);
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
-	g_return_val_if_fail (name != NULL, FALSE);
-	
-	fcnc = g_object_get_data (G_OBJECT (cnc), CONNECTION_DATA);
-	if (!fcnc) {
-		gda_connection_add_event_string (cnc, _("Invalid Firebird handle"));
-		return FALSE;
+gda_firebird_provider_supports_feature (GdaServerProvider *provider, GdaConnection *cnc, GdaConnectionFeature feature)
+{
+	if (cnc) {
+		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+		g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, FALSE);
 	}
-	
-	/* Get conection parameter list */
-	params = gda_quark_list_new_from_string (gda_connection_get_cnc_string (cnc));
 
-	/* Get parameters for database creation */	
-	fb_user = (gchar *) gda_connection_get_username (cnc);
-	fb_password = (gchar *) gda_connection_get_password (cnc);
-	fb_sql_dialect = (gchar *) gda_quark_list_find (params, "SQL_DIALECT");
-	
-	if (!fb_sql_dialect)
-		fb_sql_dialect = "3";
-		
-	fb_page_size = (gchar *) gda_quark_list_find (params, "PAGE_SIZE");
-	
-	/* Valid values = 1024, 2048, 4096 and 8192 */
-	if (!fb_page_size)
-		fb_page_size = "4096";
-		
-	fb_char_set = (gchar *) gda_quark_list_find (params, "CHARACTER_SET");
-	
-	if (!fb_char_set)
-		fb_char_set = "NONE";
-	
-	/* Create database */	
-	sql = g_strdup_printf ("CREATE DATABASE '%s' USER '%s' PASSWORD '%s' PAGE_SIZE %s DEFAULT CHARACTER SET %s;",
-				name, fb_user, fb_password, fb_page_size, fb_char_set);
-				
-	/* NOTE: Transaction and Database handles should be NULL in this case */
-	if (isc_dsql_execute_immediate (fcnc->status, &fdb, &ftr, 0, sql, (gushort) atoi (fb_sql_dialect), NULL)) {
-		gda_firebird_connection_make_error (cnc, 0);
+	switch (feature) {
+	case GDA_CONNECTION_FEATURE_SQL :
+		return TRUE;
+	default: 
 		return FALSE;
 	}
+}
 
-	gda_quark_list_free (params);
-	
-	/* we need to detach from the newly created database */
-	isc_detach_database (fcnc->status, &fdb);
+/*
+ * 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_firebird_provider_get_data_handler (GdaServerProvider *provider, GdaConnection *cnc,
+					GType type, const gchar *dbms_type)
+{
+	GdaDataHandler *dh;
+	if (cnc) {
+		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+		g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, FALSE);
+	}
+
+	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);
 
-	return TRUE;
+	return dh;
 }
 
-static GList *
-gda_firebird_provider_run_sql (GList *reclist,
-			       GdaConnection *cnc,
-			       isc_tr_handle *ftr,
-			       const gchar *sql)
-{
-	GObject *res = NULL;
-	gchar **arr;
-	gint n = 0;
-
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+/*
+ * Get default DBMS type request
+ *
+ * This method returns the "preferred" DBMS type for GType
+ */
+static const gchar*
+gda_firebird_provider_get_default_dbms_type (GdaServerProvider *provider, GdaConnection *cnc, GType type)
+{
+	if (cnc) {
+		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+		g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, FALSE);
+	}
 
-	/* parse SQL string, which can contain several commands, separated by ';' */
-	arr = gda_delimiter_split_sql (sql);
-	if (arr) {
-		while (arr[n]) {
-			GdaDataModel *recset;
-			GdaConnectionEvent *event = NULL;
-
-			recset = (GdaDataModel *) gda_firebird_recordset_new (cnc, ftr, arr [n], &res, &event);
-  			if (GDA_IS_FIREBIRD_RECORDSET (recset)) {
-				g_assert (!res);
-				g_object_set (G_OBJECT (recset), "command_text", arr[n],
-					      "command_type", GDA_COMMAND_TYPE_SQL, NULL);
-				reclist = g_list_append (reclist, recset);
-			}
-			else if (res) 
-				reclist = g_list_append (reclist, res);
-			else
-				reclist = g_list_append (reclist, NULL);
+	TO_IMPLEMENT;
 
-			gda_connection_internal_treat_sql (cnc, sql, event);
-			n++;
-		}
-		
-		g_strfreev(arr);
-	}
+	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";
 
-	return reclist;
-}
+	if ((type == GDA_TYPE_BINARY) ||
+	    (type == GDA_TYPE_BLOB))
+		return "blob";
 
-/* drop_database_cnc handler for the GdaFirebirdProvider class */
-static gboolean
-gda_firebird_provider_drop_database_cnc (GdaServerProvider *provider,
-					 GdaConnection *cnc,
-					 const gchar *name)
-{
-	GdaFirebirdConnection *fcnc;
-	isc_db_handle db_handle = NULL;
+	if (type == G_TYPE_BOOLEAN)
+		return "boolean";
 	
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
-	g_return_val_if_fail (name != NULL, FALSE);
+	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))
+		return "string";
 
-	/* Get current firebird connection */
-	fcnc = g_object_get_data (G_OBJECT (cnc), CONNECTION_DATA);
-	if (!fcnc) {
-		gda_connection_add_event_string (cnc, _("Invalid Firebird handle"));
-		return FALSE;
-	}
-	
-	/* Make connection to database */
-	if (isc_attach_database (fcnc->status, strlen (name), (gchar *) name, &(db_handle),
-				 fcnc->dpb_length, fcnc->dpb_buffer)) {
-		gda_firebird_connection_make_error (cnc, 0);
-		return FALSE;
-	}
-	
-	/* Drop database */
-	if (isc_drop_database (fcnc->status, &(db_handle))) {
-		gda_firebird_connection_make_error (cnc, 0);
-		return FALSE;
-	}
+	if ((type == G_TYPE_DOUBLE) ||
+	    (type == GDA_TYPE_NUMERIC) ||
+	    (type == G_TYPE_FLOAT))
+		return "real";
 	
-	return TRUE;
+	if (type == GDA_TYPE_TIME)
+		return "time";
+	if (type == GDA_TYPE_TIMESTAMP)
+		return "timestamp";
+	if (type == G_TYPE_DATE)
+		return "date";
+
+	return "text";
 }
 
-/* execute_command handler for the GdaFirebirdProvider class */
-static GList *
-gda_firebird_provider_execute_command (GdaServerProvider *provider,
-				       GdaConnection *cnc,
-				       GdaCommand *cmd,
-				       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_firebird_provider_create_parser (GdaServerProvider *provider, GdaConnection *cnc)
 {
-	isc_tr_handle *ftr;
-	GList *reclist = NULL;
+	TO_IMPLEMENT;
+	return NULL;
+}
 
-	g_return_val_if_fail (GDA_IS_FIREBIRD_PROVIDER (provider), NULL);
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-	g_return_val_if_fail (cmd != NULL, NULL);
-	
-	/* Begin transaction if it was not already started 
-	 * REM: don't close the transaction because otherwise blobs won't be readable anymore */
-	begin_transaction_if_not_current (provider, cnc, 
-					  "local_tr", 
-					  GDA_TRANSACTION_ISOLATION_UNKNOWN, NULL, NULL);
-	ftr = g_object_get_data (G_OBJECT (cnc), TRANSACTION_DATA);
-	
-	/* Parse command */
-	switch (gda_command_get_command_type (cmd)) {
-		case GDA_COMMAND_TYPE_SQL:
-			reclist = gda_firebird_provider_run_sql (reclist, cnc, ftr, gda_command_get_text (cmd));
-			break;
-		default:
-			break;
+/*
+ * 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_firebird_provider_statement_to_sql (GdaServerProvider *provider, GdaConnection *cnc,
+					GdaStatement *stmt, GdaSet *params, GdaStatementSqlFlag flags,
+					GSList **params_used, GError **error)
+{
+	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_obj (cnc) == provider, NULL);
 	}
-	
-	return reclist;
+
+	return gda_statement_to_sql_extended (stmt, cnc, params, flags, params_used, error);
 }
 
 /*
- * Starts a new transaction is one is not yet running
- * @has_error: set to TRUE if there was an error while starting a transaction
- * Returns: TRUE if a new transaction was just started
+ * 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 #GdaFirebirdPStmt object and declare it to @cnc.
  */
 static gboolean
-begin_transaction_if_not_current (GdaServerProvider *provider,
-				  GdaConnection *cnc,
-				  const gchar *name, GdaTransactionIsolation level,
-				  GError **error, gboolean *has_error)
+gda_firebird_provider_statement_prepare (GdaServerProvider *provider, GdaConnection *cnc,
+					 GdaStatement *stmt, GError **error)
 {
+	GdaFirebirdPStmt *ps;
+
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, FALSE);
+	g_return_val_if_fail (GDA_IS_STATEMENT (stmt), FALSE);
 
-	if (g_object_get_data (G_OBJECT (cnc), TRANSACTION_DATA)) {
-		/* aalready in a transaction */
-		if (has_error)
-			*has_error = FALSE;
+	/* fetch prepares stmt if already done */
+	ps = gda_connection_get_prepared_statement (cnc, stmt);
+	if (ps)
+		return TRUE;
+
+	/* prepare @stmt using the C API, creates @ps */
+	TO_IMPLEMENT;
+	if (!ps)
 		return FALSE;
-	}
 	else {
-		gboolean newtrans;
-		newtrans = gda_firebird_provider_begin_transaction (provider, cnc, name, level, error);
-		if (has_error)
-			*has_error = !newtrans;
-		return newtrans;
+		gda_connection_add_prepared_statement (cnc, stmt, ps);
+		return TRUE;
 	}
 }
 
-
-/* begin_transaction handler for the GdaFirebirdProvider class */
-static gboolean
-gda_firebird_provider_begin_transaction (GdaServerProvider *provider,
-					 GdaConnection *cnc,
-					 const gchar *name, GdaTransactionIsolation level,
-					 GError **error)
+/*
+ * 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_firebird_provider_statement_execute (GdaServerProvider *provider, GdaConnection *cnc,
+					 GdaStatement *stmt, GdaSet *params,
+					 GdaStatementModelUsage model_usage, 
+					 GType *col_types, GdaSet **last_inserted_row, 
+					 guint *task_id, 
+					 GdaServerProviderAsyncCallback async_cb, gpointer cb_data, GError **error)
 {
-	GdaFirebirdConnection *fcnc;
-	isc_tr_handle *ftr;
-	static char tpb[] = {
-		isc_tpb_version3,
-		isc_tpb_write,
-		isc_tpb_read_committed,
-		isc_tpb_rec_version,
-		isc_tpb_wait
-	};
+	GdaFirebirdPStmt *ps;
+	FirebirdConnectionData *cdata;
 
-	g_return_val_if_fail (GDA_IS_FIREBIRD_PROVIDER (provider), FALSE);
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+	g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, NULL);
+	g_return_val_if_fail (GDA_IS_STATEMENT (stmt), NULL);
 
-	fcnc = g_object_get_data (G_OBJECT (cnc), CONNECTION_DATA);
-	if (!fcnc) {
-		gda_connection_add_event_string (cnc, _("Invalid Firebird handle"));
+	/* 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,
+			     _("Provider does not support asynchronous statement execution"));
+                return FALSE;
+	}
+
+	cdata = (FirebirdConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
 		return FALSE;
+
+
+	/* get/create new prepared statement */
+	ps = gda_connection_get_prepared_statement (cnc, stmt);
+	if (!ps) {
+		if (!gda_firebird_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 GdaFirebirdPStmt object.
+			 */
+			TO_IMPLEMENT;
+			return NULL;
+		}
+		else
+			ps = gda_connection_get_prepared_statement (cnc, stmt);
 	}
+	g_assert (ps);
+
+	/* optionnally reset the prepared statement if required by the API */
+	TO_IMPLEMENT;
+	
+	/* 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,
+				     _("Missing parameter(s) to execute query"));
+			break;
+		}
 
-	/* start the transaction */
-	ftr = g_new0 (isc_tr_handle, 1);
-	if (isc_start_transaction (fcnc->status, ftr, 1, &(fcnc->handle),
-				   (unsigned short) sizeof (tpb), &tpb)) {
-		gda_firebird_connection_make_error (cnc, 0);
-		g_free (ftr);
+		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);
+			}
+		}
+		if (!h) {
+			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, str);
+			g_free (str);
+			break;
+		}
+
+		/* actual binding using the C API, for parameter at position @i */
+		const GValue *value = gda_holder_get_value (h);
+		TO_IMPLEMENT;
+	}
 		
-		return FALSE;
+	if (event) {
+		gda_connection_add_event (cnc, event);
+		return NULL;
 	}
 	
-	g_object_set_data (G_OBJECT (cnc), TRANSACTION_DATA, ftr);
-	gda_connection_internal_transaction_started (cnc, NULL, name, level);
+	/* 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);
+	
+	/* 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;
 
-	return TRUE;
+		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_firebird_recordset_new (cnc, ps, flags, col_types);
+		gda_connection_internal_statement_executed (cnc, stmt, params, NULL); /* required: help @cnc keep some stats */
+		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 */
+		return (GObject*) set;
+	}
 }
 
-/* commit_transaction handler for the GdaFirebirdProvider class */
+/*
+ * starts a distributed transaction: put the XA transaction in the ACTIVE state
+ */
 static gboolean
-gda_firebird_provider_commit_transaction (GdaServerProvider *provider,
-					  GdaConnection *cnc,
-					  const gchar *name, GError **error)
+gda_firebird_provider_xa_start (GdaServerProvider *provider, GdaConnection *cnc, 
+				const GdaXaTransactionId *xid, GError **error)
 {
-	GdaFirebirdConnection *fcnc;
-	isc_tr_handle *ftr;
-	gboolean result;
+	FirebirdConnectionData *cdata;
 
-	g_return_val_if_fail (GDA_IS_FIREBIRD_PROVIDER (provider), FALSE);
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, FALSE);
+	g_return_val_if_fail (xid, FALSE);
 
-	fcnc = g_object_get_data (G_OBJECT (cnc), CONNECTION_DATA);
-	if (!fcnc) {
-		gda_connection_add_event_string (cnc, _("Invalid Firebird handle"));
+	cdata = (FirebirdConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
 		return FALSE;
-	}
-
-	ftr = g_object_get_data (G_OBJECT (cnc), TRANSACTION_DATA);
-	if (!ftr) {
-		gda_connection_add_event_string (cnc, _("Invalid transaction handle"));
-		return FALSE;
-	}
 
-	if (isc_commit_transaction (fcnc->status, ftr)) {
-		gda_firebird_connection_make_error (cnc, 0);
-		result = FALSE;
-	}
-	else {
-		gda_connection_internal_transaction_committed (cnc, name);
-		result = TRUE;
-	}
-
-	g_free (ftr);
-	g_object_set_data (G_OBJECT (cnc), TRANSACTION_DATA, NULL);
-
-	return result;
+	TO_IMPLEMENT;
+	return FALSE;
 }
 
-/* rollback_transaction handler for the GdaFirebirdProvider class */
+/*
+ * 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_firebird_provider_rollback_transaction (GdaServerProvider *provider,
-					    GdaConnection *cnc,
-					    const gchar *name, GError **error)
+gda_firebird_provider_xa_end (GdaServerProvider *provider, GdaConnection *cnc, 
+			      const GdaXaTransactionId *xid, GError **error)
 {
-	GdaFirebirdConnection *fcnc;
-	isc_tr_handle *ftr;
-	gboolean result;
+	FirebirdConnectionData *cdata;
 
-	g_return_val_if_fail (GDA_IS_FIREBIRD_PROVIDER (provider), FALSE);
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, FALSE);
+	g_return_val_if_fail (xid, FALSE);
 
-	fcnc = g_object_get_data (G_OBJECT (cnc), CONNECTION_DATA);
-	if (!fcnc) {
-		gda_connection_add_event_string (cnc, _("Invalid Firebird handle"));
+	cdata = (FirebirdConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
 		return FALSE;
-	}
 
-	ftr = g_object_get_data (G_OBJECT (cnc), TRANSACTION_DATA);
-	if (!ftr) {
-		gda_connection_add_event_string (cnc, _("Invalid transaction handle"));
-		return FALSE;
-	}
+	TO_IMPLEMENT;
+	return FALSE;
+}
 
-	if (isc_rollback_transaction (fcnc->status, ftr)) {
-		gda_firebird_connection_make_error (cnc, 0);
-		result = FALSE;
-	}
-	else {
-		gda_connection_internal_transaction_rolledback (cnc, name);
-		result = TRUE;
-	}
+/*
+ * prepares the distributed transaction: put the XA transaction in the PREPARED state
+ */
+static gboolean
+gda_firebird_provider_xa_prepare (GdaServerProvider *provider, GdaConnection *cnc, 
+				  const GdaXaTransactionId *xid, GError **error)
+{
+	FirebirdConnectionData *cdata;
 
-	g_free (ftr);
-	g_object_set_data (G_OBJECT (cnc), TRANSACTION_DATA, NULL);
+	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, FALSE);
+	g_return_val_if_fail (xid, FALSE);
 
-	return result;
+	cdata = (FirebirdConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
+		return FALSE;
+
+	TO_IMPLEMENT;
+	return FALSE;
 }
 
-/* supports handler for the GdaFirebirdProvider class */
+/*
+ * commits the distributed transaction: actually write the prepared data to the database and
+ * terminates the XA transaction
+ */
 static gboolean
-gda_firebird_provider_supports (GdaServerProvider *provider,
-				GdaConnection *cnc,
-				GdaConnectionFeature feature)
+gda_firebird_provider_xa_commit (GdaServerProvider *provider, GdaConnection *cnc, 
+				 const GdaXaTransactionId *xid, GError **error)
 {
-	g_return_val_if_fail (GDA_IS_FIREBIRD_PROVIDER (provider), FALSE);
+	FirebirdConnectionData *cdata;
 
-	switch (feature) {
-		case GDA_CONNECTION_FEATURE_VIEWS:
-		case GDA_CONNECTION_FEATURE_SQL:
-		case GDA_CONNECTION_FEATURE_TRANSACTIONS:
-		case GDA_CONNECTION_FEATURE_AGGREGATES:
-		case GDA_CONNECTION_FEATURE_BLOBS:
-		case GDA_CONNECTION_FEATURE_TRIGGERS:
-		case GDA_CONNECTION_FEATURE_INDEXES:
-		case GDA_CONNECTION_FEATURE_PROCEDURES:
-		case GDA_CONNECTION_FEATURE_USERS:
-			return TRUE;
-		default:
-			break;
-	}
+	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, FALSE);
+	g_return_val_if_fail (xid, FALSE);
+
+	cdata = (FirebirdConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
+		return FALSE;
 
+	TO_IMPLEMENT;
 	return FALSE;
 }
 
-static GdaServerProviderInfo *
-gda_firebird_provider_get_info (GdaServerProvider *provider, GdaConnection *cnc)
+/*
+ * Rolls back an XA transaction, possible only if in the ACTIVE, IDLE or PREPARED state
+ */
+static gboolean
+gda_firebird_provider_xa_rollback (GdaServerProvider *provider, GdaConnection *cnc, 
+				   const GdaXaTransactionId *xid, GError **error)
 {
-	static GdaServerProviderInfo info = {
-		"Firebird",
-		TRUE, 
-		TRUE,
-		TRUE,
-		TRUE,
-		TRUE,
-		FALSE
-	};
-	
-	return &info;
-}
+	FirebirdConnectionData *cdata;
 
-/* get_schema handler for the GdaFirebirdProvider class */
-static GdaDataModel *
-gda_firebird_provider_get_schema (GdaServerProvider *provider,
-				  GdaConnection *cnc,
-				  GdaConnectionSchema schema,
-				  GdaParameterList *params)
-{
-	g_return_val_if_fail (GDA_IS_FIREBIRD_PROVIDER (provider), FALSE);
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, FALSE);
+	g_return_val_if_fail (xid, FALSE);
 
-	switch (schema) {
-		case GDA_CONNECTION_SCHEMA_TYPES:
-			return fb_get_types (cnc, params);
-		case GDA_CONNECTION_SCHEMA_TABLES:
-			return fb_get_tables (cnc, params, FALSE);
-		case GDA_CONNECTION_SCHEMA_VIEWS:
-			return fb_get_tables (cnc, params, TRUE);
-		case GDA_CONNECTION_SCHEMA_FIELDS:
-			return fb_get_fields_metadata (cnc, params);
-		case GDA_CONNECTION_SCHEMA_AGGREGATES:
-			return fb_get_aggregates (cnc, params);
-/*		case GDA_CONNECTION_SCHEMA_INDEXES:
-			return get_firebird_indexes (cnc, params);
-		case GDA_CONNECTION_SCHEMA_PROCEDURES:
-			return get_firebird_procedures (cnc, params);
-		case GDA_CONNECTION_SCHEMA_USERS:
-			return get_firebird_users (cnc, params);
-		case GDA_CONNECTION_SCHEMA_TRIGGERS:
-			return get_firebird_triggers (cnc, params);*/
-		default:
-			break;
-	}
+	cdata = (FirebirdConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
+		return FALSE;
 
-	return NULL;
+	TO_IMPLEMENT;
+	return FALSE;
 }
 
-static GdaDataHandler *
-gda_firebird_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_firebird_provider_xa_recover (GdaServerProvider *provider, GdaConnection *cnc,
+				  GError **error)
 {
-	GdaDataHandler *dh = NULL;
-	
-	g_return_val_if_fail (GDA_IS_SERVER_PROVIDER (provider), NULL);
+	FirebirdConnectionData *cdata;
 
-        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_ULONG) ||
-	    (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_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_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   ((GdaHandlerTime *) dh, G_DATE_YEAR,
-							 G_DATE_MONTH, G_DATE_DAY, '-', 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_with_provider (provider, cnc);
-			gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_STRING, NULL);
-			g_object_unref (dh);
-		}
-	}
-	else if (type == GDA_TYPE_BLOB) {
-		dh = gda_server_provider_handler_find (provider, NULL, type, NULL);
-		if (!dh) {
-			dh = gda_handler_bin_new ();
-			gda_server_provider_handler_declare (provider, dh, NULL, GDA_TYPE_BLOB, NULL);
-			g_object_unref (dh);
-		}
-	}
+	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+	g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, NULL);
 
-	return dh;
+	cdata = (FirebirdConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
+		return NULL;
+
+	TO_IMPLEMENT;
+	return NULL;
 }
-	
-static const gchar* 
-gda_firebird_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 "int64";
-	if (type == G_TYPE_UINT64)
-		return "FIXME";
-	if (type == GDA_TYPE_BLOB)
-		return "blob";
-	if (type == G_TYPE_BOOLEAN)
-		return "smallint";
-	if (type == G_TYPE_DATE)
-		return "date";
-	if (type == G_TYPE_DOUBLE)
-		return "double";
-	if (type == G_TYPE_INT)
-		return "integer";
-	if (type == GDA_TYPE_NUMERIC)
-		return "numeric";
-	if (type == G_TYPE_FLOAT)
-		return "float";
-	if (type == GDA_TYPE_SHORT)
-		return "smallint";
-	if (type == GDA_TYPE_USHORT)
-		return "integer";
-	if (type == G_TYPE_STRING)
-		return "varchar";
-	if (type == GDA_TYPE_TIME)
-		return "time";
-	if (type == GDA_TYPE_TIMESTAMP)
-		return "timestamp";
-	if (type == G_TYPE_CHAR)
-		return "smallint";
-	if (type == G_TYPE_UCHAR)
-		return "smallint";
-	if (type == G_TYPE_ULONG)
-		return "int64";
-        if (type == G_TYPE_UINT)
-		return "int64";
 
-	return "text";
+/*
+ * Free connection's specific data
+ */
+static void
+gda_firebird_free_cnc_data (FirebirdConnectionData *cdata)
+{
+	if (!cdata)
+		return;
+
+	TO_IMPLEMENT;
+	g_free (cdata);
 }

Modified: trunk/providers/firebird/gda-firebird-provider.h
==============================================================================
--- trunk/providers/firebird/gda-firebird-provider.h	(original)
+++ trunk/providers/firebird/gda-firebird-provider.h	Thu Jun 19 20:40:28 2008
@@ -1,38 +1,29 @@
-/* GDA FireBird Provider
- * Copyright (C) 1998 - 2007 The GNOME Foundation
+/* GDA firebird provider
+ * Copyright (C) 2008 The GNOME Foundation.
  *
  * AUTHORS:
- *         Albi Jeronimo <jeronimoalbi yahoo com ar>
- *         Rodrigo Moya <rodrigo gnome-db org>
- *         Vivien Malerba <malerba 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 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_FIREBIRD_PROVIDER_H__
 #define __GDA_FIREBIRD_PROVIDER_H__
 
 #include <libgda/gda-server-provider.h>
-#include <ibase.h>
-
-
-G_BEGIN_DECLS
-
-#define CONNECTION_DATA "GDA_Firebird_ConnectionData"
-#define TRANSACTION_DATA "GDA_Firebird_TransactionData"
-#define STATEMENT_DATA "GDA_Firebird_StatementData"
 
 #define GDA_TYPE_FIREBIRD_PROVIDER            (gda_firebird_provider_get_type())
 #define GDA_FIREBIRD_PROVIDER(obj)            (G_TYPE_CHECK_INSTANCE_CAST (obj, GDA_TYPE_FIREBIRD_PROVIDER, GdaFirebirdProvider))
@@ -40,24 +31,20 @@
 #define GDA_IS_FIREBIRD_PROVIDER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE (obj, GDA_TYPE_FIREBIRD_PROVIDER))
 #define GDA_IS_FIREBIRD_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDA_TYPE_FIREBIRD_PROVIDER))
 
-#define PARENT_TYPE GDA_TYPE_SERVER_PROVIDER
-
 typedef struct _GdaFirebirdProvider      GdaFirebirdProvider;
 typedef struct _GdaFirebirdProviderClass GdaFirebirdProviderClass;
 
 struct _GdaFirebirdProvider {
-	GdaServerProvider provider;
+	GdaServerProvider      provider;
 };
 
 struct _GdaFirebirdProviderClass {
 	GdaServerProviderClass parent_class;
 };
 
-GType              gda_firebird_provider_get_type (void) G_GNUC_CONST;
-GdaServerProvider *gda_firebird_provider_new (void);
+G_BEGIN_DECLS
 
-GdaConnectionEvent *gda_firebird_connection_make_error (GdaConnection *cnc, 
-							const gint statement_type);
+GType gda_firebird_provider_get_type (void) G_GNUC_CONST;
 
 G_END_DECLS
 

Modified: trunk/providers/firebird/gda-firebird-recordset.c
==============================================================================
--- trunk/providers/firebird/gda-firebird-recordset.c	(original)
+++ trunk/providers/firebird/gda-firebird-recordset.c	Thu Jun 19 20:40:28 2008
@@ -1,1194 +1,342 @@
-/* GDA FireBird Provider
- * Copyright (C) 1998 - 2007 The GNOME Foundation
+/* GDA Firebird provider
+ * Copyright (C) 2008 The GNOME Foundation.
  *
  * AUTHORS:
- *         Albi Jeronimo <jeronimoalbi yahoo com ar>
- *         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 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.
  */
 
-
+#include <stdarg.h>
+#include <string.h>
+#include <glib/gi18n-lib.h>
+#include <libgda/gda-util.h>
+#include <libgda/gda-connection-private.h>
+#include "gda-firebird.h"
 #include "gda-firebird-recordset.h"
 #include "gda-firebird-provider.h"
-#include "gda-firebird-blob-op.h"
-#include <libgda/gda-quark-list.h>
-#include <libgda/gda-parameter-list.h>
-#include <glib/gi18n-lib.h>
-#include <glib/gprintf.h>
-#include <string.h>
-#include <math.h>
-                                                                                                                             
-#ifdef PARENT_TYPE
-#undef PARENT_TYPE
-#endif
-                                                                                                                            
-#define PARENT_TYPE GDA_TYPE_DATA_MODEL_ROW
+
+#define _GDA_PSTMT(x) ((GdaPStmt*)(x))
+
+static void gda_firebird_recordset_class_init (GdaFirebirdRecordsetClass *klass);
+static void gda_firebird_recordset_init       (GdaFirebirdRecordset *recset,
+					     GdaFirebirdRecordsetClass *klass);
+static void gda_firebird_recordset_dispose   (GObject *object);
+
+/* virtual methods */
+static gint     gda_firebird_recordset_fetch_nb_rows (GdaPModel *model);
+static gboolean gda_firebird_recordset_fetch_random (GdaPModel *model, GdaPRow **prow, gint rownum, GError **error);
+static gboolean gda_firebird_recordset_fetch_next (GdaPModel *model, GdaPRow **prow, gint rownum, GError **error);
+static gboolean gda_firebird_recordset_fetch_prev (GdaPModel *model, GdaPRow **prow, gint rownum, GError **error);
+static gboolean gda_firebird_recordset_fetch_at (GdaPModel *model, GdaPRow **prow, gint rownum, GError **error);
+
 
 struct _GdaFirebirdRecordsetPrivate {
 	GdaConnection *cnc;
-	GPtrArray *rows;
-	gchar *table_name;
-	gint ncolumns;
-	gint nrows;
-	gchar *sql_dialect;
-	
-	isc_stmt_handle sql_handle;
-	XSQLDA *sql_result;
-	ISC_STATUS fetch_stat;
-	gboolean sql_prepared;
-	gint fetched_rows;	
+	/* TO_ADD: specific information */
 };
-
-static void 			gda_firebird_recordset_class_init (GdaFirebirdRecordsetClass *klass);
-static void 			gda_firebird_recordset_init (GdaFirebirdRecordset *recset,
-							     GdaFirebirdRecordsetClass *klass);
-static void 			gda_firebird_recordset_finalize (GObject *object);
-
-static gint			gda_firebird_recordset_get_n_rows (GdaDataModelRow *model);
-static gint			gda_firebird_recordset_get_n_columns (GdaDataModelRow *model);
-static void       	        gda_firebird_recordset_describe_column (GdaDataModel *model, gint col);
-static GdaRow 	               *gda_firebird_recordset_get_row (GdaDataModelRow *model,
-								gint row, GError **error);
-static const GValue 	       *gda_firebird_recordset_get_value_at (GdaDataModelRow *model,
-								     gint col,
-								     gint row);
-static gboolean			gda_firebird_recordset_is_updatable (GdaDataModelRow *model);
-static GdaRow 	               *gda_firebird_recordset_append_values (GdaDataModelRow *model,
-								      const GList *values, GError **error);
-static gboolean			gda_firebird_recordset_remove_row (GdaDataModelRow *model,
-								   GdaRow *row, GError **error);
-
 static GObjectClass *parent_class = NULL;
 
-/*******************************/
-/* Firebird utility functions  */
-/*******************************/
-
-static GType
-fb_sql_type_to_g_type (const gshort field_type, gboolean has_decimals)
-{
-	switch (field_type) {
-	case SQL_ARRAY:
-	case SQL_ARRAY+1:
-		return GDA_TYPE_LIST;
-	case SQL_BLOB:
-	case SQL_BLOB+1:
-		return GDA_TYPE_BLOB;
-	case SQL_TIMESTAMP:
-	case SQL_TIMESTAMP+1:
-		return GDA_TYPE_TIMESTAMP;
-	case SQL_TYPE_TIME:
-	case SQL_TYPE_TIME+1:
-		return GDA_TYPE_TIME;
-	case SQL_TYPE_DATE:
-	case SQL_TYPE_DATE+1:
-		return G_TYPE_DATE;
-	case SQL_TEXT:
-	case SQL_TEXT+1:
-	case SQL_VARYING:
-	case SQL_VARYING+1:
-		return G_TYPE_STRING;
-	case SQL_SHORT:
-	case SQL_SHORT+1:
-		return GDA_TYPE_SHORT;
-	case SQL_LONG:
-	case SQL_LONG+1:
-		if (has_decimals)
-			return GDA_TYPE_NUMERIC;
-		else
-			return G_TYPE_INT;
-	case SQL_INT64:
-	case SQL_INT64+1:
-		return GDA_TYPE_NUMERIC;
-	case SQL_FLOAT:
-	case SQL_FLOAT+1:
-		return G_TYPE_FLOAT;
-	case SQL_DOUBLE:
-	case SQL_DOUBLE+1:
-		return G_TYPE_DOUBLE;
-	default:
-		return G_TYPE_INVALID;
-	}
-}
-
-
-static void 
-fb_sql_result_free (XSQLDA *sql_result)
+/*
+ * Object init and finalize
+ */
+static void
+gda_firebird_recordset_init (GdaFirebirdRecordset *recset,
+			   GdaFirebirdRecordsetClass *klass)
 {
-	gint i;
-
-	if (sql_result) {
-		if (sql_result->sqlvar) {
-			/* Free memory for each column */
-			for (i = 0; i < sql_result->sqld; i++) {
-				g_free (sql_result->sqlvar[i].sqldata);
-				g_free (sql_result->sqlvar[i].sqlind);
-			}
-		}
+	g_return_if_fail (GDA_IS_FIREBIRD_RECORDSET (recset));
+	recset->priv = g_new0 (GdaFirebirdRecordsetPrivate, 1);
+	recset->priv->cnc = NULL;
 
-		/* Free sql_result */
-		g_free (sql_result);
-		sql_result = NULL;
-	}
+	/* initialize specific information */
+	TO_IMPLEMENT;
 }
 
-static void 
-fb_sql_result_columns_malloc (XSQLDA *sql_result)
+static void
+gda_firebird_recordset_class_init (GdaFirebirdRecordsetClass *klass)
 {
-	gint i;
-
-	g_assert (sql_result != NULL);
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	GdaPModelClass *pmodel_class = GDA_PMODEL_CLASS (klass);
 
-	/* Alloc memory to hold values */
-	for (i = 0; i < sql_result->sqld; i++) {
-		switch (sql_result->sqlvar[i].sqltype & ~1) {
-			case SQL_ARRAY:
-	  		case SQL_ARRAY+1:
-				sql_result->sqlvar[i].sqldata = (gchar *) g_malloc0 (sizeof (ISC_QUAD));
-				break;
-			case SQL_BLOB:
-			case SQL_BLOB+1:
-				sql_result->sqlvar[i].sqldata = (gchar *) g_malloc0 (sizeof (ISC_QUAD));
-				break;
-			case SQL_TIMESTAMP:
-			case SQL_TIMESTAMP+1:
-				sql_result->sqlvar[i].sqldata = (gchar *) g_malloc0 (sizeof (ISC_TIMESTAMP));
-				break;
-			case SQL_TYPE_TIME:
-			case SQL_TYPE_TIME+1:
-				sql_result->sqlvar[i].sqldata = (gchar *) g_malloc0 (sizeof (ISC_TIME));
-				break;
-			case SQL_TYPE_DATE:
-			case SQL_TYPE_DATE+1:
-				sql_result->sqlvar[i].sqldata = (gchar *) g_malloc0 (sizeof (ISC_DATE));
-				break;
-			case SQL_TEXT:
-			case SQL_TEXT+1:
-			case SQL_VARYING:
-			case SQL_VARYING+1:
-				sql_result->sqlvar[i].sqldata = (gchar *) g_malloc0 (sizeof (gchar) * 
-										     (sql_result->sqlvar[i].sqllen + 1));
-				break;
-			case SQL_SHORT:
-			case SQL_SHORT+1:
-				sql_result->sqlvar[i].sqldata = (gchar *) g_malloc0 (sizeof (ISC_USHORT));
-				break;
-			case SQL_LONG:
-			case SQL_LONG+1:
-				sql_result->sqlvar[i].sqldata = (gchar *) g_malloc0 (sizeof (glong));
-				break;																		
-			case SQL_INT64:
-			case SQL_INT64+1:
-				sql_result->sqlvar[i].sqldata = (gchar *) g_malloc0 (sizeof (ISC_INT64));
-				break;
-			case SQL_FLOAT:
-			case SQL_FLOAT+1:
-				sql_result->sqlvar[i].sqldata = (gchar *) g_malloc0 (sizeof (gfloat));
-				break;
-			case SQL_DOUBLE:
-			case SQL_DOUBLE+1:
-				sql_result->sqlvar[i].sqldata = (gchar *) g_malloc0 (sizeof (gdouble));
-				break;
-			default:
-				break;
-		}
+	parent_class = g_type_class_peek_parent (klass);
 
-		/* Allocate space to hold 'allow NULL mark' */
-		sql_result->sqlvar[i].sqlind = (gshort *) g_malloc (sizeof (gshort));
-		*(sql_result->sqlvar[i].sqlind) = 0; /* default assume non-NULL */
-	}                        
+	object_class->dispose = gda_firebird_recordset_dispose;
+	pmodel_class->fetch_nb_rows = gda_firebird_recordset_fetch_nb_rows;
+	pmodel_class->fetch_random = gda_firebird_recordset_fetch_random;
+
+	pmodel_class->fetch_next = gda_firebird_recordset_fetch_next;
+	pmodel_class->fetch_prev = gda_firebird_recordset_fetch_prev;
+	pmodel_class->fetch_at = gda_firebird_recordset_fetch_at;
 }
 
-static void 
-fb_sql_result_set_columns_number (GdaFirebirdConnection *fcnc,
-				  GdaFirebirdRecordset *recset)
+static void
+gda_firebird_recordset_dispose (GObject *object)
 {
-	gint cols_number;
-
-	g_return_if_fail (GDA_IS_FIREBIRD_RECORDSET (recset));		
-	g_assert (recset->priv->sql_result != NULL);
-
-	/* Get information of retrieved columns */
-	isc_dsql_describe (fcnc->status, &(recset->priv->sql_handle), recset->priv->sql_result->version, 
-			   recset->priv->sql_result);
-						
-	cols_number = recset->priv->sql_result->sqld;
-
-	/* if we have more than @sql_result->sqln columns */
-	if (cols_number > recset->priv->sql_result->sqln) {
-
-		/* Free result (record members are not initialized) */
-		g_free (recset->priv->sql_result);
+	GdaFirebirdRecordset *recset = (GdaFirebirdRecordset *) object;
 
-		/* Allocate memory for result, to hold @col_number columns */
-		recset->priv->sql_result = (XSQLDA *) g_malloc0 (XSQLDA_LENGTH (cols_number));
+	g_return_if_fail (GDA_IS_FIREBIRD_RECORDSET (recset));
 
-		/* Set SQLDA version and columns number */
-		recset->priv->sql_result->version = SQLDA_VERSION1;
-		recset->priv->sql_result->sqln = cols_number;
+	if (recset->priv) {
+		if (recset->priv->cnc) 
+			g_object_unref (recset->priv->cnc);
 
-		/* Get information of retrieved columns */
-		isc_dsql_describe (fcnc->status, &(recset->priv->sql_handle), recset->priv->sql_result->version,
-				   recset->priv->sql_result);
+		/* free specific information */
+		TO_IMPLEMENT;
+		g_free (recset->priv);
+		recset->priv = NULL;
 	}
-	
-	recset->priv->ncolumns = cols_number;
-}
-
 
-/*
- *  fb_sql_get_statement_type
- *
- *  Gets statement type
- *
- *  Returns: 0 if error or isc_info_sql_stmt_select, isc_info_sql_stmt_insert,
- *           isc_info_sql_stmt_update, isc_info_sql_stmt_delete, isc_info_sql_stmt_ddl,
- *           ...(see ibase.h for more)
- */
-static gint
-fb_sql_get_statement_type (GdaFirebirdConnection *fcnc,
-			   GdaFirebirdRecordset *recset)
-{
-	int length;
-	char type_item[] = { 
-		isc_info_sql_stmt_type
-	};
-	char buffer[8];
-                                                                                                                            
-	g_return_val_if_fail (GDA_IS_FIREBIRD_RECORDSET (recset), -1);
-	
-	/* Get statement info */
-	isc_dsql_sql_info (fcnc->status, &(recset->priv->sql_handle), sizeof (type_item), type_item, 
-			   sizeof (buffer), buffer);
-
-	/* If OK return statement type */
-	if (buffer[0] == isc_info_sql_stmt_type) {
-		length = isc_vax_integer (&(buffer[1]), 2);
-		return isc_vax_integer (&(buffer[3]), length);
-	}
-	
-	return 0;
+	parent_class->dispose (object);
 }
 
 /*
- * fb_sql_get_statement_impacted_rows
+ * Public functions
  */
-static gint
-fb_sql_get_statement_impacted_rows (GdaFirebirdConnection *fcnc,
-				    GdaFirebirdRecordset *recset, char type)
+
+GType
+gda_firebird_recordset_get_type (void)
 {
-	static char count_info[] = { isc_info_sql_records };
-	char count_buffer [64];
-	long row_count = 0;
-	
-	if (isc_dsql_sql_info (fcnc->status, &(recset->priv->sql_handle),
-			       sizeof(count_info), count_info,
-			       sizeof(count_buffer), count_buffer))
-		return -1; /* error */
+	static GType type = 0;
 
-	unsigned i = 3, result_size = isc_vax_integer (&count_buffer[1],2);
-	
-	while (count_buffer[i] != isc_info_end && (i < result_size)) {
-		short len = (short) isc_vax_integer (&count_buffer[i+1], 2);
-		if (count_buffer[i] == type)
-			row_count += isc_vax_integer (&count_buffer[i+3], len);
-		i += len + 3;
+	if (G_UNLIKELY (type == 0)) {
+		static const GTypeInfo info = {
+			sizeof (GdaFirebirdRecordsetClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) gda_firebird_recordset_class_init,
+			NULL,
+			NULL,
+			sizeof (GdaFirebirdRecordset),
+			0,
+			(GInstanceInitFunc) gda_firebird_recordset_init
+		};
+		type = g_type_register_static (GDA_TYPE_PMODEL, "GdaFirebirdRecordset", &info, 0);
 	}
-	return row_count;
+
+	return type;
 }
 
 /*
- *  fb_sql_prepare
- *
- *  Prepares an unprepared statement
- *
- *  Returns: TRUE if sql prepared successfully, or FALSE otherwise
+ * the @ps struct is modified and transfered to the new data model created in
+ * this function
  */
-static gboolean 
-fb_sql_prepare (GdaFirebirdConnection *fcnc,
-		GdaFirebirdRecordset *recset,
-		isc_tr_handle *ftr,
-		const gchar *sql,
-		GdaConnectionEvent **event)
+GdaDataModel *
+gda_firebird_recordset_new (GdaConnection *cnc, GdaFirebirdPStmt *ps, GdaDataModelAccessFlags flags, GType *col_types)
 {
-	GdaQuarkList *params;
-	gchar *fb_sql_dialect;
-	GdaConnectionEvent *ev = NULL;
-
-	if (event)
-		*event = NULL;
-
-	g_return_val_if_fail (GDA_IS_FIREBIRD_RECORDSET (recset), FALSE);		
-
-	if (ftr) {
-		if (! recset->priv->sql_prepared) {		
-			/* Allocate memory for result to hold 10 columns */
-			recset->priv->sql_result = (XSQLDA *) g_malloc0 (XSQLDA_LENGTH (13));
-			
-			/* Set SQLDA version and columns number */
-			recset->priv->sql_result->version = SQLDA_VERSION1;
-			recset->priv->sql_result->sqln = 13;
-			
-			/* Allocate statement */
-			recset->priv->sql_handle = NULL;
-			if (! isc_dsql_allocate_statement (fcnc->status, &(fcnc->handle), &(recset->priv->sql_handle))) {
-				/* Get SQL Dialect */
-				params = gda_quark_list_new_from_string (
-						gda_connection_get_cnc_string ((GdaConnection *) recset->priv->cnc));
-				fb_sql_dialect = (gchar *) gda_quark_list_find (params, "SQL_DIALECT");		
-				if (!fb_sql_dialect)
-					fb_sql_dialect = "3";
-				
-				gda_quark_list_free (params);
-				
-				/* Prepare statement */
-				if (! isc_dsql_prepare (fcnc->status, ftr, &(recset->priv->sql_handle), 0, (gchar *) sql, 
-							(gushort) atoi (fb_sql_dialect), recset->priv->sql_result)) {
-					fb_sql_result_set_columns_number (fcnc, recset);
-					fb_sql_result_columns_malloc (recset->priv->sql_result);
-					recset->priv->sql_prepared = TRUE;
-					return TRUE;
-				} 
-				else
-					ev = gda_firebird_connection_make_error (recset->priv->cnc, 0);
+	GdaFirebirdRecordset *model;
+        FirebirdConnectionData *cdata;
+        gint i;
+	GdaDataModelAccessFlags rflags;
+
+        g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+        g_return_val_if_fail (ps != NULL, NULL);
+
+	cdata = (FirebirdConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata)
+		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 is out of range (0-%d), ignoring its specified type"), i,
+							   _GDA_PSTMT (ps)->ncols - 1);
+					else
+						_GDA_PSTMT (ps)->types [i] = col_types [i];
+				}
 			}
-			else
-				ev = gda_firebird_connection_make_error (recset->priv->cnc, 0);
+		}
+		
+		/* 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);
 
-		} 
-		else
-			ev = gda_connection_add_event_string (recset->priv->cnc, _("Statement already prepared."));
+			/* use C API to set columns' information using gda_column_set_*() */
+			TO_IMPLEMENT;
+		}
+        }
 
-	}
+	/* 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
-		ev = gda_connection_add_event_string (recset->priv->cnc, _("Transaction not initialized."));
-	
-	if (event)
-		*event = ev;
+		rflags = GDA_DATA_MODEL_ACCESS_CURSOR_FORWARD;
 
-	/* Free cursors */
-	isc_dsql_free_statement (fcnc->status, &(recset->priv->sql_handle), DSQL_drop);
+	/* create data model */
+        model = g_object_new (GDA_TYPE_FIREBIRD_RECORDSET, "prepared-stmt", ps, "model-usage", rflags, NULL);
+        model->priv->cnc = cnc;
+	g_object_ref (cnc);
 
-	/* Free SQL result */
-	fb_sql_result_free (recset->priv->sql_result);
-	recset->priv->sql_result = NULL;
+	/* post init specific code */
+	TO_IMPLEMENT;
 
-	return FALSE;
+        return GDA_DATA_MODEL (model);
 }
 
 
 /*
- *  fb_sql_unprepare
- *
- *  Unprepares a prepared statement
- *
- *  Returns: TRUE if sql unprepared successfully, or FALSE otherwise
+ * Get the number of rows in @model, if possible
  */
-static gboolean 
-fb_sql_unprepare (GdaFirebirdConnection *fcnc, 
-		  GdaFirebirdRecordset *recset)
+static gint
+gda_firebird_recordset_fetch_nb_rows (GdaPModel *model)
 {
-	g_return_val_if_fail (GDA_IS_FIREBIRD_RECORDSET (recset), FALSE);		
-	
-	if (recset->priv->sql_prepared) {
+	GdaFirebirdRecordset *imodel;
 
-		/* Free SQL result */
-		fb_sql_result_free (recset->priv->sql_result);
-		recset->priv->sql_result = NULL;
-
-		/* Free cursors */
-		if (recset->priv->sql_handle)
-			isc_dsql_free_statement (fcnc->status, &(recset->priv->sql_handle), DSQL_drop);
-		
-		return TRUE;
-	}
-	
-	return FALSE;
-}
+	imodel = GDA_FIREBIRD_RECORDSET (model);
+	if (model->advertized_nrows >= 0)
+		return model->advertized_nrows;
 
+	/* use C API to determine number of rows,if possible */
+	TO_IMPLEMENT;
+
+	return model->advertized_nrows;
+}
 
 /*
- *  fb_sql_execute
+ * Create a new filled #GdaPRow object for the row at position @rownum, and put it into *prow.
  *
- *  Call #isc_dsql_execute to execute statement
- *
- *  Returns: TRUE if sql executed successfully, or FALSE otherwise
+ * WARNING: @prow will NOT be NULL, but *prow may or may not be NULL:
+ *  -  If *prow is NULL then a new #GdaPRow object has to be created, 
+ *  -  and otherwise *prow contains a #GdaPRow 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 GdaPRow object is left to the implementation, which
+ * can use gda_pmodel_take_row(). If new row objects are "given" to the GdaPModel 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
-fb_sql_execute (GdaFirebirdConnection *fcnc,
-		GdaFirebirdRecordset *recset,
-		isc_tr_handle *ftr,
-		const gchar *sql)
+static gboolean 
+gda_firebird_recordset_fetch_random (GdaPModel *model, GdaPRow **prow, gint rownum, GError **error)
 {
-	g_return_val_if_fail (GDA_IS_FIREBIRD_RECORDSET (recset), FALSE);		
-	g_return_val_if_fail ((ftr != NULL), FALSE);		
+	GdaFirebirdRecordset *imodel;
+
+	imodel = GDA_FIREBIRD_RECORDSET (model);
 
-	/* Return statement execute status */
-	if (fb_sql_get_statement_type (fcnc, recset) == isc_info_sql_stmt_select)
-		return (! isc_dsql_execute (fcnc->status, ftr, &(recset->priv->sql_handle), 
-					    recset->priv->sql_result->version, recset->priv->sql_result));
-	else 
-		return (! isc_dsql_execute_immediate (fcnc->status, &(fcnc->handle), ftr, strlen (sql), 
-						      (gchar *) sql, atoi (recset->priv->sql_dialect), NULL));
+	TO_IMPLEMENT;
+
+	return TRUE;
 }
 
-static GdaValueList *
-fb_array_desc_to_list_value (GdaConnection *cnc, GdaFirebirdConnection *fcnc, isc_tr_handle *ftr, gpointer field_data,
-			     ISC_ARRAY_DESC *desc, short cell_type, short cell_size, short current_dim);
 /*
- *  fb_gda_value_fill
- *
- *  Fill a @gda_value with the value of @value
- *
- *  @type should contain Firebirds SQL datatype of @value
+ * Create and "give" filled #GdaPRow object for all the rows in the model
  */
-static void
-_real_fb_gda_value_fill (GValue *gda_value,
-			 GdaFirebirdRecordset *recset,
-			 const gshort field_type,
-			 gpointer field_data,
-			 gint field_number,
-			 gint sqlscale)
+static gboolean
+gda_firebird_recordset_store_all (GdaPModel *model, GError **error)
 {
-	GdaTime a_time;
-	GDate a_date;
-	GdaTimestamp a_times;
-	struct tm *a_date_time;
-#if FB_API_VER < 20
-	struct vary *var_text;
-#else
-	PARAMVARY *var_text;
-#endif
-	
-	switch (field_type) {
-	case SQL_ARRAY:
-	case SQL_ARRAY+1: {
-		/* fetch table and column names */
-		GdaColumn *gdacol;
-
-		gdacol = gda_data_model_describe_column (GDA_DATA_MODEL (recset), field_number);
-		g_assert (gdacol);
-
-		ISC_ARRAY_DESC desc;
-		GdaFirebirdConnection *fcnc;
-		isc_tr_handle *ftr;
-		
-		fcnc = g_object_get_data (G_OBJECT (recset->priv->cnc), CONNECTION_DATA);
-		if (!fcnc) {
-			gda_connection_add_event_string (recset->priv->cnc, _("Invalid Firebird handle"));
-			gda_value_set_null (gda_value);
-			return;
-		}
-		ftr = g_object_get_data (G_OBJECT (recset->priv->cnc), TRANSACTION_DATA);
-		
-		if (isc_array_lookup_bounds (fcnc->status, &(fcnc->handle), ftr,
-					     gda_column_get_table (gdacol),
-					     gda_column_get_name (gdacol), &desc)) {
-			gda_firebird_connection_make_error (recset->priv->cnc, 0);
-			gda_value_set_null (gda_value);
-			return;
-		}
-		
-		short cell_type;
-		short cell_size;
-		switch (desc.array_desc_dtype) {
-		case blr_text:
-		case blr_text2:
-			cell_type = SQL_TEXT;
-			cell_size = desc.array_desc_length + 1;
-			break;
-		case blr_short:
-			cell_type = SQL_SHORT;
-			cell_size = sizeof (short);
-			break;
-		case blr_long:
-			cell_type = SQL_LONG;
-			cell_size = sizeof (long);
-			break;
-		case blr_float:
-			cell_type = SQL_FLOAT;
-			cell_size = sizeof(float);
-			break;
-		case blr_double:
-			cell_type = SQL_DOUBLE;
-			cell_size = sizeof(double);
-			break;
-		case blr_date:
-			cell_type = SQL_DATE;
-			cell_size = sizeof(ISC_QUAD);
-			break;
-		case blr_varying:
-		case blr_varying2:	
-			cell_type = SQL_TEXT;
-			cell_size = desc.array_desc_length + sizeof(short);
-			break;
-		default:
-			gda_connection_add_event_string (recset->priv->cnc, _("Can't handle type of array element"));
-			gda_value_set_null (gda_value);
-			return;
-		}
+	GdaFirebirdRecordset *imodel;
+	gint i;
 
-		GdaValueList *vlist;
-		vlist = fb_array_desc_to_list_value (recset->priv->cnc, fcnc, ftr, 
-						     field_data, &desc, cell_type, cell_size, 0);
-		if (vlist) {
-			g_value_init (gda_value, GDA_TYPE_LIST);
-			gda_value_set_list (gda_value, vlist);
-		}
-		else
-			gda_value_set_null (gda_value);
-		break;
-	}
-	case SQL_BLOB:
-	case SQL_BLOB+1: {
-		GdaBlob *blob;
-                GdaBlobOp *op;
-
-                blob = g_new0 (GdaBlob, 1);
-                op = gda_firebird_blob_op_new_with_id (recset->priv->cnc, (const ISC_QUAD *) field_data);
-                gda_blob_set_op (blob, op);
-                g_object_unref (op);
-		g_value_init (gda_value, GDA_TYPE_BLOB);
-                gda_value_take_blob (gda_value, blob);
-		break;
-	}
-	case SQL_TIMESTAMP:
-	case SQL_TIMESTAMP+1:
-		a_date_time = g_malloc0 (sizeof (struct tm));
-		isc_decode_timestamp ((ISC_TIMESTAMP *) field_data, a_date_time);
-		a_date_time->tm_mon ++;
-		a_date_time->tm_year += 1900;
-		a_times.hour = a_date_time->tm_hour;
-		a_times.minute = a_date_time->tm_min;
-		a_times.second = a_date_time->tm_sec;
-		a_times.year = a_date_time->tm_year;
-		a_times.month = a_date_time->tm_mon;
-		a_times.day = a_date_time->tm_mday;
-		a_times.timezone = 0; /* FIXME: timezone */
-		a_times.fraction = 0; /* FIXME: fraction */			
-
-		g_value_init (gda_value, GDA_TYPE_TIMESTAMP);
-		gda_value_set_timestamp (gda_value, (const GdaTimestamp *) &a_times);
-		g_free (a_date_time);
-		break;
-	case SQL_TYPE_TIME:
-	case SQL_TYPE_TIME+1:
-		a_date_time = g_malloc0 (sizeof (struct tm));
-		isc_decode_sql_time ((ISC_TIME *) field_data, a_date_time);
-		a_time.hour = a_date_time->tm_hour;
-		a_time.minute = a_date_time->tm_min;
-		a_time.second = a_date_time->tm_sec;
-		a_time.timezone = 0; /* FIXME: timezone */
-
-		g_value_init (gda_value, GDA_TYPE_TIME);
-		gda_value_set_time (gda_value, (const GdaTime *) &a_time);
-		g_free (a_date_time);
-		break;
-	case SQL_TYPE_DATE:
-	case SQL_TYPE_DATE+1:
-		a_date_time = g_malloc0 (sizeof (struct tm));
-		isc_decode_sql_date ((ISC_DATE *) field_data, a_date_time);
-		a_date_time->tm_mon++;
-		a_date_time->tm_year += 1900;
-		a_date.year = a_date_time->tm_year;
-		a_date.month = a_date_time->tm_mon;
-		a_date.day = a_date_time->tm_mday;
-
-		g_value_init (gda_value, G_TYPE_DATE);
-		g_value_set_boxed (gda_value, (const GDate *) &a_date);
-		g_free (a_date_time);			
-		break;
-	case SQL_TEXT: 
-	case SQL_TEXT+1: {
-		/* remove trailing spaces... */
-		gchar *str;
-		g_value_init (gda_value, G_TYPE_STRING);
-		str = g_strdup ((const gchar *) field_data);
-		g_strchomp (str);
-		g_value_take_string (gda_value, str);
-		break;
-	}
-	case SQL_VARYING:
-	case SQL_VARYING+1:
-#if FB_API_VER < 20
-		var_text = (struct vary *) field_data;
-#else
-		var_text = (PARAMVARY *) field_data;
-#endif
-		var_text->vary_string[var_text->vary_length] = '\0';
-
-		g_value_init (gda_value, G_TYPE_STRING);
-		g_value_set_string (gda_value, (const gchar *) var_text->vary_string);
-		break;
-	case SQL_SHORT:
-	case SQL_SHORT+1:
-		gda_value_set_short (gda_value, *((gshort *) field_data));
-		break;
-	case SQL_LONG:
-	case SQL_LONG+1:
-		g_value_init (gda_value, G_TYPE_LONG);
-		if (sqlscale < 0) 
-			g_value_set_long (gda_value, *((glong *) field_data) /
-					  pow (10, (sqlscale * -1)));
-		else
-			g_value_set_long (gda_value, *((glong *) field_data));
-		break;
-	case SQL_INT64:
-	case SQL_INT64+1:
-		g_value_init (gda_value, G_TYPE_INT64);
-		if (sqlscale < 0) 
-			g_value_set_int64 (gda_value, *((ISC_INT64 *) field_data) / 
-					   pow (10, (sqlscale * -1)));
-		else
-			g_value_set_int64 (gda_value, *((ISC_INT64 *) field_data));
-		break;
-	case SQL_FLOAT:
-	case SQL_FLOAT+1:
-		g_value_init (gda_value, G_TYPE_FLOAT);
-		g_value_set_float (gda_value, *((gfloat *) field_data));
-		break;
-	case SQL_DOUBLE:
-	case SQL_DOUBLE+1:
-		g_value_init (gda_value, G_TYPE_DOUBLE);
-		g_value_set_double (gda_value, *((gdouble *) field_data));
-		break;
-	default:
-		g_print (_("Unknown Firebird's field value!\n"));
-
-		gda_value_set_null (gda_value);
-		break;
-	};
-}
+	imodel = GDA_FIREBIRD_RECORDSET (model);
 
-static GdaValueList *
-fb_array_desc_to_list_value (GdaConnection *cnc, GdaFirebirdConnection *fcnc, isc_tr_handle *ftr, gpointer field_data,
-			     ISC_ARRAY_DESC *desc, short cell_type, short cell_size, short current_dim)
-{
-	GdaValueList *vlist = NULL;
-	gint i, min, max;
-	long len;
-	gchar *buffer;
-	
-	buffer = g_new0 (gchar, cell_size);
-	min = desc->array_desc_bounds[current_dim].array_bound_lower;
-	max = desc->array_desc_bounds[current_dim].array_bound_upper;
-	for (i = min; i <= max; i++) {
-		GValue *lv;
-		desc->array_desc_bounds[current_dim].array_bound_lower = i;
-		desc->array_desc_bounds[current_dim].array_bound_upper = i;
-
-		if (current_dim + 1 < desc->array_desc_dimensions) {
-			GdaValueList *sub_vlist;
-			sub_vlist = fb_array_desc_to_list_value (cnc, fcnc, ftr, field_data, 
-								 desc, cell_type, cell_size, current_dim + 1);
-			vlist = g_list_prepend (vlist, sub_vlist);
-		}
-		else {
-			len = cell_size;
-			if (isc_array_get_slice (fcnc->status, &(fcnc->handle), ftr, 
-						 field_data, desc, (void *)buffer, &len)) {
-				g_free (buffer);
-				gda_firebird_connection_make_error (cnc, 0);
-				return NULL;
-			}
-			lv = g_new0 (GValue, 1);
-			_real_fb_gda_value_fill (lv, NULL, cell_type, buffer, -1, 0);
-			vlist = g_list_prepend (vlist, lv);
-		}
+	/* default implementation */
+	for (i = 0; i < model->advertized_nrows; i++) {
+		GdaPRow *prow;
+		if (! gda_firebird_recordset_fetch_random (model, &prow, i, error))
+			return FALSE;
 	}
-	desc->array_desc_bounds[current_dim].array_bound_lower = min;
-	desc->array_desc_bounds[current_dim].array_bound_upper = max;
-	g_free (buffer);
-
-	return g_list_reverse (vlist);
+	return TRUE;
 }
 
 /*
- *  fb_gda_value_fill
+ * Create a new filled #GdaPRow object for the next cursor row, and put it into *prow.
  *
- *  Fill a @gda_value with the value of @value
+ * WARNING: @prow will NOT be NULL, but *prow may or may not be NULL:
+ *  -  If *prow is NULL then a new #GdaPRow object has to be created, 
+ *  -  and otherwise *prow contains a #GdaPRow 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.
  *
- *  @type should contain Firebirds SQL datatype of @value
+ * Memory management for that new GdaPRow object is left to the implementation, which
+ * can use gda_pmodel_take_row().
  */
-static void
-fb_gda_value_fill (GValue *gda_value,
-		   GdaFirebirdRecordset *recset,
-		   const gshort field_type,
-		   gint field_number)
+static gboolean 
+gda_firebird_recordset_fetch_next (GdaPModel *model, GdaPRow **prow, gint rownum, GError **error)
 {
-	gpointer field_data;
-	XSQLDA *sql_result;
-	
-	g_return_if_fail (GDA_IS_FIREBIRD_RECORDSET (recset));
+	GdaFirebirdRecordset *imodel = (GdaFirebirdRecordset*) model;
 
-	sql_result = recset->priv->sql_result;
-	field_data = (gchar *) sql_result->sqlvar[field_number].sqldata;
-	
-	/* If value is null  */
-	if (*(sql_result->sqlvar[field_number].sqlind) == -1) {
-		gda_value_set_null (gda_value);
-		return;
-	}	
-
-	/* real value fill */
-	_real_fb_gda_value_fill (gda_value, recset, field_type, field_data, field_number, 
-				 sql_result->sqlvar[field_number].sqlscale);
-}
+	TO_IMPLEMENT;
 
+	return TRUE;
+}
 
 /*
+ * Create a new filled #GdaPRow object for the previous cursor row, and put it into *prow.
  *
- *  fb_sql_fetch_row
- *
- *  Fetch a single row
+ * WARNING: @prow will NOT be NULL, but *prow may or may not be NULL:
+ *  -  If *prow is NULL then a new #GdaPRow object has to be created, 
+ *  -  and otherwise *prow contains a #GdaPRow 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.
  *
- *  Returns: TRUE if fetched successfully, or FALSE otherwise
+ * Memory management for that new GdaPRow object is left to the implementation, which
+ * can use gda_pmodel_take_row().
  */
-static gboolean
-fb_sql_fetch_row (GdaFirebirdConnection *fcnc,
-		  GdaFirebirdRecordset *recset)
-{
-	GdaRow *row;
-	gint col_n;
-	gshort field_type;
-
-	g_return_val_if_fail (GDA_IS_FIREBIRD_RECORDSET (recset), FALSE);
-
-	/* Fetch a single row */
-	recset->priv->fetch_stat = isc_dsql_fetch (fcnc->status, &(recset->priv->sql_handle), 
-						   recset->priv->sql_result->version, recset->priv->sql_result);
-	/* If we're not at end of file */
-	if (! (recset->priv->fetch_stat == 100L)) {
-
-		/* ... and fetch was successful */
-		if (recset->priv->fetch_stat == 0) {
-			recset->priv->fetched_rows++;
-
-			/* Create a row for the fetched data */
-			row = gda_row_new (GDA_DATA_MODEL (recset), recset->priv->ncolumns);
-
-			/* Fill each GValue in @row with fetched values */
-			for (col_n = 0; col_n < recset->priv->ncolumns; col_n++) {
-
-				/* Get current field type from statement XSQLDA's variable */
-				field_type = (((gshort) recset->priv->sql_result->sqlvar[col_n].sqltype) & ~1);
-
-				/* Set row's field value */
-				fb_gda_value_fill ((GValue *) gda_row_get_value (row, col_n), recset,
-						   (const gint) field_type, col_n);
-			}
-
-			/* Add value to rows array */
-			g_ptr_array_add (recset->priv->rows, row);
-			
-			return TRUE;
-		}
-		else /* Inform error */
-			gda_firebird_connection_make_error (recset->priv->cnc, 0);
-	}
-
-	return FALSE;
-}
-
-
-/**********************************************/
-/* GdaFirebirdRecordset class implementation  */
-/**********************************************/
-
-static gint
-gda_firebird_recordset_get_n_rows (GdaDataModelRow *model)
-{
-	GdaFirebirdRecordset *recset = (GdaFirebirdRecordset *) model;
-	
-	g_return_val_if_fail (GDA_IS_FIREBIRD_RECORDSET (recset), -1);
-	
-	return (recset->priv->nrows);
-}
-                                                                                                                            
-static gint
-gda_firebird_recordset_get_n_columns (GdaDataModelRow *model)
-{
-	GdaFirebirdRecordset *recset = (GdaFirebirdRecordset *) model;
-	
-	g_return_val_if_fail (GDA_IS_FIREBIRD_RECORDSET (recset), -1);
-	
-	return (recset->priv->ncolumns);
-}
-
-static GdaRow *
-gda_firebird_recordset_get_row (GdaDataModelRow *model, gint row, GError **error)
+static gboolean 
+gda_firebird_recordset_fetch_prev (GdaPModel *model, GdaPRow **prow, gint rownum, GError **error)
 {
-	GdaRow *fields = NULL;
-	GdaFirebirdConnection *fcnc;
-	GdaFirebirdRecordset *recset = (GdaFirebirdRecordset *) model;
-
-	g_return_val_if_fail (GDA_IS_FIREBIRD_RECORDSET (recset), NULL);
-
-	fcnc = g_object_get_data (G_OBJECT (recset->priv->cnc), CONNECTION_DATA);
-	if (!fcnc) {
-		gda_connection_add_event_string (recset->priv->cnc, _("Invalid Firebird handle"));
-		return NULL;
-	}
-
-	/* If row doesn't exists */
-	if (row >= recset->priv->nrows)
-		return NULL;
-		
-	/* If row was already fetched */
-	if (row < recset->priv->fetched_rows)
-		return (GdaRow *) g_ptr_array_index (recset->priv->rows, row);
+	GdaFirebirdRecordset *imodel = (GdaFirebirdRecordset*) model;
 
-	/* Fetch if statement is a SELECT */
-	if (fb_sql_get_statement_type (fcnc, recset) == isc_info_sql_stmt_select) {
+	TO_IMPLEMENT;
 
-		/* Disable DataModel's change notifications */
-		gda_data_model_freeze (GDA_DATA_MODEL (recset));
-
-		while (fb_sql_fetch_row (fcnc, recset) && (row > recset->priv->fetched_rows))
-			recset->priv->nrows++;
-
-		/* If row was fetched */
-		if (row == recset->priv->fetched_rows)
-			return (GdaRow *) g_ptr_array_index (recset->priv->rows, row);
-
-		/* Enable notificarions again */
-		gda_data_model_thaw (GDA_DATA_MODEL (recset));
-	}
-	
-	return (GdaRow *) fields;		
+	return TRUE;
 }
 
-static const GValue *
-gda_firebird_recordset_get_value_at (GdaDataModelRow *model, 
-				     gint col,
-				     gint row)
+/*
+ * Create a new filled #GdaPRow 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 #GdaPRow object has to be created, 
+ *  -  and otherwise *prow contains a #GdaPRow 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 GdaPRow object is left to the implementation, which
+ * can use gda_pmodel_take_row().
+ */
+static gboolean 
+gda_firebird_recordset_fetch_at (GdaPModel *model, GdaPRow **prow, gint rownum, GError **error)
 {
-	gint n_cols;
-	const GdaRow *fields;
-	GdaFirebirdRecordset *recset = (GdaFirebirdRecordset *) model;
-
-	g_return_val_if_fail (GDA_IS_FIREBIRD_RECORDSET (recset), NULL);
-                                                                                                                            
-	n_cols = recset->priv->ncolumns;
-	if (col >= n_cols)
-		return NULL;
-
-	fields = gda_firebird_recordset_get_row (model, row, NULL);
+	GdaFirebirdRecordset *imodel = (GdaFirebirdRecordset*) model;
 	
-	return fields != NULL ? gda_row_get_value ((GdaRow *) fields, col) : NULL;
-}
-
-static gboolean
-gda_firebird_recordset_is_updatable (GdaDataModelRow *model)
-{
-	return FALSE;
-}
-                                                                                                                            
-static GdaRow *
-gda_firebird_recordset_append_values (GdaDataModelRow *model, const GList *values, GError **error)
-{
-	return NULL;
-}
-
-static gboolean
-gda_firebird_recordset_remove_row (GdaDataModelRow *model, GdaRow *row, GError **error)
-{
-	return FALSE;
-}
-
-
-static void
-gda_firebird_recordset_init (GdaFirebirdRecordset *recset,
-			     GdaFirebirdRecordsetClass *klass)
-{
-	g_return_if_fail (GDA_IS_FIREBIRD_RECORDSET (recset));
-
-	/* Init private structure and properties */
-	recset->priv = g_new0 (GdaFirebirdRecordsetPrivate, 1);
-	recset->priv->rows = g_ptr_array_new ();
-	recset->priv->cnc = NULL;
-	recset->priv->sql_prepared = FALSE;
-	recset->priv->sql_result = NULL;
-	recset->priv->sql_handle = NULL;    
-	recset->priv->ncolumns = 0;
-	recset->priv->nrows = 0;
-	recset->priv->sql_dialect = "3";
-	recset->priv->fetched_rows = 0;	
-}			
-
-
-static void
-gda_firebird_recordset_finalize (GObject *object)
-{
-	GdaFirebirdConnection *fcnc;
-	GdaRow *row;
-	GdaFirebirdRecordset *recset = (GdaFirebirdRecordset *) object;
-
-	g_return_if_fail (GDA_IS_FIREBIRD_RECORDSET (recset));
-
-	fcnc = g_object_get_data (G_OBJECT (recset->priv->cnc), CONNECTION_DATA);		
-
-	/* Free Firebirds sql allocated space */
-	fb_sql_result_free (recset->priv->sql_result);
-	recset->priv->sql_result = NULL;
-
-	fb_sql_unprepare (fcnc, recset);
+	TO_IMPLEMENT;
 
-	/* Free all rows */
-	while (recset->priv->rows->len > 0) {
-
-		/* Get row at zero position */
-		row = (GdaRow *) g_ptr_array_index (recset->priv->rows, 0);
-
-		/* if it exists then free it */
-		if (row != NULL)
-			g_object_unref (row);
-
-		/* Move down all existing rows */
-		g_ptr_array_remove_index (recset->priv->rows, 0);
-	}
-
-	/* Free rows pointer object */
-	g_ptr_array_free (recset->priv->rows, TRUE);
-	recset->priv->rows = NULL;
-
-	/* Free private properties */
-	g_free (recset->priv);
-	recset->priv = NULL;
-
-	/* Finally call parents finalize method */
-	parent_class->finalize (object);
-}	
-
-
-static void
-gda_firebird_recordset_class_init (GdaFirebirdRecordsetClass *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_firebird_recordset_finalize;
-	model_class->get_n_rows = gda_firebird_recordset_get_n_rows;
-	model_class->get_n_columns = gda_firebird_recordset_get_n_columns;
-	model_class->get_row = gda_firebird_recordset_get_row;
-	model_class->get_value_at = gda_firebird_recordset_get_value_at;
-	model_class->is_updatable = gda_firebird_recordset_is_updatable;
-	model_class->append_values = gda_firebird_recordset_append_values;
-	model_class->update_row = NULL;
-	model_class->remove_row = gda_firebird_recordset_remove_row;
+	return TRUE;
 }
 
-
-GType
-gda_firebird_recordset_get_type (void)
-{
-	static GType type = 0;
-
-	if (G_UNLIKELY (type == 0)) {
-		static const GTypeInfo info = {
-			sizeof (GdaFirebirdRecordsetClass),
-			(GBaseInitFunc) NULL,
-			(GBaseFinalizeFunc) NULL,
-			(GClassInitFunc) gda_firebird_recordset_class_init,
-			NULL,
-			NULL,
-			sizeof (GdaFirebirdRecordset),
-			0,
-			(GInstanceInitFunc) gda_firebird_recordset_init
-		};
-		
-		type = g_type_register_static (PARENT_TYPE, "GdaFirebirdRecordset", &info, 0);
-	}
-
-	return type;
-}
-
-
-static void
-gda_firebird_recordset_describe_column (GdaDataModel *model, gint col)
-{
-	GdaColumn *fa;
-	GdaFirebirdRecordset *recset = (GdaFirebirdRecordset *) model;
-
-	g_return_if_fail (GDA_IS_FIREBIRD_RECORDSET (recset));
-	g_return_if_fail (col < recset->priv->ncolumns);
-
-	fa = gda_data_model_describe_column (model, col);
-	gda_column_set_title (fa, recset->priv->sql_result->sqlvar[col].sqlname);
-	gda_column_set_name (fa, (const gchar *) recset->priv->sql_result->sqlvar[col].sqlname);
-	gda_column_set_defined_size (fa, (glong) recset->priv->sql_result->sqlvar[col].sqllen);
-	gda_column_set_table (fa, (const gchar *) recset->priv->sql_result->sqlvar[col].relname);
-	gda_column_set_scale (fa, (glong) (recset->priv->sql_result->sqlvar[col].sqlscale * -1));
-	gda_column_set_g_type (fa, fb_sql_type_to_g_type (recset->priv->sql_result->sqlvar[col].sqltype,
-							  (recset->priv->sql_result->sqlvar[col].sqlscale < 0)));
-	gda_column_set_position (fa, col);
-
-	/* FIXME */
-	gda_column_set_allow_null (fa, TRUE);
-	gda_column_set_primary_key (fa, FALSE);
-	gda_column_set_unique_key (fa, FALSE);
-}
-
-GdaFirebirdRecordset *
-gda_firebird_recordset_new (GdaConnection *cnc, 
-			    isc_tr_handle *ftr,
-			    const gchar *sql, GObject **non_select_obj, GdaConnectionEvent **event)
-{
-	GdaFirebirdRecordset *recset;
-	GdaFirebirdConnection *fcnc;
-	gint field_n;
-	GdaConnectionEvent *ev = NULL;
-
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-	g_return_val_if_fail (ftr, NULL);
-
-	if (event)
-		*event = NULL;
-
-	fcnc = g_object_get_data (G_OBJECT (cnc), CONNECTION_DATA);
-	if (!fcnc) {
-		ev = gda_connection_add_event_string (cnc, _("Invalid Firebird handle"));
-		if (event)
-			*event = ev;
-		return NULL;
-	}
-	if (non_select_obj)
-		*non_select_obj = NULL;
-
-	/* Create Firebird Recordset object */
-	recset = g_object_new (GDA_TYPE_FIREBIRD_RECORDSET, NULL);
-	
-	/* Save connection */
-	recset->priv->cnc = cnc;
-	
-	/* Prepare statement */
-	if (fb_sql_prepare (fcnc, recset, ftr, sql, event)) {
-		gint stmt_type;
-
-		ev = gda_connection_event_new (GDA_CONNECTION_EVENT_COMMAND);
-		gda_connection_event_set_description (ev, sql);
-		gda_connection_add_event (cnc, ev);
-
-		stmt_type = fb_sql_get_statement_type (fcnc, recset);
-
-		/* ... and then execute it */
-		if (!fb_sql_execute (fcnc, recset, ftr, sql)) {
-			ev = gda_firebird_connection_make_error (cnc, stmt_type);
-			if (event)
-				*event = ev;
-
-			/* Free Firebirds sql allocated space */
-			fb_sql_result_free (recset->priv->sql_result);
-			recset->priv->sql_result = NULL;
-
-			fb_sql_unprepare (fcnc, recset);
-
-			/* Release recordset */
-			g_object_unref (recset);
-			
-			return NULL;
-		}
-
-		/* If statement is not a select release recordset */
-		if ((stmt_type != isc_info_sql_stmt_select) && 
-		    (stmt_type != isc_info_sql_stmt_select_for_upd)) {
-			GdaConnectionEvent *event;
-			const gchar *cstr;
-			char count_type = 0;
-				
-			switch (stmt_type) {
-			case isc_info_sql_stmt_insert:
-				count_type = isc_info_req_insert_count;
-				cstr = "INSERT";
-				break;
-			case isc_info_sql_stmt_update:
-				count_type = isc_info_req_update_count;
-				cstr = "UPDATE";
-				break;
-			case isc_info_sql_stmt_delete:
-				count_type = isc_info_req_delete_count;
-				cstr = "DELETE";
-				break;
-			case isc_info_sql_stmt_ddl:
-				cstr = "DDL";
-				break;
-			case isc_info_sql_stmt_get_segment:
-				cstr = "GET_SEGMENT";
-				break;
-			case isc_info_sql_stmt_put_segment:
-				cstr = "PUT_SEGMENT";
-				break;
-			case isc_info_sql_stmt_exec_procedure:
-				cstr = "EXECUTE";
-				break;
-			case isc_info_sql_stmt_start_trans:
-				cstr = "BEGIN";
-				break;
-			case isc_info_sql_stmt_commit:
-				cstr = "COMMIT";
-				break;
-			case isc_info_sql_stmt_rollback:
-				cstr = "ROLLBACK";
-				break;
-			case isc_info_sql_stmt_set_generator:
-				cstr = "SET_GENERATOR";
-				break;
-			case isc_info_sql_stmt_savepoint:
-				cstr = "SAVEPOINT";
-				break;
-			default:
-				cstr = "UNKNOWN";
-				break;
-			}
-			event = gda_connection_event_new (GDA_CONNECTION_EVENT_NOTICE);
-			gda_connection_event_set_description (event, cstr);
-			gda_connection_add_event (cnc, event);
-			
-
-			if (non_select_obj && (count_type != 0)) {
-				gint nb = fb_sql_get_statement_impacted_rows (fcnc, recset, count_type);
-				if (nb >= 0)
-					*non_select_obj = (GObject *) gda_parameter_list_new_inline (NULL, "IMPACTED_ROWS", 
-												     G_TYPE_INT, nb, NULL);
-			}
-			g_object_unref (recset);
-			return NULL;
-		}
-
-		/* Set column attributes */
-		for (field_n = 0; field_n < recset->priv->ncolumns; field_n++) {
-			gda_firebird_recordset_describe_column (GDA_DATA_MODEL (recset), field_n);
-			gda_data_model_set_column_title (GDA_DATA_MODEL(recset), field_n, 
-							 recset->priv->sql_result->sqlvar[field_n].sqlname);
-		}
-
-		/* Fetch all rows */
-		while (fb_sql_fetch_row (fcnc, recset))
-			recset->priv->nrows++;
-	}
-	else {	
-		/* Release recordset if statement couldn't be prepared, don't add any error as it has already been done */
-		g_object_unref (recset);
-		recset = NULL;
-	}
-
-	return recset;
-}					
-

Modified: trunk/providers/firebird/gda-firebird-recordset.h
==============================================================================
--- trunk/providers/firebird/gda-firebird-recordset.h	(original)
+++ trunk/providers/firebird/gda-firebird-recordset.h	Thu Jun 19 20:40:28 2008
@@ -1,32 +1,31 @@
-/* GDA FireBird Provider
- * Copyright (C) 1998 - 2004 The GNOME Foundation
+/* GDA Firebird provider
+ * Copyright (C) 2008 The GNOME Foundation.
  *
  * AUTHORS:
- *         Albi Jeronimo <jeronimoalbi yahoo com ar>
- *         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 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_FIREBIRD_RECORDSET_H__
 #define __GDA_FIREBIRD_RECORDSET_H__
 
-#include <libgda/gda-data-model-hash.h>
-#include <libgda/gda-connection.h>
-#include <ibase.h>
+#include <libgda/libgda.h>
+#include <providers-support/gda-pmodel.h>
+#include "gda-firebird-pstmt.h"
 
 G_BEGIN_DECLS
 
@@ -41,29 +40,17 @@
 typedef struct _GdaFirebirdRecordsetPrivate GdaFirebirdRecordsetPrivate;
 
 struct _GdaFirebirdRecordset {
-	GdaDataModelRow model;
+	GdaPModel                model;
 	GdaFirebirdRecordsetPrivate *priv;
 };
 
 struct _GdaFirebirdRecordsetClass {
-	GdaDataModelRowClass parent_class;
+	GdaPModelClass             parent_class;
 };
 
-typedef struct {
-	gchar *dbname, *server_version;
-	isc_db_handle handle;
-	ISC_STATUS status[20];
-	gchar dpb_buffer[128];
-	gshort dpb_length;
-} GdaFirebirdConnection;
-
-
-GType			 gda_firebird_recordset_get_type (void) G_GNUC_CONST;
-GdaFirebirdRecordset 	*gda_firebird_recordset_new (GdaConnection *cnc,
-				 		     isc_tr_handle *ftr,
-						     const gchar *sql,
-						     GObject **non_select_obj,
-						     GdaConnectionEvent **event);
+GType         gda_firebird_recordset_get_type  (void) G_GNUC_CONST;
+GdaDataModel *gda_firebird_recordset_new       (GdaConnection *cnc, GdaFirebirdPStmt *ps, GdaDataModelAccessFlags flags, 
+					    GType *col_types);
 
 G_END_DECLS
 

Modified: trunk/providers/firebird/libgda-firebird-4.0.pc.in
==============================================================================
--- trunk/providers/firebird/libgda-firebird-4.0.pc.in	(original)
+++ trunk/providers/firebird/libgda-firebird-4.0.pc.in	Thu Jun 19 20:40:28 2008
@@ -3,7 +3,7 @@
 libdir= libdir@
 includedir= includedir@
 
-Name: libgda-firebird- GDA_ABI_MAJOR_VERSION@  GDA_ABI_MINOR_VERSION@
+Name: libgda-postgres- GDA_ABI_MAJOR_VERSION@  GDA_ABI_MINOR_VERSION@
 Description: GDA (GNOME Data Access) Firebird provider
 Requires: libgda- GDA_ABI_MAJOR_VERSION@  GDA_ABI_MINOR_VERSION@
 Version: @VERSION@

Modified: trunk/providers/firebird/libmain.c
==============================================================================
--- trunk/providers/firebird/libmain.c	(original)
+++ trunk/providers/firebird/libmain.c	Thu Jun 19 20:40:28 2008
@@ -1,10 +1,8 @@
-/* GDA FireBird Provider
- * Copyright (C) 1998 - 2007 The GNOME Foundation
+/* GDA Firebird Provider
+ * Copyright (C) 2008 The GNOME Foundation
  *
  * AUTHORS:
- *         Rodrigo Moya <rodrigo gnome-db org>
- *         Albi Jeronimo <jeronimoalbi yahoo com ar>
- *         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
@@ -22,9 +20,10 @@
  */
 
 #include <glib/gi18n-lib.h>
-#include "gda-firebird-provider.h"
 #include <libgda/gda-server-provider-extra.h>
 #include <libgda/binreloc/gda-binreloc.h>
+#include "gda-firebird.h"
+#include "gda-firebird-provider.h"
 
 static gchar      *module_path = NULL;
 const gchar       *plugin_get_name (void);
@@ -42,19 +41,19 @@
 const gchar *
 plugin_get_name (void)
 {
-	return "Firebird";
+	return FIREBIRD_PROVIDER_NAME;
 }
 
 const gchar *
 plugin_get_description (void)
 {
-	return _("Provider for Firebird databases");
+	return _("Example provider for C API databases");
 }
 
 gchar *
 plugin_get_dsn_spec (void)
 {
-gchar *ret, *dir;
+	gchar *ret, *dir;
 
 	dir = gda_gbr_get_file_path (GDA_DATA_DIR, LIBGDA_ABI_NAME, NULL);
 	ret = gda_server_provider_load_file_contents (module_path, dir, "firebird_specs_dsn.xml");
@@ -67,7 +66,7 @@
 {
 	GdaServerProvider *prov;
 
-        prov = gda_firebird_provider_new ();
-        g_object_set_data (G_OBJECT (prov), "GDA_PROVIDER_DIR", module_path);
+	prov = (GdaServerProvider*) g_object_new (GDA_TYPE_FIREBIRD_PROVIDER, NULL);
+        g_object_set_data ((GObject *) prov, "GDA_PROVIDER_DIR", module_path);
         return prov;
 }

Modified: trunk/providers/mysql/gda-mysql-blob-op.c
==============================================================================
--- trunk/providers/mysql/gda-mysql-blob-op.c	(original)
+++ trunk/providers/mysql/gda-mysql-blob-op.c	Thu Jun 19 20:40:28 2008
@@ -71,7 +71,6 @@
 gda_mysql_blob_op_init (GdaMysqlBlobOp *op,
 			   GdaMysqlBlobOpClass *klass)
 {
-	g_print ("*** %s\n", __func__);
 	g_return_if_fail (GDA_IS_MYSQL_BLOB_OP (op));
 
 	op->priv = g_new0 (GdaMysqlBlobOpPrivate, 1);
@@ -83,7 +82,6 @@
 static void
 gda_mysql_blob_op_class_init (GdaMysqlBlobOpClass *klass)
 {
-	g_print ("*** %s\n", __func__);
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 	GdaBlobOpClass *blob_class = GDA_BLOB_OP_CLASS (klass);
 
@@ -98,7 +96,6 @@
 static void
 gda_mysql_blob_op_finalize (GObject * object)
 {
-	g_print ("*** %s\n", __func__);
 	GdaMysqlBlobOp *pgop = (GdaMysqlBlobOp *) object;
 
 	g_return_if_fail (GDA_IS_MYSQL_BLOB_OP (pgop));
@@ -115,7 +112,6 @@
 GdaBlobOp *
 gda_mysql_blob_op_new (GdaConnection *cnc)
 {
-	g_print ("*** %s\n", __func__);
 	GdaMysqlBlobOp *pgop;
 
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
@@ -132,7 +128,6 @@
 static glong
 gda_mysql_blob_op_get_length (GdaBlobOp *op)
 {
-	g_print ("*** %s\n", __func__);
 	GdaMysqlBlobOp *pgop;
 
 	g_return_val_if_fail (GDA_IS_MYSQL_BLOB_OP (op), -1);
@@ -150,7 +145,6 @@
 static glong
 gda_mysql_blob_op_read (GdaBlobOp *op, GdaBlob *blob, glong offset, glong size)
 {
-	g_print ("*** %s\n", __func__);
 	GdaMysqlBlobOp *pgop;
 	GdaBinary *bin;
 
@@ -180,7 +174,6 @@
 static glong
 gda_mysql_blob_op_write (GdaBlobOp *op, GdaBlob *blob, glong offset)
 {
-	g_print ("*** %s\n", __func__);
 	GdaMysqlBlobOp *pgop;
 	GdaBinary *bin;
 

Modified: trunk/providers/mysql/gda-mysql-meta.c
==============================================================================
--- trunk/providers/mysql/gda-mysql-meta.c	(original)
+++ trunk/providers/mysql/gda-mysql-meta.c	Thu Jun 19 20:40:28 2008
@@ -44,7 +44,24 @@
 typedef enum {
 	I_STMT_CATALOG,
         I_STMT_BTYPES,
+        I_STMT_SCHEMAS,
         I_STMT_SCHEMAS_ALL,
+        I_STMT_SCHEMA_NAMED,
+        I_STMT_TABLES,
+        I_STMT_TABLES_ALL,
+        I_STMT_TABLE_NAMED,
+        I_STMT_VIEWS,
+        I_STMT_VIEWS_ALL,
+        I_STMT_VIEW_NAMED,
+        I_STMT_COLUMNS_OF_TABLE,
+        I_STMT_COLUMNS_ALL,
+        I_STMT_TABLES_CONSTRAINTS,
+        I_STMT_TABLES_CONSTRAINTS_ALL,
+        I_STMT_TABLES_CONSTRAINTS_NAMED,
+        I_STMT_REF_CONSTRAINTS,
+        I_STMT_REF_CONSTRAINTS_ALL,
+        I_STMT_KEY_COLUMN_USAGE,
+        I_STMT_KEY_COLUMN_USAGE_ALL
 } InternalStatementItem;
 
 
@@ -56,44 +73,61 @@
         "SELECT DATABASE()",
 
         /* I_STMT_BTYPES */
-        "SELECT DISTINCT data_type, CONCAT(table_schema, '.', data_type),  CASE data_type WHEN 'int' THEN 'gint' WHEN 'bigint' THEN 'gint64' WHEN 'blob' THEN 'GdaBinary' WHEN 'date' THEN 'GDate' WHEN 'time' THEN 'GdaTime' WHEN 'double' THEN 'gdouble' WHEN 'timestamp' THEN 'GdaTimestamp' ELSE 'string' END  ,    CONCAT('Desc:', data_type), NULL, 0   FROM information_schema.columns WHERE table_schema = SCHEMA() ORDER BY 1",
+        "SELECT DISTINCT data_type, CONCAT(table_schema, '.', data_type), CASE data_type WHEN 'int' THEN 'gint' WHEN 'bigint' THEN 'gint64' WHEN 'blob' THEN 'GdaBinary' WHEN 'date' THEN 'GDate' WHEN 'time' THEN 'GdaTime' WHEN 'double' THEN 'gdouble' WHEN 'timestamp' THEN 'GdaTimestamp' ELSE 'string' END, CONCAT('Desc:', data_type), NULL, 0 FROM information_schema.columns WHERE table_schema = SCHEMA() ORDER BY 1",
 
         /* I_STMT_SCHEMAS */
+	"SELECT IFNULL(catalog_name, schema_name), schema_name, NULL, CASE schema_name WHEN 'information_schema' THEN 1 ELSE 0 END FROM information_schema.schemata WHERE schema_name = ##cat::string",
 
         /* I_STMT_SCHEMAS_ALL */
-	"SELECT catalog_name, schema_name, 'mysql', CASE schema_name WHEN 'information_schema' THEN TRUE WHEN 'mysql' THEN TRUE ELSE FALSE END   FROM information_schema.schemata",
+	"SELECT IFNULL(catalog_name, schema_name), schema_name, NULL, CASE schema_name WHEN 'information_schema' THEN 1 ELSE 0 END FROM information_schema.schemata",
 
         /* I_STMT_SCHEMA_NAMED */
+	"SELECT IFNULL(catalog_name, schema_name), schema_name, NULL, CASE schema_name WHEN 'information_schema' THEN 1 ELSE 0 END FROM information_schema.schemata WHERE schema_name = ##name::string",
 
         /* I_STMT_TABLES */
+	"SELECT IFNULL(table_catalog, table_schema), table_schema, table_name, table_type, CASE table_type WHEN 'BASE TABLE' THEN 1 ELSE 0 END, table_comment, table_name, CONCAT(table_schema, '.', table_name), NULL FROM information_schema.tables WHERE table_catalog = ##cat::string AND schema_name = ##schema::string",
 
         /* I_STMT_TABLES_ALL */
+	"SELECT IFNULL(table_catalog, table_schema), table_schema, table_name, table_type, CASE table_type WHEN 'BASE TABLE' THEN 1 ELSE 0 END, table_comment, table_name, CONCAT(table_schema, '.', table_name), NULL FROM information_schema.tables",
 
         /* I_STMT_TABLE_NAMED */
+	"SELECT IFNULL(table_catalog, table_schema), table_schema, table_name, table_type, CASE table_type WHEN 'BASE TABLE' THEN 1 ELSE 0 END, table_comment, table_name, CONCAT(table_schema, '.', table_name), NULL FROM information_schema.tables WHERE table_catalog = ##cat::string AND schema_name = ##schema::string",
 
         /* I_STMT_VIEWS */
+	"SELECT IFNULL(table_catalog, table_schema), table_schema, table_name, view_definition, check_option, is_updatable FROM information_schema.views ",
 
         /* I_STMT_VIEWS_ALL */
+	"SELECT IFNULL(table_catalog, table_schema), table_schema, table_name, view_definition, check_option, is_updatable FROM information_schema.views ",
 
         /* I_STMT_VIEW_NAMED */
+	"SELECT IFNULL(table_catalog, table_schema), table_schema, table_name, view_definition, check_option, is_updatable FROM information_schema.views WHERE table_catalog = ##cat::string AND schema_name = ##schema::string",
 
         /* I_STMT_COLUMNS_OF_TABLE */
+	"SELECT IFNULL(table_catalog, table_schema), table_schema, table_name, column_name, ordinal_position, column_default, is_nullable, data_type, 'gchararray', character_maximum_length,character_octet_length, numeric_precision, numeric_scale, 0, character_set_name, character_set_name, character_set_name, collation_name, collation_name, collation_name, '', 1, column_comment FROM information_schema.columns WHERE table_catalog = ##cat::string AND table_schema = ##schema::string AND table_name = ##name::string",
 
         /* I_STMT_COLUMNS_ALL */
+	"SELECT IFNULL(table_catalog, table_schema), table_schema, table_name, column_name, ordinal_position, column_default, is_nullable, data_type, 'gchararray', character_maximum_length,character_octet_length, numeric_precision, numeric_scale, 0, character_set_name, character_set_name, character_set_name, collation_name, collation_name, collation_name, '', 1, column_comment FROM information_schema.columns",
 
         /* I_STMT_TABLES_CONSTRAINTS */
+	"SELECT IFNULL(constraint_catalog, constraint_schema), constraint_schema, constraint_name, IFNULL(table_catalog, table_schema), table_schema, table_name, constraint_type, NULL, 0, 0 FROM information_schema.table_constraints WHERE constraint_catalog = ##cat::string AND constraint_schema = ##schema::string AND table_name = ##name::string",
 
         /* I_STMT_TABLES_CONSTRAINTS_ALL */
+	"SELECT IFNULL(constraint_catalog, constraint_schema), constraint_schema, constraint_name, IFNULL(table_catalog, table_schema), table_schema, table_name, constraint_type, NULL, 0, 0 FROM information_schema.table_constraints",
 
         /* I_STMT_TABLES_CONSTRAINTS_NAMED */
+	"SELECT IFNULL(constraint_catalog, constraint_schema), constraint_schema, constraint_name, IFNULL(table_catalog, table_schema), table_schema, table_name, constraint_type, NULL, 0, 0 FROM information_schema.table_constraints WHERE constraint_catalog = ##cat::string AND constraint_schema = ##schema::string AND table_name = ##name::string AND constraint_name = ##name2::string",
 
         /* I_STMT_REF_CONSTRAINTS */
+	"SELECT IFNULL(t.constraint_catalog, t.constraint_schema), t.table_schema, t.table_name, t.constraint_name, IFNULL(k.constraint_catalog, k.constraint_schema), k.table_schema, k.table_name, k.constraint_name, NULL, NULL, NULL FROM information_schema.table_constraints t INNER JOIN information_schema.key_column_usage k ON t.table_schema=k.table_schema AND t.table_name=k.table_name AND t.constraint_name=k.constraint_name AND ((t.constraint_type = 'FOREIGN KEY' AND k.referenced_table_schema IS NOT NULL) OR (t.constraint_type != 'FOREIGN KEY' AND k.referenced_table_schema IS NULL)) WHERE t.constraint_catalog = ##cat::string AND t.table_schema = ##schema::string AND t.table_name = ##name::string AND t.constraint_name =  ##name2::string",
 
         /* I_STMT_REF_CONSTRAINTS_ALL */
+	"SELECT IFNULL(t.constraint_catalog, t.constraint_schema), t.table_schema, t.table_name, t.constraint_name, IFNULL(k.constraint_catalog, k.constraint_schema), k.table_schema, k.table_name, k.constraint_name, NULL, NULL, NULL FROM information_schema.table_constraints t INNER JOIN information_schema.key_column_usage k ON t.table_schema=k.table_schema AND t.table_name=k.table_name AND t.constraint_name=k.constraint_name AND ((t.constraint_type = 'FOREIGN KEY' AND k.referenced_table_schema IS NOT NULL) OR (t.constraint_type != 'FOREIGN KEY' AND k.referenced_table_schema IS NULL))",
 
         /* I_STMT_KEY_COLUMN_USAGE */
+	"SELECT IFNULL(table_catalog, table_schema), table_schema, table_name, constraint_name, column_name WHERE table_catalog = ##cat::string AND table_schema = ##schema::string AND table_name = ##name::string AND constraint_name = ##name2::string",
 
         /* I_STMT_KEY_COLUMN_USAGE_ALL */
+	"SELECT IFNULL(table_catalog, table_schema), table_schema, table_name, constraint_name, column_name",
 
         /* I_STMT_UDT */
 
@@ -172,7 +206,6 @@
 		       GdaMetaContext     *context,
 		       GError            **error)
 {
-	g_print ("*** %s\n", __func__);
 	GdaDataModel *model;
         gboolean retval;
         model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_CATALOG], NULL, error);
@@ -193,7 +226,6 @@
 			 GdaMetaContext     *context,
 			 GError            **error)
 {
-	g_print ("*** %s\n", __func__);
 	GType col_types[] = {
                 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
                 G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_NONE
@@ -232,25 +264,7 @@
 		     const GValue       *udt_catalog,
 		     const GValue       *udt_schema)
 {
-
 	TO_IMPLEMENT;
-
-	/* /\* set internal holder's values from the arguments *\/ */
-	/* gda_holder_set_value (gda_set_get_holder (i_set, "cat"), udt_catalog); */
-	/* gda_holder_set_value (gda_set_get_holder (i_set, "schema"), udt_schema); */
-	/* GdaDataModel *model; */
-	/* gboolean retval; */
-	/* /\* fill in @model, with something like: */
-	/*  * model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_UDT], i_set, error); */
-	/*  *\/ */
-	/* if (model == NULL) */
-	/* 	retval = FALSE; */
-	/* else { */
-	/* 	retval = gda_meta_store_modify_with_context (store, context, model, error); */
-	/* 	g_object_unref (G_OBJECT(model)); */
-	/* } */
-
-	/* return retval; */
 	return TRUE;
 }
 
@@ -423,7 +437,6 @@
 			   GdaMetaContext     *context,
 			   GError            **error)
 {
-	g_print ("*** %s\n", __func__);
 	// TO_IMPLEMENT;
 
 	GdaDataModel *model;
@@ -448,8 +461,33 @@
 			  const GValue       *catalog_name,
 			  const GValue       *schema_name_n)
 {
-	TO_IMPLEMENT;
-	return TRUE;
+	// TO_IMPLEMENT;
+	
+	GdaDataModel *model;
+	gboolean retval;
+
+	gda_holder_set_value (gda_set_get_holder (i_set, "cat"), catalog_name);
+	if (!schema_name_n) {
+		model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_SCHEMAS], i_set, error);
+		if (model == NULL)
+			retval = FALSE;
+		else {
+			retval = gda_meta_store_modify (store, context->table_name, model, NULL, error, NULL);
+			g_object_unref (G_OBJECT(model));
+		}
+	} else {
+		gda_holder_set_value (gda_set_get_holder (i_set, "name"), schema_name_n);
+		model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_SCHEMA_NAMED], i_set, error);
+		if (model == NULL)
+			retval = FALSE;
+		else {
+			retval = gda_meta_store_modify (store, context->table_name, model,
+							"schema_name=##name::string", error, "name", schema_name_n, NULL);
+			g_object_unref (G_OBJECT(model));
+		}
+	}
+	
+	return retval;
 }
 
 gboolean
@@ -459,8 +497,43 @@
 			       GdaMetaContext     *context,
 			       GError            **error)
 {
-	TO_IMPLEMENT;
-	return TRUE;
+	// TO_IMPLEMENT;
+	
+	GdaDataModel *model_tables, *model_views;
+	gboolean retval;
+	/* Check correct mysql server version. */
+	MysqlConnectionData *cdata;
+	cdata = (MysqlConnectionData *) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata)
+		return FALSE;
+	if (cdata->version_long < 50000) {
+		g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_SERVER_VERSION_ERROR,
+			     _("Mysql version 5.0 at least is required"));
+		return FALSE;
+	}
+
+	/* Copy contents, just because we need to modify @context->table_name */
+	GdaMetaContext copy = *context;
+
+	model_tables = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_TABLES_ALL], i_set, error);
+	if (model_tables == NULL)
+		retval = FALSE;
+	else {
+		copy.table_name = "_tables";
+		retval = gda_meta_store_modify_with_context (store, &copy, model_tables, error);
+		g_object_unref (G_OBJECT(model_tables));
+	}
+
+	model_views = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_VIEWS_ALL], i_set, error);
+	if (model_views == NULL)
+		retval = FALSE;
+	else {
+		copy.table_name = "_views";
+		retval = gda_meta_store_modify_with_context (store, &copy, model_views, error);
+		g_object_unref (G_OBJECT(model_views));
+	}
+	
+	return retval;
 }
 
 gboolean
@@ -473,8 +546,193 @@
 			      const GValue       *table_schema, 
 			      const GValue       *table_name_n)
 {
-	TO_IMPLEMENT;
-	return TRUE;
+	// TO_IMPLEMENT;
+	
+	GdaDataModel *model_tables, *model_views;
+	gboolean retval;
+	/* Check correct mysql server version. */
+	MysqlConnectionData *cdata;
+	cdata = (MysqlConnectionData *) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata)
+		return FALSE;
+	if (cdata->version_long < 50000) {
+		g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_SERVER_VERSION_ERROR,
+			     _("Mysql version 5.0 at least is required"));
+		return FALSE;
+	}
+
+
+	/* Copy contents, just because we need to modify @context->table_name */
+	GdaMetaContext copy = *context;
+
+	gda_holder_set_value (gda_set_get_holder (i_set, "cat"), table_catalog);
+	gda_holder_set_value (gda_set_get_holder (i_set, "schema"), table_schema);
+	if (!table_name_n) {
+		model_tables = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_TABLES], i_set, error);
+		if (model_tables == NULL)
+			retval = FALSE;
+		else {
+			retval = gda_meta_store_modify_with_context (store, &copy, model_tables, NULL);
+			g_object_unref (G_OBJECT(model_tables));
+		}
+
+		model_views = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_VIEWS], i_set, error);
+		if (model_views == NULL)
+			retval = FALSE;
+		else {
+			retval = gda_meta_store_modify_with_context (store, &copy, model_views, NULL);
+			g_object_unref (G_OBJECT(model_views));
+		}
+
+	} else {
+		gda_holder_set_value (gda_set_get_holder (i_set, "name"), table_name_n);
+		model_tables = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_TABLE_NAMED], i_set, error);
+		if (model_tables == NULL)
+			retval = FALSE;
+		else {
+			copy.table_name = "_tables";
+			retval = gda_meta_store_modify_with_context (store, &copy, model_tables, error);
+			g_object_unref (G_OBJECT(model_tables));
+		}
+
+		model_views = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_VIEW_NAMED], i_set, error);
+		if (model_views == NULL)
+			retval = FALSE;
+		else {
+			copy.table_name = "_views";
+			retval = gda_meta_store_modify_with_context (store, &copy, model_views, error);
+			g_object_unref (G_OBJECT(model_views));
+		}
+
+	}
+	
+	return retval;
+}
+
+/**
+ * map_mysql_to_gda:
+ * @value: a #GValue string.
+ *
+ * It maps a mysql type to a gda type.  This means that when a
+ * mysql type is given, it will return its mapped gda type.
+ *
+ * Returns a newly created GValue string.
+ */
+static inline GValue *
+map_mysql_to_gda (const GValue  *value)
+{
+	const gchar *string = g_value_get_string (value);
+	GValue *newvalue;
+	const gchar *newstring;
+	if (strcmp (string, "bool") == 0)
+		newstring = "gboolean";
+	else
+	if (strcmp (string, "blob") == 0)
+		newstring = "GdaBinary";
+	else
+	if (strcmp (string, "bigint") == 0)
+		newstring = "gint64";
+	else
+	if (strcmp (string, "bigint unsigned") == 0)
+		newstring = "guint64";
+	else
+	if (strcmp (string, "char") == 0)
+		newstring = "gchar";
+	else
+	if (strcmp (string, "date") == 0)
+		newstring = "GDate";
+	else
+	if (strcmp (string, "datetime") == 0)
+		newstring = "GdaTimestamp";
+	else
+	if (strcmp (string, "decimal") == 0)
+		newstring = "GdaNumeric";
+	else
+	if (strcmp (string, "double") == 0)
+		newstring = "gdouble";
+	else
+	if (strcmp (string, "double unsigned") == 0)
+		newstring = "double";
+	else
+	if (strcmp (string, "enum") == 0)
+		newstring = "gchararray";
+	else
+	if (strcmp (string, "float") == 0)
+		newstring = "gfloat";
+	else
+	if (strcmp (string, "float unsigned") == 0)
+		newstring = "gfloat";
+	else
+	if (strcmp (string, "int") == 0)
+		newstring = "int";
+	else
+	if (strcmp (string, "unsigned int") == 0)
+		newstring = "guint";
+	else
+	if (strcmp (string, "long") == 0)
+		newstring = "glong";
+	else
+	if (strcmp (string, "unsigned long") == 0)
+		newstring = "gulong";
+	else
+	if (strcmp (string, "longblob") == 0)
+		newstring = "GdaBinary";
+	else
+	if (strcmp (string, "longtext") == 0)
+		newstring = "GdaBinary";
+	else
+	if (strcmp (string, "mediumint") == 0)
+		newstring = "gint";
+	else
+	if (strcmp (string, "mediumint unsigned") == 0)
+		newstring = "guint";
+	else
+	if (strcmp (string, "mediumblob") == 0)
+		newstring = "GdaBinary";
+	else
+	if (strcmp (string, "mediumtext") == 0)
+		newstring = "GdaBinary";
+	else
+	if (strcmp (string, "set") == 0)
+		newstring = "gchararray";
+	else
+	if (strcmp (string, "smallint") == 0)
+		newstring = "gshort";
+	else
+	if (strcmp (string, "smallint unsigned") == 0)
+		newstring = "gushort";
+	else
+	if (strcmp (string, "text") == 0)
+		newstring = "GdaBinary";
+	else
+	if (strcmp (string, "tinyint") == 0)
+		newstring = "gchar";
+	else
+	if (strcmp (string, "tinyint unsigned") == 0)
+		newstring = "guchar";
+	else
+	if (strcmp (string, "tinyblob") == 0)
+		newstring = "GdaBinary";
+	else
+	if (strcmp (string, "time") == 0)
+		newstring = "GdaTime";
+	else
+	if (strcmp (string, "timestamp") == 0)
+		newstring = "GdaTimestamp";
+	else
+	if (strcmp (string, "varchar") == 0)
+		newstring = "gchararray";
+	else
+	if (strcmp (string, "year") == 0)
+		newstring = "gint";
+	else
+		newstring = "";
+
+	g_value_set_string (newvalue = gda_value_new (G_TYPE_STRING),
+			    newstring);
+	
+	
+	return newvalue;
 }
 
 gboolean
@@ -484,8 +742,55 @@
 			  GdaMetaContext     *context,
 			  GError            **error)
 {
-	TO_IMPLEMENT;
-	return TRUE;
+	// TO_IMPLEMENT;
+
+	/* GType col_types[] = { */
+	/* 	G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, */
+	/* 	G_TYPE_INT, G_TYPE_NONE */
+	/* }; */
+	GdaDataModel *model, *proxy;
+	gboolean retval;
+	/* Check correct mysql server version. */
+	MysqlConnectionData *cdata;
+	cdata = (MysqlConnectionData *) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata)
+		return FALSE;
+	if (cdata->version_long < 50000) {
+		g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_SERVER_VERSION_ERROR,
+			     _("Mysql version 5.0 at least is required"));
+		return FALSE;
+	}
+
+	/* Use a prepared statement for the "base" model. */
+	model = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_COLUMNS_ALL], i_set,
+							      GDA_STATEMENT_MODEL_RANDOM_ACCESS, /* col_types */ NULL, error);
+	if (model == NULL)
+		retval = FALSE;
+	else {
+		proxy = (GdaDataModel *) gda_data_proxy_new (model);
+		gda_data_proxy_set_sample_size ((GdaDataProxy *) proxy, 0);
+		gint n_rows = gda_data_model_get_n_rows (model);
+		gint i;
+		for (i = 0; i < n_rows; ++i) {
+			const GValue *value = gda_data_model_get_value_at (model, 7, i);
+
+			GValue *newvalue = map_mysql_to_gda (value);
+
+			retval = gda_data_model_set_value_at (GDA_DATA_MODEL(proxy), 8, i, newvalue, error);
+			gda_value_free (newvalue);
+			if (retval == 0)
+				break;
+
+		}
+
+		if (retval != 0)
+			retval = gda_meta_store_modify_with_context (store, context, proxy, error);
+		g_object_unref (G_OBJECT(proxy));
+		g_object_unref (G_OBJECT(model));
+
+	}
+
+	return retval;
 }
 
 gboolean
@@ -498,8 +803,60 @@
 			 const GValue       *table_schema, 
 			 const GValue       *table_name)
 {
-	TO_IMPLEMENT;
-	return TRUE;
+	// TO_IMPLEMENT;
+
+	/* GType col_types[] = { */
+	/* 	G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, */
+	/* 	G_TYPE_INT, G_TYPE_NONE */
+	/* }; */
+	GdaDataModel *model, *proxy;
+	gboolean retval;
+	/* Check correct mysql server version. */
+	MysqlConnectionData *cdata;
+	cdata = (MysqlConnectionData *) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata)
+		return FALSE;
+	if (cdata->version_long < 50000) {
+		g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_SERVER_VERSION_ERROR,
+			     _("Mysql version 5.0 at least is required"));
+		return FALSE;
+	}
+
+	/* Use a prepared statement for the "base" model. */
+	gda_holder_set_value (gda_set_get_holder (i_set, "cat"), table_catalog);
+	gda_holder_set_value (gda_set_get_holder (i_set, "schema"), table_schema);
+	gda_holder_set_value (gda_set_get_holder (i_set, "name"), table_name);
+	model = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_COLUMNS_OF_TABLE], i_set,
+							      GDA_STATEMENT_MODEL_RANDOM_ACCESS, /* col_types */ NULL, error);
+	if (model == NULL)
+		retval = FALSE;
+	else {
+		proxy = (GdaDataModel *) gda_data_proxy_new (model);
+		gda_data_proxy_set_sample_size ((GdaDataProxy *) proxy, 0);
+		gint n_rows = gda_data_model_get_n_rows (model);
+		gint i;
+		for (i = 0; i < n_rows; ++i) {
+			const GValue *value = gda_data_model_get_value_at (model, 7, i);
+
+			GValue *newvalue = map_mysql_to_gda (value);
+
+			retval = gda_data_model_set_value_at (GDA_DATA_MODEL(proxy), 8, i, newvalue, error);
+			gda_value_free (newvalue);
+			if (retval == 0)
+				break;
+
+		}
+
+		if (retval != 0)
+			retval = gda_meta_store_modify (store, context->table_name, proxy,
+							"table_schema=##schema::string AND table_name=##name::string", error,
+							"schema", table_schema, "name", table_name, NULL);
+		g_object_unref (G_OBJECT(proxy));
+		g_object_unref (G_OBJECT(model));
+
+	}
+
+	return retval;
 }
 
 gboolean
@@ -560,8 +917,19 @@
 				  GdaMetaContext     *context,
 				  GError            **error)
 {
-	TO_IMPLEMENT;
-	return TRUE;
+	// TO_IMPLEMENT;
+
+	GdaDataModel *model;
+	gboolean retval;
+	model = gda_connection_statement_execute_select	(cnc, internal_stmt[I_STMT_REF_CONSTRAINTS_ALL], NULL, error);
+	if (model == NULL)
+		retval = FALSE;
+	else {
+		retval = gda_meta_store_modify_with_context (store, context, model, error);
+		g_object_unref (G_OBJECT(model));
+	}
+
+	return retval;
 }
 
 gboolean
@@ -575,8 +943,38 @@
 				 const GValue       *table_name, 
 				 const GValue       *constraint_name)
 {
-	TO_IMPLEMENT;
-	return TRUE;
+	// TO_IMPLEMENT;
+
+	GdaDataModel *model;
+	gboolean retval;
+	/* Check correct mysql server version. */
+	MysqlConnectionData *cdata;
+	cdata = (MysqlConnectionData *) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata)
+		return FALSE;
+	if (cdata->version_long < 50000) {
+		g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_SERVER_VERSION_ERROR,
+			     _("Mysql version 5.0 at least is required"));
+		return FALSE;
+	}
+
+	/* Use a prepared statement for the "base" model. */
+	gda_holder_set_value (gda_set_get_holder (i_set, "cat"), table_catalog);
+	gda_holder_set_value (gda_set_get_holder (i_set, "schema"), table_schema);
+	gda_holder_set_value (gda_set_get_holder (i_set, "name"), table_name);
+	gda_holder_set_value (gda_set_get_holder (i_set, "name2"), constraint_name);
+	model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_REF_CONSTRAINTS], i_set, error);
+	if (model == NULL)
+		retval = FALSE;
+	else {
+		retval = gda_meta_store_modify (store, context->table_name, model,
+						"table_schema=##schema::string AND table_name=##name::string AND constraint_name=##name2::string", error,
+						"schema", table_schema, "name", table_name, "name2", constraint_name, NULL);
+		g_object_unref (G_OBJECT(model));
+
+	}
+
+	return retval;
 }
 
 gboolean
@@ -586,8 +984,19 @@
 			      GdaMetaContext     *context,
 			      GError            **error)
 {
-	TO_IMPLEMENT;
-	return TRUE;
+	// TO_IMPLEMENT;
+
+	GdaDataModel *model;
+	gboolean retval;
+	model = gda_connection_statement_execute_select	(cnc, internal_stmt[I_STMT_KEY_COLUMN_USAGE_ALL], NULL, error);
+	if (model == NULL)
+		retval = FALSE;
+	else {
+		retval = gda_meta_store_modify_with_context (store, context, model, error);
+		g_object_unref (G_OBJECT(model));
+	}
+
+	return retval;
 }
 
 gboolean
@@ -601,8 +1010,38 @@
 			     const GValue       *table_name,
 			     const GValue       *constraint_name)
 {
-	TO_IMPLEMENT;
-	return TRUE;
+	// TO_IMPLEMENT;
+
+	GdaDataModel *model;
+	gboolean retval;
+	/* Check correct mysql server version. */
+	MysqlConnectionData *cdata;
+	cdata = (MysqlConnectionData *) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata)
+		return FALSE;
+	if (cdata->version_long < 50000) {
+		g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_SERVER_VERSION_ERROR,
+			     _("Mysql version 5.0 at least is required"));
+		return FALSE;
+	}
+
+	/* Use a prepared statement for the "base" model. */
+	gda_holder_set_value (gda_set_get_holder (i_set, "cat"), table_catalog);
+	gda_holder_set_value (gda_set_get_holder (i_set, "schema"), table_schema);
+	gda_holder_set_value (gda_set_get_holder (i_set, "name"), table_name);
+	gda_holder_set_value (gda_set_get_holder (i_set, "name2"), constraint_name);
+	model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_KEY_COLUMN_USAGE], i_set, error);
+	if (model == NULL)
+		retval = FALSE;
+	else {
+		retval = gda_meta_store_modify (store, context->table_name, model,
+						"table_schema=##schema::string AND table_name=##name::string AND constraint_name=##name2::string", error,
+						"schema", table_schema, "name", table_name, "name2", constraint_name, NULL);
+		g_object_unref (G_OBJECT(model));
+
+	}
+
+	return retval;
 }
 
 gboolean

Modified: trunk/providers/mysql/gda-mysql-parser.c
==============================================================================
--- trunk/providers/mysql/gda-mysql-parser.c	(original)
+++ trunk/providers/mysql/gda-mysql-parser.c	Thu Jun 19 20:40:28 2008
@@ -65,7 +65,6 @@
 static void
 gda_mysql_parser_class_init (GdaMysqlParserClass * klass)
 {
-	g_print ("*** %s\n", __func__);
 	GdaSqlParserClass *pclass = GDA_SQL_PARSER_CLASS (klass);
 
 	pclass->parser_alloc = gda_lemon_mysql_parserAlloc;
@@ -78,5 +77,4 @@
 static void
 gda_mysql_parser_init (GdaMysqlParser *parser)
 {
-	g_print ("*** %s\n", __func__);
 }

Modified: trunk/providers/mysql/gda-mysql-provider.c
==============================================================================
--- trunk/providers/mysql/gda-mysql-provider.c	(original)
+++ trunk/providers/mysql/gda-mysql-provider.c	Thu Jun 19 20:40:28 2008
@@ -158,7 +158,7 @@
 								  GdaServerProviderAsyncCallback   async_cb, 
 								  gpointer                         cb_data,
 								  GError                         **error);
-//
+
 
 /* distributed transactions */
 static gboolean gda_mysql_provider_xa_start    (GdaServerProvider         *provider,
@@ -187,7 +187,7 @@
 static GList   *gda_mysql_provider_xa_recover  (GdaServerProvider  *provider,
 						GdaConnection      *cnc, 
 						GError            **error);
-//
+
 
 /* 
  * private connection data destroy 
@@ -216,7 +216,6 @@
 static void
 gda_mysql_provider_class_init (GdaMysqlProviderClass  *klass)
 {
-	g_print ("*** %s\n", __func__);
 	GdaServerProviderClass *provider_class = GDA_SERVER_PROVIDER_CLASS (klass);
 
 	parent_class = g_type_class_peek_parent (klass);
@@ -296,7 +295,7 @@
         provider_class->meta_funcs.routine_col = _gda_mysql_meta_routine_col;
         provider_class->meta_funcs._routine_par = _gda_mysql_meta__routine_par;
         provider_class->meta_funcs.routine_par = _gda_mysql_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);
@@ -306,14 +305,13 @@
 	provider_class->xa_funcs->xa_commit = gda_mysql_provider_xa_commit;
 	provider_class->xa_funcs->xa_rollback = gda_mysql_provider_xa_rollback;
 	provider_class->xa_funcs->xa_recover = gda_mysql_provider_xa_recover;
-	//
+	
 }
 
 static void
 gda_mysql_provider_init (GdaMysqlProvider       *mysql_prv,
 			 GdaMysqlProviderClass  *klass)
 {
-	g_print ("*** %s\n", __func__);
 	InternalStatementItem i;
 	GdaSqlParser *parser;
 
@@ -361,7 +359,6 @@
 static const gchar *
 gda_mysql_provider_get_name (GdaServerProvider  *provider)
 {
-	g_print ("*** %s\n", __func__);
 	return MYSQL_PROVIDER_NAME;
 }
 
@@ -371,7 +368,6 @@
 static const gchar *
 gda_mysql_provider_get_version (GdaServerProvider  *provider)
 {
-	g_print ("*** %s\n", __func__);
 	return PACKAGE_VERSION;
 }
 
@@ -390,7 +386,6 @@
 		      gboolean      compress,
 		      GError      **error)
 {
-	g_print ("*** %s\n", __func__);
 	unsigned int flags = 0;
 
 	/* Exclusive: host/pair otherwise unix socket. */
@@ -457,7 +452,6 @@
 static gchar *
 get_mysql_version (MYSQL  *mysql)
 {
-	g_print ("*** %s\n", __func__);
 	g_return_val_if_fail (mysql != NULL, NULL);
 	unsigned long version_long;
 	version_long = mysql_get_server_version (mysql);
@@ -488,7 +482,6 @@
 				    GdaServerProviderAsyncCallback   async_cb,
 				    gpointer                         cb_data)
 {
-	g_print ("*** %s\n", __func__);
 	g_return_val_if_fail (GDA_IS_MYSQL_PROVIDER (provider), FALSE);
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
 
@@ -586,7 +579,6 @@
 gda_mysql_provider_close_connection (GdaServerProvider  *provider,
 				     GdaConnection      *cnc)
 {
-	g_print ("*** %s\n", __func__);
 	MysqlConnectionData *cdata;
 
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
@@ -614,7 +606,6 @@
 gda_mysql_provider_get_server_version (GdaServerProvider  *provider,
 				       GdaConnection      *cnc)
 {
-	g_print ("*** %s\n", __func__);
 	MysqlConnectionData *cdata;
 
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
@@ -636,7 +627,6 @@
 gda_mysql_provider_get_database (GdaServerProvider  *provider,
 				 GdaConnection      *cnc)
 {
-	g_print ("*** %s\n", __func__);
 	MysqlConnectionData *cdata;
 
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
@@ -666,7 +656,6 @@
 				       GdaServerOperationType   type,
 				       GdaSet                  *options)
 {
-	g_print ("*** %s\n", __func__);
 	if (cnc) {
 		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
 		g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, FALSE);
@@ -707,7 +696,6 @@
 				     GdaSet                  *options,
 				     GError                 **error)
 {
-	g_print ("*** %s\n", __func__);
         gchar *file;
         GdaServerOperation *op;
         gchar *str;
@@ -747,7 +735,6 @@
 				     GdaServerOperation  *op,
 				     GError             **error)
 {
-	g_print ("*** %s\n", __func__);
         gchar *sql = NULL;
         gchar *file;
         gchar *str;
@@ -814,7 +801,6 @@
 				      gpointer                         cb_data,
 				      GError                         **error)
 {
-	g_print ("*** %s\n", __func__);
         GdaServerOperationType optype;
 
 	/* If asynchronous connection opening is not supported, then exit now */
@@ -848,7 +834,6 @@
 				      GdaTransactionIsolation   level,
 				      GError                  **error)
 {
-	g_print ("*** %s\n", __func__);
 	MysqlConnectionData *cdata;
 
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
@@ -872,7 +857,6 @@
 				       const gchar        *name,
 				       GError            **error)
 {
-	g_print ("*** %s\n", __func__);
 	MysqlConnectionData *cdata;
 
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
@@ -896,7 +880,6 @@
 					 const gchar        *name,
 					 GError            **error)
 {
-	g_print ("*** %s\n", __func__);
 	MysqlConnectionData *cdata;
 
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
@@ -920,7 +903,6 @@
 				  const gchar        *name,
 				  GError            **error)
 {
-	g_print ("*** %s\n", __func__);
 	MysqlConnectionData *cdata;
 
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
@@ -944,7 +926,6 @@
 				       const gchar        *name,
 				       GError            **error)
 {
-	g_print ("*** %s\n", __func__);
 	MysqlConnectionData *cdata;
 
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
@@ -968,7 +949,6 @@
 				     const gchar        *name,
 				     GError            **error)
 {
-	g_print ("*** %s\n", __func__);
 	MysqlConnectionData *cdata;
 
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
@@ -991,7 +971,6 @@
 				     GdaConnection         *cnc,
 				     GdaConnectionFeature   feature)
 {
-	g_print ("*** %s\n", __func__);
 	if (cnc) {
 		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
 		g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, FALSE);
@@ -1026,7 +1005,6 @@
 				     GType               type,
 				     const gchar        *dbms_type)
 {
-	g_print ("*** %s\n", __func__);
 	GdaDataHandler *dh;
 	if (cnc) {
 		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
@@ -1064,7 +1042,6 @@
 					  GdaConnection      *cnc,
 					  GType               type)
 {
-	g_print ("*** %s\n", __func__);
 	if (cnc) {
 		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
 		g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, FALSE);
@@ -1125,7 +1102,6 @@
 gda_mysql_provider_create_parser (GdaServerProvider  *provider,
 				  GdaConnection      *cnc)
 {
-	g_print ("*** %s\n", __func__);
 	// TO_IMPLEMENT;
 	return (GdaSqlParser *) g_object_new (GDA_TYPE_MYSQL_PARSER,
 					      "tokenizer-flavour", GDA_SQL_PARSER_FLAVOUR_MYSQL,
@@ -1150,7 +1126,6 @@
 				     GSList              **params_used,
 				     GError              **error)
 {
-	g_print ("*** %s\n", __func__);
 	g_return_val_if_fail (GDA_IS_STATEMENT (stmt), NULL);
 	if (cnc) {
 		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
@@ -1173,7 +1148,6 @@
 				      GdaStatement       *stmt,
 				      GError            **error)
 {
-	g_print ("*** %s\n", __func__);
 	GdaMysqlPStmt *ps;
 	MysqlConnectionData *cdata;
 
@@ -1308,7 +1282,6 @@
 				      gpointer                         cb_data,
 				      GError                         **error)
 {
-	g_print ("*** %s\n", __func__);
 	GdaMysqlPStmt *ps;
 	MysqlConnectionData *cdata;
 
@@ -1356,9 +1329,9 @@
 	/* optionnally reset the prepared statement if required by the API */
 	// TO_IMPLEMENT;
 	
-	//
+	
 	g_print ("   %s: SQL=%s\n", __func__, _GDA_PSTMT(ps)->sql);
-	//
+	
 	/* bind statement's parameters */
 	GSList *list;
 	GdaConnectionEvent *event = NULL;
@@ -1413,13 +1386,13 @@
 		} else if ((G_VALUE_TYPE(value) == G_TYPE_DATE) ||
 			   (G_VALUE_TYPE(value) == GDA_TYPE_TIME) ||
 			   (G_VALUE_TYPE(value) == GDA_TYPE_TIMESTAMP)) {
-			//
+			
 			GdaHandlerTime *handler_time = (GdaHandlerTime *) gda_server_provider_get_data_handler_gtype
 				(provider, cnc, G_VALUE_TYPE(value));
 			g_assert (handler_time);
 			param_values[i] = gda_handler_time_get_no_locale_str_from_value (handler_time,
 											 value);
-			//
+			
 			g_print ("--- TIME=%s\n", param_values[i]);
 		} else {
 			GdaDataHandler *data_handler = gda_server_provider_get_data_handler_gtype
@@ -1437,11 +1410,11 @@
 			mysql_bind_param[i].length = g_malloc0 (sizeof(unsigned long));
 
 		}
-		//
+		
 		gchar *str = gda_value_stringify (value);
 		g_print ("   %s: %s=%s\n", __func__, pname, str);
 		g_free (str);
-		//
+		
 
 	}
 		
@@ -1533,7 +1506,6 @@
 			     const GdaXaTransactionId  *xid,
 			     GError                   **error)
 {
-	g_print ("*** %s\n", __func__);
 	MysqlConnectionData *cdata;
 
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
@@ -1558,7 +1530,6 @@
 			   const GdaXaTransactionId  *xid,
 			   GError                   **error)
 {
-	g_print ("*** %s\n", __func__);
 	MysqlConnectionData *cdata;
 
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
@@ -1582,7 +1553,6 @@
 			       const GdaXaTransactionId  *xid,
 			       GError                   **error)
 {
-	g_print ("*** %s\n", __func__);
 	MysqlConnectionData *cdata;
 
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
@@ -1607,7 +1577,6 @@
 			      const GdaXaTransactionId  *xid,
 			      GError                   **error)
 {
-	g_print ("*** %s\n", __func__);
 	MysqlConnectionData *cdata;
 
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
@@ -1631,7 +1600,6 @@
 				const GdaXaTransactionId  *xid,
 				GError                   **error)
 {
-	g_print ("*** %s\n", __func__);
 	MysqlConnectionData *cdata;
 
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
@@ -1656,7 +1624,6 @@
 			       GdaConnection      *cnc,
 			       GError            **error)
 {
-	g_print ("*** %s\n", __func__);
 	MysqlConnectionData *cdata;
 
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
@@ -1676,7 +1643,6 @@
 static void
 gda_mysql_free_cnc_data (MysqlConnectionData  *cdata)
 {
-	g_print ("*** %s\n", __func__);
 	if (!cdata)
 		return;
 

Modified: trunk/providers/mysql/gda-mysql-pstmt.c
==============================================================================
--- trunk/providers/mysql/gda-mysql-pstmt.c	(original)
+++ trunk/providers/mysql/gda-mysql-pstmt.c	Thu Jun 19 20:40:28 2008
@@ -65,7 +65,6 @@
 static void 
 gda_mysql_pstmt_class_init (GdaMysqlPStmtClass  *klass)
 {
-	g_print ("*** %s\n", __func__);
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 	parent_class = g_type_class_peek_parent (klass);
 
@@ -77,28 +76,26 @@
 gda_mysql_pstmt_init (GdaMysqlPStmt       *pstmt,
 		      GdaMysqlPStmtClass  *klass)
 {
-	g_print ("*** %s\n", __func__);
 	g_return_if_fail (GDA_IS_PSTMT (pstmt));
 	
 	/* initialize specific parts of @pstmt */
 	// TO_IMPLEMENT;
-	//
+	
 	pstmt->mysql_bind_param = NULL;
 	pstmt->mysql_bind_result = NULL;
-	//
+	
 }
 
 static void
 gda_mysql_pstmt_finalize (GObject  *object)
 {
-	g_print ("*** %s\n", __func__);
 	GdaMysqlPStmt *pstmt = (GdaMysqlPStmt *) object;
 
 	g_return_if_fail (GDA_IS_PSTMT (pstmt));
 
 	/* free memory */
 	// TO_IMPLEMENT; /* free some specific parts of @pstmt */
-	//
+	
 	gint i;
 	for (i = 0; i < g_slist_length (((GdaPStmt *) pstmt)->param_ids); ++i) {
 		g_free (pstmt->mysql_bind_param[i].buffer);
@@ -114,7 +111,7 @@
 	}
 	g_free (pstmt->mysql_bind_result);
 	pstmt->mysql_bind_result = NULL;
-	//
+	
 
 	/* chain to parent class */
 	parent_class->finalize (object);

Modified: trunk/providers/mysql/gda-mysql-recordset.c
==============================================================================
--- trunk/providers/mysql/gda-mysql-recordset.c	(original)
+++ trunk/providers/mysql/gda-mysql-recordset.c	Thu Jun 19 20:40:28 2008
@@ -97,7 +97,6 @@
 gda_mysql_recordset_init (GdaMysqlRecordset       *recset,
 			  GdaMysqlRecordsetClass  *klass)
 {
-	g_print ("*** %s\n", __func__);
 	g_return_if_fail (GDA_IS_MYSQL_RECORDSET (recset));
 	recset->priv = g_new0 (GdaMysqlRecordsetPrivate, 1);
 	recset->priv->cnc = NULL;
@@ -166,7 +165,6 @@
 static void
 gda_mysql_recordset_class_init (GdaMysqlRecordsetClass  *klass)
 {
-	g_print ("*** %s\n", __func__);
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 	GdaPModelClass *pmodel_class = GDA_PMODEL_CLASS (klass);
 
@@ -205,7 +203,6 @@
 static void
 gda_mysql_recordset_dispose (GObject  *object)
 {
-	g_print ("*** %s\n", __func__);
 	GdaMysqlRecordset *recset = (GdaMysqlRecordset *) object;
 
 	g_return_if_fail (GDA_IS_MYSQL_RECORDSET (recset));
@@ -261,7 +258,6 @@
 			 GdaDataModelAccessFlags   flags,
 			 GType                    *col_types)
 {
-	g_print ("*** %s\n", __func__);
 	GdaMysqlRecordset *model;
         MysqlConnectionData *cdata;
         gint i;
@@ -326,7 +322,6 @@
 			// TO_IMPLEMENT;
 			
 			MYSQL_FIELD *field = &mysql_fields[i];
-			/* g_print ("*** %s , %d\n", */
 			/* 	 field->name, field->type); */
 			GType gtype = _GDA_PSTMT(ps)->types[i];
 			if (gtype == 0) {
@@ -440,7 +435,6 @@
 static gint
 gda_mysql_recordset_fetch_nb_rows (GdaPModel *model)
 {
-	g_print ("*** %s\n", __func__);
 	GdaMysqlRecordset *imodel;
 
 	imodel = GDA_MYSQL_RECORDSET (model);
@@ -461,8 +455,7 @@
 new_row_from_mysql_stmt (GdaMysqlRecordset  *imodel,
 			 gint                rownum)
 {
-	g_print ("*** %s -- %d -- %d\n", __func__,
-		 ((GdaPModel *) imodel)->prep_stmt->ncols, rownum);
+	g_print ("*** %s -- %d -- %d\n", __func__, ((GdaPModel *) imodel)->prep_stmt->ncols, rownum);
 	
 	MYSQL_BIND *mysql_bind_result = ((GdaMysqlPStmt *) ((GdaPModel *) imodel)->prep_stmt)->mysql_bind_result;
 	g_assert (mysql_bind_result);
@@ -510,7 +503,8 @@
 			g_memmove (&is_null, mysql_bind_result[i].is_null, sizeof(my_bool));
 			break;
 		case MYSQL_TYPE_NULL:
-			g_value_unset (value);
+			if (G_IS_VALUE(value))
+				g_value_unset (value);
 			break;
 		case MYSQL_TYPE_TIME:
 		case MYSQL_TYPE_DATE:
@@ -575,7 +569,7 @@
 		case MYSQL_TYPE_NEWDECIMAL:
 		case MYSQL_TYPE_BIT:
 			g_memmove (&length, mysql_bind_result[i].length, sizeof(unsigned long));
-			strvalue = g_memdup (mysql_bind_result[i].buffer, length + 1);
+			strvalue = length ? g_memdup (mysql_bind_result[i].buffer, length + 1) : NULL;
 			
 			if (type == G_TYPE_STRING)
 				g_value_set_string (value, strvalue);
@@ -586,10 +580,11 @@
 				};
 				gda_value_set_binary (value, &binary);
 			} else if (type == GDA_TYPE_BLOB) {
-				GdaBlob *blob = (GdaBlob *) gda_value_new_blob
-					((const guchar *) strvalue, (gulong) length);
-				gda_value_take_blob (value, blob);
-				gda_value_free ((GValue *) blob);
+				GdaBinary binary = {
+					.data = strvalue,
+					.binary_length = length
+				};
+				gda_value_set_binary (value, &binary);
 			} else if (type == G_TYPE_DOUBLE) {
 				setlocale (LC_NUMERIC, "C");
 				g_value_set_double (value, atof (strvalue));
@@ -604,10 +599,12 @@
 			g_warning (_("Invalid column bind data type. %d\n"),
 				   mysql_bind_result[i].buffer_type);
 		}
-		//
-		gchar *str = gda_value_stringify (value);
-		g_print ("   V=%s, %d\n", str, is_null);
-		g_free (str);
+
+		g_free (strvalue);
+		
+		/* gchar *str = gda_value_stringify (value); */
+		/* g_print ("   V%d=%s\n", i, str); */
+		/* g_free (str); */
 		//		
 	}
 	return prow;
@@ -635,7 +632,6 @@
 				  gint        rownum,
 				  GError    **error)
 {
-	g_print ("*** %s\n", __func__);
 	GdaMysqlRecordset *imodel;
 
 	imodel = GDA_MYSQL_RECORDSET (model);
@@ -672,7 +668,6 @@
 static gboolean
 gda_mysql_recordset_store_all (GdaPModel *model, GError **error)
 {
-	g_print ("*** %s\n", __func__);
 	GdaMysqlRecordset *imodel;
 	gint i;
 
@@ -702,7 +697,6 @@
 static gboolean 
 gda_mysql_recordset_fetch_next (GdaPModel *model, GdaPRow **prow, gint rownum, GError **error)
 {
-	g_print ("*** %s\n", __func__);
 	GdaMysqlRecordset *imodel = (GdaMysqlRecordset*) model;
 
 	TO_IMPLEMENT;
@@ -725,7 +719,6 @@
 static gboolean 
 gda_mysql_recordset_fetch_prev (GdaPModel *model, GdaPRow **prow, gint rownum, GError **error)
 {
-	g_print ("*** %s\n", __func__);
 	GdaMysqlRecordset *imodel = (GdaMysqlRecordset*) model;
 
 	TO_IMPLEMENT;
@@ -748,7 +741,6 @@
 static gboolean 
 gda_mysql_recordset_fetch_at (GdaPModel *model, GdaPRow **prow, gint rownum, GError **error)
 {
-	g_print ("*** %s\n", __func__);
 	GdaMysqlRecordset *imodel = (GdaMysqlRecordset*) model;
 	
 	TO_IMPLEMENT;

Modified: trunk/providers/mysql/gda-mysql-util.c
==============================================================================
--- trunk/providers/mysql/gda-mysql-util.c	(original)
+++ trunk/providers/mysql/gda-mysql-util.c	Thu Jun 19 20:40:28 2008
@@ -115,9 +115,9 @@
 			(event_error, mysql_errno (mysql));
 		g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_STATEMENT_EXEC_ERROR,
 			     mysql_sqlstate (mysql));
-		//
+		
 		g_print ("%s: %s\n", __func__, mysql_error (mysql));
-		//
+		
 	} else if (mysql_stmt) {
 		gda_connection_event_set_description
 			(event_error, mysql_stmt_error (mysql_stmt));
@@ -125,9 +125,9 @@
 			(event_error, mysql_stmt_errno (mysql_stmt));
 		g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_STATEMENT_EXEC_ERROR,
 			     mysql_stmt_sqlstate (mysql_stmt));
-		//
+		
 		g_print ("%s: %s\n", __func__, mysql_stmt_error (mysql_stmt));
-		//
+		
 	} else {
 		gda_connection_event_set_description
 			(event_error, _("No description"));



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