1 /*
2  * Copyright (C) 2010 Claude Paroz <claude@2xlibre.net>
3  * Copyright (C) 2010 David King <davidk@openismus.com>
4  * Copyright (C) 2010 Murray Cumming <murrayc@murrayc.com>
5  * Copyright (C) 2010 - 2012 Vivien Malerba <malerba@gnome-db.org>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20  */
21 
22 #include <string.h>
23 #include <glib/gi18n-lib.h>
24 #include "browser-connection.h"
25 #include <libgda/thread-wrapper/gda-thread-wrapper.h>
26 #include "support.h"
27 #include "marshal.h"
28 #include <sql-parser/gda-sql-parser.h>
29 #include <libgda/gda-data-model-extra.h>
30 #include <libgda/gda-sql-builder.h>
31 #include "../common/ui-formgrid.h"
32 #include "../../tool-utils.h"
main(int,char **)33 
34 #include "data-source.h"
35 #define DEFAULT_DATA_SOURCE_NAME "DataSource"
36 #define DEPENDENCY_SEPARATOR "<|>"
37 
38 /* signals */
39 enum {
40 	CHANGED,
41 	EXEC_STARTED,
42 	EXEC_FINISHED,
43 	LAST_SIGNAL
44 };
45 
46 gint data_source_signals [LAST_SIGNAL] = {0, 0, 0};
47 
48 /*
49  * Main static functions
50  */
51 static void data_source_class_init (DataSourceClass *klass);
52 static void data_source_init (DataSource *source);
53 static void data_source_dispose (GObject *object);
54 
55 
56 static void update_export_information (DataSource *source);
57 static void compute_stmt_and_params (DataSource *source);
58 static void compute_import_params (DataSource *source);
59 
60 
61 /* get a pointer to the parents to be able to call their destructor */
62 static GObjectClass  *parent_class = NULL;
63 
64 typedef struct {
65 	gchar *dep_id;
66 	gchar *dep_table;
67 	gchar *dep_columns; /* column names, separated by a |, sorted */
68 } Dependency;
69 
70 static void
71 dependency_free (Dependency *dep)
72 {
73 	g_free (dep->dep_id);
74 	g_free (dep->dep_table);
75 	g_free (dep->dep_columns);
76 	g_free (dep);
77 }
78 
79 /*
80  * converts an array of column names into a single string in the format:
81  * <colname>[SEP<colname>...] where SEP is DEPENDENCY_SEPARATOR
82  *
83  * Returns: a new string, never %NULL
84  */
85 static gchar *
86 column_names_to_string (gint size, const gchar **colnames)
87 {
88 	if (!colnames)
89 		return g_strdup ("");
90 
91 	GString *string = NULL;
92 	GArray *colsarray;
93 	gint i;
94 	colsarray = g_array_new (FALSE, FALSE, sizeof (gchar*));
95 	for (i = 0; i < size; i++)
96 		g_array_append_val (colsarray, colnames[i]);
97 	g_array_sort (colsarray, (GCompareFunc) g_strcmp0);
98 	for (i = 0; i < size; i++) {
99 		gchar *tmp;
100 		tmp = g_array_index (colsarray, gchar *, i);
101 		if (!string)
102 			string = g_string_new (tmp);
103 		else {
104 			g_string_append (string, DEPENDENCY_SEPARATOR);
105 			g_string_append (string, tmp);
106 		}
107 	}
108 	g_array_free (colsarray, TRUE);
109 	return g_string_free (string, FALSE);
110 }
111 
112 static Dependency *
113 dependency_find (GSList *dep_list, const gchar *id, const gchar *table, gint size, const gchar **colnames)
114 {
115 	GSList *list;
116 	gchar *colsstring = NULL;
117 	for (list = dep_list; list; list = list->next) {
118 		Dependency *dep = (Dependency*) list->data;
119 		if (strcmp (dep->dep_id, id) || strcmp (dep->dep_table, table))
120 			continue;
121 
122 		if (!colsstring)
123 			colsstring = column_names_to_string (size, colnames);
124 		if (!strcmp (colsstring, dep->dep_columns)) {
125 			g_free (colsstring);
126 			return dep;
127 		}
128 	}
129 	g_free (colsstring);
130 	return NULL;
131 }
132 
133 struct _DataSourcePrivate {
134 	BrowserConnection *bcnc;
135 	gchar             *title;
136 	gchar             *impl_title;
137 	gchar             *id;
138 	DataSourceType     source_type;
139 
140 	GError            *init_error;
141 	GArray            *export_names; /* array of strings, memory allocated in export_columns */
142 	GHashTable        *export_columns; /* key = export name, value = column number */
143 
144 	guint              exec_id;
145 	gboolean           executing;
146 	gboolean           exec_again;
147 
148 	gchar             *tablename;
149 	GdaSqlBuilder     *builder;
150 	GSList            *dependencies; /* list of Dependency pointers */
151 
152 	GdaStatement      *stmt;
153 	GdaSet            *ext_params; /* "free" parameters */
154 	GdaSet            *params; /* all the params used when executing @stmt */
155 	gboolean           need_rerun; /* set to %TRUE if @params has changed since the last exec */
156 
157 	GError            *exec_error;
158 
159 	GdaDataModel      *model;
160 };
161 
162 GType
163 data_source_get_type (void)
164 {
165 	static GType type = 0;
166 
167 	if (G_UNLIKELY (type == 0)) {
168 		static GMutex registering;
169 		static const GTypeInfo info = {
170 			sizeof (DataSourceClass),
171 			(GBaseInitFunc) NULL,
172 			(GBaseFinalizeFunc) NULL,
173 			(GClassInitFunc) data_source_class_init,
174 			NULL,
175 			NULL,
176 			sizeof (DataSource),
177 			0,
178 			(GInstanceInitFunc) data_source_init,
179 			0
180 		};
181 
182 
183 		g_mutex_lock (&registering);
184 		if (type == 0)
185 			type = g_type_register_static (G_TYPE_OBJECT, "DataSource", &info, 0);
186 		g_mutex_unlock (&registering);
187 	}
188 	return type;
189 }
190 
191 static void
192 data_source_class_init (DataSourceClass *klass)
193 {
194 	GObjectClass   *object_class = G_OBJECT_CLASS (klass);
195 	parent_class = g_type_class_peek_parent (klass);
196 
197 	/* signals */
198 	data_source_signals [CHANGED] =
199                 g_signal_new ("changed",
200                               G_TYPE_FROM_CLASS (object_class),
201                               G_SIGNAL_RUN_FIRST,
202                               G_STRUCT_OFFSET (DataSourceClass, changed),
203                               NULL, NULL,
204                               _dm_marshal_VOID__VOID, G_TYPE_NONE, 0);
205 	data_source_signals [EXEC_STARTED] =
206                 g_signal_new ("execution-started",
207                               G_TYPE_FROM_CLASS (object_class),
208                               G_SIGNAL_RUN_FIRST,
209                               G_STRUCT_OFFSET (DataSourceClass, execution_started),
210                               NULL, NULL,
211                               _dm_marshal_VOID__VOID, G_TYPE_NONE, 0);
212 	data_source_signals [EXEC_FINISHED] =
213                 g_signal_new ("execution-finished",
214                               G_TYPE_FROM_CLASS (object_class),
215                               G_SIGNAL_RUN_FIRST,
216                               G_STRUCT_OFFSET (DataSourceClass, execution_finished),
217                               NULL, NULL,
218                               _dm_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);
219         klass->changed = NULL;
220         klass->execution_started = NULL;
221         klass->execution_finished = NULL;
222 
223 	object_class->dispose = data_source_dispose;
224 }
225 
226 static void
227 data_source_init (DataSource *source)
228 {
229 	source->priv = g_new0 (DataSourcePrivate, 1);
230 	source->priv->id = g_strdup (DEFAULT_DATA_SOURCE_NAME);
231 	source->priv->bcnc = NULL;
232 	source->priv->source_type = DATA_SOURCE_UNKNOWN;
233 	source->priv->need_rerun = FALSE;
234 	source->priv->exec_id = 0;
235 	source->priv->executing = FALSE;
236 	source->priv->exec_again = FALSE;
237 }
238 
239 static void
240 params_changed_cb (G_GNUC_UNUSED GdaSet *params, G_GNUC_UNUSED GdaHolder *holder, DataSource *source)
241 {
242 	source->priv->need_rerun = TRUE;
243 }
244 
245 static void
246 ext_params_changed_cb (G_GNUC_UNUSED GdaSet *params, G_GNUC_UNUSED GdaHolder *holder, DataSource *source)
247 {
248 #ifdef DEBUG_SOURCE
249 	g_print ("  => data source [%s] should rerun\n",
250 		 data_source_get_title (source));
251 #endif
252 	source->priv->need_rerun = TRUE;
253 }
254 
255 static void
256 data_source_reset (DataSource *source)
257 {
258 	source->priv->source_type = DATA_SOURCE_UNKNOWN;
259 	g_clear_error (& source->priv->init_error);
260 
261 	if (source->priv->builder) {
262 		g_object_unref (source->priv->builder);
263 		source->priv->builder = NULL;
264 	}
265 	if (source->priv->stmt) {
266 		g_object_unref (source->priv->stmt);
267 		source->priv->stmt = NULL;
268 	}
269 	if (source->priv->params) {
270 		g_signal_handlers_disconnect_by_func (source->priv->params,
271 						      G_CALLBACK (params_changed_cb), source);
272 		g_object_unref (source->priv->params);
273 		source->priv->params = NULL;
274 	}
275 	if (source->priv->ext_params) {
276 		g_signal_handlers_disconnect_by_func (source->priv->ext_params,
277 						      G_CALLBACK (ext_params_changed_cb),
278 						      source);
279 		g_object_unref (source->priv->ext_params);
280 		source->priv->ext_params = NULL;
281 	}
282 
283 	if (source->priv->tablename) {
284 		g_free (source->priv->tablename);
285 		source->priv->tablename = NULL;
286 	}
287 
288 	if (source->priv->dependencies) {
289 		g_slist_foreach (source->priv->dependencies, (GFunc) dependency_free, NULL);
290 		g_slist_free (source->priv->dependencies);
291 		source->priv->dependencies = NULL;
292 	}
293 
294 	if (source->priv->model) {
295 		g_object_unref (source->priv->model);
296 		source->priv->model = NULL;
297 	}
298 
299 	if (source->priv->export_names) {
300 		g_array_free (source->priv->export_names, TRUE);
301 		source->priv->export_names = NULL;
302 	}
303 
304 	if (source->priv->export_columns) {
305 		g_hash_table_destroy (source->priv->export_columns);
306 		source->priv->export_columns = NULL;
307 	}
308 }
309 
310 static void
311 data_source_dispose (GObject *object)
312 {
313 	DataSource *source;
314 
315 	g_return_if_fail (object != NULL);
316 	g_return_if_fail (IS_DATA_SOURCE (object));
317 
318 	source = DATA_SOURCE (object);
319 	if (source->priv) {
320 		if (source->priv->bcnc)
321 			g_object_unref (source->priv->bcnc);
322 		data_source_reset (source);
323 		g_free (source->priv->id);
324 		g_free (source->priv->title);
325 		g_free (source->priv->impl_title);
326 
327 		g_free (source->priv);
328 		source->priv = NULL;
329 	}
330 
331 	/* parent class */
332 	parent_class->dispose (object);
333 }
334 
335 static void init_from_query (DataSource *source, xmlNodePtr node);
336 static gboolean init_from_table_node (DataSource *source, xmlNodePtr node, GError **error);
337 
338 /**
339  * data_source_new
340  * @bcnc: a #BrowserConnection
341  * @type: the new data source's requested type
342  *
343  * Returns: a new #DataSource object
344  */
345 DataSource *
346 data_source_new (BrowserConnection *bcnc, DataSourceType type)
347 {
348 	DataSource *source;
349 
350 	g_return_val_if_fail (BROWSER_IS_CONNECTION (bcnc), NULL);
351 
352 	source = DATA_SOURCE (g_object_new (DATA_SOURCE_TYPE, NULL));
353 	source->priv->bcnc = g_object_ref (bcnc);
354 	source->priv->source_type = type;
355 
356 	return source;
357 }
358 
359 /**
360  * data_source_new_from_xml_node
361  * @bcnc: a #BrowserConnection
362  * @node:
363  * @error:
364  *
365  * Creates a new #DataSource object
366  *
367  * Returns: a new object
368  */
369 DataSource*
370 data_source_new_from_xml_node (BrowserConnection *bcnc, xmlNodePtr node, GError **error)
371 {
372 	DataSource *source;
373 
374 	g_return_val_if_fail (BROWSER_IS_CONNECTION (bcnc), NULL);
375 	g_return_val_if_fail (node, NULL);
376 
377 	source = DATA_SOURCE (g_object_new (DATA_SOURCE_TYPE, NULL));
378 	source->priv->bcnc = g_object_ref (bcnc);
379 	xmlChar *prop;
380 	prop = xmlGetProp (node, BAD_CAST "title");
381 	if (prop) {
382 		g_free (source->priv->title);
383 		source->priv->title = g_strdup ((gchar*) prop);
384 		xmlFree (prop);
385 	}
386 	prop = xmlGetProp (node, BAD_CAST "id");
387 	if (prop) {
388 		g_free (source->priv->id);
389 		source->priv->id = g_strdup ((gchar*) prop);
390 		xmlFree (prop);
391 	}
392 
393 	if (!strcmp ((gchar*)node->name, "table")) {
394 		if (! init_from_table_node (source, node, error)) {
395 			g_object_unref (source);
396 			source = NULL;
397 		}
398 	}
399 	else if (!strcmp ((gchar*)node->name, "query")) {
400 		init_from_query (source, node);
401 	}
402 	else {
403 		g_set_error (error, GDA_TOOLS_ERROR, GDA_TOOLS_COMMAND_ARGUMENTS_ERROR,
404 			     /* Translators: Do not translate "table" nor "query" */
405 			     _("Node must be \"table\" or \"query\", and is \"%s\""), (gchar*)node->name);
406 		g_object_unref (source);
407 		source = NULL;
408 	}
409 
410 	return source;
411 }
412 
413 static void
414 init_from_query (DataSource *source, xmlNodePtr node)
415 {
416 	xmlChar *contents;
417 
418 #ifdef DEBUG_SOURCE
419 	g_print ("%s(%s [%s])\n", __FUNCTION__, source->priv->id, source->priv->title);
420 #endif
421 	contents = xmlNodeGetContent (node);
422 	g_clear_error (& source->priv->init_error);
423 	data_source_set_query (source, (gchar*) contents, &source->priv->init_error);
424 }
425 
426 static GdaMetaTable *
427 get_meta_table (DataSource *source, const gchar *table_name, GError **error)
428 {
429 	GdaMetaStruct *mstruct;
430 	GdaMetaDbObject *dbo;
431 	GValue *vname[3] = {NULL, NULL, NULL};
432 	gchar **split;
433 	gint len;
434 
435 	mstruct = browser_connection_get_meta_struct (source->priv->bcnc);
436 	if (! mstruct) {
437 		g_set_error (error, GDA_TOOLS_ERROR, GDA_TOOLS_STORED_DATA_ERROR,
438 			     "%s", _("Not ready"));
439 		return NULL;
440 	}
441 
442 	split = gda_sql_identifier_split (table_name);
443 	if (! split) {
444 		g_set_error (error, GDA_TOOLS_ERROR, GDA_TOOLS_COMMAND_ARGUMENTS_ERROR,
445 			     _("Malformed table name \"%s\""), table_name);
446 		return NULL;
447 	}
448 	len = g_strv_length (split);
449 	g_value_set_string ((vname[2] = gda_value_new (G_TYPE_STRING)), split[len - 1]);
450 	if (len > 1)
451 		g_value_set_string ((vname[1] = gda_value_new (G_TYPE_STRING)), split[len -2]);
452 	if (len > 2)
453 		g_value_set_string ((vname[0] = gda_value_new (G_TYPE_STRING)), split[len - 3]);
454 
455 	dbo = gda_meta_struct_get_db_object (mstruct, vname[0], vname[1], vname[2]);
456 	if (vname[0]) gda_value_free (vname[0]);
457 	if (vname[1]) gda_value_free (vname[1]);
458 	if (vname[2]) gda_value_free (vname[2]);
459 
460 	if (! dbo) {
461 		g_set_error (error, GDA_TOOLS_ERROR, GDA_TOOLS_INTERNAL_COMMAND_ERROR,
462 			     _("Could not find the \"%s\" table"), table_name);
463 		return NULL;
464 	}
465 	if ((dbo->obj_type != GDA_META_DB_TABLE) && (dbo->obj_type != GDA_META_DB_VIEW)) {
466 		g_set_error (error, GDA_TOOLS_ERROR, GDA_TOOLS_INTERNAL_COMMAND_ERROR,
467 			     _("The \"%s\" object is not a table"), table_name);
468 		return NULL;
469 	}
470 	return GDA_META_TABLE (dbo);
471 }
472 
473 static gboolean
474 init_from_table_node (DataSource *source, xmlNodePtr node, GError **error)
475 {
476 	xmlChar *tname;
477 	gboolean retval;
478 
479 #ifdef DEBUG_SOURCE
480 	g_print ("%s(%s [%s])\n", __FUNCTION__, source->priv->id, source->priv->title);
481 #endif
482 	tname = xmlGetProp (node, BAD_CAST "name");
483 	if (!tname) {
484 		g_set_error (error, GDA_TOOLS_ERROR, GDA_TOOLS_COMMAND_ARGUMENTS_ERROR,
485 			     /* Translators: Do not translate "name" */
486 			     "%s", _("Missing attribute \"name\" for table"));
487 		return FALSE;
488 	}
489 
490 	retval = data_source_set_table (source, (gchar*) tname, error);
491 	xmlFree (tname);
492 
493 	/* linking */
494 	xmlNodePtr subnode;
495 	for (subnode = node->children; subnode; subnode = subnode->next) {
496 		if (!strcmp ((gchar*)subnode->name, "depend")) {
497 			xmlChar *fk_table, *id;
498 			GArray *cols_array = NULL;
499 			xmlNodePtr chnode;
500 
501 			fk_table = xmlGetProp (subnode, BAD_CAST "foreign_key_table");
502 			id = xmlGetProp (subnode, BAD_CAST "id");
503 			for (chnode = subnode->children; chnode; chnode = chnode->next) {
504 				xmlChar *colname;
505 				if (strcmp ((gchar*)chnode->name, "column"))
506 					continue;
507 				colname = xmlNodeGetContent (chnode);
508 				if (colname) {
509 					if (! cols_array)
510 						cols_array = g_array_new (FALSE, FALSE, sizeof (gchar*));
511 					g_array_append_val (cols_array, colname);
512 				}
513 			}
514 
515 			if (fk_table &&
516 			    ! data_source_add_dependency (source, (gchar *) fk_table, (gchar*) id,
517 							  cols_array ? cols_array->len : 0,
518 							  (const gchar **) (cols_array ? cols_array->data : NULL),
519 							  error))
520 				retval = FALSE;
521 			if (fk_table)
522 				xmlFree (fk_table);
523 			if (id)
524 				xmlFree (id);
525 			if (cols_array) {
526 				gsize i;
527 				for (i = 0; i < cols_array->len; i++) {
528 					xmlChar *colname;
529 					colname = g_array_index (cols_array, xmlChar*, i);
530 					xmlFree (colname);
531 				}
532 				g_array_free (cols_array, TRUE);
533 			}
534 			break;
535 		}
536 	}
537 
538 	return retval;
539 }
540 
541 /**
542  * data_source_add_dependency
543  * @source: a #DataSource
544  * @table: the name of the referenced table
545  * @id: (allow-none): the ID of the referenced data source, or %NULL if its ID is the same as the table name
546  * @col_name_size: the size of @col_names
547  * @col_names: (allow-none): names of the FK columns involved in the foreign key, or %NULL
548  * @error: a place to store errors, or %NULL
549  *
550  * Adds a dependency on the @table table, only for DATA_SOURCE_TABLE sources
551  */
552 gboolean
553 data_source_add_dependency (DataSource *source, const gchar *table,
554 			    const char *id, gint col_name_size, const gchar **col_names,
555 			    GError **error)
556 {
557 	g_return_val_if_fail (IS_DATA_SOURCE (source), FALSE);
558 	g_return_val_if_fail (table && *table, FALSE);
559 	g_return_val_if_fail (source->priv->source_type == DATA_SOURCE_TABLE, FALSE);
560 	g_return_val_if_fail (source->priv->builder, FALSE);
561 
562 	if (dependency_find (source->priv->dependencies, id ? id : table, table, col_name_size, col_names))
563 		return TRUE;
564 
565 	GdaMetaTable *mtable, *mlinked;
566 	mtable = get_meta_table (source, source->priv->tablename, error);
567 	if (!mtable)
568 		return FALSE;
569 
570 	mlinked = get_meta_table (source, table, error);
571 	if (!mlinked)
572 		return FALSE;
573 
574 	/* find foreign key to linked table */
575 	GdaMetaTableForeignKey *fk = NULL;
576 	GSList *list;
577 	gboolean reverse = FALSE;
578 	for (list = mtable->fk_list; list; list = list->next) {
579 		if (GDA_META_TABLE_FOREIGN_KEY (list->data)->depend_on == GDA_META_DB_OBJECT (mlinked)) {
580 			fk = GDA_META_TABLE_FOREIGN_KEY (list->data);
581 			if (col_names && (col_name_size == fk->cols_nb)) {
582 				gint i;
583 				for (i = 0; i < col_name_size; i++) {
584 					gint j;
585 					for (j = 0; j < col_name_size; j++) {
586 						if (!strcmp (col_names [i], fk->fk_names_array [j]))
587 							break;
588 					}
589 					if (j == col_name_size) {
590 						fk = NULL; /* not this FK */
591 						break;
592 					}
593 				}
594 			}
595 			if (fk)
596 				break;
597 		}
598 	}
599 	if (!fk) {
600 		for (list = mlinked->fk_list; list; list = list->next) {
601 			if (GDA_META_TABLE_FOREIGN_KEY (list->data)->depend_on == GDA_META_DB_OBJECT (mtable)) {
602 				fk = GDA_META_TABLE_FOREIGN_KEY (list->data);
603 				reverse = TRUE;
604 				if (col_names && (col_name_size == fk->cols_nb)) {
605 					gint i;
606 					for (i = 0; i < col_name_size; i++) {
607 						gint j;
608 						for (j = 0; j < col_name_size; j++) {
609 							if (!strcmp (col_names [i],
610 								     fk->fk_names_array [j]))
611 								break;
612 						}
613 						if (j == col_name_size) {
614 							fk = NULL; /* not this FK */
615 							break;
616 						}
617 					}
618 				}
619 				if (fk)
620 					break;
621 			}
622 		}
623 	}
624 	if (!fk) {
625 		g_set_error (error, GDA_TOOLS_ERROR, GDA_TOOLS_INTERNAL_COMMAND_ERROR,
626 			     _("Could not find any foreign key to \"%s\""), table);
627 		return FALSE;
628 	}
629 	else if (fk->cols_nb <= 0) {
630 		g_set_error (error, GDA_TOOLS_ERROR, GDA_TOOLS_INTERNAL_COMMAND_ERROR,
631 			     _("The fields involved in the foreign key to \"%s\" are not known"),
632 			     table);
633 		return FALSE;
634 	}
635 	else if (fk->cols_nb == 1) {
636 		gchar *tmp;
637 		GdaMetaTableColumn *col;
638 		GdaSqlBuilderId id1, id2, id_cond;
639 		if (reverse) {
640 			id1 = gda_sql_builder_add_id (source->priv->builder, fk->ref_pk_names_array [0]);
641 			tmp = g_strdup_printf ("%s@%s", id ? id : table, fk->fk_names_array [0]);
642 
643 			col = GDA_META_TABLE_COLUMN (g_slist_nth_data (mlinked->columns,
644 								       fk->fk_cols_array [0] - 1));
645 			g_assert (col);
646 			id2 = gda_sql_builder_add_param (source->priv->builder, tmp, col->gtype, FALSE);
647 			g_free (tmp);
648 		}
649 		else {
650 			id1 = gda_sql_builder_add_id (source->priv->builder, fk->fk_names_array [0]);
651 			tmp = g_strdup_printf ("%s@%s", id ? id : table, fk->ref_pk_names_array [0]);
652 
653 			col = GDA_META_TABLE_COLUMN (g_slist_nth_data (mlinked->columns,
654 								       fk->ref_pk_cols_array [0] - 1));
655 			g_assert (col);
656 			id2 = gda_sql_builder_add_param (source->priv->builder, tmp, col->gtype, FALSE);
657 			g_free (tmp);
658 			id_cond = gda_sql_builder_add_cond (source->priv->builder,
659 							    GDA_SQL_OPERATOR_TYPE_EQ,
660 							    id1, id2, 0);
661 		}
662 		id_cond = gda_sql_builder_add_cond (source->priv->builder,
663 						    GDA_SQL_OPERATOR_TYPE_EQ,
664 						    id1, id2, 0);
665 		gda_sql_builder_set_where (source->priv->builder, id_cond);
666 	}
667 	else {
668 		gchar *tmp;
669 		gint i;
670 		GdaMetaTableColumn *col;
671 		GdaSqlBuilderId andid;
672 		GdaSqlBuilderId *op_ids;
673 		GdaSqlBuilderId id1, id2;
674 		op_ids = g_new (GdaSqlBuilderId, fk->cols_nb);
675 
676 		for (i = 0; i < fk->cols_nb; i++) {
677 			if (reverse) {
678 				id1 = gda_sql_builder_add_id (source->priv->builder, fk->ref_pk_names_array [i]);
679 				tmp = g_strdup_printf ("%s@%s", id ? id : table, fk->fk_names_array [i]);
680 
681 				col = GDA_META_TABLE_COLUMN (g_slist_nth_data (mlinked->columns,
682 									       fk->fk_cols_array [i] - 1));
683 				g_assert (col);
684 				id2 = gda_sql_builder_add_param (source->priv->builder, tmp, col->gtype, FALSE);
685 				g_free (tmp);
686 			}
687 			else {
688 				id1 = gda_sql_builder_add_id (source->priv->builder, fk->fk_names_array [i]);
689 				tmp = g_strdup_printf ("%s@%s", id ? id : table, fk->ref_pk_names_array [i]);
690 
691 				col = GDA_META_TABLE_COLUMN (g_slist_nth_data (mlinked->columns,
692 									       fk->ref_pk_cols_array [i] - 1));
693 				g_assert (col);
694 				id2 = gda_sql_builder_add_param (source->priv->builder, tmp, col->gtype, FALSE);
695 				g_free (tmp);
696 			}
697 			op_ids [i] = gda_sql_builder_add_cond (source->priv->builder,
698 							       GDA_SQL_OPERATOR_TYPE_EQ,
699 							       id1, id2, 0);
700 		}
701 		andid = gda_sql_builder_add_cond_v (source->priv->builder, GDA_SQL_OPERATOR_TYPE_AND,
702 						    op_ids, fk->cols_nb);
703 		g_free (op_ids);
704 		gda_sql_builder_set_where (source->priv->builder, andid);
705 	}
706 
707 	Dependency *dep = g_new0 (Dependency, 1);
708 	dep->dep_id = g_strdup (id ? id : table);
709 	dep->dep_table = g_strdup (table);
710 	dep->dep_columns = column_names_to_string (col_name_size, col_names);
711 	source->priv->dependencies = g_slist_append (source->priv->dependencies, dep);
712 
713 	compute_stmt_and_params (source);
714 	return TRUE;
715 }
716 
717 
718 /**
719  * data_source_to_xml_node
720  */
721 xmlNodePtr
722 data_source_to_xml_node (DataSource *source)
723 {
724 	xmlNodePtr node = NULL;
725 	g_return_val_if_fail (IS_DATA_SOURCE (source), NULL);
726 	switch (source->priv->source_type) {
727 	case DATA_SOURCE_TABLE:
728 		node = xmlNewNode (NULL, BAD_CAST "table");
729 		if (g_strcmp0 (source->priv->id, source->priv->tablename))
730 			xmlSetProp (node, BAD_CAST "id", BAD_CAST source->priv->id);
731 		if (source->priv->title && g_strcmp0 (source->priv->title, source->priv->tablename))
732 			xmlSetProp (node, BAD_CAST "title", BAD_CAST source->priv->title);
733 		xmlSetProp (node, BAD_CAST "name",
734 			    BAD_CAST (source->priv->tablename ? source->priv->tablename : ""));
735 
736 		if (source->priv->dependencies) {
737 			GSList *list;
738 			for (list = source->priv->dependencies; list; list = list->next) {
739 				Dependency *dep = (Dependency*) list->data;
740 				xmlNodePtr depnode;
741 				depnode = xmlNewChild (node, NULL, BAD_CAST "depend", NULL);
742 				xmlSetProp (depnode, BAD_CAST "foreign_key_table",
743 					    BAD_CAST (dep->dep_table));
744 				xmlSetProp (depnode, BAD_CAST "id",
745 					    BAD_CAST (dep->dep_id));
746 
747 				gchar **array;
748 				gint i;
749 				array = g_strsplit (dep->dep_columns, DEPENDENCY_SEPARATOR, 0);
750 				for (i = 0; array[i]; i++)
751 					xmlNewChild (depnode, NULL, BAD_CAST "column", BAD_CAST (array[i]));
752 				g_strfreev (array);
753 			}
754 		}
755 		break;
756 	case DATA_SOURCE_SELECT: {
757 		node = xmlNewNode (NULL, BAD_CAST "query");
758 		xmlSetProp (node, BAD_CAST "id", BAD_CAST source->priv->id);
759 		if (source->priv->title)
760 			xmlSetProp (node, BAD_CAST "title", BAD_CAST source->priv->title);
761 
762 		if (source->priv->stmt) {
763 			gchar *sql;
764 			sql = gda_statement_to_sql_extended (source->priv->stmt, NULL, NULL,
765 							     GDA_STATEMENT_SQL_PRETTY |
766 							     GDA_STATEMENT_SQL_PARAMS_SHORT, NULL, NULL);
767 			if (sql) {
768 				xmlNodeSetContent (node, BAD_CAST sql);
769 				g_free (sql);
770 			}
771 		}
772 		break;
773 	}
774 	default:
775 		break;
776 	}
777 
778 	if (node) {
779 	}
780 	return node;
781 }
782 
783 static gboolean
784 exec_end_timeout_cb (DataSource *source)
785 {
786 	GObject *obj;
787 
788 	g_return_val_if_fail (source->priv->exec_id > 0, FALSE);
789 
790 	g_clear_error (&source->priv->exec_error);
791 	obj = browser_connection_execution_get_result (source->priv->bcnc,
792 						       source->priv->exec_id,
793 						       NULL,
794 						       &source->priv->exec_error);
795 	if (obj) {
796 		if (GDA_IS_DATA_MODEL (obj)) {
797 			if (source->priv->model != GDA_DATA_MODEL (obj)) {
798 				if (source->priv->model)
799 					g_object_unref (source->priv->model);
800 				source->priv->model = GDA_DATA_MODEL (obj);
801 				g_object_set (source->priv->model, "auto-reset", FALSE, NULL);
802 			}
803 			else {
804 				gda_data_model_thaw (source->priv->model);
805 				gda_data_model_reset (source->priv->model);
806 			}
807 			/*gda_data_model_dump (source->priv->model, NULL);*/
808 		}
809 		else {
810 			g_object_unref (obj);
811 			g_set_error (&source->priv->exec_error, GDA_TOOLS_ERROR, GDA_TOOLS_COMMAND_ARGUMENTS_ERROR,
812 				     "%s", _("Statement to execute is not a selection statement"));
813 		}
814 
815 		source->priv->exec_id = 0;
816 		g_signal_emit (source, data_source_signals [EXEC_FINISHED], 0, source->priv->exec_error);
817 		if (source->priv->exec_again) {
818 			source->priv->exec_again = FALSE;
819 			data_source_execute (source, NULL);
820 		}
821 		return FALSE;
822 	}
823 	else if (source->priv->exec_error) {
824 		source->priv->exec_id = 0;
825 		g_signal_emit (source, data_source_signals [EXEC_FINISHED], 0, source->priv->exec_error);
826 		if (source->priv->exec_again) {
827 			source->priv->exec_again = FALSE;
828 			data_source_execute (source, NULL);
829 		}
830 		return FALSE;
831 	}
832 	else
833 		return TRUE; /* keep timer */
834 }
835 
836 /**
837  *data_source_get_statement
838  */
839 GdaStatement *
840 data_source_get_statement (DataSource *source)
841 {
842 	g_return_val_if_fail (IS_DATA_SOURCE (source), NULL);
843 	return source->priv->stmt;
844 }
845 
846 /**
847  * data_source_execution_going_on
848  */
849 gboolean
850 data_source_execution_going_on (DataSource *source)
851 {
852 	g_return_val_if_fail (IS_DATA_SOURCE (source), FALSE);
853 	return source->priv->executing || (source->priv->exec_id > 0);
854 }
855 
856 /**
857  * data_source_get_import
858  *
859  * Returns: a pointer to a read-only #GdaSet, or %NULL (must not be modified)
860  */
861 GdaSet *
862 data_source_get_import (DataSource *source)
863 {
864 	g_return_val_if_fail (IS_DATA_SOURCE (source), NULL);
865 	return source->priv->params;
866 }
867 
868 /**
869  * data_source_set_params
870  */
871 void
872 data_source_set_params (DataSource *source, GdaSet *params)
873 {
874 	gboolean bound = FALSE;
875 	g_return_if_fail (IS_DATA_SOURCE (source));
876 	g_return_if_fail (!params || GDA_IS_SET (params));
877 
878 	if (source->priv->ext_params) {
879 		g_signal_handlers_disconnect_by_func (source->priv->ext_params,
880 						      G_CALLBACK (ext_params_changed_cb), source);
881 		g_object_unref (source->priv->ext_params);
882 		source->priv->ext_params = NULL;
883 	}
884 
885 	if (source->priv->params) {
886 		GSList *list;
887 		for (list = source->priv->params->holders; list; list = list->next) {
888 			GdaHolder *holder = GDA_HOLDER (list->data);
889 			GdaHolder *bind = NULL;
890 			if (params)
891 				bind = gda_set_get_holder (params, gda_holder_get_id (holder));
892 			if ((holder != bind) && gda_holder_set_bind (holder, bind, NULL))
893 				bound = TRUE;
894 		}
895 	}
896 
897 	if (params && bound) {
898 		source->priv->ext_params = g_object_ref (params);
899 		g_signal_connect (params, "holder-changed",
900 				  G_CALLBACK (ext_params_changed_cb), source);
901 	}
902 }
903 
904 /**
905  * data_source_get_export_names
906  *
907  * Returns: an array of strings (don't modify) or %NULL
908  */
909 GArray *
910 data_source_get_export_names (DataSource *source)
911 {
912 	g_return_val_if_fail (IS_DATA_SOURCE (source), NULL);
913 	return source->priv->export_names;
914 }
915 
916 /**
917  * data_source_get_export_columns
918  *
919  * Returns: a #GHashTable where key is an export name and value is its column number (use GPOINTER_TO_INT)
920  */
921 GHashTable *
922 data_source_get_export_columns (DataSource *source)
923 {
924 	g_return_val_if_fail (IS_DATA_SOURCE (source), NULL);
925 	return source->priv->export_columns;
926 }
927 
928 /**
929  * data_source_execute
930  */
931 void
932 data_source_execute (DataSource *source, GError **error)
933 {
934 	GError *lerror = NULL;
935 	gboolean has_exec = TRUE;
936 	guint exec_id = 0;
937 	g_return_if_fail (IS_DATA_SOURCE (source));
938 
939 	if (source->priv->exec_again)
940 		return;
941 	if (source->priv->executing || (source->priv->exec_id > 0)) {
942 		source->priv->exec_again = TRUE;
943 		return;
944 	}
945 
946 	source->priv->executing = TRUE;
947 	if (! source->priv->stmt) {
948 		if (source->priv->init_error)
949 			g_propagate_error (error, source->priv->init_error);
950 		else
951 			g_set_error (error, GDA_TOOLS_ERROR, GDA_TOOLS_COMMAND_ARGUMENTS_ERROR,
952 				     "%s", _("No SELECT statement to execute"));
953 	}
954 
955 	if (source->priv->model) {
956 		if (source->priv->need_rerun) {
957 			/* freeze source->priv->model to avoid that it emits signals while being in the
958 			 * wrong thread */
959 			source->priv->need_rerun = FALSE;
960 			gda_data_model_freeze (source->priv->model);
961 			exec_id = browser_connection_rerun_select (source->priv->bcnc,
962 								   source->priv->model, &lerror);
963 		}
964 		else
965 			has_exec = FALSE;
966 	}
967 	else
968 		exec_id = browser_connection_execute_statement (source->priv->bcnc,
969 								source->priv->stmt,
970 								source->priv->params,
971 								GDA_STATEMENT_MODEL_RANDOM_ACCESS |
972 								GDA_STATEMENT_MODEL_ALLOW_NOPARAM,
973 								FALSE, &lerror);
974 
975 	if (has_exec) {
976 		g_signal_emit (source, data_source_signals [EXEC_STARTED], 0);
977 		if (! exec_id) {
978 			gda_data_model_thaw (source->priv->model);
979 			gda_data_model_reset (source->priv->model);
980 			g_signal_emit (source, data_source_signals [EXEC_FINISHED], 0, lerror);
981 			g_propagate_error (error, lerror);
982 		}
983 		else {
984 			/* monitor the end of execution */
985 			source->priv->exec_id = exec_id;
986 			g_timeout_add (50, (GSourceFunc) exec_end_timeout_cb, source);
987 		}
988 	}
989 	source->priv->executing = FALSE;
990 }
991 
992 static void
993 action_refresh_cb (GtkAction *action, DataSource *source)
994 {
995 	source->priv->need_rerun = TRUE;
996 	data_source_execute (source, NULL);
997 }
998 
999 /**
1000  * data_source_create_grid
1001  *
1002  * Returns: a new #GdauiRawGrid, or %NULL if an error occurred
1003  */
1004 GtkWidget *
1005 data_source_create_grid (DataSource *source)
1006 {
1007 	g_return_val_if_fail (IS_DATA_SOURCE (source), NULL);
1008 
1009 	if (! source->priv->model)
1010 		return NULL;
1011 
1012 	GtkWidget *fg;
1013 	fg = ui_formgrid_new (source->priv->model, FALSE, GDAUI_DATA_PROXY_INFO_ROW_MODIFY_BUTTONS);
1014 
1015 	/* add a refresh action */
1016 	GtkUIManager *uimanager;
1017 	GtkActionGroup *agroup;
1018 	GtkAction *action;
1019 	guint mid;
1020 
1021 	agroup = gtk_action_group_new ("DSGroup");
1022 	gtk_action_group_set_translation_domain (agroup, GETTEXT_PACKAGE);
1023 	action = gtk_action_new ("Refresh", "Refresh",
1024 				 _("Refresh data"), GTK_STOCK_EXECUTE);
1025 	gtk_action_group_add_action (agroup, action);
1026 	g_signal_connect (G_OBJECT (action), "activate",
1027 			  G_CALLBACK (action_refresh_cb), source);
1028 	g_object_unref (action);
1029 	uimanager = ui_formgrid_get_ui_manager (UI_FORMGRID (fg));
1030 	gtk_ui_manager_insert_action_group (uimanager, agroup, 0);
1031 	g_object_unref (agroup);
1032 
1033 	mid = gtk_ui_manager_new_merge_id (uimanager);
1034 	gtk_ui_manager_add_ui (uimanager, mid, "/ToolBar/RowModifExtension", "Refresh", "Refresh",
1035 			       GTK_UI_MANAGER_AUTO, TRUE);
1036 	gtk_ui_manager_ensure_update (uimanager);
1037 
1038 	return fg;
1039 }
1040 
1041 /**
1042  * data_source_set_id
1043  * @source: a #DataSource
1044  * @id: the new source's ID, not %NULL
1045  *
1046  * @source MUST NOT be executed when calling this method.
1047  */
1048 void
1049 data_source_set_id (DataSource *source, const gchar * id)
1050 {
1051 	g_return_if_fail (IS_DATA_SOURCE (source));
1052 	g_return_if_fail (! data_source_execution_going_on (source));
1053 	g_return_if_fail (id && *id);
1054 
1055 	g_free (source->priv->id);
1056 	source->priv->id = g_strdup (id);
1057 	update_export_information (source);
1058 	g_signal_emit (source, data_source_signals [CHANGED], 0);
1059 }
1060 
1061 
1062 /**
1063  * data_source_get_id
1064  * @source: a #DataSource
1065  *
1066  * Returns: the ID, or %NULL if no ID has been defined
1067  */
1068 const gchar *
1069 data_source_get_id (DataSource *source)
1070 {
1071 	g_return_val_if_fail (IS_DATA_SOURCE (source), NULL);
1072 
1073 	return source->priv->id;
1074 }
1075 
1076 /**
1077  * data_source_set_title
1078  * @source: a #DataSource
1079  * @title: the new source's TITLE
1080  *
1081  * @source MUST NOT be executed when calling this method.
1082  */
1083 void
1084 data_source_set_title (DataSource *source, const gchar * title)
1085 {
1086 	g_return_if_fail (IS_DATA_SOURCE (source));
1087 	g_return_if_fail (! data_source_execution_going_on (source));
1088 
1089 	g_free (source->priv->title);
1090 	if (title)
1091 		source->priv->title = g_strdup (title);
1092 	else
1093 		source->priv->title = NULL;
1094 	g_signal_emit (source, data_source_signals [CHANGED], 0);
1095 }
1096 
1097 /**
1098  * data_source_get_title
1099  * @source: a #DataSource
1100  */
1101 const gchar *
1102 data_source_get_title (DataSource *source)
1103 {
1104 	g_return_val_if_fail (IS_DATA_SOURCE (source), NULL);
1105 
1106 	if (source->priv->title)
1107 		return source->priv->title;
1108 	else if (source->priv->impl_title)
1109 		return source->priv->impl_title;
1110 	else
1111 		return source->priv->id;
1112 }
1113 
1114 static void
1115 update_export_information (DataSource *source)
1116 {
1117 	g_assert (source->priv->id);
1118 
1119 	/* clear previous information */
1120 	if (source->priv->export_names) {
1121 		g_array_free (source->priv->export_names, TRUE);
1122 		source->priv->export_names = NULL;
1123 	}
1124 	if (source->priv->export_columns) {
1125 		g_hash_table_destroy (source->priv->export_columns);
1126 		source->priv->export_columns = NULL;
1127 	}
1128 
1129 	if (! source->priv->stmt)
1130 		return;
1131 
1132 	/* Get GdaSqlStatement */
1133 	GdaSqlStatement *sqlst;
1134 	g_object_get ((GObject*) source->priv->stmt, "structure", &sqlst, NULL);
1135 	if (browser_connection_check_sql_statement_validify (source->priv->bcnc, sqlst, NULL))
1136 		g_object_set ((GObject*) source->priv->stmt, "structure", sqlst, NULL);
1137 	if (! sqlst)
1138 		return;
1139 
1140 	/* compute exported data */
1141 	if (sqlst->stmt_type == GDA_SQL_STATEMENT_SELECT) {
1142 		GdaSqlStatementSelect *selst;
1143 		selst = (GdaSqlStatementSelect*) sqlst->contents;
1144 		GSList *list;
1145 		gint i;
1146 		for (i = 0, list = selst->expr_list; list; i++, list = list->next) {
1147 			gchar *tmp;
1148 			if (! source->priv->export_names)
1149 				source->priv->export_names = g_array_new (FALSE, FALSE,
1150 									  sizeof (gchar*));
1151 			if (! source->priv->export_columns)
1152 				source->priv->export_columns =
1153 					g_hash_table_new_full (g_str_hash, g_str_equal,
1154 							       g_free, NULL);
1155 
1156 			tmp = g_strdup_printf ("%s@%d", source->priv->id, i+1);
1157 			g_array_append_val (source->priv->export_names, tmp);
1158 			g_hash_table_insert (source->priv->export_columns, tmp,
1159 					     GINT_TO_POINTER (i + 1));
1160 #ifdef DEBUG_SOURCE
1161 			g_print ("\tEXPORT [%s]\n", tmp);
1162 #endif
1163 
1164 			GdaSqlSelectField *sf = (GdaSqlSelectField *) list->data;
1165 			if (sf->validity_meta_table_column) {
1166 				tmp = g_strdup_printf ("%s@%s", source->priv->id,
1167 						       sf->validity_meta_table_column->column_name);
1168 				g_array_append_val (source->priv->export_names, tmp);
1169 				g_hash_table_insert (source->priv->export_columns, tmp,
1170 						     GINT_TO_POINTER (i + 1));
1171 #ifdef DEBUG_SOURCE
1172 				g_print ("\tEXPORT [%s]\n", tmp);
1173 #endif
1174 			}
1175 		}
1176 	}
1177 
1178 	gda_sql_statement_free (sqlst);
1179 }
1180 
1181 /**
1182  * data_source_set_table
1183  *
1184  * @source MUST NOT be executed when calling this method.
1185  */
1186 gboolean
1187 data_source_set_table (DataSource *source, const gchar *table, GError **error)
1188 {
1189 	g_return_val_if_fail (IS_DATA_SOURCE (source), FALSE);
1190 	g_return_val_if_fail (! data_source_execution_going_on (source), FALSE);
1191 
1192 	data_source_reset (source);
1193 	if (!table)
1194 		return FALSE;
1195 
1196 	/* locate table */
1197 	GdaMetaTable *mtable;
1198 	mtable = get_meta_table (source, table, error);
1199 	if (!mtable)
1200 		return FALSE;
1201 
1202 	source->priv->source_type = DATA_SOURCE_TABLE;
1203 	source->priv->tablename = g_strdup (table);
1204 
1205 	if (! strcmp (source->priv->id, DEFAULT_DATA_SOURCE_NAME)) {
1206 		g_free (source->priv->id);
1207 		source->priv->id = g_strdup (table);
1208 	}
1209 
1210 	g_free (source->priv->impl_title);
1211 	source->priv->impl_title = g_strdup_printf (_("Contents of '%s'"), table);
1212 
1213 	/* build statement */
1214 	GdaSqlBuilder *b;
1215 	gint i;
1216 	GSList *list;
1217 
1218 	b = gda_sql_builder_new (GDA_SQL_STATEMENT_SELECT);
1219 	source->priv->builder = b;
1220 	if (! gda_sql_builder_select_add_target (b, table, NULL)) {
1221 		g_set_error (error, GDA_TOOLS_ERROR, GDA_TOOLS_INTERNAL_COMMAND_ERROR,
1222 			     "%s", _("Could not build SELECT statement"));
1223 		return FALSE;
1224 	}
1225 	gda_sql_builder_select_set_limit (b,
1226 					  gda_sql_builder_add_expr (b, NULL,
1227 								    G_TYPE_INT, DEFAULT_DATA_SELECT_LIMIT),
1228 					  0);
1229 	for (i = 0, list = mtable->columns; list; i++, list = list->next) {
1230 		GdaMetaTableColumn *mcol;
1231 		mcol = GDA_META_TABLE_COLUMN (list->data);
1232 		gda_sql_builder_select_add_field (b, mcol->column_name, NULL, NULL);
1233 
1234 		if (mcol->pkey) {
1235 			/* ORDER BY */
1236 			gda_sql_builder_select_order_by (b,
1237 							 gda_sql_builder_add_id (b,
1238 										 mcol->column_name),
1239 							 FALSE, NULL);
1240 		}
1241 	}
1242 
1243 	/* compute statement & parameters */
1244 	compute_stmt_and_params (source);
1245 	/*g_print ("SQL [%s]\n", gda_statement_to_sql (source->priv->stmt, NULL, NULL));*/
1246 
1247 	update_export_information (source);
1248 
1249 #ifdef DEBUG_SOURCE
1250 	g_print ("\n");
1251 #endif
1252 
1253 	g_signal_emit (source, data_source_signals [CHANGED], 0);
1254 	return source->priv->stmt ? TRUE : FALSE;
1255 }
1256 
1257 /**
1258  * data_source_set_query
1259  *
1260  * @source MUST NOT be executed when calling this method.
1261  */
1262 void
1263 data_source_set_query (DataSource *source, const gchar *sql, GError **warning)
1264 {
1265 	g_return_if_fail (IS_DATA_SOURCE (source));
1266 	g_return_if_fail (! data_source_execution_going_on (source));
1267 
1268 	data_source_reset (source);
1269 
1270 	source->priv->source_type = DATA_SOURCE_SELECT;
1271 	if (!sql) {
1272 		g_signal_emit (source, data_source_signals [CHANGED], 0);
1273 		return;
1274 	}
1275 
1276 	GdaSqlParser *parser;
1277 	const gchar *remain;
1278 	parser = browser_connection_create_parser (source->priv->bcnc);
1279 	source->priv->stmt = gda_sql_parser_parse_string (parser, sql,
1280 							  &remain, warning);
1281 	g_object_unref (parser);
1282 	if (!source->priv->stmt) {
1283 		g_signal_emit (source, data_source_signals [CHANGED], 0);
1284 		return;
1285 	}
1286 
1287 	if (remain)
1288 		g_set_error (warning, GDA_TOOLS_ERROR, GDA_TOOLS_COMMAND_ARGUMENTS_ERROR,
1289 			     "%s", _("Multiple statements detected, only the first will be used"));
1290 
1291 	/* try to normalize the statement */
1292 	GdaSqlStatement *sqlst;
1293 	g_object_get ((GObject*) source->priv->stmt, "structure", &sqlst, NULL);
1294 	if (browser_connection_normalize_sql_statement (source->priv->bcnc, sqlst, NULL))
1295 		g_object_set ((GObject*) source->priv->stmt, "structure", sqlst, NULL);
1296 	gda_sql_statement_free (sqlst);
1297 
1298 	update_export_information (source);
1299 
1300 	/* compute parameters */
1301 	source->priv->need_rerun = FALSE;
1302 	compute_import_params (source);
1303 
1304 #ifdef DEBUG_SOURCE
1305 	g_print ("\n");
1306 #endif
1307 
1308 	g_signal_emit (source, data_source_signals [CHANGED], 0);
1309 }
1310 
1311 static void
1312 compute_stmt_and_params (DataSource *source)
1313 {
1314 	g_assert (source->priv->builder);
1315 	if (source->priv->stmt)
1316 		g_object_unref (source->priv->stmt);
1317 	source->priv->stmt = gda_sql_builder_get_statement (source->priv->builder, NULL);
1318 	compute_import_params (source);
1319 
1320 #ifdef DEBUG_SOURCE
1321 	gchar *sql;
1322 	sql = gda_statement_to_sql (source->priv->stmt, NULL, NULL);
1323 	g_print ("[%s]\n", sql);
1324 	g_free (sql);
1325 #endif
1326 }
1327 
1328 static void
1329 compute_import_params (DataSource *source)
1330 {
1331 	if (source->priv->params) {
1332 		g_signal_handlers_disconnect_by_func (source->priv->params,
1333 						      G_CALLBACK (params_changed_cb), source);
1334 		g_object_unref (source->priv->params);
1335 		source->priv->params = NULL;
1336 	}
1337 	g_clear_error (& source->priv->init_error);
1338 
1339 	gda_statement_get_parameters (source->priv->stmt, &source->priv->params,
1340 				      &source->priv->init_error);
1341 	if (source->priv->params) {
1342 		GSList *list;
1343 		for (list = source->priv->params->holders; list; list = list->next) {
1344 			gda_holder_set_not_null (GDA_HOLDER (list->data), FALSE);
1345 #ifdef DEBUG_SOURCE
1346 			g_print ("\tIMPORT [%s]\n", gda_holder_get_id (GDA_HOLDER (list->data)));
1347 #endif
1348 		}
1349 
1350 		browser_connection_define_ui_plugins_for_stmt (source->priv->bcnc, source->priv->stmt,
1351 							       source->priv->params);
1352 
1353 		g_signal_connect (source->priv->params, "holder-changed",
1354 				  G_CALLBACK (params_changed_cb), source);
1355 	}
1356 }
1357 
1358 /**
1359  * data_source_get_table
1360  * @source: a #DataSource
1361  *
1362  * Returns: the name of the table used by @source, if its type is %DATA_SOURCE_TABLE
1363  */
1364 const gchar *
1365 data_source_get_table (DataSource *source)
1366 {
1367 	g_return_val_if_fail (IS_DATA_SOURCE (source), NULL);
1368 	return source->priv->tablename;
1369 }
1370 
1371 /**
1372  * data_source_get_source_type
1373  */
1374 DataSourceType
1375 data_source_get_source_type (DataSource *source)
1376 {
1377 	g_return_val_if_fail (IS_DATA_SOURCE (source), DATA_SOURCE_UNKNOWN);
1378 	return source->priv->source_type;
1379 }
1380 
1381 /**
1382  * data_source_should_rerun
1383  *
1384  * The SELECT statement will be re-executed the next time
1385  * data_source_execute() is called
1386  */
1387 void
1388 data_source_should_rerun (DataSource *source)
1389 {
1390 	g_return_if_fail (IS_DATA_SOURCE (source));
1391 	source->priv->need_rerun = TRUE;
1392 }
1393