[libgda] Better handle SQL identifiers' case sensitiveness



commit 6f0002e1fb637b5fa583d35d7d434067718bca28
Author: Vivien Malerba <malerba gnome-db org>
Date:   Fri May 1 22:21:41 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
---
 ChangeLog                                     |   18 +
 doc/C/libgda-4.0-docs.sgml                    |   11 +-
 doc/C/libgda-4.0-sections.txt                 |    2 +
 doc/C/tmpl/provider-support.sgml              |   17 +
 gtk-doc.make                                  |   47 ++-
 libgda/Makefile.am                            |    2 +
 libgda/gda-data-access-wrapper.h              |    1 -
 libgda/gda-data-meta-wrapper.c                |  545 +++++++++++++++++++++++++
 libgda/gda-data-meta-wrapper.h                |   67 +++
 libgda/gda-enums.h                            |    8 +-
 libgda/gda-meta-store.c                       |   87 ++++-
 libgda/gda-meta-store.h                       |    1 +
 libgda/gda-meta-struct.c                      |   33 +-
 libgda/gda-util.c                             |   85 ++---
 libgda/information_schema.xml                 |  194 +++++-----
 libgda/sql-parser/gda-statement-struct-util.c |    2 +-
 tools/tools-input.c                           |    1 +
 17 files changed, 926 insertions(+), 195 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index f22bfe7..7dea9de 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2009-05-01  Vivien Malerba <malerba gnome-db org>
+
+	* 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
+
 2009-04-28  Vivien Malerba <malerba gnome-db org>
 
 	* libgda.doap: prefixed mail with "mailto:";
diff --git a/doc/C/libgda-4.0-docs.sgml b/doc/C/libgda-4.0-docs.sgml
index 46085c7..45802ee 100644
--- a/doc/C/libgda-4.0-docs.sgml
+++ b/doc/C/libgda-4.0-docs.sgml
@@ -1072,10 +1072,13 @@ 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.
+	    SQL identifiers (database object's names) are generally case insensitive, but it is still possible to
+	    have case sensitive SQL identifier if they are enclosed between double quotes. Each database has its own
+	    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). To harmonize meta data information usage, &LIBGDA; has chosen
+	    to represent case insensitive SQL identifiers in lower case 
+	    and case sensitive SQL identifiers enclosed between double quotes. 
 	  </para>
 	  <para>
 	    This convention must be respected by database providers' implementations or the 
diff --git a/doc/C/libgda-4.0-sections.txt b/doc/C/libgda-4.0-sections.txt
index aa74914..a1dabfc 100644
--- a/doc/C/libgda-4.0-sections.txt
+++ b/doc/C/libgda-4.0-sections.txt
@@ -1457,6 +1457,8 @@ gda_connection_internal_change_transaction_state
 <SUBSECTION>
 gda_meta_store_modify
 gda_meta_store_modify_with_context
+GdaSqlIdentifierStyle
+gda_meta_store_set_identifiers_style
 <SUBSECTION>
 gda_compute_dml_statements
 gda_compute_select_statement_from_update
diff --git a/doc/C/tmpl/provider-support.sgml b/doc/C/tmpl/provider-support.sgml
index aa7a45e..260654d 100644
--- a/doc/C/tmpl/provider-support.sgml
+++ b/doc/C/tmpl/provider-support.sgml
@@ -349,6 +349,23 @@ Methods dedicated to implementing providers
 @Returns: 
 
 
+<!-- ##### ENUM GdaSqlIdentifierStyle ##### -->
+<para>
+  Specifies how SQL identifiers are represented by a specific database.
+</para>
+
+ GDA_SQL_IDENTIFIERS_LOWER_CASE: case insensitive SQL identifiers are represented in lower case (meaning that any SQL identifier which has a non lower case character is case sensitive)
+ GDA_SQL_IDENTIFIERS_UPPER_CASE: case insensitive SQL identifiers are represented in upper case (meaning that any SQL identifier which has a non upper case character is case sensitive)
+
+<!-- ##### FUNCTION gda_meta_store_set_identifiers_style ##### -->
+<para>
+
+</para>
+
+ store: 
+ style: 
+
+
 <!-- ##### FUNCTION gda_compute_dml_statements ##### -->
 <para>
 
diff --git a/gtk-doc.make b/gtk-doc.make
index 354ffb7..0f87cc7 100644
--- a/gtk-doc.make
+++ b/gtk-doc.make
@@ -7,9 +7,11 @@
 if GTK_DOC_USE_LIBTOOL
 GTKDOC_CC = $(LIBTOOL) --mode=compile $(CC) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
 GTKDOC_LD = $(LIBTOOL) --mode=link $(CC) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS)
+GTKDOC_RUN = $(LIBTOOL) --mode=execute
 else
 GTKDOC_CC = $(CC) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
 GTKDOC_LD = $(CC) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS)
+GTKDOC_RUN = sh -c
 endif
 
 # We set GPATH here; this gives us semantics for GNU make
@@ -53,6 +55,8 @@ endif
 
 docs: html-build.stamp
 
+$(REPORT_FILES): sgml-build.stamp
+
 #### scan ####
 
 scan-build.stamp: $(HFILE_GLOB) $(CFILE_GLOB)
@@ -61,7 +65,7 @@ scan-build.stamp: $(HFILE_GLOB) $(CFILE_GLOB)
 	cd $(srcdir) && \
 	  gtkdoc-scan --module=$(DOC_MODULE) --source-dir=$(DOC_SOURCE_DIR) --ignore-headers="$(IGNORE_HFILES)" $(SCAN_OPTIONS) $(EXTRA_HFILES)
 	if grep -l '^..*$$' $(srcdir)/$(DOC_MODULE).types > /dev/null 2>&1 ; then \
-	    CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" CFLAGS="$(GTKDOC_CFLAGS)" LDFLAGS="$(GTKDOC_LIBS)" gtkdoc-scangobj $(SCANGOBJ_OPTIONS) --module=$(DOC_MODULE) --output-dir=$(srcdir) ; \
+	    CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" RUN="$(GTKDOC_RUN)" CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS)" LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" gtkdoc-scangobj $(SCANGOBJ_OPTIONS) --module=$(DOC_MODULE) --output-dir=$(srcdir) ; \
 	else \
 	    cd $(srcdir) ; \
 	    for i in $(SCANOBJ_FILES) ; do \
@@ -107,7 +111,12 @@ html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files)
 	@-chmod -R u+w $(srcdir)
 	rm -rf $(srcdir)/html
 	mkdir $(srcdir)/html
-	cd $(srcdir)/html && gtkdoc-mkhtml $(DOC_MODULE) ../$(DOC_MAIN_SGML_FILE)
+	mkhtml_options=""; \
+	gtkdoc-mkhtml 2>&1 --help | grep  >/dev/null "\-\-path"; \
+	if test "$(?)" = "0"; then \
+	  mkhtml_options=--path="$(srcdir)"; \
+	fi
+	cd $(srcdir)/html && gtkdoc-mkhtml $(mkhtml_options) $(MKHTML_OPTIONS) $(DOC_MODULE) ../$(DOC_MAIN_SGML_FILE)
 	test "x$(HTML_IMAGES)" = "x" || ( cd $(srcdir) && cp $(HTML_IMAGES) html )
 	@echo 'gtk-doc: Fixing cross-references'
 	cd $(srcdir) && gtkdoc-fixxref --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS)
@@ -128,24 +137,37 @@ maintainer-clean-local: clean
 	cd $(srcdir) && rm -rf xml html
 
 install-data-local:
-	-installfiles=`echo $(srcdir)/html/*`; \
+	installfiles=`echo $(srcdir)/html/*`; \
 	if test "$$installfiles" = '$(srcdir)/html/*'; \
 	then echo '-- Nothing to install' ; \
 	else \
-	  $(mkinstalldirs) $(DESTDIR)$(TARGET_DIR); \
+	  if test -n "$(DOC_MODULE_VERSION)"; then \
+	    installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \
+	  else \
+	    installdir="$(DESTDIR)$(TARGET_DIR)"; \
+	  fi; \
+	  $(mkinstalldirs) $${installdir} ; \
 	  for i in $$installfiles; do \
 	    echo '-- Installing '$$i ; \
-	    $(INSTALL_DATA) $$i $(DESTDIR)$(TARGET_DIR); \
+	    $(INSTALL_DATA) $$i $${installdir}; \
 	  done; \
-	  echo '-- Installing $(srcdir)/html/index.sgml' ; \
-	  $(INSTALL_DATA) $(srcdir)/html/index.sgml $(DESTDIR)$(TARGET_DIR) || :; \
-	  which gtkdoc-rebase >/dev/null && \
-	    gtkdoc-rebase --relative --dest-dir=$(DESTDIR) --html-dir=$(DESTDIR)$(TARGET_DIR) ; \
+	  if test -n "$(DOC_MODULE_VERSION)"; then \
+	    mv -f $${installdir}/$(DOC_MODULE).devhelp2 \
+	      $${installdir}/$(DOC_MODULE)-$(DOC_MODULE_VERSION).devhelp2; \
+	    mv -f $${installdir}/$(DOC_MODULE).devhelp \
+	      $${installdir}/$(DOC_MODULE)-$(DOC_MODULE_VERSION).devhelp; \
+	  fi; \
+	  ! which gtkdoc-rebase >/dev/null 2>&1 || \
+	    gtkdoc-rebase --relative --dest-dir=$(DESTDIR) --html-dir=$${installdir} ; \
 	fi
-	
 
 uninstall-local:
-	rm -f $(DESTDIR)$(TARGET_DIR)/*
+	if test -n "$(DOC_MODULE_VERSION)"; then \
+	  installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \
+	else \
+	  installdir="$(DESTDIR)$(TARGET_DIR)"; \
+	fi; \
+	rm -rf $${installdir}
 
 #
 # Require gtk-doc when making dist
@@ -168,6 +190,7 @@ dist-hook: dist-check-gtkdoc dist-hook-local
 	-cp $(srcdir)/$(DOC_MODULE).types $(distdir)/
 	-cp $(srcdir)/$(DOC_MODULE)-sections.txt $(distdir)/
 	cd $(distdir) && rm -f $(DISTCLEANFILES)
-	-gtkdoc-rebase --online --relative --html-dir=$(distdir)/html
+	! which gtkdoc-rebase >/dev/null 2>&1 || \
+	  gtkdoc-rebase --online --relative --html-dir=$(distdir)/html
 
 .PHONY : dist-hook-local docs
diff --git a/libgda/Makefile.am b/libgda/Makefile.am
index 563c45d..79a278c 100644
--- a/libgda/Makefile.am
+++ b/libgda/Makefile.am
@@ -114,6 +114,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-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..17bf87e
--- /dev/null
+++ b/libgda/gda-data-meta-wrapper.c
@@ -0,0 +1,545 @@
+/* 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++) {
+		if ((*ptr == ' ') || (*ptr == '"') ||
+		    ((mode == GDA_SQL_IDENTIFIERS_LOWER_CASE) && (*ptr != g_ascii_tolower (*ptr))) ||
+		    ((mode == GDA_SQL_IDENTIFIERS_UPPER_CASE) && (*ptr != g_ascii_toupper (*ptr))))
+			return TRUE;
+	}
+	return FALSE;
+}
+
+/*
+ * 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 */
+	if (identifier_needs_quotes (str, mode)) {
+		gchar **sa = g_strsplit (str, ".", 0);
+		if (sa[1]) {
+			gint i;
+			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;
+				}
+			}
+			retval = gda_value_new (G_TYPE_STRING);
+			g_value_take_string (retval, g_strjoinv (".", sa));
+		}
+		else {
+			retval = gda_value_new (G_TYPE_STRING);
+			g_value_take_string (retval, gda_sql_identifier_add_quotes (str));
+		}
+		g_strfreev (sa);
+		return retval;
+	}
+	else
+		return NULL;
+}
+
+/*
+ * 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.c b/libgda/gda-meta-store.c
index 78c808a..2e89aa7 100644
--- a/libgda/gda-meta-store.c
+++ b/libgda/gda-meta-store.c
@@ -43,6 +43,7 @@
 #include <libgda/gda-lockable.h>
 #include <libgda/gda-mutex.h>
 #include "gda-types.h"
+#include "gda-data-meta-wrapper.h"
 
 /*
  * Main static functions
@@ -106,6 +107,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);
 
@@ -203,6 +208,7 @@ static gboolean ProviderSpecific_equal (gconstpointer a, gconstpointer b);
 
 struct _GdaMetaStorePrivate {
 	GdaConnection *cnc;
+	GdaSqlIdentifierStyle ident_style;
 	gint           version;
 	gboolean       schema_ok;
 
@@ -487,6 +493,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;
 
@@ -779,6 +786,23 @@ gda_meta_store_get_property (GObject *object,
 	}
 }
 
+/**
+ * gda_meta_store_set_identifiers_style
+ * @store: a #GdaMetaStore object
+ * @style: a style
+ *
+ * Specifies how @store must handle SQL identifiers it has to store. This method is mainly used by
+ * database providers.
+ *
+ * Since: 4.2
+ */
+void
+gda_meta_store_set_identifiers_style (GdaMetaStore *store, GdaSqlIdentifierStyle style)
+{
+	g_return_if_fail (GDA_IS_META_STORE (store));
+	store->priv->ident_style = style;
+}
+
 /*
  * Checks the structure of @store->priv->cnc and update it if necessary
  */
@@ -1335,26 +1359,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);
                         }
@@ -1370,6 +1392,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);
@@ -1887,6 +1925,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
@@ -2301,12 +2341,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++) {
@@ -2317,7 +2371,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);
@@ -2328,6 +2382,7 @@ gda_meta_store_modify_v (GdaMetaStore *store, const gchar *table_name,
 				}
 				if (erow < -1) {
 					retval = FALSE;
+					g_object_unref (wrapped_data);
 					goto out;
 				}
 				
@@ -2348,16 +2403,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) {
@@ -2378,6 +2435,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) 
@@ -2395,11 +2453,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) {
@@ -2417,6 +2477,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) 
@@ -2441,11 +2502,12 @@ gda_meta_store_modify_v (GdaMetaStore *store, const gchar *table_name,
 					context.column_values = g_new (GValue *, context.size);
 					
 					for (k = 0; k < tfk->cols_nb; k++) {
-						context.column_values [k] = (GValue*) gda_data_model_get_value_at (new_data, 
+						context.column_values [k] = (GValue*) gda_data_model_get_value_at (wrapped_data, 
 									    tfk->ref_pk_cols_array[k], i, error);
 						if (!context.column_values [k]) {
 							g_free (context.column_values);
 							retval = FALSE;
+							g_object_unref (wrapped_data);
 							goto out;
 						}
 					}
@@ -2470,6 +2532,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;
 					}
 				}
diff --git a/libgda/gda-meta-store.h b/libgda/gda-meta-store.h
index 4b9775f..2f1f520 100644
--- a/libgda/gda-meta-store.h
+++ b/libgda/gda-meta-store.h
@@ -114,6 +114,7 @@ gboolean          gda_meta_store_modify                   (GdaMetaStore *store,
 gboolean          gda_meta_store_modify_with_context      (GdaMetaStore *store, GdaMetaContext *context, 
 							   GdaDataModel *new_data, GError **error);
 GdaDataModel     *gda_meta_store_create_modify_data_model (GdaMetaStore *store, const gchar *table_name);
+void              gda_meta_store_set_identifiers_style    (GdaMetaStore *store, GdaSqlIdentifierStyle style);
 
 gboolean          gda_meta_store_get_attribute_value      (GdaMetaStore *store, const gchar *att_name, 
 							   gchar **att_value, GError **error);
diff --git a/libgda/gda-meta-struct.c b/libgda/gda-meta-struct.c
index ea99f7d..8490997 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) {
@@ -1551,13 +1564,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);
@@ -2063,8 +2076,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..951c40d 100644
--- a/libgda/sql-parser/gda-statement-struct-util.c
+++ b/libgda/sql-parser/gda-statement-struct-util.c
@@ -300,7 +300,7 @@ gda_sql_identifier_needs_quotes (const gchar *str)
 
 	g_return_val_if_fail (str, FALSE);
 	for (ptr = str; *ptr; ptr++) {
-		if (*ptr != g_ascii_tolower (*ptr))
+		if ((*ptr == ' ') || (*ptr != g_ascii_tolower (*ptr)))
 			return TRUE;
 	}
 	return FALSE;
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]