[libgda/LIBGDA_4.0] More gda_sql_identifier_quote() work
- From: Vivien Malerba <vivien src gnome org>
- To: svn-commits-list gnome org
- Subject: [libgda/LIBGDA_4.0] More gda_sql_identifier_quote() work
- Date: Thu, 16 Jul 2009 19:37:07 +0000 (UTC)
commit 3ffffd7ab27aeb24df57864819c80ce4a28490d8
Author: Vivien Malerba <malerba gnome-db org>
Date: Thu Jul 16 21:35:30 2009 +0200
More gda_sql_identifier_quote() work
* Fixed documentation
* added NR test
* fixed the MySQL provider (mainly meta data and stability)
libgda/gda-data-select.c | 8 +-
libgda/gda-meta-store.c | 3 +
libgda/gda-server-provider.h | 2 +-
libgda/gda-util.c | 233 ++++++++++++++++++--
libgda/sqlite/Makefile.am | 5 +-
libgda/sqlite/gda-sqlite-meta.c | 100 ++++++---
libgda/sqlite/gda-sqlite-provider.c | 190 ++++++++++++++++-
libgda/sqlite/gda-sqlite-recordset.c | 1 +
libgda/sqlite/{utils.c => gda-sqlite-util.c} | 25 ++-
libgda/sqlite/gda-sqlite-util.h | 40 ++++
libgda/sqlite/gda-sqlite.h | 6 -
providers/mysql/gda-mysql-meta.c | 86 ++++----
providers/mysql/gda-mysql-provider.c | 256 +++++++++++++++++++---
providers/mysql/gda-mysql-provider.h | 2 +
providers/mysql/gda-mysql-recordset.c | 244 +++++++++++++--------
providers/mysql/gda-mysql.h | 2 +-
providers/postgres/gda-postgres-provider.c | 308 ++++++++++++++++++--------
tests/test-identifiers-quotes.c | 288 ++++++++++++------------
18 files changed, 1324 insertions(+), 475 deletions(-)
---
diff --git a/libgda/gda-data-select.c b/libgda/gda-data-select.c
index 93fa556..98e11e1 100644
--- a/libgda/gda-data-select.c
+++ b/libgda/gda-data-select.c
@@ -1757,8 +1757,14 @@ gda_data_select_get_value_at (GdaDataModel *model, gint col, gint row, GError **
GValue *retval = gda_row_get_value (prow, col);
if (gda_row_value_is_valid (prow, retval))
return retval;
- else
+ else {
+ gchar *str;
+ str = g_strdup_printf (_("Unable to get value for row %d and column %d"), row, col);
+ g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_ACCESS_ERROR,
+ "%s", str);
+ g_free (str);
return NULL;
+ }
}
static GdaValueAttribute
diff --git a/libgda/gda-meta-store.c b/libgda/gda-meta-store.c
index f23bffb..7913c1c 100644
--- a/libgda/gda-meta-store.c
+++ b/libgda/gda-meta-store.c
@@ -2502,12 +2502,15 @@ gda_meta_store_modify_v (GdaMetaStore *store, const gchar *table_name,
retval = FALSE;
if (error && !(*error))
g_propagate_error (error, suggest_reports_error);
+ else
+ g_error_free (suggest_reports_error);
g_object_unref (wrapped_data);
goto out;
}
}
}
}
+ g_object_unref (wrapped_data);
}
if (!store->priv->override_mode) {
diff --git a/libgda/gda-server-provider.h b/libgda/gda-server-provider.h
index 6a8db44..9b589f7 100644
--- a/libgda/gda-server-provider.h
+++ b/libgda/gda-server-provider.h
@@ -297,7 +297,7 @@ struct _GdaServerProviderClass {
/* SQL identifiers quoting */
gchar *(* identifier_quote) (GdaServerProvider *provider, GdaConnection *cnc,
const gchar *id,
- gboolean meta_store_convention, gboolean force_quotes);
+ gboolean for_meta_store, gboolean force_quotes);
/* Padding for future expansion */
void (*_gda_reserved2) (void);
diff --git a/libgda/gda-util.c b/libgda/gda-util.c
index b60a57c..fd1d458 100644
--- a/libgda/gda-util.c
+++ b/libgda/gda-util.c
@@ -862,7 +862,7 @@ gda_compute_unique_table_row_condition_with_cnc (GdaConnection *cnc, GdaSqlState
op->operator_type = GDA_SQL_OPERATOR_TYPE_EQ;
/* left operand */
opexpr = gda_sql_expr_new (GDA_SQL_ANY_PART (op));
- str = gda_sql_identifier_quote (tcol->column_name, cnc, NULL, TRUE, FALSE);
+ str = gda_sql_identifier_quote (tcol->column_name, cnc, NULL, FALSE, FALSE);
g_value_take_string (opexpr->value = gda_value_new (G_TYPE_STRING), str);
op->operands = g_slist_append (op->operands, opexpr);
@@ -971,7 +971,7 @@ gda_compute_dml_statements (GdaConnection *cnc, GdaStatement *select_stmt, gbool
target = (GdaSqlSelectTarget*) stsel->from->targets->data;
/* actual statement structure's computation */
- tmp = gda_sql_identifier_quote (target->table_name, cnc, NULL, TRUE, FALSE);
+ tmp = gda_sql_identifier_quote (target->table_name, cnc, NULL, FALSE, FALSE);
if (insert_stmt) {
sql_ist = gda_sql_statement_new (GDA_SQL_STATEMENT_INSERT);
ist = (GdaSqlStatementInsert*) sql_ist->contents;
@@ -1035,7 +1035,7 @@ gda_compute_dml_statements (GdaConnection *cnc, GdaStatement *select_stmt, gbool
g_hash_table_insert (fields_hash, selfield->field_name, GINT_TO_POINTER (1));
gchar *str;
- str = gda_sql_identifier_quote (selfield->field_name, cnc, NULL, TRUE, FALSE);
+ str = gda_sql_identifier_quote (selfield->field_name, cnc, NULL, FALSE, FALSE);
if (insert_stmt) {
GdaSqlField *field;
field = gda_sql_field_new (GDA_SQL_ANY_PART (ist));
@@ -1580,37 +1580,181 @@ gda_sql_identifier_split (const gchar *id)
static gboolean _sql_identifier_needs_quotes (const gchar *str);
-
/**
* gda_sql_identifier_quote
* @id: an SQL identifier
* @cnc: a #GdaConnection object, or %NULL
* @prov: a #GdaServerProvider object, or %NULL
- * @meta_store_convention: set to %TRUE if @id respects the #GdaMetaStore
- * representation of SQL identifiers, or if it is a user input
+ * @for_meta_store set to %TRUE if the returned string will be used in a #GdaMetaStore
* @force_quotes: set to %TRUE to force the returned string to be quoted
*
- * Use this function for any SQL identifier to make sure it is correctly formatted
- * to be used with @cnc (if @cnc is %NULL, then the standard SQL quoting rules will be applied).
- *
- * If @id already has quotes, then this function returns a copy of @id, except that the quotes may be
- * replaced by database specific characters (such as the backquote for MySQL).
+ * Use this function for any SQL identifier to make sure that:
+ * <itemizedlist>
+ * <listitem>
+ * <para>it is correctly formatted
+ * to be used with @cnc (if @cnc is %NULL, then the standard SQL quoting rules will be applied) if
+ * @for_meta_store is %FALSE;
+ * </para>
+ * </listitem>
+ * <listitem>
+ * <para>it is correctly formatted to be used with the #GdaMetaStore's object associated to @cnc
+ * is @for_meta_store is %TRUE.
+ * </para>
+ * </listitem>
+ * </itemizedlist>
*
- * If @id has no quotes, if none are requited, and if @force_quotes if %FALSE,
- * then this function returns a copy if @id. The criteria to
- * determine if @id needs quotes depends on the database provider associated to @cnc, and if @cnc is %NULL, then
- * in all the following cases quotes are required:
+ * The @force_quotes allow some control of how to interpret @id: if %FALSE, then @id will be left
+ * unchanged most of the time (except for example if it's a reserved keyword), otherwise
+ * if @force_quotes is %TRUE, then the returned string will most probably have quotes around it
+ * to request that the database keep the case sensitiveness (but again, this may vary depending
+ * on the database being accessed through @cnc).
+ *
+ * For example, the following table gives the result of this function depending on the arguments
+ * when @cnc is %NULL (and @prov is also %NULL):
+ * <table frame="all">
+ * <tgroup cols="6" colsep="1" rowsep="1" align="justify">
+ * <thead>
+ * <row>
+ * <entry>id</entry>
+ * <entry>for_meta_store=%FALSE, force_quotes=%FALSE</entry>
+ * <entry>for_meta_store=%TRUE, force_quotes=%FALSE</entry>
+ * <entry>for_meta_store=%FALSE, force_quotes=%TRUE</entry>
+ * <entry>for_meta_store=%TRUE, force_quotes=%TRUE</entry>
+ * <entry>remark</entry>
+ * </row>
+ * </thead>
+ * <tbody>
+ * <row>
+ * <entry>"double word"</entry>
+ * <entry>"double word"</entry>
+ * <entry>"double word"</entry>
+ * <entry>"double word"</entry>
+ * <entry>"double word"</entry>
+ * <entry>non allowed character in SQL identifier</entry>
+ * </row>
+ * <row>
+ * <entry>"CapitalTest"</entry>
+ * <entry>"CapitalTest"</entry>
+ * <entry>"CapitalTest"</entry>
+ * <entry>"CapitalTest"</entry>
+ * <entry>"CapitalTest"</entry>
+ * <entry>Mixed case SQL identifier, already quoted</entry>
+ * </row>
+ * <row>
+ * <entry>CapitalTest</entry>
+ * <entry>CapitalTest</entry>
+ * <entry>capitaltest</entry>
+ * <entry>"CapitalTest"</entry>
+ * <entry>"CapitalTest"</entry>
+ * <entry>Mixed case SQL identifier, non quoted</entry>
+ * </row>
+ * <row>
+ * <entry>"mytable"</entry>
+ * <entry>"mytable"</entry>
+ * <entry>mytable</entry>
+ * <entry>"mytable"</entry>
+ * <entry>mytable</entry>
+ * <entry>All lowser case, quoted</entry>
+ * </row>
+ * <row>
+ * <entry>mytable</entry>
+ * <entry>mytable</entry>
+ * <entry>mytable</entry>
+ * <entry>"mytable"</entry>
+ * <entry>mytable</entry>
+ * <entry>All lowser case</entry>
+ * </row>
+ * <row>
+ * <entry>MYTABLE</entry>
+ * <entry>MYTABLE</entry>
+ * <entry>mytable</entry>
+ * <entry>"MYTABLE"</entry>
+ * <entry>"MYTABLE"</entry>
+ * <entry>All upper case</entry>
+ * </row>
+ * <row>
+ * <entry>"MYTABLE"</entry>
+ * <entry>"MYTABLE"</entry>
+ * <entry>"MYTABLE"</entry>
+ * <entry>"MYTABLE"</entry>
+ * <entry>"MYTABLE"</entry>
+ * <entry>All upper case, quoted</entry>
+ * </row>
+ * <row>
+ * <entry>desc</entry>
+ * <entry>"desc"</entry>
+ * <entry>"desc"</entry>
+ * <entry>"desc"</entry>
+ * <entry>"desc"</entry>
+ * <entry>SQL reserved keyword</entry>
+ * </row>
+ * <row>
+ * <entry>5ive</entry>
+ * <entry>"5ive"</entry>
+ * <entry>"5ive"</entry>
+ * <entry>"5ive"</entry>
+ * <entry>"5ive"</entry>
+ * <entry>SQL identifier starting with a digit</entry>
+ * </row>
+ * </tbody>
+ * </tgroup>
+ * </table>
+ *
+ * Here are a few examples of when and how to use this function:
* <itemizedlist>
- * <listitem><para>If @id's 1st character is a digit</para></listitem>
- * <listitem><para>If @id contains other characters than digits, letters and the '_', '$' and '#'</para></listitem>
- * <listitem><para>If @id is an SQL reserved keyword</para></listitem>
+ * <listitem>
+ * <para>
+ * When creating a table, the user has entered the table name, this function can be used to
+ * create a valid SQL identifier from the user provided table name:
+ * <programlisting>
+ * gchar *user_sqlid=...
+ * gchar *valid_sqlid = gda_sql_identifier_quote (user_sqlid, cnc, NULL, FALSE, FALSE);
+ * gchar *sql = g_strdup_printf ("CREATE TABLE %s ...", valid_sqlid);
+ * g_free (valid_sqlid);
+ * </programlisting>
+ * Note that this is an illustration and creating a table should be sone using a #GdaServerOperation
+ * object.
+ * </para>
+ * </listitem>
+ * <listitem>
+ * <para>
+ * When updating the meta data associated to a table which has been created with the code
+ * above:
+ * <programlisting>
+ * GValue table_name_value = { 0 };
+ * gchar* column_names[] = { (gchar*)"table_name" };
+ * GValue* column_values[] = { &table_name_value };
+ * GdaMetaContext mcontext = { (gchar*)"_tables", 1, column_names, column_values };
+ * g_value_init (&table_name_value, G_TYPE_STRING);
+ * g_value_take_string (&table_name_value, gda_sql_identifier_quote (user_sqlid, cnc, NULL, TRUE, FALSE);
+ * gda_connection_update_meta_store (cnc, &mcontext, NULL);
+ * g_value_reset (&table_name_value);
+ * </programlisting>
+ * </para>
+ * </listitem>
+ * <listitem>
+ * <para>
+ * When using a #GdaMetaStruct object to fetch information about a table (which has been created with
+ * the code above):
+ * <programlisting>
+ * GValue table_name_value = { 0 };
+ * g_value_init (&table_name_value, G_TYPE_STRING);
+ * g_value_take_string (&table_name_value, gda_sql_identifier_quote (user_sqlid, cnc, NULL, TRUE, FALSE);
+ * GdaMetaDbObject *dbo;
+ * dbo = gda_meta_struct_complement (mstruct, GDA_META_DB_TABLE, NULL, NULL, &table_name_value, NULL);
+ * g_value_reset (&table_name_value);
+ * </programlisting>
+ * </para>
+ * </listitem>
* </itemizedlist>
*
- * If @force_quotes is %TRUE, then the this function always returns a quoted SQL identifier.
*
* Note that @id must not be a composed SQL identifier (such as "mytable.mycolumn" which should be
* treated as the "mytable" and "mycolumn" SQL identifiers). If unsure, use gda_sql_identifier_split().
*
+ * Also note that if @cnc is %NULL, then it's possible to pass an non %NULL @prov to have a result specific
+ * to @prov.
+ *
* For more information, see the <link linkend="gen:sql_identifiers">SQL identifiers and abstraction</link> and
* <link linkend="information_schema:sql_identifiers">SQL identifiers in meta data</link> sections.
*
@@ -1621,7 +1765,7 @@ static gboolean _sql_identifier_needs_quotes (const gchar *str);
*/
gchar *
gda_sql_identifier_quote (const gchar *id, GdaConnection *cnc, GdaServerProvider *prov,
- gboolean meta_store_convention, gboolean force_quotes)
+ gboolean for_meta_store, gboolean force_quotes)
{
g_return_val_if_fail (id && *id, NULL);
if (prov)
@@ -1634,9 +1778,56 @@ gda_sql_identifier_quote (const gchar *id, GdaConnection *cnc, GdaServerProvider
prov = gda_connection_get_provider (cnc);
}
- if (prov && PROV_CLASS (prov)->identifier_quote) {
+ if (prov && PROV_CLASS (prov)->identifier_quote)
return PROV_CLASS (prov)->identifier_quote (prov, cnc, id,
- meta_store_convention, force_quotes);
+ for_meta_store, force_quotes);
+
+ if (for_meta_store) {
+ gchar *tmp, *ptr;
+ tmp = _remove_quotes (g_strdup (id));
+ if (is_keyword (tmp)) {
+ ptr = gda_sql_identifier_add_quotes (tmp);
+ g_free (tmp);
+ return ptr;
+ }
+ else if (force_quotes) {
+ /* quote if non LC characters or digits at the 1st char or non allowed characters */
+ for (ptr = tmp; *ptr; ptr++) {
+ if (((*ptr >= 'a') && (*ptr <= 'z')) ||
+ ((*ptr >= '0') && (*ptr <= '9') && (ptr != tmp)) ||
+ (*ptr == '_'))
+ continue;
+ else {
+ ptr = gda_sql_identifier_add_quotes (tmp);
+ g_free (tmp);
+ return ptr;
+ }
+ }
+ return tmp;
+ }
+ else {
+ for (ptr = tmp; *ptr; ptr++) {
+ if (*id == '"') {
+ if (((*ptr >= 'a') && (*ptr <= 'z')) ||
+ ((*ptr >= '0') && (*ptr <= '9') && (ptr != tmp)) ||
+ (*ptr == '_'))
+ continue;
+ else {
+ ptr = gda_sql_identifier_add_quotes (tmp);
+ g_free (tmp);
+ return ptr;
+ }
+ }
+ else if ((*ptr >= 'A') && (*ptr <= 'Z'))
+ *ptr += 'a' - 'A';
+ else if ((*ptr >= '0') && (*ptr <= '9') && (ptr == tmp)) {
+ ptr = gda_sql_identifier_add_quotes (tmp);
+ g_free (tmp);
+ return ptr;
+ }
+ }
+ return tmp;
+ }
}
else {
/* default SQL standard */
diff --git a/libgda/sqlite/Makefile.am b/libgda/sqlite/Makefile.am
index d64c5d7..dd2a66f 100644
--- a/libgda/sqlite/Makefile.am
+++ b/libgda/sqlite/Makefile.am
@@ -51,9 +51,10 @@ libgda_sqlite_la_SOURCES = \
gda-sqlite-pstmt.c \
gda-sqlite-recordset.c \
gda-sqlite-recordset.h \
+ gda-sqlite-util.c \
+ gda-sqlite-util.h \
gda-sqlite.h \
- keywords_hash.h \
- utils.c
+ keywords_hash.h
libgda_sqlite_la_LDFLAGS = -export-dynamic -module -avoid-version $(NO_UNDEFINED)
libgda_sqlite_la_LIBADD = \
diff --git a/libgda/sqlite/gda-sqlite-meta.c b/libgda/sqlite/gda-sqlite-meta.c
index 0c80fda..53dd02f 100644
--- a/libgda/sqlite/gda-sqlite-meta.c
+++ b/libgda/sqlite/gda-sqlite-meta.c
@@ -24,6 +24,7 @@
#include <string.h>
#include "gda-sqlite.h"
#include "gda-sqlite-meta.h"
+#include "gda-sqlite-util.h"
#include "gda-sqlite-provider.h"
#include <libgda/gda-meta-store.h>
#include <libgda/sql-parser/gda-sql-parser.h>
@@ -33,9 +34,6 @@
#include <libgda/gda-data-model-array.h>
#include <libgda/gda-set.h>
-#include <libgda/sqlite/keywords_hash.h>
-#include "keywords_hash.c" /* this one is dynamically generated */
-
static gboolean append_a_row (GdaDataModel *to_model, GError **error, gint nb, ...);
/*
@@ -98,6 +96,31 @@ static GValue *zero_value;
static GValue *rule_value;
static GdaSet *pragma_set;
+static GValue *
+new_caseless_value (const GValue *cvalue)
+{
+ GValue *newvalue;
+ gchar *str, *ptr;
+ str = g_value_dup_string (cvalue);
+ for (ptr = str; *ptr; ptr++) {
+ if ((*ptr >= 'A') && (*ptr <= 'Z'))
+ *ptr += 'a' - 'A';
+ if (((*ptr >= 'a') && (*ptr <= 'z')) ||
+ ((*ptr >= '0') && (*ptr <= '9')) ||
+ (*ptr >= '_'))
+ continue;
+ else {
+ g_free (str);
+ newvalue = gda_value_new (G_TYPE_STRING);
+ g_value_set_string (newvalue, g_value_get_string (cvalue));
+ return newvalue;
+ }
+ }
+ newvalue = gda_value_new (G_TYPE_STRING);
+ g_value_take_string (newvalue, str);
+ return newvalue;
+}
+
/*
* Meta initialization
*/
@@ -202,7 +225,7 @@ _gda_sqlite_meta__info (GdaServerProvider *prov, GdaConnection *cnc,
retval = append_a_row (model, error, 1, FALSE, catalog_value);
if (retval) {
- gda_meta_store_set_reserved_keywords_func (store, is_keyword);
+ gda_meta_store_set_reserved_keywords_func (store, _gda_sqlite_get_reserved_keyword_func());
retval = gda_meta_store_modify (store, context->table_name, model, NULL, error, NULL);
}
g_object_unref (model);
@@ -261,7 +284,7 @@ _gda_sqlite_meta__btypes (GdaServerProvider *prov, GdaConnection *cnc,
}
}
if (retval) {
- gda_meta_store_set_reserved_keywords_func (store, is_keyword);
+ gda_meta_store_set_reserved_keywords_func (store, _gda_sqlite_get_reserved_keyword_func());
retval = gda_meta_store_modify (store, context->table_name, mod_model, NULL, error, NULL);
}
g_object_unref (mod_model);
@@ -445,7 +468,7 @@ _gda_sqlite_meta__udt (GdaServerProvider *prov, GdaConnection *cnc,
/* actually use mod_model */
if (retval) {
- gda_meta_store_set_reserved_keywords_func (store, is_keyword);
+ gda_meta_store_set_reserved_keywords_func (store, _gda_sqlite_get_reserved_keyword_func());
retval = gda_meta_store_modify (store, context->table_name, mod_model, NULL, error, NULL);
}
g_object_unref (mod_model);
@@ -481,7 +504,7 @@ _gda_sqlite_meta_udt (GdaServerProvider *prov, GdaConnection *cnc,
/* actually use mod_model */
if (retval) {
- gda_meta_store_set_reserved_keywords_func (store, is_keyword);
+ gda_meta_store_set_reserved_keywords_func (store, _gda_sqlite_get_reserved_keyword_func());
retval = gda_meta_store_modify (store, context->table_name, mod_model, NULL, error, NULL);
}
g_object_unref (mod_model);
@@ -653,7 +676,7 @@ _gda_sqlite_meta_schemata (GdaServerProvider *prov, GdaConnection *cnc,
const gchar *cstr;
GValue *v1;
- cstr = g_value_get_string (cvalue);
+ cstr = g_value_get_string (cvalue); /* VMA */
if (!cstr || !strncmp (cstr, TMP_DATABASE_NAME, 4))
continue;
@@ -667,7 +690,7 @@ _gda_sqlite_meta_schemata (GdaServerProvider *prov, GdaConnection *cnc,
}
g_object_unref (tmpmodel);
if (retval){
- gda_meta_store_set_reserved_keywords_func (store, is_keyword);
+ gda_meta_store_set_reserved_keywords_func (store, _gda_sqlite_get_reserved_keyword_func());
retval = gda_meta_store_modify_with_context (store, context, model, error);
}
g_object_unref (model);
@@ -713,60 +736,68 @@ fill_tables_views_model (GdaConnection *cnc,
nrows = gda_data_model_get_n_rows (tmpmodel);
for (i = 0; (i < nrows) && retval; i++) {
const GValue *cvalue;
+ GValue *ncvalue;
cvalue = gda_data_model_get_value_at (tmpmodel, 0, i, error);
if (!cvalue) {
retval = FALSE;
break;
}
+ ncvalue = new_caseless_value (cvalue);
+
if (!p_table_name ||
- !gda_value_compare (p_table_name, cvalue)) {
+ !gda_value_compare (p_table_name, ncvalue)) {
GValue *v1, *v2 = NULL;
const GValue *tvalue;
const GValue *dvalue;
gboolean is_view = FALSE;
const gchar *this_table_name;
- this_table_name = g_value_get_string (cvalue);
+ this_table_name = g_value_get_string (ncvalue);
g_assert (this_table_name);
- if (!strcmp (this_table_name, "sqlite_sequence"))
+ if (!strcmp (this_table_name, "sqlite_sequence")) {
+ gda_value_free (ncvalue);
continue; /* ignore that table */
+ }
tvalue = gda_data_model_get_value_at (tmpmodel, 1, i, error);
if (!tvalue) {
retval = FALSE;
+ gda_value_free (ncvalue);
break;
}
dvalue = gda_data_model_get_value_at (tmpmodel, 2, i, error);
if (!dvalue) {
retval = FALSE;
+ gda_value_free (ncvalue);
break;
}
if (*(g_value_get_string (tvalue)) == 'v')
is_view = TRUE;
g_value_set_boolean ((v1 = gda_value_new (G_TYPE_BOOLEAN)), TRUE);
- str = g_strdup_printf ("%s.%s", schema_name, g_value_get_string (cvalue));
+ str = g_strdup_printf ("%s.%s", schema_name, g_value_get_string (ncvalue));
g_value_take_string ((v2 = gda_value_new (G_TYPE_STRING)), str);
if (! append_a_row (to_tables_model, error, 9,
FALSE, catalog_value, /* table_catalog */
FALSE, p_table_schema, /* table_schema */
- FALSE, cvalue, /* table_name */
+ FALSE, ncvalue, /* table_name */
FALSE, is_view ? view_type_value : table_type_value, /* table_type */
TRUE, v1, /* is_insertable_into */
FALSE, NULL, /* table_comments */
- FALSE, cvalue, /* table_short_name */
+ FALSE, ncvalue, /* table_short_name */
TRUE, v2, /* table_full_name */
FALSE, NULL)) /* table_owner */
retval = FALSE;
if (is_view && ! append_a_row (to_views_model, error, 6,
FALSE, catalog_value,
FALSE, p_table_schema,
- FALSE, cvalue,
+ FALSE, ncvalue,
FALSE, dvalue,
FALSE, view_check_option,
FALSE, false_value))
retval = FALSE;
}
+ gda_value_free (ncvalue);
}
g_object_unref (tmpmodel);
@@ -814,12 +845,12 @@ _gda_sqlite_meta__tables_views (GdaServerProvider *prov, GdaConnection *cnc,
c2 = *context; /* copy contents, just because we need to modify @context->table_name */
if (retval) {
c2.table_name = "_tables";
- gda_meta_store_set_reserved_keywords_func (store, is_keyword);
+ gda_meta_store_set_reserved_keywords_func (store, _gda_sqlite_get_reserved_keyword_func());
retval = gda_meta_store_modify_with_context (store, &c2, tables_model, error);
}
if (retval) {
c2.table_name = "_views";
- gda_meta_store_set_reserved_keywords_func (store, is_keyword);
+ gda_meta_store_set_reserved_keywords_func (store, _gda_sqlite_get_reserved_keyword_func());
retval = gda_meta_store_modify_with_context (store, &c2, views_model, error);
}
g_object_unref (tables_model);
@@ -848,12 +879,12 @@ _gda_sqlite_meta_tables_views (GdaServerProvider *prov, GdaConnection *cnc,
c2 = *context; /* copy contents, just because we need to modify @context->table_name */
if (retval) {
c2.table_name = "_tables";
- gda_meta_store_set_reserved_keywords_func (store, is_keyword);
+ gda_meta_store_set_reserved_keywords_func (store, _gda_sqlite_get_reserved_keyword_func());
retval = gda_meta_store_modify_with_context (store, &c2, tables_model, error);
}
if (retval) {
c2.table_name = "_views";
- gda_meta_store_set_reserved_keywords_func (store, is_keyword);
+ gda_meta_store_set_reserved_keywords_func (store, _gda_sqlite_get_reserved_keyword_func());
retval = gda_meta_store_modify_with_context (store, &c2, views_model, error);
}
g_object_unref (tables_model);
@@ -897,6 +928,7 @@ fill_columns_model (GdaConnection *cnc, SqliteConnectionData *cdata,
const gchar *this_table_name;
const gchar *this_col_name;
const GValue *this_col_pname;
+ GValue *nthis_col_pname;
GType gtype = 0;
const GValue *cvalue;
@@ -905,12 +937,14 @@ fill_columns_model (GdaConnection *cnc, SqliteConnectionData *cdata,
retval = FALSE;
break;
}
+ nthis_col_pname = new_caseless_value (this_col_pname);
+
this_table_name = g_value_get_string (p_table_name);
g_assert (this_table_name);
if (!strcmp (this_table_name, "sqlite_sequence"))
continue; /* ignore that table */
- this_col_name = g_value_get_string (this_col_pname);
+ this_col_name = g_value_get_string (nthis_col_pname);
if (sqlite3_table_column_metadata (cdata->connection, g_value_get_string (p_table_schema),
this_table_name, this_col_name,
&pzDataType, &pzCollSeq, &pNotNull, &pPrimaryKey, &pAutoinc)
@@ -919,6 +953,7 @@ fill_columns_model (GdaConnection *cnc, SqliteConnectionData *cdata,
cvalue = gda_data_model_get_value_at (tmpmodel, 2, i, error);
if (!cvalue) {
retval = FALSE;
+ gda_value_free (nthis_col_pname);
break;
}
pzDataType = g_value_get_string (cvalue);
@@ -926,12 +961,14 @@ fill_columns_model (GdaConnection *cnc, SqliteConnectionData *cdata,
cvalue = gda_data_model_get_value_at (tmpmodel, 3, i, error);
if (!cvalue) {
retval = FALSE;
+ gda_value_free (nthis_col_pname);
break;
}
pNotNull = g_value_get_int (cvalue);
cvalue = gda_data_model_get_value_at (tmpmodel, 5, i, error);
if (!cvalue) {
retval = FALSE;
+ gda_value_free (nthis_col_pname);
break;
}
pPrimaryKey = g_value_get_boolean (cvalue);
@@ -941,6 +978,7 @@ fill_columns_model (GdaConnection *cnc, SqliteConnectionData *cdata,
cvalue = gda_data_model_get_value_at (tmpmodel, 0, i, error);
if (!cvalue) {
retval = FALSE;
+ gda_value_free (nthis_col_pname);
break;
}
v1 = gda_value_copy (cvalue);
@@ -974,7 +1012,7 @@ fill_columns_model (GdaConnection *cnc, SqliteConnectionData *cdata,
FALSE, catalog_value, /* table_catalog */
FALSE, p_table_schema, /* table_schema */
FALSE, p_table_name, /* table_name */
- FALSE, this_col_pname, /* column name */
+ TRUE, nthis_col_pname, /* column name */
TRUE, v1, /* ordinal_position */
FALSE, cvalue, /* column default */
TRUE, v3, /* is_nullable */
@@ -1076,7 +1114,7 @@ _gda_sqlite_meta__columns (GdaServerProvider *prov, GdaConnection *cnc,
g_object_unref (tmpmodel);
if (retval) {
- gda_meta_store_set_reserved_keywords_func (store, is_keyword);
+ gda_meta_store_set_reserved_keywords_func (store, _gda_sqlite_get_reserved_keyword_func());
retval = gda_meta_store_modify_with_context (store, context, mod_model, error);
}
g_object_unref (mod_model);
@@ -1102,7 +1140,7 @@ _gda_sqlite_meta_columns (GdaServerProvider *prov, GdaConnection *cnc,
retval = fill_columns_model (cnc, cdata, mod_model, table_schema, table_name, error);
if (retval) {
- gda_meta_store_set_reserved_keywords_func (store, is_keyword);
+ gda_meta_store_set_reserved_keywords_func (store, _gda_sqlite_get_reserved_keyword_func());
retval = gda_meta_store_modify_with_context (store, context, mod_model, error);
}
g_object_unref (mod_model);
@@ -1417,7 +1455,7 @@ _gda_sqlite_meta__constraints_tab (GdaServerProvider *prov, GdaConnection *cnc,
g_object_unref (tmpmodel);
if (retval) {
- gda_meta_store_set_reserved_keywords_func (store, is_keyword);
+ gda_meta_store_set_reserved_keywords_func (store, _gda_sqlite_get_reserved_keyword_func());
retval = gda_meta_store_modify_with_context (store, context, mod_model, error);
}
g_object_unref (mod_model);
@@ -1444,7 +1482,7 @@ _gda_sqlite_meta_constraints_tab (GdaServerProvider *prov, GdaConnection *cnc,
retval = fill_constraints_tab_model (cnc, cdata, mod_model, table_schema, table_name, constraint_name_n, error);
if (retval) {
- gda_meta_store_set_reserved_keywords_func (store, is_keyword);
+ gda_meta_store_set_reserved_keywords_func (store, _gda_sqlite_get_reserved_keyword_func());
retval = gda_meta_store_modify_with_context (store, context, mod_model, error);
}
g_object_unref (mod_model);
@@ -1608,7 +1646,7 @@ _gda_sqlite_meta__constraints_ref (GdaServerProvider *prov, GdaConnection *cnc,
g_object_unref (tmpmodel);
if (retval) {
- gda_meta_store_set_reserved_keywords_func (store, is_keyword);
+ gda_meta_store_set_reserved_keywords_func (store, _gda_sqlite_get_reserved_keyword_func());
retval = gda_meta_store_modify_with_context (store, context, mod_model, error);
}
g_object_unref (mod_model);
@@ -1635,7 +1673,7 @@ _gda_sqlite_meta_constraints_ref (GdaServerProvider *prov, GdaConnection *cnc,
retval = fill_constraints_ref_model (cnc, cdata, mod_model, table_schema, table_name, constraint_name, error);
if (retval) {
- gda_meta_store_set_reserved_keywords_func (store, is_keyword);
+ gda_meta_store_set_reserved_keywords_func (store, _gda_sqlite_get_reserved_keyword_func());
retval = gda_meta_store_modify_with_context (store, context, mod_model, error);
}
g_object_unref (mod_model);
@@ -1946,7 +1984,7 @@ _gda_sqlite_meta__key_columns (GdaServerProvider *prov, GdaConnection *cnc,
g_object_unref (const_model);
if (retval) {
- gda_meta_store_set_reserved_keywords_func (store, is_keyword);
+ gda_meta_store_set_reserved_keywords_func (store, _gda_sqlite_get_reserved_keyword_func());
retval = gda_meta_store_modify_with_context (store, context, mod_model, error);
}
g_object_unref (mod_model);
@@ -1973,7 +2011,7 @@ _gda_sqlite_meta_key_columns (GdaServerProvider *prov, GdaConnection *cnc,
retval = fill_key_columns_model (cnc, cdata, mod_model, table_schema, table_name, constraint_name, error);
if (retval) {
- gda_meta_store_set_reserved_keywords_func (store, is_keyword);
+ gda_meta_store_set_reserved_keywords_func (store, _gda_sqlite_get_reserved_keyword_func());
retval = gda_meta_store_modify_with_context (store, context, mod_model, error);
}
g_object_unref (mod_model);
@@ -2123,7 +2161,7 @@ _gda_sqlite_meta_routines (GdaServerProvider *prov, GdaConnection *cnc,
}
if (retval) {
- gda_meta_store_set_reserved_keywords_func (store, is_keyword);
+ gda_meta_store_set_reserved_keywords_func (store, _gda_sqlite_get_reserved_keyword_func());
retval = gda_meta_store_modify_with_context (store, context, mod_model, error);
}
g_object_unref (mod_model);
diff --git a/libgda/sqlite/gda-sqlite-provider.c b/libgda/sqlite/gda-sqlite-provider.c
index c106af5..4b23280 100644
--- a/libgda/sqlite/gda-sqlite-provider.c
+++ b/libgda/sqlite/gda-sqlite-provider.c
@@ -36,6 +36,7 @@
#include "gda-sqlite-provider.h"
#include "gda-sqlite-recordset.h"
#include "gda-sqlite-ddl.h"
+#include "gda-sqlite-util.h"
#include "gda-sqlite-meta.h"
#include "gda-sqlite-handler-bin.h"
#include "gda-sqlite-blob-op.h"
@@ -258,7 +259,10 @@ static GObject *gda_sqlite_provider_statement_execute (GdaServerProv
GType *col_types, GdaSet **last_inserted_row,
guint *task_id, GdaServerProviderExecCallback async_cb,
gpointer cb_data, GError **error);
-
+/* Quoting */
+static gchar *gda_sqlite_identifier_quote (GdaServerProvider *provider, GdaConnection *cnc,
+ const gchar *id,
+ gboolean meta_store_convention, gboolean force_quotes);
/*
* private connection data destroy
*/
@@ -341,6 +345,7 @@ gda_sqlite_provider_class_init (GdaSqliteProviderClass *klass)
provider_class->get_def_dbms_type = gda_sqlite_provider_get_default_dbms_type;
provider_class->create_connection = NULL;
+ provider_class->identifier_quote = gda_sqlite_identifier_quote;
provider_class->open_connection = gda_sqlite_provider_open_connection;
provider_class->close_connection = gda_sqlite_provider_close_connection;
provider_class->get_database = gda_sqlite_provider_get_database;
@@ -2564,6 +2569,189 @@ scalar_gda_file_exists_func (sqlite3_context *context, int argc, sqlite3_value *
sqlite3_result_int (context, 0);
}
+static gchar *
+identifier_add_quotes (const gchar *str)
+{
+ gchar *retval, *rptr;
+ const gchar *sptr;
+ gint len;
+
+ if (!str)
+ return NULL;
+
+ len = strlen (str);
+ retval = g_new (gchar, 2*len + 3);
+ *retval = '"';
+ for (rptr = retval+1, sptr = str; *sptr; sptr++, rptr++) {
+ if (*sptr == '"') {
+ *rptr = '\\';
+ rptr++;
+ *rptr = *sptr;
+ }
+ else
+ *rptr = *sptr;
+ }
+ *rptr = '"';
+ rptr++;
+ *rptr = 0;
+ return retval;
+}
+
+static gboolean
+_sql_identifier_needs_quotes (const gchar *str)
+{
+ const gchar *ptr;
+
+ g_return_val_if_fail (str, FALSE);
+ 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')) ||
+ ((*ptr >= 'a') && (*ptr <= 'z')))
+ continue;
+
+ if ((*ptr != '$') && (*ptr != '_') && (*ptr != '#'))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* Returns: @str */
+static gchar *
+sqlite_remove_quotes (gchar *str)
+{
+ glong total;
+ gchar *ptr;
+ glong offset = 0;
+ char delim;
+
+ if (!str)
+ return NULL;
+ delim = *str;
+ if ((delim != '[') && (delim != '"') && (delim != '\'') && (delim != '`'))
+ return str;
+
+ total = strlen (str);
+ if ((str[total-1] == delim) || ((delim == '[') && (str[total-1] == ']'))) {
+ /* string is correclty terminated */
+ g_memmove (str, str+1, total-2);
+ total -=2;
+ }
+ else {
+ /* string is _not_ correclty terminated */
+ g_memmove (str, str+1, total-1);
+ total -=1;
+ }
+ str[total] = 0;
+
+ if ((delim == '"') || (delim == '\'')) {
+ ptr = (gchar *) str;
+ while (offset < total) {
+ /* we accept the "''" as a synonym of "\'" */
+ if (*ptr == delim) {
+ if (*(ptr+1) == delim) {
+ g_memmove (ptr+1, ptr+2, total - offset);
+ offset += 2;
+ }
+ else {
+ *str = 0;
+ return str;
+ }
+ }
+ if (*ptr == '\\') {
+ if (*(ptr+1) == '\\') {
+ g_memmove (ptr+1, ptr+2, total - offset);
+ offset += 2;
+ }
+ else {
+ if (*(ptr+1) == delim) {
+ *ptr = delim;
+ g_memmove (ptr+1, ptr+2, total - offset);
+ offset += 2;
+ }
+ else {
+ *str = 0;
+ return str;
+ }
+ }
+ }
+ else
+ offset ++;
+
+ ptr++;
+ }
+ }
+
+ return str;
+}
+
+static gchar *
+gda_sqlite_identifier_quote (GdaServerProvider *provider, GdaConnection *cnc,
+ const gchar *id,
+ gboolean for_meta_store, gboolean force_quotes)
+{
+ GdaSqlReservedKeywordsFunc kwfunc;
+ SqliteConnectionData *cdata = NULL;
+
+ if (cnc) {
+ cdata = (SqliteConnectionData*) gda_connection_internal_get_provider_data (cnc);
+ if (!cdata)
+ return NULL;
+ }
+
+ kwfunc = _gda_sqlite_get_reserved_keyword_func ();
+
+ if (for_meta_store) {
+ gchar *tmp, *ptr;
+ tmp = sqlite_remove_quotes (g_strdup (id));
+ if (kwfunc (tmp)) {
+ ptr = gda_sql_identifier_add_quotes (tmp);
+ g_free (tmp);
+ return ptr;
+ }
+ else {
+ /* if only alphanum => don't quote */
+ for (ptr = tmp; *ptr; ptr++) {
+ if ((*ptr >= 'A') && (*ptr <= 'Z'))
+ *ptr += 'a' - 'A';
+ if (((*ptr >= 'a') && (*ptr <= 'z')) ||
+ ((*ptr >= '0') && (*ptr <= '9') && (ptr != tmp)) ||
+ (*ptr >= '_'))
+ continue;
+ else {
+ ptr = gda_sql_identifier_add_quotes (tmp);
+ g_free (tmp);
+ return ptr;
+ }
+ }
+ return tmp;
+ }
+ }
+ else {
+ if (*id == '"') {
+ /* there are already some quotes */
+ return g_strdup (id);
+ }
+ else if ((*id == '[') || (*id == '`')) {
+ /* there are already some quotes */
+ gchar *tmp, *ptr;
+ tmp = sqlite_remove_quotes (g_strdup (id));
+ ptr = gda_sql_identifier_add_quotes (tmp);
+ g_free (tmp);
+ return ptr;
+ }
+ if (kwfunc (id) || _sql_identifier_needs_quotes (id) || force_quotes)
+ return identifier_add_quotes (id);
+
+ /* nothing to do */
+ return g_strdup (id);
+ }
+}
+
static void
gda_sqlite_free_cnc_data (SqliteConnectionData *cdata)
{
diff --git a/libgda/sqlite/gda-sqlite-recordset.c b/libgda/sqlite/gda-sqlite-recordset.c
index 189527d..6f59d39 100644
--- a/libgda/sqlite/gda-sqlite-recordset.c
+++ b/libgda/sqlite/gda-sqlite-recordset.c
@@ -26,6 +26,7 @@
#include <string.h>
#include <glib/gi18n-lib.h>
#include "gda-sqlite.h"
+#include "gda-sqlite-util.h"
#include "gda-sqlite-recordset.h"
#include "gda-sqlite-provider.h"
#include "gda-sqlite-blob-op.h"
diff --git a/libgda/sqlite/utils.c b/libgda/sqlite/gda-sqlite-util.c
similarity index 89%
rename from libgda/sqlite/utils.c
rename to libgda/sqlite/gda-sqlite-util.c
index 9342bbe..29a55be 100644
--- a/libgda/sqlite/utils.c
+++ b/libgda/sqlite/gda-sqlite-util.c
@@ -1,9 +1,7 @@
-/* GNOME DB Postgres Provider
- * Copyright (C) 1998 - 2009 The GNOME Foundation
+/* GDA sqlite provider
+ * Copyright (C) 2009 The GNOME Foundation.
*
* AUTHORS:
- * Gonzalo Paniagua Javier <gonzalo gnome-db org>
- * Carlos Perello Marin <carlos gnome-db org>
* Vivien Malerba <malerba gnome-db org>
*
* This Library is free software; you can redistribute it and/or
@@ -23,12 +21,16 @@
*/
#include <glib/gi18n-lib.h>
+#include "gda-sqlite-util.h"
#include <stdlib.h>
#include <string.h>
#include "gda-sqlite.h"
#include <libgda/gda-connection-private.h>
#include "gda-sqlite-recordset.h"
+#include <libgda/sqlite/keywords_hash.h>
+#include "keywords_hash.c" /* this one is dynamically generated */
+
static guint
nocase_str_hash (gconstpointer v)
{
@@ -95,3 +97,18 @@ _gda_sqlite_compute_g_type (int sqlite_type)
}
}
+
+
+#ifdef GDA_DEBUG
+void
+_gda_sqlite_test_keywords (void)
+{
+ test_keywords();
+}
+#endif
+
+GdaSqlReservedKeywordsFunc
+_gda_sqlite_get_reserved_keyword_func (void)
+{
+ return is_keyword;
+}
diff --git a/libgda/sqlite/gda-sqlite-util.h b/libgda/sqlite/gda-sqlite-util.h
new file mode 100644
index 0000000..15e1676
--- /dev/null
+++ b/libgda/sqlite/gda-sqlite-util.h
@@ -0,0 +1,40 @@
+/* GDA sqlite provider
+ * Copyright (C) 2009 The GNOME Foundation.
+ *
+ * AUTHORS:
+ * Vivien Malerba <malerba gnome-db org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __GDA_SQLITE_UTIL_H__
+#define __GDA_SQLITE_UTIL_H__
+
+#include "gda-sqlite.h"
+
+G_BEGIN_DECLS
+
+void _gda_sqlite_compute_types_hash (SqliteConnectionData *scnc);
+GType _gda_sqlite_compute_g_type (int sqlite_type);
+
+#ifdef GDA_DEBUG
+void _gda_sqlite_test_keywords (void);
+#endif
+GdaSqlReservedKeywordsFunc _gda_sqlite_get_reserved_keyword_func (void);
+
+G_END_DECLS
+
+#endif
+
diff --git a/libgda/sqlite/gda-sqlite.h b/libgda/sqlite/gda-sqlite.h
index 557e3d9..c9f3237 100644
--- a/libgda/sqlite/gda-sqlite.h
+++ b/libgda/sqlite/gda-sqlite.h
@@ -46,10 +46,4 @@ typedef struct {
GHashTable *types; /* key = type name, value = GType */
} SqliteConnectionData;
-/*
- * Utility functions
- */
-void _gda_sqlite_compute_types_hash (SqliteConnectionData *scnc);
-GType _gda_sqlite_compute_g_type (int sqlite_type);
-
#endif
diff --git a/providers/mysql/gda-mysql-meta.c b/providers/mysql/gda-mysql-meta.c
index 9f6b823..1fb8148 100644
--- a/providers/mysql/gda-mysql-meta.c
+++ b/providers/mysql/gda-mysql-meta.c
@@ -3,6 +3,7 @@
*
* AUTHORS:
* Carlos Savoretti <csavoretti gmail com>
+ * 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
@@ -34,12 +35,6 @@
#include <libgda/gda-set.h>
#include <libgda/gda-holder.h>
-static gboolean
-append_a_row (GdaDataModel *to_model,
- GError **error,
- gint nb,
- ...);
-
/*
* predefined statements' IDs
*/
@@ -111,49 +106,49 @@ static gchar *internal_sql[] = {
"SELECT IFNULL(catalog_name, schema_name) AS catalog_name, schema_name, NULL, CASE WHEN schema_name = 'information_schema' OR schema_name = 'mysql' THEN TRUE ELSE FALSE END AS schema_internal FROM INFORMATION_SCHEMA.schemata WHERE schema_name = ##name::string",
/* I_STMT_TABLES */
- "SELECT IFNULL(table_catalog, table_schema) AS table_catalog, table_schema, table_name, CASE WHEN table_type LIKE '%VIEW%' THEN 'VIEW' ELSE table_type END, CASE table_type WHEN 'BASE TABLE' THEN TRUE ELSE FALSE END AS table_type, table_comment, " SHORT_NAME("table_schema", "table_name", "CONCAT(table_schema, '.', table_name)") " AS short_name, CONCAT(table_schema, '.', table_name) AS table_full_name, NULL AS table_owner FROM INFORMATION_SCHEMA.tables WHERE table_catalog = ##cat::string AND schema_name = ##schema::string",
+ "SELECT IFNULL(table_catalog, table_schema) AS table_catalog, table_schema, table_name, CASE WHEN table_type LIKE '%VIEW%' THEN 'VIEW' ELSE table_type END, CASE table_type WHEN 'BASE TABLE' THEN TRUE ELSE FALSE END AS table_type, table_comment, " SHORT_NAME("table_schema", "table_name", "CONCAT(table_schema, '.', table_name)") " AS short_name, CONCAT(table_schema, '.', table_name) AS table_full_name, NULL AS table_owner FROM INFORMATION_SCHEMA.tables WHERE IFNULL(table_catalog, table_schema) = BINARY ##cat::string AND table_schema = BINARY ##schema::string",
/* I_STMT_TABLES_ALL */
"SELECT IFNULL(table_catalog, table_schema) AS table_catalog, table_schema, table_name, CASE WHEN table_type LIKE '%VIEW%' THEN 'VIEW' ELSE table_type END, CASE table_type WHEN 'BASE TABLE' THEN TRUE ELSE FALSE END AS table_type, table_comment, " SHORT_NAME("table_schema", "table_name", "CONCAT(table_schema, '.', table_name)") " AS short_name, CONCAT(table_schema, '.', table_name) AS table_full_name, NULL AS table_owner FROM INFORMATION_SCHEMA.tables",
/* I_STMT_TABLE_NAMED */
- "SELECT IFNULL(table_catalog, table_schema) AS table_catalog, table_schema, table_name, CASE WHEN table_type LIKE '%VIEW%' THEN 'VIEW' ELSE table_type END, CASE table_type WHEN 'BASE TABLE' THEN TRUE ELSE FALSE END AS table_type, table_comment, " SHORT_NAME("table_schema", "table_name", "CONCAT(table_schema, '.', table_name)") " as short_name, CONCAT(table_schema, '.', table_name) AS table_full_name, NULL AS table_owner FROM FROM INFORMATION_SCHEMA.tables WHERE table_catalog = ##cat::string AND schema_name = ##schema::string",
+ "SELECT IFNULL(table_catalog, table_schema) AS table_catalog, table_schema, table_name, CASE WHEN table_type LIKE '%VIEW%' THEN 'VIEW' ELSE table_type END, CASE table_type WHEN 'BASE TABLE' THEN TRUE ELSE FALSE END AS table_type, table_comment, " SHORT_NAME("table_schema", "table_name", "CONCAT(table_schema, '.', table_name)") " as short_name, CONCAT(table_schema, '.', table_name) AS table_full_name, NULL AS table_owner FROM INFORMATION_SCHEMA.tables WHERE IFNULL(table_catalog, table_schema) = BINARY ##cat::string AND table_schema = BINARY ##schema::string AND table_name = BINARY ##name::string",
/* I_STMT_VIEWS_ALL */
"SELECT IFNULL(table_catalog, table_schema) AS table_catalog, table_schema, table_name, view_definition, check_option, is_updatable FROM INFORMATION_SCHEMA.views UNION SELECT IFNULL(table_catalog, table_schema) AS table_catalog, table_schema, table_name, NULL, NULL, FALSE FROM INFORMATION_SCHEMA.tables WHERE table_schema='information_schema' and table_type LIKE '%VIEW%'",
/* I_STMT_VIEW_NAMED */
- "SELECT IFNULL(table_catalog, table_schema) AS table_catalog, table_schema, table_name, view_definition, check_option, is_updatable FROM INFORMATION_SCHEMA.views WHERE table_catalog = ##cat::string AND table_schema = ##schema::string UNION SELECT IFNULL(table_catalog, table_schema) AS table_catalog, table_schema, table_name, NULL, NULL, FALSE FROM INFORMATION_SCHEMA.tables WHERE table_schema='information_schema' AND table_type LIKE '%VIEW%' AND table_catalog = ##cat::string AND table_schema = ##schema::string",
+ "SELECT IFNULL(table_catalog, table_schema) AS table_catalog, table_schema, table_name, view_definition, check_option, is_updatable FROM INFORMATION_SCHEMA.views WHERE table_catalog = BINARY ##cat::string AND table_schema = BINARY ##schema::string UNION SELECT IFNULL(table_catalog, table_schema) AS table_catalog, table_schema, table_name, NULL, NULL, FALSE FROM INFORMATION_SCHEMA.tables WHERE table_schema='information_schema' AND table_type LIKE '%VIEW%' AND IFNULL(table_catalog, table_schema) = BINARY ##cat::string AND table_schema = BINARY ##schema::string",
/* I_STMT_COLUMNS_OF_TABLE */
- "SELECT IFNULL(table_catalog, table_schema) AS table_catalog, table_schema, table_name, column_name, ordinal_position, column_default, is_nullable, data_type, 'gchararray', character_maximum_length,character_octet_length, numeric_precision, numeric_scale, 0, character_set_name, character_set_name, character_set_name, collation_name, collation_name, collation_name, CASE WHEN extra = 'auto_increment' then '" GDA_EXTRA_AUTO_INCREMENT "' ELSE extra END, 1, column_comment FROM INFORMATION_SCHEMA.columns WHERE table_catalog = ##cat::string AND table_schema = ##schema::string AND table_name = ##name::string",
+ "SELECT IFNULL(table_catalog, table_schema) AS table_catalog, table_schema, table_name, column_name, ordinal_position, column_default, is_nullable, data_type, NULL, 'gchararray', character_maximum_length,character_octet_length, numeric_precision, numeric_scale, 0, character_set_name, character_set_name, character_set_name, collation_name, collation_name, collation_name, CASE WHEN extra = 'auto_increment' then '" GDA_EXTRA_AUTO_INCREMENT "' ELSE extra END, 1, column_comment FROM INFORMATION_SCHEMA.columns WHERE IFNULL(table_catalog, table_schema) = BINARY ##cat::string AND table_schema = BINARY ##schema::string AND table_name = BINARY ##name::string",
/* I_STMT_COLUMNS_ALL */
- "SELECT IFNULL(table_catalog, table_schema) AS table_catalog, table_schema, table_name, column_name, ordinal_position, column_default, CASE is_nullable WHEN 'YES' THEN TRUE ELSE FALSE END AS is_nullable, data_type, 'gchararray', '', character_maximum_length, character_octet_length, numeric_precision, numeric_scale, 0, character_set_name, character_set_name, character_set_name, collation_name, collation_name, collation_name, CASE WHEN extra = 'auto_increment' then '" GDA_EXTRA_AUTO_INCREMENT "' ELSE extra END, IF(FIND_IN_SET('insert', privileges) != 0 OR FIND_IN_SET('update', privileges) != 0, TRUE, FALSE) AS is_updatable, column_comment FROM INFORMATION_SCHEMA.columns",
+ "SELECT IFNULL(table_catalog, table_schema) AS table_catalog, table_schema, table_name, column_name, ordinal_position, column_default, CASE is_nullable WHEN 'YES' THEN TRUE ELSE FALSE END AS is_nullable, data_type, NULL, 'gchararray', '', character_maximum_length, character_octet_length, numeric_precision, numeric_scale, 0, character_set_name, character_set_name, character_set_name, collation_name, collation_name, collation_name, CASE WHEN extra = 'auto_increment' then '" GDA_EXTRA_AUTO_INCREMENT "' ELSE extra END, IF(FIND_IN_SET('insert', privileges) != 0 OR FIND_IN_SET('update', privileges) != 0, TRUE, FALSE) AS is_updatable, column_comment FROM INFORMATION_SCHEMA.columns",
/* I_STMT_TABLES_CONSTRAINTS */
- "SELECT IFNULL(constraint_catalog, constraint_schema) AS constraint_catalog, constraint_schema, constraint_name, IFNULL(table_catalog, table_schema) AS table_catalog, table_schema, table_name, constraint_type, NULL, FALSE, FALSE FROM INFORMATION_SCHEMA.table_constraints WHERE constraint_catalog = ##cat::string AND constraint_schema = ##schema::string AND table_name = ##name::string",
+ "SELECT IFNULL(constraint_catalog, constraint_schema) AS constraint_catalog, constraint_schema, constraint_name, IFNULL(constraint_catalog, constraint_schema) AS table_catalog, table_schema, table_name, constraint_type, NULL, FALSE, FALSE FROM INFORMATION_SCHEMA.table_constraints WHERE constraint_catalog = BINARY ##cat::string AND constraint_schema = BINARY ##schema::string AND table_name = BINARY ##name::string",
/* I_STMT_TABLES_CONSTRAINTS_ALL */
"SELECT IFNULL(constraint_catalog, constraint_schema) AS constraint_catalog, constraint_schema, constraint_name, IFNULL(constraint_catalog, constraint_schema) AS onstraint_catalog, table_schema, table_name, constraint_type, NULL, FALSE, FALSE FROM INFORMATION_SCHEMA.table_constraints",
/* I_STMT_TABLES_CONSTRAINTS_NAMED */
- "SELECT IFNULL(constraint_catalog, constraint_schema) AS constraint_catalog, constraint_schema, constraint_name, IFNULL(table_catalog, table_schema) AS table_catalog, table_schema, table_name, constraint_type, NULL, FALSE, FALSE FROM INFORMATION_SCHEMA.table_constraints WHERE constraint_catalog = ##cat::string AND constraint_schema = ##schema::string AND table_name = ##name::string AND constraint_name = ##name2::string",
+ "SELECT IFNULL(constraint_catalog, constraint_schema) AS constraint_catalog, constraint_schema, constraint_name, IFNULL(constraint_catalog, constraint_schema) AS table_catalog, table_schema, table_name, constraint_type, NULL, FALSE, FALSE FROM INFORMATION_SCHEMA.table_constraints WHERE constraint_catalog = BINARY ##cat::string AND constraint_schema = BINARY ##schema::string AND table_name = BINARY ##name::string AND constraint_name = BINARY ##name2::string",
/* I_STMT_REF_CONSTRAINTS */
- "SELECT IFNULL(t.constraint_catalog, t.constraint_schema) AS constraint_catalog, t.constraint_schema, r.constraint_name, IFNULL(r.constraint_catalog, r.constraint_schema) AS constraint_catalog, r.constraint_schema, r.match_option, r.update_rule, delete_rule FROM INFORMATION_SCHEMA.referential_constraints r INNER JOIN INFORMATION_SCHEMA.table_constraints t ON r.constraint_schema=t.constraint_schema AND r.constraint_name=t.constraint_name AND r.table_name=t.table_name WHERE r.constraint_catalog = ##cat::string AND r.constraint_schema = ##schema::string AND r.table_name = ##name AND r.constraint_name = ##name2::string",
+ "SELECT IFNULL(t.constraint_catalog, t.constraint_schema) AS constraint_catalog, t.constraint_schema, r.constraint_name, IFNULL(r.constraint_catalog, r.constraint_schema) AS constraint_catalog, r.constraint_schema, r.match_option, r.update_rule, delete_rule FROM INFORMATION_SCHEMA.referential_constraints r INNER JOIN INFORMATION_SCHEMA.table_constraints t ON r.constraint_schema=t.constraint_schema AND r.constraint_name=t.constraint_name AND r.table_name=t.table_name WHERE r.constraint_catalog = BINARY ##cat::string AND r.constraint_schema = BINARY ##schema::string AND r.table_name = BINARY ##name AND r.constraint_name = BINARY ##name2::string",
/* I_STMT_REF_CONSTRAINTS_ALL */
"SELECT IFNULL(t.constraint_catalog, t.constraint_schema) AS constraint_catalog, t.constraint_schema, r.constraint_name, IFNULL(r.constraint_catalog, r.constraint_schema) AS constraint_catalog, r.constraint_schema, r.match_option, r.update_rule, delete_rule FROM INFORMATION_SCHEMA.referential_constraints r INNER JOIN INFORMATION_SCHEMA.table_constraints t ON r.constraint_schema=t.constraint_schema AND r.constraint_name=t.constraint_name AND r.table_name=t.table_name",
/* I_STMT_KEY_COLUMN_USAGE */
- "SELECT IFNULL(table_catalog, table_schema) AS table_catalog, table_schema, table_name, constraint_name, column_name, ordinal_position FROM INFORMATION_SCHEMA.key_column_usage WHERE table_catalog = ##cat::string AND table_schema = ##schema::string AND table_name = ##name::string AND constraint_name = ##name2::string",
+ "SELECT IFNULL(table_catalog, table_schema) AS table_catalog, table_schema, table_name, constraint_name, column_name, ordinal_position FROM INFORMATION_SCHEMA.key_column_usage WHERE IFNULL(table_catalog, table_schema) = BINARY ##cat::string AND table_schema = BINARY ##schema::string AND table_name = BINARY ##name::string AND constraint_name = BINARY ##name2::string",
/* I_STMT_KEY_COLUMN_USAGE_ALL */
"SELECT IFNULL(table_catalog, table_schema) AS table_catalog, table_schema, table_name, constraint_name, column_name, ordinal_position FROM INFORMATION_SCHEMA.key_column_usage",
/* I_STMT_CHARACTER_SETS */
- "SELECT DATABASE() AS character_set_catalog, DATABASE() AS character_set_schema, character_set_name, default_collate_name, default_collate_name, default_collate_name, description, character_set_name, character_set_name FROM INFORMATION_SCHEMA.character_sets WHERE character_set_catalog = ##cat::string AND character_set_schema = ##schema::string AND character_set_name = ##name::string",
+ "SELECT DATABASE() AS character_set_catalog, DATABASE() AS character_set_schema, character_set_name, default_collate_name, default_collate_name, default_collate_name, description, character_set_name, character_set_name FROM INFORMATION_SCHEMA.character_sets WHERE character_set_catalog = BINARY ##cat::string AND character_set_schema = BINARY ##schema::string AND character_set_name = BINARY ##name::string",
/* I_STMT_CHARACTER_SETS_ALL */
"SELECT DATABASE() AS character_set_catalog, DATABASE() AS character_set_schema, character_set_name, default_collate_name, default_collate_name, default_collate_name, description, character_set_name, character_set_name FROM INFORMATION_SCHEMA.character_sets",
@@ -175,13 +170,13 @@ static gchar *internal_sql[] = {
/* I_STMT_DOMAINS_CONSTRAINTS_ALL */
/* I_STMT_VIEWS_COLUMNS */
- "SELECT IFNULL(v.table_catalog, v.table_schema) AS table_catalog, v.table_schema, v.table_name, IFNULL(c.table_catalog, c.table_schema) AS table_catalog, c.table_schema, c.table_name, c.column_name FROM INFORMATION_SCHEMA.columns c INNER JOIN INFORMATION_SCHEMA.views v ON c.table_schema=v.table_schema AND c.table_name=v.table_name WHERE v.table_catalog = ##cat::string AND v.table_schema = ##schema::string AND v.table_name = ##name::string",
+ "SELECT IFNULL(v.table_catalog, v.table_schema) AS table_catalog, v.table_schema, v.table_name, IFNULL(c.table_catalog, c.table_schema) AS table_catalog, c.table_schema, c.table_name, c.column_name FROM INFORMATION_SCHEMA.columns c INNER JOIN INFORMATION_SCHEMA.views v ON c.table_schema=v.table_schema AND c.table_name=v.table_name WHERE IFNULL(v.table_catalog, v.table_schema) = BINARY ##cat::string AND v.table_schema = BINARY ##schema::string AND v.table_name = BINARY ##name::string",
/* I_STMT_VIEWS_COLUMNS_ALL */
"SELECT IFNULL(v.table_catalog, v.table_schema) AS table_catalog, v.table_schema, v.table_name, IFNULL(c.table_catalog, c.table_schema) AS table_catalog, c.table_schema, c.table_name, c.column_name FROM INFORMATION_SCHEMA.columns c INNER JOIN INFORMATION_SCHEMA.views v ON c.table_schema=v.table_schema AND c.table_name=v.table_name",
/* I_STMT_TRIGGERS */
- "SELECT IFNULL(trigger_catalog, trigger_schema) AS trigger_catalog, trigger_schema, trigger_name, event_manipulation, IFNULL(event_object_catalog, event_object_schema) AS event_object_catalog, event_object_schema, event_object_table, action_statement, action_orientation, action_timing, NULL, trigger_name, trigger_name FROM INFORMATION_SCHEMA.triggers WHERE trigger_catalog = ##cat::string AND trigger_schema = ##schema::string AND trigger_name = ##name::string",
+ "SELECT IFNULL(trigger_catalog, trigger_schema) AS trigger_catalog, trigger_schema, trigger_name, event_manipulation, IFNULL(event_object_catalog, event_object_schema) AS event_object_catalog, event_object_schema, event_object_table, action_statement, action_orientation, action_timing, NULL, trigger_name, trigger_name FROM INFORMATION_SCHEMA.triggers WHERE trigger_catalog = BINARY ##cat::string AND trigger_schema = BINARY ##schema::string AND trigger_name = BINARY ##name::string",
/* I_STMT_TRIGGERS_ALL */
"SELECT IFNULL(trigger_catalog, trigger_schema) AS trigger_catalog, trigger_schema, trigger_name, event_manipulation, IFNULL(event_object_catalog, event_object_schema) AS event_object_catalog, event_object_schema, event_object_table, action_statement, action_orientation, action_timing, NULL, trigger_name, trigger_name FROM INFORMATION_SCHEMA.triggers",
@@ -198,16 +193,16 @@ static gchar *internal_sql[] = {
"SELECT IFNULL(routine_catalog, routine_schema) AS specific_catalog, routine_schema AS specific_schema, routine_name AS specific_name, IFNULL(routine_catalog, routine_schema) AS routine_catalog, routine_schema, routine_name, routine_type, dtd_identifier AS return_type, FALSE AS returns_set, 0 AS nb_args, routine_body, routine_definition, external_name, external_language, parameter_style, CASE is_deterministic WHEN 'YES' THEN TRUE ELSE FALSE END AS is_deterministic, sql_data_access, FALSE AS is_null_call, routine_comment, routine_name, routine_name, definer FROM INFORMATION_SCHEMA.routines",
/* I_STMT_ROUTINES */
- "SELECT IFNULL(routine_catalog, routine_schema) AS specific_catalog, routine_schema AS specific_schema, routine_name AS specific_name, IFNULL(routine_catalog, routine_schema) AS routine_catalog, routine_schema, routine_name, routine_type, dtd_identifier AS return_type, FALSE AS returns_set, 0 AS nb_args, routine_body, routine_definition, external_name, external_language, parameter_style, CASE is_deterministic WHEN 'YES' THEN TRUE ELSE FALSE END AS is_deterministic, sql_data_access, FALSE AS is_null_call, routine_comment, routine_name, routine_name, definer FROM INFORMATION_SCHEMA.routines WHERE routine_catalog = ##cat::string AND routine_schema = ##schema::string",
+ "SELECT IFNULL(routine_catalog, routine_schema) AS specific_catalog, routine_schema AS specific_schema, routine_name AS specific_name, IFNULL(routine_catalog, routine_schema) AS routine_catalog, routine_schema, routine_name, routine_type, dtd_identifier AS return_type, FALSE AS returns_set, 0 AS nb_args, routine_body, routine_definition, external_name, external_language, parameter_style, CASE is_deterministic WHEN 'YES' THEN TRUE ELSE FALSE END AS is_deterministic, sql_data_access, FALSE AS is_null_call, routine_comment, routine_name, routine_name, definer FROM INFORMATION_SCHEMA.routines WHERE routine_catalog = BINARY ##cat::string AND routine_schema = BINARY ##schema::string",
/* I_STMT_ROUTINES_ONE */
- "SELECT IFNULL(routine_catalog, routine_schema) AS specific_catalog, routine_schema AS specific_schema, routine_name AS specific_name, IFNULL(routine_catalog, routine_schema) AS routine_catalog, routine_schema, routine_name, routine_type, dtd_identifier AS return_type, FALSE AS returns_set, 0 AS nb_args, routine_body, routine_definition, external_name, external_language, parameter_style, CASE is_deterministic WHEN 'YES' THEN TRUE ELSE FALSE END AS is_deterministic, sql_data_access, FALSE AS is_null_call, routine_comment, routine_name, routine_name, definer FROM INFORMATION_SCHEMA.routines WHERE routine_catalog = ##cat::string AND routine_schema = ##schema::string AND routine_name = ##name::string",
+ "SELECT IFNULL(routine_catalog, routine_schema) AS specific_catalog, routine_schema AS specific_schema, routine_name AS specific_name, IFNULL(routine_catalog, routine_schema) AS routine_catalog, routine_schema, routine_name, routine_type, dtd_identifier AS return_type, FALSE AS returns_set, 0 AS nb_args, routine_body, routine_definition, external_name, external_language, parameter_style, CASE is_deterministic WHEN 'YES' THEN TRUE ELSE FALSE END AS is_deterministic, sql_data_access, FALSE AS is_null_call, routine_comment, routine_name, routine_name, definer FROM INFORMATION_SCHEMA.routines WHERE routine_catalog = BINARY ##cat::string AND routine_schema = BINARY ##schema::string AND routine_name = BINARY ##name::string",
/* I_STMT_ROUTINES_PAR_ALL */
"SELECT IFNULL(routine_catalog, routine_schema) AS specific_catalog, routine_schema AS specific_schema, routine_name AS specific_name, IFNULL(routine_catalog, routine_schema) AS routine_catalog, routine_schema, routine_name, routine_type, dtd_identifier AS return_type, FALSE AS returns_set, 0 AS nb_args, routine_body, routine_definition, external_name, external_language, parameter_style, CASE is_deterministic WHEN 'YES' THEN TRUE ELSE FALSE END AS is_deterministic, sql_data_access, FALSE AS is_null_call, routine_comment, routine_name, routine_name, definer FROM INFORMATION_SCHEMA.routines",
/* I_STMT_ROUTINES_PAR */
- "SELECT IFNULL(routine_catalog, routine_schema) AS specific_catalog, routine_schema AS specific_schema, routine_name AS specific_name, IFNULL(routine_catalog, routine_schema) AS routine_catalog, routine_schema, routine_name, routine_type, dtd_identifier AS return_type, FALSE AS returns_set, 0 AS nb_args, routine_body, routine_definition, external_name, external_language, parameter_style, CASE is_deterministic WHEN 'YES' THEN TRUE ELSE FALSE END AS is_deterministic, sql_data_access, FALSE AS is_null_call, routine_comment, routine_name, routine_name, definer FROM INFORMATION_SCHEMA.routines WHERE routine_catalog = ##cat::string AND routine_schema = ##schema::string AND routine_name = ##name::string",
+ "SELECT IFNULL(routine_catalog, routine_schema) AS specific_catalog, routine_schema AS specific_schema, routine_name AS specific_name, IFNULL(routine_catalog, routine_schema) AS routine_catalog, routine_schema, routine_name, routine_type, dtd_identifier AS return_type, FALSE AS returns_set, 0 AS nb_args, routine_body, routine_definition, external_name, external_language, parameter_style, CASE is_deterministic WHEN 'YES' THEN TRUE ELSE FALSE END AS is_deterministic, sql_data_access, FALSE AS is_null_call, routine_comment, routine_name, routine_name, definer FROM INFORMATION_SCHEMA.routines WHERE routine_catalog = BINARY ##cat::string AND routine_schema = BINARY ##schema::string AND routine_name = BINARY ##name::string",
/* I_STMT_ROUTINES_COL_ALL */
@@ -277,7 +272,7 @@ _gda_mysql_meta__info (GdaServerProvider *prov,
else {
gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
retval = gda_meta_store_modify (store, context->table_name, model, NULL, error, NULL);
- g_object_unref (G_OBJECT(model));
+ g_object_unref (G_OBJECT (model));
}
return retval;
@@ -714,11 +709,11 @@ _gda_mysql_meta__tables_views (GdaServerProvider *prov,
{
GType col_types_tables[] = {
0, 0, 0, 0,
- G_TYPE_BOOLEAN, G_TYPE_NONE
+ G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_NONE
};
GType col_types_views[] = {
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
- G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_NONE
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_NONE
};
GdaDataModel *model_tables, *model_views;
gboolean retval;
@@ -772,8 +767,8 @@ _gda_mysql_meta_tables_views (GdaServerProvider *prov,
const GValue *table_name_n)
{
GType col_types_tables[] = {
- 0, 0, 0, 0,
- G_TYPE_BOOLEAN, G_TYPE_NONE
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_NONE
};
GType col_types_views[] = {
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
@@ -807,20 +802,25 @@ _gda_mysql_meta_tables_views (GdaServerProvider *prov,
if (model_tables == NULL)
retval = FALSE;
else {
+ copy.table_name = "_tables";
gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
- retval = gda_meta_store_modify_with_context (store, ©, model_tables, NULL);
- g_object_unref (G_OBJECT(model_tables));
+ retval = gda_meta_store_modify_with_context (store, ©, model_tables, error);
+ g_object_unref (G_OBJECT (model_tables));
}
+ if (!retval)
+ return FALSE;
+
model_views = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_VIEWS_ALL], i_set,
GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types_views,
error);
if (model_views == NULL)
retval = FALSE;
else {
+ copy.table_name = "_views";
gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
- retval = gda_meta_store_modify_with_context (store, ©, model_views, NULL);
- g_object_unref (G_OBJECT(model_views));
+ retval = gda_meta_store_modify_with_context (store, ©, model_views, error);
+ g_object_unref (G_OBJECT (model_views));
}
} else {
@@ -838,6 +838,8 @@ _gda_mysql_meta_tables_views (GdaServerProvider *prov,
g_object_unref (G_OBJECT(model_tables));
}
+ if (!retval)
+ return FALSE;
model_views = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_VIEW_NAMED], i_set,
GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types_views,
error);
@@ -991,8 +993,8 @@ _gda_mysql_meta__columns (GdaServerProvider *prov,
GType col_types[] = {
0, 0, 0, 0, G_TYPE_INT, G_TYPE_STRING,
G_TYPE_BOOLEAN,
- 0, 0, 0, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, 0, 0, 0, 0, 0, 0, 0,
- G_TYPE_BOOLEAN,
+ G_TYPE_STRING, 0, 0, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, 0, 0, 0, 0, 0, 0, G_TYPE_STRING, G_TYPE_BOOLEAN,
+ G_TYPE_STRING,
G_TYPE_NONE
};
GdaDataModel *model, *proxy;
@@ -1035,7 +1037,7 @@ _gda_mysql_meta__columns (GdaServerProvider *prov,
if (retval) {
gda_meta_store_set_reserved_keywords_func (store, _gda_mysql_get_reserved_keyword_func (cdata));
- retval = gda_meta_store_modify_with_context (store, context, proxy/* model */, error);
+ retval = gda_meta_store_modify_with_context (store, context, proxy, error);
}
g_object_unref (G_OBJECT(proxy));
@@ -1058,8 +1060,8 @@ _gda_mysql_meta_columns (GdaServerProvider *prov,
GType col_types[] = {
0, 0, 0, 0, G_TYPE_INT, G_TYPE_STRING,
G_TYPE_BOOLEAN,
- 0, 0, 0, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, 0, 0, 0, 0, 0, 0, 0,
- G_TYPE_BOOLEAN,
+ G_TYPE_STRING, 0, 0, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, 0, 0, 0, 0, 0, 0, G_TYPE_STRING, G_TYPE_BOOLEAN,
+ G_TYPE_STRING,
G_TYPE_NONE
};
GdaDataModel *model, *proxy;
@@ -1082,6 +1084,7 @@ _gda_mysql_meta_columns (GdaServerProvider *prov,
return FALSE;
if (! gda_holder_set_value (gda_set_get_holder (i_set, "name"), table_name, error))
return FALSE;
+
model = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_COLUMNS_OF_TABLE], i_set,
GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types, error);
if (model == NULL)
@@ -1228,8 +1231,8 @@ _gda_mysql_meta_constraints_tab (GdaServerProvider *prov,
const GValue *table_catalog,
const GValue *table_schema,
const GValue *table_name,
- const GValue *constraint_name_n)
-{
+ const GValue *constraint_name_n){
+
GdaDataModel *model;
gboolean retval;
MysqlConnectionData *cdata;
@@ -1469,8 +1472,6 @@ _gda_mysql_meta__triggers (GdaServerProvider *prov,
GdaMetaContext *context,
GError **error)
{
- // TO_IMPLEMENT;
-
GdaDataModel *model;
gboolean retval;
/* Check correct mysql server version. */
@@ -1506,8 +1507,6 @@ _gda_mysql_meta_triggers (GdaServerProvider *prov,
const GValue *table_schema,
const GValue *table_name)
{
- // TO_IMPLEMENT;
-
GdaDataModel *model;
gboolean retval;
/* Check correct mysql server version. */
@@ -1547,8 +1546,6 @@ _gda_mysql_meta__routines (GdaServerProvider *prov,
GdaMetaContext *context,
GError **error)
{
- //TO_IMPLEMENT;
-
GdaDataModel *model;
gboolean retval;
MysqlConnectionData *cdata;
@@ -1578,9 +1575,6 @@ _gda_mysql_meta_routines (GdaServerProvider *prov,
const GValue *routine_schema,
const GValue *routine_name_n)
{
- //TO_IMPLEMENT;
- //
-
GdaDataModel *model;
gboolean retval;
/* Check correct mysql server version. */
diff --git a/providers/mysql/gda-mysql-provider.c b/providers/mysql/gda-mysql-provider.c
index 299921f..f1d89c6 100644
--- a/providers/mysql/gda-mysql-provider.c
+++ b/providers/mysql/gda-mysql-provider.c
@@ -49,8 +49,23 @@
static void gda_mysql_provider_class_init (GdaMysqlProviderClass *klass);
static void gda_mysql_provider_init (GdaMysqlProvider *provider,
GdaMysqlProviderClass *klass);
+static void gda_mysql_provider_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gda_mysql_provider_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec);
static GObjectClass *parent_class = NULL;
+/* properties */
+enum
+{
+ PROP_0,
+ PROP_IDENT_CASE_SENSITIVE, /* used for tests */
+};
+
/*
* GdaServerProvider's virtual methods
*/
@@ -221,9 +236,20 @@ static void
gda_mysql_provider_class_init (GdaMysqlProviderClass *klass)
{
GdaServerProviderClass *provider_class = GDA_SERVER_PROVIDER_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
parent_class = g_type_class_peek_parent (klass);
+ /* Properties */
+ object_class->set_property = gda_mysql_provider_set_property;
+ object_class->get_property = gda_mysql_provider_get_property;
+
+ g_object_class_install_property (object_class, PROP_IDENT_CASE_SENSITIVE,
+ g_param_spec_boolean ("identifiers-case-sensitive", NULL, NULL, TRUE,
+ G_PARAM_READABLE | G_PARAM_WRITABLE));
+
+
+ /* virtual methods */
provider_class->get_version = gda_mysql_provider_get_version;
provider_class->get_server_version = gda_mysql_provider_get_server_version;
provider_class->get_name = gda_mysql_provider_get_name;
@@ -340,7 +366,9 @@ gda_mysql_provider_init (GdaMysqlProvider *mysql_prv,
/* meta data init */
_gda_mysql_provider_meta_init ((GdaServerProvider*) mysql_prv);
- /* TO_ADD: any other provider's init should be added here */
+ /* for tests */
+ mysql_prv->test_mode = FALSE;
+ mysql_prv->test_identifiers_case_sensitive = TRUE;
}
GType
@@ -369,12 +397,42 @@ gda_mysql_provider_get_type (void)
return type;
}
+static void
+gda_mysql_provider_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GdaMysqlProvider *mysql_prv;
+ mysql_prv = GDA_MYSQL_PROVIDER (object);
+ switch (param_id) {
+ case PROP_IDENT_CASE_SENSITIVE:
+ mysql_prv->test_identifiers_case_sensitive = g_value_get_boolean (value);
+ mysql_prv->test_mode = TRUE;
+ break;
+ }
+}
+
+static void
+gda_mysql_provider_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GdaMysqlProvider *mysql_prv;
+ mysql_prv = GDA_MYSQL_PROVIDER (object);
+ switch (param_id) {
+ case PROP_IDENT_CASE_SENSITIVE:
+ g_value_set_boolean (value, mysql_prv->test_identifiers_case_sensitive);
+ break;
+ }
+}
/*
* Get provider name request
*/
static const gchar *
-gda_mysql_provider_get_name (GdaServerProvider *provider)
+gda_mysql_provider_get_name (GdaServerProvider *provider)
{
return MYSQL_PROVIDER_NAME;
}
@@ -619,7 +677,7 @@ gda_mysql_provider_open_connection (GdaServerProvider *provider,
cdata->version_long = mysql_get_server_version (mysql);
cdata->version = get_mysql_version (mysql);
cdata->short_version = get_mysql_short_version (mysql);
- cdata->tables_case_sensitive = case_sensitive;
+ cdata->identifiers_case_sensitive = case_sensitive;
return TRUE;
}
@@ -1463,7 +1521,7 @@ gda_mysql_provider_statement_execute (GdaServerProvider *provider,
nps = real_prepare (provider, cnc, stmt, error);
if (!nps)
return NULL;
- gda_pstmt_copy_contents ((GdaPStmt *) ps, (GdaPStmt *) nps);
+ //gda_pstmt_copy_contents ((GdaPStmt *) ps, (GdaPStmt *) nps);
g_object_unref (ps);
ps = nps;
}
@@ -1973,54 +2031,192 @@ _sql_identifier_needs_quotes (const gchar *str)
return FALSE;
}
+/* Returns: @str */
+static gchar *
+my_remove_quotes (gchar *str)
+{
+ glong total;
+ gchar *ptr;
+ glong offset = 0;
+ char delim;
+
+ if (!str)
+ return NULL;
+ delim = *str;
+ if ((delim != '`') && (delim != '"'))
+ return str;
+
+ total = strlen (str);
+ if (str[total-1] == delim) {
+ /* string is correclty terminated */
+ g_memmove (str, str+1, total-2);
+ total -=2;
+ }
+ else {
+ /* string is _not_ correclty terminated */
+ g_memmove (str, str+1, total-1);
+ total -=1;
+ }
+ str[total] = 0;
+
+ ptr = (gchar *) str;
+ while (offset < total) {
+ /* we accept the "''" as a synonym of "\'" */
+ if (*ptr == delim) {
+ if (*(ptr+1) == delim) {
+ g_memmove (ptr+1, ptr+2, total - offset);
+ offset += 2;
+ }
+ else {
+ *str = 0;
+ return str;
+ }
+ }
+ if (*ptr == '\\') {
+ if (*(ptr+1) == '\\') {
+ g_memmove (ptr+1, ptr+2, total - offset);
+ offset += 2;
+ }
+ else {
+ if (*(ptr+1) == delim) {
+ *ptr = delim;
+ g_memmove (ptr+1, ptr+2, total - offset);
+ offset += 2;
+ }
+ else {
+ *str = 0;
+ return str;
+ }
+ }
+ }
+ else
+ offset ++;
+
+ ptr++;
+ }
+
+ return str;
+}
+
static gchar *
gda_mysql_identifier_quote (GdaServerProvider *provider, GdaConnection *cnc,
const gchar *id,
- gboolean meta_store_convention, gboolean force_quotes)
+ gboolean for_meta_store, gboolean force_quotes)
{
GdaSqlReservedKeywordsFunc kwfunc;
MysqlConnectionData *cdata = NULL;
+ gboolean case_sensitive = TRUE;
if (cnc) {
cdata = (MysqlConnectionData*) gda_connection_internal_get_provider_data (cnc);
if (!cdata)
return NULL;
+ case_sensitive = cdata->identifiers_case_sensitive;
}
+ else if (((GdaMysqlProvider*) provider)->test_mode)
+ case_sensitive = ((GdaMysqlProvider*) provider)->test_identifiers_case_sensitive;
kwfunc = _gda_mysql_get_reserved_keyword_func (cdata);
- if (meta_store_convention) {
- /* @id can either:
- * - be enquoted between double quotes
- * - not enquoted and in lower case
+
+ if (case_sensitive) {
+ /*
+ * case sensitive mode
*/
- if (*id == '"') {
- /* must be quoted, replace '"' with '`' */
- gchar *ptr, *retval;
- retval = g_strdup (id);
- *retval = '`';
- for (ptr = retval + 1; *ptr; ptr++) {
- if (*ptr == '"')
- *ptr = '`';
+ if (for_meta_store) {
+ gchar *tmp, *ptr;
+ tmp = my_remove_quotes (g_strdup (id));
+ if (kwfunc (tmp)) {
+ ptr = gda_sql_identifier_add_quotes (tmp);
+ g_free (tmp);
+ return ptr;
+ }
+ for (ptr = tmp; *ptr; ptr++) {
+ if (((*ptr >= 'a') && (*ptr <= 'z')) ||
+ ((*ptr >= '0') && (*ptr <= '9') && (ptr != tmp)) ||
+ (*ptr == '_'))
+ continue;
+ else {
+ ptr = gda_sql_identifier_add_quotes (tmp);
+ g_free (tmp);
+ return ptr;
+ }
}
- return retval;
+ return tmp;
+ /* ptr = gda_sql_identifier_add_quotes (tmp);
+ g_free (tmp);
+ return ptr;*/
}
-
- if (kwfunc (id) || _sql_identifier_needs_quotes (id) || force_quotes)
+ else {
+ if ((*id == '`') || (*id == '"')) {
+ /* there are already some quotes */
+ gchar *ptr, *tmp = g_strdup (id);
+ for (ptr = tmp; *ptr; ptr++)
+ if (*ptr == '"')
+ *ptr = '`';
+ return tmp;
+ }
return identifier_add_quotes (id);
-
- /* nothing to do */
- return g_strdup (id);
+ }
}
else {
- if (*id == '`') {
- /* there are already some quotes */
+ /*
+ * case insensitive mode
+ */
+ if (for_meta_store) {
+ gchar *tmp, *ptr;
+ tmp = my_remove_quotes (g_strdup (id));
+ if (kwfunc (tmp)) {
+ ptr = gda_sql_identifier_add_quotes (tmp);
+ g_free (tmp);
+ return ptr;
+ }
+ else if (0 && force_quotes) {
+ /* quote if non LC characters or digits at the 1st char or non allowed characters */
+ for (ptr = tmp; *ptr; ptr++) {
+ if (((*ptr >= 'a') && (*ptr <= 'z')) ||
+ ((*ptr >= '0') && (*ptr <= '9') && (ptr != tmp)) ||
+ (*ptr == '_'))
+ continue;
+ else {
+ ptr = gda_sql_identifier_add_quotes (tmp);
+ g_free (tmp);
+ return ptr;
+ }
+ }
+ return tmp;
+ }
+ else {
+ for (ptr = tmp; *ptr; ptr++) {
+ if ((*ptr >= 'A') && (*ptr <= 'Z'))
+ *ptr += 'a' - 'A';
+ else if (((*ptr >= 'a') && (*ptr <= 'z')) ||
+ ((*ptr >= '0') && (*ptr <= '9') && (ptr != tmp)) ||
+ (*ptr == '_'))
+ continue;
+ else {
+ ptr = gda_sql_identifier_add_quotes (tmp);
+ g_free (tmp);
+ return ptr;
+ }
+ }
+ return tmp;
+ }
+ }
+ else {
+ if ((*id == '`') || (*id == '"')) {
+ /* there are already some quotes */
+ gchar *ptr, *tmp = g_strdup (id);
+ for (ptr = tmp; *ptr; ptr++)
+ if (*ptr == '"')
+ *ptr = '`';
+ return tmp;
+ }
+ if (kwfunc (id) || _sql_identifier_needs_quotes (id) || force_quotes)
+ return identifier_add_quotes (id);
+
+ /* nothing to do */
return g_strdup (id);
}
- if (kwfunc (id) || _sql_identifier_needs_quotes (id) || force_quotes)
- return identifier_add_quotes (id);
-
- /* nothing to do */
- return g_strdup (id);
}
}
diff --git a/providers/mysql/gda-mysql-provider.h b/providers/mysql/gda-mysql-provider.h
index af8f03f..826baee 100644
--- a/providers/mysql/gda-mysql-provider.h
+++ b/providers/mysql/gda-mysql-provider.h
@@ -36,6 +36,8 @@ typedef struct _GdaMysqlProviderClass GdaMysqlProviderClass;
struct _GdaMysqlProvider {
GdaServerProvider provider;
+ gboolean test_mode; /* for tests ONLY */
+ gboolean test_identifiers_case_sensitive; /* for tests ONLY */
};
struct _GdaMysqlProviderClass {
diff --git a/providers/mysql/gda-mysql-recordset.c b/providers/mysql/gda-mysql-recordset.c
index 222bef2..2729afe 100644
--- a/providers/mysql/gda-mysql-recordset.c
+++ b/providers/mysql/gda-mysql-recordset.c
@@ -1,8 +1,9 @@
/* GDA Mysql provider
- * Copyright (C) 2008 The GNOME Foundation.
+ * Copyright (C) 2008 - 2009 The GNOME Foundation.
*
* AUTHORS:
* Carlos Savoretti <csavoretti gmail com>
+ * 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
@@ -28,6 +29,7 @@
#include "gda-mysql.h"
#include "gda-mysql-recordset.h"
#include "gda-mysql-provider.h"
+#include "gda-mysql-util.h"
#ifdef HAVE_LOCALE_H
#include <locale.h>
@@ -411,7 +413,6 @@ gda_mysql_recordset_new (GdaConnection *cnc,
ps->stmt_used = TRUE;
if (!_GDA_PSTMT (ps)->types && (_GDA_PSTMT (ps)->ncols > 0)) {
/* create prepared statement's columns */
- GSList *list;
for (i = 0; i < _GDA_PSTMT (ps)->ncols; i++)
_GDA_PSTMT (ps)->tmpl_columns = g_slist_prepend (_GDA_PSTMT (ps)->tmpl_columns,
gda_column_new ());
@@ -432,88 +433,99 @@ gda_mysql_recordset_new (GdaConnection *cnc,
}
}
}
+ }
-
- MYSQL_RES *mysql_res = mysql_stmt_result_metadata (ps->mysql_stmt);
- MYSQL_FIELD *mysql_fields = mysql_fetch_fields (mysql_res);
-
- MYSQL_BIND *mysql_bind_result = g_new0 (MYSQL_BIND, GDA_PSTMT (ps)->ncols);
-
- /* fill GdaColumn's data */
- for (i=0, list = _GDA_PSTMT (ps)->tmpl_columns;
- i < GDA_PSTMT (ps)->ncols;
- i++, list = list->next) {
- GdaColumn *column = GDA_COLUMN (list->data);
+ /* get rid of old bound result if any */
+ if (ps->mysql_bind_result) {
+ gint i;
+ for (i = 0; i < ((GdaPStmt *) ps)->ncols; ++i) {
+ g_free (ps->mysql_bind_result[i].buffer);
+ g_free (ps->mysql_bind_result[i].is_null);
+ g_free (ps->mysql_bind_result[i].length);
+ }
+ g_free (ps->mysql_bind_result);
+ ps->mysql_bind_result = NULL;
+ }
- /* use C API to set columns' information using gda_column_set_*() */
- MYSQL_FIELD *field = &mysql_fields[i];
+ /* fill bind result */
+ MYSQL_RES *mysql_res = mysql_stmt_result_metadata (ps->mysql_stmt);
+ MYSQL_FIELD *mysql_fields = mysql_fetch_fields (mysql_res);
+
+ MYSQL_BIND *mysql_bind_result = g_new0 (MYSQL_BIND, GDA_PSTMT (ps)->ncols);
+ GSList *list;
- GType gtype = _GDA_PSTMT(ps)->types[i];
- if (gtype == 0) {
- gtype = _gda_mysql_type_to_gda (cdata, field->type);
- _GDA_PSTMT(ps)->types[i] = gtype;
- }
- gda_column_set_g_type (column, gtype);
- gda_column_set_name (column, field->name);
- gda_column_set_description (column, field->name);
-
- /* binding results with types */
- mysql_bind_result[i].buffer_type = field->type;
- mysql_bind_result[i].is_unsigned = field->flags & UNSIGNED_FLAG ? TRUE : FALSE;
- mysql_bind_result[i].is_null = g_malloc0 (sizeof(my_bool));
-
- switch (mysql_bind_result[i].buffer_type) {
- case MYSQL_TYPE_TINY:
- case MYSQL_TYPE_SHORT:
- case MYSQL_TYPE_INT24:
- case MYSQL_TYPE_LONG:
- case MYSQL_TYPE_YEAR:
- mysql_bind_result[i].buffer = g_malloc0 (sizeof(int));
- break;
- case MYSQL_TYPE_LONGLONG:
- mysql_bind_result[i].buffer = g_malloc0 (sizeof(long long));
- break;
- case MYSQL_TYPE_NULL:
- break;
- case MYSQL_TYPE_TIME:
- case MYSQL_TYPE_DATE:
- case MYSQL_TYPE_DATETIME:
- case MYSQL_TYPE_TIMESTAMP:
- mysql_bind_result[i].buffer = g_malloc0 (sizeof(MYSQL_TIME));
- break;
- case MYSQL_TYPE_FLOAT:
- case MYSQL_TYPE_DOUBLE:
- mysql_bind_result[i].buffer = g_malloc0 (sizeof(double));
- break;
- case MYSQL_TYPE_STRING:
- case MYSQL_TYPE_VAR_STRING:
- case MYSQL_TYPE_BLOB:
- case MYSQL_TYPE_TINY_BLOB:
- case MYSQL_TYPE_MEDIUM_BLOB:
- case MYSQL_TYPE_LONG_BLOB:
- case MYSQL_TYPE_NEWDECIMAL:
- case MYSQL_TYPE_BIT:
- mysql_bind_result[i].buffer = g_malloc0 (field->max_length + 1);
- mysql_bind_result[i].buffer_length = field->max_length + 1;
- mysql_bind_result[i].length = g_malloc0 (sizeof(unsigned long));
- break;
- default:
- g_warning (_("Invalid column bind data type. %d\n"),
- mysql_bind_result[i].buffer_type);
- }
- /*g_print ("%s(): NAME=%s, TYPE=%d, GTYPE=%s\n",
- __FUNCTION__, field->name, field->type, g_type_name (gtype));*/
+ for (i=0, list = _GDA_PSTMT (ps)->tmpl_columns;
+ i < GDA_PSTMT (ps)->ncols;
+ i++, list = list->next) {
+ GdaColumn *column = GDA_COLUMN (list->data);
+
+ /* use C API to set columns' information using gda_column_set_*() */
+ MYSQL_FIELD *field = &mysql_fields[i];
+
+ GType gtype = _GDA_PSTMT(ps)->types[i];
+ if (gtype == 0) {
+ gtype = _gda_mysql_type_to_gda (cdata, field->type);
+ _GDA_PSTMT(ps)->types[i] = gtype;
}
+ gda_column_set_g_type (column, gtype);
+ gda_column_set_name (column, field->name);
+ gda_column_set_description (column, field->name);
- if (mysql_stmt_bind_result (ps->mysql_stmt, mysql_bind_result)) {
- g_warning ("mysql_stmt_bind_result failed: %s\n",
- mysql_stmt_error (ps->mysql_stmt));
- }
+ /* binding results with types */
+ mysql_bind_result[i].buffer_type = field->type;
+ mysql_bind_result[i].is_unsigned = field->flags & UNSIGNED_FLAG ? TRUE : FALSE;
+ mysql_bind_result[i].is_null = g_malloc0 (sizeof(my_bool));
- mysql_free_result (mysql_res);
-
- ps->mysql_bind_result = mysql_bind_result;
- }
+ switch (mysql_bind_result[i].buffer_type) {
+ case MYSQL_TYPE_TINY:
+ case MYSQL_TYPE_SHORT:
+ case MYSQL_TYPE_INT24:
+ case MYSQL_TYPE_LONG:
+ case MYSQL_TYPE_YEAR:
+ mysql_bind_result[i].buffer = g_malloc0 (sizeof(int));
+ break;
+ case MYSQL_TYPE_LONGLONG:
+ mysql_bind_result[i].buffer = g_malloc0 (sizeof(long long));
+ break;
+ case MYSQL_TYPE_NULL:
+ break;
+ case MYSQL_TYPE_TIME:
+ case MYSQL_TYPE_DATE:
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_TIMESTAMP:
+ mysql_bind_result[i].buffer = g_malloc0 (sizeof(MYSQL_TIME));
+ break;
+ case MYSQL_TYPE_FLOAT:
+ case MYSQL_TYPE_DOUBLE:
+ mysql_bind_result[i].buffer = g_malloc0 (sizeof(double));
+ break;
+ case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_NEWDECIMAL:
+ case MYSQL_TYPE_BIT:
+ mysql_bind_result[i].buffer = g_malloc0 (field->max_length + 1);
+ mysql_bind_result[i].buffer_length = field->max_length + 1;
+ mysql_bind_result[i].length = g_malloc0 (sizeof(unsigned long));
+ break;
+ default:
+ g_warning (_("Invalid column bind data type. %d\n"),
+ mysql_bind_result[i].buffer_type);
+ }
+ /*g_print ("%s(): NAME=%s, TYPE=%d, GTYPE=%s\n",
+ __FUNCTION__, field->name, field->type, g_type_name (gtype));*/
+ }
+
+ if (mysql_stmt_bind_result (ps->mysql_stmt, mysql_bind_result)) {
+ g_warning ("mysql_stmt_bind_result failed: %s\n",
+ mysql_stmt_error (ps->mysql_stmt));
+ }
+
+ mysql_free_result (mysql_res);
+ ps->mysql_bind_result = mysql_bind_result;
/* determine access mode: RANDOM or CURSOR FORWARD are the only supported */
if (flags & GDA_DATA_MODEL_ACCESS_RANDOM)
@@ -537,7 +549,7 @@ gda_mysql_recordset_new (GdaConnection *cnc,
model->priv->mysql_stmt = ps->mysql_stmt;
((GdaDataSelect *) model)->advertized_nrows = mysql_stmt_affected_rows (ps->mysql_stmt);
-
+
return GDA_DATA_MODEL (model);
}
@@ -563,20 +575,48 @@ gda_mysql_recordset_fetch_nb_rows (GdaDataSelect *model)
}
static GdaRow *
-new_row_from_mysql_stmt (GdaMysqlRecordset *imodel, gint rownum, GError **error)
+new_row_from_mysql_stmt (GdaMysqlRecordset *imodel, gint rownum, GError **error)
{
//g_print ("%s(): NCOLS=%d ROWNUM=%d\n", __func__, ((GdaDataSelect *) imodel)->prep_stmt->ncols, rownum);
-
+ int res;
+ MYSQL_BIND *mysql_bind_result;
g_return_val_if_fail (imodel->priv->mysql_stmt != NULL, NULL);
- if (mysql_stmt_fetch (imodel->priv->mysql_stmt)) {
- g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_DATA_ERROR,
- _("Can't fetch data from server"));
+ mysql_bind_result = ((GdaMysqlPStmt *) ((GdaDataSelect *) imodel)->prep_stmt)->mysql_bind_result;
+ g_assert (mysql_bind_result);
+
+ res = mysql_stmt_fetch (imodel->priv->mysql_stmt);
+ if (res == MYSQL_NO_DATA) {
+ /* should not happen */
+ g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_ACCESS_ERROR,
+ "No more data, please report this bug to "
+ "http://bugzilla.gnome.org/ for the \"libgda\" product and the MySQL provider.");
+ }
+ else if (res == MYSQL_DATA_TRUNCATED) {
+ GString *string;
+
+ string = g_string_new ("Truncated data, please report this bug to "
+ "http://bugzilla.gnome.org/ for the \"libgda\" product and the MySQL provider.");
+
+ gint col;
+ for (col = 0; col < ((GdaDataSelect *) imodel)->prep_stmt->ncols; ++col) {
+ my_bool truncated;
+ mysql_bind_result[col].error = &truncated;
+ mysql_stmt_fetch_column (imodel->priv->mysql_stmt, &(mysql_bind_result[col]),
+ (unsigned int)col, 0);
+ if (truncated)
+ g_string_append_printf (string, "\n column %d is truncated\n", col);
+ mysql_bind_result[col].error = NULL;
+ }
+ g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_ACCESS_ERROR, "%s", string->str);
+ g_string_free (string, TRUE);
+
+ return NULL;
+ }
+ else if (res) {
+ _gda_mysql_make_error (imodel->priv->cnc, NULL, imodel->priv->mysql_stmt, error);
return NULL;
}
-
- MYSQL_BIND *mysql_bind_result = ((GdaMysqlPStmt *) ((GdaDataSelect *) imodel)->prep_stmt)->mysql_bind_result;
- g_assert (mysql_bind_result);
GdaRow *row = gda_row_new (((GdaDataSelect *) imodel)->prep_stmt->ncols);
gint col;
@@ -744,12 +784,33 @@ new_row_from_mysql_stmt (GdaMysqlRecordset *imodel, gint rownum, GError **error
gda_value_set_binary (value, &binary);
}
else if (type == G_TYPE_DOUBLE) {
- setlocale (LC_NUMERIC, "C");
- g_value_set_double (value, atof (strvalue));
- setlocale (LC_NUMERIC, gda_numeric_locale);
+ if (length > 0) {
+ setlocale (LC_NUMERIC, "C");
+ g_value_set_double (value, atof (strvalue));
+ setlocale (LC_NUMERIC, gda_numeric_locale);
+ }
+ else {
+ /* error: wrong column type */
+ gda_row_invalidate_value (row, value);
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+ GDA_SERVER_PROVIDER_DATA_ERROR,
+ _("Invalid column bind data type. %d\n"),
+ mysql_bind_result[i].buffer_type);
+ break;
+ }
}
else if (type == G_TYPE_BOOLEAN) {
- g_value_set_boolean (value, atoi (strvalue));
+ if (length > 0)
+ g_value_set_boolean (value, atoi (strvalue));
+ else {
+ /* error: wrong column type */
+ gda_row_invalidate_value (row, value);
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+ GDA_SERVER_PROVIDER_DATA_ERROR,
+ _("Invalid column bind data type. %d\n"),
+ mysql_bind_result[i].buffer_type);
+ break;
+ }
}
else {
gda_row_invalidate_value (row, value);
@@ -799,7 +860,6 @@ gda_mysql_recordset_fetch_random (GdaDataSelect *model,
imodel = GDA_MYSQL_RECORDSET (model);
- // TO_IMPLEMENT;
if (*row)
return TRUE;
diff --git a/providers/mysql/gda-mysql.h b/providers/mysql/gda-mysql.h
index c601771..88b830b 100644
--- a/providers/mysql/gda-mysql.h
+++ b/providers/mysql/gda-mysql.h
@@ -51,7 +51,7 @@ typedef struct {
gchar *short_version;
/* specifies how case sensitiveness is */
- gboolean tables_case_sensitive;
+ gboolean identifiers_case_sensitive;
} MysqlConnectionData;
diff --git a/providers/postgres/gda-postgres-provider.c b/providers/postgres/gda-postgres-provider.c
index 37f3d6f..ad9955a 100644
--- a/providers/postgres/gda-postgres-provider.c
+++ b/providers/postgres/gda-postgres-provider.c
@@ -75,7 +75,7 @@ static gchar *gda_postgres_provider_render_operation (GdaServerProv
GdaServerOperation *op, GError **error);
static gboolean gda_postgres_provider_perform_operation (GdaServerProvider *provider, GdaConnection *cnc,
- GdaServerOperation *op, guint *task_id,
+ GdaServerOperation *op, guint *task_id,
GdaServerProviderAsyncCallback async_cb, gpointer cb_data,
GError **error);
/* transactions */
@@ -107,16 +107,16 @@ static const gchar* gda_postgres_provider_get_default_dbms_type (GdaServe
/* statements */
static GdaSqlParser *gda_postgres_provider_create_parser (GdaServerProvider *provider, GdaConnection *cnc);
static gchar *gda_postgres_provider_statement_to_sql (GdaServerProvider *provider, GdaConnection *cnc,
- GdaStatement *stmt, GdaSet *params,
+ GdaStatement *stmt, GdaSet *params,
GdaStatementSqlFlag flags,
GSList **params_used, GError **error);
static gboolean gda_postgres_provider_statement_prepare (GdaServerProvider *provider, GdaConnection *cnc,
GdaStatement *stmt, GError **error);
static GObject *gda_postgres_provider_statement_execute (GdaServerProvider *provider, GdaConnection *cnc,
GdaStatement *stmt, GdaSet *params,
- GdaStatementModelUsage model_usage,
- GType *col_types, GdaSet **last_inserted_row,
- guint *task_id, GdaServerProviderExecCallback async_cb,
+ GdaStatementModelUsage model_usage,
+ GType *col_types, GdaSet **last_inserted_row,
+ guint *task_id, GdaServerProviderExecCallback async_cb,
gpointer cb_data, GError **error);
/* Quoting */
@@ -125,24 +125,24 @@ static gchar *gda_postgresql_identifier_quote (GdaServerProvide
gboolean meta_store_convention, gboolean force_quotes);
/* distributed transactions */
-static gboolean gda_postgres_provider_xa_start (GdaServerProvider *provider, GdaConnection *cnc,
+static gboolean gda_postgres_provider_xa_start (GdaServerProvider *provider, GdaConnection *cnc,
const GdaXaTransactionId *xid, GError **error);
-static gboolean gda_postgres_provider_xa_end (GdaServerProvider *provider, GdaConnection *cnc,
+static gboolean gda_postgres_provider_xa_end (GdaServerProvider *provider, GdaConnection *cnc,
const GdaXaTransactionId *xid, GError **error);
-static gboolean gda_postgres_provider_xa_prepare (GdaServerProvider *provider, GdaConnection *cnc,
+static gboolean gda_postgres_provider_xa_prepare (GdaServerProvider *provider, GdaConnection *cnc,
const GdaXaTransactionId *xid, GError **error);
-static gboolean gda_postgres_provider_xa_commit (GdaServerProvider *provider, GdaConnection *cnc,
+static gboolean gda_postgres_provider_xa_commit (GdaServerProvider *provider, GdaConnection *cnc,
const GdaXaTransactionId *xid, GError **error);
-static gboolean gda_postgres_provider_xa_rollback (GdaServerProvider *provider, GdaConnection *cnc,
+static gboolean gda_postgres_provider_xa_rollback (GdaServerProvider *provider, GdaConnection *cnc,
const GdaXaTransactionId *xid, GError **error);
-static GList *gda_postgres_provider_xa_recover (GdaServerProvider *provider, GdaConnection *cnc,
+static GList *gda_postgres_provider_xa_recover (GdaServerProvider *provider, GdaConnection *cnc,
GError **error);
-/*
- * private connection data destroy
+/*
+ * private connection data destroy
*/
static void gda_postgres_free_cnc_data (PostgresConnectionData *cdata);
@@ -258,7 +258,7 @@ gda_postgres_provider_class_init (GdaPostgresProviderClass *klass)
provider_class->meta_funcs.routine_col = _gda_postgres_meta_routine_col;
provider_class->meta_funcs._routine_par = _gda_postgres_meta__routine_par;
provider_class->meta_funcs.routine_par = _gda_postgres_meta_routine_par;
-
+
provider_class->xa_funcs = g_new0 (GdaServerProviderXa, 1);
provider_class->xa_funcs->xa_start = gda_postgres_provider_xa_start;
provider_class->xa_funcs->xa_end = gda_postgres_provider_xa_end;
@@ -288,7 +288,7 @@ gda_postgres_provider_init (GdaPostgresProvider *postgres_prv, GdaPostgresProvid
internal_stmt = g_new0 (GdaStatement *, sizeof (internal_sql) / sizeof (gchar*));
for (i = I_STMT_BEGIN; i < sizeof (internal_sql) / sizeof (gchar*); i++) {
internal_stmt[i] = gda_sql_parser_parse_string (parser, internal_sql[i], NULL, NULL);
- if (!internal_stmt[i])
+ if (!internal_stmt[i])
g_error ("Could not parse internal statement: %s\n", internal_sql[i]);
}
@@ -332,7 +332,7 @@ gda_postgres_provider_get_name (GdaServerProvider *provider)
return POSTGRES_PROVIDER_NAME;
}
-/*
+/*
* Get provider's version, no need to change this
*/
static const gchar *
@@ -386,7 +386,7 @@ pq_notice_processor (PostgresConnectionData *cdata, const char *message)
gda_connection_event_set_description (error, message);
gda_connection_event_set_code (error, -1);
gda_connection_event_set_source (error, gda_connection_get_provider_name (cdata->cnc));
- gda_connection_event_set_sqlstate (error, "-1");
+ gda_connection_event_set_sqlstate (error, "-1");
gda_connection_add_event (cdata->cnc, error);
}
@@ -504,13 +504,13 @@ get_connection_type_list (PostgresConnectionData *cdata)
g_free (query);
/* query to fetch the oid of the 'any' data type */
- pg_res_anyoid = _gda_postgres_PQexec_wrap (cdata->cnc, cdata->pconn,
+ pg_res_anyoid = _gda_postgres_PQexec_wrap (cdata->cnc, cdata->pconn,
"SELECT t.oid FROM pg_catalog.pg_type t WHERE t.typname = 'any'");
}
if (!pg_res || (PQresultStatus (pg_res) != PGRES_TUPLES_OK) ||
!pg_res_avoid || (PQresultStatus (pg_res_avoid) != PGRES_TUPLES_OK) ||
- ((cdata->version_float >= 7.3) &&
+ ((cdata->version_float >= 7.3) &&
(!pg_res_anyoid || (PQresultStatus (pg_res_anyoid) != PGRES_TUPLES_OK)))) {
if (pg_res)
PQclear (pg_res);
@@ -548,7 +548,7 @@ get_connection_type_list (PostgresConnectionData *cdata)
string = NULL;
nrows = PQntuples (pg_res_avoid);
for (i = 0; i < nrows; i++) {
- if (!string)
+ if (!string)
string = g_string_new (PQgetvalue (pg_res_avoid, i, 0));
else
g_string_append_printf (string, ", %s", PQgetvalue (pg_res_avoid, i, 0));
@@ -570,7 +570,7 @@ get_connection_type_list (PostgresConnectionData *cdata)
return 0;
}
-/*
+/*
* Open connection request
*
* In this function, the following _must_ be done:
@@ -674,7 +674,7 @@ gda_postgres_provider_open_connection (GdaServerProvider *provider, GdaConnectio
pq_requiressl ? " requiressl=" : "",
pq_requiressl ? pq_requiressl : "",
NULL);
-
+
/* open the real connection to the database */
PGconn *pconn;
pconn = PQconnectdb (conn_string);
@@ -685,7 +685,7 @@ gda_postgres_provider_open_connection (GdaServerProvider *provider, GdaConnectio
PQfinish (pconn);
return FALSE;
}
-
+
/* Create a new instance of the provider specific data associated to a connection (PostgresConnectionData),
* and set its contents */
PostgresConnectionData *cdata;
@@ -761,7 +761,7 @@ gda_postgres_provider_open_connection (GdaServerProvider *provider, GdaConnectio
return FALSE;
}
}
-
+
/* attach connection data */
gda_connection_internal_set_provider_data (cnc, cdata, (GDestroyNotify) gda_postgres_free_cnc_data);
@@ -778,7 +778,7 @@ gda_postgres_provider_open_connection (GdaServerProvider *provider, GdaConnectio
return TRUE;
}
-/*
+/*
* Close connection request
*
* In this function, the following _must_ be done:
@@ -797,10 +797,10 @@ gda_postgres_provider_close_connection (GdaServerProvider *provider, GdaConnecti
/* Close the connection using the C API */
cdata = (PostgresConnectionData*) gda_connection_internal_get_provider_data (cnc);
- if (!cdata)
+ if (!cdata)
return FALSE;
- /* Free the PostgresConnectionData structure and its contents
+ /* Free the PostgresConnectionData structure and its contents
* (will also actually close the connection to the server )*/
gda_postgres_free_cnc_data (cdata);
gda_connection_internal_set_provider_data (cnc, NULL, NULL);
@@ -822,7 +822,7 @@ gda_postgres_provider_get_server_version (GdaServerProvider *provider, GdaConnec
g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
cdata = (PostgresConnectionData*) gda_connection_internal_get_provider_data (cnc);
- if (!cdata)
+ if (!cdata)
return FALSE;
return cdata->version;
@@ -842,7 +842,7 @@ gda_postgres_provider_get_database (GdaServerProvider *provider, GdaConnection *
g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
cdata = (PostgresConnectionData*) gda_connection_internal_get_provider_data (cnc);
- if (!cdata)
+ if (!cdata)
return NULL;
return (const char *) PQdb ((const PGconn *) cdata->pconn);
@@ -1015,7 +1015,7 @@ gda_postgres_provider_render_operation (GdaServerProvider *provider, GdaConnecti
*/
static gboolean
gda_postgres_provider_perform_operation (GdaServerProvider *provider, GdaConnection *cnc,
- GdaServerOperation *op, guint *task_id,
+ GdaServerOperation *op, guint *task_id,
GdaServerProviderAsyncCallback async_cb, gpointer cb_data, GError **error)
{
GdaServerOperationType optype;
@@ -1032,14 +1032,14 @@ gda_postgres_provider_perform_operation (GdaServerProvider *provider, GdaConnect
g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
}
optype = gda_server_operation_get_op_type (op);
- if (!cnc &&
+ if (!cnc &&
((optype == GDA_SERVER_OPERATION_CREATE_DB) ||
(optype == GDA_SERVER_OPERATION_DROP_DB))) {
GValue *value;
PGconn *pconn;
PGresult *pg_res;
GString *string;
-
+
const gchar *pq_host = NULL;
const gchar *pq_db = NULL;
gint pq_port = -1;
@@ -1051,7 +1051,7 @@ gda_postgres_provider_perform_operation (GdaServerProvider *provider, GdaConnect
value = (GValue *) gda_server_operation_get_value_at (op, "/SERVER_CNX_P/HOST");
if (value && G_VALUE_HOLDS (value, G_TYPE_STRING) && g_value_get_string (value))
pq_host = g_value_get_string (value);
-
+
value = (GValue *) gda_server_operation_get_value_at (op, "/SERVER_CNX_P/PORT");
if (value && G_VALUE_HOLDS (value, G_TYPE_INT) && (g_value_get_int (value) > 0))
pq_port = g_value_get_int (value);
@@ -1113,7 +1113,7 @@ gda_postgres_provider_perform_operation (GdaServerProvider *provider, GdaConnect
PQfinish (pconn);
return FALSE;
}
-
+
PQfinish (pconn);
return TRUE;
}
@@ -1138,7 +1138,7 @@ gda_postgres_provider_begin_transaction (GdaServerProvider *provider, GdaConnect
g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
cdata = (PostgresConnectionData*) gda_connection_internal_get_provider_data (cnc);
- if (!cdata)
+ if (!cdata)
return FALSE;
/* transaction's parameters */
@@ -1164,13 +1164,13 @@ gda_postgres_provider_begin_transaction (GdaServerProvider *provider, GdaConnect
case GDA_TRANSACTION_ISOLATION_READ_UNCOMMITTED:
g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_NON_SUPPORTED_ERROR,
"%s", _("Transactions are not supported in read uncommitted isolation level"));
- gda_connection_add_event_string (cnc,
+ gda_connection_add_event_string (cnc,
_("Transactions are not supported in read uncommitted isolation level"));
return FALSE;
case GDA_TRANSACTION_ISOLATION_REPEATABLE_READ:
g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_NON_SUPPORTED_ERROR,
"%s", _("Transactions are not supported in repeatable read isolation level"));
- gda_connection_add_event_string (cnc,
+ gda_connection_add_event_string (cnc,
_("Transactions are not supported in repeatable read isolation level"));
return FALSE;
case GDA_TRANSACTION_ISOLATION_SERIALIZABLE :
@@ -1222,7 +1222,7 @@ gda_postgres_provider_commit_transaction (GdaServerProvider *provider, GdaConnec
g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
cdata = (PostgresConnectionData*) gda_connection_internal_get_provider_data (cnc);
- if (!cdata)
+ if (!cdata)
return FALSE;
/* COMMIT statement */
@@ -1246,7 +1246,7 @@ gda_postgres_provider_rollback_transaction (GdaServerProvider *provider,
g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
cdata = (PostgresConnectionData*) gda_connection_internal_get_provider_data (cnc);
- if (!cdata)
+ if (!cdata)
return FALSE;
/* ROLLBACK statement */
@@ -1270,7 +1270,7 @@ gda_postgres_provider_add_savepoint (GdaServerProvider *provider, GdaConnection
g_return_val_if_fail (name && *name, FALSE);
cdata = (PostgresConnectionData*) gda_connection_internal_get_provider_data (cnc);
- if (!cdata)
+ if (!cdata)
return FALSE;
/* Statement */
@@ -1320,7 +1320,7 @@ gda_postgres_provider_rollback_savepoint (GdaServerProvider *provider, GdaConnec
g_return_val_if_fail (name && *name, FALSE);
cdata = (PostgresConnectionData*) gda_connection_internal_get_provider_data (cnc);
- if (!cdata)
+ if (!cdata)
return FALSE;
/* Statement */
@@ -1370,7 +1370,7 @@ gda_postgres_provider_delete_savepoint (GdaServerProvider *provider, GdaConnecti
g_return_val_if_fail (name && *name, FALSE);
cdata = (PostgresConnectionData*) gda_connection_internal_get_provider_data (cnc);
- if (!cdata)
+ if (!cdata)
return FALSE;
/* Statement */
@@ -1438,7 +1438,7 @@ gda_postgres_provider_supports_feature (GdaServerProvider *provider, GdaConnecti
PostgresConnectionData *cdata;
cdata = (PostgresConnectionData*) gda_connection_internal_get_provider_data (cnc);
- if (!cdata)
+ if (!cdata)
return FALSE;
if (cdata->version_float >= 7.3)
return TRUE;
@@ -1464,7 +1464,7 @@ gda_postgres_provider_supports_feature (GdaServerProvider *provider, GdaConnecti
* The recommended method is to create GdaDataHandler objects only when they are needed and to keep a reference to them
* for further usage, using the gda_server_provider_handler_declare() method.
*
- * The implementation shown here does not define any specific data handler, but there should be some for at least
+ * The implementation shown here does not define any specific data handler, but there should be some for at least
* binary and time related types.
*/
static GdaDataHandler *
@@ -1593,7 +1593,7 @@ gda_postgres_provider_create_parser (GdaServerProvider *provider, GdaConnection
/*
* GdaStatement to SQL request
- *
+ *
* This method renders a #GdaStatement into its SQL representation.
*
* The implementation show here simply calls gda_statement_to_sql_extended() but the rendering
@@ -1640,7 +1640,7 @@ gda_postgres_provider_statement_prepare (GdaServerProvider *provider, GdaConnect
/* get private connection data */
cdata = (PostgresConnectionData*) gda_connection_internal_get_provider_data (cnc);
- if (!cdata)
+ if (!cdata)
return FALSE;
/* render as SQL understood by PostgreSQL */
@@ -1698,7 +1698,7 @@ gda_postgres_provider_statement_prepare (GdaServerProvider *provider, GdaConnect
gda_pstmt_set_gda_statement (_GDA_PSTMT (ps), stmt);
_GDA_PSTMT (ps)->param_ids = param_ids;
_GDA_PSTMT (ps)->sql = sql;
-
+
gda_connection_add_prepared_statement (cnc, stmt, (GdaPStmt *) ps);
g_object_unref (ps);
@@ -1730,7 +1730,7 @@ check_transaction_started (GdaConnection *cnc, gboolean *out_started)
}
/*
- * Creates a "simple" prepared statement which has no variable, but does not call
+ * Creates a "simple" prepared statement which has no variable, but does not call
* gda_connection_add_prepared_statement()
*/
static GdaPostgresPStmt *
@@ -1859,7 +1859,7 @@ make_last_inserted_set (GdaConnection *cnc, GdaStatement *stmt, Oid last_id)
return NULL;
}
else if (nrows > 1) {
- g_warning (_("SELECT statement to get last inserted row returned too many (%d) rows"),
+ g_warning (_("SELECT statement to get last inserted row returned too many (%d) rows"),
nrows);
return NULL;
}
@@ -1905,7 +1905,7 @@ make_last_inserted_set (GdaConnection *cnc, GdaStatement *stmt, Oid last_id)
* - all the *param_values
* - param_values
* - param_mem
- *
+ *
*/
static void
params_freev (gchar **param_values, gboolean *param_mem, gint size)
@@ -1936,9 +1936,9 @@ params_freev (gchar **param_values, gboolean *param_mem, gint size)
static GObject *
gda_postgres_provider_statement_execute (GdaServerProvider *provider, GdaConnection *cnc,
GdaStatement *stmt, GdaSet *params,
- GdaStatementModelUsage model_usage,
- GType *col_types, GdaSet **last_inserted_row,
- guint *task_id,
+ GdaStatementModelUsage model_usage,
+ GType *col_types, GdaSet **last_inserted_row,
+ guint *task_id,
GdaServerProviderExecCallback async_cb, gpointer cb_data, GError **error)
{
GdaPostgresPStmt *ps;
@@ -1968,11 +1968,11 @@ gda_postgres_provider_statement_execute (GdaServerProvider *provider, GdaConnect
*last_inserted_row = NULL;
cdata = (PostgresConnectionData*) gda_connection_internal_get_provider_data (cnc);
- if (!cdata)
+ if (!cdata)
return NULL;
- /*
- * execute prepared statement using C API: CURSOR based
+ /*
+ * execute prepared statement using C API: CURSOR based
*/
if (!(model_usage & GDA_STATEMENT_MODEL_RANDOM_ACCESS) &&
(gda_statement_get_statement_type (stmt) == GDA_SQL_STATEMENT_SELECT)) {
@@ -2013,7 +2013,7 @@ gda_postgres_provider_statement_execute (GdaServerProvider *provider, GdaConnect
return NULL;
}
PQclear (pg_res);
-
+
/* create data model in CURSOR mode */
recset = gda_postgres_recordset_new_cursor (cnc, ps, params, cursor_name, col_types);
gda_connection_internal_statement_executed (cnc, stmt, params, NULL); /* required: help @cnc keep some stats */
@@ -2054,7 +2054,7 @@ gda_postgres_provider_statement_execute (GdaServerProvider *provider, GdaConnect
gboolean *param_mem = NULL;
gint nb_params;
gboolean transaction_started = FALSE;
-
+
nb_params = g_slist_length (_GDA_PSTMT (ps)->param_ids);
param_values = g_new0 (char *, nb_params);
param_lengths = g_new0 (int, nb_params);
@@ -2064,7 +2064,7 @@ gda_postgres_provider_statement_execute (GdaServerProvider *provider, GdaConnect
for (i = 0, list = _GDA_PSTMT (ps)->param_ids; list; list = list->next, i++) {
const gchar *pname = (gchar *) list->data;
GdaHolder *h = NULL;
-
+
/* find requested parameter */
if (!params) {
event = gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR);
@@ -2128,7 +2128,7 @@ gda_postgres_provider_statement_execute (GdaServerProvider *provider, GdaConnect
/* specific BLOB treatment */
GdaBlob *blob = (GdaBlob*) gda_value_get_blob ((GValue *) value);
GdaPostgresBlobOp *op;
-
+
/* Postgres requires that a transaction be started for LOB operations */
if (!check_transaction_started (cnc, &transaction_started)) {
event = gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR);
@@ -2137,10 +2137,10 @@ gda_postgres_provider_statement_execute (GdaServerProvider *provider, GdaConnect
"%s", _("Cannot start transaction"));
break;
}
-
+
/* create GdaBlobOp */
op = (GdaPostgresBlobOp *) gda_postgres_blob_op_new (cnc);
-
+
/* always create a new blob as there is no way to truncate an existing blob */
if (gda_postgres_blob_op_declare_blob (op) &&
gda_blob_op_write ((GdaBlobOp*) op, blob, 0))
@@ -2157,12 +2157,12 @@ gda_postgres_provider_statement_execute (GdaServerProvider *provider, GdaConnect
param_formats [i] = 1; /* binary format */
param_mem [i] = TRUE; /* don't free later */
}
- else if ((G_VALUE_TYPE (value) == G_TYPE_DATE) ||
+ else if ((G_VALUE_TYPE (value) == G_TYPE_DATE) ||
(G_VALUE_TYPE (value) == GDA_TYPE_TIMESTAMP) ||
(G_VALUE_TYPE (value) == GDA_TYPE_TIME)) {
GdaHandlerTime *timdh;
-
- timdh = GDA_HANDLER_TIME (gda_server_provider_get_data_handler_g_type (provider, cnc,
+
+ timdh = GDA_HANDLER_TIME (gda_server_provider_get_data_handler_g_type (provider, cnc,
G_VALUE_TYPE (value)));
g_assert (timdh);
param_values [i] = gda_handler_time_get_no_locale_str_from_value (timdh, value);
@@ -2177,7 +2177,7 @@ gda_postgres_provider_statement_execute (GdaServerProvider *provider, GdaConnect
param_values [i] = NULL;
}
}
-
+
if (event) {
gda_connection_add_event (cnc, event);
params_freev (param_values, param_mem, nb_params);
@@ -2187,7 +2187,7 @@ gda_postgres_provider_statement_execute (GdaServerProvider *provider, GdaConnect
gda_connection_rollback_transaction (cnc, NULL, NULL);
return NULL;
}
-
+
/* add a connection event for the execution */
event = gda_connection_event_new (GDA_CONNECTION_EVENT_COMMAND);
gda_connection_event_set_description (event, _GDA_PSTMT (ps)->sql);
@@ -2225,7 +2225,7 @@ gda_postgres_provider_statement_execute (GdaServerProvider *provider, GdaConnect
g_free (param_lengths);
g_free (param_formats);
- if (!pg_res)
+ if (!pg_res)
event = _gda_postgres_make_error (cnc, cdata->pconn, NULL, error);
else {
int status;
@@ -2236,7 +2236,7 @@ gda_postgres_provider_statement_execute (GdaServerProvider *provider, GdaConnect
if (status == PGRES_COMMAND_OK) {
gchar *str;
GdaConnectionEvent *event;
-
+
event = gda_connection_event_new (GDA_CONNECTION_EVENT_NOTICE);
str = g_strdup (PQcmdStatus (pg_res));
gda_connection_event_set_description (event, str);
@@ -2244,8 +2244,8 @@ gda_postgres_provider_statement_execute (GdaServerProvider *provider, GdaConnect
gda_connection_add_event (cnc, event);
retval = (GObject *) gda_set_new_inline (1, "IMPACTED_ROWS", G_TYPE_INT,
atoi (PQcmdTuples (pg_res)));
-
- if ((PQoidValue (pg_res) != InvalidOid) && last_inserted_row)
+
+ if ((PQoidValue (pg_res) != InvalidOid) && last_inserted_row)
*last_inserted_row = make_last_inserted_set (cnc, stmt, PQoidValue (pg_res));
PQclear (pg_res);
@@ -2260,12 +2260,12 @@ gda_postgres_provider_statement_execute (GdaServerProvider *provider, GdaConnect
retval = (GObject *) gda_data_model_array_new (0);
}
}
- else
+ else
event = _gda_postgres_make_error (cnc, cdata->pconn, NULL, error);
}
gda_connection_internal_statement_executed (cnc, stmt, params, NULL); /* required: help @cnc keep some stats */
- if (transaction_started)
+ if (transaction_started)
gda_connection_commit_transaction (cnc, NULL, NULL);
return retval;
@@ -2275,14 +2275,14 @@ gda_postgres_provider_statement_execute (GdaServerProvider *provider, GdaConnect
* starts a distributed transaction: put the XA transaction in the ACTIVE state
*/
static gboolean
-gda_postgres_provider_xa_start (GdaServerProvider *provider, GdaConnection *cnc,
+gda_postgres_provider_xa_start (GdaServerProvider *provider, GdaConnection *cnc,
const GdaXaTransactionId *xid, GError **error)
{
g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
g_return_val_if_fail (xid, FALSE);
- return gda_postgres_provider_begin_transaction (provider, cnc, NULL,
+ return gda_postgres_provider_begin_transaction (provider, cnc, NULL,
GDA_TRANSACTION_ISOLATION_READ_COMMITTED, error);
}
@@ -2291,7 +2291,7 @@ gda_postgres_provider_xa_start (GdaServerProvider *provider, GdaConnection *cnc,
* This state is required by some database providers before actually going to the PREPARED state
*/
static gboolean
-gda_postgres_provider_xa_end (GdaServerProvider *provider, GdaConnection *cnc,
+gda_postgres_provider_xa_end (GdaServerProvider *provider, GdaConnection *cnc,
const GdaXaTransactionId *xid, GError **error)
{
g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
@@ -2306,7 +2306,7 @@ gda_postgres_provider_xa_end (GdaServerProvider *provider, GdaConnection *cnc,
* prepares the distributed transaction: put the XA transaction in the PREPARED state
*/
static gboolean
-gda_postgres_provider_xa_prepare (GdaServerProvider *provider, GdaConnection *cnc,
+gda_postgres_provider_xa_prepare (GdaServerProvider *provider, GdaConnection *cnc,
const GdaXaTransactionId *xid, GError **error)
{
GdaSet *params;
@@ -2328,7 +2328,7 @@ gda_postgres_provider_xa_prepare (GdaServerProvider *provider, GdaConnection *cn
return FALSE;
}
g_free (str);
- affected = gda_connection_statement_execute_non_select (cnc, internal_stmt [I_STMT_XA_PREPARE], params,
+ affected = gda_connection_statement_execute_non_select (cnc, internal_stmt [I_STMT_XA_PREPARE], params,
NULL, error);
g_object_unref (params);
if (affected == -1)
@@ -2342,7 +2342,7 @@ gda_postgres_provider_xa_prepare (GdaServerProvider *provider, GdaConnection *cn
* terminates the XA transaction
*/
static gboolean
-gda_postgres_provider_xa_commit (GdaServerProvider *provider, GdaConnection *cnc,
+gda_postgres_provider_xa_commit (GdaServerProvider *provider, GdaConnection *cnc,
const GdaXaTransactionId *xid, GError **error)
{
GdaSet *params;
@@ -2364,7 +2364,7 @@ gda_postgres_provider_xa_commit (GdaServerProvider *provider, GdaConnection *cnc
return FALSE;
}
g_free (str);
- affected = gda_connection_statement_execute_non_select (cnc, internal_stmt [I_STMT_XA_COMMIT], params,
+ affected = gda_connection_statement_execute_non_select (cnc, internal_stmt [I_STMT_XA_COMMIT], params,
NULL, error);
g_object_unref (params);
if (affected == -1)
@@ -2377,7 +2377,7 @@ gda_postgres_provider_xa_commit (GdaServerProvider *provider, GdaConnection *cnc
* Rolls back an XA transaction, possible only if in the ACTIVE, IDLE or PREPARED state
*/
static gboolean
-gda_postgres_provider_xa_rollback (GdaServerProvider *provider, GdaConnection *cnc,
+gda_postgres_provider_xa_rollback (GdaServerProvider *provider, GdaConnection *cnc,
const GdaXaTransactionId *xid, GError **error)
{
GdaSet *params;
@@ -2399,7 +2399,7 @@ gda_postgres_provider_xa_rollback (GdaServerProvider *provider, GdaConnection *c
return FALSE;
}
g_free (str);
- affected = gda_connection_statement_execute_non_select (cnc, internal_stmt [I_STMT_XA_ROLLBACK], params,
+ affected = gda_connection_statement_execute_non_select (cnc, internal_stmt [I_STMT_XA_ROLLBACK], params,
NULL, error);
g_object_unref (params);
if (affected == -1)
@@ -2428,12 +2428,12 @@ gda_postgres_provider_xa_recover (GdaServerProvider *provider, GdaConnection *cn
else {
GList *list = NULL;
gint i, nrows;
-
+
nrows = gda_data_model_get_n_rows (model);
for (i = 0; i < nrows; i++) {
const GValue *cvalue = gda_data_model_get_value_at (model, 0, i, NULL);
if (cvalue && !gda_value_is_null (cvalue))
- list = g_list_prepend (list,
+ list = g_list_prepend (list,
gda_xa_transaction_string_to_id (g_value_get_string (cvalue)));
}
g_object_unref (model);
@@ -2492,10 +2492,78 @@ _sql_identifier_needs_quotes (const gchar *str)
return FALSE;
}
+/* Returns: @str */
+static gchar *
+pg_remove_quotes (gchar *str)
+{
+ glong total;
+ gchar *ptr;
+ glong offset = 0;
+ char delim;
+
+ if (!str)
+ return NULL;
+ delim = *str;
+ if ((delim != '\'') && (delim != '"'))
+ return str;
+
+
+ total = strlen (str);
+ if (str[total-1] == delim) {
+ /* string is correclty terminated */
+ g_memmove (str, str+1, total-2);
+ total -=2;
+ }
+ else {
+ /* string is _not_ correclty terminated */
+ g_memmove (str, str+1, total-1);
+ total -=1;
+ }
+ str[total] = 0;
+
+ ptr = (gchar *) str;
+ while (offset < total) {
+ /* we accept the "''" as a synonym of "\'" */
+ if (*ptr == delim) {
+ if (*(ptr+1) == delim) {
+ g_memmove (ptr+1, ptr+2, total - offset);
+ offset += 2;
+ }
+ else {
+ *str = 0;
+ return str;
+ }
+ }
+ if (*ptr == '\\') {
+ if (*(ptr+1) == '\\') {
+ g_memmove (ptr+1, ptr+2, total - offset);
+ offset += 2;
+ }
+ else {
+ if (*(ptr+1) == delim) {
+ *ptr = delim;
+ g_memmove (ptr+1, ptr+2, total - offset);
+ offset += 2;
+ }
+ else {
+ *str = 0;
+ return str;
+ }
+ }
+ }
+ else
+ offset ++;
+
+ ptr++;
+ }
+
+ return str;
+}
+
static gchar *
gda_postgresql_identifier_quote (GdaServerProvider *provider, GdaConnection *cnc,
const gchar *id,
- gboolean meta_store_convention, gboolean force_quotes)
+ gboolean for_meta_store, gboolean force_quotes)
{
GdaSqlReservedKeywordsFunc kwfunc;
PostgresConnectionData *cdata = NULL;
@@ -2507,15 +2575,65 @@ gda_postgresql_identifier_quote (GdaServerProvider *provider, GdaConnection *cnc
}
kwfunc = _gda_postgres_get_reserved_keyword_func (cdata);
- if (*id == '"') {
- /* there are already some quotes */
+
+ if (for_meta_store) {
+ gchar *tmp, *ptr;
+ tmp = pg_remove_quotes (g_strdup (id));
+ if (kwfunc (tmp)) {
+ ptr = gda_sql_identifier_add_quotes (tmp);
+ g_free (tmp);
+ return ptr;
+ }
+ else if (force_quotes) {
+ /* quote if non LC characters or digits at the 1st char or non allowed characters */
+ for (ptr = tmp; *ptr; ptr++) {
+ if (((*ptr >= 'a') && (*ptr <= 'z')) ||
+ ((*ptr >= '0') && (*ptr <= '9') && (ptr != tmp)) ||
+ (*ptr == '_'))
+ continue;
+ else {
+ ptr = gda_sql_identifier_add_quotes (tmp);
+ g_free (tmp);
+ return ptr;
+ }
+ }
+ return tmp;
+ }
+ else {
+ for (ptr = tmp; *ptr; ptr++) {
+ if (*id == '"') {
+ if (((*ptr >= 'a') && (*ptr <= 'z')) ||
+ ((*ptr >= '0') && (*ptr <= '9') && (ptr != tmp)) ||
+ (*ptr == '_'))
+ continue;
+ else {
+ ptr = gda_sql_identifier_add_quotes (tmp);
+ g_free (tmp);
+ return ptr;
+ }
+ }
+ else if ((*ptr >= 'A') && (*ptr <= 'Z'))
+ *ptr += 'a' - 'A';
+ else if ((*ptr >= '0') && (*ptr <= '9') && (ptr == tmp)) {
+ ptr = gda_sql_identifier_add_quotes (tmp);
+ g_free (tmp);
+ return ptr;
+ }
+ }
+ return tmp;
+ }
+ }
+ else {
+ if (*id == '"') {
+ /* there are already some quotes */
+ return g_strdup (id);
+ }
+ if (kwfunc (id) || _sql_identifier_needs_quotes (id) || force_quotes)
+ return identifier_add_quotes (id);
+
+ /* nothing to do */
return g_strdup (id);
}
- if (kwfunc (id) || _sql_identifier_needs_quotes (id) || force_quotes)
- return identifier_add_quotes (id);
-
- /* nothing to do */
- return g_strdup (id);
}
@@ -2528,7 +2646,7 @@ gda_postgres_free_cnc_data (PostgresConnectionData *cdata)
if (!cdata)
return;
- if (cdata->pconn)
+ if (cdata->pconn)
PQfinish (cdata->pconn);
if (cdata->type_data) {
@@ -2540,10 +2658,10 @@ gda_postgres_free_cnc_data (PostgresConnectionData *cdata)
}
g_free (cdata->type_data);
}
-
+
if (cdata->h_table)
g_hash_table_destroy (cdata->h_table);
-
+
g_free (cdata->version);
g_free (cdata->short_version);
g_free (cdata->avoid_types_oids);
diff --git a/tests/test-identifiers-quotes.c b/tests/test-identifiers-quotes.c
index 3e5078b..79f6792 100644
--- a/tests/test-identifiers-quotes.c
+++ b/tests/test-identifiers-quotes.c
@@ -23,123 +23,129 @@
#include <libgda/libgda.h>
typedef struct {
- gchar *sql_identifier;
gchar *provider;
- gboolean meta_store_convention;
- gboolean force_quotes;
- gchar *expected_result;
+ gchar *sql_identifier;
+ gchar *result1; /* for_meta_store=>FALSE force_quotes=>FALSE */
+ gchar *result2; /* for_meta_store=>TRUE force_quotes=>FALSE */
+ gchar *result3; /* for_meta_store=>FALSE force_quotes=>TRUE */
+ gchar *result4; /* for_meta_store=>TRUE force_quotes=>TRUE */
} ATest;
ATest tests[] = {
- /* generic SQL */
- {"\"Solution\"", NULL, FALSE, FALSE, "\"Solution\""},
- {"\"Solution\"", NULL, FALSE, TRUE, "\"Solution\""},
- {"\"solution\"", NULL, FALSE, FALSE, "\"solution\""},
- {"\"solution\"", NULL, FALSE, TRUE, "\"solution\""},
- {"solution", NULL, FALSE, FALSE, "solution"},
- {"solution", NULL, FALSE, TRUE, "\"solution\""},
- {"solution", NULL, TRUE, FALSE, "solution"},
- {"solution", NULL, TRUE, TRUE, "\"solution\""},
-
- {"SOLUTION", NULL, FALSE, TRUE, "\"SOLUTION\""},
- {"SOLUTION", NULL, FALSE, FALSE, "SOLUTION"},
-
- {"Solution", NULL, FALSE, FALSE, "Solution"}, /* mixed case */
- {"Solution", NULL, FALSE, TRUE, "\"Solution\""},
-
- {"5olution", NULL, FALSE, FALSE, "\"5olution\""}, /* test 1st digit */
- {"5olution", NULL, FALSE, TRUE, "\"5olution\""},
- {"5olution", NULL, TRUE, FALSE, "\"5olution\""}, /* this should not happen, but just in case */
- {"5olution", NULL, TRUE, TRUE, "\"5olution\""}, /* this should not happen, but just in case */
-
- {"$solu_t#ion", NULL, FALSE, FALSE, "$solu_t#ion"}, /* other allowed characters */
- {"$solu_t#ion", NULL, FALSE, TRUE, "\"$solu_t#ion\""},
- {"$solu_t#ion", NULL, TRUE, FALSE, "$solu_t#ion"},
- {"$solu_t#ion", NULL, TRUE, TRUE, "\"$solu_t#ion\""},
-
- {"solu tion", NULL, FALSE, FALSE, "\"solu tion\""}, /* non allowed characters */
- {"solu tion", NULL, FALSE, TRUE, "\"solu tion\""},
- {"solu tion", NULL, TRUE, FALSE, "\"solu tion\""},
- {"solu tion", NULL, TRUE, TRUE, "\"solu tion\""},
-
- {"select", NULL, FALSE, FALSE, "\"select\""}, /* SQL reserved keyword */
- {"select", NULL, FALSE, TRUE, "\"select\""},
- {"select", NULL, TRUE, FALSE, "\"select\""},
- {"select", NULL, TRUE, TRUE, "\"select\""},
-
- /* MySQL specific */
- {"`Solution`", "MySQL", FALSE, FALSE, "`Solution`"},
- {"`Solution`", "MySQL", FALSE, TRUE, "`Solution`"},
- {"`solution`", "MySQL", FALSE, FALSE, "`solution`"},
- {"`solution`", "MySQL", FALSE, TRUE, "`solution`"},
- {"solution", "MySQL", FALSE, FALSE, "solution"},
- {"solution", "MySQL", FALSE, TRUE, "`solution`"},
- {"solution", "MySQL", TRUE, FALSE, "solution"},
- {"solution", "MySQL", TRUE, TRUE, "`solution`"},
-
- {"SOLUTION", "MySQL", FALSE, TRUE, "`SOLUTION`"},
- {"SOLUTION", "MySQL", FALSE, FALSE, "SOLUTION"},
-
- {"Solution", "MySQL", FALSE, FALSE, "Solution"}, /* mixed case */
- {"Solution", "MySQL", FALSE, TRUE, "`Solution`"},
-
- {"5olution", "MySQL", FALSE, FALSE, "`5olution`"}, /* test 1st digit */
- {"5olution", "MySQL", FALSE, TRUE, "`5olution`"},
- {"5olution", "MySQL", TRUE, FALSE, "`5olution`"}, /* this should not happen, but just in case */
- {"5olution", "MySQL", TRUE, TRUE, "`5olution`"}, /* this should not happen, but just in case */
-
- {"$solu_t#ion", "MySQL", FALSE, FALSE, "$solu_t#ion"}, /* other allowed characters */
- {"$solu_t#ion", "MySQL", FALSE, TRUE, "`$solu_t#ion`"},
- {"$solu_t#ion", "MySQL", TRUE, FALSE, "$solu_t#ion"},
- {"$solu_t#ion", "MySQL", TRUE, TRUE, "`$solu_t#ion`"},
-
- {"solu tion", "MySQL", FALSE, FALSE, "`solu tion`"}, /* non allowed characters */
- {"solu tion", "MySQL", FALSE, TRUE, "`solu tion`"},
- {"solu tion", "MySQL", TRUE, FALSE, "`solu tion`"},
- {"solu tion", "MySQL", TRUE, TRUE, "`solu tion`"},
-
- {"select", "MySQL", FALSE, FALSE, "`select`"}, /* SQL reserved keyword */
- {"select", "MySQL", FALSE, TRUE, "`select`"},
- {"select", "MySQL", TRUE, FALSE, "`select`"},
- {"select", "MySQL", TRUE, TRUE, "`select`"},
-
- /* PostgreSQL specific */
- {"\"Solution\"", "PostgreSQL", FALSE, FALSE, "\"Solution\""},
- {"\"Solution\"", "PostgreSQL", FALSE, TRUE, "\"Solution\""},
- {"\"solution\"", "PostgreSQL", FALSE, FALSE, "\"solution\""},
- {"\"solution\"", "PostgreSQL", FALSE, TRUE, "\"solution\""},
- {"solution", "PostgreSQL", FALSE, FALSE, "solution"},
- {"solution", "PostgreSQL", FALSE, TRUE, "\"solution\""},
- {"solution", "PostgreSQL", TRUE, FALSE, "solution"},
- {"solution", "PostgreSQL", TRUE, TRUE, "\"solution\""},
-
- {"SOLUTION", "PostgreSQL", FALSE, TRUE, "\"SOLUTION\""},
- {"SOLUTION", "PostgreSQL", FALSE, FALSE, "SOLUTION"},
-
- {"Solution", "PostgreSQL", FALSE, FALSE, "Solution"}, /* mixed case */
- {"Solution", "PostgreSQL", FALSE, TRUE, "\"Solution\""},
-
- {"5olution", "PostgreSQL", FALSE, FALSE, "\"5olution\""}, /* test 1st digit */
- {"5olution", "PostgreSQL", FALSE, TRUE, "\"5olution\""},
- {"5olution", "PostgreSQL", TRUE, FALSE, "\"5olution\""}, /* this should not happen, but just in case */
- {"5olution", "PostgreSQL", TRUE, TRUE, "\"5olution\""}, /* this should not happen, but just in case */
-
- {"$solu_t#ion", "PostgreSQL", FALSE, FALSE, "$solu_t#ion"}, /* other allowed characters */
- {"$solu_t#ion", "PostgreSQL", FALSE, TRUE, "\"$solu_t#ion\""},
- {"$solu_t#ion", "PostgreSQL", TRUE, FALSE, "$solu_t#ion"},
- {"$solu_t#ion", "PostgreSQL", TRUE, TRUE, "\"$solu_t#ion\""},
-
- {"solu tion", "PostgreSQL", FALSE, FALSE, "\"solu tion\""}, /* non allowed characters */
- {"solu tion", "PostgreSQL", FALSE, TRUE, "\"solu tion\""},
- {"solu tion", "PostgreSQL", TRUE, FALSE, "\"solu tion\""},
- {"solu tion", "PostgreSQL", TRUE, TRUE, "\"solu tion\""},
-
- {"select", "PostgreSQL", FALSE, FALSE, "\"select\""}, /* SQL reserved keyword */
- {"select", "PostgreSQL", FALSE, TRUE, "\"select\""},
- {"select", "PostgreSQL", TRUE, FALSE, "\"select\""},
- {"select", "PostgreSQL", TRUE, TRUE, "\"select\""},
+ /* generic SQL rules */
+ {NULL, "\"double word\"", "\"double word\"", "\"double word\"", "\"double word\"", "\"double word\""},
+ {NULL, "\"CapitalTest\"", "\"CapitalTest\"", "\"CapitalTest\"", "\"CapitalTest\"", "\"CapitalTest\""},
+ {NULL, "CapitalTest", "CapitalTest", "capitaltest", "\"CapitalTest\"", "\"CapitalTest\""},
+ {NULL, "\"mytable\"", "\"mytable\"", "mytable", "\"mytable\"", "mytable"},
+ {NULL, "mytable", "mytable", "mytable", "\"mytable\"", "mytable"},
+ {NULL, "MYTABLE", "MYTABLE", "mytable", "\"MYTABLE\"", "\"MYTABLE\""},
+ {NULL, "\"MYTABLE\"", "\"MYTABLE\"", "\"MYTABLE\"", "\"MYTABLE\"", "\"MYTABLE\""},
+ {NULL, "desc", "\"desc\"", "\"desc\"", "\"desc\"", "\"desc\""},
+ {NULL, "\"desc\"", "\"desc\"", "\"desc\"", "\"desc\"", "\"desc\""},
+ {NULL, "5ive", "\"5ive\"", "\"5ive\"", "\"5ive\"", "\"5ive\""},
+ {NULL, "\"5ive\"", "\"5ive\"", "\"5ive\"", "\"5ive\"", "\"5ive\""},
+
+ {"PostgreSQL", "\"double word\"", "\"double word\"", "\"double word\"", "\"double word\"", "\"double word\""},
+ {"PostgreSQL", "\"CapitalTest\"", "\"CapitalTest\"", "\"CapitalTest\"", "\"CapitalTest\"", "\"CapitalTest\""},
+ {"PostgreSQL", "CapitalTest", "CapitalTest", "capitaltest", "\"CapitalTest\"", "\"CapitalTest\""},
+ {"PostgreSQL", "\"mytable\"", "\"mytable\"", "mytable", "\"mytable\"", "mytable"},
+ {"PostgreSQL", "mytable", "mytable", "mytable", "\"mytable\"", "mytable"},
+ {"PostgreSQL", "MYTABLE", "MYTABLE", "mytable", "\"MYTABLE\"", "\"MYTABLE\""},
+ {"PostgreSQL", "\"MYTABLE\"", "\"MYTABLE\"", "\"MYTABLE\"", "\"MYTABLE\"", "\"MYTABLE\""},
+ {"PostgreSQL", "desc", "\"desc\"", "\"desc\"", "\"desc\"", "\"desc\""},
+ {"PostgreSQL", "5ive", "\"5ive\"", "\"5ive\"", "\"5ive\"", "\"5ive\""},
+ {"PostgreSQL", "\"5ive\"", "\"5ive\"", "\"5ive\"", "\"5ive\"", "\"5ive\""},
+
+ /* case insensitive MySQL */
+ {"iMySQL", "\"double word\"", "`double word`", "\"double word\"", "`double word`", "\"double word\""},
+ {"iMySQL", "\"CapitalTest\"", "`CapitalTest`", "capitaltest", "`CapitalTest`", "capitaltest"},
+ {"iMySQL", "`CapitalTest`", "`CapitalTest`", "capitaltest", "`CapitalTest`", "capitaltest"},
+ {"iMySQL", "CapitalTest", "CapitalTest", "capitaltest", "`CapitalTest`", "capitaltest"},
+ {"iMySQL", "\"mytable\"", "`mytable`", "mytable", "`mytable`", "mytable"},
+ {"iMySQL", "`mytable`", "`mytable`", "mytable", "`mytable`", "mytable"},
+ {"iMySQL", "mytable", "mytable", "mytable", "`mytable`", "mytable"},
+ {"iMySQL", "MYTABLE", "MYTABLE", "mytable", "`MYTABLE`", "mytable"},
+ {"iMySQL", "\"MYTABLE\"", "`MYTABLE`", "mytable", "`MYTABLE`", "mytable"},
+ {"iMySQL", "`MYTABLE`", "`MYTABLE`", "mytable", "`MYTABLE`", "mytable"},
+ {"iMySQL", "desc", "`desc`", "\"desc\"", "`desc`", "\"desc\""},
+ {"iMySQL", "`desc`", "`desc`", "\"desc\"", "`desc`", "\"desc\""},
+ {"iMySQL", "5ive", "`5ive`", "\"5ive\"", "`5ive`", "\"5ive\""},
+ {"iMySQL", "\"5ive\"", "`5ive`", "\"5ive\"", "`5ive`", "\"5ive\""},
+ {"iMySQL", "`5ive`", "`5ive`", "\"5ive\"", "`5ive`", "\"5ive\""},
+
+ /* case sensitive MySQL */
+ {"sMySQL", "\"double word\"", "`double word`", "\"double word\"", "`double word`", "\"double word\""},
+ {"sMySQL", "\"CapitalTest\"", "`CapitalTest`", "\"CapitalTest\"", "`CapitalTest`", "\"CapitalTest\""},
+ {"sMySQL", "`CapitalTest`", "`CapitalTest`", "\"CapitalTest\"", "`CapitalTest`", "\"CapitalTest\""},
+ {"sMySQL", "CapitalTest", "`CapitalTest`", "\"CapitalTest\"", "`CapitalTest`", "\"CapitalTest\""},
+ {"sMySQL", "\"mytable\"", "`mytable`", "mytable", "`mytable`", "mytable"},
+ {"sMySQL", "`mytable`", "`mytable`", "mytable", "`mytable`", "mytable"},
+ {"sMySQL", "mytable", "`mytable`", "mytable", "`mytable`", "mytable"},
+ {"sMySQL", "MYTABLE", "`MYTABLE`", "\"MYTABLE\"", "`MYTABLE`", "\"MYTABLE\""},
+ {"sMySQL", "\"MYTABLE\"", "`MYTABLE`", "\"MYTABLE\"", "`MYTABLE`", "\"MYTABLE\""},
+ {"sMySQL", "`MYTABLE`", "`MYTABLE`", "\"MYTABLE\"", "`MYTABLE`", "\"MYTABLE\""},
+ {"sMySQL", "desc", "`desc`", "\"desc\"", "`desc`", "\"desc\""},
+ {"sMySQL", "`desc`", "`desc`", "\"desc\"", "`desc`", "\"desc\""},
+ {"sMySQL", "5ive", "`5ive`", "\"5ive\"", "`5ive`", "\"5ive\""},
+ {"sMySQL", "\"5ive\"", "`5ive`", "\"5ive\"", "`5ive`", "\"5ive\""},
+ {"sMySQL", "`5ive`", "`5ive`", "\"5ive\"", "`5ive`", "\"5ive\""},
+
+ {"SQLite", "\"double word\"", "\"double word\"", "\"double word\"", "\"double word\"", "\"double word\""},
+ {"SQLite", "[double word]", "\"double word\"", "\"double word\"", "\"double word\"", "\"double word\""},
+ {"SQLite", "\"CapitalTest\"", "\"CapitalTest\"", "capitaltest", "\"CapitalTest\"", "capitaltest"},
+ {"SQLite", "`CapitalTest`", "\"CapitalTest\"", "capitaltest", "\"CapitalTest\"", "capitaltest"},
+ {"SQLite", "[CapitalTest]", "\"CapitalTest\"", "capitaltest", "\"CapitalTest\"", "capitaltest"},
+ {"SQLite", "CapitalTest", "CapitalTest", "capitaltest", "\"CapitalTest\"", "capitaltest"},
+ {"SQLite", "\"mytable\"", "\"mytable\"", "mytable", "\"mytable\"", "mytable"},
+ {"SQLite", "[mytable]", "\"mytable\"", "mytable", "\"mytable\"", "mytable"},
+ {"SQLite", "`mytable`", "\"mytable\"", "mytable", "\"mytable\"", "mytable"},
+ {"SQLite", "mytable", "mytable", "mytable", "\"mytable\"", "mytable"},
+ {"SQLite", "MYTABLE", "MYTABLE", "mytable", "\"MYTABLE\"", "mytable"},
+ {"SQLite", "\"MYTABLE\"", "\"MYTABLE\"", "mytable", "\"MYTABLE\"", "mytable"},
+ {"SQLite", "[MYTABLE]", "\"MYTABLE\"", "mytable", "\"MYTABLE\"", "mytable"},
+ {"SQLite", "`MYTABLE`", "\"MYTABLE\"", "mytable", "\"MYTABLE\"", "mytable"},
+ {"SQLite", "desc", "\"desc\"", "\"desc\"", "\"desc\"", "\"desc\""},
+ {"SQLite", "[desc]", "\"desc\"", "\"desc\"", "\"desc\"", "\"desc\""},
+ {"SQLite", "`desc`", "\"desc\"", "\"desc\"", "\"desc\"", "\"desc\""},
+ {"SQLite", "5ive", "\"5ive\"", "\"5ive\"", "\"5ive\"", "\"5ive\""},
+ {"SQLite", "\"5ive\"", "\"5ive\"", "\"5ive\"", "\"5ive\"", "\"5ive\""},
+ {"SQLite", "[5ive]", "\"5ive\"", "\"5ive\"", "\"5ive\"", "\"5ive\""},
+ {"SQLite", "`5ive`", "\"5ive\"", "\"5ive\"", "\"5ive\"", "\"5ive\""},
+
};
+static gboolean
+check_result (ATest *test, const gchar *result, const gchar *expected, gboolean for_meta_store, gboolean force_quotes)
+{
+ gchar *str = NULL;
+ if (!result) {
+ if (expected)
+ str = g_strdup_printf ("Failed for %s: result is NULL when %s was expected\n",
+ test->sql_identifier,
+ expected);
+ }
+ else {
+ if (!expected)
+ str = g_strdup_printf ("Failed for %s: result is %s when NULL was expected\n",
+ test->sql_identifier,
+ result);
+ else if (strcmp (result, expected))
+ str = g_strdup_printf ("Failed for %s: result is %s when %s was expected\n",
+ test->sql_identifier,
+ result, expected);
+ }
+
+ if (str) {
+ g_print ("\tTEST failed, (provider %s%s%s): %s\n", test->provider,
+ for_meta_store ? " for Meta store" : "",
+ force_quotes ? " force quotes" : "", str);
+ g_free (str);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
int
main (int argc, char** argv)
{
@@ -149,49 +155,43 @@ main (int argc, char** argv)
ATest *test = &(tests [i]);
gchar *result;
GdaServerProvider *prov = NULL;
- gboolean fail = FALSE;
+
if (test->provider) {
- prov = gda_config_get_provider (test->provider, NULL);
+ if ((*test->provider == 'i') || (*test->provider == 's'))
+ prov = gda_config_get_provider (test->provider + 1, NULL);
+ else
+ prov = gda_config_get_provider (test->provider, NULL);
if (!prov) {
g_print ("Can't find provider for %s, ignoring test\n", test->provider);
continue;
}
+ if (*test->provider == 'i')
+ g_object_set (G_OBJECT (prov), "identifiers-case-sensitive", FALSE, NULL);
+ else if (*test->provider == 's')
+ g_object_set (G_OBJECT (prov), "identifiers-case-sensitive", TRUE, NULL);
}
- result = gda_sql_identifier_quote (test->sql_identifier, NULL, prov, test->meta_store_convention,
- test->force_quotes);
- if (!result) {
- if (test->expected_result) {
- g_print ("Failed for %s: result is NULL when %s was expected\n",
- test->sql_identifier,
- test->expected_result);
- fail = TRUE;
- }
- }
- else {
- if (!test->expected_result) {
- g_print ("Failed for %s: result is %s when NULL was expected\n",
- test->sql_identifier,
- result);
- fail = TRUE;
- }
- else if (strcmp (result, test->expected_result)) {
- g_print ("Failed for %s: result is %s when %s was expected\n",
- test->sql_identifier,
- result, test->expected_result);
- fail = TRUE;
- }
- g_free (result);
- }
+ result = gda_sql_identifier_quote (test->sql_identifier, NULL, prov, FALSE, FALSE);
+ if (!check_result (test, result, test->result1, FALSE, FALSE))
+ nfailed++;
+ g_free (result);
- if (fail) {
- g_print ("\tprovider: %s\n", test->provider);
- g_print ("\tmeta store convention: %s\n", test->meta_store_convention ? "Yes" : "No");
- g_print ("\tforce quotes: %s\n", test->force_quotes ? "Yes" : "No");
+ result = gda_sql_identifier_quote (test->sql_identifier, NULL, prov, TRUE, FALSE);
+ if (!check_result (test, result, test->result2, TRUE, FALSE))
nfailed++;
- }
+ g_free (result);
+
+ result = gda_sql_identifier_quote (test->sql_identifier, NULL, prov, FALSE, TRUE);
+ if (!check_result (test, result, test->result3, FALSE, TRUE))
+ nfailed++;
+ g_free (result);
+
+ result = gda_sql_identifier_quote (test->sql_identifier, NULL, prov, TRUE, TRUE);
+ if (!check_result (test, result, test->result4, TRUE, TRUE))
+ nfailed++;
+ g_free (result);
}
- g_print ("%d tests executed, ", i);
+ g_print ("%d tests executed, ", i * 4);
if (nfailed > 0)
g_print ("%d failed\n", nfailed);
else
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]