libgda r3122 - in trunk: . providers providers/mysql



Author: vivien
Date: Sun Apr  6 17:06:43 2008
New Revision: 3122
URL: http://svn.gnome.org/viewvc/libgda?rev=3122&view=rev

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

	* configure.in:
	* providers/Makefile.am:
	* providers/mysql/*: merged Carlos Savoretti's preliminary MySQL provider's
	rework


Added:
   trunk/providers/mysql/gda-mysql-blob-op.c
   trunk/providers/mysql/gda-mysql-blob-op.h
   trunk/providers/mysql/gda-mysql-meta.c
   trunk/providers/mysql/gda-mysql-meta.h
   trunk/providers/mysql/gda-mysql-parser.c
   trunk/providers/mysql/gda-mysql-parser.h
   trunk/providers/mysql/gda-mysql-pstmt.c
   trunk/providers/mysql/gda-mysql-pstmt.h
   trunk/providers/mysql/gda-mysql-util.c
   trunk/providers/mysql/gda-mysql-util.h
   trunk/providers/mysql/gen_def.c
   trunk/providers/mysql/parser.y
Modified:
   trunk/ChangeLog
   trunk/configure.in
   trunk/providers/Makefile.am
   trunk/providers/mysql/   (props changed)
   trunk/providers/mysql/Makefile.am
   trunk/providers/mysql/gda-mysql-provider.c
   trunk/providers/mysql/gda-mysql-provider.h
   trunk/providers/mysql/gda-mysql-recordset.c
   trunk/providers/mysql/gda-mysql-recordset.h
   trunk/providers/mysql/gda-mysql.h
   trunk/providers/mysql/libgda-mysql-4.0.pc.in
   trunk/providers/mysql/libmain.c

Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in	(original)
+++ trunk/configure.in	Sun Apr  6 17:06:43 2008
@@ -1190,6 +1190,8 @@
 providers/bdb/libgda-bdb-4.0.pc
 providers/mdb/Makefile
 providers/mdb/libgda-mdb-4.0.pc
+providers/mysql/Makefile
+providers/mysql/libgda-mysql-4.0.pc
 providers/postgres/Makefile
 providers/postgres/libgda-postgres-4.0.pc
 providers/sqlite/Makefile
@@ -1232,7 +1234,7 @@
 dnl echo "      FreeTDS = `if test x$freetdsdir != x; then echo yes; else echo no; fi`"
 dnl echo "      IBM DB2 = `if test x$ibmdb2dir != x; then echo yes; else echo no; fi`"
 echo "      MDB (MS Access) = `if test x$mdbdir != x; then echo yes; else echo no; fi`"
-dnl echo "      MySQL = `if test x$mysqldir != x; then echo yes; else echo no; fi`"
+echo "      MySQL = `if test x$mysqldir != x; then echo yes; else echo no; fi`"
 dnl echo "      mSQL = `if test x$msqldir != x; then echo yes; else echo no; fi`"
 dnl echo "      ODBC = `if test x$odbcdir != x; then echo yes; else echo no; fi`"
 dnl echo "      Oracle = `if test x$oracledir != x; then echo yes; else echo no; fi`"

Modified: trunk/providers/Makefile.am
==============================================================================
--- trunk/providers/Makefile.am	(original)
+++ trunk/providers/Makefile.am	Sun Apr  6 17:06:43 2008
@@ -55,11 +55,11 @@
 	skel-implementation \
 	$(GDA_BDB_SERVER) \
 	$(GDA_MDB_SERVER) \
-	$(GDA_POSTGRES_SERVER)
+	$(GDA_POSTGRES_SERVER) \
+	$(GDA_MYSQL_SERVER)
 #	$(GDA_FREETDS_SERVER) \
 #	$(GDA_IBMDB2_SERVER) \
 #	$(GDA_FIREBIRD_SERVER) \
-#	$(GDA_MYSQL_SERVER) \
 #       $(GDA_MSQL_SERVER) \
 #	$(GDA_ODBC_SERVER) \
 #	$(GDA_ORACLE_SERVER) \

Modified: trunk/providers/mysql/Makefile.am
==============================================================================
--- trunk/providers/mysql/Makefile.am	(original)
+++ trunk/providers/mysql/Makefile.am	Sun Apr  6 17:06:43 2008
@@ -1,29 +1,54 @@
 providerdir=$(libdir)/libgda-$(GDA_ABI_MAJOR_VERSION).$(GDA_ABI_MINOR_VERSION)/providers
 provider_LTLIBRARIES = libgda-mysql.la
 
+#Rem: MYSQL_CFLAGS and MYSQL_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) \
-	$(MYSQL_CFLAGS) \
-	-DGDA_PACKAGE_VERSION=\""$(PACKAGE_VERSION)"\"
+	$(LIBGDA_CFLAGS) $(MYSQL_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) parser.y
+
+gen_def$(EXEEXT_FOR_BUILD): gen_def.c
+	$(CC_FOR_BUILD) -o gen_def$(EXEEXT_FOR_BUILD) -DIMPOSED_HEADER=\""$(top_builddir)/libgda/sql-parser/parser_tokens.h"\" gen_def.c
+
+mysql_token_types.h: gen_def$(EXEEXT_FOR_BUILD) parser.h
+	./gen_def$(EXEEXT_FOR_BUILD) > mysql_token_types.h
+
+$(OBJECTS) $(libgda_mysql_la_OBJECTS): mysql_token_types.h
 
 libgda_mysql_la_SOURCES = \
+	gda-mysql-blob-op.c \
+	gda-mysql-blob-op.h \
 	gda-mysql-ddl.c \
-        gda-mysql-ddl.h \
+	gda-mysql-ddl.h \
+	gda-mysql-parser.c \
+	gda-mysql-parser.h \
 	gda-mysql-provider.c \
 	gda-mysql-provider.h \
+	gda-mysql-meta.c \
+	gda-mysql-meta.h \
 	gda-mysql-recordset.c \
 	gda-mysql-recordset.h \
+	gda-mysql-util.c \
+	gda-mysql-util.h \
+	gda-mysql-pstmt.c \
+	gda-mysql-pstmt.h \
 	gda-mysql.h \
 	libmain.c \
-	utils.c
+	parser.h \
+        parser.c \
+        mysql_token_types.h
+
 libgda_mysql_la_LDFLAGS = -export-dynamic -module -avoid-version $(NO_UNDEFINED)
 libgda_mysql_la_LIBADD = \
 	$(top_builddir)/libgda/libgda-4.0.la \
-	$(LIBGDA_LIBS) \
-	$(MYSQL_LIBS)
+	$(LIBGDA_LIBS) $(MYSQL_LIBS)
 
 xmldir   = $(datadir)/libgda-4.0
 xml_in_files = \
@@ -47,5 +72,7 @@
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libgda-mysql-4.0.pc
 
-EXTRA_DIST = $(xml_in_files) libgda-mysql-4.0.pc.in
+EXTRA_DIST = $(xml_in_files) libgda-mysql-4.0.pc.in parser.y
 DISTCLEANFILES = $(xml_DATA)
+
+CLEANFILES = parser.h parser.c parser.out mysql_token_types.h gen_def$(EXEEXT_FOR_BUILD)

Added: trunk/providers/mysql/gda-mysql-blob-op.c
==============================================================================
--- (empty file)
+++ trunk/providers/mysql/gda-mysql-blob-op.c	Sun Apr  6 17:06:43 2008
@@ -0,0 +1,198 @@
+/* GDA Mysql provider
+ * Copyright (C) 2008 The GNOME Foundation
+ *
+ * AUTHORS:
+ *      TO_ADD: your name and email
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <glib/gi18n-lib.h>
+#include <string.h>
+#include <libgda/libgda.h>
+#include "gda-mysql.h"
+#include "gda-mysql-blob-op.h"
+
+struct _GdaMysqlBlobOpPrivate {
+	GdaConnection *cnc;
+	/* TO_ADD: specific information describing a Blob in the C API */
+};
+
+static void gda_mysql_blob_op_class_init (GdaMysqlBlobOpClass *klass);
+static void gda_mysql_blob_op_init       (GdaMysqlBlobOp *blob,
+					 GdaMysqlBlobOpClass *klass);
+static void gda_mysql_blob_op_finalize   (GObject *object);
+
+static glong gda_mysql_blob_op_get_length (GdaBlobOp *op);
+static glong gda_mysql_blob_op_read       (GdaBlobOp *op, GdaBlob *blob, glong offset, glong size);
+static glong gda_mysql_blob_op_write      (GdaBlobOp *op, GdaBlob *blob, glong offset);
+
+static GObjectClass *parent_class = NULL;
+
+/*
+ * Object init and finalize
+ */
+GType
+gda_mysql_blob_op_get_type (void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY (type == 0)) {
+		static const GTypeInfo info = {
+			sizeof (GdaMysqlBlobOpClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) gda_mysql_blob_op_class_init,
+			NULL,
+			NULL,
+			sizeof (GdaMysqlBlobOp),
+			0,
+			(GInstanceInitFunc) gda_mysql_blob_op_init
+		};
+		type = g_type_register_static (GDA_TYPE_BLOB_OP, "GdaMysqlBlobOp", &info, 0);
+	}
+	return type;
+}
+
+static void
+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);
+
+	/* initialize specific structure */
+	TO_IMPLEMENT;
+}
+
+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);
+
+	parent_class = g_type_class_peek_parent (klass);
+
+	object_class->finalize = gda_mysql_blob_op_finalize;
+	blob_class->get_length = gda_mysql_blob_op_get_length;
+	blob_class->read = gda_mysql_blob_op_read;
+	blob_class->write = gda_mysql_blob_op_write;
+}
+
+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));
+
+	/* free specific information */
+	TO_IMPLEMENT;
+
+	g_free (pgop->priv);
+	pgop->priv = NULL;
+
+	parent_class->finalize (object);
+}
+
+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);
+
+	pgop = g_object_new (GDA_TYPE_MYSQL_BLOB_OP, NULL);
+	pgop->priv->cnc = cnc;
+	
+	return GDA_BLOB_OP (pgop);
+}
+
+/*
+ * Get length request
+ */
+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);
+	pgop = GDA_MYSQL_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;
+}
+
+/*
+ * Blob read request
+ */
+static glong
+gda_mysql_blob_op_read (GdaBlobOp *op, GdaBlob *blob, glong offset, glong size)
+{
+	g_print ("*** %s\n", __func__);
+	GdaMysqlBlobOp *pgop;
+	GdaBinary *bin;
+
+	g_return_val_if_fail (GDA_IS_MYSQL_BLOB_OP (op), -1);
+	pgop = GDA_MYSQL_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);
+
+	bin = (GdaBinary *) blob;
+	if (bin->data) 
+		g_free (bin->data);
+	bin->data = g_new0 (gchar, size);
+	bin->binary_length = 0;
+
+	/* fetch blob data using C API into bin->data, and set bin->binary_length */
+	TO_IMPLEMENT;
+
+	return bin->binary_length;
+}
+
+/*
+ * Blob write request
+ */
+static glong
+gda_mysql_blob_op_write (GdaBlobOp *op, GdaBlob *blob, glong offset)
+{
+	g_print ("*** %s\n", __func__);
+	GdaMysqlBlobOp *pgop;
+	GdaBinary *bin;
+
+	g_return_val_if_fail (GDA_IS_MYSQL_BLOB_OP (op), -1);
+	pgop = GDA_MYSQL_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);
+
+	/* write blob using bin->data and bin->binary_length */
+	bin = (GdaBinary *) blob;
+	TO_IMPLEMENT;
+
+	return -1;
+}

Added: trunk/providers/mysql/gda-mysql-blob-op.h
==============================================================================
--- (empty file)
+++ trunk/providers/mysql/gda-mysql-blob-op.h	Sun Apr  6 17:06:43 2008
@@ -0,0 +1,57 @@
+/* GDA Mysql provider
+ * Copyright (C) 2008 The GNOME Foundation
+ *
+ * AUTHORS:
+ *      TO_ADD: your name and email
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GDA_MYSQL_BLOB_OP_H__
+#define __GDA_MYSQL_BLOB_OP_H__
+
+#include <libgda/gda-blob-op.h>
+
+G_BEGIN_DECLS
+
+#define GDA_TYPE_MYSQL_BLOB_OP            (gda_mysql_blob_op_get_type())
+#define GDA_MYSQL_BLOB_OP(obj)            (G_TYPE_CHECK_INSTANCE_CAST (obj, GDA_TYPE_MYSQL_BLOB_OP, GdaMysqlBlobOp))
+#define GDA_MYSQL_BLOB_OP_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST (klass, GDA_TYPE_MYSQL_BLOB_OP, GdaMysqlBlobOpClass))
+#define GDA_IS_MYSQL_BLOB_OP(obj)         (G_TYPE_CHECK_INSTANCE_TYPE (obj, GDA_TYPE_MYSQL_BLOB_OP))
+#define GDA_IS_MYSQL_BLOB_OP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDA_TYPE_MYSQL_BLOB_OP))
+
+typedef struct _GdaMysqlBlobOp        GdaMysqlBlobOp;
+typedef struct _GdaMysqlBlobOpClass   GdaMysqlBlobOpClass;
+typedef struct _GdaMysqlBlobOpPrivate GdaMysqlBlobOpPrivate;
+
+struct _GdaMysqlBlobOp {
+	GdaBlobOp             parent;
+	GdaMysqlBlobOpPrivate *priv;
+};
+
+struct _GdaMysqlBlobOpClass {
+	GdaBlobOpClass        parent_class;
+};
+
+GType         gda_mysql_blob_op_get_type     (void) G_GNUC_CONST;
+GdaBlobOp    *gda_mysql_blob_op_new          (GdaConnection *cnc);
+
+/* TO_ADD: more convenient API to create a GdaBlobOp with some specific information as argument */
+
+G_END_DECLS
+
+#endif
+

Added: trunk/providers/mysql/gda-mysql-meta.c
==============================================================================
--- (empty file)
+++ trunk/providers/mysql/gda-mysql-meta.c	Sun Apr  6 17:06:43 2008
@@ -0,0 +1,494 @@
+/* GDA mysql provider
+ * Copyright (C) 2008 The GNOME Foundation.
+ *
+ * AUTHORS:
+ *      Carlos Savoretti <csavoretti gmail com>
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include "gda-mysql.h"
+#include "gda-mysql-meta.h"
+#include "gda-mysql-provider.h"
+#include <libgda/gda-meta-store.h>
+#include <libgda/sql-parser/gda-sql-parser.h>
+#include <glib/gi18n-lib.h>
+#include <libgda/gda-server-provider-extra.h>
+#include <libgda/gda-connection-private.h>
+#include <libgda/gda-data-model-array.h>
+#include <libgda/gda-set.h>
+#include <libgda/gda-holder.h>
+
+static gboolean append_a_row (GdaDataModel *to_model, GError **error, gint nb, ...);
+
+/*
+ * predefined statements' IDs
+ */
+typedef enum {
+	I_STMT_CATALOG,
+        I_STMT_BTYPES,
+} InternalStatementItem;
+
+
+/*
+ * predefined statements' SQL
+ */
+static gchar *internal_sql[] = {
+	/* I_STMT_CATALOG */
+        "SELECT database()",
+
+        /* I_STMT_BTYPES */
+        "SELECT DISTINCT data_type, CONCAT(table_schema, '.', data_type),  CASE data_type WHEN 'bigint' THEN 'gint' 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"
+};
+
+/*
+ * predefined statements' GdaStatement
+ */
+static GdaStatement **internal_stmt;
+static GdaSet        *i_set;
+
+/* 
+ * global static values
+ */
+static GdaSqlParser *internal_parser = NULL;
+/* TO_ADD: other static values */
+
+
+/*
+ * Meta initialization
+ */
+void
+_gda_mysql_provider_meta_init (GdaServerProvider *provider)
+{
+	InternalStatementItem i;
+
+        internal_parser = gda_server_provider_internal_get_parser (provider);
+
+        internal_stmt = g_new0 (GdaStatement *, sizeof (internal_sql) / sizeof (gchar*));
+        for (i = I_STMT_CATALOG; i < sizeof (internal_sql) / sizeof (gchar*); i++) {
+                internal_stmt[i] = gda_sql_parser_parse_string (internal_parser, internal_sql[i], NULL, NULL);
+                if (!internal_stmt[i])
+                        g_error ("Could not parse internal statement: %s\n", internal_sql[i]);
+        }
+
+	/* initialize static values here */
+	i_set = gda_set_new_inline (3, "cat", G_TYPE_STRING, "", 
+				    "name", G_TYPE_STRING, "",
+				    "schema", G_TYPE_STRING, "");
+}
+
+gboolean
+_gda_mysql_meta__info (GdaServerProvider *prov, GdaConnection *cnc, 
+		      GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	GdaDataModel *model;
+        gboolean retval;
+
+        model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_CATALOG], NULL, error);
+        if (!model)
+                return FALSE;
+
+        retval = gda_meta_store_modify (store, context->table_name, model, NULL, error, NULL);
+        g_object_unref (model);
+
+        return retval;
+}
+
+gboolean
+_gda_mysql_meta__btypes (GdaServerProvider *prov, GdaConnection *cnc, 
+			GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	g_print ("*** %s\n", __func__);
+        GdaDataModel *model;
+        gboolean retval = TRUE;
+	GType col_types[] = {
+                G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+                G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_NONE
+        };
+	model = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_BTYPES], NULL,
+                                                              GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types, error);
+        if (!model)
+                return FALSE;
+
+        if (retval)
+                retval = gda_meta_store_modify (store, context->table_name, model, NULL, error, NULL);
+        g_object_unref (G_OBJECT(model));
+
+        return retval;
+}
+
+gboolean
+_gda_mysql_meta__udt (GdaServerProvider *prov, GdaConnection *cnc, 
+		     GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta_udt (GdaServerProvider *prov, GdaConnection *cnc, 
+		    GdaMetaStore *store, GdaMetaContext *context, GError **error,
+		    const GValue *udt_catalog, const GValue *udt_schema)
+{
+	GdaDataModel *model;
+	gboolean retval = TRUE;
+
+	/* set internal holder's values from the arguments */
+	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);
+
+	TO_IMPLEMENT;
+	/* fill in @model, with something like:
+	 * model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_UDT], i_set, error);
+	 */
+	if (!model)
+		return FALSE;
+	retval = gda_meta_store_modify_with_context (store, context, model, error);
+	g_object_unref (model);
+
+	return retval;
+}
+
+
+gboolean
+_gda_mysql_meta__udt_cols (GdaServerProvider *prov, GdaConnection *cnc, 
+			  GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;	
+}
+
+gboolean
+_gda_mysql_meta_udt_cols (GdaServerProvider *prov, GdaConnection *cnc, 
+			 GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			 const GValue *udt_catalog, const GValue *udt_schema, const GValue *udt_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;	
+}
+
+gboolean
+_gda_mysql_meta__enums (GdaServerProvider *prov, GdaConnection *cnc, 
+		       GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;	
+}
+
+gboolean
+_gda_mysql_meta_enums (GdaServerProvider *prov, GdaConnection *cnc, 
+		      GdaMetaStore *store, GdaMetaContext *context, GError **error,
+		      const GValue *udt_catalog, const GValue *udt_schema, const GValue *udt_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+
+gboolean
+_gda_mysql_meta__domains (GdaServerProvider *prov, GdaConnection *cnc, 
+			 GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta_domains (GdaServerProvider *prov, GdaConnection *cnc, 
+			GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			const GValue *domain_catalog, const GValue *domain_schema)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta__constraints_dom (GdaServerProvider *prov, GdaConnection *cnc, 
+				 GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta_constraints_dom (GdaServerProvider *prov, GdaConnection *cnc, 
+				GdaMetaStore *store, GdaMetaContext *context, GError **error,
+				const GValue *domain_catalog, const GValue *domain_schema, 
+				const GValue *domain_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta__el_types (GdaServerProvider *prov, GdaConnection *cnc, 
+			  GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta__collations (GdaServerProvider *prov, GdaConnection *cnc, 
+			    GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta_collations (GdaServerProvider *prov, GdaConnection *cnc, 
+			   GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			   const GValue *collation_catalog, const GValue *collation_schema, 
+			   const GValue *collation_name_n)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta__character_sets (GdaServerProvider *prov, GdaConnection *cnc, 
+				GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta_character_sets (GdaServerProvider *prov, GdaConnection *cnc, 
+			       GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			       const GValue *chset_catalog, const GValue *chset_schema, 
+			       const GValue *chset_name_n)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta__schemata (GdaServerProvider *prov, GdaConnection *cnc, 
+			  GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta_schemata (GdaServerProvider *prov, GdaConnection *cnc, 
+			 GdaMetaStore *store, GdaMetaContext *context, GError **error, 
+			 const GValue *catalog_name, const GValue *schema_name_n)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta__tables_views (GdaServerProvider *prov, GdaConnection *cnc, 
+			      GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta_tables_views (GdaServerProvider *prov, GdaConnection *cnc, 
+			     GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			     const GValue *table_catalog, const GValue *table_schema, 
+			     const GValue *table_name_n)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta__columns (GdaServerProvider *prov, GdaConnection *cnc, 
+			 GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta_columns (GdaServerProvider *prov, GdaConnection *cnc, 
+			GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			const GValue *table_catalog, const GValue *table_schema, 
+			const GValue *table_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta__view_cols (GdaServerProvider *prov, GdaConnection *cnc, 
+			   GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta_view_cols (GdaServerProvider *prov, GdaConnection *cnc, 
+			  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			  const GValue *view_catalog, const GValue *view_schema, 
+			  const GValue *view_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta__constraints_tab (GdaServerProvider *prov, GdaConnection *cnc, 
+				 GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta_constraints_tab (GdaServerProvider *prov, GdaConnection *cnc, 
+				GdaMetaStore *store, GdaMetaContext *context, GError **error, 
+				const GValue *table_catalog, const GValue *table_schema, 
+				const GValue *table_name, const GValue *constraint_name_n)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta__constraints_ref (GdaServerProvider *prov, GdaConnection *cnc, 
+				 GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta_constraints_ref (GdaServerProvider *prov, GdaConnection *cnc, 
+				GdaMetaStore *store, GdaMetaContext *context, GError **error,
+				const GValue *table_catalog, const GValue *table_schema, const GValue *table_name, 
+				const GValue *constraint_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta__key_columns (GdaServerProvider *prov, GdaConnection *cnc, 
+			     GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta_key_columns (GdaServerProvider *prov, GdaConnection *cnc, 
+			    GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			    const GValue *table_catalog, const GValue *table_schema, 
+			    const GValue *table_name, const GValue *constraint_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta__check_columns (GdaServerProvider *prov, GdaConnection *cnc, 
+			       GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta_check_columns (GdaServerProvider *prov, GdaConnection *cnc, 
+			      GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			      const GValue *table_catalog, const GValue *table_schema, 
+			      const GValue *table_name, const GValue *constraint_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta__triggers (GdaServerProvider *prov, GdaConnection *cnc, 
+			  GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta_triggers (GdaServerProvider *prov, GdaConnection *cnc, 
+			 GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			 const GValue *table_catalog, const GValue *table_schema, 
+			 const GValue *table_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta__routines (GdaServerProvider *prov, GdaConnection *cnc, 
+			  GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta_routines (GdaServerProvider *prov, GdaConnection *cnc, 
+			 GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			 const GValue *routine_catalog, const GValue *routine_schema, 
+			 const GValue *routine_name_n)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta__routine_col (GdaServerProvider *prov, GdaConnection *cnc, 
+			     GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta_routine_col (GdaServerProvider *prov, GdaConnection *cnc, 
+			    GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			    const GValue *rout_catalog, const GValue *rout_schema, 
+			    const GValue *rout_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta__routine_par (GdaServerProvider *prov, GdaConnection *cnc, 
+			     GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_mysql_meta_routine_par (GdaServerProvider *prov, GdaConnection *cnc, 
+			    GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			    const GValue *rout_catalog, const GValue *rout_schema, 
+			    const GValue *rout_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}

Added: trunk/providers/mysql/gda-mysql-meta.h
==============================================================================
--- (empty file)
+++ trunk/providers/mysql/gda-mysql-meta.h	Sun Apr  6 17:06:43 2008
@@ -0,0 +1,194 @@
+/* GDA mysql provider
+ * Copyright (C) 2008 The GNOME Foundation.
+ *
+ * AUTHORS:
+ *      TO_ADD: your name and email
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __GDA_MYSQL_META_H__
+#define __GDA_MYSQL_META_H__
+
+#include <libgda/gda-server-provider.h>
+
+G_BEGIN_DECLS
+
+void     _gda_mysql_provider_meta_init    (GdaServerProvider *provider);
+
+/* _information_schema_catalog_name */
+gboolean _gda_mysql_meta__info            (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+
+/* _builtin_data_types */
+gboolean _gda_mysql_meta__btypes          (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+
+/* _udt */
+gboolean _gda_mysql_meta__udt             (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_mysql_meta_udt              (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *udt_catalog, const GValue *udt_schema);
+
+/* _udt_columns */
+gboolean _gda_mysql_meta__udt_cols        (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_mysql_meta_udt_cols         (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *udt_catalog, const GValue *udt_schema, const GValue *udt_name);
+
+/* _enums */
+gboolean _gda_mysql_meta__enums           (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_mysql_meta_enums            (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *udt_catalog, const GValue *udt_schema, const GValue *udt_name);
+
+/* _domains */
+gboolean _gda_mysql_meta__domains         (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_mysql_meta_domains          (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *domain_catalog, const GValue *domain_schema);
+
+/* _domain_constraints */
+gboolean _gda_mysql_meta__constraints_dom (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_mysql_meta_constraints_dom  (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *domain_catalog, const GValue *domain_schema, 
+					  const GValue *domain_name);
+
+/* _element_types */
+gboolean _gda_mysql_meta__el_types        (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+
+/* _collations */
+gboolean _gda_mysql_meta__collations      (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_mysql_meta_collations       (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *collation_catalog, const GValue *collation_schema, 
+					  const GValue *collation_name_n);
+
+/* _character_sets */
+gboolean _gda_mysql_meta__character_sets  (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_mysql_meta_character_sets   (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *chset_catalog, const GValue *chset_schema, 
+					  const GValue *chset_name_n);
+
+/* _schemata */
+gboolean _gda_mysql_meta__schemata        (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_mysql_meta_schemata         (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error, 
+					  const GValue *catalog_name, const GValue *schema_name_n);
+
+/* _tables or _views */
+gboolean _gda_mysql_meta__tables_views    (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_mysql_meta_tables_views     (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *table_catalog, const GValue *table_schema, 
+					  const GValue *table_name_n);
+
+/* _columns */
+gboolean _gda_mysql_meta__columns         (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_mysql_meta_columns          (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *table_catalog, const GValue *table_schema, 
+					  const GValue *table_name);
+
+/* _view_column_usage */
+gboolean _gda_mysql_meta__view_cols       (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_mysql_meta_view_cols        (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *view_catalog, const GValue *view_schema, 
+					  const GValue *view_name);
+
+/* _table_constraints */
+gboolean _gda_mysql_meta__constraints_tab (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_mysql_meta_constraints_tab  (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error, 
+					  const GValue *table_catalog, const GValue *table_schema, 
+					  const GValue *table_name, const GValue *constraint_name_n);
+
+/* _referential_constraints */
+gboolean _gda_mysql_meta__constraints_ref (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_mysql_meta_constraints_ref  (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *table_catalog, const GValue *table_schema, const GValue *table_name, 
+					  const GValue *constraint_name);
+
+/* _key_column_usage */
+gboolean _gda_mysql_meta__key_columns     (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_mysql_meta_key_columns      (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *table_catalog, const GValue *table_schema, 
+					  const GValue *table_name, const GValue *constraint_name);
+
+/* _check_column_usage */
+gboolean _gda_mysql_meta__check_columns   (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_mysql_meta_check_columns    (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *table_catalog, const GValue *table_schema, 
+					  const GValue *table_name, const GValue *constraint_name);
+
+/* _triggers */
+gboolean _gda_mysql_meta__triggers        (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_mysql_meta_triggers         (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *table_catalog, const GValue *table_schema, 
+					  const GValue *table_name);
+
+/* _routines */
+gboolean _gda_mysql_meta__routines       (GdaServerProvider *prov, GdaConnection *cnc, 
+					 GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_mysql_meta_routines        (GdaServerProvider *prov, GdaConnection *cnc, 
+					 GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					 const GValue *routine_catalog, const GValue *routine_schema, 
+					 const GValue *routine_name_n);
+
+/* _routine_columns */
+gboolean _gda_mysql_meta__routine_col     (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_mysql_meta_routine_col      (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *rout_catalog, const GValue *rout_schema, 
+					  const GValue *rout_name);
+
+/* _parameters */
+gboolean _gda_mysql_meta__routine_par     (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_mysql_meta_routine_par      (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *rout_catalog, const GValue *rout_schema, 
+					  const GValue *rout_name);
+
+
+G_END_DECLS
+
+#endif
+

Added: trunk/providers/mysql/gda-mysql-parser.c
==============================================================================
--- (empty file)
+++ trunk/providers/mysql/gda-mysql-parser.c	Sun Apr  6 17:06:43 2008
@@ -0,0 +1,82 @@
+/* GDA Mysql provider
+ *
+ * Copyright (C) 2008 The GNOME Foundation
+ *
+ * AUTHORS:
+ *      TO_ADD: your name and email
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "gda-mysql-parser.h"
+#include "mysql_token_types.h"
+#include <string.h>
+
+/* 
+ * Main static functions 
+ */
+static void gda_mysql_parser_class_init (GdaMysqlParserClass *klass);
+static void gda_mysql_parser_init (GdaMysqlParser *stmt);
+
+GType
+gda_mysql_parser_get_type (void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY (type == 0)) {
+		static const GTypeInfo info = {
+			sizeof (GdaMysqlParserClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) gda_mysql_parser_class_init,
+			NULL,
+			NULL,
+			sizeof (GdaMysqlParser),
+			0,
+			(GInstanceInitFunc) gda_mysql_parser_init
+		};
+		
+		type = g_type_register_static (GDA_TYPE_SQL_PARSER, "GdaMysqlParser", &info, 0);
+	}
+	return type;
+}
+
+/*
+ * The interface to the LEMON-generated parser
+ */
+void *gda_lemon_mysql_parserAlloc (void*(*)(size_t));
+void gda_lemon_mysql_parserFree (void*, void(*)(void*));
+void gda_lemon_mysql_parserTrace (void*, char *);
+void gda_lemon_mysql_parser (void*, int, GValue *, GdaSqlParserIface *);
+
+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;
+	pclass->parser_free = gda_lemon_mysql_parserFree;
+	pclass->parser_trace = gda_lemon_mysql_parserTrace;
+	pclass->parser_parse = gda_lemon_mysql_parser;
+	pclass->parser_tokens_trans = mysql_parser_tokens;
+}
+
+static void
+gda_mysql_parser_init (GdaMysqlParser *parser)
+{
+	g_print ("*** %s\n", __func__);
+}

Added: trunk/providers/mysql/gda-mysql-parser.h
==============================================================================
--- (empty file)
+++ trunk/providers/mysql/gda-mysql-parser.h	Sun Apr  6 17:06:43 2008
@@ -0,0 +1,59 @@
+/* GDA Mysql provider
+ *
+ * Copyright (C) 2008 The GNOME Foundation
+ *
+ * AUTHORS:
+ *      TO_ADD: your name and email
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __GDA_MYSQL_PARSER_H_
+#define __GDA_MYSQL_PARSER_H_
+
+#include <sql-parser/gda-sql-parser.h>
+
+G_BEGIN_DECLS
+
+#define GDA_TYPE_MYSQL_PARSER            (gda_mysql_parser_get_type())
+#define GDA_MYSQL_PARSER(obj)            (G_TYPE_CHECK_INSTANCE_CAST (obj, GDA_TYPE_MYSQL_PARSER, GdaMysqlParser))
+#define GDA_MYSQL_PARSER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST (klass, GDA_TYPE_MYSQL_PARSER, GdaMysqlParserClass))
+#define GDA_IS_MYSQL_PARSER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE (obj, GDA_TYPE_MYSQL_PARSER))
+#define GDA_IS_MYSQL_PARSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDA_TYPE_MYSQL_PARSER))
+
+typedef struct _GdaMysqlParser GdaMysqlParser;
+typedef struct _GdaMysqlParserClass GdaMysqlParserClass;
+typedef struct _GdaMysqlParserPrivate GdaMysqlParserPrivate;
+
+/* struct for the object's data */
+struct _GdaMysqlParser
+{
+	GdaSqlParser          object;
+	GdaMysqlParserPrivate *priv;
+};
+
+/* struct for the object's class */
+struct _GdaMysqlParserClass
+{
+	GdaSqlParserClass      parent_class;
+};
+
+GType gda_mysql_parser_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif

Modified: trunk/providers/mysql/gda-mysql-provider.c
==============================================================================
--- trunk/providers/mysql/gda-mysql-provider.c	(original)
+++ trunk/providers/mysql/gda-mysql-provider.c	Sun Apr  6 17:06:43 2008
@@ -1,12 +1,8 @@
-
-/* GDA MySQL provider
- * Copyright (C) 1998 - 2007 The GNOME Foundation.
+/* GDA Mysql provider
+ * Copyright (C) 2008 The GNOME Foundation.
  *
  * AUTHORS:
- *      Michael Lausch <michael lausch at>
- *	Rodrigo Moya <rodrigo gnome-db org>
- *      Vivien Malerba <malerba gnome-db org>
- *	Bas Driessen <bas driessen xobas com>
+ *      Carlos Savoretti <csavoretti gmail com>
  *
  * This Library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public License as
@@ -24,183 +20,274 @@
  * Boston, MA 02111-1307, USA.
  */
 
-#include <libgda/gda-data-model-array.h>
-#include <libgda/gda-data-model-private.h>
-#include <libgda/gda-column-index.h>
-#include <libgda/gda-util.h>
-#include <libgda/gda-data-handler.h>
-#include <libgda/gda-parameter-list.h>
-#include <libgda/gda-server-provider-extra.h>
-#include <glib/gi18n-lib.h>
+#include <stdio.h>
 #include <stdlib.h>
+#include <errno.h>
 #include <string.h>
+#include <glib/gi18n-lib.h>
+#include <glib/gstdio.h>
+#include <libgda/libgda.h>
+#include <libgda/gda-data-model-private.h>
+#include <libgda/gda-server-provider-extra.h>
+#include <libgda/binreloc/gda-binreloc.h>
+#include <libgda/gda-statement-extra.h>
+#include <sql-parser/gda-sql-parser.h>
 #include "gda-mysql.h"
+#include "gda-mysql-provider.h"
 #include "gda-mysql-recordset.h"
 #include "gda-mysql-ddl.h"
+#include "gda-mysql-meta.h"
 
-#include <libgda/handlers/gda-handler-numerical.h>
-#include <libgda/handlers/gda-handler-bin.h>
-#include <libgda/handlers/gda-handler-boolean.h>
-#include <libgda/handlers/gda-handler-time.h>
-#include <libgda/handlers/gda-handler-string.h>
-#include <libgda/handlers/gda-handler-type.h>
-
-#include <libgda/sql-parser/gda-sql-parser.h>
-#include <libgda/sql-delimiter/gda-sql-delimiter.h>
-#include <libgda/gda-connection-private.h>
-#include <libgda/binreloc/gda-binreloc.h>
+#include "gda-mysql-util.h"
+#include "gda-mysql-parser.h"
 
-#define PARENT_TYPE GDA_TYPE_SERVER_PROVIDER
+#define _GDA_PSTMT(x) ((GdaPStmt*)(x))
 
-static void gda_mysql_provider_class_init (GdaMysqlProviderClass *klass);
-static void gda_mysql_provider_init       (GdaMysqlProvider *provider,
-					   GdaMysqlProviderClass *klass);
-static void gda_mysql_provider_finalize   (GObject *object);
-
-static const gchar *gda_mysql_provider_get_version (GdaServerProvider *provider);
-
-static gboolean gda_mysql_provider_open_connection (GdaServerProvider *provider,
-						    GdaConnection *cnc,
-						    GdaQuarkList *params,
-						    const gchar *username,
-						    const gchar *password);
-
-static gboolean gda_mysql_provider_close_connection (GdaServerProvider *provider,
-						     GdaConnection *cnc);
-
-static const gchar *gda_mysql_provider_get_server_version (GdaServerProvider *provider,
-							   GdaConnection *cnc);
-
-static const gchar *gda_mysql_provider_get_database (GdaServerProvider *provider,
-						     GdaConnection *cnc);
-
-static gboolean gda_mysql_provider_change_database (GdaServerProvider *provider,
-		                                    GdaConnection *cnc,
-		                                    const gchar *name);
-
-static gboolean gda_mysql_provider_supports_operation (GdaServerProvider *provider, GdaConnection *cnc, 
-							  GdaServerOperationType type, GdaParameterList *options);
-static GdaServerOperation *gda_mysql_provider_create_operation (GdaServerProvider *provider, GdaConnection *cnc, 
-								   GdaServerOperationType type, 
-								   GdaParameterList *options, GError **error);
-static gchar *gda_mysql_provider_render_operation (GdaServerProvider *provider, GdaConnection *cnc, 
-						      GdaServerOperation *op, GError **error);
-
-static gboolean gda_mysql_provider_perform_operation (GdaServerProvider *provider, GdaConnection *cnc, 
-						      GdaServerOperation *op, GError **error);
-
-static GList *gda_mysql_provider_execute_command (GdaServerProvider *provider,
-						  GdaConnection *cnc,
-						  GdaCommand *cmd,
-						  GdaParameterList *params);
-
-static gchar *gda_mysql_provider_get_last_insert_id (GdaServerProvider *provider,
-						     GdaConnection *cnc,
-						     GdaDataModel *recset);
-
-static gboolean gda_mysql_provider_begin_transaction (GdaServerProvider *provider,
-						      GdaConnection *cnc,
-						      const gchar *name, GdaTransactionIsolation level,
-						      GError **error);
-
-static gboolean gda_mysql_provider_commit_transaction (GdaServerProvider *provider,
-						       GdaConnection *cnc,
-						       const gchar *name, GError **error);
-
-static gboolean gda_mysql_provider_rollback_transaction (GdaServerProvider *provider,
-							 GdaConnection *cnc,
-							 const gchar *name, GError **error);
-
-static gboolean gda_mysql_provider_supports (GdaServerProvider *provider,
-					     GdaConnection *cnc,
-					     GdaConnectionFeature feature);
-
-static GdaServerProviderInfo *gda_mysql_provider_get_info (GdaServerProvider *provider,
-							      GdaConnection *cnc);
-
-static GdaDataModel *gda_mysql_provider_get_schema (GdaServerProvider *provider,
-						    GdaConnection *cnc,
-						    GdaConnectionSchema schema,
-						    GdaParameterList *params);
-static GdaDataHandler *gda_mysql_provider_get_data_handler (GdaServerProvider *provider,
-						     GdaConnection *cnc,
-						     GType g_type,
-						     const gchar *dbms_type);
-static const gchar* gda_mysql_provider_get_default_dbms_type (GdaServerProvider *provider,
-							      GdaConnection *cnc,
-							      GType type);
+/*
+ * GObject methods
+ */
+static void gda_mysql_provider_class_init (GdaMysqlProviderClass  *klass);
+static void gda_mysql_provider_init       (GdaMysqlProvider       *provider,
+					   GdaMysqlProviderClass  *klass);
+static GObjectClass *parent_class = NULL;
 
-static GdaSqlParser *gda_mysql_provider_create_parser (GdaServerProvider *provider, GdaConnection *cnc);
+/*
+ * GdaServerProvider's virtual methods
+ */
+/* connection management */
+static gboolean            gda_mysql_provider_open_connection (GdaServerProvider               *provider,
+							       GdaConnection                   *cnc,
+							       GdaQuarkList                    *params,
+							       GdaQuarkList                    *auth,
+							       guint                           *task_id,
+							       GdaServerProviderAsyncCallback   async_cb,
+							       gpointer                         cb_data);
+static gboolean            gda_mysql_provider_close_connection (GdaServerProvider  *provider,
+								GdaConnection      *cnc);
+static const gchar        *gda_mysql_provider_get_server_version (GdaServerProvider  *provider,
+								  GdaConnection      *cnc);
+static const gchar        *gda_mysql_provider_get_database (GdaServerProvider  *provider,
+							    GdaConnection      *cnc);
+
+/* DDL operations */
+static gboolean            gda_mysql_provider_supports_operation (GdaServerProvider       *provider,
+								  GdaConnection           *cnc,
+								  GdaServerOperationType   type,
+								  GdaSet                  *options);
+static GdaServerOperation *gda_mysql_provider_create_operation (GdaServerProvider       *provider,
+								GdaConnection           *cnc,
+								GdaServerOperationType   type,
+								GdaSet                  *options,
+								GError                **error);
+static gchar              *gda_mysql_provider_render_operation (GdaServerProvider   *provider,
+								GdaConnection       *cnc,
+								GdaServerOperation  *op,
+								GError             **error);
+
+static gboolean            gda_mysql_provider_perform_operation (GdaServerProvider               *provider,
+								 GdaConnection                   *cnc,
+								 GdaServerOperation              *op,
+								 guint                           *task_id, 
+								 GdaServerProviderAsyncCallback   async_cb,
+								 gpointer                         cb_data,
+								 GError                         **error);
+/* transactions */
+static gboolean            gda_mysql_provider_begin_transaction (GdaServerProvider        *provider,
+								 GdaConnection            *cnc,
+								 const gchar              *name,
+								 GdaTransactionIsolation   level,
+								 GError                  **error);
+static gboolean            gda_mysql_provider_commit_transaction (GdaServerProvider  *provider,
+								  GdaConnection *cnc,
+								  const gchar *name, GError **error);
+static gboolean            gda_mysql_provider_rollback_transaction (GdaServerProvider *provider,
+								    GdaConnection     *cnc,
+								    const gchar       *name,
+								    GError           **error);
+static gboolean            gda_mysql_provider_add_savepoint (GdaServerProvider  *provider,
+							     GdaConnection      *cnc,
+							     const gchar        *name,
+							     GError            **error);
+static gboolean            gda_mysql_provider_rollback_savepoint (GdaServerProvider  *provider,
+								  GdaConnection      *cnc,
+								  const gchar        *name,
+								  GError            **error);
+static gboolean            gda_mysql_provider_delete_savepoint (GdaServerProvider  *provider,
+								GdaConnection      *cnc,
+								const gchar        *name,
+								GError            **error);
+
+/* information retrieval */
+static const gchar        *gda_mysql_provider_get_version (GdaServerProvider  *provider);
+static gboolean            gda_mysql_provider_supports_feature (GdaServerProvider     *provider,
+								GdaConnection         *cnc,
+								GdaConnectionFeature   feature);
+
+static const gchar        *gda_mysql_provider_get_name (GdaServerProvider  *provider);
+
+static GdaDataHandler     *gda_mysql_provider_get_data_handler (GdaServerProvider  *provider,
+								GdaConnection      *cnc,
+								GType               g_type,
+								const gchar        *dbms_type);
+
+static const gchar*        gda_mysql_provider_get_default_dbms_type (GdaServerProvider  *provider,
+								     GdaConnection      *cnc,
+								     GType               type);
+/* statements */
+static GdaSqlParser        *gda_mysql_provider_create_parser (GdaServerProvider  *provider,
+							      GdaConnection      *cnc);
+static gchar               *gda_mysql_provider_statement_to_sql  (GdaServerProvider    *provider,
+								  GdaConnection        *cnc,
+								  GdaStatement         *stmt,
+								  GdaSet               *params, 
+								  GdaStatementSqlFlag   flags,
+								  GSList              **params_used,
+								  GError              **error);
+static gboolean             gda_mysql_provider_statement_prepare (GdaServerProvider  *provider,
+								  GdaConnection      *cnc,
+								  GdaStatement       *stmt,
+								  GError            **error);
+static GObject             *gda_mysql_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);
 
+/* 
+ * private connection data destroy 
+ */
+static void gda_mysql_free_cnc_data (MysqlConnectionData  *cdata);
 
-static GObjectClass *parent_class = NULL;
 
 /*
- * GdaMysqlProvider class implementation
+ * Prepared internal statements
+ * TO_ADD: any prepared statement to be used internally by the provider should be
+ *         declared here, as constants and as SQL statements
  */
+GdaStatement **internal_stmt;
+
+typedef enum {
+	INTERNAL_STMT1
+} InternalStatementItem;
+
+gchar *internal_sql[] = {
+	"SQL for INTERNAL_STMT1"
+};
 
+/*
+ * GdaMysqlProvider class implementation
+ */
 static void
-gda_mysql_provider_class_init (GdaMysqlProviderClass *klass)
+gda_mysql_provider_class_init (GdaMysqlProviderClass  *klass)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	g_print ("*** %s\n", __func__);
 	GdaServerProviderClass *provider_class = GDA_SERVER_PROVIDER_CLASS (klass);
 
 	parent_class = g_type_class_peek_parent (klass);
 
-	object_class->finalize = gda_mysql_provider_finalize;
-
 	provider_class->get_version = gda_mysql_provider_get_version;
 	provider_class->get_server_version = gda_mysql_provider_get_server_version;
-	provider_class->get_info = gda_mysql_provider_get_info;
-	provider_class->supports_feature = gda_mysql_provider_supports;
-	provider_class->get_schema = gda_mysql_provider_get_schema;
+	provider_class->get_name = gda_mysql_provider_get_name;
+	provider_class->supports_feature = gda_mysql_provider_supports_feature;
 
 	provider_class->get_data_handler = gda_mysql_provider_get_data_handler;
-	provider_class->string_to_value = NULL;
 	provider_class->get_def_dbms_type = gda_mysql_provider_get_default_dbms_type;
 
-	provider_class->create_connection = NULL;
 	provider_class->open_connection = gda_mysql_provider_open_connection;
 	provider_class->close_connection = gda_mysql_provider_close_connection;
 	provider_class->get_database = gda_mysql_provider_get_database;
-	provider_class->change_database = gda_mysql_provider_change_database;
 
 	provider_class->supports_operation = gda_mysql_provider_supports_operation;
-	provider_class->create_operation = gda_mysql_provider_create_operation;
-	provider_class->render_operation = gda_mysql_provider_render_operation;
-	provider_class->perform_operation = gda_mysql_provider_perform_operation;
-
-	provider_class->execute_command = gda_mysql_provider_execute_command;
-	provider_class->execute_query = NULL;
-	provider_class->get_last_insert_id = gda_mysql_provider_get_last_insert_id;
+        provider_class->create_operation = gda_mysql_provider_create_operation;
+        provider_class->render_operation = gda_mysql_provider_render_operation;
+        provider_class->perform_operation = gda_mysql_provider_perform_operation;
 
 	provider_class->begin_transaction = gda_mysql_provider_begin_transaction;
 	provider_class->commit_transaction = gda_mysql_provider_commit_transaction;
 	provider_class->rollback_transaction = gda_mysql_provider_rollback_transaction;
-	provider_class->add_savepoint = NULL;
-	provider_class->rollback_savepoint = NULL;
-	provider_class->delete_savepoint = NULL;
+	provider_class->add_savepoint = gda_mysql_provider_add_savepoint;
+        provider_class->rollback_savepoint = gda_mysql_provider_rollback_savepoint;
+        provider_class->delete_savepoint = gda_mysql_provider_delete_savepoint;
 
 	provider_class->create_parser = gda_mysql_provider_create_parser;
-        provider_class->statement_to_sql = NULL;
-        provider_class->statement_prepare = NULL;
-        provider_class->statement_execute = NULL;
-}
+	provider_class->statement_to_sql = gda_mysql_provider_statement_to_sql;
+	provider_class->statement_prepare = gda_mysql_provider_statement_prepare;
+	provider_class->statement_execute = gda_mysql_provider_statement_execute;
 
-static void
-gda_mysql_provider_init (GdaMysqlProvider *myprv, GdaMysqlProviderClass *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_mysql_meta__info;
+        provider_class->meta_funcs._btypes = _gda_mysql_meta__btypes;
+        provider_class->meta_funcs._udt = _gda_mysql_meta__udt;
+        provider_class->meta_funcs.udt = _gda_mysql_meta_udt;
+        provider_class->meta_funcs._udt_cols = _gda_mysql_meta__udt_cols;
+        provider_class->meta_funcs.udt_cols = _gda_mysql_meta_udt_cols;
+        provider_class->meta_funcs._enums = _gda_mysql_meta__enums;
+        provider_class->meta_funcs.enums = _gda_mysql_meta_enums;
+        provider_class->meta_funcs._domains = _gda_mysql_meta__domains;
+        provider_class->meta_funcs.domains = _gda_mysql_meta_domains;
+        provider_class->meta_funcs._constraints_dom = _gda_mysql_meta__constraints_dom;
+        provider_class->meta_funcs.constraints_dom = _gda_mysql_meta_constraints_dom;
+        provider_class->meta_funcs._el_types = _gda_mysql_meta__el_types;
+        provider_class->meta_funcs._collations = _gda_mysql_meta__collations;
+        provider_class->meta_funcs.collations = _gda_mysql_meta_collations;
+        provider_class->meta_funcs._character_sets = _gda_mysql_meta__character_sets;
+        provider_class->meta_funcs.character_sets = _gda_mysql_meta_character_sets;
+        provider_class->meta_funcs._schemata = _gda_mysql_meta__schemata;
+        provider_class->meta_funcs.schemata = _gda_mysql_meta_schemata;
+        provider_class->meta_funcs._tables_views = _gda_mysql_meta__tables_views;
+        provider_class->meta_funcs.tables_views = _gda_mysql_meta_tables_views;
+        provider_class->meta_funcs._columns = _gda_mysql_meta__columns;
+        provider_class->meta_funcs.columns = _gda_mysql_meta_columns;
+        provider_class->meta_funcs._view_cols = _gda_mysql_meta__view_cols;
+        provider_class->meta_funcs.view_cols = _gda_mysql_meta_view_cols;
+        provider_class->meta_funcs._constraints_tab = _gda_mysql_meta__constraints_tab;
+        provider_class->meta_funcs.constraints_tab = _gda_mysql_meta_constraints_tab;
+        provider_class->meta_funcs._constraints_ref = _gda_mysql_meta__constraints_ref;
+        provider_class->meta_funcs.constraints_ref = _gda_mysql_meta_constraints_ref;
+        provider_class->meta_funcs._key_columns = _gda_mysql_meta__key_columns;
+        provider_class->meta_funcs.key_columns = _gda_mysql_meta_key_columns;
+        provider_class->meta_funcs._check_columns = _gda_mysql_meta__check_columns;
+        provider_class->meta_funcs.check_columns = _gda_mysql_meta_check_columns;
+        provider_class->meta_funcs._triggers = _gda_mysql_meta__triggers;
+        provider_class->meta_funcs.triggers = _gda_mysql_meta_triggers;
+        provider_class->meta_funcs._routines = _gda_mysql_meta__routines;
+        provider_class->meta_funcs.routines = _gda_mysql_meta_routines;
+        provider_class->meta_funcs._routine_col = _gda_mysql_meta__routine_col;
+        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;
 }
 
 static void
-gda_mysql_provider_finalize (GObject *object)
+gda_mysql_provider_init (GdaMysqlProvider       *mysql_prv,
+			 GdaMysqlProviderClass  *klass)
 {
-	GdaMysqlProvider *myprv = (GdaMysqlProvider *) object;
+	g_print ("*** %s\n", __func__);
+	InternalStatementItem i;
+	GdaSqlParser *parser;
 
-	g_return_if_fail (GDA_IS_MYSQL_PROVIDER (myprv));
+	parser = gda_server_provider_internal_get_parser ((GdaServerProvider*) mysql_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]);
+	}
+
+	/* meta data init */
+	_gda_mysql_provider_meta_init ((GdaServerProvider*) mysql_prv);
 
-	/* chain to parent class */
-	parent_class->finalize (object);
+	/* TO_ADD: any other provider's init should be added here */
 }
 
 GType
@@ -219,55 +306,60 @@
 			0,
 			(GInstanceInitFunc) gda_mysql_provider_init
 		};
-		type = g_type_register_static (PARENT_TYPE, "GdaMysqlProvider", &info, 0);
+		type = g_type_register_static (GDA_TYPE_SERVER_PROVIDER, "GdaMysqlProvider",
+					       &info, 0);
 	}
 
 	return type;
 }
 
-GdaServerProvider *
-gda_mysql_provider_new (void)
-{
-	GdaMysqlProvider *provider;
 
-	provider = g_object_new (gda_mysql_provider_get_type (), NULL);
-	return GDA_SERVER_PROVIDER (provider);
+/*
+ * Get provider name request
+ */
+static const gchar *
+gda_mysql_provider_get_name (GdaServerProvider  *provider)
+{
+	g_print ("*** %s\n", __func__);
+	return MYSQL_PROVIDER_NAME;
 }
 
-/* get_version handler for the GdaMysqlProvider class */
+/* 
+ * Get provider's version, no need to change this
+ */
 static const gchar *
-gda_mysql_provider_get_version (GdaServerProvider *provider)
+gda_mysql_provider_get_version (GdaServerProvider  *provider)
 {
-	GdaMysqlProvider *myprv = (GdaMysqlProvider *) provider;
-
-	g_return_val_if_fail (GDA_IS_MYSQL_PROVIDER (myprv), NULL);
-
-	return GDA_PACKAGE_VERSION;
+	g_print ("*** %s\n", __func__);
+	return PACKAGE_VERSION;
 }
 
-/* generic function to open a MYSQL connection */
+
+/*
+ * Open a MYSQL connection.
+ */
 static MYSQL *
-real_open_connection (const gchar *host, gint port, const gchar *socket,
-		      const gchar *db,
-		      const gchar *login, const gchar *password, 
-		      gboolean usessl, GError **error)
-{
-	MYSQL *mysql;
-	MYSQL *mysql_ret;
-	unsigned int mysqlflags = 0;
-#if MYSQL_VERSION_ID < 32200
-        gint err;
-#endif
-	
-	/* we can't have both a host/pair AND a unix_socket */
-        if ((host || (port >= 0)) && socket) {
-                g_set_error (error, 0, 0,
-			     _("You cannot provide a UNIX SOCKET if you also provide"
-			       " either a HOST or a PORT."));
-                return NULL;
-        }
+real_open_connection (const gchar  *host,
+		      gint          port,
+		      const gchar  *socket,
+		      const gchar  *db,
+		      const gchar  *username,
+		      const gchar  *password,
+		      gboolean      use_ssl,
+		      GError      **error)
+{
+	g_print ("*** %s\n", __func__);
+	unsigned int flags = 0;
+
+	/* Exclusive: host/pair otherwise unix socket. */
+	if ((host || port >= 0) && socket) {
+		g_set_error (error, 0, 0,
+			     _("Cannot give a UNIX SOCKET if you also provide "
+			       "either a HOST or a PORT"));
+		return NULL;
+	}
 
-	/* provide the default of localhost:3306 if neither is provided */
+	/* Defaults. */
 	if (!socket) {
 		if (!host)
 			host = "localhost";
@@ -275,2187 +367,1091 @@
 			port = 3306;
 	}
 
-	if (usessl)
-		 mysqlflags |= CLIENT_SSL;
+	if (use_ssl)
+		flags |= CLIENT_SSL;
+	
+	MYSQL *mysql = g_new0 (MYSQL, 1);
+	mysql_init (mysql);
 
-	mysql = g_new0 (MYSQL, 1);
-        mysql_init (mysql);
-        mysql_ret = mysql_real_connect (mysql, host, login, password,
+	MYSQL *return_mysql = mysql_real_connect (mysql, host,
+						  username, password,
 #if MYSQL_VERSION_ID >= 32200
-					db,
+						  db,
 #endif
-					port > 0? port : 0,
-					socket,
-					mysqlflags);
-	
-	
-	if (!mysql_ret) {
+						  (port > 0) ? port : 0,
+						  socket, flags);
+	if (!return_mysql || mysql != return_mysql) {
 		g_set_error (error, 0, 0, mysql_error (mysql));
 		g_free (mysql);
-		return NULL;
+		mysql = NULL;
 	}
-	
+
+	/* Optionnally set some attributes for the newly opened connection (encoding to UTF-8 for example )*/
+
 #if MYSQL_VERSION_ID < 32200
-	err = mysql_select_db (mysql, db);
-	if (err != 0) {
+	if (mysql &&
+	    mysql_select_db (mysql, db) != 0) {
 		g_set_error (error, 0, 0, mysql_error (mysql));
-		mysql_close (mysql);
-		
-		return NULL;
+		g_free (mysql);
+		mysql = NULL;
 	}
 #endif
 
 #if MYSQL_VERSION_ID >= 50007
-	if (mysql_set_character_set (mysql, "utf8"))
-		g_warning ("Could not set client character set to UTF8 (using %s), expect problems with non UTF-8 characters\n", 
+	if (mysql &&
+	    mysql_set_character_set (mysql, "utf8")) {
+		g_warning (_("Could not set client charset to UTF8. "
+			     "Using %s. It'll be problems with non UTF-8 characters"),
 			   mysql_character_set_name (mysql));
+	}
 #endif
-	
+
 	return mysql;
 }
 
-/* open_connection handler for the GdaMysqlProvider class */
-static gboolean
-gda_mysql_provider_open_connection (GdaServerProvider *provider,
-				    GdaConnection *cnc,
-				    GdaQuarkList *params,
-				    const gchar *username,
-				    const gchar *password)
-{
-	const gchar *t_host = NULL;
-        const gchar *t_db = NULL;
-        const gchar *t_user = NULL;
-        const gchar *t_password = NULL;
-        const gchar *t_port = NULL;
-        const gchar *t_unix_socket = NULL;
-        const gchar *t_use_ssl = NULL;
-
-	MYSQL *mysql;
-	GdaConnectionEvent *error;
-	GError *gerror = NULL;
-	GdaMysqlProvider *myprv = (GdaMysqlProvider *) provider;
+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);
+	return g_strdup_printf ("%lu.%lu.%lu",
+				version_long/10000,
+				(version_long%10000)/100,
+				(version_long%100));
+}
+
 
-	g_return_val_if_fail (GDA_IS_MYSQL_PROVIDER (myprv), FALSE);
+/* 
+ * Open connection request
+ *
+ * In this function, the following _must_ be done:
+ *   - check for the presence and validify of the parameters required to actually open a connection,
+ *     using @params
+ *   - open the real connection to the database using the parameters previously checked
+ *   - create a MysqlConnectionData structure and associate it to @cnc
+ *
+ * Returns: TRUE if no error occurred, or FALSE otherwise (and an ERROR gonnection event must be added to @cnc)
+ */
+static gboolean
+gda_mysql_provider_open_connection (GdaServerProvider               *provider,
+				    GdaConnection                   *cnc,
+				    GdaQuarkList                    *params,
+				    GdaQuarkList                    *auth,
+				    guint                           *task_id,
+				    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);
 
-	/* get all parameters received */
-	t_host = gda_quark_list_find (params, "HOST");
-	t_db = gda_quark_list_find (params, "DB_NAME");
-	if (!t_db) {
-		const gchar *str;
-
-		str = gda_quark_list_find (params, "DATABASE");
-		if (!str) {
-			gda_connection_add_event_string (cnc,
-							 _("The connection string must contain a DB_NAME value"));
-			return FALSE;
-		}
-		else {
-			g_warning (_("The connection string format has changed: replace DATABASE with "
-				     "DB_NAME and the same contents"));
-			t_db = str;
-		}
+	/* 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;
 	}
 
-	t_user = gda_quark_list_find (params, "USER");
-	t_password = gda_quark_list_find (params, "PASSWORD");
-	t_port = gda_quark_list_find (params, "PORT");
-	t_unix_socket = gda_quark_list_find (params, "UNIX_SOCKET");
-	t_use_ssl = gda_quark_list_find (params, "USE_SSL");
-
-	if (username && *username != '\0')
-		t_user = username;
-	if (password && *password != '\0')
-		t_password = password;
+	/* Check for connection parameters */
+	/* TO_ADD: your own connection parameters */
+	const gchar *db_name;
+	db_name = gda_quark_list_find (params, "DB_NAME");
+	if (!db_name) {
+		gda_connection_add_event_string (cnc,
+						 _("The connection string must contain the DB_NAME values"));
+		return FALSE;
+	}
+	
+	const gchar *host;
+	host = gda_quark_list_find (params, "HOST");
 
-	mysql = real_open_connection (t_host, t_port ? atoi (t_port) : 0, t_unix_socket,
-				      t_db, t_user, t_password, t_use_ssl ? TRUE : FALSE, &gerror);
+	const gchar *user, *password;
+	user = gda_quark_list_find (params, "USER");
+	password = gda_quark_list_find (params, "PASSWORD");
+
+	const gchar *port, *unix_socket, *use_ssl;
+	port = gda_quark_list_find (params, "PORT");
+	unix_socket = gda_quark_list_find (params, "UNIX_SOCKET");
+	use_ssl = gda_quark_list_find (params, "USE_SSL");
+	
+	
+	/* open the real connection to the database */
+	/* TO_ADD: C API specific function calls;
+	 * if it fails, add a connection event and return FALSE */
+	// TO_IMPLEMENT;
+	
+	GError *error = NULL;
+	MYSQL *mysql = real_open_connection (host, (port != NULL) ? atoi (port) : 0,
+					     unix_socket, db_name,
+					     user, password,
+					     (use_ssl != NULL) ? TRUE : FALSE,
+					     &error);
 	if (!mysql) {
-		error = gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR);
-		gda_connection_event_set_description (error, gerror && gerror->message ? 
-					   gerror->message : "NO DESCRIPTION");
-                gda_connection_event_set_code (error, gerror ? gerror->code : -1);
-		if (gerror)
-			g_error_free (gerror);
-		gda_connection_add_event (cnc, error);
+		_gda_mysql_make_error (cnc, mysql, NULL);
+		return FALSE;
+	}
+
+	MYSQL_STMT *mysql_stmt = mysql_stmt_init (mysql);
+	if (!mysql_stmt) {
+		_gda_mysql_make_error (cnc, mysql, NULL);
+		return FALSE;
+	}
 
+	my_bool update_max_length = 1;
+	if (mysql_stmt_attr_set (mysql_stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (const void *) &update_max_length)) {
+		_gda_mysql_make_error (cnc, mysql, NULL);
 		return FALSE;
 	}
-	g_object_set_data (G_OBJECT (cnc), OBJECT_DATA_MYSQL_HANDLE, mysql);
+	
+
+	/* Create a new instance of the provider specific data associated to a connection (MysqlConnectionData),
+	 * and set its contents */
+	MysqlConnectionData *cdata;
+	cdata = g_new0 (MysqlConnectionData, 1);
+	gda_connection_internal_set_provider_data (cnc, cdata, (GDestroyNotify) gda_mysql_free_cnc_data);
+	// TO_IMPLEMENT; /* cdata->... = ... */
+	
+	cdata->cnc = cnc;
+	cdata->mysql = mysql;
+	cdata->mysql_stmt = mysql_stmt;
+
+	cdata->version_long = mysql_get_server_version (mysql);
+	cdata->version = get_mysql_version (mysql);
+	
+
+	/* Optionnally set some attributes for the newly opened connection (encoding to UTF-8 for example )*/
+	// TO_IMPLEMENT;
 
 	return TRUE;
 }
 
-/* close_connection handler for the GdaMysqlProvider class */
+/* 
+ * Close connection request
+ *
+ * In this function, the following _must_ be done:
+ *   - Actually close the connection to the database using @cnc's associated MysqlConnectionData structure
+ *   - Free the MysqlConnectionData structure and its contents
+ *
+ * Returns: TRUE if no error occurred, or FALSE otherwise (and an ERROR gonnection event must be added to @cnc)
+ */
 static gboolean
-gda_mysql_provider_close_connection (GdaServerProvider *provider, GdaConnection *cnc)
+gda_mysql_provider_close_connection (GdaServerProvider  *provider,
+				     GdaConnection      *cnc)
 {
-	MYSQL *mysql;
-	GdaMysqlProvider *myprv = (GdaMysqlProvider *) provider;
+	g_print ("*** %s\n", __func__);
+	MysqlConnectionData *cdata;
 
-	g_return_val_if_fail (GDA_IS_MYSQL_PROVIDER (myprv), FALSE);
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, FALSE);
 
-	mysql = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_MYSQL_HANDLE);
-	if (!mysql)
+	/* Close the connection using the C API */
+	cdata = (MysqlConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
 		return FALSE;
+	// TO_IMPLEMENT;
 
-	mysql_close (mysql);
-	g_object_set_data (G_OBJECT (cnc), OBJECT_DATA_MYSQL_HANDLE, NULL);
+	/* Free the MysqlConnectionData structure and its contents*/
+	gda_mysql_free_cnc_data (cdata);
+	gda_connection_internal_set_provider_data (cnc, NULL, NULL);
 
 	return TRUE;
 }
 
-/* get_server_version handler for the GdaMysqlProvider class */
+/*
+ * Server version request
+ *
+ * Returns the server version as a string, which should be stored in @cnc's associated MysqlConnectionData structure
+ */
 static const gchar *
-gda_mysql_provider_get_server_version (GdaServerProvider *provider, GdaConnection *cnc)
+gda_mysql_provider_get_server_version (GdaServerProvider  *provider,
+				       GdaConnection      *cnc)
 {
-	MYSQL *mysql;
-	GdaMysqlProvider *myprv = (GdaMysqlProvider *) provider;
+	g_print ("*** %s\n", __func__);
+	MysqlConnectionData *cdata;
 
-	g_return_val_if_fail (GDA_IS_MYSQL_PROVIDER (myprv), NULL);
-	if (cnc)
-		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-	else
-		return NULL;
-	
-	mysql = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_MYSQL_HANDLE);
-	if (!mysql) {
-		gda_connection_add_event_string (cnc, _("Invalid MySQL handle"));
-		return FALSE;
-	}
-
-	return (const gchar *) mysql->server_version;
-}
-
-static GList *
-process_sql_commands (GList *reclist, GdaConnection *cnc, const gchar *sql)
-{
-	MYSQL *mysql;
-	gchar **arr;
-	GdaConnectionOptions options;
-
-	mysql = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_MYSQL_HANDLE);
-	if (!mysql) {
-		gda_connection_add_event_string (cnc, _("Invalid MySQL handle"));
-		return NULL;
-	}
-
-	options = gda_connection_get_options (cnc);
-
-	/* parse SQL string, which can contain several commands, separated by ';' */
-	arr = gda_delimiter_split_sql (sql);
-	if (arr) {
-		gint n = 0;
-		gboolean allok = TRUE;
-
-		while (arr[n] && allok) {
-			gint rc;
-			MYSQL_RES *mysql_res;
-			GdaMysqlRecordset *recset;
-			gchar *tststr;
-			GdaConnectionEvent *error = NULL;
-
-			/* if the connection is in read-only mode, just allow SELECT,
-			   SHOW commands */
-			if (options & GDA_CONNECTION_OPTIONS_READ_ONLY) {
-				gchar *s;
-
-				/* FIXME: maybe there's a better way of doing this? */
-				s = g_strstrip (g_strdup (arr[n]));
-				if (g_ascii_strncasecmp (s, "select", strlen ("select")) &&
-				    g_ascii_strncasecmp (s, "show", strlen ("show"))) {
-					gda_connection_add_event_string (
-						cnc, "Command '%s' cannot be executed in read-only mode", arr[n]);
-					reclist = g_list_append (reclist, NULL);
-					allok = FALSE;
-					break;
-				}
-
-				g_free (s);
-			}
-
-			/* execute the command on the server */
-			rc = gda_mysql_real_query_wrap (cnc, mysql, arr[n], strlen (arr[n]));
-			if (rc != 0) {
-				error = gda_mysql_make_error (mysql);
-				gda_connection_add_event (cnc, error);
-				reclist = g_list_append (reclist, NULL);
-				allok = FALSE;
-			}
-			else {
-				/* command was executed OK */
-				g_strchug (arr[n]);
-				tststr = arr[n];
-				if (! g_ascii_strncasecmp (tststr, "SELECT", 6) ||
-				    ! g_ascii_strncasecmp (tststr, "SHOW", 4) ||
-				    ! g_ascii_strncasecmp (tststr, "DESCRIBE", 6) ||
-				    ! g_ascii_strncasecmp (tststr, "EXPLAIN", 7)) {
-					mysql_res = mysql_store_result (mysql);
-					recset = gda_mysql_recordset_new (cnc, mysql_res, mysql);
-					if (GDA_IS_MYSQL_RECORDSET (recset)) {
-						g_object_set (G_OBJECT (recset), 
-							      "command_text", arr[n],
-							      "command_type", GDA_COMMAND_TYPE_SQL, NULL);
-						reclist = g_list_append (reclist, recset);
-					}
-					else
-						reclist = g_list_append (reclist, NULL);
-				}
-				else {
-					int changes;
-					GdaConnectionEvent *event;
-					gchar *str, *tmp, *ptr;
-					
-					changes = mysql_affected_rows (mysql);
-					reclist = g_list_append (reclist, 
-								 gda_parameter_list_new_inline (NULL, 
-												"IMPACTED_ROWS", G_TYPE_INT, changes,
-												NULL));
-					
-					/* generate a notice about changes */
-					event = gda_connection_event_new (GDA_CONNECTION_EVENT_NOTICE);
-					ptr = tststr;
-					while (*ptr && (*ptr != ' ') && (*ptr != '\t') &&
-					       (*ptr != '\n'))
-						ptr++;
-					*ptr = 0;
-					tmp = g_ascii_strup (tststr, -1);
-					if (!strcmp (tmp, "INSERT")) {
-						if (mysql_insert_id (mysql) != 0)
-							str = g_strdup_printf ("%s %lld %d", tmp, 
-									       mysql_insert_id (mysql),
-									       changes);
-						else
-							str = g_strdup_printf ("%s NOID %d", tmp, changes);
-					}
-					else
-						str = g_strdup_printf ("%s %d", tmp, changes);
-					gda_connection_event_set_description (event, str);
-					g_free (str);
-					g_free (tmp);
-					gda_connection_add_event (cnc, event);
-				}
-			}
-
-			gda_connection_internal_treat_sql (cnc, arr[n], error);
-			n++;
-		}
-
-		g_strfreev (arr);
-	}
+	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;
+	cdata = (MysqlConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
+		return FALSE;
+	TO_IMPLEMENT;
+	return NULL;
 }
 
-/* get_database handler for the GdaMysqlProvider class */
+/*
+ * Get database request
+ *
+ * Returns the server version as a string, which should be stored in @cnc's associated MysqlConnectionData structure
+ */
 static const gchar *
-gda_mysql_provider_get_database (GdaServerProvider *provider,
-				 GdaConnection *cnc)
+gda_mysql_provider_get_database (GdaServerProvider  *provider,
+				 GdaConnection      *cnc)
 {
-	MYSQL *mysql;
-	GdaMysqlProvider *myprv = (GdaMysqlProvider *) provider;
+	g_print ("*** %s\n", __func__);
+	MysqlConnectionData *cdata;
 
-	g_return_val_if_fail (GDA_IS_MYSQL_PROVIDER (myprv), NULL);
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+	g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, NULL);
 
-	mysql = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_MYSQL_HANDLE);
-	if (!mysql) {
-		gda_connection_add_event_string (cnc, _("Invalid MySQL handle"));
+	cdata = (MysqlConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
 		return NULL;
-	}
-
-	return (const gchar *) mysql->db;
+	TO_IMPLEMENT;
+	return NULL;
 }
 
-/* change_database handler for the GdaMysqlProvider class */
+/*
+ * Support operation request
+ *
+ * Tells what the implemented server operations are. To add support for an operation, the following steps are required:
+ *   - create a mysql_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_mysql_provider_render_operation() and gda_mysql_provider_perform_operation() methods
+ *
+ * In this example, the GDA_SERVER_OPERATION_CREATE_TABLE is implemented
+ */
 static gboolean
-gda_mysql_provider_change_database (GdaServerProvider *provider,
-		                    GdaConnection *cnc,
-				    const gchar *name)
-{
-	gint rc;
-	MYSQL *mysql;
-	GdaMysqlProvider *myprv = (GdaMysqlProvider *) provider;
-
-	g_return_val_if_fail (GDA_IS_MYSQL_PROVIDER (myprv), FALSE);
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
-	g_return_val_if_fail (name != NULL, FALSE);
-
-	mysql = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_MYSQL_HANDLE);
-	if (!mysql) {
-		gda_connection_add_event_string (cnc, _("Invalid MySQL handle"));
-		return FALSE;
+gda_mysql_provider_supports_operation (GdaServerProvider       *provider,
+				       GdaConnection           *cnc,
+				       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);
 	}
 
-	rc = mysql_select_db (mysql, name);
-	if (rc != 0) {
-		gda_connection_add_event (cnc, gda_mysql_make_error (mysql));
+        switch (type) {
+        case GDA_SERVER_OPERATION_CREATE_DB:
+        case GDA_SERVER_OPERATION_DROP_DB:
 		return FALSE;
-	}
 
-	return TRUE;
-}
-
-static gboolean
-gda_mysql_provider_supports_operation (GdaServerProvider *provider, GdaConnection *cnc,
-				       GdaServerOperationType type, GdaParameterList *options)
-{
-	switch (type) {
-	case GDA_SERVER_OPERATION_CREATE_DB:
-	case GDA_SERVER_OPERATION_DROP_DB:
-
-	case GDA_SERVER_OPERATION_CREATE_TABLE:
-	case GDA_SERVER_OPERATION_DROP_TABLE:
-	case GDA_SERVER_OPERATION_RENAME_TABLE:
+        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_DROP_COLUMN:
+        case GDA_SERVER_OPERATION_ADD_COLUMN:
 
-	case GDA_SERVER_OPERATION_CREATE_INDEX:
-	case GDA_SERVER_OPERATION_DROP_INDEX:
+        case GDA_SERVER_OPERATION_CREATE_INDEX:
+        case GDA_SERVER_OPERATION_DROP_INDEX:
 
-	case GDA_SERVER_OPERATION_CREATE_VIEW:
-	case GDA_SERVER_OPERATION_DROP_VIEW:
-		return TRUE;
-	default:
-		return FALSE;
-	}
+        case GDA_SERVER_OPERATION_CREATE_VIEW:
+        case GDA_SERVER_OPERATION_DROP_VIEW:
+        default:
+                return FALSE;
+        }
 }
 
+/*
+ * Create operation request
+ *
+ * Creates a #GdaServerOperation. The following code is generic and should only be changed
+ * if some further initialization is required, or if operation's contents is dependant on @cnc
+ */
 static GdaServerOperation *
-gda_mysql_provider_create_operation (GdaServerProvider *provider, GdaConnection *cnc, 
-				     GdaServerOperationType type, 
-				     GdaParameterList *options, GError **error)
-{
-	gchar *file;
-	GdaServerOperation *op;
-	gchar *str;
+gda_mysql_provider_create_operation (GdaServerProvider       *provider,
+				     GdaConnection           *cnc,
+				     GdaServerOperationType   type,
+				     GdaSet                  *options,
+				     GError                 **error)
+{
+	g_print ("*** %s\n", __func__);
+        gchar *file;
+        GdaServerOperation *op;
+        gchar *str;
 	gchar *dir;
-	
-	file = g_utf8_strdown (gda_server_operation_op_type_to_string (type), -1);
-	str = g_strdup_printf ("mysql_specs_%s.xml", file);
-	g_free (file);
+
+	if (cnc) {
+		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+		g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, FALSE);
+	}
+
+        file = g_utf8_strdown (gda_server_operation_op_type_to_string (type), -1);
+        str = g_strdup_printf ("mysql_specs_%s.xml", file);
+        g_free (file);
 
 	dir = gda_gbr_get_file_path (GDA_DATA_DIR, LIBGDA_ABI_NAME, NULL);
-	file = gda_server_provider_find_file (provider, dir, str);
+        file = gda_server_provider_find_file (provider, dir, str);
 	g_free (dir);
+        g_free (str);
 
-	if (! file) {
-		g_set_error (error, 0, 0, _("Missing spec. file '%s'"), str);
-		g_free (str);
-		return NULL;
-	}
-	g_free (str);
+        if (! file) {
+                g_set_error (error, 0, 0, _("Missing spec. file '%s'"), file);
+                return NULL;
+        }
 
-	op = gda_server_operation_new (type, file);
-	g_free (file);
+        op = gda_server_operation_new (type, file);
+        g_free (file);
 
-	return op;
+        return op;
 }
 
+/*
+ * Render operation request
+ */
 static gchar *
-gda_mysql_provider_render_operation (GdaServerProvider *provider, GdaConnection *cnc, 
-				     GdaServerOperation *op, GError **error)
-{
-	gchar *sql = NULL;
-	gchar *file;
-	gchar *str;
+gda_mysql_provider_render_operation (GdaServerProvider   *provider,
+				     GdaConnection       *cnc,
+				     GdaServerOperation  *op,
+				     GError             **error)
+{
+	g_print ("*** %s\n", __func__);
+        gchar *sql = NULL;
+        gchar *file;
+        gchar *str;
 	gchar *dir;
 
-	file = g_utf8_strdown (gda_server_operation_op_type_to_string (gda_server_operation_get_op_type (op)), -1);
-	str = g_strdup_printf ("mysql_specs_%s.xml", file);
-	g_free (file);
+	if (cnc) {
+		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+		g_return_val_if_fail (gda_connection_get_provider_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 ("mysql_specs_%s.xml", file);
+        g_free (file);
 
 	dir = gda_gbr_get_file_path (GDA_DATA_DIR, LIBGDA_ABI_NAME, NULL);
-	file = gda_server_provider_find_file (provider, dir, str);
+        file = gda_server_provider_find_file (provider, dir, str);
 	g_free (dir);
-	g_free (str);
+        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);
+        if (! file) {
+                g_set_error (error, 0, 0, _("Missing spec. file '%s'"), file);
+                return NULL;
+        }
+        if (!gda_server_operation_is_valid (op, file, error)) {
+                g_free (file);
+                return NULL;
+        }
+        g_free (file);
 
-	switch (gda_server_operation_get_op_type (op)) {
-	case GDA_SERVER_OPERATION_CREATE_DB:
-		sql = gda_mysql_render_CREATE_DB (provider, cnc, op, error);
-		break;
-	case GDA_SERVER_OPERATION_DROP_DB:
-		sql = gda_mysql_render_DROP_DB (provider, cnc, op, error);
-		break;
-	case GDA_SERVER_OPERATION_CREATE_TABLE:
-		sql = gda_mysql_render_CREATE_TABLE (provider, cnc, op, error);
-		break;
-	case GDA_SERVER_OPERATION_DROP_TABLE:
-		sql = gda_mysql_render_DROP_TABLE (provider, cnc, op, error);
-		break;
-	case GDA_SERVER_OPERATION_RENAME_TABLE:
-		sql = gda_mysql_render_RENAME_TABLE (provider, cnc, op, error);
-		break;
-	case GDA_SERVER_OPERATION_ADD_COLUMN:
-		sql = gda_mysql_render_ADD_COLUMN (provider, cnc, op, error);
-		break;
-	case GDA_SERVER_OPERATION_DROP_COLUMN:
-		sql = gda_mysql_render_DROP_COLUMN (provider, cnc, op, error);
-		break;
-	case GDA_SERVER_OPERATION_CREATE_INDEX:
-		sql = gda_mysql_render_CREATE_INDEX (provider, cnc, op, error);
-		break;
-	case GDA_SERVER_OPERATION_DROP_INDEX:
-		sql = gda_mysql_render_DROP_INDEX (provider, cnc, op, error);
-		break;
-	case GDA_SERVER_OPERATION_CREATE_VIEW:
-		sql = gda_mysql_render_CREATE_VIEW (provider, cnc, op, error);
-		break;
-	case GDA_SERVER_OPERATION_DROP_VIEW:
-		sql = gda_mysql_render_DROP_VIEW (provider, cnc, op, error);
-		break;
-	default:
-		g_assert_not_reached ();
-	}
-	return sql;
+	/* 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_mysql_render_CREATE_TABLE (provider, cnc, op, error);
+                break;
+        case GDA_SERVER_OPERATION_DROP_TABLE:
+        case GDA_SERVER_OPERATION_RENAME_TABLE:
+        case GDA_SERVER_OPERATION_ADD_COLUMN:
+        case GDA_SERVER_OPERATION_CREATE_INDEX:
+        case GDA_SERVER_OPERATION_DROP_INDEX:
+        case GDA_SERVER_OPERATION_CREATE_VIEW:
+        case GDA_SERVER_OPERATION_DROP_VIEW:
+                sql = NULL;
+                break;
+        default:
+                g_assert_not_reached ();
+        }
+        return sql;
 }
 
+/*
+ * Perform operation request
+ */
 static gboolean
-gda_mysql_provider_perform_operation (GdaServerProvider *provider, GdaConnection *cnc, 
-				      GdaServerOperation *op, GError **error)
-{
-	GdaServerOperationType optype;
-
-	optype = gda_server_operation_get_op_type (op);
-	if (!cnc && 
-	    ((optype == GDA_SERVER_OPERATION_CREATE_DB) ||
-	     (optype == GDA_SERVER_OPERATION_DROP_DB))) {
-		const GValue *value;
-		MYSQL *mysql;
-		const gchar *login = NULL;
-		const gchar *password = NULL;
-		const gchar *host = NULL;
-		gint         port = -1;
-		const gchar *socket = NULL;
-		gboolean     usessl = FALSE;
-
-		value = gda_server_operation_get_value_at (op, "/SERVER_CNX_P/HOST");
-		if (value && G_VALUE_HOLDS (value, G_TYPE_STRING) && g_value_get_string (value))
-			host = g_value_get_string (value);
-		
-		value = gda_server_operation_get_value_at (op, "/SERVER_CNX_P/PORT");
-		if (value && G_VALUE_HOLDS (value, G_TYPE_INT) && (g_value_get_int (value) > 0))
-			port = g_value_get_int (value);
-
-		value = gda_server_operation_get_value_at (op, "/SERVER_CNX_P/UNIX_SOCKET");
-		if (value && G_VALUE_HOLDS (value, G_TYPE_STRING) && g_value_get_string (value))
-			socket = g_value_get_string (value);
-
-		value = gda_server_operation_get_value_at (op, "/SERVER_CNX_P/USE_SSL");
-		if (value && G_VALUE_HOLDS (value, G_TYPE_BOOLEAN) && g_value_get_boolean (value))
-			usessl = TRUE;
-
-		value = gda_server_operation_get_value_at (op, "/SERVER_CNX_P/ADM_LOGIN");
-		if (value && G_VALUE_HOLDS (value, G_TYPE_STRING) && g_value_get_string (value))
-			login = g_value_get_string (value);
-
-		value = gda_server_operation_get_value_at (op, "/SERVER_CNX_P/ADM_PASSWORD");
-		if (value && G_VALUE_HOLDS (value, G_TYPE_STRING) && g_value_get_string (value))
-			password = g_value_get_string (value);
-
-		mysql = real_open_connection (host, port, socket,
-                                              "mysql", login, password, usessl, error);
-                if (!mysql)
-                        return FALSE;
-		else {
-			gchar *sql;
-			int res;
-
-			sql = gda_server_provider_render_operation (provider, cnc, op, error);
-			if (!sql)
-				return FALSE;
-
-			GdaConnectionEvent *event = gda_connection_event_new (GDA_CONNECTION_EVENT_COMMAND);
-			gda_connection_event_set_description (event, sql);
-			gda_connection_add_event (cnc, event);
+gda_mysql_provider_perform_operation (GdaServerProvider               *provider,
+				      GdaConnection                   *cnc,
+				      GdaServerOperation              *op,
+				      guint                           *task_id, 
+				      GdaServerProviderAsyncCallback   async_cb,
+				      gpointer                         cb_data,
+				      GError                         **error)
+{
+	g_print ("*** %s\n", __func__);
+        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;
+	}
 
-			res = mysql_query (mysql, sql);
-			g_free (sql);
-			
-			if (res) {
-				g_set_error (error, 0, 0, mysql_error (mysql));
-				mysql_close (mysql);
-				return FALSE;
-			}
-			else {
-				mysql_close (mysql);
-				return TRUE;
-			}
-		}
+	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);
 	}
-	else {
+        optype = gda_server_operation_get_op_type (op);
+	switch (optype) {
+	case GDA_SERVER_OPERATION_CREATE_DB: 
+	case GDA_SERVER_OPERATION_DROP_DB: 
+        default: 
 		/* use the SQL from the provider to perform the action */
-		gchar *sql;
-		GdaCommand *cmd;
-		
-		sql = gda_server_provider_render_operation (provider, cnc, op, error);
-		if (!sql)
-			return FALSE;
-		
-		cmd = gda_command_new (sql, GDA_COMMAND_TYPE_SQL, GDA_COMMAND_OPTION_STOP_ON_ERRORS);
-		g_free (sql);
-		if (gda_connection_execute_non_select_command (cnc, cmd, NULL, error) != -1) {
-			gda_command_free (cmd);
-			return TRUE;
-		}
-		else {
-			gda_command_free (cmd);
-			return FALSE;
-		}
+		return gda_server_provider_perform_operation_default (provider, cnc, op, error);
 	}
 }
 
+/*
+ * Begin transaction request
+ */
+static gboolean
+gda_mysql_provider_begin_transaction (GdaServerProvider        *provider,
+				      GdaConnection            *cnc,
+				      const gchar              *name,
+				      GdaTransactionIsolation   level,
+				      GError                  **error)
+{
+	g_print ("*** %s\n", __func__);
+	MysqlConnectionData *cdata;
 
-/* execute_command handler for the GdaMysqlProvider class */
-static GList *
-gda_mysql_provider_execute_command (GdaServerProvider *provider,
-				    GdaConnection *cnc,
-				    GdaCommand *cmd,
-				    GdaParameterList *params)
-{
-	GList *reclist = NULL;
-	gchar *str;
-	GdaMysqlProvider *myprv = (GdaMysqlProvider *) provider;
-
-	g_return_val_if_fail (GDA_IS_MYSQL_PROVIDER (myprv), NULL);
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-	g_return_val_if_fail (cmd != NULL, NULL);
+	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, FALSE);
 
-	switch (gda_command_get_command_type (cmd)) {
-	case GDA_COMMAND_TYPE_SQL :
-		reclist = process_sql_commands (reclist, cnc, gda_command_get_text (cmd));
-		break;
-	case GDA_COMMAND_TYPE_TABLE :
-		str = g_strdup_printf ("SELECT * FROM %s", gda_command_get_text (cmd));
-		reclist = process_sql_commands (reclist, cnc, str);
-		if (reclist && GDA_IS_DATA_MODEL (reclist->data))
-			g_object_set (G_OBJECT (reclist->data), 
-				      "command_text", gda_command_get_text (cmd),
-				      "command_type", GDA_COMMAND_TYPE_TABLE, NULL);
+	cdata = (MysqlConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
+		return FALSE;
 
-		g_free (str);
-		break;
-	default: break;
-	}
+	TO_IMPLEMENT;
 
-	return reclist;
+	return FALSE;
 }
 
-/* get_last_insert_id handler for the GdaMysqlProvider class */
-static gchar *
-gda_mysql_provider_get_last_insert_id (GdaServerProvider *provider,
-				       GdaConnection *cnc,
-				       GdaDataModel *recset)
+/*
+ * Commit transaction request
+ */
+static gboolean
+gda_mysql_provider_commit_transaction (GdaServerProvider  *provider,
+				       GdaConnection      *cnc,
+				       const gchar        *name,
+				       GError            **error)
 {
-	MYSQL *mysql;
-	GdaMysqlProvider *myprv = (GdaMysqlProvider *) provider;
+	g_print ("*** %s\n", __func__);
+	MysqlConnectionData *cdata;
 
-	g_return_val_if_fail (GDA_IS_MYSQL_PROVIDER (myprv), 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);
 
-	if (recset) {
-		g_return_val_if_fail (GDA_IS_MYSQL_RECORDSET (recset), NULL);
-		TO_IMPLEMENT;
-		return NULL;
-	}
+	cdata = (MysqlConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
+		return FALSE;
 
-	mysql = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_MYSQL_HANDLE);
-	if (!mysql) {
-		gda_connection_add_event_string (cnc, _("Invalid MySQL handle"));
-		return NULL;
-	}
+	TO_IMPLEMENT;
 
-	return g_strdup_printf ("%ld", (unsigned long int ) mysql_insert_id (mysql));
+	return FALSE;
 }
 
-/* begin_transaction handler for the GdaMysqlProvider class */
+/*
+ * Rollback transaction request
+ */
 static gboolean
-gda_mysql_provider_begin_transaction (GdaServerProvider *provider,
-				      GdaConnection *cnc,
-				      const gchar *name, GdaTransactionIsolation level,
-				      GError **error)
-{
-	MYSQL *mysql;
-	gint rc;
-	GdaMysqlProvider *myprv = (GdaMysqlProvider *) provider;
-	GdaConnectionEvent *event = NULL;
+gda_mysql_provider_rollback_transaction (GdaServerProvider  *provider,
+					 GdaConnection      *cnc,
+					 const gchar        *name,
+					 GError            **error)
+{
+	g_print ("*** %s\n", __func__);
+	MysqlConnectionData *cdata;
 
-	g_return_val_if_fail (GDA_IS_MYSQL_PROVIDER (myprv), FALSE);
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, FALSE);
 
-	mysql = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_MYSQL_HANDLE);
-	if (!mysql) {
-		gda_connection_add_event_string (cnc, _("Invalid MySQL handle"));
-		return FALSE;
-	}
-
-	if (gda_connection_get_options (cnc) & GDA_CONNECTION_OPTIONS_READ_ONLY) {
-		gda_connection_add_event_string (cnc, _("Transactions are not supported in read-only mode"));
+	cdata = (MysqlConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
 		return FALSE;
-	}
 
-	/* set isolation level */
-	switch (level) {
-	case GDA_TRANSACTION_ISOLATION_READ_COMMITTED :
-		rc = gda_mysql_real_query_wrap (cnc, mysql, "SET TRANSACTION ISOLATION LEVEL READ COMMITTED", 46);
-		break;
-	case GDA_TRANSACTION_ISOLATION_READ_UNCOMMITTED :
-		rc = gda_mysql_real_query_wrap (cnc, mysql, "SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED", 48);
-		break;
-	case GDA_TRANSACTION_ISOLATION_REPEATABLE_READ :
-		rc = gda_mysql_real_query_wrap (cnc, mysql, "SET TRANSACTION ISOLATION LEVEL REPEATABLE READ", 47);
-		break;
-	case GDA_TRANSACTION_ISOLATION_SERIALIZABLE :
-		rc = gda_mysql_real_query_wrap (cnc, mysql, "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE", 44);
-		break;
-	default :
-		rc = 0;
-	}
+	TO_IMPLEMENT;
 
-	if (rc != 0) {
-		event = gda_mysql_make_error (mysql);
-		gda_connection_add_event (cnc, event);
-	}
-	else {
-		/* start the transaction */
-		rc = gda_mysql_real_query_wrap (cnc, mysql, "BEGIN", 5);
-		if (rc != 0) {
-			event = gda_mysql_make_error (mysql);
-			gda_connection_add_event (cnc, event);
-		}
-	}
-	
-	gda_connection_internal_treat_sql (cnc, "BEGIN", event);
-	return event ? FALSE : TRUE;
+	return FALSE;
 }
 
-/* commit_transaction handler for the GdaMysqlProvider class */
+/*
+ * Add savepoint request
+ */
 static gboolean
-gda_mysql_provider_commit_transaction (GdaServerProvider *provider,
-				       GdaConnection *cnc,
-				       const gchar *name, GError **error)
-{
-	MYSQL *mysql;
-	gint rc;
-	GdaMysqlProvider *myprv = (GdaMysqlProvider *) provider;
-	GdaConnectionEvent *event = NULL;
+gda_mysql_provider_add_savepoint (GdaServerProvider  *provider,
+				  GdaConnection      *cnc,
+				  const gchar        *name,
+				  GError            **error)
+{
+	g_print ("*** %s\n", __func__);
+	MysqlConnectionData *cdata;
 
-	g_return_val_if_fail (GDA_IS_MYSQL_PROVIDER (myprv), FALSE);
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, FALSE);
 
-	mysql = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_MYSQL_HANDLE);
-	if (!mysql) {
-		gda_connection_add_event_string (cnc, _("Invalid MySQL handle"));
-		return FALSE;
-	}
-
-	if (gda_connection_get_options (cnc) & GDA_CONNECTION_OPTIONS_READ_ONLY) {
-		gda_connection_add_event_string (cnc, _("Transactions are not supported in read-only mode"));
+	cdata = (MysqlConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
 		return FALSE;
-	}
 
-	rc = gda_mysql_real_query_wrap (cnc, mysql, "COMMIT", 6);
-	if (rc != 0) {
-		event = gda_mysql_make_error (mysql);
-		gda_connection_add_event (cnc, event);
-	}
+	TO_IMPLEMENT;
 
-	gda_connection_internal_treat_sql (cnc, "COMMIT", event);
-	return event ? FALSE : TRUE;
+	return FALSE;
 }
 
-/* rollback_transaction handler for the GdaMysqlProvider class */
-static gboolean
-gda_mysql_provider_rollback_transaction (GdaServerProvider *provider,
-					 GdaConnection *cnc,
-					 const gchar *name, GError **error)
-{
-	MYSQL *mysql;
-	gint rc;
-	GdaMysqlProvider *myprv = (GdaMysqlProvider *) provider;
-	GdaConnectionEvent *event = NULL;
+/*
+ * Rollback savepoint request
+ */
+static gboolean
+gda_mysql_provider_rollback_savepoint (GdaServerProvider  *provider,
+				       GdaConnection      *cnc,
+				       const gchar        *name,
+				       GError            **error)
+{
+	g_print ("*** %s\n", __func__);
+	MysqlConnectionData *cdata;
 
-	g_return_val_if_fail (GDA_IS_MYSQL_PROVIDER (myprv), FALSE);
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, FALSE);
 
-	mysql = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_MYSQL_HANDLE);
-	if (!mysql) {
-		gda_connection_add_event_string (cnc, _("Invalid MySQL handle"));
-		return FALSE;
-	}
-
-	if (gda_connection_get_options (cnc) & GDA_CONNECTION_OPTIONS_READ_ONLY) {
-		gda_connection_add_event_string (cnc, _("Transactions are not supported in read-only mode"));
+	cdata = (MysqlConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
 		return FALSE;
-	}
 
-	rc = gda_mysql_real_query_wrap (cnc, mysql, "ROLLBACK", 8);
-	if (rc != 0) {
-		event = gda_mysql_make_error (mysql);
-		gda_connection_add_event (cnc, event);
-	}
-
-	gda_connection_internal_treat_sql (cnc, "ROLLBACK", event);
-	return event ? FALSE : TRUE;
-}
-
-/* supports handler for the GdaMysqlProvider class */
-static gboolean
-gda_mysql_provider_supports (GdaServerProvider *provider,
-			     GdaConnection *cnc,
-			     GdaConnectionFeature feature)
-{
-	GdaMysqlProvider *myprv = (GdaMysqlProvider *) provider;
-
-	g_return_val_if_fail (GDA_IS_MYSQL_PROVIDER (myprv), FALSE);
-
-	switch (feature) {
-	case GDA_CONNECTION_FEATURE_AGGREGATES :
-	case GDA_CONNECTION_FEATURE_SQL :
-	case GDA_CONNECTION_FEATURE_TRANSACTIONS :
-		return TRUE;
-	default : break;
-	}
+	TO_IMPLEMENT;
 
 	return FALSE;
 }
 
-static GdaServerProviderInfo *
-gda_mysql_provider_get_info (GdaServerProvider *provider, GdaConnection *cnc)
+/*
+ * Delete savepoint request
+ */
+static gboolean
+gda_mysql_provider_delete_savepoint (GdaServerProvider  *provider,
+				     GdaConnection      *cnc,
+				     const gchar        *name,
+				     GError            **error)
 {
-	static GdaServerProviderInfo info = {
-		"MySQL",
-		TRUE, 
-		TRUE,
-		TRUE,
-		TRUE,
-		TRUE,
-		FALSE
-	};
-	
-	return &info;
-}
+	g_print ("*** %s\n", __func__);
+	MysqlConnectionData *cdata;
 
-static void
-add_aggregate_row (GdaDataModelArray *recset, const gchar *str, const gchar *comments)
-{
-	GList *list;
-	GValue *tmpval;
+	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_if_fail (GDA_IS_DATA_MODEL_ARRAY (recset));
+	cdata = (MysqlConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
+		return FALSE;
 
-	/* 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 */
-	list = g_list_append (list, gda_value_new_null ());
-	/* 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 */
-	list = g_list_append (list, gda_value_new_null ());
-	/* 6th the argument type */
-	list = g_list_append (list, gda_value_new_null ());
-	/* 7th the SQL definition */
-	list = g_list_append (list, gda_value_new_null ());
-
-	gda_data_model_append_values (GDA_DATA_MODEL (recset), list, NULL);
+	TO_IMPLEMENT;
 
-	g_list_foreach (list, (GFunc) gda_value_free, NULL);
-	g_list_free (list);
+	return FALSE;
 }
 
-static GdaDataModel *
-get_mysql_aggregates (GdaConnection *cnc, GdaParameterList *params)
+/*
+ * Feature support request
+ */
+static gboolean
+gda_mysql_provider_supports_feature (GdaServerProvider     *provider,
+				     GdaConnection         *cnc,
+				     GdaConnectionFeature   feature)
 {
-	GdaDataModelArray *recset;
-
-	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_AGGREGATES));
-	gda_server_provider_init_schema_model (GDA_DATA_MODEL (recset), GDA_CONNECTION_SCHEMA_AGGREGATES);
-
-	/* fill the recordset */
-	add_aggregate_row (recset, "abs", "");
-	add_aggregate_row (recset, "acos", "");
-	add_aggregate_row (recset, "adddate", "");
-	add_aggregate_row (recset, "ascii", "");
-	add_aggregate_row (recset, "asin", "");
-	add_aggregate_row (recset, "atan", "");
-	add_aggregate_row (recset, "atan2", "");
-	add_aggregate_row (recset, "benchmark", "");
-	add_aggregate_row (recset, "bin", "");
-	add_aggregate_row (recset, "bit_count", "");
-	add_aggregate_row (recset, "ceiling", "");
-	add_aggregate_row (recset, "char", "");
-	add_aggregate_row (recset, "char_length", "");
-	add_aggregate_row (recset, "character_length", "");
-	add_aggregate_row (recset, "coalesce", "");
-	add_aggregate_row (recset, "concat", "");
-	add_aggregate_row (recset, "concat_ws", "");
-	add_aggregate_row (recset, "connection_id", "");
-	add_aggregate_row (recset, "conv", "");
-	add_aggregate_row (recset, "cos", "");
-	add_aggregate_row (recset, "cot", "");
-	add_aggregate_row (recset, "count", "");
-	add_aggregate_row (recset, "curdate", "");
-	add_aggregate_row (recset, "current_date", "");
-	add_aggregate_row (recset, "current_time", "");
-	add_aggregate_row (recset, "current_timestamp", "");
-	add_aggregate_row (recset, "curtime", "");
-	add_aggregate_row (recset, "database", "");
-	add_aggregate_row (recset, "date_add", "");
-	add_aggregate_row (recset, "date_format", "");
-	add_aggregate_row (recset, "date_sub", "");
-	add_aggregate_row (recset, "dayname", "");
-	add_aggregate_row (recset, "dayofmonth", "");
-	add_aggregate_row (recset, "dayofweek", "");
-	add_aggregate_row (recset, "dayofyear", "");
-	add_aggregate_row (recset, "decode", "");
-	add_aggregate_row (recset, "degrees", "");
-	add_aggregate_row (recset, "elt", "");
-	add_aggregate_row (recset, "encode", "");
-	add_aggregate_row (recset, "encrypt", "");
-	add_aggregate_row (recset, "exp", "");
-	add_aggregate_row (recset, "export_set", "");
-	add_aggregate_row (recset, "extract", "");
-	add_aggregate_row (recset, "field", "");
-	add_aggregate_row (recset, "find_in_set", "");
-	add_aggregate_row (recset, "floor", "");
-	add_aggregate_row (recset, "format", "");
-	add_aggregate_row (recset, "from_days", "");
-	add_aggregate_row (recset, "from_unixtime", "");
-	add_aggregate_row (recset, "get_lock", "");
-	add_aggregate_row (recset, "greatest", "");
-	add_aggregate_row (recset, "hex", "");
-	add_aggregate_row (recset, "hour", "");
-	add_aggregate_row (recset, "if", "");
-	add_aggregate_row (recset, "ifnull", "");
-	add_aggregate_row (recset, "inet_aton", "");
-	add_aggregate_row (recset, "inet_ntoa", "");
-	add_aggregate_row (recset, "insert", "");
-	add_aggregate_row (recset, "instr", "");
-	add_aggregate_row (recset, "interval", "");
-	add_aggregate_row (recset, "isnull", "");
-	add_aggregate_row (recset, "last_insert_id", "");
-	add_aggregate_row (recset, "lcase", "");
-	add_aggregate_row (recset, "least", "");
-	add_aggregate_row (recset, "left", "");
-	add_aggregate_row (recset, "length", "");
-	add_aggregate_row (recset, "load_file", "");
-	add_aggregate_row (recset, "locate", "");
-	add_aggregate_row (recset, "log", "");
-	add_aggregate_row (recset, "log10", "");
-	add_aggregate_row (recset, "lower", "");
-	add_aggregate_row (recset, "lpad", "");
-	add_aggregate_row (recset, "ltrim", "");
-	add_aggregate_row (recset, "make_set", "");
-	add_aggregate_row (recset, "master_pos_wait", "");
-	add_aggregate_row (recset, "match", "");
-	add_aggregate_row (recset, "max", "");
-	add_aggregate_row (recset, "md5", "");
-	add_aggregate_row (recset, "mid", "");
-	add_aggregate_row (recset, "min", "");
-	add_aggregate_row (recset, "minute", "");
-	add_aggregate_row (recset, "mod", "");
-	add_aggregate_row (recset, "month", "");
-	add_aggregate_row (recset, "monthname", "");
-	add_aggregate_row (recset, "now", "");
-	add_aggregate_row (recset, "nullif", "");
-	add_aggregate_row (recset, "oct", "");
-	add_aggregate_row (recset, "octet_length", "");
-	add_aggregate_row (recset, "ord", "");
-	add_aggregate_row (recset, "password", "");
-	add_aggregate_row (recset, "period_add", "");
-	add_aggregate_row (recset, "period_diff", "");
-	add_aggregate_row (recset, "pi", "");
-	add_aggregate_row (recset, "position", "");	
-	add_aggregate_row (recset, "pow", "");
-	add_aggregate_row (recset, "power", "");
-	add_aggregate_row (recset, "quarter", "");
-	add_aggregate_row (recset, "radians", "");
-	add_aggregate_row (recset, "rand", "");
-	add_aggregate_row (recset, "release_lock", "");
-	add_aggregate_row (recset, "repeat", "");
-	add_aggregate_row (recset, "replace", "");	
-	add_aggregate_row (recset, "reverse", "");
-	add_aggregate_row (recset, "right", "");
-	add_aggregate_row (recset, "round", "");
-	add_aggregate_row (recset, "rpad", "");
-	add_aggregate_row (recset, "rtrim", "");
-	add_aggregate_row (recset, "second", "");
-	add_aggregate_row (recset, "sec_to_time", "");
-	add_aggregate_row (recset, "session_user", "");
-	add_aggregate_row (recset, "sign", "");
-	add_aggregate_row (recset, "sin", "");
-	add_aggregate_row (recset, "soundex", "");
-	add_aggregate_row (recset, "space", "");
-	add_aggregate_row (recset, "sqrt", "");
-	add_aggregate_row (recset, "strcmp", "");
-	add_aggregate_row (recset, "subdate", "");
-	add_aggregate_row (recset, "substring", "");
-	add_aggregate_row (recset, "substring_index", "");
-	add_aggregate_row (recset, "sysdate", "");
-	add_aggregate_row (recset, "system_user", "");
-	add_aggregate_row (recset, "tan", "");
-	add_aggregate_row (recset, "time_format", "");
-	add_aggregate_row (recset, "time_to_sec", "");
-	add_aggregate_row (recset, "to_days", "");
-	add_aggregate_row (recset, "trim", "");
-	add_aggregate_row (recset, "truncate", "");
-	add_aggregate_row (recset, "ucase", "");
-	add_aggregate_row (recset, "unix_timestamp", "");
-	add_aggregate_row (recset, "upper", "");
-	add_aggregate_row (recset, "user", "");
-	add_aggregate_row (recset, "version", "");
-	add_aggregate_row (recset, "week", "");
-	add_aggregate_row (recset, "weekday", "");
-	add_aggregate_row (recset, "year", "");
-	add_aggregate_row (recset, "yearweek", "");
+	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);
+	}
 
-	return GDA_DATA_MODEL (recset);
+	switch (feature) {
+	case GDA_CONNECTION_FEATURE_SQL :
+		return TRUE;
+	default: 
+		return FALSE;
+	}
 }
 
-static GdaDataModel *
-get_mysql_databases (GdaConnection *cnc, GdaParameterList *params)
-{
-	GList *reclist;
-	GdaMysqlRecordset *recset;
-
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-
-	reclist = process_sql_commands (NULL, cnc, "show databases");
-	if (!reclist)
-		return NULL;
+/*
+ * 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_mysql_provider_get_data_handler (GdaServerProvider  *provider,
+				     GdaConnection      *cnc,
+				     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);
+		g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, FALSE);
+	}
 
-	recset = GDA_MYSQL_RECORDSET (reclist->data);
-	g_list_free (reclist);
+	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 GDA_DATA_MODEL (recset);
+	return dh;
 }
 
-static GdaDataModel *
-get_mysql_tables (GdaConnection *cnc, GdaParameterList *params)
+/*
+ * Get default DBMS type request
+ *
+ * This method returns the "preferred" DBMS type for GType
+ */
+static const gchar*
+gda_mysql_provider_get_default_dbms_type (GdaServerProvider  *provider,
+					  GdaConnection      *cnc,
+					  GType               type)
 {
-	GList *reclist;
-	GdaMysqlRecordset *recset;
-	GdaDataModel *model;
-	gint rows, r;
-	GdaParameter *par = NULL;
-	const gchar *tablename = NULL;
-	
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-
-	if (params) {
-		par = gda_parameter_list_find_param (params, "name");
-		if (par)
-			tablename = g_value_get_string ((GValue *) gda_parameter_get_value (par));
+	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);
 	}
 
-	reclist = process_sql_commands (NULL, cnc, "show table status");
-	if (!reclist)
-		return NULL;
-
-	recset = (GdaMysqlRecordset *) reclist->data;
-	g_list_free (reclist);
-	if (!GDA_IS_MYSQL_RECORDSET (recset))
-		return NULL;
-
-	/* add the extra information */
-	model = gda_data_model_array_new (gda_server_provider_get_schema_nb_columns (GDA_CONNECTION_SCHEMA_TABLES));
-	gda_server_provider_init_schema_model (model, GDA_CONNECTION_SCHEMA_TABLES);
-
-	rows = gda_data_model_get_n_rows (GDA_DATA_MODEL (recset));
-	for (r = 0; r < rows; r++) {
-		GList *value_list = NULL;
-		const gchar *name;
-		gchar *str;
-		GValue *tmpval;
+	TO_IMPLEMENT;
 
-		if (tablename) {
-			const GValue *cvalue;
-			
-			cvalue = gda_data_model_get_value_at (GDA_DATA_MODEL (recset), 0, r);
-			if (strcmp (tablename, g_value_get_string (cvalue)))
-				continue;
-		}
-
-		/* 1st, the name of the table */
-		tmpval = gda_value_copy ((GValue *) gda_data_model_get_value_at (GDA_DATA_MODEL (recset), 0, r));
-		name = g_value_get_string (tmpval);
-		value_list = g_list_append (value_list, tmpval);
-
-		/* 2nd, the owner */
-		value_list = g_list_append (value_list, gda_value_new_null ());
-
-		/* 3rd, the comments */
-		tmpval = gda_value_copy ((GValue *) gda_data_model_get_value_at (GDA_DATA_MODEL (recset), 14, r));
-		value_list = g_list_append (value_list, tmpval);
-
-		/* 4th, the SQL command */
-		str = g_strdup_printf ("SHOW CREATE TABLE %s", name);
-		reclist = process_sql_commands (NULL, cnc, str);
-		g_free (str);
-		if (reclist && GDA_IS_DATA_MODEL (reclist->data)) {
-			tmpval = gda_value_copy ((GValue *) gda_data_model_get_value_at (GDA_DATA_MODEL (reclist->data), 1, 0));
-			value_list = g_list_append (value_list, tmpval);
-
-			g_list_foreach (reclist, (GFunc) g_object_unref, NULL);
-			g_list_free (reclist);
-		}
-		else
-			value_list = g_list_append (value_list, gda_value_new_null ());
+	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";
+
+	if ((type == GDA_TYPE_BINARY) ||
+	    (type == GDA_TYPE_BLOB))
+		return "blob";
 
-		gda_data_model_append_values (model, value_list, NULL);
+	if (type == G_TYPE_BOOLEAN)
+		return "boolean";
+	
+	if ((type == G_TYPE_DATE) || 
+	    (type == GDA_TYPE_GEOMETRIC_POINT) ||
+	    (type == G_TYPE_OBJECT) ||
+	    (type == GDA_TYPE_LIST) ||
+	    (type == G_TYPE_STRING) ||
+	    (type == GDA_TYPE_TIME) ||
+	    (type == GDA_TYPE_TIMESTAMP) ||
+	    (type == G_TYPE_INVALID))
+		return "string";
 
-		g_list_foreach (value_list, (GFunc) gda_value_free, NULL);
-		g_list_free (value_list);
-	}
+	if ((type == G_TYPE_DOUBLE) ||
+	    (type == GDA_TYPE_NUMERIC) ||
+	    (type == G_TYPE_FLOAT))
+		return "real";
+	
+	if (type == GDA_TYPE_TIME)
+		return "time";
+	if (type == GDA_TYPE_TIMESTAMP)
+		return "timestamp";
+	if (type == G_TYPE_DATE)
+		return "date";
 
-	return model;
+	return "text";
 }
 
-static GdaDataModel *
-get_mysql_views (GdaConnection *cnc, GdaParameterList *params)
+/*
+ * Create parser request
+ *
+ * This method is responsible for creating a #GdaSqlParser object specific to the SQL dialect used
+ * by the database. See the PostgreSQL provider implementation for an example.
+ */
+static GdaSqlParser *
+gda_mysql_provider_create_parser (GdaServerProvider  *provider,
+				  GdaConnection      *cnc)
 {
-	GdaDataModel *model;
-
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-
-	/* add the extra information */
-	model = gda_data_model_array_new (gda_server_provider_get_schema_nb_columns (GDA_CONNECTION_SCHEMA_VIEWS));
-	gda_server_provider_init_schema_model (model, GDA_CONNECTION_SCHEMA_VIEWS);
-
-	/* views are not yet supported in MySql => return an empty set */
-
-	return model;
-}
-
-static GdaDataModel *
-get_mysql_procedures (GdaConnection *cnc, GdaParameterList *params)
-{
-	GdaDataModel *model;
-	gint i;
-
-	struct {
-		const gchar *name;
-		const gchar *id;
-		/*const gchar *owner; "" */
-		const gchar *comments;
-		const gchar *rettype;
-		gint         nb_args;
-		const gchar *argtypes;
-		/*const gchar *definition; NULL */
-	} procs[] = {
-		{ "ascii", "ascii", "", "smallint", 1, "text"},
-		{ "bin", "bin", "", "text", 1, "bigint"},
-		{ "bit_length", "bit_length", "", "int", 1, "text"},
-		{ "char", "char", "", "text", -1, "-"}
-	};
-
-
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-
-	/* add the extra information */
-	model = gda_data_model_array_new (gda_server_provider_get_schema_nb_columns (GDA_CONNECTION_SCHEMA_PROCEDURES));
-	gda_server_provider_init_schema_model (model, GDA_CONNECTION_SCHEMA_PROCEDURES);
-
-	/* fill the recordset */
-	for (i = 0; i < sizeof (procs) / sizeof (procs[0]); i++) {
-		GList *value_list = NULL;
-		GValue *tmpval;
-		
-		g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), procs[i].name);
-		value_list = g_list_append (value_list, tmpval);
-		
-		g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), procs[i].id);
-		value_list = g_list_append (value_list, tmpval);
-		
-		value_list = g_list_append (value_list, gda_value_new_null ());
-		
-		g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), procs[i].comments);
-		value_list = g_list_append (value_list, tmpval);
-		
-		g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), procs[i].rettype);
-		value_list = g_list_append (value_list, tmpval);
-
-		g_value_set_int (tmpval = gda_value_new (G_TYPE_INT), procs[i].nb_args);
-		value_list = g_list_append (value_list, tmpval);
-
-		g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), procs[i].argtypes);
-		value_list = g_list_append (value_list, tmpval);
-
-		value_list = g_list_append (value_list, gda_value_new_null ());
-
-		gda_data_model_append_values (GDA_DATA_MODEL (model), value_list, NULL);
-
-		g_list_foreach (value_list, (GFunc) gda_value_free, NULL);
-		g_list_free (value_list);
-	}
-
-	return model;
-}
-
-
-static GdaDataModel *
-get_mysql_types (GdaConnection *cnc, GdaParameterList *params)
-{
-	GdaDataModelArray *recset;
-	gint i;
-	struct {
-		const gchar *name;
-		const gchar *owner;
-		const gchar *comments;
-		GType type;
-		const gchar *synonyms;
-	} types[] = {
-		{ "bool", "", "Boolean type", G_TYPE_BOOLEAN, "boolean" },
-		{ "blob", "", "Binary blob (up to 65535 bytes)", GDA_TYPE_BINARY, NULL },
-		{ "bigint", "", "Big integer, range is -9223372036854775808 to 9223372036854775807", G_TYPE_INT64, NULL  },
-		{ "bigint unsigned", "", "Big unsigned integer, range is 0 to 18446744073709551615", G_TYPE_UINT64, NULL  },
-		{ "char", "", "Char", G_TYPE_STRING, "binary"  },
-		{ "date", "", "Date", G_TYPE_DATE, NULL  },
-		{ "datetime", "", "Date and time", GDA_TYPE_TIMESTAMP, NULL  },
-		{ "decimal", "", "Decimal number", GDA_TYPE_NUMERIC, "dec,numeric,fixed"  },
-		{ "double", "", "Double precision number", G_TYPE_DOUBLE, "double precision,real"  },
-		{ "double unsigned", "", "Unsigned double precision number", G_TYPE_DOUBLE, "double precision unsigned,real unsigned"  },
-		{ "enum", "", "Enumeration: a string object that can have only one value, chosen from the list of values 'value1', 'value2', ..., NULL or the special '' error value. An ENUM column can have a maximum of 65,535 distinct values", G_TYPE_STRING, NULL  },
-		{ "float", "", "Floating point number", G_TYPE_FLOAT , NULL },
-		{ "float unsigned", "", "Unsigned floating point number", G_TYPE_FLOAT , NULL },
-		{ "int", "", "Integer, range is -2147483648 to 2147483647", G_TYPE_INT, "integer"  },
-		{ "int unsigned", "", "Unsigned integer, range is 0 to 4294967295", G_TYPE_UINT, "integer unsigned"  },
-		{ "long", "", "Long integer", G_TYPE_LONG, NULL  },
-		{ "long unsigned", "", "Long unsigned integer", G_TYPE_ULONG, NULL  },
-		{ "longblob", "", "Long blob (up to 4Gb)", GDA_TYPE_BINARY, NULL  },
-		{ "longtext", "", "Long text (up to 4Gb characters)", GDA_TYPE_BINARY, NULL  },
-		{ "mediumint", "", "Medium integer, range is -8388608 to 8388607", G_TYPE_INT, NULL  },
-		{ "mediumint unsigned", "", "Medium unsigned integer, range is 0 to 16777215", G_TYPE_INT, NULL  },
-		{ "mediumblob", "", "Medium blob (up to 16777215 bytes)", GDA_TYPE_BINARY, NULL  },
-		{ "mediumtext", "", "Medium text (up to 16777215 characters)", GDA_TYPE_BINARY, NULL  },				
-		{ "set", "", "Set: a string object that can have zero or more values, each of which must be chosen from the list of values 'value1', 'value2', ... A SET column can have a maximum of 64 members", G_TYPE_STRING, NULL  },
-		{ "smallint", "", "Small integer, range is -32768 to 32767", GDA_TYPE_SHORT, NULL  },
-		{ "smallint unsigned", "", "Small unsigned integer, range is 0 to 65535", GDA_TYPE_USHORT, NULL  },
-		{ "text", "", "Text (up to 65535 characters)", GDA_TYPE_BINARY, NULL  },
-		{ "tinyint", "", "Tiny integer, range is -128 to 127", G_TYPE_CHAR, "bit" },
-		{ "tinyint unsigned", "", "Tiny unsigned integer, range is 0 to 255", G_TYPE_UCHAR, NULL  },
-		{ "tinyblob", "", "Tiny blob (up to 255 bytes)", GDA_TYPE_BINARY, NULL  },
-		{ "tinytext", "", "Tiny text (up to 255 characters)", GDA_TYPE_BINARY, NULL  },		
-		{ "time", "", "Time", GDA_TYPE_TIME, NULL  },
-		{ "timestamp", "", "Time stamp", GDA_TYPE_TIMESTAMP, NULL  },
-		{ "varchar", "", "Variable Length Char", G_TYPE_STRING, "varbinary"  },
-		{ "year", "", "Year", G_TYPE_INT, NULL  }
-	};
-
-	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);
-	
-	/* fill the recordset */
-	for (i = 0; i < sizeof (types) / sizeof (types[0]); i++) {
-		GList *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);
-		
-		g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), types[i].owner);		
-		value_list = g_list_append (value_list, tmpval);
-		
-		g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), types[i].comments);		
-		value_list = g_list_append (value_list, tmpval);
-		
-		g_value_set_ulong (tmpval = gda_value_new (G_TYPE_ULONG), types[i].type);		
-		value_list = g_list_append (value_list, tmpval);
-		
-		g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), types[i].synonyms);		
-		value_list = g_list_append (value_list, tmpval);
-
-		gda_data_model_append_values (GDA_DATA_MODEL (recset), value_list, NULL);
+	g_print ("*** %s\n", __func__);
+	// TO_IMPLEMENT;
+	return (GdaSqlParser *) g_object_new (GDA_TYPE_MYSQL_PARSER,
+					      "tokenizer-flavour", GDA_SQL_PARSER_FLAVOUR_MYSQL,
+					      NULL);
+}
 
-		g_list_foreach (value_list, (GFunc) gda_value_free, NULL);
-		g_list_free (value_list);
+/*
+ * 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_mysql_provider_statement_to_sql (GdaServerProvider    *provider,
+				     GdaConnection        *cnc,
+				     GdaStatement         *stmt,
+				     GdaSet               *params,
+				     GdaStatementSqlFlag   flags,
+				     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);
+		g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, NULL);
 	}
 
-	return GDA_DATA_MODEL (recset);
+	return gda_statement_to_sql_extended (stmt, cnc, params, flags, params_used, error);
 }
 
-static GList *
-field_row_to_value_list (MYSQL *mysql, MYSQL_ROW mysql_row)
-{
-	gchar **arr;
-	GList *value_list = NULL;
-	GValue *tmpval;
-	
-	g_return_val_if_fail (mysql_row != NULL, NULL);
-
-	/* field name */
-	g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), mysql_row[0]);
-	value_list = g_list_append (value_list, tmpval);
-
-	/* type and size */
-	arr = g_strsplit_set ((const gchar *) mysql_row[1], "() ", 0);
-	if (!arr) {
-		g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), "");
-		value_list = g_list_append (value_list, tmpval);
+/*
+ * 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 #GdaMysqlPStmt object and declare it to @cnc.
+ */
+static gboolean
+gda_mysql_provider_statement_prepare (GdaServerProvider  *provider,
+				      GdaConnection      *cnc,
+				      GdaStatement       *stmt,
+				      GError            **error)
+{
+	g_print ("*** %s\n", __func__);
+	GdaMysqlPStmt *ps;
+	MysqlConnectionData *cdata;
 
-		g_value_set_int (tmpval = gda_value_new (G_TYPE_INT), -1);
-		value_list = g_list_append (value_list, tmpval);
-	}
-	else {
-		if (!strcmp (arr[0], "enum") ||
-		    !strcmp (arr[0], "set")) {
-			g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), arr[0]);
-			value_list = g_list_append (value_list, tmpval);
-			
-			g_value_set_int (tmpval = gda_value_new (G_TYPE_INT), -1);
-			value_list = g_list_append (value_list, tmpval);
-		}
-		else {
-			if (arr[0] && arr[1]) {
-				gint i, len;
-				len = g_strv_length (arr);
-				for (i = 2; (i < len) && strcmp (arr[i], "unsigned"); i++);
-				if (i < len) {
-					gchar *type;
-
-					type = g_strdup_printf ("%s unsigned", arr[0]);
-					g_value_take_string (tmpval = gda_value_new (G_TYPE_STRING), type);
-				}
-				else
-					g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), arr[0]);
-				value_list = g_list_append (value_list, tmpval);
+	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 arr[0] is an int type, hard code its size instead of
-				 * using arr[1] which is an indication of display padding */
-				if (!strcmp (arr[0], "int"))
-					g_value_set_int (tmpval = gda_value_new (G_TYPE_INT), 4);
-				else if (!strcmp (arr[0], "tinyint"))
-					g_value_set_int (tmpval = gda_value_new (G_TYPE_INT), 1);
-				else if (!strcmp (arr[0], "smallint"))
-					g_value_set_int (tmpval = gda_value_new (G_TYPE_INT), 2);
-				else if (!strcmp (arr[0], "mediumint"))
-					g_value_set_int (tmpval = gda_value_new (G_TYPE_INT), 3);
-				else if (!strcmp (arr[0], "bigint"))
-					g_value_set_int (tmpval = gda_value_new (G_TYPE_INT), 8);
-				else
-					g_value_set_int (tmpval = gda_value_new (G_TYPE_INT), atoi (arr[1]));
+	/* fetch prepares stmt if already done */
+	ps = gda_connection_get_prepared_statement (cnc, stmt);
+	if (ps)
+		return TRUE;
 
-				value_list = g_list_append (value_list, tmpval);
-			}
-			else {
-				g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), arr[0]);
-				value_list = g_list_append (value_list, tmpval);
-				
-				g_value_set_int (tmpval = gda_value_new (G_TYPE_INT), -1);
-				value_list = g_list_append (value_list, tmpval);
-			}
-		}
+	/* prepare @stmt using the C API, creates @ps */
+	// TO_IMPLEMENT;
+	
 
-		g_strfreev (arr);
-	}
+	cdata = (MysqlConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
+		return FALSE;
+	/* Render as SQL understood by Mysql. */
+	GdaSet *set;
+	if (!gda_statement_get_parameters (stmt, &set, error))
+		return FALSE;
 
-	/* scale */
-	g_value_set_int (tmpval = gda_value_new (G_TYPE_INT), 0);
-	value_list = g_list_append (value_list, tmpval);
+	GSList *used_set = NULL;
+	gchar *sql = gda_mysql_provider_statement_to_sql
+		(provider, cnc, stmt, set,
+		 GDA_STATEMENT_SQL_PARAMS_AS_QMARK, &used_set, error);
 
-	/* Not null? */
-	if (mysql_row[2] && !strcmp (mysql_row[2], "YES"))
-		g_value_set_boolean (tmpval = gda_value_new (G_TYPE_BOOLEAN), FALSE);
-	else
-		g_value_set_boolean (tmpval = gda_value_new (G_TYPE_BOOLEAN), TRUE);
-	value_list = g_list_append (value_list, tmpval);
+	
+	if (!sql)
+		goto cleanup;
 
-	/* Primary key? */
-	if (mysql_row[3] && !strcmp (mysql_row[3], "PRI"))
-		g_value_set_boolean (tmpval = gda_value_new (G_TYPE_BOOLEAN), TRUE);
-	else
-		g_value_set_boolean (tmpval = gda_value_new (G_TYPE_BOOLEAN), FALSE);
-	value_list = g_list_append (value_list, tmpval);
+	if (mysql_stmt_prepare (cdata->mysql_stmt, sql, strlen (sql))) {
+		GdaConnectionEvent *event = _gda_mysql_make_error
+			(cdata->cnc, cdata->mysql, NULL);
+		goto cleanup;
+	}
+
+	GSList *param_ids = NULL, *current;
+	for (current = used_set; current; current = current->next) {
+		const gchar *id = gda_holder_get_id
+			(GDA_HOLDER(current->data));
+		if (id) {
+			param_ids = g_slist_append (param_ids,
+						    g_strdup (id));
+			g_print ("MYSQL preparation: param id=%s\n", id);
+		} else {
+			g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+				     GDA_SERVER_PROVIDER_PREPARE_STMT_ERROR,
+				     _("Unnamed holder is not allowed in prepared statement."));
+			g_slist_foreach (param_ids, (GFunc) g_free, NULL);
+			g_slist_free (param_ids);
+			param_ids = NULL;
 
-	/* Unique index? */
-	g_value_set_boolean (tmpval = gda_value_new (G_TYPE_BOOLEAN), FALSE);
-	value_list = g_list_append (value_list, tmpval);
-
-	/* references */
-	if (atoi (mysql->server_version) < 5) {
-		g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), "");
-		value_list = g_list_append (value_list, tmpval);
-	}
-	else {
-		if (mysql_row[6] && mysql_row[7]) {
-			gchar *str = g_strdup_printf ("%s.%s", mysql_row[6], mysql_row[7]);
-			g_value_take_string (tmpval = gda_value_new (G_TYPE_STRING), str);
-			value_list = g_list_append (value_list, tmpval);
+			goto cleanup;
 		}
-		else {
-			g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), "");
-			value_list = g_list_append (value_list, tmpval);
-		}
-	}
-
-	/* default value */
-	g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), mysql_row[4]);
-	value_list = g_list_append (value_list, tmpval);
-
-	/* Extra column */
-	if (!strcmp (mysql_row[5], "auto_increment"))
-		g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), "AUTO_INCREMENT");
-	else
-		g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), "");
-	value_list = g_list_append (value_list, tmpval);
-
-	return value_list;
-}
-
-static GdaDataModel *
-get_table_fields (GdaConnection *cnc, GdaParameterList *params)
-{
-	const gchar *table_name;
-	GdaParameter *par;
-	gchar *cmd_str;
-	GdaDataModelArray *recset;
-	gint rows, r;
-	gint rc;
-	MYSQL *mysql;
-	MYSQL_RES *mysql_res;
-
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-	g_return_val_if_fail (params != NULL, NULL);
-
-	mysql = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_MYSQL_HANDLE);
-	if (!mysql) {
-		gda_connection_add_event_string (cnc, _("Invalid MySQL handle"));
-		return NULL;
-	}
-
-	/* get parameters sent by client */
-	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;
 	}
 
-	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;
-	}
-
-	/* execute command on server */	
-	if (atoi (mysql->server_version) < 5)
-		cmd_str = g_strdup_printf ("SHOW COLUMNS FROM %s", table_name);
+	/* Create prepared statement. */
+	ps = gda_mysql_pstmt_new (cnc, cdata->mysql, cdata->mysql_stmt);
+	
+	if (!ps)
+		return FALSE;
 	else {
-		/* with MySQL >= 5.0 there are foreign keys: add support for those */
-		cmd_str = g_strdup_printf ("SELECT c.COLUMN_NAME, c.COLUMN_TYPE, c.IS_NULLABLE, c.COLUMN_KEY, "
-					   "c.COLUMN_DEFAULT, c.EXTRA, "
-					   "u.REFERENCED_TABLE_NAME, u.REFERENCED_COLUMN_NAME "
-					   "FROM INFORMATION_SCHEMA.COLUMNS c "
-					   "LEFT OUTER JOIN "
-					   "(SELECT sub.TABLE_SCHEMA, sub.COLUMN_NAME, sub.TABLE_NAME, "
-					   "sub.REFERENCED_TABLE_NAME, sub.REFERENCED_COLUMN_NAME "
-					   "FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE sub where sub.TABLE_NAME='%s' "
-					   "AND sub.REFERENCED_TABLE_NAME IS NOT NULL) u "
-					   "ON (c.TABLE_NAME = u.TABLE_NAME AND c.TABLE_SCHEMA = u.TABLE_SCHEMA "
-					   "AND c.COLUMN_NAME = u.COLUMN_NAME) "
-					   "WHERE c.TABLE_NAME = '%s' AND c.TABLE_SCHEMA = DATABASE() "
-					   "ORDER BY c.ORDINAL_POSITION",
-					   table_name, table_name);
-	}
-
-	rc = gda_mysql_real_query_wrap (cnc, mysql, cmd_str, strlen (cmd_str));
-	g_free (cmd_str);
-	if (rc != 0) {
-		gda_connection_add_event (cnc, gda_mysql_make_error (mysql));
-		return NULL;
-	}
-
-	mysql_res = mysql_store_result (mysql);
-	rows = mysql_num_rows (mysql_res);
-
-	/* fill in the 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);
-	
-	for (r = 0; r < rows; r++) {
-		GList *value_list;
-		MYSQL_ROW mysql_row;
-
-		mysql_data_seek (mysql_res, r);
-		mysql_row = mysql_fetch_row (mysql_res);
-		if (!mysql_row) {
-			mysql_free_result (mysql_res);
-			g_object_unref (G_OBJECT (recset));
-
-			return NULL;
-		}
-
-		value_list = field_row_to_value_list (mysql, mysql_row);
-		if (!value_list) {
-			mysql_free_result (mysql_res);
-			g_object_unref (G_OBJECT (recset));
-
-			return NULL;
-		}
-
-		gda_data_model_append_values (GDA_DATA_MODEL (recset),
-					      (const GList *) value_list, NULL);
-
-		g_list_foreach (value_list, (GFunc) gda_value_free, NULL);
-		g_list_free (value_list);
+		
+		gda_pstmt_set_gda_statement (_GDA_PSTMT(ps), stmt);
+		_GDA_PSTMT(ps)->param_ids = param_ids;
+		_GDA_PSTMT(ps)->sql = sql;
+		
+		gda_connection_add_prepared_statement (cnc, stmt, ps);
+		return TRUE;
 	}
+	
+ cleanup:
 
-	mysql_free_result (mysql_res);
+	if (set)
+		g_object_unref (G_OBJECT(set));
+	if (used_set)
+		g_slist_free (used_set);
+	g_free (sql);
 	
-	return GDA_DATA_MODEL (recset);
+	return FALSE;
 }
 
-static void
-mysql_get_constraints_form_create_table_line (GdaDataModelArray *recset, gchar *pos)
-{
-	/* try to parse a line like this:
-	 * "  CONSTRAINT `name` FOREIGN KEY (`fid1`,`fid2`) REFERENCES othertable(`id1`,`id2`)"
-	 */
-	gchar *cname = 0, *start, *stop;
-	GString *kname;
-	gchar *tname = 0;
-	GString *fname;
-	GList *value_list;
-	gchar *temp;
-	GValue *tmpval;
-
-	/* remove prefix spaces */
-	while ( *pos==' ')
-		pos++;
-
-	/* "CONSTRAINT "? */
-	if ( strncmp (pos, "CONSTRAINT ", 11) )
-		return;
-
-	pos += 11; /* strlen("CONSTRAINT ") */ 
-
-	/* find the start of the constraint name.. it should be a ` char */
-	if ( ! ( start = strchr (pos, '`') ) )
-		return;
-	/* we want the first character from the name */
-	start++;
-
-	/* find the ending constraint name.. it should be a ` char */
-	if ( ! ( stop = strchr (start, '`') ) )
-		return;
-
-	/* allocate cname, and store the constraint name */
-	cname = g_malloc ( stop - start  + 1);
-	g_strlcpy (cname, start, stop - start + 1);
-
-	pos = stop + 1;
-
-	/* remove spaces again */
-	while ( *pos == ' ' )
-		pos++;
-
-	/* "FOREIGN KEY "? */
-	if ( strncmp (pos, "FOREIGN KEY ", 12) )
-		goto cname_out;
-	/* this is a foreign key constraint */
-	pos += 12; /* strlen("FOREIGN KEY ") */
-
-	/* we should be able to locate a ( inside our string */
-	if ( ! ( pos = strchr (pos, '(') ) )
-		goto cname_out;
-	pos++;
-
-	/* we should now be at the character behind the ( */
-
-	kname = g_string_new (NULL);
-
-	while (1) {
-		/* find all the entries.. they are in this format "`a`, `b`, `c`".
-		 * The list is terminated by a ) character */
-		if ( ! ( start = strchr (pos, '`') ) )
-			goto kname_out;
-		start++;
-		if ( ! ( stop = strchr (start, '`') ) )
-			goto kname_out;
-		if ( kname->len )
-			g_string_append_c (kname, ',');
-		g_string_append_len (kname, start, stop - start);
-
-		pos = stop + 1;
-
-		while ( *pos == ' ')
-			pos++;
-		if ( *pos == ',' )
-			pos++;
-		else /* if (*pos==')')*/
-			break;
-	}
-	/* pass by the ) character.. but if we had an unexpected \0 character, don't crash */
-	if (*pos)
-		pos++;
-
-	/* remove spaces again */
-	while ( *pos == ' ' )
-		pos++;
-
-	/* we now expected the REFERENCES text */
-	if ( strncmp (pos, "REFERENCES ", 11) )
-		goto kname_out;
-
-	pos += 11;
-
-	/* and yeah... remove spaces */
-	while ( *pos == ' ' )
-		pos++;
-
-	/* we should now hit the name of the foreign table. It is embedded inside ` characters */
-	if ( ! ( start = strchr (pos, '`') ) )
-		goto kname_out;
-	start++;
-
-	if ( ! ( stop = strchr (start, '`') ) )
-		goto kname_out;
-	/* store it in tname */
-	tname = g_malloc ( stop - start + 1);
-	g_strlcpy (tname, start, stop - start + 1);
-
-	pos = stop + 1;
-
-	/* we now should find a ( character */
-	if ( ! ( start = strchr (pos, '(') ) )
-		goto tname_out;
-	pos = start + 1;
-
-	fname = g_string_new (NULL);
-
-	while (1) {
-		/* and after this character we find a list like above with keys */
-		if ( ! ( start = strchr (pos, '`') ) )
-			goto kname_out;
-		start++;
-		if ( ! ( stop = strchr (start, '`') ) )
-			goto kname_out;
-		if (fname->len)
-			g_string_append_c (fname, ',');
-		g_string_append_len (fname, start, stop - start);
-
-		pos = stop + 1;
-		while ( *pos == ' ')
-			pos++;
-		if ( *pos == ',' )
-			pos++;
-		else /* if (*pos==')')*/
-			break;
-	}
-	/* fill in the result into the result table */
-	g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), cname);
-	value_list = g_list_append (NULL, tmpval);
 
-	g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), "FOREIGN_KEY");
-	value_list = g_list_append (value_list, tmpval);
-
-	g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), kname->str);
-	value_list = g_list_append (value_list, tmpval);
+static GdaMysqlPStmt *
+prepare_stmt_simple (MysqlConnectionData  *cdata,
+		     const gchar          *sql,
+		     GError              **error)
+{
+	GdaMysqlPStmt *ps = NULL;
+	g_return_val_if_fail (sql != NULL, NULL);
 	
-	temp = g_strdup_printf ("%s(%s)", tname, fname->str);
-	g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), temp);
-	value_list = g_list_append (value_list, tmpval);
+	if (mysql_stmt_prepare (cdata->mysql_stmt, sql, strlen (sql))) {
+		GdaConnectionEvent *event = _gda_mysql_make_error
+			(cdata->cnc, cdata->mysql, NULL);
+		ps = NULL;
+	} else {
+		ps = gda_mysql_pstmt_new (cdata->cnc, cdata->mysql, cdata->mysql_stmt);
+		_GDA_PSTMT(ps)->param_ids = NULL;
+		_GDA_PSTMT(ps)->sql = g_strdup (sql);
+	}
 	
-	value_list = g_list_append (value_list, gda_value_new_null ());
-
-	gda_data_model_append_values (GDA_DATA_MODEL (recset),
-	                              (const GList *) value_list, NULL);
-		
-	g_list_foreach (value_list, (GFunc) gda_value_free, NULL);
-	g_list_free (value_list);
-
-	g_string_free (fname, TRUE);
-tname_out:
-	g_free (tname);
-kname_out:
-	g_string_free (kname, TRUE);
-cname_out:
-	g_free (cname);
+	return ps;
 }
 
-static void
-mysql_get_constraints_from_create_table (GdaDataModelArray *recset, gchar *pos)
-{
-	/* skip the first line. nothing of interrest there */
-	if ((pos=strchr(pos, '\n')))
-		pos++;
-	else
-		return;
-	while (*pos)
-	{
-		gchar *next;
-		if ((next = strchr (pos, '\n'))) {
-			*next=0;
-			next++;
-		} else
-			next = pos + strlen (pos);
-		mysql_get_constraints_form_create_table_line (recset, pos);
-		pos=next;
-	}
-}
 
-static GdaDataModel *
-get_mysql_constraints (GdaConnection *cnc, GdaParameterList *params)
-{
-	const gchar *table_name;
-	GdaParameter *par;
-	gchar *cmd_str;
-	GdaDataModelArray *recset;
-	gint rows, r;
-	gint rc;
-	MYSQL *mysql;
-	MYSQL_RES *mysql_res;
-	GString *pkey_fields = NULL;
-	GValue *tmpval;
+/*
+ * 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_mysql_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)
+{
+	g_print ("*** %s\n", __func__);
+	GdaMysqlPStmt *ps;
+	MysqlConnectionData *cdata;
 
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-	g_return_val_if_fail (params != NULL, NULL);
+	g_return_val_if_fail (gda_connection_get_provider_obj (cnc) == provider, NULL);
+	g_return_val_if_fail (GDA_IS_STATEMENT (stmt), NULL);
 
-	mysql = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_MYSQL_HANDLE);
-	if (!mysql) {
-		gda_connection_add_event_string (cnc, _("Invalid MySQL handle"));
-		return NULL;
-	}
-
-	/* get parameters sent by client */
-	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;
-	}
-
-	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;
-	}
-
-	/* create and initialize the recordset to be returned */
-	recset = (GdaDataModelArray *) gda_data_model_array_new (gda_server_provider_get_schema_nb_columns (GDA_CONNECTION_SCHEMA_CONSTRAINTS));
-	gda_server_provider_init_schema_model (GDA_DATA_MODEL (recset), GDA_CONNECTION_SCHEMA_CONSTRAINTS);
-
-	/* 
-	 * Obtaining list of columns 
-	 */
-	cmd_str = g_strdup_printf ("SHOW COLUMNS FROM %s", table_name);
-	rc = gda_mysql_real_query_wrap (cnc, mysql, cmd_str, strlen (cmd_str));
-	g_free (cmd_str);
-	if (rc != 0) {
-		gda_connection_add_event (cnc, gda_mysql_make_error (mysql));
-		return NULL;
+	/* 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;
 	}
 
-	mysql_res = mysql_store_result (mysql);
-	rows = mysql_num_rows (mysql_res);
-
-	for (r = 0; r < rows; r++) {
-		GList *value_list = NULL;
-		MYSQL_ROW mysql_row;
-		gchar **arr;
-
-		mysql_data_seek (mysql_res, r);
-		mysql_row = mysql_fetch_row (mysql_res);
-		if (!mysql_row) {
-			mysql_free_result (mysql_res);
-			g_object_unref (G_OBJECT (recset));
-
-			return NULL;
-		}
-
-		/* treating ENUM and SET types into CHECK constraints */
-		arr = g_strsplit ((const gchar *) mysql_row[1], "(", 0);
-		if (arr) {
-			gchar *str;
-			if (!strcmp (arr[0], "enum")) {
-				g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), "");
-				value_list = g_list_append (value_list, tmpval);
-
-				g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), "CHECK");
-				value_list = g_list_append (value_list, tmpval);
-
-				g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), mysql_row[0]);
-				value_list = g_list_append (value_list, tmpval);
-
-				str = g_strdup_printf ("IN %s", mysql_row[1]+4);
-				g_value_take_string (tmpval = gda_value_new (G_TYPE_STRING), str);
-				value_list = g_list_append (value_list, tmpval);
-
-				value_list = g_list_append (value_list, gda_value_new_null());
-			}
-			else if (!strcmp (arr[0], "set")) {
-				g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), "");
-				value_list = g_list_append (value_list, tmpval);
-
-				g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), "CHECK");
-				value_list = g_list_append (value_list, tmpval);
-
-				g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), mysql_row[0]);
-				value_list = g_list_append (value_list, tmpval);
+	cdata = (MysqlConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
+		return FALSE;
 
-				str = g_strdup_printf ("SETOF %s", mysql_row[1]+3);
-				g_value_take_string (tmpval = gda_value_new (G_TYPE_STRING), str);
-				value_list = g_list_append (value_list, tmpval);
 
-				value_list = g_list_append (value_list, gda_value_new_null());
-			}
-			g_strfreev (arr);
-		}
-		if (value_list) {
-			gda_data_model_append_values (GDA_DATA_MODEL (recset),
-						      (const GList *) value_list, NULL);
+	/* get/create new prepared statement */
+	ps = gda_connection_get_prepared_statement (cnc, stmt);
+	if (!ps) {
+		if (!gda_mysql_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 GdaMysqlPStmt object.
+			 */
+			// TO_IMPLEMENT;
+			
+			gchar *sql = gda_mysql_provider_statement_to_sql
+				(provider, cnc, stmt, params, 0, NULL, error);
+			if (!sql)
+				return NULL;
+			ps = prepare_stmt_simple (cdata, sql, error);
+			if (!ps)
+				return NULL;
 			
-			g_list_foreach (value_list, (GFunc) gda_value_free, NULL);
-			g_list_free (value_list);
-			value_list = NULL;
-		}
-
-		/* treating PRIMARY key constraints */
-		if (!strcmp (mysql_row[3], "PRI")) {
-			if (!pkey_fields)
-				pkey_fields = g_string_new (mysql_row[0]);
-			else {
-				g_string_append_c (pkey_fields, ',');
-				g_string_append (pkey_fields, mysql_row[0]);
-			}
 		}
+		else
+			ps = gda_connection_get_prepared_statement (cnc, stmt);
 	}
+	g_assert (ps);
 
-	/* creating the PKEY entry if necessary */
-	if (pkey_fields) {
-		GList *value_list = NULL;
-		g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), "");
-		value_list = g_list_append (value_list, tmpval);
-
-		g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), "PRIMARY_KEY");
-		value_list = g_list_append (value_list, tmpval);
-
-		g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), pkey_fields->str);
-		value_list = g_list_append (value_list, tmpval);
-
-		value_list = g_list_append (value_list, gda_value_new_null());
-		value_list = g_list_append (value_list, gda_value_new_null());
-		g_string_free (pkey_fields, TRUE);
-
-		gda_data_model_append_values (GDA_DATA_MODEL (recset),
-					      (const GList *) value_list, NULL);
-		
-		g_list_foreach (value_list, (GFunc) gda_value_free, NULL);
-		g_list_free (value_list);
-	}
-
-	mysql_free_result (mysql_res);
+	/* optionnally reset the prepared statement if required by the API */
+	// TO_IMPLEMENT;
+	
+	/* bind statement's parameters */
+	GSList *list;
+	GdaConnectionEvent *event = NULL;
+	int i;
+	
+	gint nb_params = g_slist_length (_GDA_PSTMT (ps)->param_ids);
+	char **param_values = g_new0 (char *, nb_params + 1);
+        int *param_lengths = g_new0 (int, nb_params + 1);
+        int *param_formats = g_new0 (int, nb_params + 1);
+	g_print ("NB=%d\n", nb_params);
+	
+	for (i = 1, list = _GDA_PSTMT (ps)->param_ids; list; list = list->next, i++) {
+		const gchar *pname = (gchar *) list->data;
+		GdaHolder *h;
 
-	/* 
-	 * taking care of foreign keys if possible 
-	 */
-	if (atoi (mysql->server_version) >= 5) {
-		gchar *current_cname = NULL;
-		GString *ref_string = NULL;
-		GString *src_string = NULL;
-		GList *value_list = NULL;
 		
-		cmd_str = g_strdup_printf ("SELECT CONSTRAINT_NAME, COLUMN_NAME, ORDINAL_POSITION, REFERENCED_TABLE_SCHEMA, "
-					   "REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME "
-					   "FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE "
-					   "WHERE TABLE_NAME = '%s' AND TABLE_SCHEMA = DATABASE() AND "
-					   "CONSTRAINT_NAME != 'PRIMARY' AND REFERENCED_TABLE_NAME IS NOT NULL "
-					   "ORDER BY CONSTRAINT_NAME, ORDINAL_POSITION", 
-					   table_name);
-		rc = gda_mysql_real_query_wrap (cnc, mysql, cmd_str, strlen (cmd_str));
-		g_free (cmd_str);
-		if (rc != 0) {
-			gda_connection_add_event (cnc, gda_mysql_make_error (mysql));
-			return NULL;
+		g_print ("PNAME=%s\n", pname);
+		//		
+		/* 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;
 		}
 
-		mysql_res = mysql_store_result (mysql);
-		rows = mysql_num_rows (mysql_res);
-
-		for (r = 0; r < rows; r++) {
-			MYSQL_ROW mysql_row;
-
-			mysql_data_seek (mysql_res, r);
-			mysql_row = mysql_fetch_row (mysql_res);
-			if (!mysql_row) {
-				mysql_free_result (mysql_res);
-				g_object_unref (G_OBJECT (recset));
-
-				return NULL;
-			}
-
-
-			if ((! current_cname) || strcmp (current_cname, mysql_row[0])) {
-				/* new constraint */
-				if (value_list) {
-					/* complete and store current row */
-					g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), src_string->str);
-					value_list = g_list_append (value_list, tmpval);
-					g_string_free (src_string, TRUE);
-
-					g_string_append_c (ref_string, ')');
-					g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), ref_string->str);
-					value_list = g_list_append (value_list, tmpval);
-					g_string_free (ref_string, TRUE);
-
-					value_list = g_list_append (value_list, gda_value_new_null ());
-
-					gda_data_model_append_values (GDA_DATA_MODEL (recset),
-								      (const GList *) value_list, NULL);
-
-					g_list_foreach (value_list, (GFunc) gda_value_free, NULL);
-					g_list_free (value_list);
-				}
-				if (current_cname) 
-					g_free (current_cname);
-
-				/* prepare new constraint */
-				g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), mysql_row[0]);
-				value_list = g_list_append (NULL, tmpval);
-
-				g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), "FOREIGN_KEY");
-				value_list = g_list_append (value_list, tmpval);
-
-				src_string = g_string_new (mysql_row[1]);
-
-				ref_string = g_string_new (mysql_row[4]);
-				g_string_append_c (ref_string, '(');
-				g_string_append (ref_string, mysql_row[5]);
-				current_cname = g_strdup (mysql_row[0]);
-			}
-			else {
-				g_string_append_c (ref_string, ',');
-				g_string_append (ref_string, mysql_row[5]);
-				g_string_append_c (src_string, ',');
-				g_string_append (src_string, mysql_row[1]);
+		h = gda_set_get_holder (params, pname);
+		if (!h) {
+			gchar *tmp = gda_alphanum_to_text (g_strdup (pname + 1));
+			if (tmp) {
+				h = gda_set_get_holder (params, tmp);
+				g_free (tmp);
 			}
 		}
-
-		if (value_list) {
-			/* complete and store current row */
-			g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), src_string->str);
-			value_list = g_list_append (value_list, tmpval);
-			g_string_free (src_string, TRUE);
-
-			g_string_append_c (ref_string, ')');
-			g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), ref_string->str);
-			value_list = g_list_append (value_list, tmpval);
-			g_string_free (ref_string, TRUE);
-
-			value_list = g_list_append (value_list, gda_value_new_null ());
-		
-			gda_data_model_append_values (GDA_DATA_MODEL (recset),
-						      (const GList *) value_list, NULL);
-		
-			g_list_foreach (value_list, (GFunc) gda_value_free, NULL);
-			g_list_free (value_list);
-		}
-		if (current_cname)
-			g_free(current_cname);
-		mysql_free_result (mysql_res);
-	} else {
-		gchar *temp;
-		MYSQL_ROW mysql_row;
-		cmd_str = g_strdup_printf ("SHOW CREATE TABLE %s",
-					   table_name);
-		rc = gda_mysql_real_query_wrap (cnc, mysql, cmd_str, strlen (cmd_str));
-		g_free (cmd_str);
-		if (rc != 0) {
-			gda_connection_add_event (cnc, gda_mysql_make_error (mysql));
-			return NULL;
+		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;
 		}
-		mysql_res = mysql_store_result (mysql);
-		
-		mysql_row = mysql_fetch_row (mysql_res);
-		if (!mysql_row) {
-			mysql_free_result (mysql_res);
-			g_object_unref (G_OBJECT (recset));
 
-			return NULL;
-		}
-		temp = g_strdup ( mysql_row[1] );
-		mysql_get_constraints_from_create_table (recset, mysql_row[1]);
-		g_free (temp);
-		mysql_free_result (mysql_res);
+		/* actual binding using the C API, for parameter at position @i */
+		const GValue *value = gda_holder_get_value (h);
+		TO_IMPLEMENT;
 	}
-
-	return GDA_DATA_MODEL (recset);
-}
-
-/* get_schema handler for the GdaMysqlProvider class */
-static GdaDataModel *
-gda_mysql_provider_get_schema (GdaServerProvider *provider,
-			       GdaConnection *cnc,
-			       GdaConnectionSchema schema,
-			       GdaParameterList *params)
-{
-	g_return_val_if_fail (GDA_IS_SERVER_PROVIDER (provider), NULL);
-	if (cnc)
-		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-	else
+		
+	if (event) {
+		gda_connection_add_event (cnc, event);
 		return NULL;
-
-	switch (schema) {
-	case GDA_CONNECTION_SCHEMA_AGGREGATES :
-		return get_mysql_aggregates (cnc, params);
-	case GDA_CONNECTION_SCHEMA_DATABASES :
-		return get_mysql_databases (cnc, params);
-	case GDA_CONNECTION_SCHEMA_FIELDS :
-		return get_table_fields (cnc, params);
-	case GDA_CONNECTION_SCHEMA_TABLES :
-		return get_mysql_tables (cnc, params);
-	case GDA_CONNECTION_SCHEMA_VIEWS:
-		return get_mysql_views (cnc, params);
-	case GDA_CONNECTION_SCHEMA_TYPES :
-		return get_mysql_types (cnc, params);
-	case GDA_CONNECTION_SCHEMA_PROCEDURES:
-		return get_mysql_procedures (cnc, params);
-	case GDA_CONNECTION_SCHEMA_CONSTRAINTS:
-		return get_mysql_constraints (cnc, params);
-	default : break;
 	}
+	
+	/* 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);
 
-	return NULL;
-}
+	
+	GObject *return_value = NULL;
+	if (mysql_stmt_execute (cdata->mysql_stmt)) {
+		event = _gda_mysql_make_error (cnc, cdata->mysql, error);
+	} else {
+		//	
+		/* 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, "SHOW", 4) ||
+		    !g_ascii_strncasecmp (_GDA_PSTMT (ps)->sql, "DESCRIBE", 8) ||
+		    !g_ascii_strncasecmp (_GDA_PSTMT (ps)->sql, "EXPLAIN", 7)) {
+			
+			if (mysql_stmt_store_result (cdata->mysql_stmt)) {
+				_gda_mysql_make_error (cnc, cdata->mysql, error);
+			} else {
+				GdaDataModelAccessFlags flags;
 
-gchar *
-gda_mysql_provider_value_to_sql_string (GdaServerProvider *provider, /* we dont actually use this!*/
-					GdaConnection *cnc,
-					GValue *from)
-{
-	gchar *val_str;
-	gchar *ret;
-	GType type;
+				if (model_usage & GDA_STATEMENT_MODEL_RANDOM_ACCESS)
+					flags = GDA_DATA_MODEL_ACCESS_RANDOM;
+				else
+					flags = GDA_DATA_MODEL_ACCESS_CURSOR_FORWARD;
 
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
-	g_return_val_if_fail (from != NULL, FALSE);
-	
-	val_str = gda_value_stringify (from);
-	if (!val_str)
-		return NULL;
+				return_value = (GObject *) gda_mysql_recordset_new (cnc, ps, flags, col_types);
+				gda_connection_internal_statement_executed (cnc, stmt, params, NULL); /* required: help @cnc keep some stats */
+			}
+			
+		} else {
+			my_ulonglong affected_rows = (my_ulonglong)~0;
 
-	type = G_VALUE_TYPE (from);
-	if ((type == G_TYPE_INT64) ||
-	    (type == G_TYPE_DOUBLE) ||
-	    (type == G_TYPE_INT) ||
-	    (type == GDA_TYPE_NUMERIC) ||
-	    (type == G_TYPE_FLOAT) ||
-	    (type == GDA_TYPE_SHORT) ||
-	    (type == G_TYPE_CHAR))
-		ret = g_strdup (val_str);
-	else if ((type == GDA_TYPE_TIMESTAMP) ||
-		 (type == G_TYPE_DATE) ||
-		 (type == GDA_TYPE_TIME))
-		ret = g_strdup_printf ("\"%s\"", val_str);
-	else {
-		MYSQL *mysql;
-		char *quoted;
-		mysql = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_MYSQL_HANDLE);
-		
-		if (!mysql) {
-			gda_connection_add_event_string (cnc, _("Invalid MySQL handle"));
-			return NULL;
+			// TO_IMPLEMENT;
+			/* Create a #GdaSet containing "IMPACTED_ROWS" */
+			/* Create GdaConnectionEvent notice with the type of command and impacted rows */
+
+			
+			affected_rows = mysql_stmt_affected_rows (cdata->mysql_stmt);
+			if (affected_rows >= 0) {
+				GdaConnectionEvent *event;
+                                gchar *str;
+                                event = gda_connection_event_new (GDA_CONNECTION_EVENT_NOTICE);
+                                str = g_strdup_printf ("%lu", affected_rows);
+                                gda_connection_event_set_description (event, str);
+                                g_free (str);
+
+                                return_value = (GObject *) gda_set_new_inline
+                                        (1, "IMPACTED_ROWS", G_TYPE_INT, (int) affected_rows);
+
+				gda_connection_internal_statement_executed (cnc, stmt, params, event); /* required: help @cnc keep some stats */
+			} else {
+				return_value = (GObject *) gda_data_model_array_new (0);
+			}
+			
 		}
-		quoted = ret = g_malloc(strlen(val_str) * 2 + 3);
-		*quoted++ 	= '\'';
-		quoted += mysql_real_escape_string (
-						    mysql, quoted, val_str, strlen (val_str));
 		
-		*quoted++     	= '\'';
-		*quoted++     	= '\0';
-		ret = g_realloc(ret, quoted - ret + 1);
 	}
+	return return_value;
 	
-	g_free (val_str);
-
-	return ret;
 }
 
-static GdaDataHandler *
-gda_mysql_provider_get_data_handler (GdaServerProvider *provider,
-				     GdaConnection *cnc,
-				     GType type, const gchar *dbms_type)
+/*
+ * Free connection's specific data
+ */
+static void
+gda_mysql_free_cnc_data (MysqlConnectionData  *cdata)
 {
-	GdaDataHandler *dh = NULL;
+	g_print ("*** %s\n", __func__);
+	if (!cdata)
+		return;
 
-	g_return_val_if_fail (GDA_IS_SERVER_PROVIDER (provider), FALSE);
-	if (cnc) 
-		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+	// TO_IMPLEMENT;
 	
-        if ((type == G_TYPE_INT64) ||
-	    (type == G_TYPE_UINT64) ||
-	    (type == G_TYPE_DOUBLE) ||
-	    (type == G_TYPE_INT) ||
-	    (type == GDA_TYPE_NUMERIC) ||
-	    (type == G_TYPE_FLOAT) ||
-	    (type == GDA_TYPE_SHORT) ||
-	    (type == GDA_TYPE_USHORT) ||
-	    (type == G_TYPE_CHAR) ||
-	    (type == G_TYPE_UCHAR) ||
-	    (type == G_TYPE_UINT)) {
-		dh = gda_server_provider_handler_find (provider, NULL, type, NULL);
-		if (!dh) {
-			dh = gda_handler_numerical_new ();
-			gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_INT64, NULL);
-			gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_UINT64, NULL);
-			gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_DOUBLE, NULL);
-			gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_INT, NULL);
-			gda_server_provider_handler_declare (provider, dh, NULL, GDA_TYPE_NUMERIC, NULL);
-			gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_FLOAT, NULL);
-			gda_server_provider_handler_declare (provider, dh, NULL, GDA_TYPE_SHORT, NULL);
-			gda_server_provider_handler_declare (provider, dh, NULL, GDA_TYPE_USHORT, NULL);
-			gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_CHAR, NULL);
-			gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_UCHAR, NULL);
-			gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_UINT, NULL);
-			g_object_unref (dh);
-		}
-	}
-        else if (type == GDA_TYPE_BINARY) {
-		dh = gda_server_provider_handler_find (provider, cnc, type, NULL);
-		if (!dh) {
-			dh = gda_handler_bin_new ();
-			if (dh) {
-				gda_server_provider_handler_declare (provider, dh, cnc, GDA_TYPE_BINARY, NULL);
-				g_object_unref (dh);
-			}
-		}
+	if (cdata->mysql) {
+		mysql_close (cdata->mysql);
+		cdata->mysql = NULL;
 	}
-        else if (type == G_TYPE_BOOLEAN) {
-		dh = gda_server_provider_handler_find (provider, NULL, type, NULL);
-		if (!dh) {
-			dh = gda_handler_boolean_new ();
-			gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_BOOLEAN, NULL);
-			g_object_unref (dh);
-		}
-	}
-	else if ((type == G_TYPE_DATE) ||
-		 (type == GDA_TYPE_TIME) ||
-		 (type == GDA_TYPE_TIMESTAMP)) {
-		dh = gda_server_provider_handler_find (provider, NULL, type, NULL);
-		if (!dh) {
-			dh = gda_handler_time_new ();
-			gda_handler_time_set_sql_spec (GDA_HANDLER_TIME (dh), 
-						       G_DATE_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 ();
-			gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_STRING, NULL);
-			g_object_unref (dh);
-		}
+	if (cdata->mysql_stmt) {
+		mysql_stmt_close (cdata->mysql_stmt);
+		cdata->mysql_stmt = NULL;
 	}
-	else if (type == G_TYPE_ULONG) {
-		dh = gda_server_provider_handler_find (provider, NULL, type, NULL);
-		if (!dh) {
-			dh = gda_handler_type_new ();
-			gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_ULONG, NULL);
-			g_object_unref (dh);
-		}
-	}
-	else {
-		/* special case: we take into account the dbms_type argument */
-		if (dbms_type)
-			TO_IMPLEMENT;
-	}
-
-	return dh;
-}
-
-static const gchar*
-gda_mysql_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 "bigint";
-	if (type == G_TYPE_UINT64)
-		return "bigint unsigned";
-	if (type == GDA_TYPE_BINARY)
-		return "longtext";
-	if (type == G_TYPE_BOOLEAN)
-		return "bool";
-	if (type == G_TYPE_DATE)
-		return "date";
-	if (type == G_TYPE_DOUBLE)
-		return "double";
-	if (type == GDA_TYPE_GEOMETRIC_POINT)
-		return "varchar";
-	if (type == G_TYPE_OBJECT)
-		return "text";
-	if (type == G_TYPE_INT)
-		return "int";
-	if (type == GDA_TYPE_LIST)
-		return "text";
-	if (type == GDA_TYPE_NUMERIC)
-		return "decimal";
-	if (type == G_TYPE_FLOAT)
-		return "float";
-	if (type == GDA_TYPE_SHORT)
-		return "smallint";
-	if (type == GDA_TYPE_USHORT)
-		return "smallint unsigned";
-	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 "tinyint";
-	if (type == G_TYPE_UCHAR)
-		return "tinyint unsigned";
-	if (type == G_TYPE_ULONG)
-		return "bigint unsigned";
-        if (type == G_TYPE_UINT)
-		return "int unsigned";
-	if (type == G_TYPE_INVALID)
-		return "text";
 
-	return "text";
-}
-
-static GdaSqlParser *
-gda_mysql_provider_create_parser (GdaServerProvider *provider, GdaConnection *cnc)
-{
-        g_return_val_if_fail (GDA_IS_SERVER_PROVIDER (provider), NULL);
-        return (GdaSqlParser*) g_object_new (GDA_TYPE_SQL_PARSER, "tokenizer-flavour", 
-					     GDA_SQL_PARSER_FLAVOUR_MYSQL, NULL);
+	g_free (cdata->version);
+	cdata->version_long = -1;
+	
+	g_free (cdata);
 }

Modified: trunk/providers/mysql/gda-mysql-provider.h
==============================================================================
--- trunk/providers/mysql/gda-mysql-provider.h	(original)
+++ trunk/providers/mysql/gda-mysql-provider.h	Sun Apr  6 17:06:43 2008
@@ -1,10 +1,8 @@
-/* GDA MySQL provider
- * Copyright (C) 1998-2005 The GNOME Foundation.
+/* GDA mysql provider
+ * Copyright (C) 2008 The GNOME Foundation.
  *
  * AUTHORS:
- *      Michael Lausch <michael lausch at>
- *	Rodrigo Moya <rodrigo gnome-db org>
- *      Vivien Malerba <malerba gnome-db org>
+ *      Carlos Savoretti <csavoretti gmail com>
  *
  * This Library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public License as
@@ -22,37 +20,32 @@
  * Boston, MA 02111-1307, USA.
  */
 
-#if !defined(__gda_mysql_provider_h__)
-#  define __gda_mysql_provider_h__
+#ifndef __GDA_MYSQL_PROVIDER_H__
+#define __GDA_MYSQL_PROVIDER_H__
 
 #include <libgda/gda-server-provider.h>
 
-G_BEGIN_DECLS
-
 #define GDA_TYPE_MYSQL_PROVIDER            (gda_mysql_provider_get_type())
 #define GDA_MYSQL_PROVIDER(obj)            (G_TYPE_CHECK_INSTANCE_CAST (obj, GDA_TYPE_MYSQL_PROVIDER, GdaMysqlProvider))
 #define GDA_MYSQL_PROVIDER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST (klass, GDA_TYPE_MYSQL_PROVIDER, GdaMysqlProviderClass))
 #define GDA_IS_MYSQL_PROVIDER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE (obj, GDA_TYPE_MYSQL_PROVIDER))
 #define GDA_IS_MYSQL_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDA_TYPE_MYSQL_PROVIDER))
 
-#define OBJECT_DATA_MYSQL_HANDLE "GDA_Mysql_MysqlHandle"
-
 typedef struct _GdaMysqlProvider      GdaMysqlProvider;
 typedef struct _GdaMysqlProviderClass GdaMysqlProviderClass;
 
 struct _GdaMysqlProvider {
-	GdaServerProvider provider;
+	GdaServerProvider      provider;
 };
 
 struct _GdaMysqlProviderClass {
 	GdaServerProviderClass parent_class;
 };
 
-GType              gda_mysql_provider_get_type (void) G_GNUC_CONST;
-GdaServerProvider *gda_mysql_provider_new (void);
-gchar *gda_mysql_provider_value_to_sql_string (GdaServerProvider *provider,
-						  GdaConnection *cnc,
-						  GValue *from);
+G_BEGIN_DECLS
+
+GType gda_mysql_provider_get_type (void) G_GNUC_CONST;
+
 G_END_DECLS
 
 #endif

Added: trunk/providers/mysql/gda-mysql-pstmt.c
==============================================================================
--- (empty file)
+++ trunk/providers/mysql/gda-mysql-pstmt.c	Sun Apr  6 17:06:43 2008
@@ -0,0 +1,116 @@
+/* GDA Mysql provider
+ * Copyright (C) 2008 The GNOME Foundation.
+ *
+ * AUTHORS:
+ *      TO_ADD: your name and email
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include <glib/gi18n-lib.h>
+#include "gda-mysql-pstmt.h"
+
+static void
+gda_mysql_pstmt_class_init (GdaMysqlPStmtClass  *klass);
+static void
+gda_mysql_pstmt_init (GdaMysqlPStmt       *pstmt,
+		      GdaMysqlPStmtClass  *klass);
+static void
+gda_mysql_pstmt_finalize (GObject  *object);
+
+static GObjectClass *parent_class = NULL;
+
+/**
+ * gda_mysql_pstmt_get_type
+ *
+ * Returns: the #GType of GdaMysqlPStmt.
+ */
+GType
+gda_mysql_pstmt_get_type (void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY (type == 0)) {
+		static const GTypeInfo info = {
+			sizeof (GdaMysqlPStmtClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) gda_mysql_pstmt_class_init,
+			NULL,
+			NULL,
+			sizeof (GdaMysqlPStmt),
+			0,
+			(GInstanceInitFunc) gda_mysql_pstmt_init
+		};
+
+		type = g_type_register_static (GDA_TYPE_PSTMT, "GdaMysqlPStmt", &info, 0);
+	}
+	return type;
+}
+
+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);
+
+	/* virtual functions */
+	object_class->finalize = gda_mysql_pstmt_finalize;
+}
+
+static void
+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;
+}
+
+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 */
+
+	/* chain to parent class */
+	parent_class->finalize (object);
+}
+
+
+GdaMysqlPStmt *
+gda_mysql_pstmt_new (GdaConnection  *cnc,
+		     MYSQL          *mysql,
+		     MYSQL_STMT     *mysql_stmt)
+{
+	GdaMysqlPStmt *ps = (GdaMysqlPStmt *) g_object_new (GDA_TYPE_MYSQL_PSTMT,
+							    NULL);
+	ps->cnc = cnc;
+	ps->mysql = mysql;
+	ps->mysql_stmt = mysql_stmt;
+
+	return ps;
+}
+

Added: trunk/providers/mysql/gda-mysql-pstmt.h
==============================================================================
--- (empty file)
+++ trunk/providers/mysql/gda-mysql-pstmt.h	Sun Apr  6 17:06:43 2008
@@ -0,0 +1,65 @@
+/* GDA Mysql library
+ * Copyright (C) 2008 The GNOME Foundation.
+ *
+ * AUTHORS:
+ *      Carlos Savoretti <csavoretti gmail com>
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GDA_MYSQL_PSTMT_H__
+#define __GDA_MYSQL_PSTMT_H__
+
+#include <providers-support/gda-pstmt.h>
+#include "gda-mysql.h"
+
+G_BEGIN_DECLS
+
+#define GDA_TYPE_MYSQL_PSTMT            (gda_mysql_pstmt_get_type())
+#define GDA_MYSQL_PSTMT(obj)            (G_TYPE_CHECK_INSTANCE_CAST (obj, GDA_TYPE_MYSQL_PSTMT, GdaMysqlPStmt))
+#define GDA_MYSQL_PSTMT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST (klass, GDA_TYPE_MYSQL_PSTMT, GdaMysqlPStmtClass))
+#define GDA_IS_MYSQL_PSTMT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE(obj, GDA_TYPE_MYSQL_PSTMT))
+#define GDA_IS_MYSQL_PSTMT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GDA_TYPE_MYSQL_PSTMT))
+
+typedef struct _GdaMysqlPStmt        GdaMysqlPStmt;
+typedef struct _GdaMysqlPStmtClass   GdaMysqlPStmtClass;
+
+struct _GdaMysqlPStmt {
+	GdaPStmt        object;
+
+	GdaConnection  *cnc;
+	MYSQL          *mysql;
+	MYSQL_STMT     *mysql_stmt;
+	
+};
+
+struct _GdaMysqlPStmtClass {
+	GdaPStmtClass  parent_class;
+};
+
+GType
+gda_mysql_pstmt_get_type  (void) G_GNUC_CONST;
+/* TO_ADD: helper function to create a GdaMysqlPStmt such as gda_mysql_pstmt_new() with some specific arguments */
+
+GdaMysqlPStmt *
+gda_mysql_pstmt_new       (GdaConnection  *cnc,
+			   MYSQL          *mysql,
+			   MYSQL_STMT     *mysql_stmt);
+
+
+G_END_DECLS
+
+#endif

Modified: trunk/providers/mysql/gda-mysql-recordset.c
==============================================================================
--- trunk/providers/mysql/gda-mysql-recordset.c	(original)
+++ trunk/providers/mysql/gda-mysql-recordset.c	Sun Apr  6 17:06:43 2008
@@ -1,11 +1,8 @@
-/* GDA MySQL provider
- * Copyright (C) 1998 - 2006 The GNOME Foundation.
+/* GDA Mysql provider
+ * Copyright (C) 2008 The GNOME Foundation.
  *
  * AUTHORS:
- *      Michael Lausch <michael lausch at>
- *	Rodrigo Moya <rodrigo gnome-db org>
- *      Vivien Malerba <malerba gnome-db org>
- *	Bas Driessen <bas driessen xobas com>
+ *      Carlos Savoretti <csavoretti gmail com>
  *
  * This Library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public License as
@@ -23,911 +20,686 @@
  * Boston, MA 02111-1307, USA.
  */
 
-#include <glib/gi18n-lib.h>
-#include <stdlib.h>
+#include <stdarg.h>
 #include <string.h>
+#include <glib/gi18n-lib.h>
+#include <libgda/gda-util.h>
+#include <libgda/gda-connection-private.h>
 #include "gda-mysql.h"
 #include "gda-mysql-recordset.h"
-#include <libgda/gda-data-model-private.h>
+#include "gda-mysql-provider.h"
 
-#define PARENT_TYPE GDA_TYPE_DATA_MODEL_ARRAY
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
 
-struct _GdaMysqlRecordsetPrivate {
-	MYSQL_RES     *mysql_res;
-	gint           mysql_res_rows;
-	GdaConnection *cnc;
-	gint           ncolumns;
-	gchar         *table_name;
-	gboolean       row_sync;
-};
 
-static void gda_mysql_recordset_class_init (GdaMysqlRecordsetClass *klass);
-static void gda_mysql_recordset_init       (GdaMysqlRecordset *recset,
-					    GdaMysqlRecordsetClass *klass);
-static void gda_mysql_recordset_finalize   (GObject *object);
-
-static gint gda_mysql_recordset_get_n_rows			     (GdaDataModelRow *model);
-static GdaRow *gda_mysql_recordset_get_row		     (GdaDataModelRow *model, 
-							      gint row, GError **error);
-static const GValue *gda_mysql_recordset_get_value_at		     (GdaDataModelRow *model, gint col, gint row);
-static gboolean gda_mysql_recordset_is_updatable		     (GdaDataModelRow *model);
-static gboolean gda_mysql_recordset_append_row			     (GdaDataModelRow *model, GdaRow *row, GError **error);
-static gboolean gda_mysql_recordset_remove_row			     (GdaDataModelRow *model, GdaRow *row, GError **error);
-static gboolean gda_mysql_recordset_update_row			     (GdaDataModelRow *model, GdaRow *row, GError **error);
+#define _GDA_PSTMT(x) ((GdaPStmt*)(x))
 
-static GObjectClass *parent_class = NULL;
 
-/*
- * Private functions
- */
+enum
+{
+	PROP_0,
+	PROP_CHUNK_SIZE,
+	PROP_CHUNKS_READ
+};
+
 
-/*
- * Object init and finalize
- */
 static void
-gda_mysql_recordset_class_init (GdaMysqlRecordsetClass *klass)
-{
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	GdaDataModelRowClass *model_class = GDA_DATA_MODEL_ROW_CLASS (klass);
+gda_mysql_recordset_class_init (GdaMysqlRecordsetClass  *klass);
+static void
+gda_mysql_recordset_init (GdaMysqlRecordset       *recset,
+			  GdaMysqlRecordsetClass  *klass);
+static void
+gda_mysql_recordset_dispose (GObject  *object);
 
-	parent_class = g_type_class_peek_parent (klass);
+/* virtual methods */
+static gint
+gda_mysql_recordset_fetch_nb_rows (GdaPModel  *model);
+static gboolean
+gda_mysql_recordset_fetch_random (GdaPModel  *model,
+				  GdaPRow   **prow,
+				  gint        rownum,
+				  GError    **error);
+static gboolean
+gda_mysql_recordset_fetch_next (GdaPModel  *model,
+				GdaPRow   **prow,
+				gint        rownum,
+				GError    **error);
+static gboolean
+gda_mysql_recordset_fetch_prev (GdaPModel  *model,
+				GdaPRow   **prow,
+				gint        rownum,
+				GError    **error);
+static gboolean
+gda_mysql_recordset_fetch_at (GdaPModel  *model,
+			      GdaPRow   **prow,
+			      gint        rownum,
+			      GError    **error);
 
-	object_class->finalize = gda_mysql_recordset_finalize;
-	model_class->get_n_rows = gda_mysql_recordset_get_n_rows;
-	model_class->get_row = gda_mysql_recordset_get_row;
-	model_class->get_value_at = gda_mysql_recordset_get_value_at;
-	model_class->is_updatable = gda_mysql_recordset_is_updatable;
-	model_class->append_row = gda_mysql_recordset_append_row;
-	model_class->remove_row = gda_mysql_recordset_remove_row;
-	model_class->update_row = gda_mysql_recordset_update_row;
-}
 
+struct _GdaMysqlRecordsetPrivate {
+	GdaConnection *cnc;
+	/* TO_ADD: specific information */
+	
+	MYSQL_STMT  *mysql_stmt;
+	MYSQL_BIND  *mysql_bind;    /* Array to bind columns in the result set. */
+
+	gint  chunk_size;    /* Number of rows to fetch at a time when iterating forward/backward. */
+	gint  chunks_read;   /* Number of times that we've iterated forward/backward. */
+	
+};
+static GObjectClass *parent_class = NULL;
+
+/*
+ * Object init and finalize
+ */
 static void
-gda_mysql_recordset_init (GdaMysqlRecordset *recset, GdaMysqlRecordsetClass *klass)
+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;
+
+	/* initialize specific information */
+	// TO_IMPLEMENT;
+	
+	recset->priv->chunk_size = 10;
+	recset->priv->chunks_read = 0;
+	
 }
 
+
 static void
-gda_mysql_recordset_finalize (GObject *object)
+gda_mysql_recordset_set_property (GObject       *object,
+				  guint          param_id,
+				  const GValue  *value,
+				  GParamSpec    *pspec)
 {
-	GdaMysqlRecordset *recset = (GdaMysqlRecordset *) object;
-
-	g_return_if_fail (GDA_IS_MYSQL_RECORDSET (recset));
+	GdaMysqlRecordset *record_set;
 
-	if (recset->priv->mysql_res != NULL) {
-		mysql_free_result (recset->priv->mysql_res);
-		recset->priv->mysql_res = NULL;
-	}
-
-	g_free (recset->priv->table_name);
-	recset->priv->table_name = NULL;
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (GDA_IS_MYSQL_RECORDSET(object));
+	g_return_if_fail (GDA_MYSQL_RECORDSET(object)->priv != NULL);
 
-	g_free (recset->priv);
-	recset->priv = NULL;
+	record_set = GDA_MYSQL_RECORDSET(object);
 
-	parent_class->finalize (object);
+	switch (param_id) {
+	case PROP_CHUNK_SIZE:
+		record_set->priv->chunk_size = g_value_get_int (value);
+		break;
+	case PROP_CHUNKS_READ:
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+	}
 }
 
 static void
-fill_gda_value (GValue *gda_value, enum enum_field_types type, gchar *value,
-		unsigned long length, gboolean is_unsigned)
+gda_mysql_recordset_get_property (GObject     *object,
+				  guint        param_id,
+				  GValue      *value,
+				  GParamSpec  *pspec)
 {
-	if (!value) {
-		gda_value_set_null (gda_value);
-		return;
-	}
+	GdaMysqlRecordset *record_set;
 
-	switch (type) {
-	case FIELD_TYPE_DECIMAL :
-	case FIELD_TYPE_DOUBLE :
-#if NDB_VERSION_MAJOR >= 5
-	case FIELD_TYPE_NEWDECIMAL :
-#endif
-		gda_value_reset_with_type (gda_value, G_TYPE_DOUBLE);
-		g_value_set_double (gda_value, atof (value));
-		break;
-	case FIELD_TYPE_FLOAT :
-		gda_value_reset_with_type (gda_value, G_TYPE_FLOAT);
-		g_value_set_float (gda_value, atof (value));
-		break;
-	case FIELD_TYPE_LONG :
-		if (is_unsigned) {
-			gda_value_reset_with_type (gda_value, G_TYPE_UINT);
-			g_value_set_uint (gda_value, strtoul (value, NULL, 0));
-			break;
-		}
-	case FIELD_TYPE_YEAR :
-		gda_value_reset_with_type (gda_value, G_TYPE_INT);
-		g_value_set_int (gda_value, atol (value));
-		break;
-	case FIELD_TYPE_LONGLONG :
-	case FIELD_TYPE_INT24 :
-		if (is_unsigned) {
-			gda_value_reset_with_type (gda_value, G_TYPE_UINT64);
-			g_value_set_uint64 (gda_value, strtoull (value, NULL, 0));
-		} else {
-			gda_value_reset_with_type (gda_value, G_TYPE_INT64);
-			g_value_set_int64 (gda_value, atoll (value));
-		}
-		break;
-	case FIELD_TYPE_SHORT :
-		if (is_unsigned) {
-			gda_value_reset_with_type (gda_value, GDA_TYPE_USHORT);
-			gda_value_set_ushort (gda_value, atoi (value));
-		} else {
-			gda_value_reset_with_type (gda_value, GDA_TYPE_SHORT);
-			gda_value_set_short (gda_value, atoi (value));
-		}
-		break;
-	case FIELD_TYPE_TINY :
-		if (is_unsigned) {
-			gda_value_reset_with_type (gda_value, G_TYPE_UCHAR);
-			g_value_set_uchar (gda_value, atoi (value));
-		} else {
-			gda_value_reset_with_type (gda_value, G_TYPE_CHAR);
-			g_value_set_char (gda_value, atoi (value));
-		}
-		break;
-	case FIELD_TYPE_TINY_BLOB :
-	case FIELD_TYPE_MEDIUM_BLOB :
-	case FIELD_TYPE_LONG_BLOB :
-	case FIELD_TYPE_BLOB : {
-		GdaBinary bin;
-		bin.data = value;
-		bin.binary_length = length;
-		gda_value_reset_with_type (gda_value, GDA_TYPE_BINARY);
-		gda_value_set_binary (gda_value, &bin);
-		break;
-	}
-	case FIELD_TYPE_VAR_STRING :
-	case FIELD_TYPE_STRING :
-		/* FIXME: we might get "[VAR]CHAR(20) BINARY" type with \0 inside
-		   We should check for BINARY flag and treat it like a BLOB
-		 */
-		gda_value_reset_with_type (gda_value, G_TYPE_STRING);
-		g_value_set_string (gda_value, value);
-		break;
-	case FIELD_TYPE_DATE :
-		gda_value_set_from_string (gda_value, value, G_TYPE_DATE);
-		break;
-	case FIELD_TYPE_TIME :
-		gda_value_set_from_string (gda_value, value, GDA_TYPE_TIME);
-		break;
-	case FIELD_TYPE_TIMESTAMP :
-	case FIELD_TYPE_DATETIME :
-		gda_value_set_from_string (gda_value, value, GDA_TYPE_TIMESTAMP);
-		break;
-	case FIELD_TYPE_NULL :
-		gda_value_set_null (gda_value);
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (GDA_IS_MYSQL_RECORDSET(object));
+	g_return_if_fail (GDA_MYSQL_RECORDSET(object)->priv != NULL);
+
+	record_set = GDA_MYSQL_RECORDSET(object);
+
+	switch (param_id) {
+	case PROP_CHUNK_SIZE:
+		g_value_set_int (value, record_set->priv->chunk_size);
 		break;
-	case FIELD_TYPE_NEWDATE :
-	case FIELD_TYPE_ENUM :
-	case FIELD_TYPE_SET : /* FIXME */
-		gda_value_reset_with_type (gda_value, G_TYPE_STRING);
-		g_value_set_string (gda_value, value);
+	case PROP_CHUNKS_READ:
+		g_value_set_int (value, record_set->priv->chunks_read);
 		break;
-	default :
-		g_printerr ("Unknown MySQL datatype.  This is fishy, but continuing anyway.\n");
-		g_value_set_string (gda_value, value);
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
 	}
 }
 
 
-static GdaRow *
-fetch_row (GdaMysqlRecordset *recset, gulong rownum)
+static void
+gda_mysql_recordset_class_init (GdaMysqlRecordsetClass  *klass)
 {
-	GdaRow *row;
-	gint field_count;
-	gint row_count;
-	gint i;
-	MYSQL_FIELD *mysql_fields;
-	MYSQL_ROW mysql_row;
-	unsigned long *mysql_lengths;
-
-	g_return_val_if_fail (GDA_IS_MYSQL_RECORDSET (recset), NULL);
-	g_return_val_if_fail (recset->priv != NULL, 0);
+	g_print ("*** %s\n", __func__);
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	GdaPModelClass *pmodel_class = GDA_PMODEL_CLASS (klass);
 
-	if (!recset->priv->mysql_res) {
-		gda_connection_add_event_string (recset->priv->cnc, _("Invalid MySQL handle"));
-		return NULL;
-	}
+	parent_class = g_type_class_peek_parent (klass);
 
-	/* move to the corresponding row */
-	row_count = mysql_num_rows (recset->priv->mysql_res);
-	if (row_count == 0)
-		return NULL;
-	field_count = mysql_num_fields (recset->priv->mysql_res);
+	object_class->dispose = gda_mysql_recordset_dispose;
+	pmodel_class->fetch_nb_rows = gda_mysql_recordset_fetch_nb_rows;
+	pmodel_class->fetch_random = gda_mysql_recordset_fetch_random;
+
+	pmodel_class->fetch_next = gda_mysql_recordset_fetch_next;
+	pmodel_class->fetch_prev = gda_mysql_recordset_fetch_prev;
+	pmodel_class->fetch_at = gda_mysql_recordset_fetch_at;
+	
+	/* Properties. */
+	object_class->set_property = gda_mysql_recordset_set_property;
+	object_class->get_property = gda_mysql_recordset_get_property;
+
+	g_object_class_install_property
+		(object_class,
+		 PROP_CHUNK_SIZE,
+		 g_param_spec_int ("chunk-size", _("Number of rows fetched at a time"),
+				   NULL,
+				   1, G_MAXINT - 1, 10,
+				   (G_PARAM_CONSTRUCT | G_PARAM_WRITABLE | G_PARAM_READABLE)));
+
+	g_object_class_install_property
+		(object_class,
+		 PROP_CHUNKS_READ,
+		 g_param_spec_int ("chunks-read", _("Number of row chunks read since the object creation"),
+				   NULL,
+				   0, G_MAXINT - 1, 0,
+				   (G_PARAM_CONSTRUCT | G_PARAM_WRITABLE | G_PARAM_READABLE)));
+	
+}
 
-	if (rownum < 0 || rownum >= row_count) {
-		gda_connection_add_event_string (recset->priv->cnc, _("Row number out of range"));
-		return NULL;
-	}
+static void
+gda_mysql_recordset_dispose (GObject  *object)
+{
+	g_print ("*** %s\n", __func__);
+	GdaMysqlRecordset *recset = (GdaMysqlRecordset *) object;
 
-	mysql_data_seek (recset->priv->mysql_res, rownum);
-	mysql_fields = mysql_fetch_fields (recset->priv->mysql_res);
-	mysql_row = mysql_fetch_row (recset->priv->mysql_res);
-	mysql_lengths = mysql_fetch_lengths (recset->priv->mysql_res);
-	if (!mysql_row || !mysql_lengths)
-		return NULL;
-	
-	row = gda_row_new (GDA_DATA_MODEL (recset), field_count);
+	g_return_if_fail (GDA_IS_MYSQL_RECORDSET (recset));
 
-	for (i = 0; i < field_count; i++) {
-		fill_gda_value ((GValue*) gda_row_get_value (row, i),
-				mysql_fields[i].type,
-				mysql_row[i],
-				mysql_lengths[i],
-				mysql_fields[i].flags & UNSIGNED_FLAG);
+	if (recset->priv) {
+		if (recset->priv->cnc) 
+			g_object_unref (recset->priv->cnc);
+
+		/* free specific information */
+		// TO_IMPLEMENT;
+		
+                gint i;
+                for (i = 0; i < (((GdaPModel *)recset)->prep_stmt)->ncols; ++i) {
+                        g_free (recset->priv->mysql_bind[i].buffer);
+                        g_free (recset->priv->mysql_bind[i].is_null);
+                        g_free (recset->priv->mysql_bind[i].length);
+                }
+                g_free (recset->priv->mysql_bind);
+                recset->priv->mysql_bind = NULL;
+
+		
+		g_free (recset->priv);
+		recset->priv = NULL;
 	}
 
-	return row;
+	parent_class->dispose (object);
 }
 
 /*
- * GdaMysqlRecordset class implementation
+ * Public functions
  */
 
-static gint
-gda_mysql_recordset_get_n_rows (GdaDataModelRow *model)
+GType
+gda_mysql_recordset_get_type (void)
 {
-	GdaMysqlRecordset *recset = (GdaMysqlRecordset *) model;
+	static GType type = 0;
 
-	g_return_val_if_fail (GDA_IS_MYSQL_RECORDSET (recset), -1);
-	g_return_val_if_fail (recset->priv != NULL, -1);
+	if (G_UNLIKELY (type == 0)) {
+		static const GTypeInfo info = {
+			sizeof (GdaMysqlRecordsetClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) gda_mysql_recordset_class_init,
+			NULL,
+			NULL,
+			sizeof (GdaMysqlRecordset),
+			0,
+			(GInstanceInitFunc) gda_mysql_recordset_init
+		};
+		type = g_type_register_static (GDA_TYPE_PMODEL, "GdaMysqlRecordset", &info, 0);
+	}
 
-	if (recset->priv->row_sync == FALSE)
-		return recset->priv->mysql_res_rows;
-	else
-		return GDA_DATA_MODEL_ROW_CLASS (parent_class)->get_n_rows (model);
+	return type;
 }
 
-static GdaRow *
-gda_mysql_recordset_get_row (GdaDataModelRow *model, gint row, GError **error)
+/*
+ * the @ps struct is modified and transfered to the new data model created in
+ * this function
+ */
+GdaDataModel *
+gda_mysql_recordset_new (GdaConnection            *cnc,
+			 GdaMysqlPStmt            *ps,
+			 GdaDataModelAccessFlags   flags,
+			 GType                    *col_types)
 {
-	GdaMysqlRecordset *recset = (GdaMysqlRecordset *) model;
-	GdaMysqlRecordsetPrivate *priv_data;
-	gint fetched_rows;
-	gint i;
-	GdaRow *row_list;
+	g_print ("*** %s\n", __func__);
+	GdaMysqlRecordset *model;
+        MysqlConnectionData *cdata;
+        gint i;
+	GdaDataModelAccessFlags rflags;
+	
+	MYSQL_BIND *mysql_bind = NULL;
+	
 
-	g_return_val_if_fail (GDA_IS_MYSQL_RECORDSET (recset), NULL);
-	g_return_val_if_fail (recset->priv != NULL, 0);
+        g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+        g_return_val_if_fail (ps != NULL, NULL);
 
-	row_list = (GdaRow *) GDA_DATA_MODEL_ROW_CLASS (parent_class)->get_row (model, row, 
-										error);
-	if (row_list != NULL)
-		return row_list;	
-
-	priv_data = recset->priv;
-	if (!priv_data->mysql_res) {
-		gda_connection_add_event_string (priv_data->cnc,
-						_("Invalid MySQL handle"));
+	cdata = (MysqlConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata)
 		return NULL;
-	}
-	
-	if (row < 0 || row > priv_data->mysql_res_rows) {
-		gchar *str;
 
-		str = g_strdup_printf (_("Row number out of range 0 - %d"),
-				       priv_data->mysql_res_rows - 1);
-		gda_connection_add_event_string (priv_data->cnc, str);
-		g_set_error (error, 0, 0, str);
-		g_free (str);
-						 
-		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;
+		
+		_GDA_PSTMT(ps)->ncols = mysql_stmt_field_count (cdata->mysql_stmt);
+		
+	}
+
+        /* 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];
+				}
+			}
+		}
 
-	fetched_rows = GDA_DATA_MODEL_ROW_CLASS (parent_class)->get_n_rows (model);
+		
+		MYSQL_RES *mysql_res = mysql_stmt_result_metadata (cdata->mysql_stmt);
+		MYSQL_FIELD *mysql_fields = mysql_fetch_fields (mysql_res);
+		
+		mysql_bind = g_new0 (MYSQL_BIND, GDA_PSTMT (ps)->ncols);
+		//		
+		/* 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);
 
-	gda_data_model_freeze (GDA_DATA_MODEL (recset));
+			/* use C API to set columns' information using gda_column_set_*() */
+			// 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) {
+				gtype = _gda_mysql_type_to_gda (cdata, field->type);
+				_GDA_PSTMT(ps)->types[i] = gtype;
+			}
+			gda_column_set_g_type (column, gtype);
+			gda_column_set_name (column, field->name);
+			gda_column_set_title (column, field->name);
+			gda_column_set_scale (column, (gtype == G_TYPE_DOUBLE) ? DBL_DIG :
+					      (gtype == G_TYPE_FLOAT) ? FLT_DIG : 0);
+			gda_column_set_defined_size (column, field->length);
+			gda_column_set_references (column, "");
+
+			/* Use @cnc's associate GdaMetaStore to get the following information:
+			gda_column_set_references (column, ...);
+			gda_column_set_table (column, ...);
+			gda_column_set_primary_key (column, ...);
+			gda_column_set_unique_key (column, ...);
+			gda_column_set_allow_null (column, ...);
+			gda_column_set_auto_increment (column, ...);
+			*/
+
+			
+			mysql_bind[i].buffer_type = field->type;
+			switch (mysql_bind[i].buffer_type) {
+			case MYSQL_TYPE_TINY:
+			case MYSQL_TYPE_SHORT:
+			case MYSQL_TYPE_INT24:
+			case MYSQL_TYPE_LONG:
+			case MYSQL_TYPE_LONGLONG:
+				mysql_bind[i].buffer = g_malloc0 (sizeof(int));
+				mysql_bind[i].is_null = g_malloc0 (sizeof(my_bool));
+				break;
+			case MYSQL_TYPE_NULL:
+				break;
+			case MYSQL_TYPE_TIME:
+			case MYSQL_TYPE_DATE:
+			case MYSQL_TYPE_DATETIME:
+			case MYSQL_TYPE_TIMESTAMP:
+				mysql_bind[i].buffer = g_malloc0 (sizeof(MYSQL_TIME));
+				break;
+			case MYSQL_TYPE_FLOAT:
+			case MYSQL_TYPE_DOUBLE:
+				mysql_bind[i].buffer = g_malloc0 (sizeof(double));
+				mysql_bind[i].is_null = g_malloc0 (sizeof(my_bool));
+				break;
+			case MYSQL_TYPE_VAR_STRING:
+			case MYSQL_TYPE_BLOB:
+			case MYSQL_TYPE_TINY_BLOB:
+			case MYSQL_TYPE_MEDIUM_BLOB:
+			case MYSQL_TYPE_LONG_BLOB:
+				mysql_bind[i].buffer = g_malloc0 (field->max_length + 1);
+				mysql_bind[i].buffer_length = field->max_length + 1;
+				mysql_bind[i].length = g_malloc0 (sizeof(unsigned long));
+				break;
+			default:
+				g_warning (_("Invalid column bind data type.\n"),
+					   mysql_bind[i].buffer_type);
+			}
+			
+		}
+		
+                if (mysql_stmt_bind_result (cdata->mysql_stmt, mysql_bind)) {
+                        g_warning ("mysql_stmt_bind_result failed: %s\n", mysql_stmt_error (cdata->mysql_stmt));
+                }
+		
+		mysql_free_result (mysql_res);
+		
+        }
+
+	/* determine access mode: RANDOM or CURSOR FORWARD are the only supported */
+	if (flags & GDA_DATA_MODEL_ACCESS_RANDOM)
+		rflags = GDA_DATA_MODEL_ACCESS_RANDOM;
+	else
+		rflags = GDA_DATA_MODEL_ACCESS_CURSOR_FORWARD;
 
-	for (i = fetched_rows; i <= row; i++) {
-		row_list = fetch_row (recset, i);
-		if (!row_list)
-			return NULL;
+	/* create data model */
+        model = g_object_new (GDA_TYPE_MYSQL_RECORDSET,
+			      "prepared-stmt", ps,
+			      "model-usage", rflags,
+			      NULL);
+        model->priv->cnc = cnc;
+	g_object_ref (G_OBJECT(cnc));
 
-		if (! GDA_DATA_MODEL_ROW_CLASS (parent_class)->append_row (model, row_list, NULL))
-			return NULL;
-	}
+	/* post init specific code */
+	// TO_IMPLEMENT;
+	
+	if (mysql_bind != NULL)
+		model->priv->mysql_bind = mysql_bind;
+	
+	model->priv->mysql_stmt = cdata->mysql_stmt;
 
-	gda_data_model_thaw (GDA_DATA_MODEL (recset));
+	((GdaPModel *) model)->advertized_nrows = mysql_stmt_affected_rows (cdata->mysql_stmt);
+	
 
-	return row_list;
+        return GDA_DATA_MODEL (model);
 }
 
-static const GValue *
-gda_mysql_recordset_get_value_at (GdaDataModelRow *model, gint col, gint row)
-{
-	GdaMysqlRecordset *recset = (GdaMysqlRecordset *) model;
-	GdaMysqlRecordsetPrivate *priv_data;
-	const GValue *value;
-	const GdaRow *fields;
 
-	g_return_val_if_fail (GDA_IS_MYSQL_RECORDSET (recset), NULL);
-	g_return_val_if_fail (recset->priv != NULL, 0);
-
-	if (row < GDA_DATA_MODEL_ROW_CLASS (parent_class)->get_n_rows (model)) {
-		value = GDA_DATA_MODEL_ROW_CLASS (parent_class)->get_value_at (model, col, row);
-		if (value != NULL)
-			return value;
-	}
-
-	priv_data = recset->priv;
-        if (!priv_data->mysql_res) {
-		gda_connection_add_event_string (priv_data->cnc,
-						 _("Invalid MySQL handle"));
-		return NULL;
-	}
+/*
+ * Get the number of rows in @model, if possible
+ */
+static gint
+gda_mysql_recordset_fetch_nb_rows (GdaPModel *model)
+{
+	g_print ("*** %s\n", __func__);
+	GdaMysqlRecordset *imodel;
 
-	if (row < 0 || row > priv_data->mysql_res_rows) {
-		gda_connection_add_event_string (priv_data->cnc,
-						 _("Row number out of range"));
-		return NULL;
-	}
+	imodel = GDA_MYSQL_RECORDSET (model);
+	if (model->advertized_nrows >= 0)
+		return model->advertized_nrows;
 
-	if (col >= priv_data->ncolumns) {
-		gda_connection_add_event_string (priv_data->cnc,
-						 _("Column number out of range"));
-		return NULL;
-	}	
+	/* use C API to determine number of rows,if possible */
+	// TO_IMPLEMENT;
+	
+	model->advertized_nrows = mysql_stmt_affected_rows (imodel->priv->mysql_stmt);
+	
 
-	fields = gda_mysql_recordset_get_row (model, row, NULL);
-	return fields != NULL ? gda_row_get_value ((GdaRow *) fields, col) : NULL;
+	return model->advertized_nrows;
 }
 
-static gboolean
-gda_mysql_recordset_is_updatable (GdaDataModelRow *model)
-{
-	GdaCommandType cmd_type;
-	GdaMysqlRecordset *recset = (GdaMysqlRecordset *) model;
 
-	g_return_val_if_fail (GDA_IS_MYSQL_RECORDSET (recset), FALSE);
-	
-	g_object_get (G_OBJECT (model), "command_type", &cmd_type, NULL);
-	return cmd_type == GDA_COMMAND_TYPE_TABLE ? TRUE : FALSE;
-}
-
-static gboolean
-gda_mysql_recordset_append_row (GdaDataModelRow *model, GdaRow *row, GError **error)
+static GdaPRow *
+new_row_from_mysql_stmt (GdaMysqlRecordset  *imodel,
+			 gint                rownum)
 {
-	GdaMysqlRecordset *recset = (GdaMysqlRecordset *) model;
-	GdaMysqlRecordsetPrivate *priv_data;
-	GdaRow *row_list;
-	MYSQL *mysql;
-	MYSQL_FIELD *mysql_field;
-	gint i, fetched_rows, rc;
-	GString *sql, *sql_value;
-	const gchar *column_name;
-
-	g_return_val_if_fail (GDA_IS_MYSQL_RECORDSET (recset), FALSE);
-	g_return_val_if_fail (row != NULL, FALSE);
-	g_return_val_if_fail (gda_data_model_is_updatable (GDA_DATA_MODEL (model)), FALSE);
-	g_return_val_if_fail (recset->priv != NULL, FALSE);
-
-	priv_data = recset->priv;
-
-	/* checks for valid MySQL handle */
-        if (!priv_data->mysql_res) {
-		gda_connection_add_event_string (priv_data->cnc, _("Invalid MySQL handle"));
-		return FALSE;
-	}
-
-	/* get the mysql handle */
-	mysql = g_object_get_data (G_OBJECT (priv_data->cnc), OBJECT_DATA_MYSQL_HANDLE);
+	g_print ("*** %s -- %d -- %d\n", __func__,
+		 ((GdaPModel *) imodel)->prep_stmt->ncols, rownum);
 	
-	/* checks if the table name has been guessed */
-	if (priv_data->table_name == NULL) {
-		gda_connection_add_event_string (priv_data->cnc,
-						_("Table name could not be guessed"));
-		return FALSE;
-	}
-
-	/* checks for correct number of columns */
-	if (priv_data->ncolumns != gda_row_get_length (row)) {
-		gda_connection_add_event_string (priv_data->cnc,
-						_("Attempt to insert a row with an invalid number of columns"));
-		return FALSE;
-	}
-
-	/* check if all results are loaded in array, if not do so */
-	if (priv_data->row_sync == FALSE)
-	{
-		fetched_rows = GDA_DATA_MODEL_ROW_CLASS (parent_class)->get_n_rows (model);
-
-		gda_data_model_freeze (GDA_DATA_MODEL (recset));
-
-		for (i = fetched_rows; i < priv_data->mysql_res_rows; i++) {
-			row_list = fetch_row (recset, i);
-			if (!row_list) {
-				gda_connection_add_event_string (priv_data->cnc,
-						_("Can not synchronize array with MySQL result set"));
-				return FALSE;
+	MYSQL_BIND *mysql_bind = imodel->priv->mysql_bind;
+	g_assert (mysql_bind);
+	
+	GdaPRow *prow = gda_prow_new (((GdaPModel *) imodel)->prep_stmt->ncols);
+	gint col;
+	for (col = 0; col < ((GdaPModel *) imodel)->prep_stmt->ncols; ++col) {
+		
+		GValue *value = gda_prow_get_value (prow, col);
+		GType type = ((GdaPModel *) imodel)->prep_stmt->types[col];
+		gda_value_reset_with_type (value, type);
+		
+		gint i = col;
+		
+		int intvalue = 0;
+		double doublevalue = 0.0;
+		MYSQL_TIME timevalue = { 0 };
+		char *strvalue = NULL;
+		my_bool is_null;
+		unsigned long length;
+		
+		switch (mysql_bind[i].buffer_type) {
+		case MYSQL_TYPE_TINY:
+		case MYSQL_TYPE_SHORT:
+		case MYSQL_TYPE_INT24:
+		case MYSQL_TYPE_LONG:
+		case MYSQL_TYPE_LONGLONG:
+			g_memmove (&intvalue, mysql_bind[i].buffer, sizeof(int));
+			g_memmove (&is_null, mysql_bind[i].is_null, sizeof(my_bool));
+			
+			if (type == G_TYPE_INT)
+				g_value_set_int (value, intvalue);
+			else if (type == G_TYPE_LONG)
+				g_value_set_long (value, (long) intvalue);
+			else {
+				g_warning (_("Type %s not mapped for value %d"),
+					   g_type_name (type), intvalue);
 			}
-
-			if (!GDA_DATA_MODEL_ROW_CLASS (parent_class)->append_row (model, row_list, NULL)) {
-				gda_connection_add_event_string (priv_data->cnc,
-						_("Can not synchronize array with MySQL result set"));
-				return FALSE;
+			
+			break;
+		case MYSQL_TYPE_NULL:
+			break;
+		case MYSQL_TYPE_TIME:
+		case MYSQL_TYPE_DATE:
+		case MYSQL_TYPE_DATETIME:
+		case MYSQL_TYPE_TIMESTAMP:
+			g_memmove (&timevalue, mysql_bind[i].buffer, sizeof(MYSQL_TIME));
+			break;
+		case MYSQL_TYPE_FLOAT:
+		case MYSQL_TYPE_DOUBLE:
+			g_memmove (&doublevalue, mysql_bind[i].buffer, sizeof(double));
+			g_memmove (&is_null, mysql_bind[i].is_null, sizeof(my_bool));
+			
+			setlocale (LC_NUMERIC, "C");
+			if (type == G_TYPE_FLOAT)
+				g_value_set_float (value, (float) doublevalue);
+			else if (type == G_TYPE_DOUBLE)
+				g_value_set_long (value, doublevalue);
+			else {
+				g_warning (_("Type %s not mapped for value %f"),
+					   g_type_name (type), intvalue);
 			}
+			setlocale (LC_NUMERIC, "");
+			
+			break;
+		case MYSQL_TYPE_VAR_STRING:
+		case MYSQL_TYPE_BLOB:
+		case MYSQL_TYPE_TINY_BLOB:
+		case MYSQL_TYPE_MEDIUM_BLOB:
+		case MYSQL_TYPE_LONG_BLOB:
+			g_memmove (&length, mysql_bind[i].length, sizeof(unsigned long));
+			strvalue = g_memdup (mysql_bind[i].buffer, length + 1);
+			
+			if (type == G_TYPE_STRING)
+				g_value_set_string (value, strvalue);
+			else {
+				g_warning (_("Type %s not mapped for value %p"),
+					   g_type_name (type), strvalue);
+			}
+			
+			break;
+		default:
+			g_warning (_("Invalid column bind data type.\n"),
+				   mysql_bind[i].buffer_type);
 		}
+		
+	}
+	return prow;
+}
 
-		gda_data_model_thaw (GDA_DATA_MODEL (recset));
-
-		/* set flag that all mysql result records are in array */
-		priv_data->row_sync = TRUE;
-	}	
-
-	/* prepare the SQL statement */
-	sql = g_string_new ("INSERT INTO ");
-        g_string_append_printf (sql, "%s (", priv_data->table_name);
 
-	sql_value = g_string_new ("VALUES (");
+/*
+ * Create a new filled #GdaPRow object for the row at position @rownum, and put it into *prow.
+ *
+ * WARNING: @prow will NOT be NULL, but *prow may or may not be NULL:
+ *  -  If *prow is NULL then a new #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 
+gda_mysql_recordset_fetch_random (GdaPModel  *model,
+				  GdaPRow   **prow,
+				  gint        rownum,
+				  GError    **error)
+{
+	g_print ("*** %s\n", __func__);
+	GdaMysqlRecordset *imodel;
 
-	for (i = 0; i < priv_data->ncolumns; i++) {
+	imodel = GDA_MYSQL_RECORDSET (model);
 
-		if (i != 0) {
-			sql = g_string_append (sql, ", ");
-			sql_value = g_string_append (sql_value, ", ");
-		}
-		/* get column name */
-		mysql_field = mysql_fetch_field_direct (priv_data->mysql_res, i);
-		if (mysql_field)
-			column_name = mysql_field->name;
-		else
-			column_name = gda_data_model_get_column_title (GDA_DATA_MODEL (model), i);
-
-		sql = g_string_append (sql, "`");
-		sql = g_string_append (sql, column_name);
-		sql = g_string_append (sql, "`");
-
-		sql_value = g_string_append (sql_value, 
-			gda_mysql_provider_value_to_sql_string ( 	 
-				NULL, 	 
-				priv_data->cnc, 	 
-				gda_row_get_value ((GdaRow *) row, i)) 	 
-                 );
-	}
+	// TO_IMPLEMENT;
+	
+	if (*prow)
+		return TRUE;
 
-	/* concatenate SQL statement */
-	sql = g_string_append (sql, ") ");
-	sql = g_string_append (sql, sql_value->str);
-	sql = g_string_append (sql, ")");
-
-	/* execute append command */
-	rc = gda_mysql_real_query_wrap (priv_data->cnc, mysql, sql->str, strlen (sql->str));
-	if (rc != 0) {
-		gda_connection_add_event (
-			priv_data->cnc, gda_mysql_make_error (mysql));
+	if (imodel->priv->mysql_stmt == NULL) {
+		g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+			     GDA_SERVER_PROVIDER_INTERNAL_ERROR,
+			     _("Internal error"));
 		return FALSE;
 	}
-
-	g_string_free (sql, TRUE);
-	g_string_free (sql_value, TRUE);
-
-	/* append row in the array */
-	if (! GDA_DATA_MODEL_ROW_CLASS (parent_class)->append_row (model, row, NULL)) {
-		gda_connection_add_event_string (priv_data->cnc,
-			_("Can not append row to data model"));
+	
+	if (mysql_stmt_fetch (imodel->priv->mysql_stmt))
 		return FALSE;
+	
+	*prow = new_row_from_mysql_stmt (imodel, rownum);
+	gda_pmodel_take_row (model, *prow, rownum);
+	
+	if (model->nb_stored_rows == model->advertized_nrows) {
+		g_print ("*** All the row have been converted...");
 	}
+	
 
 	return TRUE;
 }
 
+/*
+ * Create and "give" filled #GdaPRow object for all the rows in the model
+ */
 static gboolean
-gda_mysql_recordset_remove_row (GdaDataModelRow *model, GdaRow *row, GError **error)
+gda_mysql_recordset_store_all (GdaPModel *model, GError **error)
 {
-	GdaMysqlRecordset *recset = (GdaMysqlRecordset *) model;
-	GdaMysqlRecordsetPrivate *priv_data;
-	GdaRow *row_list;
-	GdaColumn *attrs;
-	MYSQL *mysql;
-	MYSQL_FIELD *mysql_field;
-	gint i, fetched_rows, rc, colnum, uk;
-	gchar *query, *query_where, *tmp;
-	const gchar *column_name;
-
-	g_return_val_if_fail (GDA_IS_MYSQL_RECORDSET (recset), FALSE);
-	g_return_val_if_fail (row != NULL, FALSE);
-	g_return_val_if_fail (gda_data_model_is_updatable (GDA_DATA_MODEL (model)), FALSE);
-	g_return_val_if_fail (recset->priv != NULL, FALSE);
-
-	priv_data = recset->priv;
-
-	/* checks for valid MySQL handle */
-        if (!priv_data->mysql_res) {
-		gda_connection_add_event_string (priv_data->cnc, _("Invalid MySQL handle"));
-		return FALSE;
-	}
-
-	/* get the mysql handle */
-	mysql = g_object_get_data (G_OBJECT (priv_data->cnc), OBJECT_DATA_MYSQL_HANDLE);
-	
-	/* checks if the given row belongs to the given model */
-	if (gda_row_get_model ((GdaRow *) row) != GDA_DATA_MODEL (model)) {
-		g_set_error (error, 0, 0,
-			     _("Given row doesn't belong to the model."));
-		gda_connection_add_event_string (priv_data->cnc,
-						_("Given row doesn't belong to the model."));
-		return FALSE;
-	}
-
-	/* checks if the table name has been guessed */
-	if (priv_data->table_name == NULL) {
-		g_set_error (error, 0, 0,
-			     _("Table name could not be guessed"));
-		gda_connection_add_event_string (priv_data->cnc,
-						_("Table name could not be guessed"));
-		return FALSE;
-	}
-
-	/* check if all results are loaded in array, if not do so */
-	if (priv_data->row_sync == FALSE)
-	{
-		fetched_rows = GDA_DATA_MODEL_ROW_CLASS (parent_class)->get_n_rows (model);
-
-		gda_data_model_freeze (GDA_DATA_MODEL (recset));
-
-		for (i = fetched_rows; i < priv_data->mysql_res_rows; i++) {
-			row_list = fetch_row (recset, i);
-			if (!row_list) {
-				g_set_error (error, 0, 0,
-					     _("Can not synchronize array with MySQL result set"));
-				gda_connection_add_event_string (priv_data->cnc,
-						_("Can not synchronize array with MySQL result set"));
-				return FALSE;
-			}
-
-			if (! GDA_DATA_MODEL_ROW_CLASS (parent_class)->append_row (model, row_list, error)) {
-				gda_connection_add_event_string (priv_data->cnc,
-						_("Can not synchronize array with MySQL result set"));
-				return FALSE;
-			}
-		}
-
-		gda_data_model_thaw (GDA_DATA_MODEL (recset));
-
-		/* set flag that all mysql result records are in array */
-		priv_data->row_sync = TRUE;
-	}	
-
-	query_where = g_strdup ("WHERE ");
-
-	for (colnum = uk = 0;
-	     colnum != gda_data_model_get_n_columns (GDA_DATA_MODEL(model));
-	     colnum++)
-	{
-		attrs = gda_data_model_describe_column (GDA_DATA_MODEL(model), colnum);
-
-		mysql_field = mysql_fetch_field_direct (priv_data->mysql_res, colnum);
-		if (mysql_field)
-			column_name = mysql_field->name;
-		else
-			column_name = gda_data_model_get_column_title (GDA_DATA_MODEL (model), colnum);
-
-		gchar *curval = gda_mysql_provider_value_to_sql_string (
-				NULL, 	 
-				priv_data->cnc, 	 
-				gda_row_get_value ((GdaRow *) row, colnum) 	 
-     		);
-
-		/* unique column: we will use it as an index */
-		if (gda_column_get_primary_key (attrs) ||
-		    gda_column_get_unique_key (attrs)) {
-			/* fills the 'where' part of the update command */
-			if (colnum != 0)
-				query_where = g_strconcat (query_where, "AND ", NULL);
-
-			/* fills the 'where' part of the remove command */
-			tmp = g_strdup_printf ("`%s` = %s ",
-					       column_name,
-					       curval);
-			query_where = g_strconcat (query_where, tmp, NULL);
-			g_free (tmp);
-			uk++;
-		}
-
-		g_free (curval);
-	}
-
-	if (uk == 0) {
-		g_set_error (error, 0, 0,
-			     _("Model doesn't have at least one unique key."));
-		gda_connection_add_event_string (priv_data->cnc,
-						_("Model doesn't have at least one unique key."));
-		g_free (query_where);
-
-		return FALSE;
-	}
-
-	/* build the delete command */
-	query = g_strdup_printf ("DELETE FROM %s %s",
-				 priv_data->table_name,
-				 query_where);
-
-	/* execute append command */
-	rc = gda_mysql_real_query_wrap (priv_data->cnc, mysql, query, strlen (query));
-	if (rc != 0) {
-		gda_connection_add_event (
-			priv_data->cnc, gda_mysql_make_error (mysql));
-		g_free (query);
-		g_free (query_where);
-
-		return FALSE;
-	}
+	g_print ("*** %s\n", __func__);
+	GdaMysqlRecordset *imodel;
+	gint i;
 
-	g_free (query);
-	g_free (query_where);
+	imodel = GDA_MYSQL_RECORDSET (model);
 
-	/* remove row from the array */
-	if (! GDA_DATA_MODEL_ROW_CLASS (parent_class)->remove_row (model, row, NULL)) {
-		g_set_error (error, 0, 0,
-			     _("Can not remove row from data model"));
-		gda_connection_add_event_string (priv_data->cnc,
-			_("Can not remove row from data model"));
-		return FALSE;
+	/* default implementation */
+	for (i = 0; i < model->advertized_nrows; i++) {
+		GdaPRow *prow;
+		if (! gda_mysql_recordset_fetch_random (model, &prow, i, error))
+			return FALSE;
 	}
-
 	return TRUE;
 }
 
-static gboolean
-gda_mysql_recordset_update_row (GdaDataModelRow *model, GdaRow *row, GError **error)
+/*
+ * Create a new filled #GdaPRow object for the next cursor row, and put it into *prow.
+ *
+ * WARNING: @prow will NOT be NULL, but *prow may or may not be NULL:
+ *  -  If *prow is NULL then a new #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_mysql_recordset_fetch_next (GdaPModel *model, GdaPRow **prow, gint rownum, GError **error)
 {
-	GdaMysqlRecordset *recset = (GdaMysqlRecordset *) model;
-	GdaMysqlRecordsetPrivate *priv_data;
-	gint colnum, uk, nuk, rc, rownum;
-	gchar *query, *query_where, *query_set, *tmp;
-	gchar *oldval, *newval;
-	const gchar *column_name;
-	MYSQL *mysql;
-	MYSQL_FIELD *mysql_field;
-	MYSQL_ROW mysql_row;
-	GdaColumn *attrs;
-
-	g_return_val_if_fail (GDA_IS_MYSQL_RECORDSET (recset), FALSE);
-	g_return_val_if_fail (row != NULL, FALSE);
-	g_return_val_if_fail (gda_data_model_is_updatable (GDA_DATA_MODEL (model)), FALSE);
-	g_return_val_if_fail (recset->priv != NULL, FALSE);
-
-	priv_data = recset->priv;
-
-	/* checks for valid MySQL handle */
-        if (!priv_data->mysql_res) {
-		g_set_error (error, 0, 0,
-			     _("Invalid MySQL handle"));
-		gda_connection_add_event_string (priv_data->cnc, _("Invalid MySQL handle"));
-		return FALSE;
-	}
-
-	/* get the mysql handle */
-	mysql = g_object_get_data (G_OBJECT (priv_data->cnc), OBJECT_DATA_MYSQL_HANDLE);
-	
-	/* checks if the given row belongs to the given model */
-	if (gda_row_get_model ((GdaRow *) row) != GDA_DATA_MODEL (model)) {
-		g_set_error (error, 0, 0,
-			     _("Given row doesn't belong to the model."));
-		gda_connection_add_event_string (priv_data->cnc,
-						_("Given row doesn't belong to the model."));
-		return FALSE;
-	}
-
-	/* checks if the table name has been guessed */
-	if (priv_data->table_name == NULL) {
-		g_set_error (error, 0, 0,
-			     _("Table name could not be guessed."));
-		gda_connection_add_event_string (priv_data->cnc,
-						_("Table name could not be guessed."));
-		return FALSE;
-	}
-
-	/* init query */
-	query_where = g_strdup ("WHERE ");
-	query_set = g_strdup ("SET ");
-
-	/* get original data if from mysql result set */
-	rownum = gda_row_get_number ((GdaRow *) row);
-	if (rownum < priv_data->mysql_res_rows) {
-		mysql_data_seek (recset->priv->mysql_res, rownum);
-		mysql_row = mysql_fetch_row (recset->priv->mysql_res);
-	}
-
-	/* process columns */
-	for (colnum = uk = nuk = 0;
-	     colnum != gda_data_model_get_n_columns (GDA_DATA_MODEL (model));
-	     colnum++) 
-	{
-		attrs = gda_data_model_describe_column (GDA_DATA_MODEL (model), colnum);
-		mysql_field = mysql_fetch_field_direct (priv_data->mysql_res, colnum);
-		if (mysql_field)
-			column_name = mysql_field->name;
-		else
-			column_name = gda_data_model_get_column_title (GDA_DATA_MODEL (model), colnum);
-		newval = gda_value_stringify (gda_row_get_value ((GdaRow *) row, colnum));
-
-		/* for data from mysql result we can retrieve original values to avoid 
-		   unique columns to be updated */
-		if (rownum < priv_data->mysql_res_rows)
-			oldval = mysql_row[colnum];
-		else
-			oldval = newval;
-
-		/* unique column: we won't update it, but we will use it as
-		   an index */
-		if (gda_column_get_primary_key (attrs) ||
-		    gda_column_get_unique_key (attrs)) 
-		{
-			/* checks if it hasn't be modified anyway */
-			if (oldval == NULL ||
-	   		    newval == NULL ||
-			    strcmp (oldval, newval) != 0)
-			    	continue;
-
-			/* fills the 'where' part of the update command */
-			if (colnum != 0)
-				query_where = g_strconcat (query_where, "AND ", NULL);
-
-			tmp = g_strdup_printf ("`%s` = '%s' ",
-					       column_name,
-					       newval);
-			query_where = g_strconcat (query_where, tmp, NULL);
-			g_free (tmp);
-			uk++;
-		}
-		/* non-unique column: update it */
-		else {
-			/* fills the 'set' part of the update command */
-			tmp = g_strdup_printf ("`%s` = '%s', ", 
-					       column_name,
-					       newval);
-			query_set = g_strconcat (query_set, tmp, NULL);
-			g_free (tmp);
-			nuk++;
-		}
-
-		g_free (newval);
-	}
-
-	if (uk == 0) {
-		g_set_error (error, 0, 0,
-			     _("Model does not have at least one non-modified unique key."));	     
-		gda_connection_add_event_string (priv_data->cnc,
-						_("Model does not have at least one non-modified unique key."));
-		g_free (query_set);
-		g_free (query_where);
-
-		return FALSE;
-	}
-
-	if (nuk == 0) {
-		g_set_error (error, 0, 0,
-			     _("Model does not have any non-unique values to update."));
-		gda_connection_add_event_string (priv_data->cnc,
-						_("Model does not have any non-unique values to update."));
-		g_free (query_set);
-		g_free (query_where);
-
-		return FALSE;
-	}
-
-	/* remove the last ',' in the SET part */
-	tmp = strrchr (query_set, ',');
-	if (tmp != NULL)
-		*tmp = ' ';
-	
-	/* build the update command */
-	query = g_strdup_printf ("UPDATE %s %s %s", 
-				 priv_data->table_name,
-				 query_set,
-				 query_where);
-	
-	/* execute update command */
-	rc = gda_mysql_real_query_wrap (priv_data->cnc, mysql, query, strlen (query));
-	if (rc != 0) {
-		GdaConnectionEvent *event = gda_mysql_make_error (mysql);
-		gda_connection_add_event (priv_data->cnc, event);
-		g_set_error (error, 0, 0,
-			     gda_connection_event_get_description (event));
-		return FALSE;
-	}
-	
-	/* emit update signals */
-	gda_data_model_row_updated (GDA_DATA_MODEL (model), gda_row_get_number ((GdaRow *) row));
+	g_print ("*** %s\n", __func__);
+	GdaMysqlRecordset *imodel = (GdaMysqlRecordset*) model;
 
-	/* clean up */
-	g_free (query);
-	g_free (query_set);
-	g_free (query_where);
+	TO_IMPLEMENT;
 
 	return TRUE;
 }
 
-GType
-gda_mysql_recordset_get_type (void)
+/*
+ * Create a new filled #GdaPRow object for the previous cursor row, and put it into *prow.
+ *
+ * WARNING: @prow will NOT be NULL, but *prow may or may not be NULL:
+ *  -  If *prow is NULL then a new #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_mysql_recordset_fetch_prev (GdaPModel *model, GdaPRow **prow, gint rownum, GError **error)
 {
-	static GType type = 0;
+	g_print ("*** %s\n", __func__);
+	GdaMysqlRecordset *imodel = (GdaMysqlRecordset*) model;
 
-	if (G_UNLIKELY (type == 0)) {
-		static const GTypeInfo info = {
-			sizeof (GdaMysqlRecordsetClass),
-			(GBaseInitFunc) NULL,
-			(GBaseFinalizeFunc) NULL,
-			(GClassInitFunc) gda_mysql_recordset_class_init,
-			NULL,
-			NULL,
-			sizeof (GdaMysqlRecordset),
-			0,
-			(GInstanceInitFunc) gda_mysql_recordset_init
-		};
-		type = g_type_register_static (PARENT_TYPE, "GdaMysqlRecordset", &info, 0);
-	}
+	TO_IMPLEMENT;
 
-	return type;
+	return TRUE;
 }
 
-GdaMysqlRecordset *
-gda_mysql_recordset_new (GdaConnection *cnc, MYSQL_RES *mysql_res, MYSQL *mysql)
+/*
+ * 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_mysql_recordset_fetch_at (GdaPModel *model, GdaPRow **prow, gint rownum, GError **error)
 {
-	GdaMysqlRecordset *model;
-	MYSQL_FIELD *mysql_fields;
-
-	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-	g_return_val_if_fail (mysql_res != NULL || mysql != NULL, NULL);
-
-	model = g_object_new (GDA_TYPE_MYSQL_RECORDSET, NULL);
-	model->priv->mysql_res = mysql_res;
-	model->priv->cnc = cnc;
-	model->priv->row_sync = FALSE;
-	model->priv->ncolumns = 0;
-	if (mysql_res == NULL) {
-		model->priv->mysql_res_rows = mysql_affected_rows (mysql);
-		return model;
-	} 
-	else 
-		model->priv->mysql_res_rows = mysql_num_rows (model->priv->mysql_res);
-
-	mysql_fields = mysql_fetch_fields (model->priv->mysql_res);
-	if (mysql_fields != NULL) {
-		gint i;
-
-		model->priv->ncolumns = mysql_num_fields (model->priv->mysql_res);
-		gda_data_model_array_set_n_columns (GDA_DATA_MODEL_ARRAY (model),
-						    model->priv->ncolumns);
-		for (i = 0; i < model->priv->ncolumns; i++) {
-			GdaColumn *column;
-			MYSQL_FIELD *mysql_field;
-
-			/* determine table name */
-			gboolean multi_table = FALSE;
-			if (strcmp(mysql_fields[i].table, mysql_fields[0].table) != 0)
-				multi_table = TRUE;
-
-			if (multi_table == FALSE)
-				model->priv->table_name = g_strdup (mysql_fields[0].table);
-			else
-				model->priv->table_name = NULL;
-
-			/* set GdaColumn attributes */
-			column = gda_data_model_describe_column (GDA_DATA_MODEL (model), i);
-			mysql_field = &(mysql_fields[i]);
-			gda_column_set_title (column, mysql_field->name);
-			if (mysql_field->name)
-				gda_column_set_name (column, mysql_field->name);
-			gda_column_set_defined_size (column, mysql_field->length);
-			gda_column_set_table (column, mysql_field->table);
-			gda_column_set_scale (column, mysql_field->decimals);
-			gda_column_set_g_type (column, gda_mysql_type_to_gda (mysql_field->type,
-									       mysql_field->flags & UNSIGNED_FLAG));
-			gda_column_set_allow_null (column, !IS_NOT_NULL (mysql_field->flags));
-			gda_column_set_primary_key (column, IS_PRI_KEY (mysql_field->flags));
-			gda_column_set_unique_key (column, mysql_field->flags & UNIQUE_KEY_FLAG);
-			gda_column_set_auto_increment (column, mysql_field->flags & AUTO_INCREMENT_FLAG);
-		}
-	}
+	g_print ("*** %s\n", __func__);
+	GdaMysqlRecordset *imodel = (GdaMysqlRecordset*) model;
+	
+	TO_IMPLEMENT;
 
-	return model;
+	return TRUE;
 }
 

Modified: trunk/providers/mysql/gda-mysql-recordset.h
==============================================================================
--- trunk/providers/mysql/gda-mysql-recordset.h	(original)
+++ trunk/providers/mysql/gda-mysql-recordset.h	Sun Apr  6 17:06:43 2008
@@ -1,11 +1,8 @@
-/* GDA MySQL provider
- * Copyright (C) 1998 - 2005 The GNOME Foundation.
+/* GDA Mysql provider
+ * Copyright (C) 2008 The GNOME Foundation.
  *
  * AUTHORS:
- *      Michael Lausch <michael lausch at>
- *	Rodrigo Moya <rodrigo gnome-db org>
- *      Vivien Malerba <malerba gnome-db org>
- *	Bas Driessen <bas driessen xobas com>
+ *      Carlos Savoretti <csavoretti gmail com>
  *
  * This Library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public License as
@@ -23,10 +20,12 @@
  * Boston, MA 02111-1307, USA.
  */
 
-#if !defined(__gda_mysql_recordset_h__)
-#  define __gda_mysql_recordset_h__
+#ifndef __GDA_MYSQL_RECORDSET_H__
+#define __GDA_MYSQL_RECORDSET_H__
 
-#include <libgda/gda-data-model-array.h>
+#include <libgda/libgda.h>
+#include <providers-support/gda-pmodel.h>
+#include "gda-mysql-pstmt.h"
 
 G_BEGIN_DECLS
 
@@ -36,21 +35,22 @@
 #define GDA_IS_MYSQL_RECORDSET(obj)         (G_TYPE_CHECK_INSTANCE_TYPE (obj, GDA_TYPE_MYSQL_RECORDSET))
 #define GDA_IS_MYSQL_RECORDSET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDA_TYPE_MYSQL_RECORDSET))
 
-typedef struct _GdaMysqlRecordset      GdaMysqlRecordset;
-typedef struct _GdaMysqlRecordsetClass GdaMysqlRecordsetClass;
+typedef struct _GdaMysqlRecordset        GdaMysqlRecordset;
+typedef struct _GdaMysqlRecordsetClass   GdaMysqlRecordsetClass;
 typedef struct _GdaMysqlRecordsetPrivate GdaMysqlRecordsetPrivate;
 
 struct _GdaMysqlRecordset {
-	GdaDataModelArray         model;
+	GdaPModel                model;
 	GdaMysqlRecordsetPrivate *priv;
 };
 
 struct _GdaMysqlRecordsetClass {
-	GdaDataModelArrayClass parent_class;
+	GdaPModelClass             parent_class;
 };
 
-GType              gda_mysql_recordset_get_type (void) G_GNUC_CONST;
-GdaMysqlRecordset *gda_mysql_recordset_new      (GdaConnection *cnc, MYSQL_RES *mysql_res, MYSQL *mysql);
+GType         gda_mysql_recordset_get_type  (void) G_GNUC_CONST;
+GdaDataModel *gda_mysql_recordset_new       (GdaConnection *cnc, GdaMysqlPStmt *ps, GdaDataModelAccessFlags flags, 
+					    GType *col_types);
 
 G_END_DECLS
 

Added: trunk/providers/mysql/gda-mysql-util.c
==============================================================================
--- (empty file)
+++ trunk/providers/mysql/gda-mysql-util.c	Sun Apr  6 17:06:43 2008
@@ -0,0 +1,213 @@
+/* GDA mysql provider
+ * Copyright (C) 1998 - 2008 The GNOME Foundation.
+ *
+ * AUTHORS:
+ *         Vivien Malerba <malerba gnome-db org>
+ *         Rodrigo Moya <rodrigo gnome-db org>
+ *         Gonzalo Paniagua Javier <gonzalo gnome-db org>
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <glib/gi18n-lib.h>
+#include "gda-mysql-util.h"
+
+/* static GdaConnectionEventCode */
+/* gda_mysql_sqlsate_to_gda_code (const gchar  *sqlstate) */
+/* { */
+/*         guint64 gda_code = g_ascii_strtoull (sqlstate, NULL, 0); */
+
+/*         switch (gda_code) { */
+/*                 case 42501: */
+/*                         return GDA_CONNECTION_EVENT_CODE_INSUFFICIENT_PRIVILEGES; */
+/*                 case 23505: */
+/*                         return GDA_CONNECTION_EVENT_CODE_UNIQUE_VIOLATION; */
+/*                 case 23502: */
+/*                         return GDA_CONNECTION_EVENT_CODE_NOT_NULL_VIOLATION; */
+/*                 default: */
+/*                         return GDA_CONNECTION_EVENT_CODE_UNKNOWN; */
+/*         } */
+/* } */
+
+/*
+ * Create a new #GdaConnectionEvent object and "adds" it to @cnc
+ *
+ * Returns: a new GdaConnectionEvent which must not be unrefed()
+ */
+GdaConnectionEvent *
+_gda_mysql_make_error (GdaConnection  *cnc,
+		       MYSQL          *mysql, /* PGresult *pg_res, */
+		       GError        **error)
+{
+	/* GdaConnectionEvent *error_ev; */
+        /* GdaConnectionEventCode gda_code = GDA_CONNECTION_EVENT_CODE_UNKNOWN; */
+        /* GdaTransactionStatus *trans; */
+
+        /* error_ev = gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR); */
+        /* if (mysql != NULL) { */
+        /*         gchar *message; */
+
+        /*         if (pg_res != NULL) { */
+        /*                 gchar *sqlstate; */
+
+        /*                 message = g_strdup (PQresultErrorMessage (pg_res)); */
+        /*                 // sqlstate = PQresultErrorField (pg_res, PG_DIAG_SQLSTATE); */
+        /*                 gda_connection_event_set_sqlstate (error_ev, sqlstate); */
+        /*                 gda_code = gda_mysql_sqlsate_to_gda_code (sqlstate); */
+        /*         } */
+        /*         else { */
+        /*                 message = g_strdup (PQerrorMessage (mysql)); */
+        /*                 gda_code = GDA_CONNECTION_EVENT_CODE_UNKNOWN; */
+        /*         } */
+
+		
+	/* 	gchar *ptr = message; */
+	/* 	if (g_str_has_prefix (message, "ERROR:")) */
+	/* 		ptr += 6; */
+	/* 	g_strstrip (ptr); */
+
+        /*         gda_connection_event_set_description (error_ev, ptr); */
+        /*         gda_connection_event_set_gda_code (error_ev, gda_code); */
+	/* 	g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_STATEMENT_EXEC_ERROR, ptr); */
+	/* 	g_free (message); */
+        /* } */
+        /* else { */
+        /*         gda_connection_event_set_description (error_ev, _("No detail")); */
+        /*         gda_connection_event_set_gda_code (error_ev, gda_code); */
+	/* 	g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_STATEMENT_EXEC_ERROR, */
+	/* 		     _("No detail")); */
+        /* } */
+
+        /* gda_connection_event_set_code (error_ev, -1); */
+        /* gda_connection_event_set_source (error_ev, "gda-mysql"); */
+        /* gda_connection_add_event (cnc, error_ev); */
+
+        /* /\* change the transaction status if there is a problem *\/ */
+        /* trans = gda_connection_get_transaction_status (cnc); */
+        /* if (trans) { */
+        /*         if ((PQtransactionStatus (mysql) == PQTRANS_INERROR) && */
+        /*             (trans->state != GDA_TRANSACTION_STATUS_STATE_FAILED)) */
+        /*                 gda_connection_internal_change_transaction_state (cnc, */
+        /*                                                                   GDA_TRANSACTION_STATUS_STATE_FAILED); */
+        /* } */
+        /* return error_ev; */
+	
+	GdaConnectionEvent *event_error =
+		gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR);
+	if (mysql) {
+		gda_connection_event_set_description
+			(event_error, mysql_error (mysql));
+		gda_connection_event_set_code
+			(event_error, mysql_errno (mysql));
+		g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_STATEMENT_EXEC_ERROR,
+			     mysql_sqlstate (mysql));
+	} else {
+		gda_connection_event_set_description
+			(event_error, _("No description"));
+		gda_connection_event_set_code
+			(event_error, -1);
+		g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_STATEMENT_EXEC_ERROR,
+			     _("No detail"));
+	}
+	gda_connection_event_set_code (event_error, -1);
+	gda_connection_event_set_source (event_error, "gda-mysql");
+
+	gda_connection_add_event (cnc, event_error);
+
+	return event_error;
+}
+
+/* /\* to be used only while initializing a connection *\/ */
+/* int */
+/* _gda_mysql_real_query_wrap (GdaConnection  *cnc, */
+/* 			    MYSQL          *mysql, */
+/* 			    const char     *query, */
+/* 			    unsigned long   length) */
+/* { */
+/* 	GdaConnectionEvent *event; */
+
+/*         if (cnc) { */
+/*                 event = gda_connection_event_new (GDA_CONNECTION_EVENT_COMMAND); */
+/*                 gda_connection_event_set_description (event, query); */
+/*                 gda_connection_add_event (cnc, event); */
+/*         } */
+
+/*         return mysql_real_query (mysql, query, length); */
+/* } */
+
+GType
+_gda_mysql_type_to_gda (MysqlConnectionData    *cdata,
+			enum enum_field_types   mysql_type)
+{
+	/* 	gint i; */
+
+	/* 	for (i = 0; i < cdata->ntypes; i++) */
+	/* 		if (cdata->type_data[i].oid == mysql_type) */
+	/* 			break; */
+
+	/*   	if (cdata->type_data[i].oid != mysql_type) */
+	/* 		return G_TYPE_STRING; */
+
+	/* 	return cdata->type_data[i].type; */
+	
+	GType gtype = 0;
+	switch (mysql_type) {
+	case MYSQL_TYPE_TINY:
+	case MYSQL_TYPE_SHORT:
+	case MYSQL_TYPE_LONG:
+	case MYSQL_TYPE_INT24:
+	case MYSQL_TYPE_YEAR:
+		gtype = G_TYPE_INT;
+		break;
+	case MYSQL_TYPE_LONGLONG:
+		gtype = G_TYPE_LONG;
+		break;
+	case MYSQL_TYPE_FLOAT:
+		gtype = G_TYPE_FLOAT;
+		break;
+	case MYSQL_TYPE_DECIMAL:
+	case MYSQL_TYPE_NEWDECIMAL:
+	case MYSQL_TYPE_DOUBLE:
+		gtype = G_TYPE_DOUBLE;
+		break;
+	case MYSQL_TYPE_BIT:
+	case MYSQL_TYPE_BLOB:
+		gtype = GDA_TYPE_BLOB;
+		break;
+	case MYSQL_TYPE_TIMESTAMP:
+	case MYSQL_TYPE_DATETIME:
+		gtype = GDA_TYPE_TIMESTAMP;
+		break;
+	case MYSQL_TYPE_DATE:
+		gtype = G_TYPE_DATE;
+		break;
+	case MYSQL_TYPE_TIME:
+		gtype = GDA_TYPE_TIME;
+		break;
+	case MYSQL_TYPE_NULL:
+		gtype = GDA_TYPE_NULL;
+		break;
+	case MYSQL_TYPE_STRING:
+	case MYSQL_TYPE_VAR_STRING:
+	case MYSQL_TYPE_SET:
+	case MYSQL_TYPE_ENUM:
+	case MYSQL_TYPE_GEOMETRY:
+	default:
+		gtype = G_TYPE_STRING;
+	}
+	return gtype;
+	
+}

Added: trunk/providers/mysql/gda-mysql-util.h
==============================================================================
--- (empty file)
+++ trunk/providers/mysql/gda-mysql-util.h	Sun Apr  6 17:06:43 2008
@@ -0,0 +1,50 @@
+/* GDA mysql provider
+ * Copyright (C) 1998 - 2008 The GNOME Foundation.
+ *
+ * AUTHORS:
+ *         Vivien Malerba <malerba gnome-db org>
+ *         Rodrigo Moya <rodrigo gnome-db org>
+ *         Gonzalo Paniagua Javier <gonzalo gnome-db org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __GDA_MYSQL_UTIL_H__
+#define __GDA_MYSQL_UTIL_H__
+
+#include "gda-mysql.h"
+
+G_BEGIN_DECLS
+
+GdaConnectionEvent *
+_gda_mysql_make_error               (GdaConnection  *cnc,
+				     MYSQL          *mysql,
+				     GError        **error);
+/* int */
+/* _gda_mysql_real_query_wrap          (GdaConnection  *cnc, */
+/* 				     MYSQL          *mysql, */
+/* 				     const char     *query, */
+/* 				     unsigned long   length); */
+/* int */
+/* _gda_mysql_get_connection_type_list (GdaConnection        *cnc, */
+/* 				     MysqlConnectionData  *cdata); */
+/* GType */
+/* _gda_mysql_type_oid_to_gda          (MysqlConnectionData    *cdata, */
+/* 				     enum enum_field_types   mysql_type); */
+
+G_END_DECLS
+
+#endif
+

Modified: trunk/providers/mysql/gda-mysql.h
==============================================================================
--- trunk/providers/mysql/gda-mysql.h	(original)
+++ trunk/providers/mysql/gda-mysql.h	Sun Apr  6 17:06:43 2008
@@ -1,10 +1,8 @@
-/* GDA MySQL provider
- * Copyright (C) 1998 - 2006 The GNOME Foundation.
+/* GDA mysql provider
+ * Copyright (C) 2008 The GNOME Foundation.
  *
  * AUTHORS:
- *      Michael Lausch <michael lausch at>
- *	Rodrigo Moya <rodrigo gnome-db org>
- *      Vivien Malerba <malerba gnome-db org>
+ *      Carlos Savoretti <csavoretti gmail com>
  *
  * This Library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public License as
@@ -25,40 +23,30 @@
 #ifndef __GDA_MYSQL_H__
 #define __GDA_MYSQL_H__
 
-#include <glib/gmacros.h>
-#include <libgda/gda-connection.h>
-#include <libgda/gda-server-provider.h>
-#include <glib/gi18n-lib.h>
-#include <libgda/gda-value.h>
-#include "gda-mysql-provider.h"
-
-#ifdef G_OS_WIN32
-#include <windows.h>
-#endif
+/*
+ * Provider name
+ */
+#define MYSQL_PROVIDER_NAME "Mysql"
 
+#include <libgda/libgda.h>
 #include <mysql.h>
-#include <mysql_com.h>
-
-/* undefine the macros defined by Libgda because MySQL exports them */
-#undef PACKAGE_BUGREPORT
-#undef PACKAGE_NAME
-#undef PACKAGE_STRING
-#undef PACKAGE_TARNAME
-#undef PACKAGE_VERSION
-#include <my_config.h>
-
-#define GDA_MYSQL_PROVIDER_ID          "GDA MySQL provider"
-
-G_BEGIN_DECLS
 
 /*
- * Utility functions
+ * Provider's specific connection data
  */
-
-GdaConnectionEvent     *gda_mysql_make_error    (MYSQL *handle);
-GType                   gda_mysql_type_to_gda   (enum enum_field_types mysql_type, gboolean is_unsigned);
-int                     gda_mysql_real_query_wrap (GdaConnection *cnc, MYSQL *mysql, 
-						   const char *stmt_str, unsigned long length);
-G_END_DECLS
+typedef struct {
+	/* TO_ADD: this structure holds any information necessary to specialize the GdaConnection, usually a connection
+	 * handle from the C or C++ API
+	 */
+	
+	GdaConnection    *cnc;
+	MYSQL            *mysql;
+	MYSQL_STMT       *mysql_stmt;
+
+	/* Backend version (to which we're connected). */
+	gchar            *version;
+	unsigned long     version_long;
+	
+} MysqlConnectionData;
 
 #endif

Added: trunk/providers/mysql/gen_def.c
==============================================================================
--- (empty file)
+++ trunk/providers/mysql/gen_def.c	Sun Apr  6 17:06:43 2008
@@ -0,0 +1,194 @@
+/* 
+ * Copyright (C) 2007 Vivien Malerba
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * This program generates tokens'ID transformation because the GdaSqlParser object uses 2 Lemon generated
+ * parsers at once, but with only one tokenizer (because each Lemon generated parser generates it own IDs for
+ * tokens).
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+#define MAX_SYMBOLS 500
+#define PARSER_HEADER "parser.h"
+#define FALSE 0
+#define TRUE (!FALSE)
+
+typedef struct {
+	char *key;
+	int   parser_value;
+} HashEntry;
+
+HashEntry entries[MAX_SYMBOLS];
+int nb_entries; /* must remain < MAX_SYMBOLS */
+
+typedef enum {
+	TYPE_IMPOSED,
+	TYPE_PARSER
+} SourceType;
+
+static void parse_contents (FILE *stream, SourceType type);
+static HashEntry *find_entry_for_token (char *token);
+int 
+main (int argc,char** argv)
+{
+	int i;
+	FILE *fd_imposed;
+	FILE *fd_parser;
+	HashEntry *illegal_entry;
+	HashEntry *rawstring_entry;
+
+	memset (entries, 0, sizeof (entries));
+	fd_imposed = fopen (IMPOSED_HEADER, "r");
+	if (!fd_imposed) {
+		printf ("Can't open '%s':%s\n", IMPOSED_HEADER, strerror (errno));
+		return 1;
+	}
+	fd_parser = fopen (PARSER_HEADER, "r");
+	if (!fd_parser) {
+		printf ("Can't open '%s':%s\n", PARSER_HEADER, strerror (errno));
+		return 1;
+	}
+
+	nb_entries = 0;
+	parse_contents (fd_imposed, TYPE_IMPOSED);
+	parse_contents (fd_parser, TYPE_PARSER);
+
+	fclose (fd_imposed);
+	fclose (fd_parser);
+
+	/* output notice */
+	printf ("/*\n * This file is generated by the gen_def program (see the gen_def.c file \n"
+		" * for some explanations)\n"
+		" * DO NOT EDIT MANUALLY\n */\n\n\n");
+
+	/* output */
+	for (i = 0; i < nb_entries; i++) {
+		HashEntry *entry = &(entries[i]);
+		printf ("#define L_%s \t\t %d\n", entry->key, i);
+	}
+	illegal_entry = find_entry_for_token ("ILLEGAL");
+	rawstring_entry = find_entry_for_token ("RAWSTRING");
+	printf ("gint mysql_parser_tokens[] = {\n");
+	for (i = 0; i < nb_entries; i++) {
+		HashEntry *entry = &(entries[i]);
+		if (i!= 0)
+			printf (",");
+		if (entry->parser_value >= 0)
+			printf ("%d", entry->parser_value);
+		else
+			printf ("%d", illegal_entry->parser_value);
+	}
+	printf ("};\n");
+
+	return 0;
+}
+
+static HashEntry *
+find_entry_for_token (char *token) 
+{
+	int i;
+
+	for (i = 0; i < nb_entries; i++) {
+		HashEntry *e = &(entries[i]);
+		if (!strcmp (e->key, token))
+			return e;
+	}
+	return NULL;
+}
+
+
+
+static void 
+parse_line (char *line, SourceType type) 
+{
+	char *z, *token;
+	int value;
+	HashEntry *entry;
+	
+	z = line;
+	if (strncmp (z, "#define ", 8)) {
+		printf ("Expected '#define', not found");
+		exit (1);
+	}
+	z += 8;
+	token = z + 2;
+	for (; *z && *z != ' '; z++);
+	*z = 0;
+	z++;
+	for (; *z == ' '; z++);
+	value = atoi (z);
+	/*printf ("%d Token: /%s/, value=%d\n", type, token, value);*/
+
+	entry = find_entry_for_token (token);
+	if (!entry) {
+		nb_entries++;
+		entry = &(entries[nb_entries - 1]);
+		entry->key = malloc (sizeof (char) * (strlen (token) + 1));
+		memcpy (entry->key, token, strlen (token) + 1);
+		entry->parser_value = -1;
+	}
+	if (type == TYPE_PARSER)
+		entry->parser_value = value;
+}
+
+static void
+parse_contents (FILE *stream, SourceType type)
+{
+#define BUFSIZE 500
+	char buffer[BUFSIZE];
+	int read;
+	char *end;
+
+	read = fread (buffer, 1, BUFSIZE, stream);
+	end = buffer + read;
+	while (read > 0) {
+		char *ptr;
+
+		/* read all complete lines in buffer */
+		while (end > buffer) {
+			char *hold = NULL;
+			for (ptr = buffer; (ptr < end) && *ptr && (*ptr != '\n'); ptr++);
+			if (ptr == end)
+				break;
+			if (*ptr)
+				hold = ptr+1;
+			*ptr = 0;
+
+			/* treat the line */
+			parse_line (buffer, type);
+
+			if (hold) {
+				int l = end - hold;
+				end -= hold - buffer;
+				memmove (buffer, hold, l);
+			}
+			else
+				break;
+		}
+
+		read = fread (end, 1, BUFSIZE - (end - buffer), stream);
+		end += read;
+	}
+}
+

Modified: trunk/providers/mysql/libgda-mysql-4.0.pc.in
==============================================================================
--- trunk/providers/mysql/libgda-mysql-4.0.pc.in	(original)
+++ trunk/providers/mysql/libgda-mysql-4.0.pc.in	Sun Apr  6 17:06:43 2008
@@ -3,7 +3,7 @@
 libdir= libdir@
 includedir= includedir@
 
-Name: libgda-mysql- GDA_ABI_MAJOR_VERSION@  GDA_ABI_MINOR_VERSION@
-Description: GDA (GNOME Data Access) MySQL provider
+Name: libgda-postgres- GDA_ABI_MAJOR_VERSION@  GDA_ABI_MINOR_VERSION@
+Description: GDA (GNOME Data Access) Mysql provider
 Requires: libgda- GDA_ABI_MAJOR_VERSION@  GDA_ABI_MINOR_VERSION@
 Version: @VERSION@

Modified: trunk/providers/mysql/libmain.c
==============================================================================
--- trunk/providers/mysql/libmain.c	(original)
+++ trunk/providers/mysql/libmain.c	Sun Apr  6 17:06:43 2008
@@ -1,10 +1,8 @@
-/* GDA MySQL Provider
- * Copyright (C) 1998 - 2007 The GNOME Foundation
+/* GDA Mysql Provider
+ * Copyright (C) 2008 The GNOME Foundation
  *
  * AUTHORS:
- * 	   Michael Lausch <michael lausch at>
- *         Rodrigo Moya <rodrigo gnome-db org>
- *         Vivien Malerba <malerba gnome-db org>
+ *      TO_ADD: your name and email
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -22,10 +20,10 @@
  */
 
 #include <glib/gi18n-lib.h>
-#include <libgda/gda-config.h>
-#include "gda-mysql-provider.h"
 #include <libgda/gda-server-provider-extra.h>
 #include <libgda/binreloc/gda-binreloc.h>
+#include "gda-mysql.h"
+#include "gda-mysql-provider.h"
 
 static gchar      *module_path = NULL;
 const gchar       *plugin_get_name (void);
@@ -36,20 +34,20 @@
 void
 plugin_init (const gchar *real_path)
 {
-	if (real_path)
-		module_path = g_strdup (real_path);
+        if (real_path)
+                module_path = g_strdup (real_path);
 }
 
 const gchar *
 plugin_get_name (void)
 {
-	return "MySQL";
+	return MYSQL_PROVIDER_NAME;
 }
 
 const gchar *
 plugin_get_description (void)
 {
-	return _("Provider for MySQL databases");
+	return _("Example provider for C API databases");
 }
 
 gchar *
@@ -68,7 +66,7 @@
 {
 	GdaServerProvider *prov;
 
-	prov = gda_mysql_provider_new ();
-	g_object_set_data ((GObject* ) prov, "GDA_PROVIDER_DIR", module_path);
-	return prov;
+	prov = (GdaServerProvider*) g_object_new (GDA_TYPE_MYSQL_PROVIDER, NULL);
+        g_object_set_data ((GObject *) prov, "GDA_PROVIDER_DIR", module_path);
+        return prov;
 }

Added: trunk/providers/mysql/parser.y
==============================================================================
--- (empty file)
+++ trunk/providers/mysql/parser.y	Sun Apr  6 17:06:43 2008
@@ -0,0 +1,1025 @@
+// All token codes are small integers with #defines that begin with "TK_"
+%token_prefix T_
+
+// The type of the data attached to each token is GValue.  This is also the
+// default type for non-terminals.
+//
+%token_type {GValue *}
+%default_type {GValue *}
+%token_destructor {if ($$) {
+		 gchar *str = gda_sql_value_stringify ($$);
+		 DEBUG ("token destructor /%s/", str);
+		 g_free (str);
+		 g_value_unset ($$); g_free ($$);}}
+
+// The generated parser function takes a 4th argument as follows:
+%extra_argument {GdaSqlParserIface *pdata}
+
+// This code runs whenever there is a syntax error
+//
+%syntax_error {
+	gda_sql_parser_set_syntax_error (pdata->parser);
+}
+%stack_overflow {
+	gda_sql_parser_set_overflow_error (pdata->parser);
+}
+
+// The name of the generated procedure that implements the parser
+// is as follows:
+%name gda_lemon_mysql_parser
+
+// The following text is included near the beginning of the C source
+// code file that implements the parser.
+//
+%include {
+#include <string.h>
+#include <glib.h>
+#include <glib-object.h>
+#include <glib/gi18n-lib.h>
+#include <libgda/sql-parser/gda-sql-parser-private.h>
+#include <libgda/sql-parser/gda-statement-struct-util.h>
+#include <libgda/sql-parser/gda-statement-struct-trans.h>
+#include <libgda/sql-parser/gda-statement-struct-insert.h>
+#include <libgda/sql-parser/gda-statement-struct-update.h>
+#include <libgda/sql-parser/gda-statement-struct-delete.h>
+#include <libgda/sql-parser/gda-statement-struct-select.h>
+#include <libgda/sql-parser/gda-statement-struct-compound.h>
+#include <libgda/sql-parser/gda-statement-struct-parts.h>
+#include <assert.h>
+
+#ifdef GDA_DEBUG_NO
+#define DEBUG(format, ...) g_print ("___" format "\n", __VA_ARGS__)
+#else
+#define DEBUG(format, ...)
+#endif
+
+typedef struct {
+	GValue *fname;
+	GdaSqlExpr *expr;
+} UpdateSet;
+
+typedef struct {
+	gboolean    distinct;
+	GdaSqlExpr *expr;
+} Distinct;
+
+typedef struct {
+	GdaSqlExpr *count;
+	GdaSqlExpr *offset;
+} Limit;
+
+typedef struct {
+	GSList *when_list;
+	GSList *then_list;
+} CaseBody;
+
+static GdaSqlOperator
+sql_operation_string_to_operator (const gchar *op)
+{
+	switch (g_ascii_toupper (*op)) {
+	case 'A':
+		return GDA_SQL_OPERATOR_AND;
+	case 'O':
+		return GDA_SQL_OPERATOR_OR;
+	case 'N':
+		return GDA_SQL_OPERATOR_NOT;
+	case '=':
+		return GDA_SQL_OPERATOR_EQ;
+	case 'I':
+		if (op[1] == 'S')
+			return GDA_SQL_OPERATOR_IS;
+		else if (op[1] == 'N')
+			return GDA_SQL_OPERATOR_IN;
+		break;
+	case 'L':
+		return GDA_SQL_OPERATOR_LIKE;
+	case 'B':
+		return GDA_SQL_OPERATOR_BETWEEN;
+	case '>':
+		if (op[1] == '=')
+			return GDA_SQL_OPERATOR_GEQ;
+		else if (op[1] == 0)
+			return GDA_SQL_OPERATOR_GT;
+		break;
+	case '<':
+		if (op[1] == '=')
+			return GDA_SQL_OPERATOR_LEQ;
+		else if (op[1] == 0)
+			return GDA_SQL_OPERATOR_LT;
+		break;
+	case '!':
+		if (op[1] == '=')
+			return GDA_SQL_OPERATOR_DIFF;
+		else if (op[1] == '~') {
+			if (op[2] == 0)
+				return GDA_SQL_OPERATOR_NOT_REGEXP;
+			else if (op[2] == '*')
+				return GDA_SQL_OPERATOR_NOT_REGEXP_CI;
+		}
+		break;
+	case '~':
+		if (op[1] == '*')
+			return GDA_SQL_OPERATOR_REGEXP_CI;
+		else if (op[1] == 0)
+			return GDA_SQL_OPERATOR_REGEXP;
+		break;
+	case 'S':
+		return GDA_SQL_OPERATOR_SIMILAR;
+	case '|':
+		if (op[1] == '|')
+			return GDA_SQL_OPERATOR_CONCAT;
+		else
+			return GDA_SQL_OPERATOR_BITOR;
+	case '+':
+		return GDA_SQL_OPERATOR_PLUS;
+	case '-':
+		return GDA_SQL_OPERATOR_MINUS;
+	case '*':
+		return GDA_SQL_OPERATOR_STAR;
+	case '/':
+		return GDA_SQL_OPERATOR_DIV;
+	case '%':
+		return GDA_SQL_OPERATOR_REM;
+	case '&':
+		return GDA_SQL_OPERATOR_BITAND;
+	}
+	g_error ("Unhandled operator named '%s'\n", op);
+	return 0;
+}
+
+static GdaSqlOperator
+string_to_op_type (GValue *value)
+{
+	GdaSqlOperator op;
+	op = sql_operation_string_to_operator (g_value_get_string (value));
+	g_value_reset (value);
+	g_free (value);
+	return op;
+}
+
+static GdaSqlExpr *
+compose_multiple_expr (GdaSqlOperator op, GdaSqlExpr *left, GdaSqlExpr *right) {
+	GdaSqlExpr *ret;
+	if (left->cond && (left->cond->operator == op)) {
+		ret = left;
+		ret->cond->operands = g_slist_append (ret->cond->operands, right);
+	}
+	else {
+		GdaSqlOperation *cond;
+		ret = gda_sql_expr_new (NULL);
+		cond = gda_sql_operation_new (GDA_SQL_ANY_PART (ret));
+		ret->cond = cond;
+		cond->operator = op;
+		cond->operands = g_slist_prepend (NULL, right);
+		GDA_SQL_ANY_PART (right)->parent = GDA_SQL_ANY_PART (cond);
+		cond->operands = g_slist_prepend (cond->operands, left);
+		GDA_SQL_ANY_PART (left)->parent = GDA_SQL_ANY_PART (cond);
+	}
+	return ret;
+}
+
+static GdaSqlExpr *
+create_two_expr (GdaSqlOperator op, GdaSqlExpr *left, GdaSqlExpr *right) {
+	GdaSqlExpr *ret;
+	GdaSqlOperation *cond;
+	ret = gda_sql_expr_new (NULL);
+	cond = gda_sql_operation_new (GDA_SQL_ANY_PART (ret));
+	ret->cond = cond;
+	cond->operator = op;
+	cond->operands = g_slist_prepend (NULL, right);
+	GDA_SQL_ANY_PART (right)->parent = GDA_SQL_ANY_PART (cond);
+	cond->operands = g_slist_prepend (cond->operands, left);
+	GDA_SQL_ANY_PART (left)->parent = GDA_SQL_ANY_PART (cond);
+	return ret;
+}
+
+static GdaSqlExpr *
+create_uni_expr (GdaSqlOperator op, GdaSqlExpr *expr) {
+	GdaSqlExpr *ret;
+	GdaSqlOperation *cond;
+	ret = gda_sql_expr_new (NULL);
+	cond = gda_sql_operation_new (GDA_SQL_ANY_PART (ret));
+	ret->cond = cond;
+	cond->operator = op;
+	cond->operands = g_slist_prepend (NULL, expr);
+	GDA_SQL_ANY_PART (expr)->parent = GDA_SQL_ANY_PART (cond);
+	return ret;
+}
+
+static GdaSqlStatement *
+compose_multiple_compounds (GdaSqlStatementCompoundType ctype, GdaSqlStatement *left, GdaSqlStatement *right) {
+	GdaSqlStatement *ret;
+	GdaSqlStatementCompound *lc = (GdaSqlStatementCompound*) left->contents;
+	if (lc->compound_type == ctype) {
+		GdaSqlStatementCompound *rc = (GdaSqlStatementCompound*) right->contents;
+		if (!rc->stmt_list->next || rc->compound_type == ctype) {
+			GSList *list;
+			for (list = rc->stmt_list; list; list = list->next)
+				GDA_SQL_ANY_PART (((GdaSqlStatement*)list->data)->contents)->parent = GDA_SQL_ANY_PART (lc);
+
+			ret = left;
+			lc->stmt_list = g_slist_concat (lc->stmt_list, rc->stmt_list);
+			rc->stmt_list = NULL;
+			gda_sql_statement_free (right);
+		}
+	}
+	else {
+		ret = gda_sql_statement_new (GDA_SQL_STATEMENT_COMPOUND);
+		gda_sql_statement_compound_set_type (ret, ctype);
+		gda_sql_statement_compound_take_stmt (ret, left);
+		gda_sql_statement_compound_take_stmt (ret, right);
+	}
+	return ret;
+}
+
+}
+
+// The following directive causes tokens ABORT, AFTER, ASC, etc. to
+// fallback to ID if they will not parse as their original value.
+%fallback ID
+  ABORT AFTER ANALYZE ASC ATTACH BEFORE BEGIN CASCADE CAST CONFLICT
+  DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR
+  IGNORE IMMEDIATE INITIALLY INSTEAD LIKE MATCH PLAN
+  QUERY KEY OF OFFSET PRAGMA RAISE REPLACE RESTRICT ROW
+  TEMP TRIGGER VACUUM VIEW VIRTUAL
+  REINDEX RENAME CTIME_KW IF
+  DELIMITER COMMIT ROLLBACK ISOLATION LEVEL SERIALIZABLE READ COMMITTED 
+  UNCOMMITTED REPEATABLE WRITE ONLY SAVEPOINT RELEASE COMMENT FORCE WAIT NOWAIT BATCH.
+
+// Define operator precedence early so that this is the first occurance
+// of the operator tokens in the grammer.  Keeping the operators together
+// causes them to be assigned integer values that are close together,
+// which keeps parser tables smaller.
+%left OR.
+%left AND.
+%right NOT.
+%left IS MATCH LIKE IN ISNULL NOTNULL DIFF EQ.
+%left BETWEEN.
+%left GT LEQ LT GEQ.
+%left REGEXP REGEXP_CI NOT_REGEXP NOT_REGEXP_CI.
+%left SIMILAR.
+%right ESCAPE.
+%left BITAND BITOR LSHIFT RSHIFT.
+%left PLUS MINUS.
+%left STAR SLASH REM.
+%left CONCAT.
+%left COLLATE.
+%right UMINUS UPLUS BITNOT.
+%left LP RP.
+%left JOIN INNER NATURAL LEFT RIGHT FULL CROSS.
+%left UNION EXCEPT.
+%left INTERSECT.
+%left PGCAST.
+
+// force the declaration of the ILLEGAL and SQLCOMMENT tokens
+%nonassoc ILLEGAL.
+%nonassoc SQLCOMMENT.
+
+// Input is a single SQL command
+%type stmt {GdaSqlStatement *}
+%destructor stmt {g_print ("Statement destroyed by parser: %p\n", $$); gda_sql_statement_free ($$);}
+stmt ::= cmd(C) eos. {pdata->parsed_statement = C;}
+stmt ::= compound(C) eos. {
+	GdaSqlStatementCompound *scompound = (GdaSqlStatementCompound *) C->contents;
+	if (scompound->stmt_list->next)
+		/* real compound (multiple statements) */
+		pdata->parsed_statement = C;
+	else {
+		/* false compound (only 1 select) */
+		pdata->parsed_statement = (GdaSqlStatement*) scompound->stmt_list->data;
+		GDA_SQL_ANY_PART (pdata->parsed_statement->contents)->parent = NULL;
+		g_slist_free (scompound->stmt_list);
+		scompound->stmt_list = NULL;
+		gda_sql_statement_free (C);
+	}
+}
+cmd(C) ::= LP cmd(E) RP. {C = E;}
+compound(C) ::= LP compound(E) RP. {C = E;}
+
+eos ::= SEMI.
+eos ::= END_OF_FILE.
+
+%type cmd {GdaSqlStatement *}
+%destructor cmd {gda_sql_statement_free ($$);}
+
+//
+// Transactions
+//
+cmd(C) ::= BEGIN. {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);}
+cmd(C) ::= BEGIN TRANSACTION nm_opt(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+					 gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= BEGIN transtype(Y) TRANSACTION nm_opt(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+						      gda_sql_statement_trans_take_mode (C, Y);
+						      gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= BEGIN transtype(Y) nm_opt(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+					  gda_sql_statement_trans_take_mode (C, Y);
+					  gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= BEGIN transilev(L). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+				gda_sql_statement_trans_set_isol_level (C, L);
+}
+
+cmd(C) ::= BEGIN TRANSACTION transilev(L). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+					    gda_sql_statement_trans_set_isol_level (C, L);
+}
+
+cmd(C) ::= BEGIN TRANSACTION transtype(Y). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+					    gda_sql_statement_trans_take_mode (C, Y);
+}
+
+cmd(C) ::= BEGIN TRANSACTION transtype(Y) opt_comma transilev(L). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+								   gda_sql_statement_trans_take_mode (C, Y);
+								   gda_sql_statement_trans_set_isol_level (C, L);
+}
+
+cmd(C) ::= BEGIN TRANSACTION transilev(L) opt_comma transtype(Y). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+								   gda_sql_statement_trans_take_mode (C, Y);
+								   gda_sql_statement_trans_set_isol_level (C, L);
+}
+
+cmd(C) ::= BEGIN transtype(Y) opt_comma transilev(L). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+						       gda_sql_statement_trans_take_mode (C, Y);
+						       gda_sql_statement_trans_set_isol_level (C, L);
+}
+	
+cmd(C) ::= BEGIN transilev(L) opt_comma transtype(Y). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+						       gda_sql_statement_trans_take_mode (C, Y);
+						       gda_sql_statement_trans_set_isol_level (C, L);
+}
+
+cmd(C) ::= END trans_opt_kw nm_opt(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);
+					gda_sql_statement_trans_take_name (C, R);
+}
+	
+cmd(C) ::= COMMIT nm_opt(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);
+			      gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= COMMIT TRANSACTION nm_opt(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);
+					  gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= COMMIT FORCE STRING. {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);}
+cmd(C) ::= COMMIT FORCE STRING COMMA INTEGER. {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);}
+cmd(C) ::= COMMIT COMMENT STRING. {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);}
+cmd(C) ::= COMMIT COMMENT STRING ora_commit_write. {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);}
+cmd(C) ::= COMMIT ora_commit_write. {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);}
+
+cmd(C) ::= ROLLBACK trans_opt_kw nm_opt(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_ROLLBACK);
+					     gda_sql_statement_trans_take_name (C, R);
+}
+
+ora_commit_write ::= WRITE IMMEDIATE.
+ora_commit_write ::= WRITE BATCH.
+ora_commit_write ::= WRITE WAIT.
+ora_commit_write ::= WRITE NOWAIT.
+ora_commit_write ::= WRITE IMMEDIATE WAIT.
+ora_commit_write ::= WRITE IMMEDIATE NOWAIT.
+ora_commit_write ::= WRITE BATCH WAIT.
+ora_commit_write ::= WRITE BATCH NOWAIT.
+
+trans_opt_kw ::= .
+trans_opt_kw ::= TRANSACTION.
+
+opt_comma ::= .
+opt_comma ::= COMMA.
+
+%type transilev {GdaTransactionIsolation}
+transilev(L) ::= ISOLATION LEVEL SERIALIZABLE. {L = GDA_TRANSACTION_ISOLATION_SERIALIZABLE;}
+transilev(L) ::= ISOLATION LEVEL REPEATABLE READ. {L = GDA_TRANSACTION_ISOLATION_REPEATABLE_READ;}
+transilev(L) ::= ISOLATION LEVEL READ COMMITTED. {L = GDA_TRANSACTION_ISOLATION_READ_COMMITTED;}
+transilev(L) ::= ISOLATION LEVEL READ UNCOMMITTED. {L = GDA_TRANSACTION_ISOLATION_READ_UNCOMMITTED;}
+
+nm_opt(R) ::= . {R = NULL;}
+nm_opt(R) ::= nm(N). {R = N;}
+
+transtype(A) ::= DEFERRED(X).  {A = X;}
+transtype(A) ::= IMMEDIATE(X). {A = X;}
+transtype(A) ::= EXCLUSIVE(X). {A = X;}
+transtype(A) ::= READ WRITE. {A = g_new0 (GValue, 1);
+			      g_value_init (A, G_TYPE_STRING);
+			      g_value_set_string (A, "READ_WRITE");
+}
+transtype(A) ::= READ ONLY. {A = g_new0 (GValue, 1);
+			     g_value_init (A, G_TYPE_STRING);
+			     g_value_set_string (A, "READ_ONLY");
+}
+
+//
+// Savepoints
+//
+cmd(C) ::= SAVEPOINT nm(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_SAVEPOINT);
+				    gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= RELEASE SAVEPOINT nm(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_DELETE_SAVEPOINT);
+				     gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= RELEASE nm(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_DELETE_SAVEPOINT);
+			   gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= ROLLBACK trans_opt_kw TO nm(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_ROLLBACK_SAVEPOINT);
+					    gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= ROLLBACK trans_opt_kw TO SAVEPOINT nm(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_ROLLBACK_SAVEPOINT);
+						      gda_sql_statement_trans_take_name (C, R);
+}
+
+//
+// INSERT
+//
+cmd(C) ::= INSERT opt_on_conflict(O) INTO fullname(X) inscollist_opt(F) VALUES LP exprlist(Y) RP. {
+	C = gda_sql_statement_new (GDA_SQL_STATEMENT_INSERT);
+	gda_sql_statement_insert_take_table_name (C, X);
+	gda_sql_statement_insert_take_fields_list (C, F);
+	gda_sql_statement_insert_take_1_values_list (C, Y);
+	gda_sql_statement_insert_take_on_conflict (C, O);
+}
+
+cmd(C) ::= INSERT opt_on_conflict(O) INTO fullname(X) inscollist_opt(F) VALUES LP exprlist(Y) RP ins_extra_values(E). {
+	C = gda_sql_statement_new (GDA_SQL_STATEMENT_INSERT);
+	gda_sql_statement_insert_take_table_name (C, X);
+	gda_sql_statement_insert_take_fields_list (C, F);
+	gda_sql_statement_insert_take_1_values_list (C, Y);
+	gda_sql_statement_insert_take_extra_values_list (C, E);
+	gda_sql_statement_insert_take_on_conflict (C, O);
+}
+
+cmd(C) ::= INSERT opt_on_conflict(O) INTO fullname(X) inscollist_opt(F) compound(S). {
+        C = gda_sql_statement_new (GDA_SQL_STATEMENT_INSERT);
+        gda_sql_statement_insert_take_table_name (C, X);
+        gda_sql_statement_insert_take_fields_list (C, F);
+        gda_sql_statement_insert_take_select (C, S);
+        gda_sql_statement_insert_take_on_conflict (C, O);
+}
+
+
+opt_on_conflict(O) ::= . {O = NULL;}
+opt_on_conflict(O) ::= OR ID(V). {O = V;}
+
+%type ins_extra_values {GSList*}
+%destructor ins_extra_values {GSList *list;
+		for (list = $$; list; list = list->next) {
+			g_slist_foreach ((GSList*) list->data, (GFunc) gda_sql_field_free, NULL); 
+			g_slist_free ((GSList*) list->data);
+		}
+		g_slist_free ($$);
+}
+ins_extra_values(E) ::= ins_extra_values(A) COMMA LP exprlist(L) RP. {E = g_slist_append (A, L);}
+ins_extra_values(E) ::= COMMA LP exprlist(L) RP. {E = g_slist_append (NULL, L);}
+
+%type inscollist_opt {GSList*}
+%destructor inscollist_opt {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_field_free, NULL); g_slist_free ($$);}}
+inscollist_opt(A) ::= .                       {A = NULL;}
+inscollist_opt(A) ::= LP inscollist(X) RP.    {A = X;}
+
+%type inscollist {GSList*}
+%destructor inscollist {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_field_free, NULL); g_slist_free ($$);}}
+inscollist(A) ::= inscollist(X) COMMA fullname(Y). {GdaSqlField *field;
+						    field = gda_sql_field_new (NULL);
+						    gda_sql_field_take_name (field, Y);
+						    A = g_slist_append (X, field);
+}
+inscollist(A) ::= fullname(Y). {GdaSqlField *field = gda_sql_field_new (NULL);
+				gda_sql_field_take_name (field, Y);
+				A = g_slist_prepend (NULL, field);
+}
+
+// DELETE
+cmd(C) ::= DELETE FROM fullname(T) where_opt(X). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_DELETE); 
+						  gda_sql_statement_delete_take_table_name (C, T);
+						  gda_sql_statement_delete_take_condition (C, X);}
+
+%type where_opt {GdaSqlExpr *}
+%destructor where_opt {gda_sql_expr_free ($$);}
+where_opt(A) ::= .                    {A = NULL;}
+where_opt(A) ::= WHERE expr(X).       {A = X;}
+
+// UPDATE
+cmd(C) ::= UPDATE opt_on_conflict(O) fullname(T) SET setlist(S) where_opt(X). {
+	GSList *list;
+	C = gda_sql_statement_new (GDA_SQL_STATEMENT_UPDATE);
+	gda_sql_statement_update_take_table_name (C, T);
+	gda_sql_statement_update_take_on_conflict (C, O);
+	gda_sql_statement_update_take_condition (C, X);
+	for (list = S; list; list = list->next) {
+		UpdateSet *set = (UpdateSet*) list->data;
+		gda_sql_statement_update_take_set_value (C, set->fname, set->expr);
+		g_free (set);
+	}
+	g_slist_free (S);
+}
+
+%type setlist {GSList*}
+%destructor setlist {GSList *list;
+	for (list = $$; list; list = list->next) {
+		UpdateSet *set = (UpdateSet*) list->data;
+		g_value_reset (set->fname); g_free (set->fname);
+		gda_sql_expr_free (set->expr);
+		g_free (set);
+	}
+	g_slist_free ($$);
+}
+setlist(A) ::= setlist(Z) COMMA fullname(X) EQ expr(Y). {UpdateSet *set;
+							 set = g_new (UpdateSet, 1);
+							 set->fname = X;
+							 set->expr = Y;
+							 A = g_slist_append (Z, set);
+}
+setlist(A) ::= fullname(X) EQ expr(Y). {UpdateSet *set;
+					set = g_new (UpdateSet, 1);
+					set->fname = X;
+					set->expr = Y;
+					A = g_slist_append (NULL, set);
+}
+
+// COMPOUND SELECT
+%type compound {GdaSqlStatement *}
+%destructor compound {gda_sql_statement_free ($$);}
+//compound(C) ::= LP compound(E) RP. {C = E;}
+compound(C) ::= selectcmd(S). {
+	C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMPOUND);
+	gda_sql_statement_compound_take_stmt (C, S);
+}
+compound(C) ::= compound(L) UNION opt_compound_all(A) compound(R). {
+	C = compose_multiple_compounds (A ? GDA_SQL_STATEMENT_COMPOUND_UNION_ALL : GDA_SQL_STATEMENT_COMPOUND_UNION,
+					L, R);
+}
+
+compound(C) ::= compound(L) EXCEPT opt_compound_all(A) compound(R). {
+	C = compose_multiple_compounds (A ? GDA_SQL_STATEMENT_COMPOUND_EXCEPT_ALL : GDA_SQL_STATEMENT_COMPOUND_EXCEPT,
+					L, R);
+} 
+
+compound(C) ::= compound(L) INTERSECT opt_compound_all(A) compound(R). {
+	C = compose_multiple_compounds (A ? GDA_SQL_STATEMENT_COMPOUND_INTERSECT_ALL : GDA_SQL_STATEMENT_COMPOUND_INTERSECT,
+					L, R);
+} 
+
+%type opt_compound_all {gboolean}
+opt_compound_all(A) ::= .    {A = FALSE;}
+opt_compound_all(A) ::= ALL. {A = TRUE;}
+
+
+// SELECT
+%type selectcmd {GdaSqlStatement *}
+%destructor selectcmd {gda_sql_statement_free ($$);}
+selectcmd(C) ::= SELECT distinct(D) selcollist(W) from(F) where_opt(Y)
+	 groupby_opt(P) having_opt(Q) orderby_opt(Z) limit_opt(L). {
+	C = gda_sql_statement_new (GDA_SQL_STATEMENT_SELECT);
+	if (D) {
+		gda_sql_statement_select_take_distinct (C, D->distinct, D->expr);
+		g_free (D);
+	}
+	gda_sql_statement_select_take_expr_list (C, W);
+	gda_sql_statement_select_take_from (C, F);
+	gda_sql_statement_select_take_where_cond (C, Y);
+	gda_sql_statement_select_take_group_by (C, P);
+	gda_sql_statement_select_take_having_cond (C, Q);
+	gda_sql_statement_select_take_order_by (C, Z);
+	gda_sql_statement_select_take_limits (C, L.count, L.offset);
+}
+
+%type limit_opt {Limit}
+%destructor limit_opt {gda_sql_expr_free ($$.count); gda_sql_expr_free ($$.offset);}
+limit_opt(A) ::= .                     {A.count = NULL; A.offset = NULL;}
+limit_opt(A) ::= LIMIT expr(X).        {A.count = X; A.offset = NULL;}
+limit_opt(A) ::= LIMIT expr(X) OFFSET expr(Y). {A.count = X; A.offset = Y;}
+limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y). {A.count = X; A.offset = Y;}
+
+%type orderby_opt {GSList *}
+%destructor orderby_opt {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_select_order_free, NULL); g_slist_free ($$);}}
+orderby_opt(A) ::= .                          {A = 0;}
+orderby_opt(A) ::= ORDER BY sortlist(X).      {A = X;}
+
+%type sortlist {GSList *}
+%destructor sortlist {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_select_order_free, NULL); g_slist_free ($$);}}
+sortlist(A) ::= sortlist(X) COMMA expr(Y) sortorder(Z). {GdaSqlSelectOrder *order;
+							 order = gda_sql_select_order_new (NULL);
+							 order->expr = Y;
+							 order->asc = Z;
+							 A = g_slist_append (X, order);
+}
+sortlist(A) ::= expr(Y) sortorder(Z). {GdaSqlSelectOrder *order;
+				       order = gda_sql_select_order_new (NULL);
+				       order->expr = Y;
+				       order->asc = Z;
+				       A = g_slist_prepend (NULL, order);
+}
+
+%type sortorder {gboolean}
+sortorder(A) ::= ASC.           {A = TRUE;}
+sortorder(A) ::= DESC.          {A = FALSE;}
+sortorder(A) ::= .              {A = TRUE;}
+
+
+%type having_opt {GdaSqlExpr *}
+%destructor having_opt {gda_sql_expr_free ($$);}
+having_opt(A) ::= .                     {A = NULL;}
+having_opt(A) ::= HAVING expr(X).       {A = X;}
+
+%type groupby_opt {GSList*}
+%destructor groupby_opt {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_expr_free, NULL); g_slist_free ($$);}}
+groupby_opt(A) ::= .                      {A = 0;}
+groupby_opt(A) ::= GROUP BY nexprlist(X). {A = X;}
+
+%type from {GdaSqlSelectFrom *}
+%destructor from {gda_sql_select_from_free ($$);}
+from(F) ::= .                   {F = NULL;}
+from(F) ::= FROM seltablist(X). {F = X;}
+
+%type seltablist {GdaSqlSelectFrom *}
+%destructor seltablist {gda_sql_select_from_free ($$);}
+%type stl_prefix {GdaSqlSelectFrom *}
+%destructor stl_prefix {gda_sql_select_from_free ($$);}
+
+seltablist(L) ::= stl_prefix(P) seltarget(T) on_cond(C) using_opt(U). {
+	GSList *last;
+	if (P)
+		L = P;
+	else 
+		L = gda_sql_select_from_new (NULL);
+	gda_sql_select_from_take_new_target (L, T);
+	last = g_slist_last (L->joins);
+	if (last) {
+		GdaSqlSelectJoin *join = (GdaSqlSelectJoin *) (last->data);
+		join->expr = C;
+		join->position = g_slist_length (L->targets) - 1;
+		join->using = U;
+	}
+}
+
+%type using_opt {GSList*}
+%destructor using_opt {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_field_free, NULL); g_slist_free ($$);}}
+using_opt(U) ::= USING LP inscollist(L) RP. {U = L;}
+using_opt(U) ::= .                          {U = NULL;}
+
+stl_prefix(P) ::= . {P = NULL;}
+stl_prefix(P) ::= seltablist(L) jointype(J). {GdaSqlSelectJoin *join;
+					      P = L;
+					      join = gda_sql_select_join_new (GDA_SQL_ANY_PART (P));
+					      join->type = J;
+					      gda_sql_select_from_take_new_join (P, join);
+}
+					      
+
+%type on_cond {GdaSqlExpr *}
+%destructor on_cond {gda_sql_expr_free ($$);}
+on_cond(N) ::= ON expr(E).  {N = E;}
+on_cond(N) ::= .            {N = NULL;}
+
+%type jointype {GdaSqlSelectJoinType}
+jointype(J) ::= COMMA. {J = GDA_SQL_SELECT_JOIN_CROSS;}
+jointype(J) ::= JOIN. {J = GDA_SQL_SELECT_JOIN_INNER;}
+jointype(J) ::= CROSS JOIN. {J = GDA_SQL_SELECT_JOIN_CROSS;}
+jointype(J) ::= INNER JOIN. {J = GDA_SQL_SELECT_JOIN_INNER;}
+jointype(J) ::= NATURAL JOIN. {J = GDA_SQL_SELECT_JOIN_NATURAL;}
+jointype(J) ::= LEFT JOIN. {J = GDA_SQL_SELECT_JOIN_LEFT;}
+jointype(J) ::= LEFT OUTER JOIN. {J = GDA_SQL_SELECT_JOIN_LEFT;}
+jointype(J) ::= RIGHT JOIN. {J = GDA_SQL_SELECT_JOIN_RIGHT;}
+jointype(J) ::= RIGHT OUTER JOIN. {J = GDA_SQL_SELECT_JOIN_RIGHT;}
+jointype(J) ::= FULL JOIN. {J = GDA_SQL_SELECT_JOIN_FULL;}
+jointype(J) ::= FULL OUTER JOIN. {J = GDA_SQL_SELECT_JOIN_FULL;}
+
+
+%type seltarget {GdaSqlSelectTarget *}
+%destructor seltarget {gda_sql_select_target_free ($$);}
+seltarget(T) ::= fullname(F) as(A). {T = gda_sql_select_target_new (NULL);
+				     gda_sql_select_target_take_alias (T, A);
+				     gda_sql_select_target_take_table_name (T, F);
+}
+seltarget(T) ::= fullname(F) ID(A). {T = gda_sql_select_target_new (NULL);
+                                     gda_sql_select_target_take_alias (T, A);
+                                     gda_sql_select_target_take_table_name (T, F);
+}
+seltarget(T) ::= LP compound(S) RP as(A). {T = gda_sql_select_target_new (NULL);
+					     gda_sql_select_target_take_alias (T, A);
+					     gda_sql_select_target_take_select (T, S);
+}
+
+%type selcollist {GSList *}
+%destructor selcollist {g_slist_foreach ($$, (GFunc) gda_sql_select_field_free, NULL); g_slist_free ($$);}
+
+%type sclp {GSList *}
+%destructor sclp {g_slist_foreach ($$, (GFunc) gda_sql_select_field_free, NULL); g_slist_free ($$);}
+sclp(A) ::= selcollist(X) COMMA.             {A = X;}
+sclp(A) ::= .                                {A = NULL;}
+
+selcollist(L) ::= sclp(E) expr(X) as(A). {GdaSqlSelectField *field;
+					  field = gda_sql_select_field_new (NULL);
+					  gda_sql_select_field_take_expr (field, X);
+					  gda_sql_select_field_take_alias (field, A); 
+					  L = g_slist_append (E, field);}
+selcollist(L) ::= sclp(E) starname(X). {GdaSqlSelectField *field;
+					field = gda_sql_select_field_new (NULL);
+					gda_sql_select_field_take_star_value (field, X);
+					L = g_slist_append (E, field);}
+
+starname(S) ::= STAR(X). {S = X;}
+starname(A) ::= nm(S) DOT STAR(X). {gchar *str;
+				  str = g_strdup_printf ("%s.%s", g_value_get_string (S), g_value_get_string (X));
+				  A = g_new0 (GValue, 1);
+				  g_value_init (A, G_TYPE_STRING);
+				  g_value_take_string (A, str);
+				  g_value_reset (S); g_free (S);
+				  g_value_reset (X); g_free (X);
+}
+
+starname(A) ::= nm(C) DOT nm(S) DOT STAR(X). {gchar *str;
+				  str = g_strdup_printf ("%s.%s.%s", g_value_get_string (C), 
+							 g_value_get_string (S), g_value_get_string (X));
+				  A = g_new0 (GValue, 1);
+				  g_value_init (A, G_TYPE_STRING);
+				  g_value_take_string (A, str);
+				  g_value_reset (C); g_free (C);
+				  g_value_reset (S); g_free (S);
+				  g_value_reset (X); g_free (X);
+}
+
+as(A) ::= AS fullname(F). {A = F;}
+as(A) ::= AS value(F). {A = F;}
+as(A) ::= . {A = NULL;}
+
+%type distinct {Distinct *}
+%destructor distinct {if ($$) {if ($$->expr) gda_sql_expr_free ($$->expr); g_free ($$);}}
+distinct(E) ::= . {E = NULL;}
+distinct(E) ::= ALL. {E = NULL;}
+distinct(E) ::= DISTINCT. {E = g_new0 (Distinct, 1); E->distinct = TRUE;}
+distinct(E) ::= DISTINCT ON expr(X). [OR] {E = g_new0 (Distinct, 1); E->distinct = TRUE; E->expr = X;}
+
+// Non empty list of expressions
+%type nexprlist {GSList *}
+%destructor nexprlist {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_expr_free, NULL); g_slist_free ($$);}}
+nexprlist(L) ::= nexprlist(E) COMMA expr(X). {L = g_slist_append (E, X);}
+nexprlist(L) ::= expr(E). {L = g_slist_append (NULL, E);}
+
+// List of expressions
+%type exprlist {GSList *}
+%destructor exprlist {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_expr_free, NULL); g_slist_free ($$);}}
+exprlist(L) ::= . {L = NULL;}
+exprlist(L) ::= exprlist(E) COMMA expr(X). {L = g_slist_append (E, X);}
+exprlist(L) ::= expr(E). {L = g_slist_append (NULL, E);}
+
+// A single expression
+%type expr {GdaSqlExpr *}
+%destructor expr {gda_sql_expr_free ($$);}
+expr(E) ::= pvalue(V). {E = V;}
+expr(E) ::= value(V). {E = gda_sql_expr_new (NULL); E->value = V;}
+expr(E) ::= LP expr(X) RP. {E = X;}
+expr(E) ::= fullname(V). {E = gda_sql_expr_new (NULL); E->value = V;}
+expr(E) ::= fullname(V) LP exprlist(A) RP. {GdaSqlFunction *func;
+					    E = gda_sql_expr_new (NULL); 
+					    func = gda_sql_function_new (GDA_SQL_ANY_PART (E)); 
+					    gda_sql_function_take_name (func, V);
+					    gda_sql_function_take_args_list (func, A);
+					    E->func = func;}
+expr(E) ::= fullname(V) LP compound(S) RP. {GdaSqlFunction *func;
+					     GdaSqlExpr *expr;
+					     E = gda_sql_expr_new (NULL); 
+					     func = gda_sql_function_new (GDA_SQL_ANY_PART (E)); 
+					     gda_sql_function_take_name (func, V);
+					     expr = gda_sql_expr_new (GDA_SQL_ANY_PART (func)); 
+					     gda_sql_expr_take_select (expr, S);
+					     gda_sql_function_take_args_list (func, g_slist_prepend (NULL, expr));
+					     E->func = func;}
+expr(E) ::= fullname(V) LP starname(A) RP. {GdaSqlFunction *func;
+					    GdaSqlExpr *expr;
+					    E = gda_sql_expr_new (NULL); 
+					    func = gda_sql_function_new (GDA_SQL_ANY_PART (E));
+					    gda_sql_function_take_name (func, V);
+					    expr = gda_sql_expr_new (GDA_SQL_ANY_PART (func)); 
+					    expr->value = A;
+					    gda_sql_function_take_args_list (func, g_slist_prepend (NULL, expr));
+					    E->func = func;}
+expr(E) ::= CAST LP expr(A) AS fullname(T) RP. {E = A;
+						A->cast_as = g_value_dup_string (T);
+						g_value_reset (T);
+						g_free (T);}
+expr(E) ::= expr(A) PGCAST fullname(T). {E = A;
+					 A->cast_as = g_value_dup_string (T);
+					 g_value_reset (T);
+					 g_free (T);}
+
+expr(C) ::= expr(L) PLUS|MINUS(O) expr(R). {C = compose_multiple_expr (string_to_op_type (O), L, R);}
+expr(C) ::= expr(L) STAR expr(R). {C = compose_multiple_expr (GDA_SQL_OPERATOR_STAR, L, R);}
+expr(C) ::= expr(L) SLASH|REM(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
+expr(C) ::= expr(L) BITAND|BITOR(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
+
+expr(C) ::= MINUS expr(X). [UMINUS] {C = create_uni_expr (GDA_SQL_OPERATOR_MINUS, X);}
+expr(C) ::= PLUS expr(X). [UPLUS] {C = create_uni_expr (GDA_SQL_OPERATOR_PLUS, X);}
+
+expr(C) ::= expr(L) AND expr(R). {C = compose_multiple_expr (GDA_SQL_OPERATOR_AND, L, R);}
+expr(C) ::= expr(L) OR expr(R). {C = compose_multiple_expr (GDA_SQL_OPERATOR_OR, L, R);}
+expr(C) ::= expr(L) CONCAT expr(R). {C = compose_multiple_expr (GDA_SQL_OPERATOR_CONCAT, L, R);}
+
+expr(C) ::= expr(L) GT|LEQ|GEQ|LT(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
+expr(C) ::= expr(L) DIFF|EQ(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
+expr(C) ::= expr(L) LIKE expr(R). {C = create_two_expr (GDA_SQL_OPERATOR_LIKE, L, R);}
+expr(C) ::= expr(L) REGEXP|REGEXP_CI|NOT_REGEXP|NOT_REGEXP_CI|SIMILAR(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
+expr(C) ::= expr(L) BETWEEN expr(R) AND expr(E). {GdaSqlOperation *cond;
+						  C = gda_sql_expr_new (NULL);
+						  cond = gda_sql_operation_new (GDA_SQL_ANY_PART (C));
+						  C->cond = cond;
+						  cond->operator = GDA_SQL_OPERATOR_BETWEEN;
+						  cond->operands = g_slist_append (NULL, L);
+						  GDA_SQL_ANY_PART (L)->parent = GDA_SQL_ANY_PART (cond);
+						  cond->operands = g_slist_append (cond->operands, R);
+						  GDA_SQL_ANY_PART (R)->parent = GDA_SQL_ANY_PART (cond);
+						  cond->operands = g_slist_append (cond->operands, E);
+						  GDA_SQL_ANY_PART (E)->parent = GDA_SQL_ANY_PART (cond);
+}
+
+expr(C) ::= expr(L) NOT BETWEEN expr(R) AND expr(E). {GdaSqlOperation *cond;
+						      GdaSqlExpr *expr;
+						      expr = gda_sql_expr_new (NULL);
+						      cond = gda_sql_operation_new (GDA_SQL_ANY_PART (expr));
+						      expr->cond = cond;
+						      cond->operator = GDA_SQL_OPERATOR_BETWEEN;
+						      cond->operands = g_slist_append (NULL, L);
+						      GDA_SQL_ANY_PART (L)->parent = GDA_SQL_ANY_PART (cond);
+						      cond->operands = g_slist_append (cond->operands, R);
+						      GDA_SQL_ANY_PART (R)->parent = GDA_SQL_ANY_PART (cond);
+						      cond->operands = g_slist_append (cond->operands, E);
+						      GDA_SQL_ANY_PART (E)->parent = GDA_SQL_ANY_PART (cond);
+
+						      C = gda_sql_expr_new (NULL);
+						      cond = gda_sql_operation_new (GDA_SQL_ANY_PART (C));
+						      C->cond = cond;
+						      cond->operator = GDA_SQL_OPERATOR_NOT;
+						      cond->operands = g_slist_prepend (NULL, expr);
+						      GDA_SQL_ANY_PART (expr)->parent = GDA_SQL_ANY_PART (cond);
+}
+
+expr(C) ::= NOT expr(R). {C = create_uni_expr (GDA_SQL_OPERATOR_NOT, R);}
+expr(C) ::= BITNOT expr(R). {C = create_uni_expr (GDA_SQL_OPERATOR_BITNOT, R);}
+expr(C) ::= expr(R) uni_op(O) . {C = create_uni_expr (O, R);}
+
+expr(C) ::= expr(L) IS expr(R). {C = create_two_expr (GDA_SQL_OPERATOR_IS, L, R);}
+expr(E) ::= LP compound(S) RP. {E = gda_sql_expr_new (NULL); gda_sql_expr_take_select (E, S);}
+expr(E) ::= expr(R) IN LP exprlist(L) RP. {GdaSqlOperation *cond;
+					   GSList *list;
+					   E = gda_sql_expr_new (NULL);
+					   cond = gda_sql_operation_new (GDA_SQL_ANY_PART (E));
+					   E->cond = cond;
+					   cond->operator = GDA_SQL_OPERATOR_IN;
+					   cond->operands = g_slist_prepend (L, R);
+					   for (list = cond->operands; list; list = list->next)
+						   GDA_SQL_ANY_PART (list->data)->parent = GDA_SQL_ANY_PART (cond);
+}
+expr(E) ::= expr(R) IN LP compound(S) RP. {GdaSqlOperation *cond;
+					    GdaSqlExpr *expr;
+					    E = gda_sql_expr_new (NULL);
+					    cond = gda_sql_operation_new (GDA_SQL_ANY_PART (E));
+					    E->cond = cond;
+					    cond->operator = GDA_SQL_OPERATOR_IN;
+					    
+					    expr = gda_sql_expr_new (GDA_SQL_ANY_PART (cond));
+					    gda_sql_expr_take_select (expr, S);
+					    cond->operands = g_slist_prepend (NULL, expr);
+					    cond->operands = g_slist_prepend (cond->operands, R);
+					    GDA_SQL_ANY_PART (R)->parent = GDA_SQL_ANY_PART (cond);
+}
+expr(E) ::= expr(R) NOT IN LP exprlist(L) RP. {GdaSqlOperation *cond;
+					       GdaSqlExpr *expr;
+					       GSList *list;
+					       expr = gda_sql_expr_new (NULL);
+					       cond = gda_sql_operation_new (GDA_SQL_ANY_PART (expr));
+					       expr->cond = cond;
+					       cond->operator = GDA_SQL_OPERATOR_IN;
+					       cond->operands = g_slist_prepend (L, R);
+					       for (list = cond->operands; list; list = list->next)
+						       GDA_SQL_ANY_PART (list->data)->parent = GDA_SQL_ANY_PART (cond);
+					       
+					       E = gda_sql_expr_new (NULL);
+					       cond = gda_sql_operation_new (GDA_SQL_ANY_PART (E));
+					       E->cond = cond;
+					       cond->operator = GDA_SQL_OPERATOR_NOT;
+					       cond->operands = g_slist_prepend (NULL, expr);
+					       GDA_SQL_ANY_PART (expr)->parent = GDA_SQL_ANY_PART (cond);
+}
+expr(E) ::= expr(R) NOT IN LP compound(S) RP. {GdaSqlOperation *cond;
+						GdaSqlExpr *expr1, *expr2;
+						expr1 = gda_sql_expr_new (NULL);
+						cond = gda_sql_operation_new (GDA_SQL_ANY_PART (expr1));
+						expr1->cond = cond;
+						cond->operator = GDA_SQL_OPERATOR_IN;
+						
+						expr2 = gda_sql_expr_new (NULL);
+						gda_sql_expr_take_select (expr2, S);
+						cond->operands = g_slist_prepend (NULL, expr2);
+						GDA_SQL_ANY_PART (expr2)->parent = GDA_SQL_ANY_PART (cond);
+						cond->operands = g_slist_prepend (cond->operands, R);
+						GDA_SQL_ANY_PART (R)->parent = GDA_SQL_ANY_PART (cond);
+						
+						E = gda_sql_expr_new (NULL);
+						cond = gda_sql_operation_new (GDA_SQL_ANY_PART (E));
+						E->cond = cond;
+						cond->operator = GDA_SQL_OPERATOR_NOT;
+						cond->operands = g_slist_prepend (NULL, expr1);
+						GDA_SQL_ANY_PART (expr1)->parent = GDA_SQL_ANY_PART (cond);
+}
+expr(A) ::= CASE case_operand(X) case_exprlist(Y) case_else(Z) END. {
+	GdaSqlCase *sc;
+	GSList *list;
+	A = gda_sql_expr_new (NULL);
+	sc = gda_sql_case_new (GDA_SQL_ANY_PART (A));
+	sc->base_expr = X;
+	sc->else_expr = Z;
+	sc->when_expr_list = Y.when_list;
+	sc->then_expr_list = Y.then_list;
+	A->case_s = sc;
+	for (list = sc->when_expr_list; list; list = list->next)
+		GDA_SQL_ANY_PART (list->data)->parent = GDA_SQL_ANY_PART (sc);
+	for (list = sc->then_expr_list; list; list = list->next)
+		GDA_SQL_ANY_PART (list->data)->parent = GDA_SQL_ANY_PART (sc);
+}
+	
+%type case_operand {GdaSqlExpr*}
+%destructor case_operand {gda_sql_expr_free ($$);}
+case_operand(A) ::= expr(X).            {A = X;}
+case_operand(A) ::= .                   {A = NULL;}
+
+%type case_exprlist {CaseBody}
+%destructor case_exprlist {g_slist_foreach ($$.when_list, (GFunc) gda_sql_expr_free, NULL); g_slist_free ($$.when_list);
+	g_slist_foreach ($$.then_list, (GFunc) gda_sql_expr_free, NULL); g_slist_free ($$.then_list);}
+
+case_exprlist(A) ::= case_exprlist(X) WHEN expr(Y) THEN expr(Z). {
+	A.when_list = g_slist_append (X.when_list, Y);
+	A.then_list = g_slist_append (X.then_list, Z);
+}
+case_exprlist(A) ::= WHEN expr(Y) THEN expr(Z). {
+	A.when_list = g_slist_prepend (NULL, Y);
+	A.then_list = g_slist_prepend (NULL, Z);
+}
+
+%type case_else {GdaSqlExpr*}
+%destructor case_else {gda_sql_expr_free ($$);}
+case_else(A) ::= ELSE expr(X).       {A = X;}
+case_else(A) ::= .                   {A = NULL;}
+
+%type uni_op {GdaSqlOperator}
+uni_op(O) ::= ISNULL. {O = GDA_SQL_OPERATOR_ISNULL;}
+uni_op(O) ::= IS NOTNULL. {O = GDA_SQL_OPERATOR_ISNOTNULL;}
+
+
+// Values: for all constants (G_TYPE_STRING GValue)
+value(V) ::= NULL. {V = NULL;}
+value(V) ::= STRING(S). {V = S;}
+value(V) ::= TEXTUAL(T). {V = T;}
+value(V) ::= INTEGER(I). {V = I;}
+value(V) ::= FLOAT(F). {V = F;}
+
+// pvalue: values which are parameters (GdaSqlExpr)
+%type pvalue {GdaSqlExpr *}
+%destructor pvalue {gda_sql_expr_free ($$);}
+	pvalue(E) ::= UNSPECVAL LSBRACKET paramspec(P) RSBRACKET. {E = gda_sql_expr_new (NULL); E->param_spec = P;}
+pvalue(E) ::= value(V) LSBRACKET paramspec(P) RSBRACKET. {E = gda_sql_expr_new (NULL); E->value = V; E->param_spec = P;}
+pvalue(E) ::= SIMPLEPARAM(S). {E = gda_sql_expr_new (NULL); E->param_spec = gda_sql_param_spec_new (S);}
+
+// paramspec: parameter's specifications
+%type paramspec {GdaSqlParamSpec *}
+%destructor paramspec {gda_sql_param_spec_free ($$);}
+paramspec(P) ::= . {P = NULL;}
+paramspec(P) ::= paramspec(E) PNAME(N). {if (!E) P = gda_sql_param_spec_new (NULL); else P = E; 
+					 gda_sql_param_spec_take_name (P, N);}
+paramspec(P) ::= paramspec(E) PDESCR(N). {if (!E) P = gda_sql_param_spec_new (NULL); else P = E; 
+					 gda_sql_param_spec_take_descr (P, N);}
+paramspec(P) ::= paramspec(E) PTYPE(N). {if (!E) P = gda_sql_param_spec_new (NULL); else P = E; 
+					 gda_sql_param_spec_take_type (P, N);}
+paramspec(P) ::= paramspec(E) PNULLOK(N). {if (!E) P = gda_sql_param_spec_new (NULL); else P = E; 
+					   gda_sql_param_spec_take_nullok (P, N);}
+
+// The name of a column or table can be any of the following:
+//
+nm(A) ::= JOIN(X).       {A = X;}
+nm(A) ::= ID(X).       {A = X;}
+
+// Fully qualified name
+fullname(A) ::= nm(X). {A = X;}
+fullname(A) ::= nm(S) DOT nm(X). {gchar *str;
+				  str = g_strdup_printf ("%s.%s", g_value_get_string (S), g_value_get_string (X));
+				  A = g_new0 (GValue, 1);
+				  g_value_init (A, G_TYPE_STRING);
+				  g_value_take_string (A, str);
+				  g_value_reset (S); g_free (S);
+				  g_value_reset (X); g_free (X);
+}
+
+fullname(A) ::= nm(C) DOT nm(S) DOT nm(X). {gchar *str;
+				  str = g_strdup_printf ("%s.%s.%s", g_value_get_string (C), 
+							 g_value_get_string (S), g_value_get_string (X));
+				  A = g_new0 (GValue, 1);
+				  g_value_init (A, G_TYPE_STRING);
+				  g_value_take_string (A, str);
+				  g_value_reset (C); g_free (C);
+				  g_value_reset (S); g_free (S);
+				  g_value_reset (X); g_free (X);
+}



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