[libgda] Extracted the MySQL reuseable part



commit e29b05cddc24041fdde2dfd653b4c4ddbdc92295
Author: Vivien Malerba <malerba gnome-db org>
Date:   Wed Nov 25 20:43:24 2009 +0100

    Extracted the MySQL reuseable part

 configure.in                                       |    1 +
 providers/mysql/Makefile.am                        |   40 +--
 providers/mysql/gda-mysql-provider.c               |   46 +--
 providers/mysql/gda-mysql-recordset.c              |    4 +-
 providers/mysql/gda-mysql-util.c                   |   34 --
 providers/mysql/gda-mysql-util.h                   |    5 -
 providers/mysql/gda-mysql.h                        |   17 +-
 providers/postgres/gda-postgres-provider.c         |    4 +-
 providers/reuseable/Makefile.am                    |    6 +-
 providers/reuseable/gda-provider-reuseable.h       |    7 +-
 providers/reuseable/mysql/Makefile.am              |   51 ++
 providers/{ => reuseable}/mysql/gda-mysql-meta.c   |  566 ++++++++++++--------
 providers/{ => reuseable}/mysql/gda-mysql-meta.h   |    0
 providers/{ => reuseable}/mysql/gda-mysql-parser.c |    0
 providers/{ => reuseable}/mysql/gda-mysql-parser.h |    0
 providers/reuseable/mysql/gda-mysql-reuseable.c    |  299 +++++++++++
 providers/reuseable/mysql/gda-mysql-reuseable.h    |   72 +++
 providers/{ => reuseable}/mysql/gen_def.c          |    0
 providers/{ => reuseable}/mysql/keywords_V50.list  |    0
 providers/{ => reuseable}/mysql/keywords_V51.list  |    0
 providers/{ => reuseable}/mysql/keywords_V54.list  |    0
 providers/{ => reuseable}/mysql/keywords_V60.list  |    0
 providers/{ => reuseable}/mysql/parser.y           |    0
 providers/reuseable/postgres/gda-postgres-meta.c   |   91 +---
 .../reuseable/postgres/gda-postgres-reuseable.c    |   89 +++-
 .../reuseable/postgres/gda-postgres-reuseable.h    |    3 +-
 providers/reuseable/reuse-all.c                    |    9 +-
 providers/reuseable/reuse-all.h                    |    5 +-
 providers/web/gda-web-util.c                       |    3 +-
 29 files changed, 909 insertions(+), 443 deletions(-)
---
diff --git a/configure.in b/configure.in
index 567397d..5b9ab8b 100644
--- a/configure.in
+++ b/configure.in
@@ -1712,6 +1712,7 @@ libgda/thread-wrapper/Makefile
 providers/Makefile
 providers/reuseable/Makefile
 providers/reuseable/postgres/Makefile
+providers/reuseable/mysql/Makefile
 providers/bdb/Makefile
 providers/bdb/libgda-bdb-4.0.pc
 providers/mdb/Makefile
diff --git a/providers/mysql/Makefile.am b/providers/mysql/Makefile.am
index 6b7526d..ffe0534 100644
--- a/providers/mysql/Makefile.am
+++ b/providers/mysql/Makefile.am
@@ -8,43 +8,16 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir) \
 	-I$(top_srcdir)/libgda \
 	-I$(top_builddir) \
+	-I$(top_srcdir)/providers/reuseable/mysql \
 	$(LIBGDA_CFLAGS) $(MYSQL_CFLAGS) 
 
-mkkeywordhash$(EXEEXT_FOR_BUILD): $(top_srcdir)/libgda/sqlite/mkkeywordhash.c
-	$(CC_FOR_BUILD) -o mkkeywordhash$(EXEEXT_FOR_BUILD) $(GDA_DEBUG_FLAGS) $<
-
-keyword_files=keywords_V50.list keywords_V51.list keywords_V54.list keywords_V60.list
-pkeyword_files=$(addprefix $(top_srcdir)/providers/mysql/,$(keyword_files))
-
-keywords_hash.c: mkkeywordhash$(EXEEXT_FOR_BUILD) $(pkeyword_files)
-	./mkkeywordhash$(EXEEXT_FOR_BUILD) $(top_srcdir)/providers/mysql/keywords_V50.list V50 > keywords_hash.c
-	./mkkeywordhash$(EXEEXT_FOR_BUILD) $(top_srcdir)/providers/mysql/keywords_V51.list V51 >> keywords_hash.c
-	./mkkeywordhash$(EXEEXT_FOR_BUILD) $(top_srcdir)/providers/mysql/keywords_V54.list V54 >> keywords_hash.c
-	./mkkeywordhash$(EXEEXT_FOR_BUILD) $(top_srcdir)/providers/mysql/keywords_V60.list V60 >> keywords_hash.c
-
-# parser generation
-parser.c parser.h: parser.y $(top_builddir)/libgda/sql-parser/lemon$(EXEEXT_FOR_BUILD)
-	- $(top_builddir)/libgda/sql-parser/lemon$(EXEEXT_FOR_BUILD) -q -d $(srcdir)/parser.y $(top_srcdir)/libgda/sql-parser/lempar.c
-
-gen_def$(EXEEXT_FOR_BUILD): gen_def.c
-	$(CC_FOR_BUILD) -o gen_def$(EXEEXT_FOR_BUILD) -DIMPOSED_HEADER=\""$(top_builddir)/libgda/sql-parser/token_types.h"\" $(srcdir)/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 keywords_hash.c
-
 libgda_mysql_la_SOURCES = \
 	gda-mysql-blob-op.c \
 	gda-mysql-blob-op.h \
 	gda-mysql-ddl.c \
 	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 \
@@ -52,14 +25,12 @@ libgda_mysql_la_SOURCES = \
 	gda-mysql-pstmt.c \
 	gda-mysql-pstmt.h \
 	gda-mysql.h \
-	libmain.c \
-	parser.h \
-        parser.c \
-        mysql_token_types.h
+	libmain.c
 
 libgda_mysql_la_LDFLAGS = -export-dynamic -module -avoid-version $(NO_UNDEFINED) $(LIBTOOL_PROV_EXPORT_OPTIONS)
 libgda_mysql_la_LIBADD = \
 	$(top_builddir)/libgda/libgda-4.0.la \
+	$(top_builddir)/providers/reuseable/mysql/libgda-mysql.la \
 	$(LIBGDA_LIBS) $(MYSQL_LIBS)
 
 xmldir   = $(datadir)/libgda-4.0
@@ -86,8 +57,5 @@ xml_DATA = $(xml_in_files:.xml.in=.xml)
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libgda-mysql-4.0.pc
 
-EXTRA_DIST = $(xml_in_files) libgda-mysql-4.0.pc.in parser.y gen_def.c $(keyword_files)
+EXTRA_DIST = $(xml_in_files) libgda-mysql-4.0.pc.in
 DISTCLEANFILES = $(xml_DATA)
-
-CLEANFILES = parser.h parser.c parser.out mysql_token_types.h gen_def$(EXEEXT_FOR_BUILD) \
-	mkkeywordhash$(EXEEXT_FOR_BUILD) keywords_hash.c
diff --git a/providers/mysql/gda-mysql-provider.c b/providers/mysql/gda-mysql-provider.c
index 882d6dd..c3a5443 100644
--- a/providers/mysql/gda-mysql-provider.c
+++ b/providers/mysql/gda-mysql-provider.c
@@ -1,5 +1,5 @@
 /* GDA Mysql provider
- * Copyright (C) 2008 The GNOME Foundation.
+ * Copyright (C) 2008 - 2009 The GNOME Foundation.
  *
  * AUTHORS:
  *      Carlos Savoretti <csavoretti gmail com>
@@ -541,30 +541,6 @@ gda_mysql_real_query_wrap (GdaConnection *cnc, MYSQL *mysql, const char *stmt_st
 	return mysql_real_query (mysql, stmt_str, length);
 }
 
-static gchar *
-get_mysql_version (MYSQL  *mysql)
-{
-	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));
-}
-
-static gchar *
-get_mysql_short_version (MYSQL  *mysql)
-{
-	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",
-				version_long/10000,
-				(version_long%10000)/100);
-}
-
-
 /* 
  * Open connection request
  *
@@ -692,10 +668,12 @@ gda_mysql_provider_open_connection (GdaServerProvider               *provider,
 	cdata->cnc = cnc;
 	cdata->mysql = mysql;
 
-	cdata->version_long = mysql_get_server_version (mysql);
-	cdata->version = get_mysql_version (mysql);
-	cdata->short_version = get_mysql_short_version (mysql);
-	cdata->identifiers_case_sensitive = case_sensitive;
+	/* handle the reuseable part */
+	GdaProviderReuseableOperations *ops;
+	ops = _gda_mysql_reuseable_get_ops ();
+	cdata->reuseable = (GdaMysqlReuseable*) ops->re_new_data ();
+	_gda_mysql_compute_version (cnc, cdata->reuseable, NULL);
+	cdata->reuseable->identifiers_case_sensitive = case_sensitive;
 
 	return TRUE;
 }
@@ -2264,7 +2242,8 @@ gda_mysql_identifier_quote (GdaServerProvider *provider, GdaConnection *cnc,
 	else if (((GdaMysqlProvider*) provider)->test_mode)
 		case_sensitive = ((GdaMysqlProvider*) provider)->test_identifiers_case_sensitive;
 
-	kwfunc = _gda_mysql_get_reserved_keyword_func (cdata);
+	kwfunc = _gda_mysql_reuseable_get_reserved_keywords_func
+		(cdata ? (GdaProviderReuseable*) cdata->reuseable : NULL);
 
 	if (case_sensitive) {
 		/*
@@ -2382,8 +2361,11 @@ gda_mysql_free_cnc_data (MysqlConnectionData  *cdata)
 		cdata->mysql = NULL;
 	}
 
-	g_free (cdata->version);
-	g_free (cdata->short_version);
+	if (cdata->reuseable) {
+		GdaProviderReuseable *rdata = (GdaProviderReuseable*)cdata->reuseable;
+		rdata->operations->re_reset_data (rdata);
+		g_free (cdata->reuseable);
+	}
 	
 	g_free (cdata);
 }
diff --git a/providers/mysql/gda-mysql-recordset.c b/providers/mysql/gda-mysql-recordset.c
index 5be82dc..6b66f12 100644
--- a/providers/mysql/gda-mysql-recordset.c
+++ b/providers/mysql/gda-mysql-recordset.c
@@ -423,9 +423,11 @@ gda_mysql_recordset_new (GdaConnection            *cnc,
 				if (col_types [i] > 0) {
 					if (col_types [i] == G_TYPE_NONE)
 						break;
-					if (i >= _GDA_PSTMT (ps)->ncols)
+					if (i >= _GDA_PSTMT (ps)->ncols) {
 						g_warning (_("Column %d out of range (0-%d), ignoring its specified type"), i,
 							   _GDA_PSTMT (ps)->ncols - 1);
+						break;
+					}
 					else
 						_GDA_PSTMT (ps)->types [i] = col_types [i];
 				}
diff --git a/providers/mysql/gda-mysql-util.c b/providers/mysql/gda-mysql-util.c
index 62fbb39..98ad113 100644
--- a/providers/mysql/gda-mysql-util.c
+++ b/providers/mysql/gda-mysql-util.c
@@ -25,9 +25,6 @@
 #include <glib/gi18n-lib.h>
 #include "gda-mysql-util.h"
 
-#include <libgda/sqlite/keywords_hash.h>
-#include "keywords_hash.c" /* this one is dynamically generated */
-
 /*
  * Create a new #GdaConnectionEvent object and "adds" it to @cnc
  *
@@ -81,34 +78,3 @@ _gda_mysql_make_error (GdaConnection  *cnc,
 
 	return event_error;
 }
-
-#ifdef GDA_DEBUG
-void
-_gda_mysql_test_keywords (void)
-{
-	V50test_keywords();
-	V51test_keywords();
-	V54test_keywords();
-	V60test_keywords();
-}
-#endif
-
-GdaSqlReservedKeywordsFunc
-_gda_mysql_get_reserved_keyword_func (MysqlConnectionData *cdata)
-{
-	if (cdata && cdata->short_version) {
-		switch (*cdata->short_version) {
-		case '5':
-			if (cdata->short_version[1] == '1')
-				return V51is_keyword;
-			if (cdata->short_version[1] == '0')
-				return V50is_keyword;
-			return V54is_keyword;
-		case '6':
-		default:
-			return V60is_keyword;
-		break;
-		}
-	}
-	return V60is_keyword;
-}
diff --git a/providers/mysql/gda-mysql-util.h b/providers/mysql/gda-mysql-util.h
index 250fa4b..5827633 100644
--- a/providers/mysql/gda-mysql-util.h
+++ b/providers/mysql/gda-mysql-util.h
@@ -32,11 +32,6 @@ GdaConnectionEvent          * _gda_mysql_make_error (GdaConnection  *cnc,
 						     MYSQL          *mysql,
 						     MYSQL_STMT     *mysql_stmt,
 						     GError        **error);
-#ifdef GDA_DEBUG
-void                          _gda_mysql_test_keywords (void);
-#endif
-GdaSqlReservedKeywordsFunc    _gda_mysql_get_reserved_keyword_func (MysqlConnectionData *cdata);
-
 
 G_END_DECLS
 
diff --git a/providers/mysql/gda-mysql.h b/providers/mysql/gda-mysql.h
index 88b830b..84026e0 100644
--- a/providers/mysql/gda-mysql.h
+++ b/providers/mysql/gda-mysql.h
@@ -33,25 +33,18 @@
 #include <winsock.h>
 #endif
 #include <mysql.h>
+#include <gda-mysql-reuseable.h>
 
 /*
  * Provider's specific connection data
  */
 typedef struct {
-	/* TO_ADD: this structure holds any information necessary to specialize the GdaConnection, usually a connection
-	 * handle from the C or C++ API
-	 */
-	
-	GdaConnection    *cnc;
-	MYSQL            *mysql;
-
-	/* Backend version (to which we're connected). */
-	gchar            *version;
-	unsigned long     version_long;
-	gchar            *short_version;
+	GdaMysqlReuseable *reuseable;
+	GdaConnection     *cnc;
+	MYSQL             *mysql;
 
 	/* specifies how case sensitiveness is */
-	gboolean          identifiers_case_sensitive;
+	gboolean           identifiers_case_sensitive;
 	
 } MysqlConnectionData;
 
diff --git a/providers/postgres/gda-postgres-provider.c b/providers/postgres/gda-postgres-provider.c
index 73de91b..3df815f 100644
--- a/providers/postgres/gda-postgres-provider.c
+++ b/providers/postgres/gda-postgres-provider.c
@@ -1,5 +1,5 @@
 /* GDA postgres provider
- * Copyright (C) 1998 - 2008 The GNOME Foundation.
+ * Copyright (C) 1998 - 2009 The GNOME Foundation.
  *
  * AUTHORS:
  *         Vivien Malerba <malerba gnome-db org>
@@ -558,7 +558,7 @@ gda_postgres_provider_open_connection (GdaServerProvider *provider, GdaConnectio
 	/* handle the reuseable part */
 	GdaProviderReuseableOperations *ops;
 	ops = _gda_postgres_reuseable_get_ops ();
-	cdata->reuseable = (GdaPostgresReuseable*) ops->re_new_data (NULL, NULL);
+	cdata->reuseable = (GdaPostgresReuseable*) ops->re_new_data ();
 	_gda_postgres_compute_types (cnc, cdata->reuseable);
 
 	/*
diff --git a/providers/reuseable/Makefile.am b/providers/reuseable/Makefile.am
index 6ce70fe..f765659 100644
--- a/providers/reuseable/Makefile.am
+++ b/providers/reuseable/Makefile.am
@@ -1,7 +1,8 @@
 noinst_LTLIBRARIES = libreuseable.la
 
 SUBDIRS = \
-	postgres
+	postgres \
+	mysql
 
 AM_CPPFLAGS = \
         -I$(top_srcdir) \
@@ -16,4 +17,5 @@ libreuseable_la_SOURCES = \
 	reuse-all.h
 
 libreuseable_la_LIBADD = \
-	postgres/libgda-postgres.la
+	postgres/libgda-postgres.la \
+	mysql/libgda-mysql.la
diff --git a/providers/reuseable/gda-provider-reuseable.h b/providers/reuseable/gda-provider-reuseable.h
index e279a43..4c05b94 100644
--- a/providers/reuseable/gda-provider-reuseable.h
+++ b/providers/reuseable/gda-provider-reuseable.h
@@ -31,7 +31,7 @@ G_BEGIN_DECLS
 
 typedef struct _GdaProviderReuseable GdaProviderReuseable;
 
-typedef GdaProviderReuseable *(*GdaProviderReuseable_NewDataFunc) (const gchar *major, const gchar *minor);
+typedef GdaProviderReuseable *(*GdaProviderReuseable_NewDataFunc) (void);
 typedef void (*GdaProviderReuseable_ResetDataFunc) (GdaProviderReuseable *rdata);
 typedef GType (*GdaProviderReuseable_GetGTypeFunc) (GdaConnection *cnc, GdaProviderReuseable *rdata, const gchar *db_type);
 typedef GdaSqlReservedKeywordsFunc (*GdaProviderReuseable_GetReservedKeywordsFunc) (GdaProviderReuseable *rdata);
@@ -58,8 +58,9 @@ typedef struct {
  */
 struct _GdaProviderReuseable {
 	GdaProviderReuseableOperations *operations;
-	gchar                          *version_major;
-	gchar                          *version_minor;
+	guint                           major; /* major version */
+	guint                           minor; /* minor version */
+	guint                           micro; /* micro version */
 };
 
 
diff --git a/providers/reuseable/mysql/Makefile.am b/providers/reuseable/mysql/Makefile.am
new file mode 100644
index 0000000..6f387f0
--- /dev/null
+++ b/providers/reuseable/mysql/Makefile.am
@@ -0,0 +1,51 @@
+noinst_LTLIBRARIES = libgda-mysql.la
+
+AM_CPPFLAGS = \
+	-I$(top_srcdir) \
+	-I$(top_srcdir)/libgda \
+	-I$(top_builddir) \
+	$(LIBGDA_CFLAGS)
+
+keyword_files=keywords_V50.list keywords_V51.list keywords_V54.list keywords_V60.list
+pkeyword_files=$(addprefix $(top_srcdir)/providers/reuseable/mysql/,$(keyword_files))
+
+mkkeywordhash$(EXEEXT_FOR_BUILD): $(top_srcdir)/libgda/sqlite/mkkeywordhash.c
+	$(CC_FOR_BUILD) -o mkkeywordhash$(EXEEXT_FOR_BUILD) $(GDA_DEBUG_FLAGS) $<
+
+keywords_hash.c: mkkeywordhash$(EXEEXT_FOR_BUILD) $(pkeyword_files)
+	./mkkeywordhash$(EXEEXT_FOR_BUILD) $(top_srcdir)/providers/reuseable/mysql/keywords_V50.list V50 > keywords_hash.c
+	./mkkeywordhash$(EXEEXT_FOR_BUILD) $(top_srcdir)/providers/reuseable/mysql/keywords_V51.list V51 >> keywords_hash.c
+	./mkkeywordhash$(EXEEXT_FOR_BUILD) $(top_srcdir)/providers/reuseable/mysql/keywords_V54.list V54 >> keywords_hash.c
+	./mkkeywordhash$(EXEEXT_FOR_BUILD) $(top_srcdir)/providers/reuseable/mysql/keywords_V60.list V60 >> keywords_hash.c
+
+# parser generation
+parser.c parser.h: parser.y $(top_builddir)/libgda/sql-parser/lemon$(EXEEXT_FOR_BUILD)
+	- $(top_builddir)/libgda/sql-parser/lemon$(EXEEXT_FOR_BUILD) -q -d $(srcdir)/parser.y $(top_srcdir)/libgda/sql-parser/lempar.c
+
+gen_def$(EXEEXT_FOR_BUILD): gen_def.c
+	$(CC_FOR_BUILD) -o gen_def$(EXEEXT_FOR_BUILD) -DIMPOSED_HEADER=\""$(top_builddir)/libgda/sql-parser/token_types.h"\" $(srcdir)/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 keywords_hash.c
+
+libgda_mysql_la_SOURCES = \
+	gda-mysql-reuseable.c \
+	gda-mysql-reuseable.h \
+	gda-mysql-parser.c \
+	gda-mysql-parser.h \
+	gda-mysql-meta.c \
+	gda-mysql-meta.h \
+	parser.h \
+        parser.c \
+        mysql_token_types.h
+
+libgda_mysql_la_LIBADD = \
+	$(top_builddir)/libgda/libgda-4.0.la \
+	$(LIBGDA_LIBS)
+
+EXTRA_DIST = $(xml_in_files) libgda-mysql-4.0.pc.in parser.y gen_def.c $(keyword_files)
+
+CLEANFILES = parser.h parser.c parser.out mysql_token_types.h gen_def$(EXEEXT_FOR_BUILD) \
+	mkkeywordhash$(EXEEXT_FOR_BUILD) keywords_hash.c
diff --git a/providers/mysql/gda-mysql-meta.c b/providers/reuseable/mysql/gda-mysql-meta.c
similarity index 77%
rename from providers/mysql/gda-mysql-meta.c
rename to providers/reuseable/mysql/gda-mysql-meta.c
index e1368f9..9bf1006 100644
--- a/providers/mysql/gda-mysql-meta.c
+++ b/providers/reuseable/mysql/gda-mysql-meta.c
@@ -1,5 +1,5 @@
 /* GDA mysql provider
- * Copyright (C) 2008 The GNOME Foundation.
+ * Copyright (C) 2008 - 2009 The GNOME Foundation.
  *
  * AUTHORS:
  *      Carlos Savoretti <csavoretti gmail com>
@@ -22,14 +22,15 @@
  */
 
 #include <string.h>
-#include "gda-mysql.h"
 #include "gda-mysql-meta.h"
-#include "gda-mysql-util.h"
-#include "gda-mysql-provider.h"
+#include "gda-mysql-reuseable.h"
+#include "gda-mysql-parser.h"
 #include <libgda/gda-meta-store.h>
+#include <libgda/gda-data-proxy.h>
 #include <libgda/sql-parser/gda-sql-parser.h>
 #include <glib/gi18n-lib.h>
 #include <libgda/gda-server-provider-extra.h>
+#include <libgda/providers-support/gda-meta-column-types.h>
 #include <libgda/gda-connection-private.h>
 #include <libgda/gda-data-model-array.h>
 #include <libgda/gda-set.h>
@@ -136,10 +137,10 @@ static gchar *internal_sql[] = {
 	"SELECT IFNULL(constraint_catalog, constraint_schema) AS constraint_catalog, constraint_schema, constraint_name, IFNULL(constraint_catalog, constraint_schema) AS table_catalog, table_schema, table_name, constraint_type, NULL, FALSE, FALSE FROM INFORMATION_SCHEMA.table_constraints WHERE IFNULL(constraint_catalog, constraint_schema) = BINARY ##cat::string AND constraint_schema = BINARY ##schema::string AND table_name = BINARY ##name::string AND constraint_name = BINARY ##name2::string",
 
         /* I_STMT_REF_CONSTRAINTS */
-	"SELECT IFNULL(t.constraint_catalog, t.constraint_schema) AS constraint_catalog, t.constraint_schema, r.constraint_name, IFNULL(r.constraint_catalog, r.constraint_schema) AS constraint_catalog, r.constraint_schema, r.match_option, r.update_rule, delete_rule FROM INFORMATION_SCHEMA.referential_constraints r INNER JOIN INFORMATION_SCHEMA.table_constraints t ON r.constraint_schema=t.constraint_schema AND r.constraint_name=t.constraint_name AND r.table_name=t.table_name WHERE IFNULL(r.constraint_catalog, r.constraint_schema) = BINARY ##cat::string AND r.constraint_schema = BINARY ##schema::string AND r.table_name = BINARY ##name::string AND r.constraint_name = BINARY ##name2::string",
+	"select IFNULL(constraint_catalog, constraint_schema) AS constraint_catalog, constraint_schema, table_name, constraint_name, IFNULL(constraint_catalog, constraint_schema) AS ref_table_cat, constraint_schema, referenced_table_name, unique_constraint_name, match_option, update_rule, delete_rule from information_schema.referential_constraints WHERE IFNULL(constraint_catalog, constraint_schema) = BINARY ##cat::string AND constraint_schema = BINARY ##schema::string AND table_name = BINARY ##name::string AND constraint_name = BINARY ##name2::string",
 
         /* I_STMT_REF_CONSTRAINTS_ALL */
-	"SELECT IFNULL(t.constraint_catalog, t.constraint_schema) AS constraint_catalog, t.constraint_schema, r.constraint_name, IFNULL(r.constraint_catalog, r.constraint_schema) AS constraint_catalog, r.constraint_schema, r.match_option, r.update_rule, delete_rule FROM INFORMATION_SCHEMA.referential_constraints r INNER JOIN INFORMATION_SCHEMA.table_constraints t ON r.constraint_schema=t.constraint_schema AND r.constraint_name=t.constraint_name AND r.table_name=t.table_name",
+	"select IFNULL(constraint_catalog, constraint_schema) AS constraint_catalog, constraint_schema, table_name, constraint_name, IFNULL(constraint_catalog, constraint_schema) AS ref_table_cat, constraint_schema, referenced_table_name, unique_constraint_name, match_option, update_rule, delete_rule from information_schema.referential_constraints",
 
         /* I_STMT_KEY_COLUMN_USAGE */
 	"SELECT IFNULL(table_catalog, table_schema) AS table_catalog, table_schema, table_name, constraint_name, column_name, ordinal_position FROM INFORMATION_SCHEMA.key_column_usage WHERE IFNULL(table_catalog, table_schema) = BINARY ##cat::string AND table_schema = BINARY ##schema::string AND table_name = BINARY ##name::string AND constraint_name = BINARY ##name2::string",
@@ -216,9 +217,6 @@ static gchar *internal_sql[] = {
  */
 static GdaStatement **internal_stmt;
 static GdaSet        *i_set;
-static GdaSqlParser  *internal_parser = NULL;
-/* TO_ADD: other static values */
-
 
 /*
  * Meta initialization
@@ -228,17 +226,24 @@ _gda_mysql_provider_meta_init (GdaServerProvider  *provider)
 {
 	static GStaticMutex init_mutex = G_STATIC_MUTEX_INIT;
 	InternalStatementItem i;
+	GdaSqlParser *parser;
 
 	g_static_mutex_lock (&init_mutex);
 
-        internal_parser = gda_server_provider_internal_get_parser (provider);
+	if (provider)
+                parser = gda_server_provider_internal_get_parser (provider);
+        else
+                parser = GDA_SQL_PARSER (g_object_new (GDA_TYPE_MYSQL_PARSER, NULL));
         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);
+                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]);
         }
 
+	if (!provider)
+                g_object_unref (parser);
+
 	/* initialize static values here */
 	i_set = gda_set_new_inline (4, "cat", G_TYPE_STRING, "", 
 				    "name", G_TYPE_STRING, "",
@@ -252,6 +257,8 @@ _gda_mysql_provider_meta_init (GdaServerProvider  *provider)
 #endif
 }
 
+#define GDA_MYSQL_GET_REUSEABLE_DATA(cdata) (* ((GdaMysqlReuseable**) (cdata)))
+
 gboolean
 _gda_mysql_meta__info (GdaServerProvider  *prov,
 		       GdaConnection      *cnc, 
@@ -261,16 +268,23 @@ _gda_mysql_meta__info (GdaServerProvider  *prov,
 {
 	GdaDataModel *model;
         gboolean retval;
-	MysqlConnectionData *cdata;
-	cdata = (MysqlConnectionData *) gda_connection_internal_get_provider_data (cnc);
-	if (!cdata)
+	GdaMysqlReuseable *rdata;
+	rdata = GDA_MYSQL_GET_REUSEABLE_DATA (gda_connection_internal_get_provider_data (cnc));
+	if (!rdata)
 		return FALSE;
 
-        model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_CATALOG], NULL, error);
+	model = gda_connection_statement_execute_select_full (cnc,
+							      internal_stmt[I_STMT_CATALOG],
+							      NULL, 
+							      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+							      _col_types_information_schema_catalog_name,
+							      error);
         if (model == NULL)
                 retval = FALSE;
 	else {
-		gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
+		gda_meta_store_set_reserved_keywords_func (store,
+							   _gda_mysql_reuseable_get_reserved_keywords_func
+							   ((GdaProviderReuseable*) rdata));
 		retval = gda_meta_store_modify (store, context->table_name, model, NULL, error, NULL);
 		g_object_unref (G_OBJECT (model));
 	}
@@ -327,9 +341,9 @@ _gda_mysql_meta__btypes (GdaServerProvider  *prov,
 	};
         GdaDataModel *model;
         gboolean retval = TRUE;
-	MysqlConnectionData *cdata;
-	cdata = (MysqlConnectionData *) gda_connection_internal_get_provider_data (cnc);
-	if (!cdata)
+	GdaMysqlReuseable *rdata;
+	rdata = GDA_MYSQL_GET_REUSEABLE_DATA (gda_connection_internal_get_provider_data (cnc));
+	if (!rdata)
 		return FALSE;
 
 	model = gda_meta_store_create_modify_data_model (store, context->table_name);
@@ -373,7 +387,9 @@ _gda_mysql_meta__btypes (GdaServerProvider  *prov,
 		}
 
 		if (retval) {
-			gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
+			gda_meta_store_set_reserved_keywords_func (store,
+								   _gda_mysql_reuseable_get_reserved_keywords_func
+								   ((GdaProviderReuseable*) rdata));
 			retval = gda_meta_store_modify (store, context->table_name, model, NULL, error, NULL);
 		}
 		g_object_unref (G_OBJECT(model));
@@ -551,7 +567,7 @@ _gda_mysql_meta_collations (GdaServerProvider  *prov,
 			    const GValue       *collation_schema, 
 			    const GValue       *collation_name_n)
 {
-	TO_IMPLEMENT;
+	/* Feature not supported by MySQL. */
 	return TRUE;
 }
 
@@ -564,16 +580,23 @@ _gda_mysql_meta__character_sets (GdaServerProvider  *prov,
 {
 	GdaDataModel *model;
 	gboolean retval;
-	MysqlConnectionData *cdata;
-	cdata = (MysqlConnectionData *) gda_connection_internal_get_provider_data (cnc);
-	if (!cdata)
+	GdaMysqlReuseable *rdata;
+	rdata = GDA_MYSQL_GET_REUSEABLE_DATA (gda_connection_internal_get_provider_data (cnc));
+	if (!rdata)
 		return FALSE;
 
-	model = gda_connection_statement_execute_select	(cnc, internal_stmt[I_STMT_CHARACTER_SETS_ALL], NULL, error);
+	model = gda_connection_statement_execute_select_full (cnc,
+							      internal_stmt[I_STMT_CHARACTER_SETS_ALL],
+							      NULL, 
+							      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+							      _col_types_character_sets,
+							      error);
 	if (model == NULL)
 		retval = FALSE;
 	else {
-		gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
+		gda_meta_store_set_reserved_keywords_func (store,
+							   _gda_mysql_reuseable_get_reserved_keywords_func
+							   ((GdaProviderReuseable*) rdata));
 		retval = gda_meta_store_modify_with_context (store, context, model, error);
 		g_object_unref (G_OBJECT(model));
 	}
@@ -593,9 +616,9 @@ _gda_mysql_meta_character_sets (GdaServerProvider  *prov,
 {
 	GdaDataModel *model;
 	gboolean retval;
-	MysqlConnectionData *cdata;
-	cdata = (MysqlConnectionData *) gda_connection_internal_get_provider_data (cnc);
-	if (!cdata)
+	GdaMysqlReuseable *rdata;
+	rdata = GDA_MYSQL_GET_REUSEABLE_DATA (gda_connection_internal_get_provider_data (cnc));
+	if (!rdata)
 		return FALSE;
 
 	if (!gda_holder_set_value (gda_set_get_holder (i_set, "cat"), chset_catalog, error))
@@ -604,11 +627,19 @@ _gda_mysql_meta_character_sets (GdaServerProvider  *prov,
 		return FALSE;
 	if (!gda_holder_set_value (gda_set_get_holder (i_set, "name"), chset_name_n, error))
 		return FALSE;
-	model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_CHARACTER_SETS], i_set, error);
+
+	model = gda_connection_statement_execute_select_full (cnc,
+							      internal_stmt[I_STMT_CHARACTER_SETS],
+							      i_set,
+							      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+							      _col_types_character_sets,
+							      error);
 	if (model == NULL)
 		retval = FALSE;
 	else {
-		gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
+		gda_meta_store_set_reserved_keywords_func (store,
+							   _gda_mysql_reuseable_get_reserved_keywords_func
+							   ((GdaProviderReuseable*) rdata));
 		retval = gda_meta_store_modify_with_context (store, context, model, error);
 		g_object_unref (G_OBJECT(model));
 
@@ -624,23 +655,24 @@ _gda_mysql_meta__schemata (GdaServerProvider  *prov,
 			   GdaMetaContext     *context,
 			   GError            **error)
 {
-	GType col_types[] = {
-		0, 0, 0,
-		G_TYPE_BOOLEAN, G_TYPE_NONE
-	};
 	GdaDataModel *model;
 	gboolean retval;
-	MysqlConnectionData *cdata;
-	cdata = (MysqlConnectionData *) gda_connection_internal_get_provider_data (cnc);
-	if (!cdata)
+	GdaMysqlReuseable *rdata;
+	rdata = GDA_MYSQL_GET_REUSEABLE_DATA (gda_connection_internal_get_provider_data (cnc));
+	if (!rdata)
 		return FALSE;
 
-	model = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_SCHEMAS_ALL], NULL,
-							      GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types, error);
+	model = gda_connection_statement_execute_select_full (cnc,
+							      internal_stmt[I_STMT_SCHEMAS_ALL],
+							      NULL,
+							      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+							      _col_types_schemata, error);
 	if (model == NULL)
 		retval = FALSE;
 	else {
-		gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
+		gda_meta_store_set_reserved_keywords_func (store,
+							   _gda_mysql_reuseable_get_reserved_keywords_func
+							   ((GdaProviderReuseable*) rdata));
 		retval = gda_meta_store_modify_with_context (store, context, model, error);
 		g_object_unref (G_OBJECT(model));
 	}
@@ -657,38 +689,46 @@ _gda_mysql_meta_schemata (GdaServerProvider  *prov,
 			  const GValue       *catalog_name,
 			  const GValue       *schema_name_n)
 {
-	GType col_types[] = {
-		0, 0, 0,
-		G_TYPE_BOOLEAN, G_TYPE_NONE
-	};
 	GdaDataModel *model;
 	gboolean retval;
-	MysqlConnectionData *cdata;
-	cdata = (MysqlConnectionData *) gda_connection_internal_get_provider_data (cnc);
-	if (!cdata)
+	GdaMysqlReuseable *rdata;
+	rdata = GDA_MYSQL_GET_REUSEABLE_DATA (gda_connection_internal_get_provider_data (cnc));
+	if (!rdata)
 		return FALSE;
 
 	if (!gda_holder_set_value (gda_set_get_holder (i_set, "cat"), catalog_name, error))
 		return FALSE;
 	if (!schema_name_n) {
-		model = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_SCHEMAS], i_set,
-							      GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types, error);
+		model = gda_connection_statement_execute_select_full (cnc,
+								      internal_stmt[I_STMT_SCHEMAS],
+								      i_set,
+								      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+								      _col_types_schemata,
+								      error);
 		if (model == NULL)
 			retval = FALSE;
 		else {
-			gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
+			gda_meta_store_set_reserved_keywords_func (store,
+								   _gda_mysql_reuseable_get_reserved_keywords_func
+								   ((GdaProviderReuseable*) rdata));
 			retval = gda_meta_store_modify (store, context->table_name, model, NULL, error, NULL);
 			g_object_unref (G_OBJECT(model));
 		}
 	} else {
 		if (!gda_holder_set_value (gda_set_get_holder (i_set, "name"), schema_name_n, error))
 			return FALSE;
-		model = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_SCHEMA_NAMED], i_set,
-							      GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types, error);
+		model = gda_connection_statement_execute_select_full (cnc,
+								      internal_stmt[I_STMT_SCHEMA_NAMED],
+								      i_set,
+								      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+								      _col_types_schemata,
+								      error);
 		if (model == NULL)
 			retval = FALSE;
 		else {
-			gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
+			gda_meta_store_set_reserved_keywords_func (store,
+								   _gda_mysql_reuseable_get_reserved_keywords_func
+								   ((GdaProviderReuseable*) rdata));
 			retval = gda_meta_store_modify (store, context->table_name, model,
 							"schema_name=##name::string",
 							error,
@@ -707,22 +747,16 @@ _gda_mysql_meta__tables_views (GdaServerProvider  *prov,
 			       GdaMetaContext     *context,
 			       GError            **error)
 {	
-	GType col_types_tables[] = {
-		0, 0, 0, 0,
-		G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_NONE
-	};
-	GType col_types_views[] = {
-		G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
-		G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_NONE
-	};
 	GdaDataModel *model_tables, *model_views;
 	gboolean retval;
 	/* Check correct mysql server version. */
-	MysqlConnectionData *cdata;
-	cdata = (MysqlConnectionData *) gda_connection_internal_get_provider_data (cnc);
-	if (!cdata)
+	GdaMysqlReuseable *rdata;
+	rdata = GDA_MYSQL_GET_REUSEABLE_DATA (gda_connection_internal_get_provider_data (cnc));
+	if (!rdata)
+		return FALSE;
+	if ((rdata->version_long == 0) && ! _gda_mysql_compute_version (cnc, rdata, error))
 		return FALSE;
-	if (cdata->version_long < 50000) {
+	if (rdata->version_long < 50000) {
 		g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_SERVER_VERSION_ERROR,
 			     "%s", _("Mysql version 5.0 at least is required"));
 		return FALSE;
@@ -731,24 +765,34 @@ _gda_mysql_meta__tables_views (GdaServerProvider  *prov,
 	/* Copy contents, just because we need to modify @context->table_name */
 	GdaMetaContext copy = *context;
 
-	model_tables = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_TABLES_ALL], NULL,
-								     GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types_tables, error);
+	model_tables = gda_connection_statement_execute_select_full (cnc,
+								     internal_stmt[I_STMT_TABLES_ALL],
+								     NULL,
+								     GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+								     _col_types_tables, error);
 	if (model_tables == NULL)
 		retval = FALSE;
 	else {
 		copy.table_name = "_tables";
-		gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
+		gda_meta_store_set_reserved_keywords_func (store,
+							   _gda_mysql_reuseable_get_reserved_keywords_func
+							   ((GdaProviderReuseable*) rdata));
 		retval = gda_meta_store_modify_with_context (store, &copy, model_tables, error);
 		g_object_unref (G_OBJECT(model_tables));
 	}
 
-	model_views = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_VIEWS_ALL], NULL, 
-								    GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types_views, error);
+	model_views = gda_connection_statement_execute_select_full (cnc,
+								    internal_stmt[I_STMT_VIEWS_ALL],
+								    NULL, 
+								    GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+								    _col_types_views, error);
 	if (model_views == NULL)
 		retval = FALSE;
 	else {
 		copy.table_name = "_views";
-		gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
+		gda_meta_store_set_reserved_keywords_func (store,
+							   _gda_mysql_reuseable_get_reserved_keywords_func
+							   ((GdaProviderReuseable*) rdata));
 		retval = gda_meta_store_modify_with_context (store, &copy, model_views, error);
 		g_object_unref (G_OBJECT(model_views));
 	}
@@ -766,22 +810,16 @@ _gda_mysql_meta_tables_views (GdaServerProvider  *prov,
 			      const GValue       *table_schema, 
 			      const GValue       *table_name_n)
 {
-	GType col_types_tables[] = {
-		G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
-		G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_NONE
-	};
-	GType col_types_views[] = {
-		G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
-		G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_NONE
-	};
 	GdaDataModel *model_tables, *model_views;
 	gboolean retval;
 	/* Check correct mysql server version. */
-	MysqlConnectionData *cdata;
-	cdata = (MysqlConnectionData *) gda_connection_internal_get_provider_data (cnc);
-	if (!cdata)
+	GdaMysqlReuseable *rdata;
+	rdata = GDA_MYSQL_GET_REUSEABLE_DATA (gda_connection_internal_get_provider_data (cnc));
+	if (!rdata)
 		return FALSE;
-	if (cdata->version_long < 50000) {
+	if ((rdata->version_long == 0) && ! _gda_mysql_compute_version (cnc, rdata, error))
+		return FALSE;
+	if (rdata->version_long < 50000) {
 		g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_SERVER_VERSION_ERROR,
 			     "%s", _("Mysql version 5.0 at least is required"));
 		return FALSE;
@@ -796,14 +834,19 @@ _gda_mysql_meta_tables_views (GdaServerProvider  *prov,
 	if (!gda_holder_set_value (gda_set_get_holder (i_set, "schema"), table_schema, error))
 		return FALSE;
 	if (!table_name_n) {
-		model_tables = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_TABLES], i_set, 
-									    GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types_tables,
-									    error);
+		model_tables = gda_connection_statement_execute_select_full (cnc,
+									     internal_stmt[I_STMT_TABLES],
+									     i_set, 
+									     GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+									     _col_types_tables,
+									     error);
 		if (model_tables == NULL)
 			retval = FALSE;
 		else {
 			copy.table_name = "_tables";
-			gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
+			gda_meta_store_set_reserved_keywords_func (store,
+								   _gda_mysql_reuseable_get_reserved_keywords_func
+								   ((GdaProviderReuseable*) rdata));
 			retval = gda_meta_store_modify_with_context (store, &copy, model_tables, error);
 			g_object_unref (G_OBJECT (model_tables));
 		}
@@ -811,14 +854,19 @@ _gda_mysql_meta_tables_views (GdaServerProvider  *prov,
 		if (!retval)
 			return FALSE;
 
-		model_views = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_VIEWS_ALL], i_set, 
-									    GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types_views,
+		model_views = gda_connection_statement_execute_select_full (cnc,
+									    internal_stmt[I_STMT_VIEWS_ALL],
+									    i_set, 
+									    GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+									    _col_types_views,
 									    error);
 		if (model_views == NULL)
 			retval = FALSE;
 		else {
 			copy.table_name = "_views";
-			gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
+			gda_meta_store_set_reserved_keywords_func (store,
+								   _gda_mysql_reuseable_get_reserved_keywords_func
+								   ((GdaProviderReuseable*) rdata));
 			retval = gda_meta_store_modify_with_context (store, &copy, model_views, error);
 			g_object_unref (G_OBJECT (model_views));
 		}
@@ -826,28 +874,38 @@ _gda_mysql_meta_tables_views (GdaServerProvider  *prov,
 	} else {
 		if (!gda_holder_set_value (gda_set_get_holder (i_set, "name"), table_name_n, error))
 			return FALSE;
-		model_tables = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_TABLE_NAMED], i_set, 
-									    GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types_tables,
-									    error);
+		model_tables = gda_connection_statement_execute_select_full (cnc,
+									     internal_stmt[I_STMT_TABLE_NAMED],
+									     i_set, 
+									     GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+									     _col_types_tables,
+									     error);
 		if (model_tables == NULL)
 			retval = FALSE;
 		else {
 			copy.table_name = "_tables";
-			gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
+			gda_meta_store_set_reserved_keywords_func (store,
+								   _gda_mysql_reuseable_get_reserved_keywords_func
+								   ((GdaProviderReuseable*) rdata));
 			retval = gda_meta_store_modify_with_context (store, &copy, model_tables, error);
 			g_object_unref (G_OBJECT(model_tables));
 		}
 
 		if (!retval)
 			return FALSE;
-		model_views = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_VIEW_NAMED], i_set, 
-									    GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types_views,
+		model_views = gda_connection_statement_execute_select_full (cnc,
+									    internal_stmt[I_STMT_VIEW_NAMED],
+									    i_set, 
+									    GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+									    _col_types_views,
 									    error);
 		if (model_views == NULL)
 			retval = FALSE;
 		else {
 			copy.table_name = "_views";
-			gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
+			gda_meta_store_set_reserved_keywords_func (store,
+								   _gda_mysql_reuseable_get_reserved_keywords_func
+								   ((GdaProviderReuseable*) rdata));
 			retval = gda_meta_store_modify_with_context (store, &copy, model_views, error);
 			g_object_unref (G_OBJECT(model_views));
 		}
@@ -990,29 +1048,26 @@ _gda_mysql_meta__columns (GdaServerProvider  *prov,
 			  GdaMetaContext     *context,
 			  GError            **error)
 {
-	GType col_types[] = {
-		0, 0, 0, 0, G_TYPE_INT, G_TYPE_STRING,
-		G_TYPE_BOOLEAN,
-		G_TYPE_STRING, 0, 0, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, 0, 0, 0, 0, 0, 0, G_TYPE_STRING, G_TYPE_BOOLEAN,
-		G_TYPE_STRING,
-		G_TYPE_NONE
-	};
 	GdaDataModel *model, *proxy;
 	gboolean retval = TRUE;
 	/* Check correct mysql server version. */
-	MysqlConnectionData *cdata;
-	cdata = (MysqlConnectionData *) gda_connection_internal_get_provider_data (cnc);
-	if (!cdata)
+	GdaMysqlReuseable *rdata;
+	rdata = GDA_MYSQL_GET_REUSEABLE_DATA (gda_connection_internal_get_provider_data (cnc));
+	if (!rdata)
 		return FALSE;
-	if (cdata->version_long < 50000) {
+	if ((rdata->version_long == 0) && ! _gda_mysql_compute_version (cnc, rdata, error))
+		return FALSE;
+	if (rdata->version_long < 50000) {
 		g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_SERVER_VERSION_ERROR,
 			     "%s", _("Mysql version 5.0 at least is required"));
 		return FALSE;
 	}
 
 	/* Use a prepared statement for the "base" model. */
-	model = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_COLUMNS_ALL], NULL,
-							      GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types, error);
+	model = gda_connection_statement_execute_select_full (cnc,
+							      internal_stmt[I_STMT_COLUMNS_ALL], NULL,
+							      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+							      _col_types_columns, error);
 	if (model == NULL)
 		retval = FALSE;
 	else {
@@ -1036,7 +1091,9 @@ _gda_mysql_meta__columns (GdaServerProvider  *prov,
 		}
 
 		if (retval) {
-			gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
+			gda_meta_store_set_reserved_keywords_func (store,
+								   _gda_mysql_reuseable_get_reserved_keywords_func
+								   ((GdaProviderReuseable*) rdata));
 			retval = gda_meta_store_modify_with_context (store, context, proxy, error);
 		}
 
@@ -1057,21 +1114,16 @@ _gda_mysql_meta_columns (GdaServerProvider  *prov,
 			 const GValue       *table_schema, 
 			 const GValue       *table_name)
 {
-	GType col_types[] = {
-		0, 0, 0, 0, G_TYPE_INT, G_TYPE_STRING,
-		G_TYPE_BOOLEAN,
-		G_TYPE_STRING, 0, 0, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, 0, 0, 0, 0, 0, 0, G_TYPE_STRING, G_TYPE_BOOLEAN,
-		G_TYPE_STRING,
-		G_TYPE_NONE
-	};
 	GdaDataModel *model, *proxy;
 	gboolean retval;
 	/* Check correct mysql server version. */
-	MysqlConnectionData *cdata;
-	cdata = (MysqlConnectionData *) gda_connection_internal_get_provider_data (cnc);
-	if (!cdata)
+	GdaMysqlReuseable *rdata;
+	rdata = GDA_MYSQL_GET_REUSEABLE_DATA (gda_connection_internal_get_provider_data (cnc));
+	if (!rdata)
 		return FALSE;
-	if (cdata->version_long < 50000) {
+	if ((rdata->version_long == 0) && ! _gda_mysql_compute_version (cnc, rdata, error))
+		return FALSE;
+	if (rdata->version_long < 50000) {
 		g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_SERVER_VERSION_ERROR,
 			     "%s", _("Mysql version 5.0 at least is required"));
 		return FALSE;
@@ -1085,8 +1137,11 @@ _gda_mysql_meta_columns (GdaServerProvider  *prov,
 	if (!gda_holder_set_value (gda_set_get_holder (i_set, "name"), table_name, error))
 		return FALSE;
 
-	model = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_COLUMNS_OF_TABLE], i_set,
-							      GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types, error);
+	model = gda_connection_statement_execute_select_full (cnc,
+							      internal_stmt[I_STMT_COLUMNS_OF_TABLE],
+							      i_set,
+							      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+							      _col_types_columns, error);
 	if (model == NULL)
 		retval = FALSE;
 	else {
@@ -1110,7 +1165,9 @@ _gda_mysql_meta_columns (GdaServerProvider  *prov,
 		}
 
 		if (retval) {
-			gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
+			gda_meta_store_set_reserved_keywords_func (store,
+								   _gda_mysql_reuseable_get_reserved_keywords_func
+								   ((GdaProviderReuseable*) rdata));
 			retval = gda_meta_store_modify (store, context->table_name, proxy,
 							"table_schema=##schema::string AND table_name=##name::string",
 							error,
@@ -1133,21 +1190,29 @@ _gda_mysql_meta__view_cols (GdaServerProvider  *prov,
 	GdaDataModel *model;
 	gboolean retval;
 	/* Check correct mysql server version. */
-	MysqlConnectionData *cdata;
-	cdata = (MysqlConnectionData *) gda_connection_internal_get_provider_data (cnc);
-	if (!cdata)
+	GdaMysqlReuseable *rdata;
+	rdata = GDA_MYSQL_GET_REUSEABLE_DATA (gda_connection_internal_get_provider_data (cnc));
+	if (!rdata)
+		return FALSE;
+	if ((rdata->version_long == 0) && ! _gda_mysql_compute_version (cnc, rdata, error))
 		return FALSE;
-	if (cdata->version_long < 50000) {
+	if (rdata->version_long < 50000) {
 		g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_SERVER_VERSION_ERROR,
 			     "%s", _("Mysql version 5.0 at least is required"));
 		return FALSE;
 	}
 
-	model = gda_connection_statement_execute_select	(cnc, internal_stmt[I_STMT_VIEWS_COLUMNS_ALL], NULL, error);
+	model = gda_connection_statement_execute_select_full (cnc,
+							      internal_stmt[I_STMT_VIEWS_COLUMNS_ALL],
+							      NULL, 
+							      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+							      _col_types_view_column_usage, error);
 	if (model == NULL)
 		retval = FALSE;
 	else {
-		gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
+		gda_meta_store_set_reserved_keywords_func (store,
+							   _gda_mysql_reuseable_get_reserved_keywords_func
+							   ((GdaProviderReuseable*) rdata));
 		retval = gda_meta_store_modify_with_context (store, context, model, error);
 		g_object_unref (G_OBJECT(model));
 	}
@@ -1167,9 +1232,9 @@ _gda_mysql_meta_view_cols (GdaServerProvider  *prov,
 {
 	GdaDataModel *model;
 	gboolean retval;
-	MysqlConnectionData *cdata;
-	cdata = (MysqlConnectionData *) gda_connection_internal_get_provider_data (cnc);
-	if (!cdata)
+	GdaMysqlReuseable *rdata;
+	rdata = GDA_MYSQL_GET_REUSEABLE_DATA (gda_connection_internal_get_provider_data (cnc));
+	if (!rdata)
 		return FALSE;
 
 	if (!gda_holder_set_value (gda_set_get_holder (i_set, "cat"), view_catalog, error))
@@ -1178,11 +1243,17 @@ _gda_mysql_meta_view_cols (GdaServerProvider  *prov,
 		return FALSE;
 	if (!gda_holder_set_value (gda_set_get_holder (i_set, "name"), view_name, error))
 		return FALSE;
-	model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_VIEWS_COLUMNS], i_set, error);
+	model = gda_connection_statement_execute_select_full (cnc,
+							      internal_stmt[I_STMT_VIEWS_COLUMNS],
+							      i_set, 
+							      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+							      _col_types_view_column_usage, error);
 	if (model == NULL)
 		retval = FALSE;
 	else {
-		gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
+		gda_meta_store_set_reserved_keywords_func (store,
+							   _gda_mysql_reuseable_get_reserved_keywords_func
+							   ((GdaProviderReuseable*) rdata));
 		retval = gda_meta_store_modify_with_context (store, context, model, error);
 		g_object_unref (G_OBJECT(model));
 
@@ -1198,23 +1269,24 @@ _gda_mysql_meta__constraints_tab (GdaServerProvider  *prov,
 				  GdaMetaContext     *context,
 				  GError            **error)
 {
-	GType col_types[] = {
-		0, 0, 0, 0, 0, 0, 0, 0,
-		G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_NONE
-	};
 	GdaDataModel *model;
 	gboolean retval;
-	MysqlConnectionData *cdata;
-	cdata = (MysqlConnectionData *) gda_connection_internal_get_provider_data (cnc);
-	if (!cdata)
+	GdaMysqlReuseable *rdata;
+	rdata = GDA_MYSQL_GET_REUSEABLE_DATA (gda_connection_internal_get_provider_data (cnc));
+	if (!rdata)
 		return FALSE;
 
-	model = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_TABLES_CONSTRAINTS_ALL], NULL,
-							      GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types, error);
+	model = gda_connection_statement_execute_select_full (cnc,
+							      internal_stmt[I_STMT_TABLES_CONSTRAINTS_ALL],
+							      NULL,
+							      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+							      _col_types_table_constraints, error);
 	if (model == NULL)
 		retval = FALSE;
 	else {
-		gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
+		gda_meta_store_set_reserved_keywords_func (store,
+							   _gda_mysql_reuseable_get_reserved_keywords_func
+							   ((GdaProviderReuseable*) rdata));
 		retval = gda_meta_store_modify_with_context (store, context, model, error);
 		g_object_unref (G_OBJECT(model));
 	}
@@ -1233,15 +1305,11 @@ _gda_mysql_meta_constraints_tab (GdaServerProvider  *prov,
 				 const GValue       *table_name,
 				 const GValue       *constraint_name_n)
 {
-	GType col_types[] = {
-		0, 0, 0, 0, 0, 0, 0, 0,
-		G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_NONE
-	};
 	GdaDataModel *model;
 	gboolean retval;
-	MysqlConnectionData *cdata;
-	cdata = (MysqlConnectionData *) gda_connection_internal_get_provider_data (cnc);
-	if (!cdata)
+	GdaMysqlReuseable *rdata;
+	rdata = GDA_MYSQL_GET_REUSEABLE_DATA (gda_connection_internal_get_provider_data (cnc));
+	if (!rdata)
 		return FALSE;
 
 	if (!gda_holder_set_value (gda_set_get_holder (i_set, "cat"), table_catalog, error))
@@ -1251,11 +1319,17 @@ _gda_mysql_meta_constraints_tab (GdaServerProvider  *prov,
 	if (!gda_holder_set_value (gda_set_get_holder (i_set, "name"), table_name, error))
 		return FALSE;
 	if (!constraint_name_n) {
-		model = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_TABLES_CONSTRAINTS], i_set, GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types, error);
+		model = gda_connection_statement_execute_select_full (cnc,
+								      internal_stmt[I_STMT_TABLES_CONSTRAINTS],
+								      i_set,
+								      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+								      _col_types_table_constraints, error);
 		if (model == NULL)
 			retval = FALSE;
 		else {
-			gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
+			gda_meta_store_set_reserved_keywords_func (store,
+								   _gda_mysql_reuseable_get_reserved_keywords_func
+								   ((GdaProviderReuseable*) rdata));
 			retval = gda_meta_store_modify (store, context->table_name, model,
 							"table_schema = ##schema::string AND table_name = ##name::string",
 							error,
@@ -1265,11 +1339,17 @@ _gda_mysql_meta_constraints_tab (GdaServerProvider  *prov,
 	} else {
 		if (!gda_holder_set_value (gda_set_get_holder (i_set, "name2"), constraint_name_n, error))
 			return FALSE;
-		model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_TABLES_CONSTRAINTS_NAMED], i_set, error);
+		model = gda_connection_statement_execute_select_full (cnc,
+								      internal_stmt[I_STMT_TABLES_CONSTRAINTS_NAMED],
+								      i_set,
+								      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+								      _col_types_table_constraints, error);
 		if (model == NULL)
 			retval = FALSE;
 		else {
-			gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
+			gda_meta_store_set_reserved_keywords_func (store,
+								   _gda_mysql_reuseable_get_reserved_keywords_func
+								   ((GdaProviderReuseable*) rdata));
 			retval = gda_meta_store_modify (store, context->table_name, model,
 							"table_schema=##schema::string AND table_name=##name::string AND constraint_name=##name2::string",
 							error,
@@ -1288,19 +1368,27 @@ _gda_mysql_meta__constraints_ref (GdaServerProvider  *prov,
 				  GdaMetaContext     *context,
 				  GError            **error)
 {
-	MysqlConnectionData *cdata;
+	GdaMysqlReuseable *rdata;
 
-	cdata = (MysqlConnectionData*) gda_connection_internal_get_provider_data (cnc);
-	g_return_val_if_fail (cdata, FALSE);
+	rdata = GDA_MYSQL_GET_REUSEABLE_DATA (gda_connection_internal_get_provider_data (cnc));
+	g_return_val_if_fail (rdata, FALSE);
 
-	if (cdata->version_long >= 50110) {
+	if ((rdata->version_long == 0) && ! _gda_mysql_compute_version (cnc, rdata, error))
+		return FALSE;
+	if (rdata->version_long >= 50110) {
 		GdaDataModel *model;
 		gboolean retval;
-		model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_REF_CONSTRAINTS_ALL], NULL, error);
+		model = gda_connection_statement_execute_select_full (cnc,
+								      internal_stmt[I_STMT_REF_CONSTRAINTS_ALL],
+								      NULL,
+								      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+								      _col_types_referential_constraints, error);
 		if (model == NULL)
 			retval = FALSE;
 		else {
-			gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
+			gda_meta_store_set_reserved_keywords_func (store,
+								   _gda_mysql_reuseable_get_reserved_keywords_func
+								   ((GdaProviderReuseable*) rdata));
 			retval = gda_meta_store_modify_with_context (store, context, model, error);
 			g_object_unref (G_OBJECT(model));
 		}
@@ -1324,12 +1412,14 @@ _gda_mysql_meta_constraints_ref (GdaServerProvider  *prov,
 				 const GValue       *table_name, 
 				 const GValue       *constraint_name)
 {
-	MysqlConnectionData *cdata;
+	GdaMysqlReuseable *rdata;
 
-	cdata = (MysqlConnectionData*) gda_connection_internal_get_provider_data (cnc);
-	g_return_val_if_fail (cdata, FALSE);
+	rdata = GDA_MYSQL_GET_REUSEABLE_DATA (gda_connection_internal_get_provider_data (cnc));
+	g_return_val_if_fail (rdata, FALSE);
 
-	if (cdata->version_long >= 50110) {
+	if ((rdata->version_long == 0) && ! _gda_mysql_compute_version (cnc, rdata, error))
+		return FALSE;
+	if (rdata->version_long >= 50110) {
 		GdaDataModel *model;
 		gboolean retval;
 		
@@ -1342,11 +1432,17 @@ _gda_mysql_meta_constraints_ref (GdaServerProvider  *prov,
 			return FALSE;
 		if (!gda_holder_set_value (gda_set_get_holder (i_set, "name2"), constraint_name, error))
 			return FALSE;
-		model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_REF_CONSTRAINTS], i_set, error);
+		model = gda_connection_statement_execute_select_full (cnc,
+								      internal_stmt[I_STMT_REF_CONSTRAINTS],
+								      i_set,
+								      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+								      _col_types_referential_constraints, error);
 		if (model == NULL)
 			retval = FALSE;
 		else {
-			gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
+			gda_meta_store_set_reserved_keywords_func (store,
+								   _gda_mysql_reuseable_get_reserved_keywords_func
+								   ((GdaProviderReuseable*) rdata));
 			retval = gda_meta_store_modify (store, context->table_name, model,
 							"table_schema=##schema::string AND table_name=##name::string AND constraint_name=##name2::string",
 							error,
@@ -1370,23 +1466,24 @@ _gda_mysql_meta__key_columns (GdaServerProvider  *prov,
 			      GdaMetaContext     *context,
 			      GError            **error)
 {
-	GType col_types[] = {
-		0, 0, 0, 0, 0,
-		G_TYPE_INT, G_TYPE_NONE
-	};
 	GdaDataModel *model;
 	gboolean retval;
-	MysqlConnectionData *cdata;
-	cdata = (MysqlConnectionData *) gda_connection_internal_get_provider_data (cnc);
-	if (!cdata)
+	GdaMysqlReuseable *rdata;
+	rdata = GDA_MYSQL_GET_REUSEABLE_DATA (gda_connection_internal_get_provider_data (cnc));
+	if (!rdata)
 		return FALSE;
 
-	model = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_KEY_COLUMN_USAGE_ALL], NULL,
-							      GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types, error);
+	model = gda_connection_statement_execute_select_full (cnc,
+							      internal_stmt[I_STMT_KEY_COLUMN_USAGE_ALL],
+							      NULL,
+							      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+							      _col_types_key_column_usage, error);
 	if (model == NULL)
 		retval = FALSE;
 	else {
-		gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
+		gda_meta_store_set_reserved_keywords_func (store,
+							   _gda_mysql_reuseable_get_reserved_keywords_func
+							   ((GdaProviderReuseable*) rdata));
 		retval = gda_meta_store_modify_with_context (store, context, model, error);
 		g_object_unref (G_OBJECT(model));
 	}
@@ -1405,18 +1502,16 @@ _gda_mysql_meta_key_columns (GdaServerProvider  *prov,
 			     const GValue       *table_name,
 			     const GValue       *constraint_name)
 {
-	GType col_types[] = {
-		0, 0, 0, 0, 0,
-		G_TYPE_INT, G_TYPE_NONE
-	};
 	GdaDataModel *model;
 	gboolean retval;
 	/* Check correct mysql server version. */
-	MysqlConnectionData *cdata;
-	cdata = (MysqlConnectionData *) gda_connection_internal_get_provider_data (cnc);
-	if (!cdata)
+	GdaMysqlReuseable *rdata;
+	rdata = GDA_MYSQL_GET_REUSEABLE_DATA (gda_connection_internal_get_provider_data (cnc));
+	if (!rdata)
 		return FALSE;
-	if (cdata->version_long < 50000) {
+	if ((rdata->version_long == 0) && ! _gda_mysql_compute_version (cnc, rdata, error))
+		return FALSE;
+	if (rdata->version_long < 50000) {
 		g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_SERVER_VERSION_ERROR,
 			     "%s", _("Mysql version 5.0 at least is required"));
 		return FALSE;
@@ -1431,11 +1526,17 @@ _gda_mysql_meta_key_columns (GdaServerProvider  *prov,
 		return FALSE;
 	if (!gda_holder_set_value (gda_set_get_holder (i_set, "name2"), constraint_name, error))
 		return FALSE;
-	model = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_KEY_COLUMN_USAGE], i_set, GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types, error);
+	model = gda_connection_statement_execute_select_full (cnc,
+							      internal_stmt[I_STMT_KEY_COLUMN_USAGE],
+							      i_set, GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+							      _col_types_key_column_usage,
+							      error);
 	if (model == NULL)
 		retval = FALSE;
 	else {
-		gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
+		gda_meta_store_set_reserved_keywords_func (store,
+							   _gda_mysql_reuseable_get_reserved_keywords_func
+							   ((GdaProviderReuseable*) rdata));
 		retval = gda_meta_store_modify (store, context->table_name, model,
 						"table_schema=##schema::string AND table_name=##name::string AND constraint_name=##name2::string",
 						error,
@@ -1483,21 +1584,29 @@ _gda_mysql_meta__triggers (GdaServerProvider  *prov,
 	GdaDataModel *model;
 	gboolean retval;
 	/* Check correct mysql server version. */
-	MysqlConnectionData *cdata;
-	cdata = (MysqlConnectionData *) gda_connection_internal_get_provider_data (cnc);
-	if (!cdata)
+	GdaMysqlReuseable *rdata;
+	rdata = GDA_MYSQL_GET_REUSEABLE_DATA (gda_connection_internal_get_provider_data (cnc));
+	if (!rdata)
+		return FALSE;
+	if ((rdata->version_long == 0) && ! _gda_mysql_compute_version (cnc, rdata, error))
 		return FALSE;
-	if (cdata->version_long < 50000) {
+	if (rdata->version_long < 50000) {
 		g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_SERVER_VERSION_ERROR,
 			     "%s", _("Mysql version 5.0 at least is required"));
 		return FALSE;
 	}
 
-	model = gda_connection_statement_execute_select	(cnc, internal_stmt[I_STMT_TRIGGERS_ALL], NULL, error);
+	model = gda_connection_statement_execute_select_full (cnc,
+							      internal_stmt[I_STMT_TRIGGERS_ALL],
+							      NULL,
+							      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+							      _col_types_triggers, error);
 	if (model == NULL)
 		retval = FALSE;
 	else {
-		gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
+		gda_meta_store_set_reserved_keywords_func (store,
+							   _gda_mysql_reuseable_get_reserved_keywords_func
+							   ((GdaProviderReuseable*) rdata));
 		retval = gda_meta_store_modify_with_context (store, context, model, error);
 		g_object_unref (G_OBJECT(model));
 	}
@@ -1518,11 +1627,13 @@ _gda_mysql_meta_triggers (GdaServerProvider  *prov,
 	GdaDataModel *model;
 	gboolean retval;
 	/* Check correct mysql server version. */
-	MysqlConnectionData *cdata;
-	cdata = (MysqlConnectionData *) gda_connection_internal_get_provider_data (cnc);
-	if (!cdata)
+	GdaMysqlReuseable *rdata;
+	rdata = GDA_MYSQL_GET_REUSEABLE_DATA (gda_connection_internal_get_provider_data (cnc));
+	if (!rdata)
 		return FALSE;
-	if (cdata->version_long < 50000) {
+	if ((rdata->version_long == 0) && ! _gda_mysql_compute_version (cnc, rdata, error))
+		return FALSE;
+	if (rdata->version_long < 50000) {
 		g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_SERVER_VERSION_ERROR,
 			     "%s", _("Mysql version 5.0 at least is required"));
 		return FALSE;
@@ -1534,11 +1645,17 @@ _gda_mysql_meta_triggers (GdaServerProvider  *prov,
 		return FALSE;
 	if (!gda_holder_set_value (gda_set_get_holder (i_set, "name"), table_name, error))
 		return FALSE;
-	model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_TRIGGERS], i_set, error);
+	model = gda_connection_statement_execute_select_full (cnc,
+							      internal_stmt[I_STMT_TRIGGERS],
+							      i_set,
+							      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+							      _col_types_triggers, error);
 	if (model == NULL)
 		retval = FALSE;
 	else {
-		gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
+		gda_meta_store_set_reserved_keywords_func (store,
+							   _gda_mysql_reuseable_get_reserved_keywords_func
+							   ((GdaProviderReuseable*) rdata));
 		retval = gda_meta_store_modify_with_context (store, context, model, error);
 		g_object_unref (G_OBJECT(model));
 
@@ -1556,16 +1673,22 @@ _gda_mysql_meta__routines (GdaServerProvider  *prov,
 {
 	GdaDataModel *model;
 	gboolean retval;
-	MysqlConnectionData *cdata;
-	cdata = (MysqlConnectionData *) gda_connection_internal_get_provider_data (cnc);
-	if (!cdata)
+	GdaMysqlReuseable *rdata;
+	rdata = GDA_MYSQL_GET_REUSEABLE_DATA (gda_connection_internal_get_provider_data (cnc));
+	if (!rdata)
 		return FALSE;
 
-	model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_ROUTINES_ALL], NULL, error);
+	model = gda_connection_statement_execute_select_full (cnc,
+							      internal_stmt[I_STMT_ROUTINES_ALL],
+							      NULL,
+							      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+							      _col_types_routines, error);
 	if (model == NULL)
 		retval = FALSE;
 	else {
-		gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
+		gda_meta_store_set_reserved_keywords_func (store,
+							   _gda_mysql_reuseable_get_reserved_keywords_func
+							   ((GdaProviderReuseable*) rdata));
 		retval = gda_meta_store_modify_with_context (store, context, model, error);
 		g_object_unref (G_OBJECT(model));
 	}
@@ -1586,11 +1709,13 @@ _gda_mysql_meta_routines (GdaServerProvider  *prov,
 	GdaDataModel *model;
 	gboolean retval;
 	/* Check correct mysql server version. */
-	MysqlConnectionData *cdata;
-	cdata = (MysqlConnectionData *) gda_connection_internal_get_provider_data (cnc);
-	if (!cdata)
+	GdaMysqlReuseable *rdata;
+	rdata = GDA_MYSQL_GET_REUSEABLE_DATA (gda_connection_internal_get_provider_data (cnc));
+	if (!rdata)
+		return FALSE;
+	if ((rdata->version_long == 0) && ! _gda_mysql_compute_version (cnc, rdata, error))
 		return FALSE;
-	if (cdata->version_long < 50000) {
+	if (rdata->version_long < 50000) {
 		g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_SERVER_VERSION_ERROR,
 			     "%s", _("Mysql version 5.0 at least is required"));
 		return FALSE;
@@ -1603,13 +1728,24 @@ _gda_mysql_meta_routines (GdaServerProvider  *prov,
 	if (routine_name_n != NULL) {
 		if (!gda_holder_set_value (gda_set_get_holder (i_set, "name"), routine_name_n, error))
 			return FALSE;
-		model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_ROUTINES_ONE], i_set, error);
-	} else
-		model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_ROUTINES], i_set, error);
+		model = gda_connection_statement_execute_select_full (cnc,
+								      internal_stmt[I_STMT_ROUTINES_ONE],
+								      i_set,
+								      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+								      _col_types_routines, error);
+	}
+	else
+		model = gda_connection_statement_execute_select_full (cnc,
+								      internal_stmt[I_STMT_ROUTINES],
+								      i_set,
+								      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+								      _col_types_routines, error);
 	if (model == NULL)
 		retval = FALSE;
 	else {
-		gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
+		gda_meta_store_set_reserved_keywords_func (store,
+							   _gda_mysql_reuseable_get_reserved_keywords_func
+							   ((GdaProviderReuseable*) rdata));
 		retval = gda_meta_store_modify_with_context (store, context, model, error);
 		g_object_unref (G_OBJECT(model));
 
diff --git a/providers/mysql/gda-mysql-meta.h b/providers/reuseable/mysql/gda-mysql-meta.h
similarity index 100%
rename from providers/mysql/gda-mysql-meta.h
rename to providers/reuseable/mysql/gda-mysql-meta.h
diff --git a/providers/mysql/gda-mysql-parser.c b/providers/reuseable/mysql/gda-mysql-parser.c
similarity index 100%
rename from providers/mysql/gda-mysql-parser.c
rename to providers/reuseable/mysql/gda-mysql-parser.c
diff --git a/providers/mysql/gda-mysql-parser.h b/providers/reuseable/mysql/gda-mysql-parser.h
similarity index 100%
rename from providers/mysql/gda-mysql-parser.h
rename to providers/reuseable/mysql/gda-mysql-parser.h
diff --git a/providers/reuseable/mysql/gda-mysql-reuseable.c b/providers/reuseable/mysql/gda-mysql-reuseable.c
new file mode 100644
index 0000000..41cc7eb
--- /dev/null
+++ b/providers/reuseable/mysql/gda-mysql-reuseable.c
@@ -0,0 +1,299 @@
+/* GDA mysql provider
+ * Copyright (C) 1998 - 2009 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 <libgda/gda-sql-builder.h>
+#include "gda-mysql-reuseable.h"
+#include "gda-mysql-parser.h"
+
+#include <libgda/sqlite/keywords_hash.h>
+#include "keywords_hash.c" /* this one is dynamically generated */
+
+/*
+ * Reuseable interface entry point
+ */
+static GdaProviderReuseableOperations
+_gda_mysql_reuseable = {
+	_gda_mysql_reuseable_new_data,
+	_gda_mysql_reuseable_reset_data,
+	_gda_mysql_reuseable_get_g_type,
+	_gda_mysql_reuseable_get_reserved_keywords_func,
+	_gda_mysql_reuseable_create_parser,
+	{
+		._info = _gda_mysql_meta__info,
+		._btypes = _gda_mysql_meta__btypes,
+		._udt = _gda_mysql_meta__udt,
+		.udt = _gda_mysql_meta_udt,
+		._udt_cols = _gda_mysql_meta__udt_cols,
+		.udt_cols = _gda_mysql_meta_udt_cols,
+		._enums = _gda_mysql_meta__enums,
+		.enums = _gda_mysql_meta_enums,
+		._domains = _gda_mysql_meta__domains,
+		.domains = _gda_mysql_meta_domains,
+		._constraints_dom = _gda_mysql_meta__constraints_dom,
+		.constraints_dom = _gda_mysql_meta_constraints_dom,
+		._el_types = _gda_mysql_meta__el_types,
+		.el_types = _gda_mysql_meta_el_types,
+		._collations = _gda_mysql_meta__collations,
+		.collations = _gda_mysql_meta_collations,
+		._character_sets = _gda_mysql_meta__character_sets,
+		.character_sets = _gda_mysql_meta_character_sets,
+		._schemata = _gda_mysql_meta__schemata,
+		.schemata = _gda_mysql_meta_schemata,
+		._tables_views = _gda_mysql_meta__tables_views,
+		.tables_views = _gda_mysql_meta_tables_views,
+		._columns = _gda_mysql_meta__columns,
+		.columns = _gda_mysql_meta_columns,
+		._view_cols = _gda_mysql_meta__view_cols,
+		.view_cols = _gda_mysql_meta_view_cols,
+		._constraints_tab = _gda_mysql_meta__constraints_tab,
+		.constraints_tab = _gda_mysql_meta_constraints_tab,
+		._constraints_ref = _gda_mysql_meta__constraints_ref,
+		.constraints_ref = _gda_mysql_meta_constraints_ref,
+		._key_columns = _gda_mysql_meta__key_columns,
+		.key_columns = _gda_mysql_meta_key_columns,
+		._check_columns = _gda_mysql_meta__check_columns,
+		.check_columns = _gda_mysql_meta_check_columns,
+		._triggers = _gda_mysql_meta__triggers,
+		.triggers = _gda_mysql_meta_triggers,
+		._routines = _gda_mysql_meta__routines,
+		.routines = _gda_mysql_meta_routines,
+		._routine_col = _gda_mysql_meta__routine_col,
+		.routine_col = _gda_mysql_meta_routine_col,
+		._routine_par = _gda_mysql_meta__routine_par,
+		.routine_par = _gda_mysql_meta_routine_par
+	}
+};
+
+GdaProviderReuseableOperations *
+_gda_mysql_reuseable_get_ops (void)
+{
+	return &_gda_mysql_reuseable;
+}
+
+#ifdef GDA_DEBUG
+void
+_gda_mysql_test_keywords (void)
+{
+	V50test_keywords();
+        V51test_keywords();
+        V54test_keywords();
+        V60test_keywords();
+}
+#endif
+
+GdaProviderReuseable *
+_gda_mysql_reuseable_new_data (void)
+{
+	GdaMysqlReuseable *reuseable;
+	reuseable = g_new0 (GdaMysqlReuseable, 1);
+	reuseable->version_long = 0;
+	reuseable->identifiers_case_sensitive = FALSE;
+	_gda_mysql_provider_meta_init (NULL);
+
+	((GdaProviderReuseable*)reuseable)->operations = &_gda_mysql_reuseable;
+
+	return (GdaProviderReuseable*) reuseable;
+}
+
+void
+_gda_mysql_reuseable_reset_data (GdaProviderReuseable *rdata)
+{
+	GdaMysqlReuseable *reuseable;
+	reuseable = (GdaMysqlReuseable*) rdata;
+
+	memset (reuseable, 0, sizeof (GdaMysqlReuseable));
+}
+
+static GdaDataModel *
+execute_select (GdaConnection *cnc, GdaMysqlReuseable *rdata, const gchar *sql)
+{
+	GdaSqlParser *parser;
+	GdaStatement *stmt;
+	GdaDataModel *model;
+	parser = _gda_mysql_reuseable_create_parser ((GdaProviderReuseable*) rdata);
+	
+	stmt = gda_sql_parser_parse_string (parser, sql, NULL, NULL);
+	g_object_unref (parser);
+	g_assert (stmt);
+
+	model = gda_connection_statement_execute_select (cnc, stmt, NULL, NULL);
+	g_object_unref (stmt);
+
+	return model;
+}
+
+gboolean
+_gda_mysql_compute_version (GdaConnection *cnc, GdaMysqlReuseable *rdata, GError **error)
+{
+	GdaSqlBuilder *b;
+	GdaStatement *stmt;
+	GdaDataModel *model;
+
+	b = gda_sql_builder_new (GDA_SQL_STATEMENT_SELECT);
+        gda_sql_builder_add_function (b, 1, "version", 0);
+        gda_sql_builder_add_field (b, 1, 0);
+	stmt = gda_sql_builder_get_statement (b, NULL);
+	g_object_unref (b);
+	g_assert (stmt);
+
+	model = gda_connection_statement_execute_select (cnc, stmt, NULL, error);
+	g_object_unref (stmt);
+	if (!model)
+		return FALSE;
+	
+	const GValue *cvalue;
+	cvalue = gda_data_model_get_value_at (model, 0, 0, NULL);
+	if (!cvalue) {
+		g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+                             GDA_SERVER_PROVIDER_INTERNAL_ERROR, "%s",
+                             _("Can't import data from web server"));
+		g_object_unref (model);
+		return FALSE;
+	}
+
+	const gchar *str;
+	str = g_value_get_string (cvalue);
+
+	/* analyse string */
+	const gchar *ptr;
+	rdata->version_long = 0;
+
+	/* go on  the first digit of version number */
+        ptr = str;
+	if (*ptr) {
+		/* scan version parts */
+		GdaProviderReuseable *prdata = (GdaProviderReuseable*) rdata;
+		sscanf (ptr, "%d.%d.%d", &(prdata->major),  &(prdata->minor),  &(prdata->micro));
+
+		/* elaborate the version number as a long int, similar to mysql_get_server_version() */
+		rdata->version_long = prdata->major * 10000 + prdata->minor *100 + prdata->micro;
+
+	}
+
+	g_object_unref (model);
+
+	/*
+	g_print ("VERSIONS: [%ld] [%d.%d.%d]\n", rdata->version_long,
+		 ((GdaProviderReuseable*)rdata)->major,
+		 ((GdaProviderReuseable*)rdata)->minor,
+		 ((GdaProviderReuseable*)rdata)->micro);
+	*/
+	return TRUE;
+}
+
+static GType
+mysql_name_to_g_type (const gchar *name, const gchar *conv_func_name)
+{
+	/* default built in data types */
+	if (!strcmp (name, "bool"))
+		return G_TYPE_BOOLEAN;
+	else if (!strcmp (name, "int8"))
+		return G_TYPE_INT64;
+	else if (!strcmp (name, "int4") || !strcmp (name, "abstime"))
+		return G_TYPE_INT;
+	else if (!strcmp (name, "int2"))
+		return GDA_TYPE_SHORT;
+	else if (!strcmp (name, "float4"))
+		return G_TYPE_FLOAT;
+	else if (!strcmp (name, "float8"))
+		return G_TYPE_DOUBLE;
+	else if (!strcmp (name, "numeric"))
+		return GDA_TYPE_NUMERIC;
+	else if (!strncmp (name, "timestamp", 9))
+		return GDA_TYPE_TIMESTAMP;
+	else if (!strcmp (name, "date"))
+		return G_TYPE_DATE;
+	else if (!strncmp (name, "time", 4))
+		return GDA_TYPE_TIME;
+	else if (!strcmp (name, "point"))
+		return GDA_TYPE_GEOMETRIC_POINT;
+	else if (!strcmp (name, "oid"))
+		return GDA_TYPE_BLOB;
+	else if (!strcmp (name, "bytea"))
+		return GDA_TYPE_BINARY;
+
+	/* other data types, using the conversion function name as a hint */
+	if (!conv_func_name)
+		return G_TYPE_STRING;
+
+	if (!strncmp (conv_func_name, "int2", 4))
+		return GDA_TYPE_SHORT;
+	if (!strncmp (conv_func_name, "int4", 4))
+		return G_TYPE_INT;
+	if (!strncmp (conv_func_name, "int8", 4))
+		return G_TYPE_INT64;
+	if (!strncmp (conv_func_name, "float4", 6))
+		return G_TYPE_FLOAT;
+	if (!strncmp (conv_func_name, "float8", 6))
+		return G_TYPE_DOUBLE;
+	if (!strncmp (conv_func_name, "timestamp", 9))
+		return GDA_TYPE_TIMESTAMP;
+	if (!strncmp (conv_func_name, "time", 4))
+		return GDA_TYPE_TIME;
+	if (!strncmp (conv_func_name, "date", 4))
+		return G_TYPE_DATE;
+	if (!strncmp (conv_func_name, "bool", 4))
+		return G_TYPE_BOOLEAN;
+	if (!strncmp (conv_func_name, "oid", 3))
+		return GDA_TYPE_BLOB;
+	if (!strncmp (conv_func_name, "bytea", 5))
+		return GDA_TYPE_BINARY;
+	return GDA_TYPE_NULL;
+}
+
+GType
+_gda_mysql_reuseable_get_g_type (GdaConnection *cnc, GdaProviderReuseable *rdata, const gchar *db_type)
+{
+	g_return_val_if_fail (db_type, GDA_TYPE_NULL);
+
+	return mysql_name_to_g_type (db_type, NULL);
+}
+
+
+GdaSqlReservedKeywordsFunc
+_gda_mysql_reuseable_get_reserved_keywords_func (GdaProviderReuseable *rdata)
+{
+	if (rdata) {
+                switch (rdata->major) {
+                case 5:
+                        if (rdata->minor == 1)
+                                return V51is_keyword;
+                        if (rdata->minor == 0)
+                                return V50is_keyword;
+                        return V54is_keyword;
+                case 6:
+                default:
+                        return V60is_keyword;
+                break;
+                }
+        }
+        return V60is_keyword;
+}
+
+GdaSqlParser *
+_gda_mysql_reuseable_create_parser (GdaProviderReuseable *rdata)
+{
+	return GDA_SQL_PARSER (g_object_new (GDA_TYPE_MYSQL_PARSER, NULL));
+}
diff --git a/providers/reuseable/mysql/gda-mysql-reuseable.h b/providers/reuseable/mysql/gda-mysql-reuseable.h
new file mode 100644
index 0000000..6218b61
--- /dev/null
+++ b/providers/reuseable/mysql/gda-mysql-reuseable.h
@@ -0,0 +1,72 @@
+/* GDA provider
+ * Copyright (C) 2009 The GNOME Foundation.
+ *
+ * AUTHORS:
+ *         Vivien Malerba <malerba gnome-db org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __GDA_MYSQL_REUSEABLE_H__
+#define __GDA_MYSQL_REUSEABLE_H__
+
+#include "../gda-provider-reuseable.h"
+#include "gda-mysql-meta.h"
+
+G_BEGIN_DECLS
+
+/*
+ * Specific structure for MysqlQL
+ *
+ * Note: each GdaMysqlTypeOid is managed by the types_oid_hash hash table, and not by the types_dbtype_hash
+ * even though it's also referenced there.
+ */
+typedef struct {
+	GdaProviderReuseable parent;
+	
+	/* Backend version (to which we're connected). */
+        unsigned long     version_long;
+
+        /* specifies how case sensitiveness is */
+        gboolean          identifiers_case_sensitive;
+} GdaMysqlReuseable;
+
+/*
+ * Reuseable implementation
+ */
+GdaProviderReuseable *_gda_mysql_reuseable_new_data (void);
+void _gda_mysql_reuseable_reset_data (GdaProviderReuseable *rdata);
+GType _gda_mysql_reuseable_get_g_type (GdaConnection *cnc, GdaProviderReuseable *rdata, const gchar *db_type);
+GdaSqlReservedKeywordsFunc _gda_mysql_reuseable_get_reserved_keywords_func (GdaProviderReuseable *rdata);
+GdaSqlParser *_gda_mysql_reuseable_create_parser (GdaProviderReuseable *rdata);
+
+/*
+ * entry point
+ */
+GdaProviderReuseableOperations *_gda_mysql_reuseable_get_ops (void);
+
+/*
+ * Specific API
+ */
+gboolean            _gda_mysql_compute_version (GdaConnection *cnc, GdaMysqlReuseable *rdata, GError **error);
+
+#ifdef GDA_DEBUG
+void                _gda_mysql_test_keywords (void);
+#endif
+
+G_END_DECLS
+
+#endif
+
diff --git a/providers/mysql/gen_def.c b/providers/reuseable/mysql/gen_def.c
similarity index 100%
rename from providers/mysql/gen_def.c
rename to providers/reuseable/mysql/gen_def.c
diff --git a/providers/mysql/keywords_V50.list b/providers/reuseable/mysql/keywords_V50.list
similarity index 100%
rename from providers/mysql/keywords_V50.list
rename to providers/reuseable/mysql/keywords_V50.list
diff --git a/providers/mysql/keywords_V51.list b/providers/reuseable/mysql/keywords_V51.list
similarity index 100%
rename from providers/mysql/keywords_V51.list
rename to providers/reuseable/mysql/keywords_V51.list
diff --git a/providers/mysql/keywords_V54.list b/providers/reuseable/mysql/keywords_V54.list
similarity index 100%
rename from providers/mysql/keywords_V54.list
rename to providers/reuseable/mysql/keywords_V54.list
diff --git a/providers/mysql/keywords_V60.list b/providers/reuseable/mysql/keywords_V60.list
similarity index 100%
rename from providers/mysql/keywords_V60.list
rename to providers/reuseable/mysql/keywords_V60.list
diff --git a/providers/mysql/parser.y b/providers/reuseable/mysql/parser.y
similarity index 100%
rename from providers/mysql/parser.y
rename to providers/reuseable/mysql/parser.y
diff --git a/providers/reuseable/postgres/gda-postgres-meta.c b/providers/reuseable/postgres/gda-postgres-meta.c
index eee8196..cac796f 100644
--- a/providers/reuseable/postgres/gda-postgres-meta.c
+++ b/providers/reuseable/postgres/gda-postgres-meta.c
@@ -1,5 +1,5 @@
 /* GDA postgres provider
- * Copyright (C) 2008 The GNOME Foundation.
+ * Copyright (C) 2008 - 2009 The GNOME Foundation.
  *
  * AUTHORS:
  *         Vivien Malerba <malerba gnome-db org>
@@ -22,7 +22,9 @@
 
 #include <string.h>
 #include "gda-postgres-meta.h"
-#include <libgda/libgda.h>
+#include <libgda/gda-set.h>
+#include <libgda/gda-holder.h>
+#include <libgda/gda-data-proxy.h>
 #include <libgda/sql-parser/gda-sql-parser.h>
 #include <glib/gi18n-lib.h>
 #include <libgda/gda-server-provider-extra.h>
@@ -256,7 +258,7 @@ _gda_postgres_provider_meta_init (GdaServerProvider *provider)
 {
 	static GStaticMutex init_mutex = G_STATIC_MUTEX_INIT;
 	InternalStatementItem i;
-	static GdaSqlParser *parser = NULL;
+	GdaSqlParser *parser;
 
 	g_static_mutex_lock (&init_mutex);
 
@@ -303,7 +305,8 @@ _gda_postgres_meta__info (GdaServerProvider *prov, GdaConnection *cnc,
 							      internal_stmt[I_STMT_CATALOG],
 							      NULL, 
 							      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
-							      _col_types_information_schema_catalog_name, error);
+							      _col_types_information_schema_catalog_name,
+							      error);
 	if (!model)
 		return FALSE;
 
@@ -873,84 +876,6 @@ _gda_postgres_meta_schemata (GdaServerProvider *prov, GdaConnection *cnc,
 	return retval;
 }
 
-/* get the float version of a Postgres version which looks like:
- * PostgreSQL 7.2.2 on i686-pc-linux-gnu, compiled by GCC 2.96 => returns 7.22
- * PostgreSQL 7.3 on i686-pc-linux-gnu, compiled by GCC 2.95.3 => returns 7.3
- * WARNING: no serious test is made on the validity of the string
- */
-static gfloat
-get_pg_version_float (const gchar *str)
-{
-        gfloat retval = 0.;
-        const gchar *ptr;
-        gfloat div = 1;
-
-        if (!str)
-                return retval;
-
-        /* go on  the first digit of version number */
-        ptr = str;
-        while (*ptr != ' ')
-                ptr++;
-        ptr++;
-
-        /* elaborate the real version number */
-        while (*ptr != ' ') {
-                if (*ptr != '.') {
-                        retval += (*ptr - '0')/div;
-                        div *= 10;
-                }
-                ptr++;
-        }
-
-        return retval;
-}
-
-static gboolean
-compute_pg_version (GdaConnection *cnc, GdaPostgresReuseable *rdata, GError **error)
-{
-	GdaSqlBuilder *b;
-	GdaStatement *stmt;
-	GdaDataModel *model;
-
-	b = gda_sql_builder_new (GDA_SQL_STATEMENT_SELECT);
-        gda_sql_builder_add_function (b, 1, "version", 0);
-        gda_sql_builder_add_field (b, 1, 0);
-	stmt = gda_sql_builder_get_statement (b, NULL);
-	g_object_unref (b);
-	g_assert (stmt);
-
-	model = gda_connection_statement_execute_select (cnc, stmt, NULL, error);
-	g_object_unref (stmt);
-	if (!model)
-		return FALSE;
-	
-	const GValue *cvalue;
-	cvalue = gda_data_model_get_value_at (model, 0, 0, NULL);
-	if (!cvalue) {
-		g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
-                             GDA_SERVER_PROVIDER_INTERNAL_ERROR, "%s",
-                             _("Can't import data from web server"));
-		g_object_unref (model);
-		return FALSE;
-	}
-
-	const gchar *str;
-	str = g_value_get_string (cvalue);
-	rdata->version_float = get_pg_version_float (str);
-	((GdaProviderReuseable*)rdata)->version_major =
-		g_strdup_printf ("%d", (int) rdata->version_float);
-	((GdaProviderReuseable*)rdata)->version_minor =
-		g_strdup_printf ("%d", (int) ((rdata->version_float - (int) rdata->version_float) * 10));
-
-	g_object_unref (model);
-
-	/*g_print ("VERSIONS: [%f] [%s] [%s]\n", rdata->version_float,
-		 ((GdaProviderReuseable*)rdata)->version_major,
-		 ((GdaProviderReuseable*)rdata)->version_minor);*/
-	return TRUE;
-}
-
 gboolean
 _gda_postgres_meta__tables_views (GdaServerProvider *prov, GdaConnection *cnc, 
 				  GdaMetaStore *store, GdaMetaContext *context, GError **error)
@@ -963,7 +888,7 @@ _gda_postgres_meta__tables_views (GdaServerProvider *prov, GdaConnection *cnc,
 	rdata = GDA_POSTGRES_GET_REUSEABLE_DATA (gda_connection_internal_get_provider_data (cnc));
 	if (!rdata)
 		return FALSE;
-	if ((rdata->version_float == 0) && ! compute_pg_version (cnc, rdata, error))
+	if ((rdata->version_float == 0) && ! _gda_postgres_compute_version (cnc, rdata, error))
 		return FALSE;
 	if (rdata->version_float < 8.2) {
 		/* nothing for this version of PostgreSQL */
diff --git a/providers/reuseable/postgres/gda-postgres-reuseable.c b/providers/reuseable/postgres/gda-postgres-reuseable.c
index 75d8972..caba4e1 100644
--- a/providers/reuseable/postgres/gda-postgres-reuseable.c
+++ b/providers/reuseable/postgres/gda-postgres-reuseable.c
@@ -23,6 +23,7 @@
  */
 
 #include <glib/gi18n-lib.h>
+#include <libgda/gda-sql-builder.h>
 #include "gda-postgres-reuseable.h"
 #include "gda-postgres-parser.h"
 
@@ -122,7 +123,7 @@ _gda_postgres_test_keywords (void)
 #endif
 
 GdaProviderReuseable *
-_gda_postgres_reuseable_new_data (const gchar *major, const gchar *minor)
+_gda_postgres_reuseable_new_data (void)
 {
 	GdaPostgresReuseable *reuseable;
 	reuseable = g_new0 (GdaPostgresReuseable, 1);
@@ -140,6 +141,7 @@ _gda_postgres_reuseable_reset_data (GdaProviderReuseable *rdata)
 {
 	GdaPostgresReuseable *reuseable;
 	reuseable = (GdaPostgresReuseable*) rdata;
+
 	if (reuseable->types_dbtype_hash)
 		g_hash_table_destroy (reuseable->types_dbtype_hash);
 	if (reuseable->types_oid_hash)
@@ -169,6 +171,75 @@ execute_select (GdaConnection *cnc, GdaPostgresReuseable *rdata, const gchar *sq
 	return model;
 }
 
+gboolean
+_gda_postgres_compute_version (GdaConnection *cnc, GdaPostgresReuseable *rdata, GError **error)
+{
+	GdaSqlBuilder *b;
+	GdaStatement *stmt;
+	GdaDataModel *model;
+
+	b = gda_sql_builder_new (GDA_SQL_STATEMENT_SELECT);
+        gda_sql_builder_add_function (b, 1, "version", 0);
+        gda_sql_builder_add_field (b, 1, 0);
+	stmt = gda_sql_builder_get_statement (b, NULL);
+	g_object_unref (b);
+	g_assert (stmt);
+
+	model = gda_connection_statement_execute_select (cnc, stmt, NULL, error);
+	g_object_unref (stmt);
+	if (!model)
+		return FALSE;
+	
+	const GValue *cvalue;
+	cvalue = gda_data_model_get_value_at (model, 0, 0, NULL);
+	if (!cvalue) {
+		g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+                             GDA_SERVER_PROVIDER_INTERNAL_ERROR, "%s",
+                             _("Can't import data from web server"));
+		g_object_unref (model);
+		return FALSE;
+	}
+
+	const gchar *str;
+	str = g_value_get_string (cvalue);
+
+	/* analyse string */
+	const gchar *ptr;
+	rdata->version_float = 0;
+
+	/* go on  the first digit of version number */
+        ptr = str;
+        while (*ptr && *ptr != ' ')
+                ptr++;
+	if (*ptr) {
+		ptr++;
+		
+		/* scan version parts */
+		GdaProviderReuseable *prdata = (GdaProviderReuseable*) rdata;
+		sscanf (ptr, "%d.%d.%d", &(prdata->major),  &(prdata->minor),  &(prdata->micro));
+
+		/* elaborate the version number as a float */
+		gfloat div = 1;
+		while (*ptr != ' ') {
+			if (*ptr != '.') {
+				rdata->version_float += (*ptr - '0')/div;
+				div *= 10;
+			}
+			ptr++;
+		}
+	}
+
+	g_object_unref (model);
+	
+	/*
+	g_print ("VERSIONS: [%f] [%d.%d.%d]\n", rdata->version_float,
+		 ((GdaProviderReuseable*)rdata)->major,
+		 ((GdaProviderReuseable*)rdata)->minor,
+		 ((GdaProviderReuseable*)rdata)->micro);
+	*/
+	return TRUE;
+}
+
 static GType
 postgres_name_to_g_type (const gchar *name, const gchar *conv_func_name)
 {
@@ -244,6 +315,8 @@ _gda_postgres_compute_types (GdaConnection *cnc, GdaPostgresReuseable *rdata)
 	gchar *avoid_types = NULL;
 	GString *string;
 
+	if (rdata->version_float == 0)
+		_gda_postgres_compute_version (cnc, rdata, NULL);
 	if (rdata->version_float < 7.3) {
 		gchar *query;
 		avoid_types = "'SET', 'cid', 'oid', 'int2vector', 'oidvector', 'regproc', 'smgr', 'tid', 'unknown', 'xid'";
@@ -291,6 +364,8 @@ _gda_postgres_compute_types (GdaConnection *cnc, GdaPostgresReuseable *rdata)
 					       "SELECT t.oid FROM pg_catalog.pg_type t WHERE t.typname = 'any'");
 	}
 
+	if (rdata->version_float == 0)
+		_gda_postgres_compute_version (cnc, rdata, NULL);
 	if (!model || !model_avoid ||
 	    ((rdata->version_float >= 7.3) && !model_anyoid)) {
 		if (model)
@@ -407,14 +482,14 @@ _gda_postgres_reuseable_get_g_type (GdaConnection *cnc, GdaProviderReuseable *rd
 GdaSqlReservedKeywordsFunc
 _gda_postgres_reuseable_get_reserved_keywords_func (GdaProviderReuseable *rdata)
 {
-	if (rdata && rdata->version_minor) {
-		switch (*rdata->version_minor) {
-                case '8':
-                        if (rdata->version_minor[1] == '2')
+	if (rdata) {
+		switch (rdata->major) {
+                case 8:
+                        if (rdata->minor == 2)
                                 return V82is_keyword;
-                        if (rdata->version_minor[1] == '3')
+                        if (rdata->minor == 3)
                                 return V83is_keyword;
-                        if (rdata->version_minor[1] == '4')
+			if (rdata->minor == 4)
                                 return V84is_keyword;
                         return V84is_keyword;
                 default:
diff --git a/providers/reuseable/postgres/gda-postgres-reuseable.h b/providers/reuseable/postgres/gda-postgres-reuseable.h
index 7765e13..bfe6b18 100644
--- a/providers/reuseable/postgres/gda-postgres-reuseable.h
+++ b/providers/reuseable/postgres/gda-postgres-reuseable.h
@@ -49,7 +49,7 @@ typedef struct {
 /*
  * Reuseable implementation
  */
-GdaProviderReuseable *_gda_postgres_reuseable_new_data (const gchar *major, const gchar *minor);
+GdaProviderReuseable *_gda_postgres_reuseable_new_data (void);
 void _gda_postgres_reuseable_reset_data (GdaProviderReuseable *rdata);
 GType _gda_postgres_reuseable_get_g_type (GdaConnection *cnc, GdaProviderReuseable *rdata, const gchar *db_type);
 GdaSqlReservedKeywordsFunc _gda_postgres_reuseable_get_reserved_keywords_func (GdaProviderReuseable *rdata);
@@ -63,6 +63,7 @@ GdaProviderReuseableOperations *_gda_postgres_reuseable_get_ops (void);
 /*
  * Specific API
  */
+gboolean            _gda_postgres_compute_version (GdaConnection *cnc, GdaPostgresReuseable *rdata, GError **error);
 void                _gda_postgres_compute_types (GdaConnection *cnc, GdaPostgresReuseable *rdata);
 
 GType               _gda_postgres_type_oid_to_gda (GdaConnection *cnc, GdaPostgresReuseable *rdata,
diff --git a/providers/reuseable/reuse-all.c b/providers/reuseable/reuse-all.c
index 332fe47..7cda29d 100644
--- a/providers/reuseable/reuse-all.c
+++ b/providers/reuseable/reuse-all.c
@@ -24,6 +24,7 @@
 #include "reuse-all.h"
 
 #include "postgres/gda-postgres-reuseable.h"
+#include "mysql/gda-mysql-reuseable.h"
 
 /**
  * _gda_provider_reuseable_new
@@ -36,18 +37,18 @@
  * Returns: a new GdaProviderReuseable pointer, or %NULL
  */
 GdaProviderReuseable *
-_gda_provider_reuseable_new (const gchar *provider_name,
-			     const gchar *version_major,
-			     const gchar *version_minor)
+_gda_provider_reuseable_new (const gchar *provider_name)
 {
 	GdaProviderReuseable *reuseable = NULL;
 	GdaProviderReuseableOperations *ops = NULL;
 	g_return_val_if_fail (provider_name && *provider_name, NULL);
 	if (!strcmp (provider_name, "PostgreSQL"))
 		ops = _gda_postgres_reuseable_get_ops ();
+	else if (!strcmp (provider_name, "MySQL"))
+		ops = _gda_mysql_reuseable_get_ops ();
 
 	if (ops) {
-		reuseable = ops->re_new_data (version_major, version_minor);
+		reuseable = ops->re_new_data ();
 		g_assert (reuseable->operations == ops);
 	}
 
diff --git a/providers/reuseable/reuse-all.h b/providers/reuseable/reuse-all.h
index d3c79a3..bdd173a 100644
--- a/providers/reuseable/reuse-all.h
+++ b/providers/reuseable/reuse-all.h
@@ -26,10 +26,7 @@
 
 G_BEGIN_DECLS
 
-GdaProviderReuseable *_gda_provider_reuseable_new (const gchar *provider_name,
-						   const gchar *version_major,
-						   const gchar *version_minor);
-
+GdaProviderReuseable *_gda_provider_reuseable_new (const gchar *provider_name);
 
 G_END_DECLS
 
diff --git a/providers/web/gda-web-util.c b/providers/web/gda-web-util.c
index 761fd89..273abdb 100644
--- a/providers/web/gda-web-util.c
+++ b/providers/web/gda-web-util.c
@@ -205,8 +205,7 @@ decode_buffer_response (GdaConnection *cnc, WebConnectionData *cdata, SoupBuffer
 				cdata->server_id = g_strdup ((gchar*) contents);
 				xmlFree (contents);
 
-				/* FIXME: get version from server */
-				cdata->reuseable = _gda_provider_reuseable_new (cdata->server_id, NULL, NULL);
+				cdata->reuseable = _gda_provider_reuseable_new (cdata->server_id);
 #ifdef DEBUG_WEB_PROV
 				g_print ("REUSEABLE [%s]: %p\n", cdata->server_id, cdata->reuseable);
 #endif



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