[libgda] GdaBrowser: use user preferences when creating forms for query parameters
- From: Vivien Malerba <vivien src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgda] GdaBrowser: use user preferences when creating forms for query parameters
- Date: Sat, 27 Nov 2010 14:15:47 +0000 (UTC)
commit 2044e5517f9b53ffc83e7f67b657f41c63ad92e4
Author: Vivien Malerba <malerba gnome-db org>
Date: Thu Nov 25 21:59:05 2010 +0100
GdaBrowser: use user preferences when creating forms for query parameters
tools/browser/browser-connection.c | 303 ++++++++++++++++++++++++
tools/browser/browser-connection.h | 5 +
tools/browser/doc/gda-browser-sections.txt | 2 +
tools/browser/doc/tmpl/browser-connection.sgml | 20 ++
tools/browser/query-exec/query-console.c | 4 +
5 files changed, 334 insertions(+), 0 deletions(-)
---
diff --git a/tools/browser/browser-connection.c b/tools/browser/browser-connection.c
index 498c918..2ffe328 100644
--- a/tools/browser/browser-connection.c
+++ b/tools/browser/browser-connection.c
@@ -25,6 +25,7 @@
#include "marshal.h"
#include <sql-parser/gda-sql-parser.h>
#include <libgda/gda-sql-builder.h>
+#include <libgda-ui/gdaui-enums.h>
#include "browser-connection-priv.h"
@@ -1706,6 +1707,308 @@ browser_connection_get_table_column_attribute (BrowserConnection *bcnc,
}
/**
+ * browser_connection_define_ui_plugins_for_batch
+ * @bcnc: a #BrowserConnection object
+ * @batch: a #GdaBatch
+ * @params: a #GdaSet (usually created with gda_batch_get_parameters())
+ *
+ * Calls browser_connection_define_ui_plugins_for_stmt() for each statement in @batch
+ */
+void
+browser_connection_define_ui_plugins_for_batch (BrowserConnection *bcnc, GdaBatch *batch, GdaSet *params)
+{
+ g_return_if_fail (BROWSER_IS_CONNECTION (bcnc));
+ g_return_if_fail (GDA_IS_BATCH (batch));
+ if (!params)
+ return;
+ g_return_if_fail (GDA_IS_SET (params));
+
+ const GSList *list;
+ for (list = gda_batch_get_statements (batch); list; list = list->next)
+ browser_connection_define_ui_plugins_for_stmt (bcnc, GDA_STATEMENT (list->data), params);
+}
+
+/* remark: the current ABI leaves no room to add a
+ * validity check to the GdaSqlExpr structure, and the following test
+ * should be done in gda_sql_expr_check_validity() once the GdaSqlExpr
+ * has the capacity to hold the information (ie. when ABI is broken)
+ *
+ * The code here is a modification from the gda_sql_select_field_check_validity()
+ * adapted for the GdaSqlExpr.
+ */
+static gboolean
+_gda_sql_expr_check_validity (GdaSqlExpr *expr, GdaMetaStruct *mstruct,
+ GdaMetaDbObject **out_validity_meta_object,
+ GdaMetaTableColumn **out_validity_meta_table_column, GError **error)
+{
+ GdaMetaDbObject *dbo = NULL;
+ const gchar *field_name;
+
+ *out_validity_meta_object = NULL;
+ *out_validity_meta_table_column = NULL;
+
+ if (! expr->value || (G_VALUE_TYPE (expr->value) != G_TYPE_STRING))
+ return TRUE;
+ field_name = g_value_get_string (expr->value);
+
+
+ GdaSqlAnyPart *any;
+ GdaMetaTableColumn *tcol = NULL;
+ GValue value;
+
+ memset (&value, 0, sizeof (GValue));
+ for (any = GDA_SQL_ANY_PART(expr)->parent;
+ any && (any->type != GDA_SQL_ANY_STMT_SELECT) && (any->type != GDA_SQL_ANY_STMT_DELETE) &&
+ (any->type != GDA_SQL_ANY_STMT_UPDATE);
+ any = any->parent);
+ if (!any) {
+ /* not in a structure which can be analysed */
+ return TRUE;
+ }
+
+ switch (any->type) {
+ case GDA_SQL_ANY_STMT_SELECT: {
+ /* go through all the SELECT's targets to see if
+ * there is a table with the corresponding field */
+ GSList *targets;
+ if (((GdaSqlStatementSelect *)any)->from) {
+ for (targets = ((GdaSqlStatementSelect *)any)->from->targets;
+ targets;
+ targets = targets->next) {
+ GdaSqlSelectTarget *target = (GdaSqlSelectTarget *) targets->data;
+ if (!target->validity_meta_object /*&&
+ * commented out in the current context because
+ * browser_connection_check_sql_statement_validify() has already been
+ * called, will need to be re-added when movind to the
+ * gda-statement-struct.c file.
+ *
+ * !gda_sql_select_target_check_validity (target, data, error)*/)
+ return FALSE;
+
+ g_value_set_string (g_value_init (&value, G_TYPE_STRING), field_name);
+ tcol = gda_meta_struct_get_table_column (mstruct,
+ GDA_META_TABLE (target->validity_meta_object),
+ &value);
+ g_value_unset (&value);
+ if (tcol) {
+ /* found a candidate */
+ if (dbo) {
+ g_set_error (error, GDA_SQL_ERROR, GDA_SQL_VALIDATION_ERROR,
+ _("Could not identify table for field '%s'"), field_name);
+ return FALSE;
+ }
+ dbo = target->validity_meta_object;
+ }
+ }
+ }
+ break;
+ }
+ case GDA_SQL_ANY_STMT_UPDATE: {
+ GdaSqlTable *table;
+ table = ((GdaSqlStatementUpdate *)any)->table;
+ if (!table || !table->validity_meta_object /* ||
+ * commented out in the current context because
+ * browser_connection_check_sql_statement_validify() has already been
+ * called, will need to be re-added when movind to the
+ * gda-statement-struct.c file.
+ *
+ * !gda_sql_select_target_check_validity (target, data, error)*/)
+ return FALSE;
+ dbo = table->validity_meta_object;
+ g_value_set_string (g_value_init (&value, G_TYPE_STRING), field_name);
+ tcol = gda_meta_struct_get_table_column (mstruct,
+ GDA_META_TABLE (table->validity_meta_object),
+ &value);
+ g_value_unset (&value);
+ break;
+ }
+ case GDA_SQL_ANY_STMT_DELETE: {
+ GdaSqlTable *table;
+ table = ((GdaSqlStatementDelete *)any)->table;
+ if (!table || !table->validity_meta_object /* ||
+ * commented out in the current context because
+ * browser_connection_check_sql_statement_validify() has already been
+ * called, will need to be re-added when movind to the
+ * gda-statement-struct.c file.
+ *
+ * !gda_sql_select_target_check_validity (target, data, error)*/)
+ return FALSE;
+ dbo = table->validity_meta_object;
+ g_value_set_string (g_value_init (&value, G_TYPE_STRING), field_name);
+ tcol = gda_meta_struct_get_table_column (mstruct,
+ GDA_META_TABLE (table->validity_meta_object),
+ &value);
+ g_value_unset (&value);
+ break;
+ }
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ if (!dbo) {
+ g_set_error (error, GDA_SQL_ERROR, GDA_SQL_VALIDATION_ERROR,
+ _("Could not identify table for field '%s'"), field_name);
+ return FALSE;
+ }
+ *out_validity_meta_object = dbo;
+ *out_validity_meta_table_column = tcol;
+ return TRUE;
+}
+
+typedef struct {
+ BrowserConnection *bcnc;
+ GdaSet *params;
+} ParamsData;
+
+/*
+ *
+ * In this function we try to find for which table's column a parameter is and use
+ * preferences to set the GdaHolder's plugin attribute
+ */
+static gboolean
+foreach_ui_plugins_for_params (GdaSqlAnyPart *part, ParamsData *data, GError **error)
+{
+ if (part->type != GDA_SQL_ANY_EXPR)
+ return TRUE;
+ GdaSqlExpr *expr = (GdaSqlExpr*) part;
+ if (!expr->param_spec)
+ return TRUE;
+
+ GdaHolder *holder;
+ holder = gda_set_get_holder (data->params, expr->param_spec->name);
+ if (! holder)
+ return TRUE;
+
+ GdaSqlAnyPart *uppart;
+ gchar *plugin = NULL;
+ uppart = part->parent;
+ if (!uppart)
+ return TRUE;
+ else if (uppart->type == GDA_SQL_ANY_SQL_OPERATION) {
+ GdaSqlOperation *op = (GdaSqlOperation*) uppart;
+ /* look into condition */
+ GSList *list;
+ for (list = op->operands; list; list = list->next) {
+ GdaSqlExpr *oexpr = (GdaSqlExpr*) list->data;
+ if (oexpr == expr)
+ continue;
+
+ GdaMetaDbObject *validity_meta_object;
+ GdaMetaTableColumn *validity_meta_table_column;
+ if (_gda_sql_expr_check_validity (oexpr,
+ browser_connection_get_meta_struct (data->bcnc),
+ &validity_meta_object,
+ &validity_meta_table_column, NULL)) {
+ plugin = browser_connection_get_table_column_attribute (data->bcnc,
+ GDA_META_TABLE (validity_meta_object),
+ validity_meta_table_column,
+ BROWSER_CONNECTION_COLUMN_PLUGIN, NULL);
+ break;
+ }
+ }
+ }
+ else if (uppart->type == GDA_SQL_ANY_STMT_UPDATE) {
+ GdaSqlStatementUpdate *upd = (GdaSqlStatementUpdate*) uppart;
+ GdaSqlField *field;
+ field = g_slist_nth_data (upd->fields_list, g_slist_index (upd->expr_list, expr));
+ if (field)
+ plugin = browser_connection_get_table_column_attribute (data->bcnc,
+ GDA_META_TABLE (upd->table->validity_meta_object),
+ field->validity_meta_table_column,
+ BROWSER_CONNECTION_COLUMN_PLUGIN, NULL);
+ }
+ else if (uppart->type == GDA_SQL_ANY_STMT_INSERT) {
+ GdaSqlStatementInsert *ins = (GdaSqlStatementInsert*) uppart;
+ GdaSqlField *field;
+ gint expr_index = -1;
+ GSList *slist;
+ GdaMetaTableColumn *column = NULL;
+ for (slist = ins->values_list; slist; slist = slist->next) {
+ expr_index = g_slist_index ((GSList*) slist->data, expr);
+ if (expr_index >= 0)
+ break;
+ }
+ if (expr_index >= 0) {
+ field = g_slist_nth_data (ins->fields_list, expr_index);
+ if (field)
+ column = field->validity_meta_table_column;
+ else {
+ /* no field specified => take the table's fields */
+ GdaMetaTable *mtable = GDA_META_TABLE (ins->table->validity_meta_object);
+ column = g_slist_nth_data (mtable->columns, expr_index);
+ }
+ }
+ if (column)
+ plugin = browser_connection_get_table_column_attribute (data->bcnc,
+ GDA_META_TABLE (ins->table->validity_meta_object),
+ column,
+ BROWSER_CONNECTION_COLUMN_PLUGIN, NULL);
+ }
+
+ if (plugin) {
+ /*g_print ("Using plugin [%s]\n", plugin);*/
+ GValue *value;
+ g_value_take_string ((value = gda_value_new (G_TYPE_STRING)), plugin);
+ gda_holder_set_attribute_static (holder, GDAUI_ATTRIBUTE_PLUGIN, value);
+ gda_value_free (value);
+ }
+
+ return TRUE;
+}
+
+/**
+ * browser_connection_define_ui_plugins_for_stmt
+ * @bcnc: a #BrowserConnection object
+ * @stmt: a #GdaStatement
+ * @params: a #GdaSet (usually created with gda_statement_get_parameters())
+ *
+ * Analyses @stmt and assign plugins to each #GdaHolder in @params according to the preferences stored
+ * for each table's field, defined at some point using browser_connection_set_table_column_attribute().
+ */
+void
+browser_connection_define_ui_plugins_for_stmt (BrowserConnection *bcnc, GdaStatement *stmt, GdaSet *params)
+{
+ g_return_if_fail (BROWSER_IS_CONNECTION (bcnc));
+ g_return_if_fail (GDA_IS_STATEMENT (stmt));
+ if (!params)
+ return;
+ g_return_if_fail (GDA_IS_SET (params));
+
+ GdaSqlStatement *sqlst;
+ GdaSqlAnyPart *rootpart;
+ g_object_get ((GObject*) stmt, "structure", &sqlst, NULL);
+ g_return_if_fail (sqlst);
+ switch (sqlst->stmt_type) {
+ case GDA_SQL_STATEMENT_INSERT:
+ case GDA_SQL_STATEMENT_UPDATE:
+ case GDA_SQL_STATEMENT_DELETE:
+ case GDA_SQL_STATEMENT_SELECT:
+ case GDA_SQL_STATEMENT_COMPOUND:
+ rootpart = (GdaSqlAnyPart*) sqlst->contents;
+ break;
+ default:
+ rootpart = NULL;
+ break;
+ }
+ GError *lerror = NULL;
+ if (!rootpart || !browser_connection_check_sql_statement_validify (bcnc, sqlst, &lerror)) {
+ /*g_print ("ERROR: %s\n", lerror && lerror->message ? lerror->message : "No detail");*/
+ g_clear_error (&lerror);
+ gda_sql_statement_free (sqlst);
+ return;
+ }
+
+ ParamsData data;
+ data.params = params;
+ data.bcnc = bcnc;
+ gda_sql_any_part_foreach (rootpart, (GdaSqlForeachFunc) foreach_ui_plugins_for_params,
+ &data, NULL);
+
+ gda_sql_statement_free (sqlst);
+}
+
+/**
* browser_connection_keep_variables
* @bcnc: a #BrowserConnection object
* @set: a #GdaSet containing variables for which a copy has to be done
diff --git a/tools/browser/browser-connection.h b/tools/browser/browser-connection.h
index 8908ffc..dc078d2 100644
--- a/tools/browser/browser-connection.h
+++ b/tools/browser/browser-connection.h
@@ -146,6 +146,11 @@ gchar *browser_connection_get_table_column_attribute (BrowserConne
const gchar *attr_name,
GError **error);
+void browser_connection_define_ui_plugins_for_batch(BrowserConnection *bcnc,
+ GdaBatch *batch, GdaSet *params);
+void browser_connection_define_ui_plugins_for_stmt (BrowserConnection *bcnc,
+ GdaStatement *stmt, GdaSet *params);
+
/*
* Variables used at various places and for which a copy of the last recent value
* is stored in the BrowserConnection object
diff --git a/tools/browser/doc/gda-browser-sections.txt b/tools/browser/doc/gda-browser-sections.txt
index ca20544..6e81b2d 100644
--- a/tools/browser/doc/gda-browser-sections.txt
+++ b/tools/browser/doc/gda-browser-sections.txt
@@ -104,6 +104,8 @@ browser_connection_get_transaction_status
<SUBSECTION>
browser_connection_set_table_column_attribute
browser_connection_get_table_column_attribute
+browser_connection_define_ui_plugins_for_batch
+browser_connection_define_ui_plugins_for_stmt
<SUBSECTION>
browser_connection_keep_variables
browser_connection_load_variables
diff --git a/tools/browser/doc/tmpl/browser-connection.sgml b/tools/browser/doc/tmpl/browser-connection.sgml
index a393308..08a98ac 100644
--- a/tools/browser/doc/tmpl/browser-connection.sgml
+++ b/tools/browser/doc/tmpl/browser-connection.sgml
@@ -383,6 +383,26 @@ An opened connection
@Returns:
+<!-- ##### FUNCTION browser_connection_define_ui_plugins_for_batch ##### -->
+<para>
+
+</para>
+
+ bcnc:
+ batch:
+ params:
+
+
+<!-- ##### FUNCTION browser_connection_define_ui_plugins_for_stmt ##### -->
+<para>
+
+</para>
+
+ bcnc:
+ stmt:
+ params:
+
+
<!-- ##### FUNCTION browser_connection_keep_variables ##### -->
<para>
diff --git a/tools/browser/query-exec/query-console.c b/tools/browser/query-exec/query-console.c
index e37aab4..e87095d 100644
--- a/tools/browser/query-exec/query-console.c
+++ b/tools/browser/query-exec/query-console.c
@@ -529,6 +529,7 @@ history_copy_clicked_cb (G_GNUC_UNUSED GtkButton *button, QueryConsole *tconsole
g_string_free (string, TRUE);
}
+
static gboolean
compute_params (QueryConsole *tconsole)
{
@@ -558,6 +559,9 @@ compute_params (QueryConsole *tconsole)
if (gda_batch_get_parameters (batch, &(tconsole->priv->params), &error)) {
if (tconsole->priv->params) {
+ browser_connection_define_ui_plugins_for_batch (tconsole->priv->bcnc,
+ batch,
+ tconsole->priv->params);
show_variables = TRUE;
tconsole->priv->params_form = gdaui_basic_form_new (tconsole->priv->params);
g_object_set ((GObject*) tconsole->priv->params_form,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]