[libgda] Use type cast information from SELECT GdaStatement during execution
- From: Vivien Malerba <vivien src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgda] Use type cast information from SELECT GdaStatement during execution
- Date: Thu, 8 Sep 2011 20:44:32 +0000 (UTC)
commit 77e5d4ebb02d5d60599397058280922aac9e4581
Author: Vivien Malerba <malerba gnome-db org>
Date: Thu Sep 8 22:41:44 2011 +0200
Use type cast information from SELECT GdaStatement during execution
libgda/gda-connection.c | 117 +++++++++++++++++++++++++++++++++++++------
libgda/gda-statement-priv.h | 3 +-
libgda/gda-statement.c | 61 ++++++++++++++++++++++
3 files changed, 165 insertions(+), 16 deletions(-)
---
diff --git a/libgda/gda-connection.c b/libgda/gda-connection.c
index eb4d073..0f9cddd 100644
--- a/libgda/gda-connection.c
+++ b/libgda/gda-connection.c
@@ -883,6 +883,47 @@ gda_connection_get_property (GObject *object,
}
/*
+ * Returns: a new GType array, free using g_free(), or %NULL if none to compute
+ */
+static GType *
+merge_column_types (const GType *struct_types, const GType *user_types)
+{
+ if (! user_types || !struct_types)
+ return NULL;
+ GArray *array;
+ guint i;
+ array = g_array_new (TRUE, FALSE, sizeof (GType));
+ for (i = 0;
+ (user_types [i] != G_TYPE_NONE) && (struct_types [i] != G_TYPE_NONE);
+ i++) {
+ GType type;
+ if (user_types [i] == 0)
+ type = struct_types [i];
+ else
+ type = user_types [i];
+ g_array_append_val (array, type);
+ }
+ if (user_types [i] != G_TYPE_NONE) {
+ for (; user_types [i] != G_TYPE_NONE; i++) {
+ GType type = user_types [i];
+ g_array_append_val (array, type);
+ }
+ }
+ else {
+ for (; struct_types [i] != G_TYPE_NONE; i++) {
+ GType type = struct_types [i];
+ g_array_append_val (array, type);
+ }
+ }
+ GType *retval;
+ guint len;
+ len = array->len;
+ retval = (GType*) g_array_free (array, FALSE);
+ retval [len] = G_TYPE_NONE;
+ return retval;
+}
+
+/*
* helper functions to manage CncTask
*/
static void task_stmt_reset_cb (GdaStatement *stmt, CncTask *task);
@@ -900,15 +941,23 @@ cnc_task_new (guint id, GdaStatement *stmt, GdaStatementModelUsage model_usage,
g_signal_connect (stmt, "reset", /* monitor statement changes */
G_CALLBACK (task_stmt_reset_cb), task);
task->model_usage = model_usage;
- if (col_types) {
- gint i;
- for (i = 0; i < 32768; i++) {
- if (col_types [i] == G_TYPE_NONE)
- break;
+ GType *req_types;
+ req_types = merge_column_types (_gda_statement_get_requested_types (stmt), col_types);
+ if (req_types)
+ task->col_types = req_types;
+ else {
+ if (_gda_statement_get_requested_types (stmt))
+ col_types = (GType*) _gda_statement_get_requested_types (stmt);
+ if (col_types) {
+ gint i;
+ for (i = 0; ; i++) {
+ if (col_types [i] == G_TYPE_NONE)
+ break;
+ }
+ i++;
+ task->col_types = g_new (GType, i);
+ memcpy (task->col_types, col_types, i * sizeof (GType)); /* Flawfinder: ignore */
}
- i++;
- task->col_types = g_new (GType, i);
- memcpy (task->col_types, col_types, i * sizeof (GType)); /* Flawfinder: ignore */
}
if (params)
task->params = gda_set_copy (params);
@@ -3201,7 +3250,7 @@ gda_connection_statement_execute_v (GdaConnection *cnc, GdaStatement *stmt, GdaS
{
va_list ap;
GObject *obj;
- GType *types;
+ GType *types, *req_types;
GTimer *timer = NULL;
va_start (ap, error);
types = make_col_types_array (ap);
@@ -3220,9 +3269,19 @@ gda_connection_statement_execute_v (GdaConnection *cnc, GdaStatement *stmt, GdaS
_("Connection is closed"));
gda_connection_unlock (GDA_LOCKABLE (cnc));
g_object_unref ((GObject*) cnc);
+ g_free (types);
return NULL;
}
+ req_types = merge_column_types (_gda_statement_get_requested_types (stmt), types);
+ if (req_types) {
+ g_free (types);
+ types = req_types;
+ req_types = NULL;
+ }
+ else if (_gda_statement_get_requested_types (stmt))
+ req_types = (GType*) _gda_statement_get_requested_types (stmt);
+
if (! (model_usage & GDA_STATEMENT_MODEL_RANDOM_ACCESS) &&
! (model_usage & GDA_STATEMENT_MODEL_CURSOR_FORWARD))
model_usage |= GDA_STATEMENT_MODEL_RANDOM_ACCESS;
@@ -3231,7 +3290,9 @@ gda_connection_statement_execute_v (GdaConnection *cnc, GdaStatement *stmt, GdaS
if (cnc->priv->exec_times)
timer = g_timer_new ();
obj = PROV_CLASS (cnc->priv->provider_obj)->statement_execute (cnc->priv->provider_obj, cnc, stmt, params,
- model_usage, types, last_inserted_row,
+ model_usage,
+ req_types ? req_types : types,
+ last_inserted_row,
NULL, NULL, NULL, error);
if (timer)
g_timer_stop (timer);
@@ -3406,7 +3467,6 @@ gda_connection_statement_execute (GdaConnection *cnc, GdaStatement *stmt, GdaSet
return gda_connection_statement_execute_v (cnc, stmt, params, model_usage, last_inserted_row, error, -1);
}
-
/**
* gda_connection_statement_execute_non_select:
* @cnc: a #GdaConnection object.
@@ -3557,7 +3617,7 @@ gda_connection_statement_execute_select_fullv (GdaConnection *cnc, GdaStatement
va_list ap;
GdaDataModel *model;
- GType *types;
+ GType *types, *req_types;
GTimer *timer = NULL;
va_start (ap, error);
@@ -3574,9 +3634,19 @@ gda_connection_statement_execute_select_fullv (GdaConnection *cnc, GdaStatement
_("Connection is closed"));
gda_connection_unlock (GDA_LOCKABLE (cnc));
g_object_unref ((GObject*) cnc);
+ g_free (types);
return NULL;
}
+ req_types = merge_column_types (_gda_statement_get_requested_types (stmt), types);
+ if (req_types) {
+ g_free (types);
+ types = req_types;
+ req_types = NULL;
+ }
+ else if (_gda_statement_get_requested_types (stmt))
+ req_types = (GType*) _gda_statement_get_requested_types (stmt);
+
if (! (model_usage & GDA_STATEMENT_MODEL_RANDOM_ACCESS) &&
! (model_usage & GDA_STATEMENT_MODEL_CURSOR_FORWARD))
model_usage |= GDA_STATEMENT_MODEL_RANDOM_ACCESS;
@@ -3586,7 +3656,8 @@ gda_connection_statement_execute_select_fullv (GdaConnection *cnc, GdaStatement
timer = g_timer_new ();
model = (GdaDataModel *) PROV_CLASS (cnc->priv->provider_obj)->statement_execute (cnc->priv->provider_obj,
cnc, stmt, params, model_usage,
- types, NULL, NULL,
+ req_types ? req_types : types,
+ NULL, NULL,
NULL, NULL, error);
if (timer)
g_timer_stop (timer);
@@ -3656,6 +3727,11 @@ gda_connection_statement_execute_select_full (GdaConnection *cnc, GdaStatement *
return NULL;
}
+ GType *req_types;
+ req_types = merge_column_types (_gda_statement_get_requested_types (stmt), col_types);
+ if (!req_types && !col_types)
+ col_types = (GType*) _gda_statement_get_requested_types (stmt);
+
if (! (model_usage & GDA_STATEMENT_MODEL_RANDOM_ACCESS) &&
! (model_usage & GDA_STATEMENT_MODEL_CURSOR_FORWARD))
model_usage |= GDA_STATEMENT_MODEL_RANDOM_ACCESS;
@@ -3665,10 +3741,13 @@ gda_connection_statement_execute_select_full (GdaConnection *cnc, GdaStatement *
timer = g_timer_new ();
model = (GdaDataModel *) PROV_CLASS (cnc->priv->provider_obj)->statement_execute (cnc->priv->provider_obj,
cnc, stmt, params,
- model_usage, col_types, NULL,
+ model_usage,
+ req_types ? req_types : col_types,
+ NULL,
NULL, NULL, NULL, error);
if (timer)
g_timer_stop (timer);
+ g_free (req_types);
gda_connection_unlock ((GdaLockable*) cnc);
g_object_unref ((GObject*) cnc);
@@ -3734,6 +3813,11 @@ gda_connection_repetitive_statement_execute (GdaConnection *cnc, GdaRepetitiveSt
return NULL;
}
+ GType *req_types;
+ req_types = merge_column_types (_gda_statement_get_requested_types (stmt), col_types);
+ if (!req_types && !col_types)
+ col_types = (GType*) _gda_statement_get_requested_types (stmt);
+
if (! (model_usage & GDA_STATEMENT_MODEL_RANDOM_ACCESS) &&
! (model_usage & GDA_STATEMENT_MODEL_CURSOR_FORWARD))
model_usage |= GDA_STATEMENT_MODEL_RANDOM_ACCESS;
@@ -3749,7 +3833,9 @@ gda_connection_repetitive_statement_execute (GdaConnection *cnc, GdaRepetitiveSt
timer = g_timer_new ();
obj = PROV_CLASS (cnc->priv->provider_obj)->statement_execute (cnc->priv->provider_obj, cnc, stmt,
GDA_SET (list->data),
- model_usage, col_types, NULL,
+ model_usage,
+ req_types ? req_types : col_types,
+ NULL,
NULL, NULL, NULL, &lerror);
if (timer)
g_timer_stop (timer);
@@ -3777,6 +3863,7 @@ gda_connection_repetitive_statement_execute (GdaConnection *cnc, GdaRepetitiveSt
g_timer_destroy (timer);
}
g_slist_free (sets_list);
+ g_free (req_types);
gda_connection_unlock ((GdaLockable*) cnc);
g_object_unref ((GObject*) cnc);
diff --git a/libgda/gda-statement-priv.h b/libgda/gda-statement-priv.h
index 0bc2997..0085a7c 100644
--- a/libgda/gda-statement-priv.h
+++ b/libgda/gda-statement-priv.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 - 2010 Vivien Malerba <malerba gnome-db org>
+ * Copyright (C) 2008 - 2011 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 Lesser General Public
@@ -24,6 +24,7 @@
G_BEGIN_DECLS
const GdaSqlStatement *_gda_statement_get_internal_struct (GdaStatement *stmt);
+const GType *_gda_statement_get_requested_types (GdaStatement *stmt);
G_END_DECLS
diff --git a/libgda/gda-statement.c b/libgda/gda-statement.c
index 6a7f11f..51b6afb 100644
--- a/libgda/gda-statement.c
+++ b/libgda/gda-statement.c
@@ -66,6 +66,7 @@ static GObjectClass *parent_class = NULL;
struct _GdaStatementPrivate {
GdaSqlStatement *internal_struct;
+ GType *requested_types;
};
/* signals */
@@ -178,6 +179,7 @@ gda_statement_init (GdaStatement * stmt)
{
stmt->priv = g_new0 (GdaStatementPrivate, 1);
stmt->priv->internal_struct = NULL;
+ stmt->priv->requested_types = NULL;
}
/**
@@ -231,6 +233,10 @@ gda_statement_dispose (GObject *object)
stmt = GDA_STATEMENT (object);
if (stmt->priv) {
+ if (stmt->priv->requested_types) {
+ g_free (stmt->priv->requested_types);
+ stmt->priv->requested_types = NULL;
+ }
if (stmt->priv->internal_struct) {
gda_sql_statement_free (stmt->priv->internal_struct);
stmt->priv->internal_struct = NULL;
@@ -276,6 +282,10 @@ gda_statement_set_property (GObject *object,
gda_sql_statement_free (stmt->priv->internal_struct);
stmt->priv->internal_struct = NULL;
}
+ if (stmt->priv->requested_types) {
+ g_free (stmt->priv->requested_types);
+ stmt->priv->requested_types = NULL;
+ }
stmt->priv->internal_struct = gda_sql_statement_copy (g_value_get_pointer (value));
g_signal_emit (stmt, gda_statement_signals [RESET], 0);
break;
@@ -567,6 +577,57 @@ gda_statement_get_parameters (GdaStatement *stmt, GdaSet **out_params, GError **
}
/*
+ * _gda_statement_get_requested_types:
+ * @stmt: a #GdaStatement
+ *
+ * Returns: a new #GType, suitable to use with gda_connection_statement_execute_select_full(), or %NULL
+ */
+const GType *
+_gda_statement_get_requested_types (GdaStatement *stmt)
+{
+ if (! stmt->priv || ! stmt->priv->internal_struct)
+ return NULL;
+ if (stmt->priv->requested_types)
+ return stmt->priv->requested_types;
+ if (stmt->priv->internal_struct->stmt_type != GDA_SQL_STATEMENT_SELECT)
+ return NULL;
+
+ GdaSqlStatementSelect *selst;
+ GSList *list;
+ GArray *array = NULL;
+ rewind:
+ selst = (GdaSqlStatementSelect*) stmt->priv->internal_struct->contents;
+ for (list = selst->expr_list; list; list = list->next) {
+ GdaSqlExpr *expr;
+ GType type = G_TYPE_INVALID;
+ expr = ((GdaSqlSelectField*) list->data)->expr;
+ if (expr->cast_as && *expr->cast_as)
+ type = gda_g_type_from_string (expr->cast_as);
+ if (array) {
+ if (type == G_TYPE_INVALID)
+ type = 0;
+ g_array_append_val (array, type);
+ }
+ else if (type != G_TYPE_INVALID) {
+ array = g_array_new (TRUE, FALSE, sizeof (GType));
+ goto rewind;
+ }
+ }
+ if (array) {
+ GType *retval;
+ guint len;
+ len = array->len;
+ retval = (GType*) g_array_free (array, FALSE);
+ retval [len] = G_TYPE_NONE;
+ stmt->priv->requested_types = retval;
+ return retval;
+ }
+ else
+ return NULL;
+}
+
+
+/*
* SQL rendering
*/
static gchar *default_render_value (const GValue *value, GdaSqlRenderingContext *context, GError **error);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]