libgda r3333 - in trunk: . doc/C doc/C/tmpl libgda libgda/sql-parser providers/mysql
- From: vivien svn gnome org
- To: svn-commits-list gnome org
- Subject: libgda r3333 - in trunk: . doc/C doc/C/tmpl libgda libgda/sql-parser providers/mysql
- Date: Tue, 24 Feb 2009 21:28:19 +0000 (UTC)
Author: vivien
Date: Tue Feb 24 21:28:19 2009
New Revision: 3333
URL: http://svn.gnome.org/viewvc/libgda?rev=3333&view=rev
Log:
2009-02-24 Vivien Malerba <malerba gnome-db org>
* libgda/sql-parser/gda-statement-struct.c:
* doc/C: doc. improvements
* libgda/gda-meta-struct.c: misc corrections
* libgda/gda-data-proxy.c: made it thread safe
* libgda/libgda.symbols:
* libgda/gda-util.[ch]: added gda_sql_identifier_split()
* providers/mysql/*: more MySQL provider work:
- remove double quotes around tables names when rendering SQL
- make sure the connection uses UTF-8
- corrected the handling of NULL values in GdaMysqlRecordset
- removed compilation warnings
- improved meta data retreival
- bug fixes
Modified:
trunk/ChangeLog
trunk/doc/C/libgda-4.0-sections.txt
trunk/doc/C/tmpl/gda-data-proxy.sgml
trunk/doc/C/tmpl/gda-sql-parser.sgml
trunk/doc/C/tmpl/provider-support.sgml
trunk/libgda/gda-data-proxy.c
trunk/libgda/gda-meta-struct.c
trunk/libgda/gda-util.c
trunk/libgda/gda-util.h
trunk/libgda/libgda.symbols
trunk/libgda/sql-parser/gda-statement-struct.c
trunk/providers/mysql/gda-mysql-meta.c
trunk/providers/mysql/gda-mysql-provider.c
trunk/providers/mysql/gda-mysql-recordset.c
trunk/providers/mysql/gda-mysql-util.c
trunk/providers/mysql/gda-mysql.h
Modified: trunk/doc/C/libgda-4.0-sections.txt
==============================================================================
--- trunk/doc/C/libgda-4.0-sections.txt (original)
+++ trunk/doc/C/libgda-4.0-sections.txt Tue Feb 24 21:28:19 2009
@@ -1111,6 +1111,7 @@
gda_sql_identifier_needs_quotes
gda_sql_identifier_add_quotes
gda_sql_identifier_remove_quotes
+gda_sql_identifier_split
<SUBSECTION Standard>
GDA_IS_SQL_PARSER
GDA_SQL_PARSER
@@ -1452,6 +1453,8 @@
gda_compute_dml_statements
gda_compute_select_statement_from_update
gda_compute_unique_table_row_condition
+<SUBSECTION>
+gda_sql_any_part_check_structure
</SECTION>
<SECTION>
Modified: trunk/doc/C/tmpl/gda-data-proxy.sgml
==============================================================================
--- trunk/doc/C/tmpl/gda-data-proxy.sgml (original)
+++ trunk/doc/C/tmpl/gda-data-proxy.sgml Tue Feb 24 21:28:19 2009
@@ -103,6 +103,11 @@
</itemizedlist>
</para>
+<para>
+ The #GdaDataProxy objects are thread safe, which means any proxy object can be used from
+ any thread at the same time as they implement their own locking mechanisms.
+</para>
+
<!-- ##### SECTION See_Also ##### -->
<para>
Modified: trunk/doc/C/tmpl/gda-sql-parser.sgml
==============================================================================
--- trunk/doc/C/tmpl/gda-sql-parser.sgml (original)
+++ trunk/doc/C/tmpl/gda-sql-parser.sgml Tue Feb 24 21:28:19 2009
@@ -205,3 +205,12 @@
@Returns:
+<!-- ##### FUNCTION gda_sql_identifier_split ##### -->
+<para>
+
+</para>
+
+ id:
+ Returns:
+
+
Modified: trunk/doc/C/tmpl/provider-support.sgml
==============================================================================
--- trunk/doc/C/tmpl/provider-support.sgml (original)
+++ trunk/doc/C/tmpl/provider-support.sgml Tue Feb 24 21:28:19 2009
@@ -386,3 +386,13 @@
@Returns:
+<!-- ##### FUNCTION gda_sql_any_part_check_structure ##### -->
+<para>
+
+</para>
+
+ node:
+ error:
+ Returns:
+
+
Modified: trunk/libgda/gda-data-proxy.c
==============================================================================
--- trunk/libgda/gda-data-proxy.c (original)
+++ trunk/libgda/gda-data-proxy.c Tue Feb 24 21:28:19 2009
@@ -40,6 +40,7 @@
#include <sql-parser/gda-statement-struct-util.h>
#include <libgda/gda-custom-marshal.h>
#include <libgda/gda-error.h>
+#include <gda-mutex.h>
/*
* Main static functions
@@ -189,6 +190,8 @@
*/
struct _GdaDataProxyPrivate
{
+ GdaMutex *mutex;
+
GdaDataModel *model; /* Gda model which is proxied */
GdaConnection *filter_vcnc; /* virtual connection used for filtering */
@@ -716,6 +719,9 @@
gda_data_proxy_init (GdaDataProxy *proxy)
{
proxy->priv = g_new0 (GdaDataProxyPrivate, 1);
+
+ proxy->priv->mutex = gda_mutex_new ();
+
proxy->priv->modify_rows = g_hash_table_new (NULL, NULL);
proxy->priv->notify_changes = TRUE;
@@ -851,8 +857,13 @@
g_return_if_fail (GDA_IS_DATA_PROXY (object));
proxy = GDA_DATA_PROXY (object);
- if (proxy->priv)
+ if (proxy->priv) {
clean_proxy (proxy);
+ if (proxy->priv->mutex) {
+ gda_mutex_free (proxy->priv->mutex);
+ proxy->priv->mutex = NULL;
+ }
+ }
/* parent class */
parent_class->dispose (object);
@@ -890,6 +901,7 @@
GdaDataModel *model;
gint col;
+ gda_mutex_lock (proxy->priv->mutex);
switch (param_id) {
case PROP_MODEL:
g_assert (!proxy->priv->model);
@@ -898,6 +910,7 @@
if (! (gda_data_model_get_access_flags (model) & GDA_DATA_MODEL_ACCESS_RANDOM)) {
g_warning (_("GdaDataProxy can't handle non random access data models"));
+ gda_mutex_unlock (proxy->priv->mutex);
return;
}
proxy->priv->model = model;
@@ -968,6 +981,7 @@
}
break;
}
+ gda_mutex_unlock (proxy->priv->mutex);
}
}
@@ -981,6 +995,7 @@
proxy = GDA_DATA_PROXY (object);
if (proxy->priv) {
+ gda_mutex_lock (proxy->priv->mutex);
switch (param_id) {
case PROP_ADD_NULL_ENTRY:
g_value_set_boolean (value, proxy->priv->add_null_entry);
@@ -992,6 +1007,7 @@
g_value_set_int (value, proxy->priv->sample_size);
break;
}
+ gda_mutex_unlock (proxy->priv->mutex);
}
}
@@ -1280,15 +1296,18 @@
g_return_val_if_fail (proxy->priv, NULL);
g_return_val_if_fail (proxy_row >= 0, NULL);
+ gda_mutex_lock (proxy->priv->mutex);
for (i = 0; i < n_cols; i++) {
value = gda_data_proxy_get_value_at ((GdaDataModel *) proxy, cols_index[i], proxy_row, NULL);
if (value)
retval = g_slist_prepend (retval, (GValue *) value);
else {
g_slist_free (retval);
+ gda_mutex_unlock (proxy->priv->mutex);
return NULL;
}
}
+ gda_mutex_unlock (proxy->priv->mutex);
return g_slist_reverse (retval);
}
@@ -1317,6 +1336,7 @@
g_return_val_if_fail (proxy->priv, 0);
g_return_val_if_fail (proxy_row >= 0, 0);
+ gda_mutex_lock (proxy->priv->mutex);
model_column = col % proxy->priv->model_nb_cols;
model_row = proxy_row_to_model_row (proxy, proxy_row);
flags = gda_data_model_get_attributes_at (proxy->priv->model, model_column, model_row);
@@ -1359,6 +1379,8 @@
flags |= GDA_VALUE_ATTR_DATA_NON_VALID;
}
+ gda_mutex_unlock (proxy->priv->mutex);
+
return flags;
}
@@ -1382,6 +1404,8 @@
g_return_if_fail (proxy->priv);
g_return_if_fail (proxy_row >= 0);
+ gda_mutex_lock (proxy->priv->mutex);
+
model_col = col % proxy->priv->model_nb_cols;
if (alter_flags & GDA_VALUE_ATTR_IS_NULL)
gda_data_proxy_set_value_at ((GdaDataModel*) proxy,
@@ -1435,6 +1459,8 @@
NULL);
}
}
+
+ gda_mutex_unlock (proxy->priv->mutex);
}
/**
@@ -1474,16 +1500,21 @@
g_return_if_fail (proxy->priv);
g_return_if_fail (proxy_row >= 0);
+ gda_mutex_lock (proxy->priv->mutex);
+
/* ensure that there is no sync to be done */
ensure_chunk_sync (proxy);
if (proxy->priv->add_null_entry && proxy_row == 0) {
g_warning (_("The first row is an empty row artificially prepended and cannot be removed"));
+ gda_mutex_unlock (proxy->priv->mutex);
return;
}
- if (! (gda_data_model_get_access_flags ((GdaDataModel*) proxy) & GDA_DATA_MODEL_ACCESS_DELETE))
+ if (! (gda_data_model_get_access_flags ((GdaDataModel*) proxy) & GDA_DATA_MODEL_ACCESS_DELETE)) {
+ gda_mutex_unlock (proxy->priv->mutex);
return;
+ }
abs_row = proxy_row_to_absolute_row (proxy, proxy_row);
model_row = absolute_row_to_model_row (proxy, abs_row, &rm);
@@ -1532,6 +1563,8 @@
gda_data_proxy_signals[ROW_DELETE_CHANGED],
0, proxy_row, TRUE);
}
+
+ gda_mutex_unlock (proxy->priv->mutex);
}
/**
@@ -1552,6 +1585,8 @@
g_return_if_fail (proxy->priv);
g_return_if_fail (proxy_row >= 0);
+ gda_mutex_lock (proxy->priv->mutex);
+
/* ensure that there is no sync to be done */
ensure_chunk_sync (proxy);
@@ -1577,6 +1612,8 @@
gda_data_proxy_signals[ROW_DELETE_CHANGED],
0, proxy_row, FALSE);
}
+
+ gda_mutex_unlock (proxy->priv->mutex);
}
/**
@@ -1737,6 +1774,8 @@
g_return_if_fail (proxy->priv);
g_return_if_fail (proxy_row >= 0);
+ gda_mutex_lock (proxy->priv->mutex);
+
/* ensure that there is no sync to be done */
ensure_chunk_sync (proxy);
@@ -1806,6 +1845,8 @@
}
else
g_warning ("GdaDataProxy column %d is not a modifiable data column", col);
+
+ gda_mutex_unlock (proxy->priv->mutex);
}
static gboolean commit_row_modif (GdaDataProxy *proxy, RowModif *rm, gboolean adjust_display, GError **error);
@@ -1844,6 +1885,9 @@
if (!rm)
return TRUE;
+
+ gda_mutex_lock (proxy->priv->mutex);
+
model_row = rm->model_row;
/* ensure that there is no sync to be done */
@@ -1866,6 +1910,7 @@
0, proxy_row, rm->model_row, &lerror);
if (lerror) {
g_propagate_error (error, lerror);
+ gda_mutex_unlock (proxy->priv->mutex);
return FALSE;
}
@@ -2021,6 +2066,8 @@
if (adjust_display)
adjust_displayed_chunk (proxy);
+ gda_mutex_unlock (proxy->priv->mutex);
+
return !err;
}
@@ -2122,6 +2169,8 @@
g_return_if_fail (GDA_IS_DATA_PROXY (proxy));
g_return_if_fail (proxy->priv);
+ gda_mutex_lock (proxy->priv->mutex);
+
/* ensure that there is no sync to be done */
ensure_chunk_sync (proxy);
@@ -2133,6 +2182,8 @@
gda_data_proxy_signals[SAMPLE_SIZE_CHANGED],
0, sample_size);
}
+
+ gda_mutex_unlock (proxy->priv->mutex);
}
/**
@@ -2166,6 +2217,8 @@
g_return_if_fail (proxy->priv);
g_return_if_fail (sample_start >= 0);
+ gda_mutex_lock (proxy->priv->mutex);
+
/* ensure that there is no sync to be done */
ensure_chunk_sync (proxy);
@@ -2173,6 +2226,8 @@
proxy->priv->sample_first_row = sample_start;
adjust_displayed_chunk (proxy);
}
+
+ gda_mutex_unlock (proxy->priv->mutex);
}
/**
@@ -2275,6 +2330,7 @@
static void
ensure_chunk_sync (GdaDataProxy *proxy)
{
+ gda_mutex_lock (proxy->priv->mutex);
if (proxy->priv->chunk_sync_idle_id) {
gboolean defer_sync = proxy->priv->defer_sync;
proxy->priv->defer_sync = FALSE;
@@ -2282,6 +2338,7 @@
chunk_sync_idle (proxy);
proxy->priv->defer_sync = defer_sync;
}
+ gda_mutex_unlock (proxy->priv->mutex);
}
/*
@@ -2292,6 +2349,7 @@
chunk_sync_idle (GdaDataProxy *proxy)
{
#define IDLE_STEP 50
+ gda_mutex_lock (proxy->priv->mutex);
gboolean finished = FALSE;
gint index;
@@ -2307,8 +2365,10 @@
max_steps = G_MAXINT;
}
- if (!proxy->priv->chunk_to)
+ if (!proxy->priv->chunk_to) {
+ gda_mutex_unlock (proxy->priv->mutex);
return FALSE; /* nothing to do */
+ }
max_steps = 0;
if (proxy->priv->chunk_proxy_nb_rows < 0)
@@ -2441,7 +2501,7 @@
else
g_print ("Sync. is NOT finished yet\n");
#endif
-
+ gda_mutex_unlock (proxy->priv->mutex);
return !finished;
}
@@ -2450,6 +2510,7 @@
{
DisplayChunk *ret_chunk = NULL;
+ gda_mutex_lock (proxy->priv->mutex);
if (proxy->priv->filtered_rows) {
/* REM: when there is a filter applied, the new rows are mixed with the
* existing ones => no need to treat them appart
@@ -2555,6 +2616,7 @@
}
}
+ gda_mutex_unlock (proxy->priv->mutex);
return ret_chunk;
}
@@ -2569,6 +2631,8 @@
{
g_return_if_fail (proxy->priv->model);
+ gda_mutex_lock (proxy->priv->mutex);
+
/*
* Stop idle adding of rows if necessary
*/
@@ -2583,8 +2647,10 @@
proxy->priv->chunk_to = NULL;
}
proxy->priv->chunk_to = compute_display_chunk (proxy);
- if (!proxy->priv->chunk_to)
+ if (!proxy->priv->chunk_to) {
+ gda_mutex_unlock (proxy->priv->mutex);
return; /* nothing to do */
+ }
/* determine if chunking has changed */
gboolean equal = FALSE;
@@ -2631,6 +2697,8 @@
proxy->priv->chunk_to = NULL;
}
}
+
+ gda_mutex_unlock (proxy->priv->mutex);
}
/**
@@ -2652,6 +2720,8 @@
g_return_val_if_fail (GDA_IS_DATA_PROXY (proxy), FALSE);
g_return_val_if_fail (proxy->priv, FALSE);
+ gda_mutex_lock (proxy->priv->mutex);
+
/* ensure that there is no sync to be done */
ensure_chunk_sync (proxy);
@@ -2663,6 +2733,8 @@
gda_data_model_send_hint (proxy->priv->model, GDA_DATA_MODEL_HINT_END_BATCH_UPDATE, NULL);
adjust_displayed_chunk (proxy);
+ gda_mutex_unlock (proxy->priv->mutex);
+
return allok;
}
@@ -2681,6 +2753,8 @@
g_return_val_if_fail (GDA_IS_DATA_PROXY (proxy), FALSE);
g_return_val_if_fail (proxy->priv, FALSE);
+ gda_mutex_lock (proxy->priv->mutex);
+
/* ensure that there is no sync to be done */
ensure_chunk_sync (proxy);
g_assert (!proxy->priv->chunk_to);
@@ -2744,6 +2818,8 @@
gda_data_model_row_updated ((GdaDataModel *) proxy, proxy_row);
}
+ gda_mutex_unlock (proxy->priv->mutex);
+
return TRUE;
}
@@ -2949,12 +3025,16 @@
g_return_val_if_fail (GDA_IS_DATA_PROXY (proxy), FALSE);
g_return_val_if_fail (proxy->priv, FALSE);
+ gda_mutex_lock (proxy->priv->mutex);
+
if (!filter_expr) {
if (proxy->priv->filter_stmt)
g_object_unref (proxy->priv->filter_stmt);
proxy->priv->filter_stmt = NULL;
- return apply_filter_statement (proxy, error);
+ gboolean retval = apply_filter_statement (proxy, error);
+ gda_mutex_unlock (proxy->priv->mutex);
+ return retval;
}
/* generate SQL with a special case if expression starts with "ORDER BY" */
@@ -2987,6 +3067,8 @@
if (stmt)
g_object_unref (stmt);
proxy->priv->force_direct_mapping = FALSE;
+
+ gda_mutex_unlock (proxy->priv->mutex);
return FALSE;
}
@@ -2994,7 +3076,9 @@
g_object_unref (proxy->priv->filter_stmt);
proxy->priv->filter_stmt = stmt;
- return apply_filter_statement (proxy, error);
+ gboolean retval = apply_filter_statement (proxy, error);
+ gda_mutex_unlock (proxy->priv->mutex);
+ return retval;
}
/**
@@ -3016,6 +3100,8 @@
g_return_val_if_fail (col >= 0, FALSE);
g_return_val_if_fail (col < gda_data_model_get_n_columns ((GdaDataModel*) proxy), FALSE);
+ gda_mutex_lock (proxy->priv->mutex);
+
if (proxy->priv->filter_stmt) {
GdaSqlStatement *sqlst;
GdaSqlStatementSelect *selst;
@@ -3085,6 +3171,8 @@
str = g_strdup_printf ("ORDER BY _%d", col + 1);
retval = gda_data_proxy_set_filter_expr (proxy, str, error);
}
+
+ gda_mutex_unlock (proxy->priv->mutex);
return retval;
}
@@ -3124,8 +3212,11 @@
if (! proxy->priv->filtered_rows)
return -1;
- else
- return gda_data_model_get_n_rows (proxy->priv->filtered_rows);
+ else {
+ gint n = gda_data_model_get_n_rows (proxy->priv->filtered_rows);
+ gda_mutex_unlock (proxy->priv->mutex);
+ return n;
+ }
}
/*
@@ -3140,6 +3231,8 @@
proxy = GDA_DATA_PROXY (model);
g_return_val_if_fail (proxy->priv, -1);
+ gda_mutex_lock (proxy->priv->mutex);
+
if (proxy->priv->chunk && !proxy->priv->force_direct_mapping)
nbrows = proxy->priv->chunk->mapping->len;
else {
@@ -3157,6 +3250,8 @@
if (!proxy->priv->force_direct_mapping && proxy->priv->add_null_entry)
nbrows += 1;
+ gda_mutex_unlock (proxy->priv->mutex);
+
return nbrows;
}
@@ -3223,8 +3318,10 @@
proxy = GDA_DATA_PROXY (model);
g_return_val_if_fail (proxy->priv, NULL);
+ gda_mutex_lock (proxy->priv->mutex);
if (!proxy->priv->columns)
create_columns (proxy);
+ gda_mutex_unlock (proxy->priv->mutex);
return proxy->priv->columns [col];
}
@@ -3241,9 +3338,12 @@
g_return_val_if_fail (proxy->priv, NULL);
g_return_val_if_fail (proxy_row >= 0, NULL);
+ gda_mutex_lock (proxy->priv->mutex);
+
if ((proxy_row == 0) && proxy->priv->add_null_entry) {
if (!null_value)
null_value = gda_value_new_null ();
+ gda_mutex_unlock (proxy->priv->mutex);
return null_value;
}
@@ -3293,6 +3393,7 @@
}
}
+ gda_mutex_unlock (proxy->priv->mutex);
return retval;
}
@@ -3324,21 +3425,32 @@
retval = NULL;
}
}
+
+ gda_mutex_unlock (proxy->priv->mutex);
return retval;
}
g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_COLUMN_OUT_OF_RANGE_ERROR,
_("Column %d out of range (0-%d)"), column, 2 *proxy->priv->model_nb_cols - 1);
+
+ gda_mutex_unlock (proxy->priv->mutex);
return NULL;
}
static GdaValueAttribute
gda_data_proxy_get_attributes_at (GdaDataModel *model, gint col, gint row)
{
+ GdaValueAttribute attrs;
+ GdaDataProxy *proxy;
+
g_return_val_if_fail (GDA_IS_DATA_PROXY (model), FALSE);
- g_return_val_if_fail (((GdaDataProxy *) model)->priv, FALSE);
+ proxy = (GdaDataProxy*) model;
+ g_return_val_if_fail (proxy->priv, FALSE);
- return gda_data_proxy_get_value_attributes ((GdaDataProxy *) model, row, col);
+ gda_mutex_lock (proxy->priv->mutex);
+ attrs = gda_data_proxy_get_value_attributes ((GdaDataProxy *) model, row, col);
+ gda_mutex_unlock (proxy->priv->mutex);
+ return attrs;
}
static gint
@@ -3354,6 +3466,8 @@
g_return_val_if_fail (proxy->priv, FALSE);
g_return_val_if_fail (values, FALSE);
+ gda_mutex_lock (proxy->priv->mutex);
+
/* ensure that there is no sync to be done */
ensure_chunk_sync (proxy);
@@ -3400,6 +3514,7 @@
}
}
+ gda_mutex_unlock (proxy->priv->mutex);
return found ? proxy_row : -1;
}
@@ -3414,6 +3529,8 @@
proxy = GDA_DATA_PROXY (model);
g_return_val_if_fail (proxy->priv, FALSE);
+ gda_mutex_lock (proxy->priv->mutex);
+
iter = gda_data_model_create_iter (proxy->priv->model);
g_object_set (G_OBJECT (iter), "forced-model", proxy, NULL);
@@ -3432,6 +3549,7 @@
g_slist_length (GDA_SET (iter2)->holders));
g_object_unref (iter2);
}
+ gda_mutex_unlock (proxy->priv->mutex);
return iter;
}
@@ -3444,8 +3562,13 @@
proxy = GDA_DATA_PROXY (model);
g_return_val_if_fail (proxy->priv, 0);
- if (proxy->priv->model)
- return gda_data_model_get_access_flags (proxy->priv->model) | GDA_DATA_MODEL_ACCESS_RANDOM;
+ if (proxy->priv->model) {
+ GdaDataModelAccessFlags flags;
+ gda_mutex_lock (proxy->priv->mutex);
+ flags = gda_data_model_get_access_flags (proxy->priv->model) | GDA_DATA_MODEL_ACCESS_RANDOM;
+ gda_mutex_unlock (proxy->priv->mutex);
+ return flags;
+ }
else
return 0;
}
@@ -3462,12 +3585,15 @@
g_return_val_if_fail (proxy_row >= 0, FALSE);
g_return_val_if_fail (value, FALSE);
+ gda_mutex_lock (proxy->priv->mutex);
+
/* ensure that there is no sync to be done */
ensure_chunk_sync (proxy);
if ((proxy_row == 0) && proxy->priv->add_null_entry) {
g_set_error (error, GDA_DATA_PROXY_ERROR, GDA_DATA_PROXY_READ_ONLY_ROW,
"%s", _("The first row is an empty row artificially prepended and cannot be altered"));
+ gda_mutex_unlock (proxy->priv->mutex);
return FALSE;
}
@@ -3480,10 +3606,13 @@
/* compare with the current stored value */
cmp_value = gda_data_proxy_get_value_at ((GdaDataModel *) proxy, col, proxy_row, error);
- if (!cmp_value)
+ if (!cmp_value) {
+ gda_mutex_unlock (proxy->priv->mutex);
return FALSE;
+ }
if (! gda_value_compare ((GValue *) value, (GValue *) cmp_value)) {
/* nothing to do: values are equal */
+ gda_mutex_unlock (proxy->priv->mutex);
return TRUE;
}
@@ -3563,9 +3692,11 @@
else {
g_set_error (error, GDA_DATA_PROXY_ERROR, GDA_DATA_PROXY_READ_ONLY_VALUE,
_("Trying to change read-only column: %d"), col);
+ gda_mutex_unlock (proxy->priv->mutex);
return FALSE;
}
+ gda_mutex_unlock (proxy->priv->mutex);
return TRUE;
}
@@ -3611,6 +3742,8 @@
if (err)
return FALSE;
+ gda_mutex_lock (proxy->priv->mutex);
+
/* temporary disable changes notification */
notify_changes = proxy->priv->notify_changes;
proxy->priv->notify_changes = FALSE;
@@ -3628,6 +3761,7 @@
/* at least one successfull value change occurred */
gda_data_model_row_updated (model, row);
+ gda_mutex_unlock (proxy->priv->mutex);
return !err;
}
@@ -3642,6 +3776,8 @@
proxy = GDA_DATA_PROXY (model);
g_return_val_if_fail (proxy->priv, -1);
+ gda_mutex_lock (proxy->priv->mutex);
+
/* ensure that there is no sync to be done */
ensure_chunk_sync (proxy);
@@ -3653,12 +3789,14 @@
if (! gda_data_proxy_set_values (model, newrow, (GList *) values, error)) {
gda_data_proxy_remove_row (model, newrow, NULL);
proxy->priv->notify_changes = notify_changes;
+ gda_mutex_unlock (proxy->priv->mutex);
return -1;
}
else {
proxy->priv->notify_changes = notify_changes;
if (proxy->priv->notify_changes)
gda_data_model_row_inserted (model, newrow);
+ gda_mutex_unlock (proxy->priv->mutex);
return newrow;
}
}
@@ -3667,11 +3805,15 @@
gda_data_proxy_append_row (GdaDataModel *model, GError **error)
{
GdaDataProxy *proxy;
+ gint i;
g_return_val_if_fail (GDA_IS_DATA_PROXY (model), -1);
proxy = GDA_DATA_PROXY (model);
g_return_val_if_fail (proxy->priv, -1);
- return gda_data_proxy_append (proxy);
+ gda_mutex_lock (proxy->priv->mutex);
+ i = gda_data_proxy_append (proxy);
+ gda_mutex_unlock (proxy->priv->mutex);
+ return i;
}
static gboolean
@@ -3682,13 +3824,17 @@
proxy = GDA_DATA_PROXY (model);
g_return_val_if_fail (proxy->priv, FALSE);
+ gda_mutex_lock (proxy->priv->mutex);
+
if (proxy->priv->add_null_entry && row == 0) {
g_set_error (error, GDA_DATA_PROXY_ERROR, GDA_DATA_PROXY_READ_ONLY_ROW,
"%s", _("The first row is an empty row artificially prepended and cannot be removed"));
+ gda_mutex_unlock (proxy->priv->mutex);
return FALSE;
}
gda_data_proxy_delete (proxy, row);
+ gda_mutex_unlock (proxy->priv->mutex);
return TRUE;
}
@@ -3700,7 +3846,9 @@
proxy = GDA_DATA_PROXY (model);
g_return_if_fail (proxy->priv);
+ gda_mutex_lock (proxy->priv->mutex);
proxy->priv->notify_changes = do_notify_changes;
+ gda_mutex_unlock (proxy->priv->mutex);
}
static gboolean
Modified: trunk/libgda/gda-meta-struct.c
==============================================================================
--- trunk/libgda/gda-meta-struct.c (original)
+++ trunk/libgda/gda-meta-struct.c Tue Feb 24 21:28:19 2009
@@ -1094,7 +1094,7 @@
"ORDER BY table_schema, table_name";
const gchar *sql2 = "SELECT table_short_name, table_full_name, table_owner, table_name "
"FROM _tables WHERE table_catalog = ##cat::string AND table_schema = ##schema::string "
- "AND table_type='VIEW' "
+ "AND table_type LIKE '%VIEW%' "
"ORDER BY table_schema, table_name";
/* schema is known, catalog unknown */
@@ -1102,7 +1102,7 @@
"FROM _tables WHERE table_schema = ##schema::string AND table_type LIKE '%TABLE%' "
"ORDER BY table_schema, table_name";
const gchar *sql4 = "SELECT table_short_name, table_full_name, table_owner, table_name, table_catalog, table_schema "
- "FROM _tables WHERE table_schema = ##schema::string AND table_type='VIEW' "
+ "FROM _tables WHERE table_schema = ##schema::string AND table_type LIKE '%VIEW%' "
"ORDER BY table_schema, table_name";
/* schema and catalog are unknown */
@@ -1110,7 +1110,7 @@
"FROM _tables WHERE table_type LIKE '%TABLE%' "
"ORDER BY table_schema, table_name";
const gchar *sql6 = "SELECT table_short_name, table_full_name, table_owner, table_name, table_catalog, table_schema "
- "FROM _tables WHERE table_type='VIEW' "
+ "FROM _tables WHERE table_type LIKE '%VIEW%' "
"ORDER BY table_schema, table_name";
g_return_val_if_fail (GDA_IS_META_STRUCT (mstruct), FALSE);
@@ -1380,11 +1380,24 @@
static gint
db_object_sort_func (GdaMetaDbObject *dbo1, GdaMetaDbObject *dbo2)
{
- gint retval;
- retval = strcmp (dbo1->obj_schema, dbo2->obj_schema);
- if (retval)
- return retval;
- return strcmp (dbo1->obj_name, dbo2->obj_name);
+ gint retval = 0;
+ if (dbo1->obj_schema && dbo2->obj_schema) {
+ retval = strcmp (dbo1->obj_schema, dbo2->obj_schema);
+ if (retval)
+ return retval;
+ }
+ else if (dbo1->obj_schema)
+ return 1;
+ else if (dbo2->obj_schema)
+ return -1;
+
+ if (dbo1->obj_name && dbo2->obj_name)
+ return strcmp (dbo1->obj_name, dbo2->obj_name);
+ else if (dbo1->obj_name)
+ return 1;
+ else if (dbo2->obj_name)
+ return -1;
+ return 0;
}
/**
Modified: trunk/libgda/gda-util.c
==============================================================================
--- trunk/libgda/gda-util.c (original)
+++ trunk/libgda/gda-util.c Tue Feb 24 21:28:19 2009
@@ -1520,6 +1520,41 @@
return str;
}
+/**
+ * gda_sql_identifier_split
+ * @id: an SQL identifier
+ *
+ * Splits @id into an array of it sub parts. @id's format has to be "<part>[.<part>[...]]" where
+ * each part is either a text surrounded by double quotes which can contain upper and lower cases or
+ * an SQL identifier in lower case.
+ *
+ * For example the <![CDATA["test.\"ATable\""]]> string will result in the array: <![CDATA[{"test", "\"ATable\"", NULL}]]>
+ *
+ * Returns: a new array of strings, or NULL (use g_strfreev() to free the returned array)
+ */
+gchar **
+gda_sql_identifier_split (const gchar *id)
+{
+ gchar *copy;
+ gchar *remain, *last;
+ GArray *array = NULL;
+
+ g_return_val_if_fail (id && *id, NULL);
+
+ for (copy = g_strdup (id); copy; copy = remain) {
+ if (_split_identifier_string (copy, &remain, &last)) {
+ if (!array)
+ array = g_array_new (TRUE, TRUE, sizeof (gchar *));
+ g_array_prepend_val (array, last);
+ }
+ }
+
+ if (array)
+ return (gchar **) g_array_free (array, FALSE);
+ else
+ return NULL;
+}
+
/*
* RFC 1738 defines that these characters should be escaped, as well
* any non-US-ASCII character or anything between 0x00 - 0x1F.
Modified: trunk/libgda/gda-util.h
==============================================================================
--- trunk/libgda/gda-util.h (original)
+++ trunk/libgda/gda-util.h Tue Feb 24 21:28:19 2009
@@ -47,6 +47,7 @@
guint gda_identifier_hash (const gchar *id);
gboolean gda_identifier_equal (const gchar *id1, const gchar *id2);
gchar **gda_completion_list_get (GdaConnection *cnc, const gchar *sql, gint start, gint end);
+gchar **gda_sql_identifier_split (const gchar *id);
/*
* Param & model utilities
Modified: trunk/libgda/libgda.symbols
==============================================================================
--- trunk/libgda/libgda.symbols (original)
+++ trunk/libgda/libgda.symbols Tue Feb 24 21:28:19 2009
@@ -574,6 +574,7 @@
gda_sql_identifier_add_quotes
gda_sql_identifier_needs_quotes
gda_sql_identifier_remove_quotes
+ gda_sql_identifier_split
gda_sqlite_handler_bin_get_type
gda_sqlite_handler_bin_new
gda_sqlite_provider_get_type
Modified: trunk/libgda/sql-parser/gda-statement-struct.c
==============================================================================
--- trunk/libgda/sql-parser/gda-statement-struct.c (original)
+++ trunk/libgda/sql-parser/gda-statement-struct.c Tue Feb 24 21:28:19 2009
@@ -873,6 +873,17 @@
return gda_sql_any_part_check_structure (node, error);
}
+/**
+ * gda_sql_any_part_check_structure
+ * @node: a #GdaSqlAnyPart pointer
+ * @error: a place to store errors, or %NULL
+ *
+ * Checks for any error in @node's structure to make sure it is valid. This
+ * is the same as gda_sql_statement_check_structure() but for individual #GdaSqlAnyPart
+ * parts. This function is mainly for database provider's implementations
+ *
+ * Returns: TRUE if no error occurred
+ */
gboolean
gda_sql_any_part_check_structure (GdaSqlAnyPart *node, GError **error)
{
Modified: trunk/providers/mysql/gda-mysql-meta.c
==============================================================================
--- trunk/providers/mysql/gda-mysql-meta.c (original)
+++ trunk/providers/mysql/gda-mysql-meta.c Tue Feb 24 21:28:19 2009
@@ -51,7 +51,6 @@
I_STMT_TABLES,
I_STMT_TABLES_ALL,
I_STMT_TABLE_NAMED,
- I_STMT_VIEWS,
I_STMT_VIEWS_ALL,
I_STMT_VIEW_NAMED,
I_STMT_COLUMNS_OF_TABLE,
@@ -111,22 +110,19 @@
"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, table_type, CASE table_type WHEN 'BASE TABLE' THEN TRUE ELSE FALSE END AS table_type, table_comment, table_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 table_catalog = ##cat::string AND schema_name = ##schema::string",
/* I_STMT_TABLES_ALL */
- "SELECT IFNULL(table_catalog, table_schema) AS table_catalog, table_schema, table_name, table_type, 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",
+ "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, table_type, 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",
-
- /* I_STMT_VIEWS */
- "SELECT IFNULL(table_catalog, table_schema) AS table_catalog, table_schema, table_name, view_definition, check_option, is_updatable FROM INFORMATION_SCHEMA.views ",
+ "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",
/* 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 ",
+ "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 schema_name = ##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 = ##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",
/* 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, extra, 1, column_comment FROM INFORMATION_SCHEMA.columns WHERE table_catalog = ##cat::string AND table_schema = ##schema::string AND table_name = ##name::string",
@@ -324,7 +320,7 @@
{ "YEAR DATA TYPE", "gint", "A year in two-digit or four-digit format. The default is four-digit format. In four-digit format, the allowable values are 1901 to 2155, and 0000. In two-digit format, the allowable values are 70 to 69, representing years from 1970 to 2069. MySQL displays YEAR values in YYYY format, but allows you to assign values to YEAR columns using either strings or numbers.", "" }
};
GdaDataModel *model;
- gboolean retval;
+ gboolean retval = TRUE;
model = gda_meta_store_create_modify_data_model (store, context->table_name);
if (model == NULL)
@@ -366,7 +362,7 @@
g_list_free (values);
}
- if (retval != 0)
+ if (retval)
retval = gda_meta_store_modify (store, context->table_name, model, NULL, error, NULL);
g_object_unref (G_OBJECT(model));
}
@@ -692,13 +688,15 @@
GdaMetaStore *store,
GdaMetaContext *context,
GError **error)
-{
- // TO_IMPLEMENT;
-
+{
GType col_types_tables[] = {
0, 0, 0, 0,
G_TYPE_BOOLEAN, G_TYPE_NONE
};
+ GType col_types_views[] = {
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_NONE
+ };
GdaDataModel *model_tables, *model_views;
gboolean retval;
/* Check correct mysql server version. */
@@ -716,7 +714,7 @@
GdaMetaContext copy = *context;
model_tables = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_TABLES_ALL], NULL,
- GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types_tables, error);
+ GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types_tables, error);
if (model_tables == NULL)
retval = FALSE;
else {
@@ -725,7 +723,8 @@
g_object_unref (G_OBJECT(model_tables));
}
- model_views = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_VIEWS_ALL], NULL, error);
+ model_views = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_VIEWS_ALL], NULL,
+ GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types_views, error);
if (model_views == NULL)
retval = FALSE;
else {
@@ -749,6 +748,14 @@
{
// TO_IMPLEMENT;
+ GType col_types_tables[] = {
+ 0, 0, 0, 0,
+ G_TYPE_BOOLEAN, G_TYPE_NONE
+ };
+ GType col_types_views[] = {
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_NONE
+ };
GdaDataModel *model_tables, *model_views;
gboolean retval;
/* Check correct mysql server version. */
@@ -771,7 +778,9 @@
if (! gda_holder_set_value (gda_set_get_holder (i_set, "schema"), table_schema, error))
return FALSE;
if (!table_name_n) {
- model_tables = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_TABLES], i_set, error);
+ model_tables = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_TABLES], i_set,
+ GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types_tables,
+ error);
if (model_tables == NULL)
retval = FALSE;
else {
@@ -779,7 +788,9 @@
g_object_unref (G_OBJECT(model_tables));
}
- model_views = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_VIEWS], i_set, error);
+ 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 {
@@ -790,7 +801,9 @@
} else {
if (! gda_holder_set_value (gda_set_get_holder (i_set, "name"), table_name_n, error))
return FALSE;
- model_tables = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_TABLE_NAMED], i_set, error);
+ model_tables = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_TABLE_NAMED], i_set,
+ GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types_tables,
+ error);
if (model_tables == NULL)
retval = FALSE;
else {
@@ -799,7 +812,9 @@
g_object_unref (G_OBJECT(model_tables));
}
- model_views = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_VIEW_NAMED], i_set, error);
+ model_views = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_VIEW_NAMED], i_set,
+ GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types_views,
+ error);
if (model_views == NULL)
retval = FALSE;
else {
@@ -956,7 +971,7 @@
G_TYPE_NONE
};
GdaDataModel *model, *proxy;
- gboolean retval;
+ gboolean retval = TRUE;
/* Check correct mysql server version. */
MysqlConnectionData *cdata;
cdata = (MysqlConnectionData *) gda_connection_internal_get_provider_data (cnc);
Modified: trunk/providers/mysql/gda-mysql-provider.c
==============================================================================
--- trunk/providers/mysql/gda-mysql-provider.c (original)
+++ trunk/providers/mysql/gda-mysql-provider.c Tue Feb 24 21:28:19 2009
@@ -557,12 +557,56 @@
return FALSE;
}
+ /* Set some attributes for the newly opened connection (encoding to UTF-8)*/
+ int res;
+ res = mysql_query (mysql, "SET NAMES 'utf8'");
+ if (res != 0) {
+ _gda_mysql_make_error (cnc, mysql, NULL, NULL);
+ return FALSE;
+ }
+
+ /* get case sensitiveness of tables */
+ res = mysql_query (mysql, "SHOW VARIABLES WHERE Variable_name = 'lower_case_table_names'");
+ if (res != 0) {
+ _gda_mysql_make_error (cnc, mysql, NULL, NULL);
+ return FALSE;
+ }
+
+ MYSQL_RES *mdata;
+ mdata = mysql_store_result (mysql);
+ if (!mdata) {
+ _gda_mysql_make_error (cnc, mysql, NULL, NULL);
+ return FALSE;
+ }
+
+ MYSQL_ROW mrow;
+ gboolean case_sensitive = FALSE;
+ mrow = mysql_fetch_row (mdata);
+ if (!mrow) {
+ _gda_mysql_make_error (cnc, mysql, NULL, NULL);
+ mysql_free_result (mdata);
+ return FALSE;
+ }
+ switch (atoi (mrow[1])) {
+ case 0:
+ case_sensitive = TRUE;
+ break;
+ case 1:
+ case 2:
+ break;
+ default:
+ g_warning ("Unknown 'lower_case_table_names' variable value: %s\n", mrow[1]);
+ }
+
+ mysql_free_result (mdata);
+
+
+
/* Create a new instance of the provider specific data associated to a connection (MysqlConnectionData),
* and set its contents */
MysqlConnectionData *cdata;
cdata = g_new0 (MysqlConnectionData, 1);
gda_connection_internal_set_provider_data (cnc, cdata, (GDestroyNotify) gda_mysql_free_cnc_data);
- // TO_IMPLEMENT; /* cdata->... = ... */
cdata->cnc = cnc;
cdata->mysql = mysql;
@@ -570,9 +614,7 @@
cdata->version_long = mysql_get_server_version (mysql);
cdata->version = get_mysql_version (mysql);
-
- /* Optionnally set some attributes for the newly opened connection (encoding to UTF-8 for example )*/
- // TO_IMPLEMENT;
+ cdata->tables_case_sensitive = case_sensitive;
return TRUE;
}
@@ -1114,20 +1156,95 @@
gda_mysql_provider_create_parser (GdaServerProvider *provider,
GdaConnection *cnc)
{
- // TO_IMPLEMENT;
return (GdaSqlParser *) g_object_new (GDA_TYPE_MYSQL_PARSER,
"tokenizer-flavour", GDA_SQL_PARSER_FLAVOUR_MYSQL,
NULL);
}
+static gchar *
+mysql_render_select_target (GdaSqlSelectTarget *target, GdaSqlRenderingContext *context, GError **error)
+{
+ GString *string;
+ gchar *str;
+
+ g_return_val_if_fail (target, NULL);
+ g_return_val_if_fail (GDA_SQL_ANY_PART (target)->type == GDA_SQL_ANY_SQL_SELECT_TARGET, NULL);
+
+ /* can't have: target->expr == NULL */
+ if (!gda_sql_any_part_check_structure (GDA_SQL_ANY_PART (target), error)) return NULL;
+
+ if (! target->expr->value || (G_VALUE_TYPE (target->expr->value) != G_TYPE_STRING)) {
+ str = context->render_expr (target->expr, context, NULL, NULL, error);
+ if (!str)
+ return NULL;
+ string = g_string_new (str);
+ }
+ else {
+ gchar **ids_array;
+ ids_array = gda_sql_identifier_split (g_value_get_string (target->expr->value));
+ if (!ids_array) {
+ g_set_error (error, GDA_SQL_ERROR, GDA_SQL_STRUCTURE_CONTENTS_ERROR,
+ "%s", _("Malformed expression in select target"));
+ return NULL;
+ }
+
+ gint i;
+ string = g_string_new ("");
+ for (i = 0; ids_array [i]; i++) {
+ if (*(ids_array [i]) == '"')
+ gda_sql_identifier_remove_quotes (ids_array [i]);
+ if (i != 0)
+ g_string_append_c (string, '.');
+ g_string_append (string, ids_array [i]);
+ }
+ g_strfreev (ids_array);
+ }
+
+ if (target->as)
+ g_string_append_printf (string, " AS %s", target->as);
+
+ str = string->str;
+ g_string_free (string, FALSE);
+ return str;
+}
+
+static gchar *
+mysql_render_table (GdaSqlTable *table, GdaSqlRenderingContext *context, GError **error)
+{
+ g_return_val_if_fail (table, NULL);
+ g_return_val_if_fail (GDA_SQL_ANY_PART (table)->type == GDA_SQL_ANY_SQL_TABLE, NULL);
+
+ /* can't have: table->table_name not a valid SQL identifier */
+ if (!gda_sql_any_part_check_structure (GDA_SQL_ANY_PART (table), error)) return NULL;
+
+ gchar **ids_array;
+ ids_array = gda_sql_identifier_split (table->table_name);
+ if (!ids_array) {
+ g_set_error (error, GDA_SQL_ERROR, GDA_SQL_STRUCTURE_CONTENTS_ERROR,
+ "%s", _("Malformed table name"));
+ return NULL;
+ }
+
+ gint i;
+ GString *string;
+ string = g_string_new ("");
+ for (i = 0; ids_array [i]; i++) {
+ if (*(ids_array [i]) == '"')
+ gda_sql_identifier_remove_quotes (ids_array [i]);
+ if (i != 0)
+ g_string_append_c (string, '.');
+ g_string_append (string, ids_array [i]);
+ }
+ g_strfreev (ids_array);
+ return g_string_free (string, FALSE);
+}
+
/*
* GdaStatement to SQL request
*
* This method renders a #GdaStatement into its SQL representation.
*
- * The implementation show here simply calls gda_statement_to_sql_extended() but the rendering
- * can be specialized to the database's SQL dialect, see the implementation of gda_statement_to_sql_extended()
- * and SQLite's specialized rendering for more details
+ * It is specialized to remove the double quotes around table names.
*/
static gchar *
gda_mysql_provider_statement_to_sql (GdaServerProvider *provider,
@@ -1138,13 +1255,36 @@
GSList **params_used,
GError **error)
{
- g_return_val_if_fail (GDA_IS_STATEMENT (stmt), NULL);
- if (cnc) {
- g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
- g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
- }
+ gchar *str;
+ GdaSqlRenderingContext context;
+
+ g_return_val_if_fail (GDA_IS_STATEMENT (stmt), NULL);
+ if (cnc) {
+ g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+ g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
+ }
- return gda_statement_to_sql_extended (stmt, cnc, params, flags, params_used, error);
+ memset (&context, 0, sizeof (context));
+ context.params = params;
+ context.flags = flags;
+ /* remove double quotes around table name */
+ context.render_select_target = (GdaSqlRenderingFunc) mysql_render_select_target;
+ context.render_table = (GdaSqlRenderingFunc) mysql_render_table;
+
+ str = gda_statement_to_sql_real (stmt, &context, error);
+
+ if (str) {
+ if (params_used)
+ *params_used = context.params_used;
+ else
+ g_slist_free (context.params_used);
+ }
+ else {
+ if (params_used)
+ *params_used = NULL;
+ g_slist_free (context.params_used);
+ }
+ return str;
}
/*
@@ -1184,16 +1324,14 @@
return FALSE;
GSList *used_set = NULL;
- gchar *sql = gda_mysql_provider_statement_to_sql
- (provider, cnc, stmt, set,
- GDA_STATEMENT_SQL_PARAMS_AS_UQMARK, &used_set, error);
+ gchar *sql = gda_mysql_provider_statement_to_sql (provider, cnc, stmt, set,
+ GDA_STATEMENT_SQL_PARAMS_AS_UQMARK, &used_set, error);
if (!sql)
goto cleanup;
if (mysql_stmt_prepare (cdata->mysql_stmt, sql, strlen (sql))) {
- GdaConnectionEvent *event = _gda_mysql_make_error
- (cdata->cnc, NULL, cdata->mysql_stmt, NULL);
+ _gda_mysql_make_error (cdata->cnc, NULL, cdata->mysql_stmt, error);
goto cleanup;
}
@@ -1253,8 +1391,7 @@
g_return_val_if_fail (sql != NULL, NULL);
if (mysql_stmt_prepare (cdata->mysql_stmt, sql, strlen (sql))) {
- GdaConnectionEvent *event = _gda_mysql_make_error
- (cdata->cnc, NULL, cdata->mysql_stmt, error);
+ _gda_mysql_make_error (cdata->cnc, NULL, cdata->mysql_stmt, error);
ps = NULL;
} else {
ps = gda_mysql_pstmt_new (cdata->cnc, cdata->mysql, cdata->mysql_stmt);
@@ -1512,8 +1649,7 @@
/* This is a re-prepare of the statement. The function mysql_stmt_prepare
* will handle this on the server side. */
if (mysql_stmt_prepare (cdata->mysql_stmt, sql_for_empty, strlen (sql_for_empty))) {
- GdaConnectionEvent *event = _gda_mysql_make_error
- (cdata->cnc, NULL, cdata->mysql_stmt, NULL);
+ _gda_mysql_make_error (cdata->cnc, NULL, cdata->mysql_stmt, error);
return NULL;
}
Modified: trunk/providers/mysql/gda-mysql-recordset.c
==============================================================================
--- trunk/providers/mysql/gda-mysql-recordset.c (original)
+++ trunk/providers/mysql/gda-mysql-recordset.c Tue Feb 24 21:28:19 2009
@@ -295,6 +295,88 @@
return type;
}
+static GType
+_gda_mysql_type_to_gda (MysqlConnectionData *cdata,
+ enum enum_field_types mysql_type)
+{
+ GType gtype = 0;
+ switch (mysql_type) {
+ case MYSQL_TYPE_TINY:
+ case MYSQL_TYPE_SHORT:
+ case MYSQL_TYPE_LONG:
+ case MYSQL_TYPE_INT24:
+ case MYSQL_TYPE_YEAR:
+ gtype = G_TYPE_INT;
+ break;
+ case MYSQL_TYPE_LONGLONG:
+ gtype = G_TYPE_LONG;
+ break;
+ case MYSQL_TYPE_FLOAT:
+ gtype = G_TYPE_FLOAT;
+ break;
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_NEWDECIMAL:
+ case MYSQL_TYPE_DOUBLE:
+ gtype = G_TYPE_DOUBLE;
+ break;
+ case MYSQL_TYPE_BIT:
+ case MYSQL_TYPE_BLOB:
+ gtype = GDA_TYPE_BLOB;
+ break;
+ case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_DATETIME:
+ gtype = GDA_TYPE_TIMESTAMP;
+ break;
+ case MYSQL_TYPE_DATE:
+ gtype = G_TYPE_DATE;
+ break;
+ case MYSQL_TYPE_TIME:
+ gtype = GDA_TYPE_TIME;
+ break;
+ case MYSQL_TYPE_NULL:
+ gtype = GDA_TYPE_NULL;
+ break;
+ case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_SET:
+ case MYSQL_TYPE_ENUM:
+ case MYSQL_TYPE_GEOMETRY:
+ default:
+ gtype = G_TYPE_STRING;
+ }
+
+ /* g_print ("%s: ", __func__); */
+ /* switch (mysql_type) { */
+ /* case MYSQL_TYPE_TINY: g_print ("MYSQL_TYPE_TINY"); break; */
+ /* case MYSQL_TYPE_SHORT: g_print ("MYSQL_TYPE_SHORT"); break; */
+ /* case MYSQL_TYPE_LONG: g_print ("MYSQL_TYPE_LONG"); break; */
+ /* case MYSQL_TYPE_INT24: g_print ("MYSQL_TYPE_INT24"); break; */
+ /* case MYSQL_TYPE_YEAR: g_print ("MYSQL_TYPE_YEAR"); break; */
+ /* case MYSQL_TYPE_LONGLONG: g_print ("MYSQL_TYPE_LONGLONG"); break; */
+ /* case MYSQL_TYPE_FLOAT: g_print ("MYSQL_TYPE_FLOAT"); break; */
+ /* case MYSQL_TYPE_DECIMAL: g_print ("MYSQL_TYPE_DECIMAL"); break; */
+ /* case MYSQL_TYPE_NEWDECIMAL: g_print ("MYSQL_TYPE_NEWDECIMAL"); break; */
+ /* case MYSQL_TYPE_DOUBLE: g_print ("MYSQL_TYPE_DOUBLE"); break; */
+ /* case MYSQL_TYPE_BIT: g_print ("MYSQL_TYPE_BIT"); break; */
+ /* case MYSQL_TYPE_BLOB: g_print ("MYSQL_TYPE_BLOB"); break; */
+ /* case MYSQL_TYPE_TIMESTAMP: g_print ("MYSQL_TYPE_TIMESTAMP"); break; */
+ /* case MYSQL_TYPE_DATETIME: g_print ("MYSQL_TYPE_DATETIME"); break; */
+ /* case MYSQL_TYPE_DATE: g_print ("MYSQL_TYPE_DATE"); break; */
+ /* case MYSQL_TYPE_TIME: g_print ("MYSQL_TYPE_TIME"); break; */
+ /* case MYSQL_TYPE_NULL: g_print ("MYSQL_TYPE_NULL"); break; */
+ /* case MYSQL_TYPE_STRING: g_print ("MYSQL_TYPE_STRING"); break; */
+ /* case MYSQL_TYPE_VAR_STRING: g_print ("MYSQL_TYPE_VAR_STRING"); break; */
+ /* case MYSQL_TYPE_SET: g_print ("MYSQL_TYPE_SET"); break; */
+ /* case MYSQL_TYPE_ENUM: g_print ("MYSQL_TYPE_ENUM"); break; */
+ /* case MYSQL_TYPE_GEOMETRY: g_print ("MYSQL_TYPE_GEOMETRY"); break; */
+ /* default: g_print ("UNKNOWN %d: MYSQL_TYPE_STRING", mysql_type); break; */
+ /* } */
+ /* g_print ("\n"); */
+
+ return gtype;
+}
+
+
/*
* the @ps struct is modified and transfered to the new data model created in
* this function
@@ -375,6 +457,8 @@
/* 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:
@@ -382,11 +466,9 @@
case MYSQL_TYPE_LONG:
case MYSQL_TYPE_YEAR:
mysql_bind_result[i].buffer = g_malloc0 (sizeof(int));
- mysql_bind_result[i].is_null = g_malloc0 (sizeof(my_bool));
break;
case MYSQL_TYPE_LONGLONG:
mysql_bind_result[i].buffer = g_malloc0 (sizeof(long long));
- mysql_bind_result[i].is_null = g_malloc0 (sizeof(my_bool));
break;
case MYSQL_TYPE_NULL:
break;
@@ -395,12 +477,10 @@
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_TIMESTAMP:
mysql_bind_result[i].buffer = g_malloc0 (sizeof(MYSQL_TIME));
- mysql_bind_result[i].is_null = g_malloc0 (sizeof(my_bool));
break;
case MYSQL_TYPE_FLOAT:
case MYSQL_TYPE_DOUBLE:
mysql_bind_result[i].buffer = g_malloc0 (sizeof(double));
- mysql_bind_result[i].is_null = g_malloc0 (sizeof(my_bool));
break;
case MYSQL_TYPE_STRING:
case MYSQL_TYPE_VAR_STRING:
@@ -478,7 +558,6 @@
return model->advertized_nrows;
}
-
static GdaRow *
new_row_from_mysql_stmt (GdaMysqlRecordset *imodel, gint rownum, GError **error)
{
@@ -502,7 +581,6 @@
GValue *value = gda_row_get_value (row, i);
GType type = ((GdaDataSelect *) imodel)->prep_stmt->types[i];
- gda_value_reset_with_type (value, type);
/*g_print ("%s: #%d : TYPE=%d, GTYPE=%s\n", __func__, i, mysql_bind_result[i].buffer_type, g_type_name (type));*/
@@ -511,10 +589,17 @@
long long longlongvalue = 0;
double doublevalue = 0.0;
MYSQL_TIME timevalue = { 0 };
- char *strvalue = NULL;
- my_bool is_null;
+ my_bool is_null = FALSE;
unsigned long length;
+ g_memmove (&is_null, mysql_bind_result[i].is_null, sizeof(my_bool));
+ if (is_null) {
+ gda_value_set_null (value);
+ continue;
+ }
+ else
+ gda_value_reset_with_type (value, type);
+
switch (mysql_bind_result[i].buffer_type) {
case MYSQL_TYPE_TINY:
case MYSQL_TYPE_SHORT:
@@ -522,7 +607,6 @@
case MYSQL_TYPE_LONG:
case MYSQL_TYPE_YEAR:
g_memmove (&intvalue, mysql_bind_result[i].buffer, sizeof(int));
- g_memmove (&is_null, mysql_bind_result[i].is_null, sizeof(my_bool));
if (type == G_TYPE_INT)
g_value_set_int (value, intvalue);
@@ -536,7 +620,7 @@
break;
case MYSQL_TYPE_LONGLONG:
g_memmove (&longlongvalue, mysql_bind_result[i].buffer, sizeof(long long));
- g_memmove (&is_null, mysql_bind_result[i].is_null, sizeof(my_bool));
+
if (type == G_TYPE_BOOLEAN)
g_value_set_boolean (value, longlongvalue ? TRUE : FALSE);
else if (type == G_TYPE_INT)
@@ -556,7 +640,6 @@
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_TIMESTAMP:
g_memmove (&timevalue, mysql_bind_result[i].buffer, sizeof(MYSQL_TIME));
- g_memmove (&is_null, mysql_bind_result[i].is_null, sizeof(my_bool));
if (type == GDA_TYPE_TIME) {
GdaTime time = {
@@ -585,7 +668,7 @@
};
gda_value_set_timestamp (value, ×tamp);
} else {
- g_warning (_("Type %s not mapped for value %d/%d/%d %d:%d:%d.%d"),
+ g_warning (_("Type %s not mapped for value %d/%d/%d %d:%d:%d.%lu"),
g_type_name (type), timevalue.year, timevalue.month,
timevalue.day, timevalue.hour, timevalue.minute,
timevalue.second, timevalue.second_part);
@@ -595,7 +678,6 @@
case MYSQL_TYPE_FLOAT:
case MYSQL_TYPE_DOUBLE:
g_memmove (&doublevalue, mysql_bind_result[i].buffer, sizeof(double));
- g_memmove (&is_null, mysql_bind_result[i].is_null, sizeof(my_bool));
setlocale (LC_NUMERIC, "C");
if (type == G_TYPE_FLOAT)
@@ -616,21 +698,26 @@
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_NEWDECIMAL:
- case MYSQL_TYPE_BIT:
+ case MYSQL_TYPE_BIT: {
+ char *strvalue = NULL;
g_memmove (&length, mysql_bind_result[i].length, sizeof(unsigned long));
- strvalue = length ? g_memdup (mysql_bind_result[i].buffer, length + 1) : NULL;
+ if (length > 0) {
+ strvalue = g_malloc (length + 1);
+ memcpy (strvalue, mysql_bind_result[i].buffer, length);
+ strvalue [length] = 0;
+ }
if (type == G_TYPE_STRING)
g_value_set_string (value, strvalue);
else if (type == GDA_TYPE_BINARY) {
GdaBinary binary = {
- .data = strvalue,
+ .data = (guchar*) strvalue,
.binary_length = length
};
gda_value_set_binary (value, &binary);
} else if (type == GDA_TYPE_BLOB) {
GdaBinary binary = {
- .data = strvalue,
+ .data = (guchar*) strvalue,
.binary_length = length
};
gda_value_set_binary (value, &binary);
@@ -638,18 +725,20 @@
setlocale (LC_NUMERIC, "C");
g_value_set_double (value, atof (strvalue));
setlocale (LC_NUMERIC, gda_numeric_locale);
+ } else if (type == G_TYPE_BOOLEAN) {
+ g_value_set_boolean (value, atoi (strvalue));
} else {
g_warning (_("Type %s not mapped for value %s"),
g_type_name (type), strvalue);
}
-
+ g_free (strvalue);
break;
+ }
default:
g_warning (_("Invalid column bind data type. %d\n"),
mysql_bind_result[i].buffer_type);
}
- g_free (strvalue);
}
return row;
}
@@ -774,7 +863,7 @@
gint rownum,
GError **error)
{
- GdaMysqlRecordset *imodel = (GdaMysqlRecordset*) model;
+ /*GdaMysqlRecordset *imodel = (GdaMysqlRecordset*) model;*/
TO_IMPLEMENT;
@@ -799,7 +888,7 @@
gint rownum,
GError **error)
{
- GdaMysqlRecordset *imodel = (GdaMysqlRecordset*) model;
+ /*GdaMysqlRecordset *imodel = (GdaMysqlRecordset*) model;*/
TO_IMPLEMENT;
Modified: trunk/providers/mysql/gda-mysql-util.c
==============================================================================
--- trunk/providers/mysql/gda-mysql-util.c (original)
+++ trunk/providers/mysql/gda-mysql-util.c Tue Feb 24 21:28:19 2009
@@ -78,84 +78,3 @@
return event_error;
}
-
-GType
-_gda_mysql_type_to_gda (MysqlConnectionData *cdata,
- enum enum_field_types mysql_type)
-{
- GType gtype = 0;
- switch (mysql_type) {
- case MYSQL_TYPE_TINY:
- case MYSQL_TYPE_SHORT:
- case MYSQL_TYPE_LONG:
- case MYSQL_TYPE_INT24:
- case MYSQL_TYPE_YEAR:
- gtype = G_TYPE_INT;
- break;
- case MYSQL_TYPE_LONGLONG:
- gtype = G_TYPE_LONG;
- break;
- case MYSQL_TYPE_FLOAT:
- gtype = G_TYPE_FLOAT;
- break;
- case MYSQL_TYPE_DECIMAL:
- case MYSQL_TYPE_NEWDECIMAL:
- case MYSQL_TYPE_DOUBLE:
- gtype = G_TYPE_DOUBLE;
- break;
- case MYSQL_TYPE_BIT:
- case MYSQL_TYPE_BLOB:
- gtype = GDA_TYPE_BLOB;
- break;
- case MYSQL_TYPE_TIMESTAMP:
- case MYSQL_TYPE_DATETIME:
- gtype = GDA_TYPE_TIMESTAMP;
- break;
- case MYSQL_TYPE_DATE:
- gtype = G_TYPE_DATE;
- break;
- case MYSQL_TYPE_TIME:
- gtype = GDA_TYPE_TIME;
- break;
- case MYSQL_TYPE_NULL:
- gtype = GDA_TYPE_NULL;
- break;
- case MYSQL_TYPE_STRING:
- case MYSQL_TYPE_VAR_STRING:
- case MYSQL_TYPE_SET:
- case MYSQL_TYPE_ENUM:
- case MYSQL_TYPE_GEOMETRY:
- default:
- gtype = G_TYPE_STRING;
- }
-
- /* g_print ("%s: ", __func__); */
- /* switch (mysql_type) { */
- /* case MYSQL_TYPE_TINY: g_print ("MYSQL_TYPE_TINY"); break; */
- /* case MYSQL_TYPE_SHORT: g_print ("MYSQL_TYPE_SHORT"); break; */
- /* case MYSQL_TYPE_LONG: g_print ("MYSQL_TYPE_LONG"); break; */
- /* case MYSQL_TYPE_INT24: g_print ("MYSQL_TYPE_INT24"); break; */
- /* case MYSQL_TYPE_YEAR: g_print ("MYSQL_TYPE_YEAR"); break; */
- /* case MYSQL_TYPE_LONGLONG: g_print ("MYSQL_TYPE_LONGLONG"); break; */
- /* case MYSQL_TYPE_FLOAT: g_print ("MYSQL_TYPE_FLOAT"); break; */
- /* case MYSQL_TYPE_DECIMAL: g_print ("MYSQL_TYPE_DECIMAL"); break; */
- /* case MYSQL_TYPE_NEWDECIMAL: g_print ("MYSQL_TYPE_NEWDECIMAL"); break; */
- /* case MYSQL_TYPE_DOUBLE: g_print ("MYSQL_TYPE_DOUBLE"); break; */
- /* case MYSQL_TYPE_BIT: g_print ("MYSQL_TYPE_BIT"); break; */
- /* case MYSQL_TYPE_BLOB: g_print ("MYSQL_TYPE_BLOB"); break; */
- /* case MYSQL_TYPE_TIMESTAMP: g_print ("MYSQL_TYPE_TIMESTAMP"); break; */
- /* case MYSQL_TYPE_DATETIME: g_print ("MYSQL_TYPE_DATETIME"); break; */
- /* case MYSQL_TYPE_DATE: g_print ("MYSQL_TYPE_DATE"); break; */
- /* case MYSQL_TYPE_TIME: g_print ("MYSQL_TYPE_TIME"); break; */
- /* case MYSQL_TYPE_NULL: g_print ("MYSQL_TYPE_NULL"); break; */
- /* case MYSQL_TYPE_STRING: g_print ("MYSQL_TYPE_STRING"); break; */
- /* case MYSQL_TYPE_VAR_STRING: g_print ("MYSQL_TYPE_VAR_STRING"); break; */
- /* case MYSQL_TYPE_SET: g_print ("MYSQL_TYPE_SET"); break; */
- /* case MYSQL_TYPE_ENUM: g_print ("MYSQL_TYPE_ENUM"); break; */
- /* case MYSQL_TYPE_GEOMETRY: g_print ("MYSQL_TYPE_GEOMETRY"); break; */
- /* default: g_print ("UNKNOWN %d: MYSQL_TYPE_STRING", mysql_type); break; */
- /* } */
- /* g_print ("\n"); */
-
- return gtype;
-}
Modified: trunk/providers/mysql/gda-mysql.h
==============================================================================
--- trunk/providers/mysql/gda-mysql.h (original)
+++ trunk/providers/mysql/gda-mysql.h Tue Feb 24 21:28:19 2009
@@ -49,6 +49,9 @@
/* Backend version (to which we're connected). */
gchar *version;
unsigned long version_long;
+
+ /* specifies how case sensitiveness is */
+ gboolean tables_case_sensitive;
} MysqlConnectionData;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]