[libgda/LIBGDA_4.0] Better handle SQL identifiers' case sensitiveness



commit 23ae47fbd4b1f4408983abdc0ae7205db7adba58
Author: Vivien Malerba <malerba gnome-db org>
Date:   Sun Jul 5 10:13:37 2009 +0200

    Better handle SQL identifiers' case sensitiveness
    
    	* libgda/Makefile.am:
    	* libgda/gda-data-meta-wrapper.[ch]: new (private) GdaDataModel wrapper internally
    	used by the GdaMetaStore object
    	* libgda/gda-data-access-wrapper.h: removed unnecessary #include
    	* libgda/gda-enums.h: added the GdaSqlIdentifierStyle enum
    	* libgda/gda-meta-store.[ch]:
    	  - use the new GdaDataMetaWrapper object to "filter" the
    	    updates made by each database provider when updating the meta data
    	  - added gda_meta_store_set_identifiers_style(), to be used by database providers
    	* libgda/gda-meta-struct.c: updates the way information is searced in the GdaMetaStore
    	* libgda/information_schema.xml: identify which columns are SQL identifiers
    	* libgda/gda-util.c: improved the gda_completion_list_get() function
    	* tools/tools-input.c: correctly set break characters for completion
    	* libgda/sql-parser/gda-statement-struct-util.c: corrected gda_sql_identifier_needs_quotes()
    	* doc/C: SQL identifiers precisions
    	* tests/meta-store/data_table_constraints.csv: fixed test case

 ChangeLog                                     |    2 +-
 doc/C/libgda-4.0-docs.sgml                    |   62 +++-
 doc/C/prov-writing.xml                        |   19 +
 libgda/Makefile.am                            |    2 +
 libgda/gda-connection.c                       |   48 ++-
 libgda/gda-data-access-wrapper.h              |    1 -
 libgda/gda-data-meta-wrapper.c                |  592 +++++++++++++++++++++++++
 libgda/gda-data-meta-wrapper.h                |   67 +++
 libgda/gda-enums.h                            |    8 +-
 libgda/gda-meta-store-extra.h                 |    1 +
 libgda/gda-meta-store.c                       |  197 ++++++++-
 libgda/gda-meta-struct.c                      |   33 +-
 libgda/gda-util.c                             |   85 ++---
 libgda/information_schema.xml                 |  194 ++++----
 libgda/sql-parser/gda-statement-struct-util.c |   31 ++-
 po/POTFILES.in                                |    1 +
 tests/.gitignore                              |    1 +
 tests/Makefile.am                             |   11 +-
 tests/meta-store/data_table_constraints.csv   |  282 ++++++------
 tests/test-sql-identifier.c                   |   65 +++
 tools/tools-input.c                           |    1 +
 21 files changed, 1356 insertions(+), 347 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 16cdaee..ab9dff4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,5 @@
 2009-06-30  Vivien Malerba <malerba gnome-db org>
-	
+
 	* doc/C/libgda-4.0-sections.txt:
 	* libgda-4.0.pc.in:
 	* libgda/providers-support/Makefile.am:
diff --git a/doc/C/libgda-4.0-docs.sgml b/doc/C/libgda-4.0-docs.sgml
index fe6eb29..440d033 100644
--- a/doc/C/libgda-4.0-docs.sgml
+++ b/doc/C/libgda-4.0-docs.sgml
@@ -889,10 +889,64 @@ g_object_unref (store);
 	<sect2 id="information_schema:sql_identifiers">
 	  <title>SQL identifiers</title>
 	  <para>
-	    SQL identifiers (database object's names) are case insitive, but it is still possible to specify
-	    that an SQL identifier be case sensitive by putting it between double quotes. &LIBGDA; has chosen
-	    the convention that case insitive SQL identifiers should all be in lower case in the meta data's tables
-	    whereas case sensitive SQL identifiers can contain some upper case ASCII characters.
+	    The SQL standard has never defined if SQL identifiers (database object's names) have to be case sensitive
+	    or not, leaving that
+	    subject to each database engine implementation. All of them accept two syntaxes for SQL identifiers:
+	    <itemizedlist>
+	      <listitem><para>the first is if the SQL identifier is surrounded by double quotes (sometimes simple
+		  quotes are also accepted), making the SQL identifier case sensitive (and also making
+		  it possible to use reserved SQL keywords as identifiers).</para></listitem>
+	      <listitem><para>the second is if it's not enquoted, meaning that the SQL identifier is not
+		  case sensitive.</para></listitem>
+	    </itemizedlist>
+	    <note>
+	      <para>
+		Many people consider that using the quoted syntax should be avoided if possible because:
+		<itemizedlist>
+		  <listitem><para>once an SQL identifier has been defined using the quoted syntax, it must
+		      <emphasis>always</emphasis> be used quoted, which is error prone especially if external
+		      tools are used on the database</para></listitem>
+		  <listitem><para>the SQL code is less readable (there are quoted strings everywhere)</para></listitem>
+		  <listitem><para>the SQL code is less portable as each database engine sets up different techniques to
+		      avoid confusing the SQL identifiers' quoting with SQL literals which are quoted when writing
+		      complex statements</para></listitem>
+		  <listitem><para>writing SQL requires a more in-depth knowledge of the database engine being used and as
+		      a consequence it's far easier to make errors when writing SQL</para></listitem>
+		</itemizedlist>
+		For some more example, see
+		<ulink url="http://www.alberton.info/dbms_identifiers_and_case_sensitivity.html";>Database identifiers, quoting and case sensitivity</ulink> from  Lorenzo Alberton.
+	      </para>
+	    </note>
+	  </para>
+	  <para>
+	    Considering that each database has its own
+	    internal way of representing case insensitive SQL identifiers (for instance PostgreSQL
+	    represents them in lower
+	    case whereas Oracle represents them in upper case and MySQL represents them in upper or lower case
+	    depending on the platform and the configuration), &LIBGDA; has chosen by convention
+	    to represent, in the meta data, case insensitive SQL identifiers in lower case 
+	    and case sensitive SQL identifiers enclosed between double quotes. 
+	  </para>
+	  <para>
+	    This convention has been made necessary to avoid confusion. To illustrate the problem, let's consider a 
+	    table named <emphasis>mytable</emphasis>. Without this convention, if that table was in a PostgreSQL
+	    database, then the meta data would report it as <emphasis>mytable</emphasis>, and if it was in an ORACLE,
+	    it would report it as <emphasis>MYTABLE</emphasis>. Now, a programmer which wants to compare the schemas
+	    of the PostgreSQL and Oracle databases has to know that the PostgreSQL's <emphasis>mytable</emphasis> and
+	    Oracle's <emphasis>MYTABLE</emphasis> represent in fact the same table which means he needs to know
+	    how each database internally stores SQL identifiers, which is not a good choice because it makes
+	    the application less portable between database engines. Better let each database provider do the job.
+
+	    Note that things can even get more confusing if MySQL is used because then one needs to figure out on
+	    which platform the MySQL server is running and how it's configured, a task which makes an application
+	    even less portable.
+	  </para>
+	  <para>
+	    To keep the same example, to build some SQL using the SQL identifier as reported by the meta data
+	    (<emphasis>mytable</emphasis> for PostgreSQL and <emphasis>MYTABLE</emphasis> for Oracle), one has either
+	    to determine if the SQL identifier needs to be quoted or not (which limits the application's portability),
+	    or systematically enquote the SQL identifier which is not something &LIBGDA; can impose to
+	    application developpers.
 	  </para>
 	  <para>
 	    This convention must be respected by database providers' implementations or the 
diff --git a/doc/C/prov-writing.xml b/doc/C/prov-writing.xml
index 8530553..35baec7 100644
--- a/doc/C/prov-writing.xml
+++ b/doc/C/prov-writing.xml
@@ -351,6 +351,25 @@ gboolean (*tables_views) (GdaServerProvider *, GdaConnection *, GdaMetaStore *,
       <link linkend="information_schema:sql_identifiers">SQL identifiers</link> section.
     </para>
     <sect2>
+      <title>Important note about SQL identifiers</title>
+      <para>
+	As mentionned in the <link linkend="information_schema:sql_identifiers">SQL identifiers</link> section,
+	any SQL identifier in the meta store is represented either:
+	<itemizedlist>
+	  <listitem><para>between double quotes if the SQL identifier is case sensitive</para></listitem>
+	  <listitem><para>all in lower case if the SQL identifier is not case sensitive</para></listitem>
+	</itemizedlist>
+      </para>
+      <para>
+	For database engines which internally store case insensitive SQL identifiers in lower case
+	(such as PostgreSQL),
+	the meta data reported by the database engine can be used almost AS IS, but for database
+	engines which internally store case insensitive SQL identifiers in upper case (such as Oracle),
+	the upper case needs to be converted to lower case. Also case sensitive SQL identifiers also need
+	to be double quoted.
+      </para>
+    </sect2>
+    <sect2>
       <title>_info()</title>
       <para>
 	<programlisting>
diff --git a/libgda/Makefile.am b/libgda/Makefile.am
index 3437e8f..a43b1e8 100644
--- a/libgda/Makefile.am
+++ b/libgda/Makefile.am
@@ -104,6 +104,8 @@ libgda_sources =  \
 	gda-data-model-import.c \
 	gda-data-model-iter.c \
 	gda-data-access-wrapper.c \
+	gda-data-meta-wrapper.c \
+	gda-data-meta-wrapper.h \
 	gda-data-proxy.c \
 	gda-data-select.c \
 	gda-data-select-extra.h \
diff --git a/libgda/gda-connection.c b/libgda/gda-connection.c
index 3c769f1..8b2f52d 100644
--- a/libgda/gda-connection.c
+++ b/libgda/gda-connection.c
@@ -1,5 +1,5 @@
 /* GDA library
- * Copyright (C) 1998 - 2008 The GNOME Foundation.
+ * Copyright (C) 1998 - 2009 The GNOME Foundation.
  *
  * AUTHORS:
  *      Michael Lausch <michael lausch at>
@@ -3031,34 +3031,37 @@ gda_connection_update_meta_store (GdaConnection *cnc, GdaMetaContext *context, G
 	store = gda_connection_get_meta_store (cnc);
 	g_assert (store);
 
-	/* prepare local context */
-	GdaMetaContext lcontext;
+	/* unlock connection */
+	gda_connection_unlock ((GdaLockable*) cnc);
 
 	if (context) {
+		GdaMetaContext *lcontext;
 		GSList *list;
 		GSList *up_templates;
 		GSList *dn_templates;
 		GError *lerror = NULL;
-		lcontext = *context;
+
+		lcontext = _gda_meta_store_validate_context (store, context, error);
+		if (!lcontext)
+			return FALSE;
 		/* alter local context because "_tables" and "_views" always go together so only
 		   "_tables" should be updated and providers should always update "_tables" and "_views"
 		*/
-		if (!strcmp (lcontext.table_name, "_views"))
-			lcontext.table_name = "_tables";
+		if (!strcmp (lcontext->table_name, "_views"))
+			lcontext->table_name = "_tables";
 
-		up_templates = build_upstream_context_templates (store, context, NULL, &lerror);
+		/* build context templates */
+		up_templates = build_upstream_context_templates (store, lcontext, NULL, &lerror);
 		if (!up_templates) {
 			if (lerror) {
 				g_propagate_error (error, lerror);
-				gda_connection_unlock ((GdaLockable*) cnc);
 				return FALSE;
 			}
 		}
-		dn_templates = build_downstream_context_templates (store, context, NULL, &lerror);
+		dn_templates = build_downstream_context_templates (store, lcontext, NULL, &lerror);
 		if (!dn_templates) {
 			if (lerror) {
 				g_propagate_error (error, lerror);
-				gda_connection_unlock ((GdaLockable*) cnc);
 				return FALSE;
 			}
 		}
@@ -3070,7 +3073,7 @@ gda_connection_update_meta_store (GdaConnection *cnc, GdaMetaContext *context, G
 			meta_context_dump ((GdaMetaContext*) list->data);
 		}
 		g_print ("->: ");
-		meta_context_dump (context);
+		meta_context_dump (lcontext);
 		for (list = dn_templates; list; list = list->next) {
 			g_print ("DN: ");
 			meta_context_dump ((GdaMetaContext*) list->data);
@@ -3084,7 +3087,7 @@ gda_connection_update_meta_store (GdaConnection *cnc, GdaMetaContext *context, G
 		cbd.prov = cnc->priv->provider_obj;
 		cbd.cnc = cnc;
 		cbd.error = NULL;
-		cbd.context_templates = g_slist_concat (g_slist_append (up_templates, context), dn_templates);
+		cbd.context_templates = g_slist_concat (g_slist_append (up_templates, lcontext), dn_templates);
 		cbd.context_templates_hash = g_hash_table_new (g_str_hash, g_str_equal);
 		for (list = cbd.context_templates; list; list = list->next) 
 			g_hash_table_insert (cbd.context_templates_hash, ((GdaMetaContext*)list->data)->table_name,
@@ -3101,18 +3104,23 @@ gda_connection_update_meta_store (GdaConnection *cnc, GdaMetaContext *context, G
 		/* free the memory associated with each template */
 		for (list = cbd.context_templates; list; list = list->next) {
 			GdaMetaContext *c = (GdaMetaContext *) list->data;
-			if (c != context) {
-				if (c->size > 0) {
-					g_free (c->column_names);
-					g_free (c->column_values);
+			if (c == lcontext) {
+				gint i;
+				for (i = 0; i < c->size; i++) {
+					g_free (c->column_names [i]);
+					if (c->column_values [i])
+						gda_value_free (c->column_values [i]);
 				}
-				g_free (c);
 			}
+			if (c->size > 0) {
+				g_free (c->column_names);
+				g_free (c->column_values);
+			}
+			g_free (c);
 		}
 		g_slist_free (cbd.context_templates);
 		g_hash_table_destroy (cbd.context_templates_hash);
 
-		gda_connection_unlock ((GdaLockable*) cnc);
 		return retval;
 	}
 	else {
@@ -3124,6 +3132,7 @@ gda_connection_update_meta_store (GdaConnection *cnc, GdaMetaContext *context, G
 			RFunc  func;
 		} RMeta;
 
+		GdaMetaContext lcontext;
 		gint nb = 0, i;
 		RMeta rmeta[] = {
 			{"_information_schema_catalog_name", "_info", NULL},
@@ -3176,7 +3185,6 @@ gda_connection_update_meta_store (GdaConnection *cnc, GdaMetaContext *context, G
 		g_assert (nb == sizeof (rmeta) / sizeof (RMeta));
 
 		if (! _gda_meta_store_begin_data_reset (store, error)) {
-			gda_connection_unlock ((GdaLockable*) cnc);
 			return FALSE;
 		}
 
@@ -3203,12 +3211,10 @@ gda_connection_update_meta_store (GdaConnection *cnc, GdaMetaContext *context, G
 			}
 		}
 		retval = _gda_meta_store_finish_data_reset (store, error);
-		gda_connection_unlock ((GdaLockable*) cnc);
 		return retval;
 
 	onerror:
 		_gda_meta_store_cancel_data_reset (store, NULL);
-		gda_connection_unlock ((GdaLockable*) cnc);
 		return FALSE;
 	}
 }
diff --git a/libgda/gda-data-access-wrapper.h b/libgda/gda-data-access-wrapper.h
index 147a689..2b55a64 100644
--- a/libgda/gda-data-access-wrapper.h
+++ b/libgda/gda-data-access-wrapper.h
@@ -24,7 +24,6 @@
 #define __GDA_DATA_ACCESS_WRAPPER_H__
 
 #include <libgda/gda-data-model.h>
-#include <libxml/tree.h>
 
 G_BEGIN_DECLS
 
diff --git a/libgda/gda-data-meta-wrapper.c b/libgda/gda-data-meta-wrapper.c
new file mode 100644
index 0000000..9e32493
--- /dev/null
+++ b/libgda/gda-data-meta-wrapper.c
@@ -0,0 +1,592 @@
+/* GDA library
+ * 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; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "gda-data-meta-wrapper.h"
+
+#include <string.h>
+#include <glib/gi18n-lib.h>
+#include <libgda/gda-enums.h>
+#include <libgda/gda-data-model.h>
+#include <libgda/sql-parser/gda-statement-struct-util.h>
+
+/*
+ * Each value in @values may be %NULL, a valid pointer, or 0x1
+ */
+typedef struct {
+	gint row; /* row number it is for */
+	gint size; /* size of the @values array */
+	GValue **values;
+} CompRow;
+
+#define NON_COMP_VALUE ((GValue*) 0x1)
+
+static void
+comp_row_free (CompRow *row)
+{
+	if (row->values) {
+		gint i;
+		for (i = 0; i < row->size; i++) {
+			if (row->values [i] && (row->values [i] != NON_COMP_VALUE))
+				gda_value_free (row->values [i]);
+		}
+		g_free (row->values);
+	}
+	g_free (row);
+}
+
+struct _GdaDataMetaWrapperPrivate {
+	GdaDataModel *model;
+	gint nb_cols;
+
+	gint *cols_to_wrap;
+	gint cols_to_wrap_size;
+	GdaSqlIdentifierStyle mode;
+	GHashTable *computed_rows; /* key = row number, value = a CompRow pointer
+				    * may be %NULL if we don't keep computed values */
+	CompRow *buffer; /* may be %NULL if we keep computed values */
+
+	/* note: either @computed_rows or @buffer is NULL, not both and one is not NULL */
+};
+
+/* properties */
+enum
+{
+        PROP_0,
+	PROP_MODEL,
+};
+
+static void gda_data_meta_wrapper_class_init (GdaDataMetaWrapperClass *klass);
+static void gda_data_meta_wrapper_init       (GdaDataMetaWrapper *model,
+					      GdaDataMetaWrapperClass *klass);
+static void gda_data_meta_wrapper_dispose    (GObject *object);
+static void gda_data_meta_wrapper_finalize   (GObject *object);
+
+static void gda_data_meta_wrapper_set_property (GObject *object,
+						    guint param_id,
+						    const GValue *value,
+						    GParamSpec *pspec);
+static void gda_data_meta_wrapper_get_property (GObject *object,
+						    guint param_id,
+						    GValue *value,
+						    GParamSpec *pspec);
+
+/* GdaDataModel interface */
+static void                 gda_data_meta_wrapper_data_model_init (GdaDataModelIface *iface);
+static gint                 gda_data_meta_wrapper_get_n_rows      (GdaDataModel *model);
+static gint                 gda_data_meta_wrapper_get_n_columns   (GdaDataModel *model);
+static GdaColumn           *gda_data_meta_wrapper_describe_column (GdaDataModel *model, gint col);
+static GdaDataModelAccessFlags gda_data_meta_wrapper_get_access_flags(GdaDataModel *model);
+static const GValue        *gda_data_meta_wrapper_get_value_at    (GdaDataModel *model, gint col, gint row, GError **error);
+
+static GObjectClass *parent_class = NULL;
+
+/**
+ * gda_data_meta_wrapper_get_type
+ *
+ * Returns: the #GType of GdaDataMetaWrapper.
+ */
+GType
+_gda_data_meta_wrapper_get_type (void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY (type == 0)) {
+		static GStaticMutex registering = G_STATIC_MUTEX_INIT;
+		static const GTypeInfo info = {
+			sizeof (GdaDataMetaWrapperClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) gda_data_meta_wrapper_class_init,
+			NULL,
+			NULL,
+			sizeof (GdaDataMetaWrapper),
+			0,
+			(GInstanceInitFunc) gda_data_meta_wrapper_init
+		};
+
+		static const GInterfaceInfo data_model_info = {
+			(GInterfaceInitFunc) gda_data_meta_wrapper_data_model_init,
+			NULL,
+			NULL
+		};
+
+		g_static_mutex_lock (&registering);
+		if (type == 0) {
+			type = g_type_register_static (G_TYPE_OBJECT, "GdaDataMetaWrapper", &info, 0);
+			g_type_add_interface_static (type, GDA_TYPE_DATA_MODEL, &data_model_info);
+		}
+		g_static_mutex_unlock (&registering);
+	}
+	return type;
+}
+
+static void 
+gda_data_meta_wrapper_class_init (GdaDataMetaWrapperClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	parent_class = g_type_class_peek_parent (klass);
+
+	/* properties */
+	object_class->set_property = gda_data_meta_wrapper_set_property;
+        object_class->get_property = gda_data_meta_wrapper_get_property;
+	g_object_class_install_property (object_class, PROP_MODEL,
+                                         g_param_spec_object ("model", NULL, "Data model being wrapped",
+                                                              GDA_TYPE_DATA_MODEL,
+							      G_PARAM_READABLE | G_PARAM_WRITABLE |
+							      G_PARAM_CONSTRUCT_ONLY));
+
+	/* virtual functions */
+	object_class->dispose = gda_data_meta_wrapper_dispose;
+	object_class->finalize = gda_data_meta_wrapper_finalize;
+}
+
+static void
+gda_data_meta_wrapper_data_model_init (GdaDataModelIface *iface)
+{
+	iface->i_get_n_rows = gda_data_meta_wrapper_get_n_rows;
+	iface->i_get_n_columns = gda_data_meta_wrapper_get_n_columns;
+	iface->i_describe_column = gda_data_meta_wrapper_describe_column;
+        iface->i_get_access_flags = gda_data_meta_wrapper_get_access_flags;
+	iface->i_get_value_at = gda_data_meta_wrapper_get_value_at;
+	iface->i_get_attributes_at = NULL;
+
+	iface->i_create_iter = NULL;
+	iface->i_iter_at_row = NULL;
+	iface->i_iter_next = NULL;
+	iface->i_iter_prev = NULL;
+
+	iface->i_set_value_at = NULL;
+	iface->i_iter_set_value = NULL;
+	iface->i_set_values = NULL;
+        iface->i_append_values = NULL;
+	iface->i_append_row = NULL;
+	iface->i_remove_row = NULL;
+	iface->i_find_row = NULL;
+	
+	iface->i_set_notify = NULL;
+	iface->i_get_notify = NULL;
+	iface->i_send_hint = NULL;
+}
+
+static void
+gda_data_meta_wrapper_init (GdaDataMetaWrapper *model, GdaDataMetaWrapperClass *klass)
+{
+	g_return_if_fail (GDA_IS_DATA_META_WRAPPER (model));
+	model->priv = g_new0 (GdaDataMetaWrapperPrivate, 1);
+	model->priv->model = NULL;
+	model->priv->cols_to_wrap = NULL;
+	model->priv->cols_to_wrap_size = 0;
+	model->priv->mode = GDA_DATA_META_WRAPPER_MODE_LC;
+	model->priv->computed_rows = NULL;
+	model->priv->buffer = NULL;
+}
+
+static void
+gda_data_meta_wrapper_dispose (GObject *object)
+{
+	GdaDataMetaWrapper *model = (GdaDataMetaWrapper *) object;
+
+	g_return_if_fail (GDA_IS_DATA_META_WRAPPER (model));
+
+	/* free memory */
+	if (model->priv) {
+		/* random meta model free */
+		if (model->priv->model) {
+			g_object_unref (model->priv->model);
+			model->priv->model = NULL;
+		}
+
+		if (model->priv->computed_rows) {
+			g_hash_table_destroy (model->priv->computed_rows);
+			model->priv->computed_rows = NULL;
+		}
+
+		if (model->priv->buffer) {
+			comp_row_free (model->priv->buffer);
+			model->priv->buffer = NULL;
+		}
+
+		if (model->priv->cols_to_wrap) {
+			g_free (model->priv->cols_to_wrap);
+			model->priv->cols_to_wrap = NULL;
+			model->priv->cols_to_wrap_size = 0;
+		}
+	}
+
+	/* chain to parent class */
+	parent_class->dispose (object);
+}
+
+static void
+gda_data_meta_wrapper_finalize (GObject *object)
+{
+	GdaDataMetaWrapper *model = (GdaDataMetaWrapper *) object;
+
+	g_return_if_fail (GDA_IS_DATA_META_WRAPPER (model));
+
+	/* free memory */
+	if (model->priv) {
+		g_free (model->priv);
+		model->priv = NULL;
+	}
+
+	/* chain to parent class */
+	parent_class->finalize (object);
+}
+
+static void
+gda_data_meta_wrapper_set_property (GObject *object,
+				      guint param_id,
+				      const GValue *value,
+				      GParamSpec *pspec)
+{
+	GdaDataMetaWrapper *model;
+
+	model = GDA_DATA_META_WRAPPER (object);
+	if (model->priv) {
+		switch (param_id) {
+		case PROP_MODEL: {
+			GdaDataModel *mod = g_value_get_object(value);
+			if (mod) {
+				g_return_if_fail (GDA_IS_DATA_MODEL (mod));
+				if (! (gda_data_model_get_access_flags (mod) & GDA_DATA_MODEL_ACCESS_RANDOM)) {
+					g_warning ("Internal implementation error: data model does not support random access");
+					return;
+				}
+  
+                                if (model->priv->model)
+					g_object_unref (model->priv->model);
+
+				model->priv->model = mod;
+				g_object_ref (mod);
+				model->priv->nb_cols = gda_data_model_get_n_columns (mod);
+			}
+			break;
+		}
+		default:
+			g_assert_not_reached ();
+			break;
+		}
+	}
+}
+
+static void
+gda_data_meta_wrapper_get_property (GObject *object,
+					guint param_id,
+					GValue *value,
+					GParamSpec *pspec)
+{
+	GdaDataMetaWrapper *model;
+
+	model = GDA_DATA_META_WRAPPER (object);
+	if (model->priv) {
+		switch (param_id) {
+		case PROP_MODEL:
+			g_value_set_object (value, G_OBJECT (model->priv->model));
+			break;
+		default:
+			g_assert_not_reached ();
+			break;
+		}
+	}
+}
+
+/**
+ * gda_data_meta_wrapper_new
+ * @model: a #GdaDataModel
+ *
+ * Creates a new #GdaDataModel object which buffers the rows of @model. This object is usefull
+ * only if @model can only be metaed using cursor based method.
+ *
+ * Returns: a pointer to the newly created #GdaDataModel.
+ */
+GdaDataModel *
+_gda_data_meta_wrapper_new (GdaDataModel *model, gboolean reuseable, gint *cols, gint size, GdaSqlIdentifierStyle mode)
+{
+	GdaDataMetaWrapper *retmodel;
+
+	g_return_val_if_fail (GDA_IS_DATA_MODEL (model), NULL);
+	
+	retmodel = g_object_new (GDA_TYPE_DATA_META_WRAPPER,
+				 "model", model, NULL);
+			      
+	retmodel->priv->cols_to_wrap = g_new0 (gint, size);
+	memcpy (retmodel->priv->cols_to_wrap, cols, sizeof (gint) * size);
+	retmodel->priv->cols_to_wrap_size = size;
+	retmodel->priv->mode = mode;
+	
+	if (reuseable)
+		retmodel->priv->computed_rows = g_hash_table_new_full (g_int_hash, g_int_equal,
+								       NULL, (GDestroyNotify) comp_row_free);
+	else {
+		retmodel->priv->buffer = g_new0 (CompRow, 1);
+		retmodel->priv->buffer->size = size;
+		retmodel->priv->buffer->values = g_new0 (GValue *, size);
+	}
+
+	return GDA_DATA_MODEL (retmodel);
+}
+
+/*
+ * GdaDataModel interface implementation
+ */
+static gint
+gda_data_meta_wrapper_get_n_rows (GdaDataModel *model)
+{
+	GdaDataMetaWrapper *imodel;
+	g_return_val_if_fail (GDA_IS_DATA_META_WRAPPER (model), 0);
+	imodel = GDA_DATA_META_WRAPPER (model);
+	g_return_val_if_fail (imodel->priv, 0);
+
+	return gda_data_model_get_n_rows (imodel->priv->model);
+}
+
+static gint
+gda_data_meta_wrapper_get_n_columns (GdaDataModel *model)
+{
+	GdaDataMetaWrapper *imodel;
+	g_return_val_if_fail (GDA_IS_DATA_META_WRAPPER (model), 0);
+	imodel = GDA_DATA_META_WRAPPER (model);
+	g_return_val_if_fail (imodel->priv, 0);
+	
+	if (imodel->priv->model)
+		return imodel->priv->nb_cols;
+	else
+		return 0;
+}
+
+static GdaColumn *
+gda_data_meta_wrapper_describe_column (GdaDataModel *model, gint col)
+{
+	GdaDataMetaWrapper *imodel;
+	g_return_val_if_fail (GDA_IS_DATA_META_WRAPPER (model), NULL);
+	imodel = GDA_DATA_META_WRAPPER (model);
+	g_return_val_if_fail (imodel->priv, NULL);
+
+	if (imodel->priv->model)
+		return gda_data_model_describe_column (imodel->priv->model, col);
+	else
+		return NULL;
+}
+
+static GdaDataModelAccessFlags
+gda_data_meta_wrapper_get_access_flags (GdaDataModel *model)
+{
+	GdaDataMetaWrapper *imodel;
+
+	g_return_val_if_fail (GDA_IS_DATA_META_WRAPPER (model), 0);
+	imodel = GDA_DATA_META_WRAPPER (model);
+	g_return_val_if_fail (imodel->priv, 0);
+	
+	return GDA_DATA_MODEL_ACCESS_RANDOM;
+}
+
+static gboolean
+identifier_needs_quotes (const gchar *str, GdaSqlIdentifierStyle mode)
+{
+	const gchar *ptr;
+	for (ptr = str; *ptr; ptr++) {
+		/* quote if 1st char is a number */
+		if ((*ptr <= '9') && (*ptr >= '0')) {
+			if (ptr == str)
+				return TRUE;
+			continue;
+		}
+		if ((*ptr >= 'A') && (*ptr <= 'Z')) {
+			if (mode == GDA_SQL_IDENTIFIERS_LOWER_CASE)
+				return TRUE;
+			continue;
+		}
+		if ((*ptr >= 'a') && (*ptr <= 'z')) {
+			if (mode == GDA_SQL_IDENTIFIERS_UPPER_CASE)
+				return TRUE;
+			continue;
+		}
+		if ((*ptr != '$') && (*ptr != '_') && (*ptr != '#'))
+			return TRUE;
+	}
+	return FALSE;
+}
+
+static gboolean
+identifier_is_all_lower (const gchar *str)
+{
+	const gchar *ptr;
+	for (ptr = str; *ptr; ptr++) {
+		if (*ptr != g_ascii_tolower (*ptr))
+			return FALSE;
+	}
+	return TRUE;
+}
+
+static gchar *
+to_lower (gchar *str)
+{
+	gchar *ptr;
+	for (ptr = str; *ptr; ptr++)
+		*ptr = g_ascii_tolower (*ptr);
+	return str;
+}
+
+/*
+ * Returns:
+ *  - NULL if no changes are necessary from the current value
+ *  - a new GValue if changes were necessary
+ */
+static GValue *
+compute_value (const GValue *value, GdaSqlIdentifierStyle mode)
+{
+	GValue *retval = NULL;
+	const gchar *str;
+
+	if (G_VALUE_TYPE (value) != G_TYPE_STRING)
+		return NULL;
+	str = g_value_get_string (value);
+	if (!str)
+		return NULL;
+	if ((*str == '"') && (str[strlen(str) - 1] == '"'))
+		return NULL; /* already quoted */
+	gchar **sa = g_strsplit (str, ".", 0);
+	if (sa[1]) {
+		gint i;
+		gboolean onechanged = FALSE;
+		for (i = 0; sa[i]; i++) {
+			if (identifier_needs_quotes (sa[i], mode)) {
+				gchar *tmp = gda_sql_identifier_add_quotes (sa[i]);
+				g_free (sa[i]);
+				sa[i] = tmp;
+				onechanged = TRUE;
+			}
+			else if (! identifier_is_all_lower (sa[i])) {
+				to_lower (sa[i]);
+				onechanged = TRUE;
+			}
+		}
+		if (onechanged) {
+			retval = gda_value_new (G_TYPE_STRING);
+			g_value_take_string (retval, g_strjoinv (".", sa));
+		}
+	}
+	else {
+		if (identifier_needs_quotes (str, mode)) {
+			retval = gda_value_new (G_TYPE_STRING);
+			g_value_take_string (retval, gda_sql_identifier_add_quotes (str));
+		}
+		else if (! identifier_is_all_lower (str)) {
+			gchar *tmp;
+			tmp = to_lower (g_strdup (str));
+			retval = gda_value_new (G_TYPE_STRING);
+			g_value_take_string (retval, tmp);
+		}
+	}
+	g_strfreev (sa);
+
+	return retval;
+}
+
+/*
+ * Returns: the index in @imodel->priv->cols_to_wrap for column @col, or -1 if not found
+ */
+static gint
+get_index_col (GdaDataMetaWrapper *imodel, gint col)
+{
+	gint i;
+	for (i = 0; i < imodel->priv->cols_to_wrap_size; i++) {
+		if (imodel->priv->cols_to_wrap [i] == col)
+			return i;
+		else if (imodel->priv->cols_to_wrap [i] > col)
+			return -1;
+	}
+	return -1;
+}
+
+static const GValue *
+gda_data_meta_wrapper_get_value_at (GdaDataModel *model, gint col, gint row, GError **error)
+{
+	GdaDataMetaWrapper *imodel;
+
+	g_return_val_if_fail (GDA_IS_DATA_META_WRAPPER (model), NULL);
+	imodel = GDA_DATA_META_WRAPPER (model);
+	g_return_val_if_fail (imodel->priv, NULL);
+	g_return_val_if_fail (imodel->priv->model, NULL);
+	g_return_val_if_fail (row >= 0, NULL);
+
+	if (col >= imodel->priv->nb_cols) {
+		g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_COLUMN_OUT_OF_RANGE_ERROR,
+			     _("Column %d out of range (0-%d)"), col, imodel->priv->nb_cols - 1);
+		return NULL;
+	}
+
+	gint indexcol = get_index_col (imodel, col);
+	if (indexcol == -1)
+		return gda_data_model_get_value_at (imodel->priv->model, col, row, error);
+
+	/* data may need to be changed */
+	if (imodel->priv->computed_rows) {
+		CompRow *crow = NULL;
+		crow = g_hash_table_lookup (imodel->priv->computed_rows, &row);
+		if (!crow || !(crow->values[indexcol]) || (crow->values[indexcol] == NON_COMP_VALUE)) {
+			const GValue *cvalue;
+			cvalue = gda_data_model_get_value_at (imodel->priv->model, col, row, error);
+			if (!cvalue)
+				return NULL;
+			
+			GValue *retval;
+			retval = compute_value (cvalue, imodel->priv->mode);
+			if (!retval)
+				return cvalue;
+			
+			if (!crow) {
+				crow = g_new0 (CompRow, 1);
+				crow->row = row;
+				crow->size = imodel->priv->cols_to_wrap_size;
+				crow->values = g_new (GValue *, crow->size);
+				gint i;
+				for (i = 0; i < crow->size; i++)
+					crow->values [i] = NON_COMP_VALUE;
+				g_hash_table_insert (imodel->priv->computed_rows, &(crow->row), crow);
+			}
+			crow->values[indexcol] = retval;
+			return retval;
+		}
+		else
+			return crow->values[indexcol];
+	}
+	else {
+		const GValue *cvalue;
+		cvalue = gda_data_model_get_value_at (imodel->priv->model, col, row, error);
+		if (!cvalue)
+			return NULL;
+
+		GValue *retval;
+		retval = compute_value (cvalue, imodel->priv->mode);
+		if (!retval)
+			return cvalue;
+		if (imodel->priv->buffer->values [indexcol])
+			gda_value_free (imodel->priv->buffer->values [indexcol]);
+		imodel->priv->buffer->values [indexcol] = retval;
+		return retval;
+	}
+	return NULL;
+}
+
diff --git a/libgda/gda-data-meta-wrapper.h b/libgda/gda-data-meta-wrapper.h
new file mode 100644
index 0000000..82b897f
--- /dev/null
+++ b/libgda/gda-data-meta-wrapper.h
@@ -0,0 +1,67 @@
+/* GDA common library
+ * 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; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GDA_DATA_META_WRAPPER_H__
+#define __GDA_DATA_META_WRAPPER_H__
+
+#include <libgda/gda-data-model.h>
+#include <libgda/gda-server-provider.h>
+
+G_BEGIN_DECLS
+
+#define GDA_TYPE_DATA_META_WRAPPER            (_gda_data_meta_wrapper_get_type())
+#define GDA_DATA_META_WRAPPER(obj)            (G_TYPE_CHECK_INSTANCE_CAST (obj, GDA_TYPE_DATA_META_WRAPPER, GdaDataMetaWrapper))
+#define GDA_DATA_META_WRAPPER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST (klass, GDA_TYPE_DATA_META_WRAPPER, GdaDataMetaWrapperClass))
+#define GDA_IS_DATA_META_WRAPPER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE(obj, GDA_TYPE_DATA_META_WRAPPER))
+#define GDA_IS_DATA_META_WRAPPER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GDA_TYPE_DATA_META_WRAPPER))
+
+typedef struct _GdaDataMetaWrapper        GdaDataMetaWrapper;
+typedef struct _GdaDataMetaWrapperClass   GdaDataMetaWrapperClass;
+typedef struct _GdaDataMetaWrapperPrivate GdaDataMetaWrapperPrivate;
+
+typedef enum {
+	GDA_DATA_META_WRAPPER_MODE_LC, /* quote identifier if there are some non lower case chars */
+	GDA_DATA_META_WRAPPER_MODE_UC  /* quote identifier if there are some non upper case chars */
+} GdaDataMetaWrapperMode;
+
+struct _GdaDataMetaWrapper {
+	GObject                        object;
+	GdaDataMetaWrapperPrivate   *priv;
+};
+
+struct _GdaDataMetaWrapperClass {
+	GObjectClass                   parent_class;
+
+	/* Padding for future expansion */
+	void (*_gda_reserved1) (void);
+	void (*_gda_reserved2) (void);
+	void (*_gda_reserved3) (void);
+	void (*_gda_reserved4) (void);
+};
+
+GType         _gda_data_meta_wrapper_get_type    (void) G_GNUC_CONST;
+GdaDataModel *_gda_data_meta_wrapper_new         (GdaDataModel *model, gboolean reuseable,
+						  gint *cols, gint size, GdaSqlIdentifierStyle mode);
+
+G_END_DECLS
+
+#endif
diff --git a/libgda/gda-enums.h b/libgda/gda-enums.h
index a666a05..543f817 100644
--- a/libgda/gda-enums.h
+++ b/libgda/gda-enums.h
@@ -1,6 +1,6 @@
 /* gda-enums.h
  *
- * Copyright (C) 2003 - 2006 Vivien Malerba
+ * Copyright (C) 2003 - 2009 Vivien Malerba
  *
  * This Library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public License as
@@ -45,6 +45,12 @@ typedef enum  {
 	GDA_VALUE_ATTR_UNUSED         = 1 << 9
 } GdaValueAttribute;
 
+/* how SQL identifiers are represented */
+typedef enum {
+	GDA_SQL_IDENTIFIERS_LOWER_CASE = 1 << 0,
+	GDA_SQL_IDENTIFIERS_UPPER_CASE = 1 << 1
+} GdaSqlIdentifierStyle;
+
 /* possible different keywords used when qualifying a table's column's extra attributes */
 #define GDA_EXTRA_AUTO_INCREMENT "AUTO_INCREMENT"
 
diff --git a/libgda/gda-meta-store-extra.h b/libgda/gda-meta-store-extra.h
index e2c2dce..85e7f67 100644
--- a/libgda/gda-meta-store-extra.h
+++ b/libgda/gda-meta-store-extra.h
@@ -27,6 +27,7 @@ gboolean  _gda_meta_store_begin_data_reset (GdaMetaStore *store, GError **error)
 gboolean  _gda_meta_store_cancel_data_reset (GdaMetaStore *store, GError **error);
 gboolean  _gda_meta_store_finish_data_reset (GdaMetaStore *store, GError **error);
 
+GdaMetaContext *_gda_meta_store_validate_context (GdaMetaStore *store, GdaMetaContext *context, GError **error);
 GSList   *_gda_meta_store_schema_get_upstream_contexts (GdaMetaStore *store, GdaMetaContext *context, GError **error);
 GSList   *_gda_meta_store_schema_get_downstream_contexts (GdaMetaStore *store, GdaMetaContext *context, GError **error);
 
diff --git a/libgda/gda-meta-store.c b/libgda/gda-meta-store.c
index aa648ca..c78bf45 100644
--- a/libgda/gda-meta-store.c
+++ b/libgda/gda-meta-store.c
@@ -41,6 +41,7 @@
 #include <libgda/gda-connection.h>
 #include <libgda/gda-connection-sqlite.h>
 #include "gda-types.h"
+#include "gda-data-meta-wrapper.h"
 
 /*
  * Main static functions
@@ -104,6 +105,10 @@ typedef struct {
 	/* fk_list */
 	GSList       *reverse_fk_list; /* list of TableFKey where @depend_on == this DbObject */
 	GSList       *fk_list; /* list of TableFKey where @table_info == this DbObject */
+
+	/* columns which contain SQL identifiers */
+	gint         *ident_cols;
+	gint          ident_cols_size;
 } TableInfo;
 static void table_info_free_contents (TableInfo *info);
 
@@ -201,6 +206,7 @@ static gboolean ProviderSpecific_equal (gconstpointer a, gconstpointer b);
 
 struct _GdaMetaStorePrivate {
 	GdaConnection *cnc;
+	GdaSqlIdentifierStyle ident_style;
 	gint           version;
 	gboolean       schema_ok;
 
@@ -483,6 +489,7 @@ gda_meta_store_init (GdaMetaStore *store)
 {
 	store->priv = g_new0 (GdaMetaStorePrivate, 1);
 	store->priv->cnc = NULL;
+	store->priv->ident_style = GDA_SQL_IDENTIFIERS_LOWER_CASE;
 	store->priv->schema_ok = FALSE;
 	store->priv->version = 0;
 
@@ -1316,26 +1323,24 @@ create_table_object (GdaMetaStoreClass *klass, GdaMetaStore *store, xmlNodePtr n
                         gboolean nullok = FALSE; 
 			gboolean autoinc = FALSE;
  
-                        if (strcmp ((gchar *) cnode->name, "column"))
-                                continue;
                         cname = xmlGetProp (cnode, BAD_CAST "name");
                         if (!cname)
                                 g_error ("Missing column name (table=%s)", complete_obj_name);
                         xstr = xmlGetProp (cnode, BAD_CAST "pkey");
                         if (xstr) {
-                                if ((*xstr == 't') || (*xstr == 'T'))
+                                if ((*xstr == 'T') || (*xstr == 't'))
                                         pkey = TRUE;
                                 xmlFree (xstr);
                         }
                         xstr = xmlGetProp (cnode, BAD_CAST "nullok");
                         if (xstr) {
-                                if ((*xstr == 't') || (*xstr == 'T'))
+                                if ((*xstr == 'T') || (*xstr == 't'))
                                         nullok = TRUE;
                                 xmlFree (xstr);
                         }
                         xstr = xmlGetProp (cnode, BAD_CAST "autoinc");
                         if (xstr) {
-                                if ((*xstr == 't') || (*xstr == 'T'))
+                                if ((*xstr == 'T') || (*xstr == 't'))
                                         autoinc = TRUE;
                                 xmlFree (xstr);
                         }
@@ -1351,6 +1356,22 @@ create_table_object (GdaMetaStoreClass *klass, GdaMetaStore *store, xmlNodePtr n
                         field->field_name = g_strdup ((gchar *) cname);
                         ust->fields_list = g_slist_append (ust->fields_list, field);
 
+			/* SQL identifier ? */
+#define MAX_IDENT_IN_TABLE 10
+			xstr = xmlGetProp (cnode, BAD_CAST "ident");
+                        if (xstr) {
+                                if ((*xstr == 'T') || (*xstr == 't')) {
+					if (!TABLE_INFO (dbobj)->ident_cols) {
+						TABLE_INFO (dbobj)->ident_cols = g_new0 (gint, MAX_IDENT_IN_TABLE);
+						TABLE_INFO (dbobj)->ident_cols_size = 0;
+					}
+					g_assert (TABLE_INFO (dbobj)->ident_cols_size < MAX_IDENT_IN_TABLE);
+					TABLE_INFO (dbobj)->ident_cols [TABLE_INFO (dbobj)->ident_cols_size] = colindex;
+					TABLE_INFO (dbobj)->ident_cols_size ++;
+				}
+                                xmlFree (xstr);
+                        }
+
 			/* parameter */
                         GType ptype;
                         GdaSqlParamSpec *pspec = g_new0 (GdaSqlParamSpec, 1);
@@ -1868,6 +1889,8 @@ table_info_free_contents (TableInfo *info)
 	g_free (info->pk_cols_array);
 	g_free (info->type_cols_array);
 	g_slist_free (info->fk_list);
+	if (info->ident_cols)
+		g_free (info->ident_cols);
 }
 
 static void
@@ -2265,12 +2288,26 @@ gda_meta_store_modify_v (GdaMetaStore *store, const gchar *table_name,
 
 	/* treat rows to insert / update */
 	if (new_data) {
+		GdaDataModel *wrapped_data;
 		gint new_n_rows, new_n_cols;
-		new_n_rows = gda_data_model_get_n_rows (new_data);
-		new_n_cols = gda_data_model_get_n_columns (new_data);
+
+		if (schema_set->ident_cols)
+			wrapped_data = _gda_data_meta_wrapper_new (new_data, !store->priv->override_mode,
+								   schema_set->ident_cols, schema_set->ident_cols_size,
+								   store->priv->ident_style);
+		else
+			wrapped_data = g_object_ref (new_data);
+
+		new_n_rows = gda_data_model_get_n_rows (wrapped_data);
+		new_n_cols = gda_data_model_get_n_columns (wrapped_data);
 #ifdef DEBUG_STORE_MODIFY
-		g_print ("NEW:\n");
-		gda_data_model_dump (new_data, stdout);
+		if (new_data != wrapped_data) {
+			g_print ("NEW for table %s:\n", table_name);
+			gda_data_model_dump (new_data, stdout);
+
+			g_print ("wrapped as:\n");
+			gda_data_model_dump (wrapped_data, stdout);
+		}
 #endif		
 
 		for (i = 0; i < new_n_rows; i++) {
@@ -2281,7 +2318,7 @@ gda_meta_store_modify_v (GdaMetaStore *store, const gchar *table_name,
 
 			if (!store->priv->override_mode) {
 				if (current) {
-					erow = find_row_in_model (current, new_data, i,
+					erow = find_row_in_model (current, wrapped_data, i,
 								  schema_set->pk_cols_array, 
 								  schema_set->pk_cols_nb, &has_changed, 
 								  error);
@@ -2292,6 +2329,7 @@ gda_meta_store_modify_v (GdaMetaStore *store, const gchar *table_name,
 				}
 				if (erow < -1) {
 					retval = FALSE;
+					g_object_unref (wrapped_data);
 					goto out;
 				}
 				
@@ -2312,16 +2350,18 @@ gda_meta_store_modify_v (GdaMetaStore *store, const gchar *table_name,
 				h = gda_set_get_holder (schema_set->params, pid);
 				if (h) {
 					const GValue *value;
-					value = gda_data_model_get_value_at (new_data, j, i, error);
+					value = gda_data_model_get_value_at (wrapped_data, j, i, error);
 					if (!value) {
 						g_free (pid);
 						retval = FALSE;
+						g_object_unref (wrapped_data);
 						goto out;
 					}
 						
 					if (! gda_holder_set_value (h, value, error)) {
 						g_free (pid);
 						retval = FALSE;
+						g_object_unref (wrapped_data);
 						goto out;
 					}
 					if (change) {
@@ -2342,6 +2382,7 @@ gda_meta_store_modify_v (GdaMetaStore *store, const gchar *table_name,
 										 schema_set->insert, schema_set->params, 
 										 NULL, error) == -1) {
 					retval = FALSE;
+					g_object_unref (wrapped_data);
 					goto out;
 				}
 				if (change) 
@@ -2359,11 +2400,13 @@ gda_meta_store_modify_v (GdaMetaStore *store, const gchar *table_name,
 						if (!value) {
 							g_free (pid);
 							retval = FALSE;
+							g_object_unref (wrapped_data);
 							goto out;
 						}
 						if (!gda_holder_set_value (h, value, error)) {
 							g_free (pid);
 							retval = FALSE;
+							g_object_unref (wrapped_data);
 							goto out;
 						}
 						if (change) {
@@ -2381,6 +2424,7 @@ gda_meta_store_modify_v (GdaMetaStore *store, const gchar *table_name,
 										 schema_set->update, schema_set->params, 
 										 NULL, error) == -1) {
 					retval = FALSE;
+					g_object_unref (wrapped_data);
 					goto out;
 				}
 				if (change) 
@@ -2410,6 +2454,7 @@ gda_meta_store_modify_v (GdaMetaStore *store, const gchar *table_name,
 						if (!context.column_values [k]) {
 							g_free (context.column_values);
 							retval = FALSE;
+							g_object_unref (wrapped_data);
 							goto out;
 						}
 					}
@@ -2434,6 +2479,7 @@ gda_meta_store_modify_v (GdaMetaStore *store, const gchar *table_name,
 						retval = FALSE;
 						if (error && !(*error))
 							g_propagate_error (error, suggest_reports_error);
+						g_object_unref (wrapped_data);
 						goto out;
 					}
 				}
@@ -3420,6 +3466,135 @@ gda_meta_store_schema_remove_custom_object (GdaMetaStore *store, const gchar *ob
 }
 
 /*
+ * Makes sure @context is well formed, and call gda_sql_identifier_remove_quotes() on SQL
+ * identifiers's values
+ *
+ * Returns: a new #GdaMetaContext
+ */
+GdaMetaContext *
+_gda_meta_store_validate_context (GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	GdaMetaStoreClass *klass;
+	gint i;
+
+	if (!context->table_name || !(*context->table_name)) {
+		g_set_error (error, GDA_META_STORE_ERROR, GDA_META_STORE_META_CONTEXT_ERROR,
+			     _("Missing table name in meta data context"));
+		return NULL;
+	}
+	if (context->size <= 0) {
+		g_set_error (error, GDA_META_STORE_ERROR, GDA_META_STORE_META_CONTEXT_ERROR,
+			     _("Missing condition in meta data context"));
+		return NULL;
+	}
+
+	klass = GDA_META_STORE_CLASS (G_OBJECT_GET_CLASS (store));
+
+	/* handle quoted SQL identifiers */
+	DbObject *dbobj = g_hash_table_lookup (klass->cpriv->db_objects_hash, context->table_name);
+	if (dbobj && (dbobj->obj_type == GDA_SERVER_OPERATION_CREATE_TABLE)) {
+		GdaMetaContext *lcontext;
+		TableInfo *tinfo;
+
+		lcontext = g_new0 (GdaMetaContext, 1);
+		lcontext->table_name = context->table_name;
+		lcontext->size = context->size;
+		lcontext->column_names = g_new0 (gchar*, lcontext->size);
+		lcontext->column_values = g_new0 (GValue*, lcontext->size);
+		
+		tinfo = TABLE_INFO (dbobj);
+		for (i = 0; i < lcontext->size; i++) {
+			GSList *list;
+			gint colindex;
+
+			if (!context->column_names [i]) {
+				g_set_error (error, GDA_META_STORE_ERROR, GDA_META_STORE_META_CONTEXT_ERROR,
+					     _("Missing column name in meta data context"));
+				goto onerror;
+			}
+			lcontext->column_names [i] = g_strdup (context->column_names [i]);
+
+			for (colindex = 0, list = tinfo->columns;
+			     list;
+			     colindex++, list = list->next) {
+				if (!strcmp (TABLE_COLUMN (list->data)->column_name, lcontext->column_names [i])) {
+					gint j;
+					for (j = 0; j < tinfo->ident_cols_size; j++) {
+						if (tinfo->ident_cols [j] == colindex) {
+							/* we have an SQL identifier */
+							if (! context->column_values [i]) {
+								g_set_error (error, GDA_META_STORE_ERROR,
+									     GDA_META_STORE_META_CONTEXT_ERROR,
+									     _("Missing condition in meta data context"));
+								goto onerror;
+							}
+							else if (G_VALUE_TYPE (context->column_values [i]) == G_TYPE_STRING) {
+								gchar *id;
+								id = g_value_dup_string (context->column_values [i]);
+								gda_sql_identifier_remove_quotes (id);
+								if (store->priv->ident_style == GDA_SQL_IDENTIFIERS_UPPER_CASE) {
+									/* move to upper case */
+									gchar *ptr;
+									for (ptr = id; *ptr; ptr++) {
+										if ((*ptr >= 'a') && (*ptr <= 'z'))
+											*ptr += 'A' - 'a';
+									}
+								}
+								lcontext->column_values [i] = gda_value_new (G_TYPE_STRING);
+								g_value_take_string (lcontext->column_values [i], id);
+								
+							}
+							else if (G_VALUE_TYPE (context->column_values [i]) == GDA_TYPE_NULL) {
+								lcontext->column_values [i] = gda_value_new_null ();
+							}
+							else {
+								g_set_error (error, GDA_META_STORE_ERROR,
+									     GDA_META_STORE_META_CONTEXT_ERROR,
+									     _("Malformed condition in meta data context"));
+								goto onerror;
+							}
+						}
+					}
+
+					if (! lcontext->column_values [i]) {
+						lcontext->column_values [i] = gda_value_copy (context->column_values [i]);
+					}
+					colindex = -1;
+					break;
+				}
+			}
+
+			if (colindex != -1) {
+				/* column not found => error */
+				g_set_error (error, GDA_META_STORE_ERROR, GDA_META_STORE_META_CONTEXT_ERROR,
+					     _("Unknown column name '%s' in meta data context"),
+					     lcontext->column_names [i]);
+				goto onerror;
+			}
+			else
+				continue;
+
+		onerror:
+			for (i = 0; i < lcontext->size; i++) {
+				g_free (lcontext->column_names [i]);
+				if (lcontext->column_values [i])
+					gda_value_free (lcontext->column_values [i]);
+			}
+			g_free (lcontext->column_names);
+			g_free (lcontext->column_values);
+			g_free (lcontext);
+			return NULL;
+		}
+		return lcontext;
+	}
+	else {
+		g_set_error (error, GDA_META_STORE_ERROR, GDA_META_STORE_META_CONTEXT_ERROR,
+			     _("Unknown table in meta data context"));
+		return NULL;
+	}
+}
+
+/*
  * Returns: a list of new #GdaMetaContext structures, one for each dependency context->table_name has,
  * or %NULL if there is no downstream context, or if an error occurred (check @error to make the difference).
  *
diff --git a/libgda/gda-meta-struct.c b/libgda/gda-meta-struct.c
index dab2ce8..4e2dc88 100644
--- a/libgda/gda-meta-struct.c
+++ b/libgda/gda-meta-struct.c
@@ -400,6 +400,19 @@ get_user_obj_name (const GValue *catalog, const GValue *schema, const GValue *na
 	return ret;
 }
 
+static gchar *
+prepare_sql_identifier_for_compare (gchar *str)
+{
+	if (!str || (*str == '"'))
+		return str;
+	else {
+		gchar *ptr;
+		for (ptr = str; *ptr; ptr++)
+			*ptr = g_ascii_tolower (*ptr);
+		return str;
+	}
+}
+
 /**
  * gda_meta_struct_complement
  * @mstruct: a #GdaMetaStruct object
@@ -453,19 +466,19 @@ gda_meta_struct_complement (GdaMetaStruct *mstruct, GdaMetaDbObjectType type,
 	/* create ready to compare strings for catalog, schema and name */
 	gchar *schema_s, *name_s;
 	if (_split_identifier_string (g_value_dup_string (name), &schema_s, &name_s)) {
-		g_value_take_string ((iname = gda_value_new (G_TYPE_STRING)), gda_sql_identifier_remove_quotes (name_s));
+		g_value_take_string ((iname = gda_value_new (G_TYPE_STRING)), prepare_sql_identifier_for_compare (name_s));
 		if (schema_s)
-			g_value_take_string ((ischema = gda_value_new (G_TYPE_STRING)), gda_sql_identifier_remove_quotes (schema_s));
+			g_value_take_string ((ischema = gda_value_new (G_TYPE_STRING)), prepare_sql_identifier_for_compare (schema_s));
 	}
 	else
 		g_value_take_string ((iname = gda_value_new (G_TYPE_STRING)), 
-				     gda_sql_identifier_remove_quotes (g_value_dup_string (name)));
+				     prepare_sql_identifier_for_compare (g_value_dup_string (name)));
 	if (catalog)
 		g_value_take_string ((icatalog = gda_value_new (G_TYPE_STRING)), 
-				     gda_sql_identifier_remove_quotes (g_value_dup_string (catalog)));
+				     prepare_sql_identifier_for_compare (g_value_dup_string (catalog)));
 	if (schema && !ischema) 
 		g_value_take_string ((ischema = gda_value_new (G_TYPE_STRING)), 
-				     gda_sql_identifier_remove_quotes (g_value_dup_string (schema)));
+				     prepare_sql_identifier_for_compare (g_value_dup_string (schema)));
 
 	if (!icatalog) {
 		if (ischema) {
@@ -1557,13 +1570,13 @@ gda_meta_struct_get_db_object (GdaMetaStruct *mstruct, const GValue *catalog, co
 	g_return_val_if_fail (!schema || (G_VALUE_TYPE (schema) == G_TYPE_STRING), NULL);
 
 	/* prepare identifiers */
-	g_value_take_string ((iname = gda_value_new (G_TYPE_STRING)), gda_sql_identifier_remove_quotes (g_value_dup_string (name)));
+	g_value_take_string ((iname = gda_value_new (G_TYPE_STRING)), prepare_sql_identifier_for_compare (g_value_dup_string (name)));
 	if (catalog)
 		g_value_take_string ((icatalog = gda_value_new (G_TYPE_STRING)), 
-				     gda_sql_identifier_remove_quotes (g_value_dup_string (catalog)));
+				     prepare_sql_identifier_for_compare (g_value_dup_string (catalog)));
 	if (schema) 
 		g_value_take_string ((ischema = gda_value_new (G_TYPE_STRING)), 
-				     gda_sql_identifier_remove_quotes (g_value_dup_string (schema)));
+				     prepare_sql_identifier_for_compare (g_value_dup_string (schema)));
 
 	dbo = _meta_struct_get_db_object (mstruct, icatalog, ischema, iname);
 	if (icatalog) gda_value_free (icatalog);
@@ -2069,8 +2082,8 @@ determine_db_object_from_short_name (GdaMetaStruct *mstruct,
 				g_free (obj_schema);
 				return FALSE;
 			}
-			g_value_take_string ((sv = gda_value_new (G_TYPE_STRING)), gda_sql_identifier_remove_quotes (obj_schema));
-			g_value_take_string ((nv = gda_value_new (G_TYPE_STRING)), gda_sql_identifier_remove_quotes (obj_name));
+			g_value_take_string ((sv = gda_value_new (G_TYPE_STRING)), prepare_sql_identifier_for_compare (obj_schema));
+			g_value_take_string ((nv = gda_value_new (G_TYPE_STRING)), prepare_sql_identifier_for_compare (obj_name));
 			retval = determine_db_object_from_schema_and_name (mstruct, in_out_type, out_catalog, 
 									   out_short_name, out_full_name, out_owner, 
 									   sv, nv);
diff --git a/libgda/gda-util.c b/libgda/gda-util.c
index d3a87be..4a0e99a 100644
--- a/libgda/gda-util.c
+++ b/libgda/gda-util.c
@@ -1200,7 +1200,6 @@ gda_identifier_equal (const gchar *id1, const gchar *id2)
 }
 
 
-static char *copy_ident (const gchar *ident);
 static char *concat_ident (const gchar *prefix, const gchar *ident);
 
 static gchar *sql_start_words[] = {
@@ -1235,6 +1234,19 @@ static gchar *sql_middle_words[] = {
 	"SET"
 };
 
+static gchar *
+prepare_sql_identifier_for_compare (gchar *str)
+{
+	if (!str || (*str == '"'))
+		return str;
+	else {
+		gchar *ptr;
+		for (ptr = str; *ptr; ptr++)
+			*ptr = g_ascii_tolower (*ptr);
+		return str;
+	}
+}
+
 /**
  * gda_completion_list_get
  * @cnc: a #GdaConnection object
@@ -1301,15 +1313,11 @@ gda_completion_list_get (GdaConnection *cnc, const gchar *sql, gint start, gint
 		else
 			goto compl_finished;
 	}
-	
-	if (*obj_name == '"') 
-		_remove_quotes (obj_name);
-	
-	if (obj_schema) {
-		if (*obj_schema == '"') 
-			_remove_quotes (obj_schema);
-		g_value_take_string ((schema_value = gda_value_new (G_TYPE_STRING)), obj_schema);
-	}
+		
+	prepare_sql_identifier_for_compare (obj_name);
+	if (obj_schema)
+		g_value_take_string ((schema_value = gda_value_new (G_TYPE_STRING)),
+				     prepare_sql_identifier_for_compare (obj_schema));
 	
 	/*
 	 * complete with "table" or "schema.table"
@@ -1340,7 +1348,7 @@ gda_completion_list_get (GdaConnection *cnc, const gchar *sql, gint start, gint
 					if (schema_value) 
 						str = concat_ident (obj_schema, tname);
 					else
-						str = copy_ident (tname);
+						str = g_strdup (tname);
 					g_array_append_val (compl, str);
 				}
 			}
@@ -1367,7 +1375,7 @@ gda_completion_list_get (GdaConnection *cnc, const gchar *sql, gint start, gint
 				cname = g_value_get_string (cvalue);
 				if (!strncmp (cname, obj_name, len)) {
 					gchar *str;
-					str = copy_ident (cname);
+					str = g_strdup (cname);
 					g_array_append_val (compl, str);
 				}
 			}
@@ -1394,7 +1402,7 @@ gda_completion_list_get (GdaConnection *cnc, const gchar *sql, gint start, gint
 				if (!strncmp (tname, obj_name, len)) {
 					char *str;
 					GdaDataModel *m2;
-					str = copy_ident (tname);
+					str = g_strdup (tname);
 				
 					m2 = gda_meta_store_extract (store, 
 								     "SELECT table_name FROM _tables WHERE table_schema = ##schema::string", 
@@ -1462,26 +1470,6 @@ gda_completion_list_get (GdaConnection *cnc, const gchar *sql, gint start, gint
 		return NULL;
 }
 
-
-static char *
-copy_ident (const gchar *ident)
-{
-	char *str;
-	gint tlen = strlen (ident);
-	if (gda_sql_identifier_needs_quotes (ident)) {
-		str = malloc (sizeof (char) * (tlen + 3));
-		*str = '"';
-		strcpy (str+1, ident);
-		str [tlen + 1] = '"';
-		str [tlen + 2] = 0;
-	}
-	else {
-		str = malloc (sizeof (char) * (tlen + 1));
-		strcpy (str, ident);		
-	}
-	return str;
-}
-
 static char *
 concat_ident (const char *prefix, const gchar *ident)
 {
@@ -1492,31 +1480,14 @@ concat_ident (const char *prefix, const gchar *ident)
 	if (prefix)
 		plen = strlen (prefix) + 1;
 
-	if (gda_sql_identifier_needs_quotes (ident)) {
-		str = malloc (sizeof (char) * (plen + tlen + 3));
-		if (prefix) {
-			strcpy (str, prefix);
-			str [plen - 1] = '.';
-			str [plen] = '"';
-			strcpy (str + plen + 1, ident);
-		}
-		else {
-			*str = '"';
-			strcpy (str+1, ident);
-		}
-		str [plen + tlen + 1] = '"';
-		str [plen + tlen + 2] = 0;
-	}
-	else {
-		str = malloc (sizeof (char) * (plen + tlen + 1));
-		if (prefix) {
-			strcpy (str, prefix);
-			str [plen - 1] = '.';
-			strcpy (str + plen, ident);
-		}
-		else
-			strcpy (str, ident);
+	str = malloc (sizeof (char) * (plen + tlen + 1));
+	if (prefix) {
+		strcpy (str, prefix);
+		str [plen - 1] = '.';
+		strcpy (str + plen, ident);
 	}
+	else
+		strcpy (str, ident);
 	return str;
 }
 
diff --git a/libgda/information_schema.xml b/libgda/information_schema.xml
index 1c2abb9..ff71657 100644
--- a/libgda/information_schema.xml
+++ b/libgda/information_schema.xml
@@ -39,7 +39,7 @@
 
   <table name="_schemata" descr="List of schemas">
     <column name="catalog_name" pkey="TRUE" descr="Name of the catalog that contains the schema"/>
-    <column name="schema_name" pkey="TRUE"/>
+    <column name="schema_name" pkey="TRUE" ident="TRUE"/>
     <column name="schema_owner" nullok="TRUE" descr="Name of the schema"/>
     <column name="schema_internal" type="boolean"  descr="Tells if the schema is specific to the database implementation (and usually can't be modified)"/>
     <fkey ref_table="_information_schema_catalog_name">
@@ -48,8 +48,8 @@
   </table>
 
   <table name="_builtin_data_types" descr="List of built-in data types such as varchar, int, ...">
-    <column name="short_type_name" descr="Short name of the data type"/>
-    <column name="full_type_name" pkey="TRUE" descr="Full name of the data type"/>
+    <column name="short_type_name" descr="Short name of the data type" ident="TRUE"/>
+    <column name="full_type_name" pkey="TRUE" descr="Full name of the data type" ident="TRUE"/>
     <column name="gtype" nullok="TRUE"/>
     <column name="comments" nullok="TRUE"/>
     <column name="synonyms" nullok="TRUE"/>
@@ -61,12 +61,12 @@
 
   <table name="_udt" descr="User defined data types">
     <column name="udt_catalog" pkey="TRUE" descr="Name of the catalog that contains the data type"/>
-    <column name="udt_schema" pkey="TRUE" descr="Name of the schema that contains the data type"/>
-    <column name="udt_name" pkey="TRUE" descr="Name of the data type"/>
+    <column name="udt_schema" pkey="TRUE" descr="Name of the schema that contains the data type" ident="TRUE"/>
+    <column name="udt_name" pkey="TRUE" descr="Name of the data type" ident="TRUE"/>
     <column name="udt_gtype" nullok="TRUE" descr="GType associated to the data type"/>
     <column name="udt_comments" nullok="TRUE"/>
-    <column name="udt_short_name"/>
-    <column name="udt_full_name"/>
+    <column name="udt_short_name" ident="TRUE"/>
+    <column name="udt_full_name" ident="TRUE"/>
     <column name="udt_internal" type="boolean" descr="Tells if the data type is reserved for the database implementation and should not be used in applications"/>
     <column name="udt_owner" nullok="TRUE"/>
     <fkey ref_table="_schemata">
@@ -80,11 +80,11 @@
 
   <table name="_udt_columns" descr="List of components for a user defined data type for composed data types (such as a complex number data type which has real and imaginary parts)">
     <column name="udt_catalog" pkey="TRUE" descr="Name of the catalog that contains the user defined data type for which the column is"/>
-    <column name="udt_schema" pkey="TRUE" descr="Name of the schema that contains the user defined data type for which the column is"/>
-    <column name="udt_name" pkey="TRUE" descr="Name of the user defined data type for which the column is"/>
-    <column name="udt_column" pkey="TRUE" descr="Name of the column (part)"/>
+    <column name="udt_schema" pkey="TRUE" descr="Name of the schema that contains the user defined data type for which the column is" ident="TRUE"/>
+    <column name="udt_name" pkey="TRUE" descr="Name of the user defined data type for which the column is" ident="TRUE"/>
+    <column name="udt_column" pkey="TRUE" descr="Name of the column (part)" ident="TRUE"/>
     <column name="ordinal_position" type="gint" descr="Column position, starts at 1"/>
-    <column name="data_type" nullok="TRUE" descr="Data type of the column (if the column is an array, then 'array_spec' is set, and this may be NULL)"/>
+    <column name="data_type" nullok="TRUE" descr="Data type of the column (if the column is an array, then 'array_spec' is set, and this may be NULL)" ident="TRUE"/>
     <column name="array_spec" nullok="TRUE" descr="Array description if the column is an array"/>
     <column name="character_maximum_length" type="gint" nullok="TRUE"/>
     <column name="character_octet_length" type="gint" nullok="TRUE"/>
@@ -92,11 +92,11 @@
     <column name="numeric_scale" type="gint" nullok="TRUE"/>
     <column name="datetime_precision" type="gint" nullok="TRUE"/>
     <column name="character_set_catalog" nullok="TRUE"/>
-    <column name="character_set_schema" nullok="TRUE"/>
-    <column name="character_set_name" nullok="TRUE"/>
+    <column name="character_set_schema" nullok="TRUE" ident="TRUE"/>
+    <column name="character_set_name" nullok="TRUE" ident="TRUE"/>
     <column name="collation_catalog" nullok="TRUE"/>
-    <column name="collation_schema" nullok="TRUE"/>
-    <column name="collation_name" nullok="TRUE"/>
+    <column name="collation_schema" nullok="TRUE" ident="TRUE"/>
+    <column name="collation_name" nullok="TRUE" ident="TRUE"/>
     <fkey ref_table="_udt">
       <part column="udt_catalog"/>
       <part column="udt_schema"/>
@@ -114,8 +114,8 @@
 
   <table name="_enums" descr="List of possible enumeration labels for enumerations">
     <column name="udt_catalog" pkey="TRUE" descr="Name of the catalog that contains the ENUM user defined data type"/>
-    <column name="udt_schema" pkey="TRUE" descr="Name of the schema that contains the ENUM user defined data type"/>
-    <column name="udt_name" pkey="TRUE" descr="Name of the ENUM user defined data type"/>
+    <column name="udt_schema" pkey="TRUE" descr="Name of the schema that contains the ENUM user defined data type" ident="TRUE"/>
+    <column name="udt_name" pkey="TRUE" descr="Name of the ENUM user defined data type" ident="TRUE"/>
     <column name="label" pkey="TRUE"/>
     <column name="ordinal_position" type="gint" descr="Position, starts at 1"/>
     <fkey ref_table="_udt">
@@ -128,10 +128,10 @@
   <table name="_element_types" descr="Array specific attributes for array data types">
     <column name="specific_name" pkey="TRUE" descr="No specific meaning, used as a primary key, and for joining"/>
     <column name="object_catalog" descr="Name of the catalog that contains the object that uses the array being described"/>
-    <column name="object_schema" descr="Name of the schema that contains the object that uses the array being described"/>
-    <column name="object_name" descr="Name of the object that uses the array being described"/>
+    <column name="object_schema" descr="Name of the schema that contains the object that uses the array being described" ident="TRUE"/>
+    <column name="object_name" descr="Name of the object that uses the array being described" ident="TRUE"/>
     <column name="object_type" descr="The type of the object that uses the array being described TABLE_COL, DOMAIN, UDT_COL, ROUTINE_COL, ROUTINE_PAR"/>
-    <column name="data_type" nullok="TRUE" descr="Base data type of the array (if the base data type is an array, then 'array_spec' is set, and this may be NULL)"/>
+    <column name="data_type" nullok="TRUE" descr="Base data type of the array (if the base data type is an array, then 'array_spec' is set, and this may be NULL)" ident="TRUE"/>
     <column name="array_spec" nullok="TRUE" descr="Array description if the base data type is an array"/>
     <column name="min_cardinality" type="gint" nullok="TRUE"/>
     <column name="max_cardinality" type="gint" nullok="TRUE"/>
@@ -139,25 +139,25 @@
 
   <table name="_domains" descr="List of domains">
     <column name="domain_catalog" pkey="TRUE" descr="Name of catalog that contains the domain"/>
-    <column name="domain_schema" pkey="TRUE" descr="Name of schema that contains the domain"/>
-    <column name="domain_name" pkey="TRUE" descr="Name of the domain"/>
-    <column name="data_type" nullok="TRUE" descr="Data type of the domain (if the domain is an array, then 'array_spec' is set, and this may be NULL)"/>
+    <column name="domain_schema" pkey="TRUE" descr="Name of schema that contains the domain" ident="TRUE"/>
+    <column name="domain_name" pkey="TRUE" descr="Name of the domain" ident="TRUE"/>
+    <column name="data_type" nullok="TRUE" descr="Data type of the domain (if the domain is an array, then 'array_spec' is set, and this may be NULL)" ident="TRUE"/>
     <column name="array_spec" nullok="TRUE" descr="Array description if the domain is an array"/>
     <column name="domain_gtype"/>
     <column name="character_maximum_length" type="gint" nullok="TRUE"/>
     <column name="character_octet_length" type="gint" nullok="TRUE"/>
     <column name="collation_catalog" nullok="TRUE" descr="Name of catalog that contains the associated collation"/>
-    <column name="collation_schema" nullok="TRUE" descr="Name of schema that contains the associated collation"/>
-    <column name="collation_name" nullok="TRUE" descr="Name of the associated collation"/>
+    <column name="collation_schema" nullok="TRUE" descr="Name of schema that contains the associated collation" ident="TRUE"/>
+    <column name="collation_name" nullok="TRUE" descr="Name of the associated collation" ident="TRUE"/>
     <column name="character_set_catalog" nullok="TRUE" descr="Name of catalog that contains the associated character set"/>
-    <column name="character_set_schema" nullok="TRUE" descr="Name of schema that contains the associated character set"/>
-    <column name="character_set_name" nullok="TRUE" descr="Name of the associated character set"/>
+    <column name="character_set_schema" nullok="TRUE" descr="Name of schema that contains the associated character set" ident="TRUE"/>
+    <column name="character_set_name" nullok="TRUE" descr="Name of the associated character set" ident="TRUE"/>
     <column name="numeric_precision" type="gint" nullok="TRUE"/>
     <column name="numeric_scale" type="gint" nullok="TRUE"/>
     <column name="domain_default" nullok="TRUE"/>
     <column name="domain_comments" nullok="TRUE"/>
-    <column name="domain_short_name"/>
-    <column name="domain_full_name"/>
+    <column name="domain_short_name" ident="TRUE"/>
+    <column name="domain_full_name" ident="TRUE"/>
     <column name="domain_internal" type="boolean"/>
     <column name="domain_owner" nullok="TRUE"/>
     <fkey ref_table="_schemata">
@@ -179,13 +179,13 @@
 
   <table name="_tables" descr="List of tables (tables, views or other objects which can contain data)">
     <column name="table_catalog" pkey="TRUE" descr="Name of catalog that contains the table"/>
-    <column name="table_schema" pkey="TRUE" descr="Name of schema that contains the table"/>
-    <column name="table_name" pkey="TRUE" descr="Name of the table"/>
+    <column name="table_schema" pkey="TRUE" descr="Name of schema that contains the table" ident="TRUE"/>
+    <column name="table_name" pkey="TRUE" descr="Name of the table" ident="TRUE"/>
     <column name="table_type" descr="Type of table: BASE TABLE, VIEW, LOCAL TEMPORARY, SYSTEM TABLE, GLOBAL TEMPORARY, ALIAS or SYNONYM"/>
     <column name="is_insertable_into" type="boolean" nullok="TRUE" descr="Tells if the table's contents can be modified"/>
     <column name="table_comments" nullok="TRUE"/>
-    <column name="table_short_name"/>
-    <column name="table_full_name"/>
+    <column name="table_short_name" ident="TRUE"/>
+    <column name="table_full_name" ident="TRUE"/>
     <column name="table_owner" nullok="TRUE"/>
     <fkey ref_table="_schemata">
       <part column="table_catalog" ref_column="catalog_name"/>
@@ -198,8 +198,8 @@
 
   <table name="_views" descr="List of views and their specific information">
     <column name="table_catalog" pkey="TRUE" descr="Name of catalog that contains the view"/>
-    <column name="table_schema" pkey="TRUE" descr="Name of schema that contains the view"/>
-    <column name="table_name" pkey="TRUE" descr="Name of the view"/>
+    <column name="table_schema" pkey="TRUE" descr="Name of schema that contains the view" ident="TRUE"/>
+    <column name="table_name" pkey="TRUE" descr="Name of the view" ident="TRUE"/>
     <column name="view_definition" nullok="TRUE" descr="View as SQL"/>
     <column name="check_option" nullok="TRUE" descr="CASCADE if the statement used to create the view included the WITH CHECK OPTION; otherwise, NONE"/>
     <column name="is_updatable" type="boolean" nullok="TRUE" descr="Tells if the view's contents can be modified"/>
@@ -212,11 +212,11 @@
 
   <table name="_collations" descr="List of collations methods">
     <column name="collation_catalog" pkey="TRUE"/>
-    <column name="collation_schema" pkey="TRUE"/>
-    <column name="collation_name" pkey="TRUE"/>
+    <column name="collation_schema" pkey="TRUE" ident="TRUE"/>
+    <column name="collation_name" pkey="TRUE" ident="TRUE"/>
     <column name="collation_comments" nullok="TRUE"/>
-    <column name="collation_short_name"/>
-    <column name="collation_full_name"/>
+    <column name="collation_short_name" ident="TRUE"/>
+    <column name="collation_full_name" ident="TRUE"/>
     <fkey ref_table="_schemata">
       <part column="collation_catalog" ref_column="catalog_name"/>
       <part column="collation_schema" ref_column="schema_name"/>
@@ -228,14 +228,14 @@
 
   <table name="_character_sets" descr="List of character sets">
     <column name="character_set_catalog" pkey="TRUE"/>
-    <column name="character_set_schema" pkey="TRUE"/>
-    <column name="character_set_name" pkey="TRUE"/>
+    <column name="character_set_schema" pkey="TRUE" ident="TRUE"/>
+    <column name="character_set_name" pkey="TRUE" ident="TRUE"/>
     <column name="default_collate_catalog" nullok="TRUE"/>
-    <column name="default_collate_schema" nullok="TRUE"/>
-    <column name="default_collate_name" nullok="TRUE"/>
+    <column name="default_collate_schema" nullok="TRUE" ident="TRUE"/>
+    <column name="default_collate_name" nullok="TRUE" ident="TRUE"/>
     <column name="character_set_comments" nullok="TRUE"/>
-    <column name="character_set_short_name"/>
-    <column name="character_set_full_name"/>
+    <column name="character_set_short_name" ident="TRUE"/>
+    <column name="character_set_full_name" ident="TRUE"/>
     <fkey ref_table="_schemata">
       <part column="character_set_catalog" ref_column="catalog_name"/>
       <part column="character_set_schema" ref_column="schema_name"/>
@@ -252,11 +252,11 @@
 
   <table name="_routines" descr="List of functions and stored procedures (note: the primary jey for that table is composed of (specific_catalog, specific_schema, specific_name))">
     <column name="specific_catalog" pkey="TRUE" descr="Specific name of catalog that contains the routine"/>
-    <column name="specific_schema" pkey="TRUE" descr="Specific name of schema that contains the routine"/>
+    <column name="specific_schema" pkey="TRUE" descr="Specific name of schema that contains the routine" ident="TRUE"/>
     <column name="specific_name" pkey="TRUE" descr="Specific name of the routine (may be mangled for polymorphic routines)"/>
     <column name="routine_catalog" nullok="TRUE" descr="Name of catalog that contains the routine (may be NULL)"/>
-    <column name="routine_schema" nullok="TRUE" descr="Name of schema that contains the routine (may be NULL)"/>
-    <column name="routine_name" descr="Name of the routine"/>
+    <column name="routine_schema" nullok="TRUE" descr="Name of schema that contains the routine (may be NULL)" ident="TRUE"/>
+    <column name="routine_name" descr="Name of the routine" ident="TRUE"/>
     <column name="routine_type" nullok="TRUE" descr="FUNCTION, PROCEDURE, AGGREGATE"/>
     <column name="return_type" nullok="TRUE" descr="Data type returned by the routine (may be NULL if routine does not return any value)"/>
     <column name="returns_set" type="boolean" descr="True if routine returns a set (i.e., multiple values of the specified data type or if data type may vary)"/>
@@ -270,8 +270,8 @@
     <column name="sql_data_access" nullok="TRUE" descr="Whether the routine contains SQL and whether it reads or modifies data (NONE, CONTAINS, READS, MODIFIES)"/>
     <column name="is_null_call" type="boolean" nullok="TRUE" descr="Tells if the routine will be called if any one of its arguments is NULL"/>
     <column name="routine_comments" nullok="TRUE"/>
-    <column name="routine_short_name"/>
-    <column name="routine_full_name"/>
+    <column name="routine_short_name" ident="TRUE"/>
+    <column name="routine_full_name" ident="TRUE"/>
     <column name="routine_owner" nullok="TRUE"/>
     <fkey ref_table="_schemata">
       <part column="specific_catalog" ref_column="catalog_name"/>
@@ -284,19 +284,19 @@
 
   <table name="_triggers" descr="List of triggers">
     <column name="trigger_catalog" pkey="TRUE"/>
-    <column name="trigger_schema" pkey="TRUE"/>
-    <column name="trigger_name" pkey="TRUE"/>
+    <column name="trigger_schema" pkey="TRUE" ident="TRUE"/>
+    <column name="trigger_name" pkey="TRUE" ident="TRUE"/>
     <column name="event_manipulation" pkey="TRUE" descr="Event that fires the trigger (INSERT, UPDATE, or DELETE)"/>
     <column name="event_object_catalog" pkey="TRUE" descr="Name of the database that contains the table that the trigger is defined on"/>
-    <column name="event_object_schema" pkey="TRUE" descr="Name of the schema that contains the table that the trigger is defined on"/>
-    <column name="event_object_table" pkey="TRUE" descr="Name of the table that the trigger is defined on"/>
+    <column name="event_object_schema" pkey="TRUE" descr="Name of the schema that contains the table that the trigger is defined on" ident="TRUE"/>
+    <column name="event_object_table" pkey="TRUE" descr="Name of the table that the trigger is defined on" ident="TRUE"/>
 
     <column name="action_statement" nullok="TRUE" descr="Statement that is executed by the trigger"/>
     <column name="action_orientation" descr="Identifies whether the trigger fires once for each processed row or once for each statement (ROW or STATEMENT)"/>
     <column name="condition_timing" descr="Time at which the trigger fires (BEFORE or AFTER)"/>
     <column name="trigger_comments" nullok="TRUE"/>
-    <column name="trigger_short_name"/>
-    <column name="trigger_full_name"/>
+    <column name="trigger_short_name" ident="TRUE"/>
+    <column name="trigger_full_name" ident="TRUE"/>
     <fkey ref_table="_schemata">
       <part column="trigger_catalog" ref_column="catalog_name"/>
       <part column="trigger_schema" ref_column="schema_name"/>
@@ -313,13 +313,13 @@
 
   <table name="_columns" descr="List of columns composing tables">
     <column name="table_catalog" pkey="TRUE"/>
-    <column name="table_schema" pkey="TRUE"/>
-    <column name="table_name" pkey="TRUE"/>
-    <column name="column_name" pkey="TRUE"/>
+    <column name="table_schema" pkey="TRUE" ident="TRUE"/>
+    <column name="table_name" pkey="TRUE" ident="TRUE"/>
+    <column name="column_name" pkey="TRUE" ident="TRUE"/>
     <column name="ordinal_position" type="gint" descr="Column position, starts at 1"/>
     <column name="column_default" nullok="TRUE"/>
     <column name="is_nullable" type="boolean"/>
-    <column name="data_type" nullok="TRUE" descr="Data type of the column (if the column is an array, then 'array_spec' is set, and this may be NULL)"/>
+    <column name="data_type" nullok="TRUE" descr="Data type of the column (if the column is an array, then 'array_spec' is set, and this may be NULL)" ident="TRUE"/>
     <column name="array_spec" nullok="TRUE" descr="Array description if the column is an array"/>
     <column name="gtype"/>
     <column name="character_maximum_length" type="gint" nullok="TRUE"/>
@@ -328,11 +328,11 @@
     <column name="numeric_scale" type="gint" nullok="TRUE" descr="If data_type identifies an exact numeric type, this column contains the scale of the type for this column (the number of significant digits to the right of the decimal point)"/>
     <column name="datetime_precision" type="gint" nullok="TRUE"/>
     <column name="character_set_catalog" nullok="TRUE"/>
-    <column name="character_set_schema" nullok="TRUE"/>
-    <column name="character_set_name" nullok="TRUE"/>
+    <column name="character_set_schema" nullok="TRUE" ident="TRUE"/>
+    <column name="character_set_name" nullok="TRUE" ident="TRUE"/>
     <column name="collation_catalog" nullok="TRUE"/>
-    <column name="collation_schema" nullok="TRUE"/>
-    <column name="collation_name" nullok="TRUE"/>
+    <column name="collation_schema" nullok="TRUE" ident="TRUE"/>
+    <column name="collation_name" nullok="TRUE" ident="TRUE"/>
     <column name="extra" nullok="TRUE" descr="CSV string with: AUTO_INCREMENT"/> <!-- set the gda-enums.h file -->
     <column name="is_updatable" type="boolean" nullok="TRUE"/>
     <column name="column_comments" nullok="TRUE"/>
@@ -363,12 +363,12 @@
 
   <table name="_table_constraints" descr="List of constraints applied to tables (Check, primary or foreign key, or unique constraints)">
     <column name="constraint_catalog" nullok="TRUE" descr="Name of the catalog that contains the constraint"/>
-    <column name="constraint_schema" nullok="TRUE" descr="Name of the schema that contains the constraint"/>
+    <column name="constraint_schema" nullok="TRUE" descr="Name of the schema that contains the constraint" ident="TRUE"/>
 
-    <column name="constraint_name" pkey="TRUE"/>
+    <column name="constraint_name" pkey="TRUE" ident="TRUE"/>
     <column name="table_catalog" pkey="TRUE"/>
-    <column name="table_schema" pkey="TRUE"/>
-    <column name="table_name" pkey="TRUE"/>
+    <column name="table_schema" pkey="TRUE" ident="TRUE"/>
+    <column name="table_name" pkey="TRUE" ident="TRUE"/>
     <column name="constraint_type" descr="CHECK, FOREIGN KEY, PRIMARY KEY or UNIQUE"/>
     <column name="check_clause" nullok="TRUE" descr="The check expression if the constraint is a check constraint, NULL otherwise"/>
     <column name="is_deferrable" type="boolean" nullok="TRUE"/>
@@ -382,14 +382,14 @@
 
   <table name="_referential_constraints" descr="List of foreign key constraints, along with some specific attributes">
     <column name="table_catalog" pkey="TRUE"/>
-    <column name="table_schema" pkey="TRUE"/>
-    <column name="table_name" pkey="TRUE"/>
-    <column name="constraint_name" pkey="TRUE"/>
+    <column name="table_schema" pkey="TRUE" ident="TRUE"/>
+    <column name="table_name" pkey="TRUE" ident="TRUE"/>
+    <column name="constraint_name" pkey="TRUE" ident="TRUE"/>
 
     <column name="ref_table_catalog"/>
-    <column name="ref_table_schema"/>
-    <column name="ref_table_name"/>
-    <column name="ref_constraint_name"/>
+    <column name="ref_table_schema" ident="TRUE"/>
+    <column name="ref_table_name" ident="TRUE"/>
+    <column name="ref_constraint_name" ident="TRUE"/>
 
     <column name="match_option" nullok="TRUE" descr="FULL, PARTIAL or NONE"/>
     <column name="update_rule" nullok="TRUE" descr="CASCADE, SET NULL, SET DEFAULT, RESTRICT, NO ACTION or NONE"/>
@@ -410,10 +410,10 @@
 
   <table name="_key_column_usage" descr="List of primary key constraints and the name of the tables' columns involved">
     <column name="table_catalog" pkey="TRUE"/>
-    <column name="table_schema" pkey="TRUE"/>
-    <column name="table_name" pkey="TRUE"/>
-    <column name="constraint_name" pkey="TRUE"/>
-    <column name="column_name" pkey="TRUE"/>
+    <column name="table_schema" pkey="TRUE" ident="TRUE"/>
+    <column name="table_name" pkey="TRUE" ident="TRUE"/>
+    <column name="constraint_name" pkey="TRUE" ident="TRUE"/>
+    <column name="column_name" pkey="TRUE" ident="TRUE"/>
     <column name="ordinal_position" type="gint" pkey="TRUE" descr="Ordinal position of the column within the constraint key (count starts at 1)"/>
     <fkey ref_table="_table_constraints">
       <part column="table_catalog"/>
@@ -431,10 +431,10 @@
 
   <table name="_check_column_usage" descr="List of check constraints and the name of the tables' columns involved">
     <column name="table_catalog" pkey="TRUE"/>
-    <column name="table_schema" pkey="TRUE"/>
-    <column name="table_name" pkey="TRUE"/>
-    <column name="constraint_name" pkey="TRUE"/>
-    <column name="column_name" pkey="TRUE"/>
+    <column name="table_schema" pkey="TRUE" ident="TRUE"/>
+    <column name="table_name" pkey="TRUE" ident="TRUE"/>
+    <column name="constraint_name" pkey="TRUE" ident="TRUE"/>
+    <column name="column_name" pkey="TRUE" ident="TRUE"/>
     <fkey ref_table="_table_constraints">
       <part column="table_catalog"/>
       <part column="table_schema"/>
@@ -451,12 +451,12 @@
 
   <table name="_view_column_usage" descr="List of the tables' columns involved in a view">
     <column name="view_catalog" pkey="TRUE"/>
-    <column name="view_schema" pkey="TRUE"/>
-    <column name="view_name" pkey="TRUE"/>
+    <column name="view_schema" pkey="TRUE" ident="TRUE"/>
+    <column name="view_name" pkey="TRUE" ident="TRUE"/>
     <column name="table_catalog" pkey="TRUE"/>
-    <column name="table_schema" pkey="TRUE"/>
-    <column name="table_name" pkey="TRUE"/>
-    <column name="column_name" pkey="TRUE"/>
+    <column name="table_schema" pkey="TRUE" ident="TRUE"/>
+    <column name="table_name" pkey="TRUE" ident="TRUE"/>
+    <column name="column_name" pkey="TRUE" ident="TRUE"/>
     <fkey ref_table="_views">
       <part column="view_catalog" ref_column="table_catalog"/>
       <part column="view_schema" ref_column="table_schema"/>
@@ -472,12 +472,12 @@
 
   <table name="_domain_constraints" descr="List of constraints applicable to domains">
     <column name="constraint_catalog" nullok="TRUE" descr="Name of the catalog that contains the constraint"/>
-    <column name="constraint_schema" nullok="TRUE" descr="Name of the schema that contains the constraint"/>
+    <column name="constraint_schema" nullok="TRUE" descr="Name of the schema that contains the constraint" ident="TRUE"/>
 
-    <column name="constraint_name" pkey="TRUE"/>
+    <column name="constraint_name" pkey="TRUE" ident="TRUE"/>
     <column name="domain_catalog" pkey="TRUE"/>
-    <column name="domain_schema" pkey="TRUE"/>
-    <column name="domain_name" pkey="TRUE"/>
+    <column name="domain_schema" pkey="TRUE" ident="TRUE"/>
+    <column name="domain_name" pkey="TRUE" ident="TRUE"/>
 
     <column name="check_clause" nullok="TRUE"/>
     <column name="is_deferrable" type="boolean" nullok="TRUE"/>
@@ -495,12 +495,12 @@
 
   <table name="_parameters" descr="List of routines' (functions and stored procedures) parameters (may not contain data for some routines which accept any type of parameter)">
     <column name="specific_catalog" pkey="TRUE"/>
-    <column name="specific_schema" pkey="TRUE"/>
+    <column name="specific_schema" pkey="TRUE" ident="TRUE"/>
     <column name="specific_name" pkey="TRUE"/>
     <column name="ordinal_position" type="gint" pkey="TRUE"/>
     <column name="parameter_mode"/>
-    <column name="parameter_name" nullok="TRUE"/>
-    <column name="data_type" nullok="TRUE" descr="Data type of the parameter (if the parameter is an array, then 'array_spec' is set, and this may be NULL; can also be NULL if any type of parameter is accepted)"/>
+    <column name="parameter_name" nullok="TRUE" ident="TRUE"/>
+    <column name="data_type" nullok="TRUE" descr="Data type of the parameter (if the parameter is an array, then 'array_spec' is set, and this may be NULL; can also be NULL if any type of parameter is accepted)" ident="TRUE"/>
     <column name="array_spec" nullok="TRUE" descr="Array description if the parameter is an array"/>
     <fkey ref_table="_routines">
       <part column="specific_catalog"/>
@@ -519,11 +519,11 @@
 
   <table name="_routine_columns" descr="List of routines' (functions and stored procedures) returned values' parts (columns) for routines returning composed values">
     <column name="specific_catalog" pkey="TRUE"/>
-    <column name="specific_schema" pkey="TRUE"/>
+    <column name="specific_schema" pkey="TRUE" ident="TRUE"/>
     <column name="specific_name" pkey="TRUE"/>
-    <column name="column_name" pkey="TRUE"/>
+    <column name="column_name" pkey="TRUE" ident="TRUE"/>
     <column name="ordinal_position" type="gint" nullok="TRUE" pkey="TRUE"/>
-    <column name="data_type" nullok="TRUE" descr="Data type of the column (if the column is an array, then 'array_spec' is set, and this may be NULL)"/>
+    <column name="data_type" nullok="TRUE" descr="Data type of the column (if the column is an array, then 'array_spec' is set, and this may be NULL)" ident="TRUE"/>
     <column name="array_spec" nullok="TRUE" descr="Array description if the column is an array"/>
     <fkey ref_table="_routines">
       <part column="specific_catalog"/>
diff --git a/libgda/sql-parser/gda-statement-struct-util.c b/libgda/sql-parser/gda-statement-struct-util.c
index bd86888..4592a89 100644
--- a/libgda/sql-parser/gda-statement-struct-util.c
+++ b/libgda/sql-parser/gda-statement-struct-util.c
@@ -291,16 +291,45 @@ _string_is_identifier (const gchar *str)
  * Tells if @str needs to be quoted before using it in an SQL statement. To actually add quotes,
  * use gda_sql_identifier_add_quotes().
  *
+ * To determine if quotes are needed: the following rules are applied:
+ * <itemizedlist>
+ *  <listitem><para>If the 1st character is a digit, then %TRUE is returned</para></listitem>
+ *  <listitem><para>If there are mixed lower and upper case letters, then %TRUE is returned</para></listitem>
+ *  <listitem><para>If there are other characters than digits, letters and the '_', '$' and '#', then %TRUE is returned</para></listitem>
+ *  <listitem><para>Otherwise %FALSE is returned</para></listitem>
+ * </itemizedlist>
+ *
  * Returns: TRUE if @str needs some quotes
  */
 gboolean
 gda_sql_identifier_needs_quotes (const gchar *str)
 {
 	const gchar *ptr;
+	gchar icase = 0;
 
 	g_return_val_if_fail (str, FALSE);
 	for (ptr = str; *ptr; ptr++) {
-		if (*ptr != g_ascii_tolower (*ptr))
+		/* quote if 1st char is a number */
+		if ((*ptr <= '9') && (*ptr >= '0')) {
+			if (ptr == str)
+				return TRUE;
+			continue;
+		}
+		if ((*ptr >= 'A') && (*ptr <= 'Z')) {
+			if (icase == 0) /* first alpha char encountered */
+				icase = 'U';
+			else if (icase == 'L') /* @str has mixed case */
+				return TRUE;
+			continue;
+		}
+		if ((*ptr >= 'a') && (*ptr <= 'z')) {
+			if (icase == 0) /* first alpha char encountered */
+				icase = 'L';
+			else if (icase == 'U')
+				return TRUE; /* @str has mixed case */
+			continue;
+		}
+		if ((*ptr != '$') && (*ptr != '_') && (*ptr != '#'))
 			return TRUE;
 	}
 	return FALSE;
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 799ea1e..a022d40 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -4,6 +4,7 @@ libgda/gda-connection.c
 libgda/gda-connection-event.c
 libgda/gda-data-access-wrapper.c
 libgda/gda-data-comparator.c
+libgda/gda-data-meta-wrapper.c
 libgda/gda-data-model-array.c
 libgda/gda-data-model-bdb.c
 libgda/gda-data-model.c
diff --git a/tests/.gitignore b/tests/.gitignore
index b0f19ac..3d3b592 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -1,2 +1,3 @@
 test-bin-converter
 test-ddl-creator
+test-sql-identifier
diff --git a/tests/Makefile.am b/tests/Makefile.am
index b05641b..7224cde 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,6 +1,6 @@
 noinst_LTLIBRARIES = libgda-test-4.0.la
-TESTS = test-ddl-creator test-bin-converter
-check_PROGRAMS = test-ddl-creator test-bin-converter
+TESTS = test-ddl-creator test-bin-converter test-sql-identifier
+check_PROGRAMS = test-ddl-creator test-bin-converter test-sql-identifier
 
 
 SUBDIRS = providers parser value-holders meta-store data-models multi-threading
@@ -45,4 +45,11 @@ test_bin_converter_LDADD = \
 	libgda-test-4.0.la \
         $(LIBGDA_LIBS)
 
+test_sql_identifier_SOURCES = \
+        test-sql-identifier.c
+
+test_sql_identifier_LDADD = \
+        $(top_builddir)/libgda/libgda-4.0.la \
+        $(LIBGDA_LIBS)
+
 EXTRA_DIST = dbstruct.xml
\ No newline at end of file
diff --git a/tests/meta-store/data_table_constraints.csv b/tests/meta-store/data_table_constraints.csv
index d9cd57d..2f00177 100644
--- a/tests/meta-store/data_table_constraints.csv
+++ b/tests/meta-store/data_table_constraints.csv
@@ -1,144 +1,144 @@
-"meta","public","2200_78469_1_not_null","meta","public","_attributes","CHECK","att_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78469_2_not_null","meta","public","_attributes","CHECK","att_value IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78476_1_not_null","meta","public","_information_schema_catalog_name","CHECK","catalog_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78483_1_not_null","meta","public","_builtin_data_types","CHECK","short_type_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78483_2_not_null","meta","public","_builtin_data_types","CHECK","full_type_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78483_6_not_null","meta","public","_builtin_data_types","CHECK","internal IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78490_1_not_null","meta","public","_udt","CHECK","udt_catalog IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78490_2_not_null","meta","public","_udt","CHECK","udt_schema IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78490_3_not_null","meta","public","_udt","CHECK","udt_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78490_6_not_null","meta","public","_udt","CHECK","udt_short_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78490_7_not_null","meta","public","_udt","CHECK","udt_full_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78490_8_not_null","meta","public","_udt","CHECK","udt_internal IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78497_1_not_null","meta","public","_element_types","CHECK","specific_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78497_2_not_null","meta","public","_element_types","CHECK","object_catalog IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78497_3_not_null","meta","public","_element_types","CHECK","object_schema IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78497_4_not_null","meta","public","_element_types","CHECK","object_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78497_6_not_null","meta","public","_element_types","CHECK","object_type IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78497_7_not_null","meta","public","_element_types","CHECK","data_type IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78497_8_not_null","meta","public","_element_types","CHECK","min_cardinality IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78497_9_not_null","meta","public","_element_types","CHECK","max_cardinality IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78504_1_not_null","meta","public","_schemata","CHECK","catalog_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78504_2_not_null","meta","public","_schemata","CHECK","schema_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78504_4_not_null","meta","public","_schemata","CHECK","schema_internal IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78516_11_not_null","meta","public","_udt_columns","CHECK","character_set_catalog IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78516_12_not_null","meta","public","_udt_columns","CHECK","character_set_schema IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78516_13_not_null","meta","public","_udt_columns","CHECK","character_set_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78516_14_not_null","meta","public","_udt_columns","CHECK","collation_catalog IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78516_15_not_null","meta","public","_udt_columns","CHECK","collation_schema IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78516_16_not_null","meta","public","_udt_columns","CHECK","collation_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78516_1_not_null","meta","public","_udt_columns","CHECK","udt_catalog IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78516_2_not_null","meta","public","_udt_columns","CHECK","udt_schema IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78516_3_not_null","meta","public","_udt_columns","CHECK","udt_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78516_4_not_null","meta","public","_udt_columns","CHECK","udt_column IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78516_5_not_null","meta","public","_udt_columns","CHECK","data_type IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78528_1_not_null","meta","public","_enums","CHECK","udt_catalog IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78528_2_not_null","meta","public","_enums","CHECK","udt_schema IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78528_3_not_null","meta","public","_enums","CHECK","udt_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78528_4_not_null","meta","public","_enums","CHECK","label IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78540_18_not_null","meta","public","_domains","CHECK","domain_short_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78540_19_not_null","meta","public","_domains","CHECK","domain_full_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78540_1_not_null","meta","public","_domains","CHECK","domain_catalog IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78540_20_not_null","meta","public","_domains","CHECK","domain_internal IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78540_2_not_null","meta","public","_domains","CHECK","domain_schema IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78540_3_not_null","meta","public","_domains","CHECK","domain_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78552_1_not_null","meta","public","_tables","CHECK","table_catalog IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78552_2_not_null","meta","public","_tables","CHECK","table_schema IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78552_3_not_null","meta","public","_tables","CHECK","table_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78552_4_not_null","meta","public","_tables","CHECK","table_type IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78552_7_not_null","meta","public","_tables","CHECK","table_short_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78552_8_not_null","meta","public","_tables","CHECK","table_full_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78564_1_not_null","meta","public","_collations","CHECK","collation_catalog IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78564_2_not_null","meta","public","_collations","CHECK","collation_schema IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78564_3_not_null","meta","public","_collations","CHECK","collation_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78564_5_not_null","meta","public","_collations","CHECK","collation_short_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78564_6_not_null","meta","public","_collations","CHECK","collation_full_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78576_19_not_null","meta","public","_routines","CHECK","routine_short_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78576_1_not_null","meta","public","_routines","CHECK","specific_catalog IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78576_20_not_null","meta","public","_routines","CHECK","routine_full_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78576_2_not_null","meta","public","_routines","CHECK","specific_schema IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78576_3_not_null","meta","public","_routines","CHECK","specific_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78576_6_not_null","meta","public","_routines","CHECK","routine_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78576_9_not_null","meta","public","_routines","CHECK","returns_set IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78588_1_not_null","meta","public","_views","CHECK","table_catalog IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78588_2_not_null","meta","public","_views","CHECK","table_schema IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78588_3_not_null","meta","public","_views","CHECK","table_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78600_1_not_null","meta","public","_character_sets","CHECK","character_set_catalog IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78600_2_not_null","meta","public","_character_sets","CHECK","character_set_schema IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78600_3_not_null","meta","public","_character_sets","CHECK","character_set_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78600_8_not_null","meta","public","_character_sets","CHECK","character_set_short_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78600_9_not_null","meta","public","_character_sets","CHECK","character_set_full_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78617_10_not_null","meta","public","_triggers","CHECK","condition_timing IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78617_12_not_null","meta","public","_triggers","CHECK","trigger_short_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78617_13_not_null","meta","public","_triggers","CHECK","trigger_full_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78617_1_not_null","meta","public","_triggers","CHECK","trigger_catalog IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78617_2_not_null","meta","public","_triggers","CHECK","trigger_schema IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78617_3_not_null","meta","public","_triggers","CHECK","trigger_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78617_4_not_null","meta","public","_triggers","CHECK","event_manipulation IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78617_5_not_null","meta","public","_triggers","CHECK","event_object_catalog IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78617_6_not_null","meta","public","_triggers","CHECK","event_object_schema IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78617_7_not_null","meta","public","_triggers","CHECK","event_object_table IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78617_9_not_null","meta","public","_triggers","CHECK","action_orientation IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78634_1_not_null","meta","public","_table_constraints","CHECK","constraint_catalog IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78634_2_not_null","meta","public","_table_constraints","CHECK","constraint_schema IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78634_3_not_null","meta","public","_table_constraints","CHECK","constraint_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78634_4_not_null","meta","public","_table_constraints","CHECK","table_catalog IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78634_5_not_null","meta","public","_table_constraints","CHECK","table_schema IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78634_6_not_null","meta","public","_table_constraints","CHECK","table_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78634_7_not_null","meta","public","_table_constraints","CHECK","constraint_type IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78651_1_not_null","meta","public","_domain_constraints","CHECK","constraint_catalog IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78651_2_not_null","meta","public","_domain_constraints","CHECK","constraint_schema IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78651_3_not_null","meta","public","_domain_constraints","CHECK","constraint_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78651_4_not_null","meta","public","_domain_constraints","CHECK","domain_catalog IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78651_5_not_null","meta","public","_domain_constraints","CHECK","domain_schema IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78651_6_not_null","meta","public","_domain_constraints","CHECK","domain_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78668_1_not_null","meta","public","_parameters","CHECK","specific_catalog IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78668_2_not_null","meta","public","_parameters","CHECK","specific_schema IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78668_3_not_null","meta","public","_parameters","CHECK","specific_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78668_4_not_null","meta","public","_parameters","CHECK","ordinal_position IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78668_5_not_null","meta","public","_parameters","CHECK","parameter_mode IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78668_7_not_null","meta","public","_parameters","CHECK","data_type IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78680_1_not_null","meta","public","_routine_columns","CHECK","specific_catalog IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78680_2_not_null","meta","public","_routine_columns","CHECK","specific_schema IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78680_3_not_null","meta","public","_routine_columns","CHECK","specific_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78680_4_not_null","meta","public","_routine_columns","CHECK","column_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78680_5_not_null","meta","public","_routine_columns","CHECK","ordinal_position IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78680_6_not_null","meta","public","_routine_columns","CHECK","data_type IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78696_1_not_null","meta","public","_columns","CHECK","table_catalog IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78696_2_not_null","meta","public","_columns","CHECK","table_schema IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78696_3_not_null","meta","public","_columns","CHECK","table_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78696_4_not_null","meta","public","_columns","CHECK","column_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78696_5_not_null","meta","public","_columns","CHECK","ordinal_position IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78696_7_not_null","meta","public","_columns","CHECK","is_nullable IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78696_8_not_null","meta","public","_columns","CHECK","data_type IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78718_1_not_null","meta","public","_referential_constraints","CHECK","constraint_catalog IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78718_2_not_null","meta","public","_referential_constraints","CHECK","constraint_schema IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78718_3_not_null","meta","public","_referential_constraints","CHECK","constraint_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78718_4_not_null","meta","public","_referential_constraints","CHECK","unique_constraint_catalog IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78718_5_not_null","meta","public","_referential_constraints","CHECK","unique_constraint_schema IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78718_6_not_null","meta","public","_referential_constraints","CHECK","unique_constraint_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78738_1_not_null","meta","public","_key_column_usage","CHECK","constraint_catalog IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78738_2_not_null","meta","public","_key_column_usage","CHECK","constraint_schema IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78738_3_not_null","meta","public","_key_column_usage","CHECK","constraint_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78738_4_not_null","meta","public","_key_column_usage","CHECK","table_catalog IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78738_5_not_null","meta","public","_key_column_usage","CHECK","table_schema IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78738_6_not_null","meta","public","_key_column_usage","CHECK","table_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78738_7_not_null","meta","public","_key_column_usage","CHECK","column_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78738_8_not_null","meta","public","_key_column_usage","CHECK","ordinal_position IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78755_1_not_null","meta","public","_check_column_usage","CHECK","constraint_catalog IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78755_2_not_null","meta","public","_check_column_usage","CHECK","constraint_schema IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78755_3_not_null","meta","public","_check_column_usage","CHECK","constraint_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78755_4_not_null","meta","public","_check_column_usage","CHECK","table_catalog IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78755_5_not_null","meta","public","_check_column_usage","CHECK","table_schema IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78755_6_not_null","meta","public","_check_column_usage","CHECK","table_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78755_7_not_null","meta","public","_check_column_usage","CHECK","column_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78772_1_not_null","meta","public","_view_column_usage","CHECK","view_catalog IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78772_2_not_null","meta","public","_view_column_usage","CHECK","view_schema IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78772_3_not_null","meta","public","_view_column_usage","CHECK","view_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78772_4_not_null","meta","public","_view_column_usage","CHECK","table_catalog IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78772_5_not_null","meta","public","_view_column_usage","CHECK","table_schema IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78772_6_not_null","meta","public","_view_column_usage","CHECK","table_name IS NOT NULL",FALSE,FALSE
-"meta","public","2200_78772_7_not_null","meta","public","_view_column_usage","CHECK","column_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78469_1_not_null""","meta","public","_attributes","CHECK","att_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78469_2_not_null""","meta","public","_attributes","CHECK","att_value IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78476_1_not_null""","meta","public","_information_schema_catalog_name","CHECK","catalog_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78483_1_not_null""","meta","public","_builtin_data_types","CHECK","short_type_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78483_2_not_null""","meta","public","_builtin_data_types","CHECK","full_type_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78483_6_not_null""","meta","public","_builtin_data_types","CHECK","internal IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78490_1_not_null""","meta","public","_udt","CHECK","udt_catalog IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78490_2_not_null""","meta","public","_udt","CHECK","udt_schema IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78490_3_not_null""","meta","public","_udt","CHECK","udt_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78490_6_not_null""","meta","public","_udt","CHECK","udt_short_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78490_7_not_null""","meta","public","_udt","CHECK","udt_full_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78490_8_not_null""","meta","public","_udt","CHECK","udt_internal IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78497_1_not_null""","meta","public","_element_types","CHECK","specific_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78497_2_not_null""","meta","public","_element_types","CHECK","object_catalog IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78497_3_not_null""","meta","public","_element_types","CHECK","object_schema IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78497_4_not_null""","meta","public","_element_types","CHECK","object_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78497_6_not_null""","meta","public","_element_types","CHECK","object_type IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78497_7_not_null""","meta","public","_element_types","CHECK","data_type IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78497_8_not_null""","meta","public","_element_types","CHECK","min_cardinality IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78497_9_not_null""","meta","public","_element_types","CHECK","max_cardinality IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78504_1_not_null""","meta","public","_schemata","CHECK","catalog_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78504_2_not_null""","meta","public","_schemata","CHECK","schema_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78504_4_not_null""","meta","public","_schemata","CHECK","schema_internal IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78516_11_not_null""","meta","public","_udt_columns","CHECK","character_set_catalog IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78516_12_not_null""","meta","public","_udt_columns","CHECK","character_set_schema IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78516_13_not_null""","meta","public","_udt_columns","CHECK","character_set_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78516_14_not_null""","meta","public","_udt_columns","CHECK","collation_catalog IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78516_15_not_null""","meta","public","_udt_columns","CHECK","collation_schema IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78516_16_not_null""","meta","public","_udt_columns","CHECK","collation_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78516_1_not_null""","meta","public","_udt_columns","CHECK","udt_catalog IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78516_2_not_null""","meta","public","_udt_columns","CHECK","udt_schema IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78516_3_not_null""","meta","public","_udt_columns","CHECK","udt_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78516_4_not_null""","meta","public","_udt_columns","CHECK","udt_column IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78516_5_not_null""","meta","public","_udt_columns","CHECK","data_type IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78528_1_not_null""","meta","public","_enums","CHECK","udt_catalog IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78528_2_not_null""","meta","public","_enums","CHECK","udt_schema IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78528_3_not_null""","meta","public","_enums","CHECK","udt_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78528_4_not_null""","meta","public","_enums","CHECK","label IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78540_18_not_null""","meta","public","_domains","CHECK","domain_short_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78540_19_not_null""","meta","public","_domains","CHECK","domain_full_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78540_1_not_null""","meta","public","_domains","CHECK","domain_catalog IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78540_20_not_null""","meta","public","_domains","CHECK","domain_internal IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78540_2_not_null""","meta","public","_domains","CHECK","domain_schema IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78540_3_not_null""","meta","public","_domains","CHECK","domain_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78552_1_not_null""","meta","public","_tables","CHECK","table_catalog IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78552_2_not_null""","meta","public","_tables","CHECK","table_schema IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78552_3_not_null""","meta","public","_tables","CHECK","table_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78552_4_not_null""","meta","public","_tables","CHECK","table_type IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78552_7_not_null""","meta","public","_tables","CHECK","table_short_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78552_8_not_null""","meta","public","_tables","CHECK","table_full_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78564_1_not_null""","meta","public","_collations","CHECK","collation_catalog IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78564_2_not_null""","meta","public","_collations","CHECK","collation_schema IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78564_3_not_null""","meta","public","_collations","CHECK","collation_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78564_5_not_null""","meta","public","_collations","CHECK","collation_short_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78564_6_not_null""","meta","public","_collations","CHECK","collation_full_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78576_19_not_null""","meta","public","_routines","CHECK","routine_short_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78576_1_not_null""","meta","public","_routines","CHECK","specific_catalog IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78576_20_not_null""","meta","public","_routines","CHECK","routine_full_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78576_2_not_null""","meta","public","_routines","CHECK","specific_schema IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78576_3_not_null""","meta","public","_routines","CHECK","specific_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78576_6_not_null""","meta","public","_routines","CHECK","routine_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78576_9_not_null""","meta","public","_routines","CHECK","returns_set IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78588_1_not_null""","meta","public","_views","CHECK","table_catalog IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78588_2_not_null""","meta","public","_views","CHECK","table_schema IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78588_3_not_null""","meta","public","_views","CHECK","table_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78600_1_not_null""","meta","public","_character_sets","CHECK","character_set_catalog IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78600_2_not_null""","meta","public","_character_sets","CHECK","character_set_schema IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78600_3_not_null""","meta","public","_character_sets","CHECK","character_set_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78600_8_not_null""","meta","public","_character_sets","CHECK","character_set_short_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78600_9_not_null""","meta","public","_character_sets","CHECK","character_set_full_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78617_10_not_null""","meta","public","_triggers","CHECK","condition_timing IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78617_12_not_null""","meta","public","_triggers","CHECK","trigger_short_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78617_13_not_null""","meta","public","_triggers","CHECK","trigger_full_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78617_1_not_null""","meta","public","_triggers","CHECK","trigger_catalog IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78617_2_not_null""","meta","public","_triggers","CHECK","trigger_schema IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78617_3_not_null""","meta","public","_triggers","CHECK","trigger_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78617_4_not_null""","meta","public","_triggers","CHECK","event_manipulation IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78617_5_not_null""","meta","public","_triggers","CHECK","event_object_catalog IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78617_6_not_null""","meta","public","_triggers","CHECK","event_object_schema IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78617_7_not_null""","meta","public","_triggers","CHECK","event_object_table IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78617_9_not_null""","meta","public","_triggers","CHECK","action_orientation IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78634_1_not_null""","meta","public","_table_constraints","CHECK","constraint_catalog IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78634_2_not_null""","meta","public","_table_constraints","CHECK","constraint_schema IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78634_3_not_null""","meta","public","_table_constraints","CHECK","constraint_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78634_4_not_null""","meta","public","_table_constraints","CHECK","table_catalog IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78634_5_not_null""","meta","public","_table_constraints","CHECK","table_schema IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78634_6_not_null""","meta","public","_table_constraints","CHECK","table_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78634_7_not_null""","meta","public","_table_constraints","CHECK","constraint_type IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78651_1_not_null""","meta","public","_domain_constraints","CHECK","constraint_catalog IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78651_2_not_null""","meta","public","_domain_constraints","CHECK","constraint_schema IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78651_3_not_null""","meta","public","_domain_constraints","CHECK","constraint_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78651_4_not_null""","meta","public","_domain_constraints","CHECK","domain_catalog IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78651_5_not_null""","meta","public","_domain_constraints","CHECK","domain_schema IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78651_6_not_null""","meta","public","_domain_constraints","CHECK","domain_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78668_1_not_null""","meta","public","_parameters","CHECK","specific_catalog IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78668_2_not_null""","meta","public","_parameters","CHECK","specific_schema IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78668_3_not_null""","meta","public","_parameters","CHECK","specific_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78668_4_not_null""","meta","public","_parameters","CHECK","ordinal_position IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78668_5_not_null""","meta","public","_parameters","CHECK","parameter_mode IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78668_7_not_null""","meta","public","_parameters","CHECK","data_type IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78680_1_not_null""","meta","public","_routine_columns","CHECK","specific_catalog IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78680_2_not_null""","meta","public","_routine_columns","CHECK","specific_schema IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78680_3_not_null""","meta","public","_routine_columns","CHECK","specific_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78680_4_not_null""","meta","public","_routine_columns","CHECK","column_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78680_5_not_null""","meta","public","_routine_columns","CHECK","ordinal_position IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78680_6_not_null""","meta","public","_routine_columns","CHECK","data_type IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78696_1_not_null""","meta","public","_columns","CHECK","table_catalog IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78696_2_not_null""","meta","public","_columns","CHECK","table_schema IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78696_3_not_null""","meta","public","_columns","CHECK","table_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78696_4_not_null""","meta","public","_columns","CHECK","column_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78696_5_not_null""","meta","public","_columns","CHECK","ordinal_position IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78696_7_not_null""","meta","public","_columns","CHECK","is_nullable IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78696_8_not_null""","meta","public","_columns","CHECK","data_type IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78718_1_not_null""","meta","public","_referential_constraints","CHECK","constraint_catalog IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78718_2_not_null""","meta","public","_referential_constraints","CHECK","constraint_schema IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78718_3_not_null""","meta","public","_referential_constraints","CHECK","constraint_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78718_4_not_null""","meta","public","_referential_constraints","CHECK","unique_constraint_catalog IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78718_5_not_null""","meta","public","_referential_constraints","CHECK","unique_constraint_schema IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78718_6_not_null""","meta","public","_referential_constraints","CHECK","unique_constraint_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78738_1_not_null""","meta","public","_key_column_usage","CHECK","constraint_catalog IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78738_2_not_null""","meta","public","_key_column_usage","CHECK","constraint_schema IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78738_3_not_null""","meta","public","_key_column_usage","CHECK","constraint_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78738_4_not_null""","meta","public","_key_column_usage","CHECK","table_catalog IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78738_5_not_null""","meta","public","_key_column_usage","CHECK","table_schema IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78738_6_not_null""","meta","public","_key_column_usage","CHECK","table_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78738_7_not_null""","meta","public","_key_column_usage","CHECK","column_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78738_8_not_null""","meta","public","_key_column_usage","CHECK","ordinal_position IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78755_1_not_null""","meta","public","_check_column_usage","CHECK","constraint_catalog IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78755_2_not_null""","meta","public","_check_column_usage","CHECK","constraint_schema IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78755_3_not_null""","meta","public","_check_column_usage","CHECK","constraint_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78755_4_not_null""","meta","public","_check_column_usage","CHECK","table_catalog IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78755_5_not_null""","meta","public","_check_column_usage","CHECK","table_schema IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78755_6_not_null""","meta","public","_check_column_usage","CHECK","table_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78755_7_not_null""","meta","public","_check_column_usage","CHECK","column_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78772_1_not_null""","meta","public","_view_column_usage","CHECK","view_catalog IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78772_2_not_null""","meta","public","_view_column_usage","CHECK","view_schema IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78772_3_not_null""","meta","public","_view_column_usage","CHECK","view_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78772_4_not_null""","meta","public","_view_column_usage","CHECK","table_catalog IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78772_5_not_null""","meta","public","_view_column_usage","CHECK","table_schema IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78772_6_not_null""","meta","public","_view_column_usage","CHECK","table_name IS NOT NULL",FALSE,FALSE
+"meta","public","""2200_78772_7_not_null""","meta","public","_view_column_usage","CHECK","column_name IS NOT NULL",FALSE,FALSE
 "meta","public","_attributes_pkey","meta","public","_attributes","PRIMARY KEY","NULL",FALSE,FALSE
 "meta","public","_builtin_data_types_pkey","meta","public","_builtin_data_types","PRIMARY KEY","NULL",FALSE,FALSE
 "meta","public","_character_sets_character_set_catalog_fkey","meta","public","_character_sets","FOREIGN KEY","NULL",FALSE,FALSE
diff --git a/tests/test-sql-identifier.c b/tests/test-sql-identifier.c
new file mode 100644
index 0000000..79dcc6e
--- /dev/null
+++ b/tests/test-sql-identifier.c
@@ -0,0 +1,65 @@
+/* 
+ * Copyright (C) 2009 The GNOME Foundation.
+ *
+ * AUTHORS:
+ *      Vivien Malerba <malerba gnome-db org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <libgda/sql-parser/gda-sql-parser.h>
+
+typedef struct {
+	gchar *sql_identifier;
+	gboolean need_quotes;
+} ATest;
+
+ATest tests[] = {
+	{"\"Solution\"", TRUE},
+	{"mytable", FALSE},
+	{"MYTABLE", FALSE},
+	{"MyTable", TRUE},
+	{"my.blob", TRUE},
+	{"_table", FALSE},
+	{"$table", FALSE},
+	{"#table", FALSE},
+	{"8table", TRUE},
+	{"t8ble", FALSE},
+	{"t8ble_1", FALSE},
+	{"t8ble_A", TRUE},
+	{"T8BLE_A", FALSE},
+	{"T8BLE_a", TRUE},
+};
+
+int
+main (int argc, char** argv)
+{
+	gint i, nfailed = 0;
+	for (i = 0; i < G_N_ELEMENTS (tests); i++) {
+		ATest *test = &(tests [i]);
+		if (gda_sql_identifier_needs_quotes (test->sql_identifier) != test->need_quotes) {
+			g_print ("Failed for %s: reported %s\n", test->sql_identifier,
+				 test->need_quotes ? "no quotes needed" : "quotes needed");
+			nfailed++;
+		}
+	}
+
+	g_print ("%d tests executed, ", i);
+	if (nfailed > 0)
+		g_print ("%d failed\n", nfailed);
+	else
+		g_print ("Ok\n");
+	return EXIT_SUCCESS;
+}
diff --git a/tools/tools-input.c b/tools/tools-input.c
index 99e2f6e..045a87d 100644
--- a/tools/tools-input.c
+++ b/tools/tools-input.c
@@ -205,6 +205,7 @@ set_completion_func (CompletionFunc func)
 #ifdef HAVE_READLINE	
 	rl_attempted_completion_function = func;
 	rl_basic_word_break_characters = " \t\n\\'` $><=;|&{(";
+	rl_completer_word_break_characters = " \t\n\\'` $><=;|&{(";
 #endif	
 }
 



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