[libgda] GdaBrowser: actually execute statements
- From: Vivien Malerba <vivien src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [libgda] GdaBrowser: actually execute statements
- Date: Sun, 6 Sep 2009 20:22:26 +0000 (UTC)
commit 4b0809fc9d1ec865f973cc77c44ba4484358eabc
Author: Vivien Malerba <malerba gnome-db org>
Date: Sun Sep 6 22:15:18 2009 +0200
GdaBrowser: actually execute statements
the results are not yet browsable and are dumped
to SDTOUT for now.
tools/browser/browser-connection.c | 76 ++++++++
tools/browser/browser-connection.h | 12 ++-
tools/browser/doc/gda-browser-sections.txt | 3 +
tools/browser/doc/tmpl/browser-connection.sgml | 36 ++++
tools/browser/query-exec/query-console.c | 222 +++++++++++++++++++++---
tools/browser/query-exec/query-editor.c | 17 ++-
6 files changed, 335 insertions(+), 31 deletions(-)
---
diff --git a/tools/browser/browser-connection.c b/tools/browser/browser-connection.c
index 6fe8c5f..2aeb4a5 100644
--- a/tools/browser/browser-connection.c
+++ b/tools/browser/browser-connection.c
@@ -675,3 +675,79 @@ browser_connection_create_parser (BrowserConnection *bcnc)
parser = gda_sql_parser_new ();
return parser;
}
+
+/**
+ * browser_connection_render_pretty_sql
+ * @bcnc: a #BrowserConnection
+ * @stmt: a #GdaStatement
+ *
+ * Renders @stmt as SQL well indented
+ *
+ * Returns: a new string
+ */
+gchar *
+browser_connection_render_pretty_sql (BrowserConnection *bcnc, GdaStatement *stmt)
+{
+ g_return_val_if_fail (BROWSER_IS_CONNECTION (bcnc), NULL);
+ g_return_val_if_fail (GDA_IS_STATEMENT (stmt), NULL);
+
+ return gda_statement_to_sql_extended (stmt, bcnc->priv->cnc, NULL,
+ GDA_STATEMENT_SQL_PRETTY |
+ GDA_STATEMENT_SQL_PARAMS_SHORT,
+ NULL, NULL);
+}
+
+/**
+ * browser_connection_execute_statement
+ * @bcnc: a #BrowserConnection
+ * @stmt: a #GdaStatement
+ * @params: a #GdaSet as parameters, or %NULL
+ * @model_usage: how the returned data model (if any) will be used
+ * @need_last_insert_row: %TRUE if the values of the last interted row must be computed
+ * @error: a place to store errors, or %NULL
+ *
+ * Executes @stmt by @bcnc
+ *
+ * Returns: a job ID, to be used with browser_connection_execution_get_result(), or %0 if an
+ * error occurred
+ */
+guint
+browser_connection_execute_statement (BrowserConnection *bcnc,
+ GdaStatement *stmt,
+ GdaSet *params,
+ GdaStatementModelUsage model_usage,
+ gboolean need_last_insert_row,
+ GError **error)
+{
+ g_return_val_if_fail (BROWSER_IS_CONNECTION (bcnc), 0);
+ g_return_val_if_fail (GDA_IS_STATEMENT (stmt), 0);
+ g_return_val_if_fail (!params || GDA_IS_SET (params), 0);
+
+ return gda_connection_async_statement_execute (bcnc->priv->cnc, stmt,
+ params, model_usage,
+ NULL, need_last_insert_row,
+ error);
+}
+
+/**
+ * browser_connection_execution_get_result
+ * @bcnc: a #BrowserConnection
+ * @exec_id: the ID of the excution
+ * @last_insert_row: a place to store the last inserted row, if any, or %NULL
+ * @error: a place to store errors, or %NULL
+ *
+ * Pick up the result of the @exec_id's execution.
+ *
+ * Retunrs: see gda_connection_async_fetch_result()
+ */
+GObject *
+browser_connection_execution_get_result (BrowserConnection *bcnc, guint exec_id,
+ GdaSet **last_insert_row, GError **error)
+{
+ g_return_val_if_fail (BROWSER_IS_CONNECTION (bcnc), NULL);
+ g_return_val_if_fail (exec_id > 0, NULL);
+
+ return gda_connection_async_fetch_result (bcnc->priv->cnc, exec_id,
+ last_insert_row,
+ error);
+}
diff --git a/tools/browser/browser-connection.h b/tools/browser/browser-connection.h
index b6f95e4..c9b03db 100644
--- a/tools/browser/browser-connection.h
+++ b/tools/browser/browser-connection.h
@@ -71,7 +71,17 @@ BrowserFavorites *browser_connection_get_favorites (BrowserConnection
* statements's execution
*/
GdaSqlParser *browser_connection_create_parser (BrowserConnection *bcnc);
-/* TODO */
+gchar *browser_connection_render_pretty_sql (BrowserConnection *bcnc,
+ GdaStatement *stmt);
+guint browser_connection_execute_statement (BrowserConnection *bcnc,
+ GdaStatement *stmt,
+ GdaSet *params,
+ GdaStatementModelUsage model_usage,
+ gboolean need_last_insert_row,
+ GError **error);
+GObject *browser_connection_execution_get_result (BrowserConnection *bcnc,
+ guint exec_id,
+ GdaSet **last_insert_row, GError **error);
G_END_DECLS
diff --git a/tools/browser/doc/gda-browser-sections.txt b/tools/browser/doc/gda-browser-sections.txt
index 41b6f39..6df6895 100644
--- a/tools/browser/doc/gda-browser-sections.txt
+++ b/tools/browser/doc/gda-browser-sections.txt
@@ -151,6 +151,9 @@ browser_connection_get_meta_store
browser_connection_get_dictionary_file
browser_connection_get_favorites
browser_connection_create_parser
+browser_connection_render_pretty_sql
+browser_connection_execute_statement
+browser_connection_execution_get_result
<SUBSECTION Standard>
BROWSER_CONNECTION
BROWSER_IS_CONNECTION
diff --git a/tools/browser/doc/tmpl/browser-connection.sgml b/tools/browser/doc/tmpl/browser-connection.sgml
index 534ff21..1a85fb2 100644
--- a/tools/browser/doc/tmpl/browser-connection.sgml
+++ b/tools/browser/doc/tmpl/browser-connection.sgml
@@ -144,3 +144,39 @@ An opened connection
@Returns:
+<!-- ##### FUNCTION browser_connection_render_pretty_sql ##### -->
+<para>
+
+</para>
+
+ bcnc:
+ stmt:
+ Returns:
+
+
+<!-- ##### FUNCTION browser_connection_execute_statement ##### -->
+<para>
+
+</para>
+
+ bcnc:
+ stmt:
+ params:
+ model_usage:
+ need_last_insert_row:
+ error:
+ Returns:
+
+
+<!-- ##### FUNCTION browser_connection_execution_get_result ##### -->
+<para>
+
+</para>
+
+ bcnc:
+ exec_id:
+ last_insert_row:
+ error:
+ Returns:
+
+
diff --git a/tools/browser/query-exec/query-console.c b/tools/browser/query-exec/query-console.c
index ef7a149..53c0546 100644
--- a/tools/browser/query-exec/query-console.c
+++ b/tools/browser/query-exec/query-console.c
@@ -45,6 +45,62 @@
"Valid types are: <tt>string</tt>, <tt>boolean</tt>, <tt>int</tt>,\n" \
"<tt>date</tt>, <tt>time</tt>, <tt>timestamp</tt>, <tt>guint</tt></small>")
+/*
+ * Statement execution structures
+ */
+typedef struct {
+ GTimeVal start_time;
+ GdaBatch *batch; /* ref held here */
+ QueryEditorHistoryBatch *hist_batch; /* ref held here */
+ GSList *statements; /* list of ExecutionStatament */
+} ExecutionBatch;
+static void execution_batch_free (ExecutionBatch *ebatch);
+
+typedef struct {
+ GdaStatement *stmt /* no ref held here */;
+ GError *exec_error;
+ GObject *result;
+ guint exec_id; /* 0 when execution not requested */
+} ExecutionStatement;
+static void execution_statement_free (ExecutionStatement *estmt);
+
+/*
+ * Frees an @ExecutionBatch
+ *
+ * If necessary, may set up and idle handler to perform some
+ * additionnal jobs
+ */
+static void
+execution_batch_free (ExecutionBatch *ebatch)
+{
+ GSList *list;
+ for (list = ebatch->statements; list; list = list->next)
+ execution_statement_free ((ExecutionStatement*) list->data);
+ g_slist_free (ebatch->statements);
+
+ g_object_unref (ebatch->batch);
+ if (ebatch->hist_batch)
+ query_editor_history_batch_unref (ebatch->hist_batch);
+
+ g_free (ebatch);
+}
+
+static void
+execution_statement_free (ExecutionStatement *estmt)
+{
+ if (estmt->exec_id > 0) {
+ /* job started => set up idle task */
+ TO_IMPLEMENT;
+ }
+ else {
+ if (estmt->exec_error)
+ g_error_free (estmt->exec_error);
+ if (estmt->result)
+ g_object_unref (estmt->result);
+ g_free (estmt);
+ }
+}
+
struct _QueryConsolePrivate {
BrowserConnection *bcnc;
GdaSqlParser *parser;
@@ -66,6 +122,9 @@ struct _QueryConsolePrivate {
QueryEditor *history;
GtkWidget *history_del_button;
GtkWidget *history_copy_button;
+
+ ExecutionBatch *current_exec;
+ guint current_exec_id; /* timout ID to fetch execution results */
};
static void query_console_class_init (QueryConsoleClass *klass);
@@ -139,6 +198,10 @@ query_console_dispose (GObject *object)
/* free memory */
if (tconsole->priv) {
+ if (tconsole->priv->current_exec_id)
+ g_source_remove (tconsole->priv->current_exec_id);
+ if (tconsole->priv->current_exec)
+ execution_batch_free (tconsole->priv->current_exec);
if (tconsole->priv->bcnc)
g_object_unref (tconsole->priv->bcnc);
if (tconsole->priv->parser)
@@ -616,11 +679,8 @@ sql_indent_clicked_cb (GtkButton *button, QueryConsole *tconsole)
stmt_list = gda_batch_get_statements (batch);
string = g_string_new ("");
for (list = stmt_list; list; list = list->next) {
- GError *error = NULL;
- sql = gda_statement_to_sql_extended (GDA_STATEMENT (list->data), NULL, NULL,
- GDA_STATEMENT_SQL_PRETTY |
- GDA_STATEMENT_SQL_PARAMS_SHORT,
- NULL, &error);
+ sql = browser_connection_render_pretty_sql (tconsole->priv->bcnc,
+ GDA_STATEMENT (list->data));
if (!sql)
sql = gda_statement_to_sql (GDA_STATEMENT (list->data), NULL, NULL);
if (list != stmt_list)
@@ -672,6 +732,8 @@ params_form_changed_cb (GdauiBasicForm *form, GdaHolder *param, gboolean is_user
gdaui_basic_form_is_valid (form));
}
+static gboolean query_exec_fetch_cb (QueryConsole *tconsole);
+
static void
sql_execute_clicked_cb (GtkButton *button, QueryConsole *tconsole)
{
@@ -765,34 +827,144 @@ sql_execute_clicked_cb (GtkButton *button, QueryConsole *tconsole)
}
g_free (sql);
- QueryEditorHistoryBatch *hbatch;
- GTimeVal tv;
- g_get_current_time (&tv);
- hbatch = query_editor_history_batch_new (tv);
- query_editor_start_history_batch (tconsole->priv->history, hbatch);
- query_editor_history_batch_unref (hbatch);
+ /* if a query is being executed, then show an error */
+ if (tconsole->priv->current_exec) {
+ g_object_unref (batch);
+ browser_show_error (GTK_WINDOW (gtk_widget_get_toplevel ((GtkWidget*) tconsole)),
+ _("A query is already being executed, "
+ "to execute another query, open a new connection."));
+ return;
+ }
+ /* actual Execution */
const GSList *stmt_list, *list;
+ ExecutionBatch *ebatch;
+ ebatch = g_new0 (ExecutionBatch, 1);
+ ebatch->batch = batch;
+ g_get_current_time (&(ebatch->start_time));
+ ebatch->hist_batch = query_editor_history_batch_new (ebatch->start_time);
+ query_editor_start_history_batch (tconsole->priv->history, ebatch->hist_batch);
+
stmt_list = gda_batch_get_statements (batch);
for (list = stmt_list; list; list = list->next) {
- QueryEditorHistoryItem *history;
- GdaSqlStatement *sqlst;
- g_object_get (G_OBJECT (list->data), "structure", &sqlst, NULL);
- if (!sqlst->sql) {
- sql = gda_statement_to_sql (GDA_STATEMENT (list->data), NULL, NULL);
- history = query_editor_history_item_new (sql, NULL, NULL);
- g_free (sql);
+ ExecutionStatement *estmt;
+ estmt = g_new0 (ExecutionStatement, 1);
+ estmt->stmt = GDA_STATEMENT (list->data);
+ ebatch->statements = g_slist_prepend (ebatch->statements, estmt);
+
+ if (list == stmt_list) {
+ estmt->exec_id = browser_connection_execute_statement (tconsole->priv->bcnc,
+ estmt->stmt,
+ tconsole->priv->params,
+ GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+ FALSE, &(estmt->exec_error));
+ g_print ("Executing: %u\n", estmt->exec_id);
+ if (estmt->exec_id == 0) {
+ browser_show_error (GTK_WINDOW (gtk_widget_get_toplevel ((GtkWidget*) tconsole)),
+ _("Error executing query: %s"),
+ estmt->exec_error && estmt->exec_error->message ? estmt->exec_error->message : _("No detail"));
+ execution_batch_free (ebatch);
+ return;
+ }
}
- else
- history = query_editor_history_item_new (sqlst->sql, NULL, NULL);
- gda_sql_statement_free (sqlst);
-
- query_editor_add_history_item (tconsole->priv->history, history);
- query_editor_history_item_unref (history);
}
- g_object_unref (batch);
+ ebatch->statements = g_slist_reverse (ebatch->statements);
+
+ tconsole->priv->current_exec = ebatch;
+ tconsole->priv->current_exec_id = g_timeout_add (200,
+ (GSourceFunc) query_exec_fetch_cb,
+ tconsole);
}
+static gboolean
+query_exec_fetch_cb (QueryConsole *tconsole)
+{
+ gboolean alldone = TRUE;
+
+ if (tconsole->priv->current_exec) {
+ if (tconsole->priv->current_exec->statements) {
+ ExecutionStatement *estmt;
+ estmt = (ExecutionStatement*) tconsole->priv->current_exec->statements->data;
+ g_assert (estmt->exec_id);
+ g_assert (!estmt->result);
+ g_assert (!estmt->exec_error);
+ g_print ("Getting results for exec ID %u\n", estmt->exec_id);
+ estmt->result = browser_connection_execution_get_result (tconsole->priv->bcnc,
+ estmt->exec_id, NULL,
+ &(estmt->exec_error));
+ if (estmt->result || estmt->exec_error) {
+ QueryEditorHistoryItem *history;
+ GdaSqlStatement *sqlst;
+ g_object_get (G_OBJECT (estmt->stmt), "structure", &sqlst, NULL);
+ if (!sqlst->sql) {
+ gchar *sql;
+ sql = gda_statement_to_sql (GDA_STATEMENT (estmt->stmt), NULL, NULL);
+ history = query_editor_history_item_new (sql, tconsole->priv->params,
+ estmt->result);
+ g_free (sql);
+ }
+ else
+ history = query_editor_history_item_new (sqlst->sql, tconsole->priv->params,
+ estmt->result);
+ gda_sql_statement_free (sqlst);
+ if (estmt->exec_error) {
+ browser_show_error (GTK_WINDOW (gtk_widget_get_toplevel ((GtkWidget*) tconsole)),
+ _("Error executing query:\n%s"),
+ estmt->exec_error && estmt->exec_error->message ?
+ estmt->exec_error->message : _("No detail"));
+ TO_IMPLEMENT;
+ /* FIXME: offer the opportunity to stop execution of batch if there
+ * are some remaining statements to execute
+ * FIXME: store error in history => modify QueryEditorHistoryItem
+ */
+ }
+
+ query_editor_add_history_item (tconsole->priv->history, history);
+ query_editor_history_item_unref (history);
+
+ /* get rid of estmt */
+ estmt->exec_id = 0;
+ execution_statement_free (estmt);
+ tconsole->priv->current_exec->statements =
+ g_slist_delete_link (tconsole->priv->current_exec->statements,
+ tconsole->priv->current_exec->statements);
+
+ /* more to do ? */
+ if (tconsole->priv->current_exec->statements) {
+ estmt = (ExecutionStatement*) tconsole->priv->current_exec->statements->data;
+ estmt->exec_id = browser_connection_execute_statement (tconsole->priv->bcnc,
+ estmt->stmt,
+ tconsole->priv->params,
+ GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+ FALSE,
+ &(estmt->exec_error));
+ g_print ("Executing: %u\n", estmt->exec_id);
+ if (estmt->exec_id == 0) {
+ browser_show_error (GTK_WINDOW (gtk_widget_get_toplevel ((GtkWidget*) tconsole)),
+ _("Error executing query:\n%s"),
+ estmt->exec_error && estmt->exec_error->message ?
+ estmt->exec_error->message : _("No detail"));
+ }
+ else
+ alldone = FALSE;
+ }
+ }
+ else
+ alldone = FALSE;
+ }
+ }
+
+ if (alldone) {
+ if (tconsole->priv->current_exec) {
+ execution_batch_free (tconsole->priv->current_exec);
+ tconsole->priv->current_exec = NULL;
+ }
+
+ tconsole->priv->current_exec_id = 0;
+ }
+
+ return !alldone;
+}
/*
* UI actions
diff --git a/tools/browser/query-exec/query-editor.c b/tools/browser/query-exec/query-editor.c
index 315fa5b..32be854 100644
--- a/tools/browser/query-exec/query-editor.c
+++ b/tools/browser/query-exec/query-editor.c
@@ -292,10 +292,12 @@ text_view_expose_event (GtkTextView *tv, GdkEventExpose *event, QueryEditor *edi
GSList *list;
HistItemData *hdata;
list = g_slist_last (editor->priv->hist_focus->batch->hist_items);
- hdata = g_hash_table_lookup (editor->priv->hash, list->data);
- gtk_text_buffer_get_iter_at_mark (tv->buffer, &cur, hdata->end_mark);
- gtk_text_view_get_line_yrange (tv, &cur, &ye, &heighte);
- height = ye - y;
+ if (list) {
+ hdata = g_hash_table_lookup (editor->priv->hash, list->data);
+ gtk_text_buffer_get_iter_at_mark (tv->buffer, &cur, hdata->end_mark);
+ gtk_text_view_get_line_yrange (tv, &cur, &ye, &heighte);
+ height = ye - y;
+ }
}
gtk_text_view_get_visible_rect (tv, &visible_rect);
@@ -1315,8 +1317,13 @@ query_editor_history_item_new (const gchar *sql, GdaSet *params, GObject *result
qih->sql = g_strdup (sql);
if (params)
qih->params = gda_set_copy (params);
- if (result)
+ if (result) {
qih->result = g_object_ref (result);
+ if (GDA_IS_DATA_MODEL (result))
+ gda_data_model_dump (GDA_DATA_MODEL (result), NULL);
+ else
+ g_print ("RESULT!!!\n");
+ }
return qih;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]