1 /*
2  * Copyright (C) 2009 - 2010 Murray Cumming <murrayc@murrayc.com>
3  * Copyright (C) 2009 - 2012 Vivien Malerba <malerba@gnome-db.org>
4  * Copyright (C) 2010 David King <davidk@openismus.com>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20 
21 #include <string.h>
22 #include <glib/gi18n-lib.h>
23 #include "tools-favorites.h"
24 #include "tool-utils.h"
25 #include <libgda/thread-wrapper/gda-thread-wrapper.h>
26 #include <libgda/gda-sql-builder.h>
27 #include <sql-parser/gda-sql-parser.h>
28 
29 struct _ToolsFavoritesPrivate {
30 	GdaMetaStore  *store;
31 	GdaConnection *store_cnc;
32 };
33 
34 
35 /*
36  * Main static functions
37  */
38 static void gda_tools_favorites_class_init (ToolsFavoritesClass *klass);
39 static void gda_tools_favorites_init (ToolsFavorites *bfav);
40 static void gda_tools_favorites_dispose (GObject *object);
41 
42 /* get a pointer to the parents to be able to call their destructor */
43 static GObjectClass  *parent_class = NULL;
44 
45 /* signals */
46 enum {
47 	FAV_CHANGED,
48 	LAST_SIGNAL
49 };
50 
51 gint gda_tools_favorites_signals [LAST_SIGNAL] = { 0 };
52 
53 GType
gda_tools_favorites_get_type(void)54 gda_tools_favorites_get_type (void)
55 {
56 	static GType type = 0;
57 
58 	if (G_UNLIKELY (type == 0)) {
59 		static GMutex registering;
60 		static const GTypeInfo info = {
61 			sizeof (ToolsFavoritesClass),
62 			(GBaseInitFunc) NULL,
63 			(GBaseFinalizeFunc) NULL,
64 			(GClassInitFunc) gda_tools_favorites_class_init,
65 			NULL,
66 			NULL,
67 			sizeof (ToolsFavorites),
68 			0,
69 			(GInstanceInitFunc) gda_tools_favorites_init,
70 			0
71 		};
72 
73 
74 		g_mutex_lock (&registering);
75 		if (type == 0)
76 			type = g_type_register_static (G_TYPE_OBJECT, "ToolsFavorites", &info, 0);
77 		g_mutex_unlock (&registering);
78 	}
79 	return type;
80 }
81 
82 static void
gda_tools_favorites_class_init(ToolsFavoritesClass * klass)83 gda_tools_favorites_class_init (ToolsFavoritesClass *klass)
84 {
85 	GObjectClass   *object_class = G_OBJECT_CLASS (klass);
86 	parent_class = g_type_class_peek_parent (klass);
87 
88 	gda_tools_favorites_signals [FAV_CHANGED] =
89 		g_signal_new ("favorites-changed",
90                               G_TYPE_FROM_CLASS (object_class),
91                               G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED,
92                               G_STRUCT_OFFSET (ToolsFavoritesClass, favorites_changed),
93                               NULL, NULL,
94                               g_cclosure_marshal_VOID__VOID, G_TYPE_NONE,
95                               0);
96 
97 	klass->favorites_changed = NULL;
98 
99 	object_class->dispose = gda_tools_favorites_dispose;
100 }
101 
102 static void
gda_tools_favorites_init(ToolsFavorites * bfav)103 gda_tools_favorites_init (ToolsFavorites *bfav)
104 {
105 	bfav->priv = g_new0 (ToolsFavoritesPrivate, 1);
106 	bfav->priv->store = NULL;
107 	bfav->priv->store_cnc = NULL;
108 }
109 
110 static void
gda_tools_favorites_dispose(GObject * object)111 gda_tools_favorites_dispose (GObject *object)
112 {
113 	ToolsFavorites *bfav;
114 
115 	g_return_if_fail (object != NULL);
116 	g_return_if_fail (GDA_TOOLS_IS_FAVORITES (object));
117 
118 	bfav = GDA_TOOLS_FAVORITES (object);
119 	if (bfav->priv) {
120 		if (bfav->priv->store)
121 			g_object_unref (bfav->priv->store);
122 		if (bfav->priv->store_cnc)
123 			g_object_unref (bfav->priv->store_cnc);
124 
125 		g_free (bfav->priv);
126 		bfav->priv = NULL;
127 	}
128 
129 	/* parent class */
130 	parent_class->dispose (object);
131 }
132 
133 /**
134  * gda_tools_favorites_new
135  *
136  * Creates a new #ToolsFavorites object
137  *
138  * Returns: the new object
139  */
140 ToolsFavorites*
gda_tools_favorites_new(GdaMetaStore * store)141 gda_tools_favorites_new (GdaMetaStore *store)
142 {
143 	ToolsFavorites *bfav;
144 
145 	g_return_val_if_fail (GDA_IS_META_STORE (store), NULL);
146 
147 	bfav = GDA_TOOLS_FAVORITES (g_object_new (GDA_TOOLS_TYPE_FAVORITES, NULL));
148 	bfav->priv->store = g_object_ref (store);
149 
150 	return bfav;
151 }
152 
153 #define FAVORITES_TABLE_NAME "gda_sql_favorites"
154 #define FAVORITES_TABLE_DESC						\
155         "<table name=\"" FAVORITES_TABLE_NAME "\"> "			\
156         "   <column name=\"id\" type=\"gint\" pkey=\"TRUE\" autoinc=\"TRUE\"/>"	\
157         "   <column name=\"session\" type=\"gint\"/>"			\
158         "   <column name=\"type\"/>"					\
159         "   <column name=\"name\" nullok=\"TRUE\"/>"			\
160         "   <column name=\"contents\"/>"				\
161         "   <column name=\"descr\" nullok=\"TRUE\"/>"			\
162         "   <unique>"							\
163         "     <column name=\"session\"/>"				\
164         "     <column name=\"type\"/>"					\
165         "     <column name=\"contents\"/>"				\
166         "   </unique>"							\
167         "</table>"
168 #define FAVORDER_TABLE_NAME "gda_sql_favorder"
169 #define FAVORDER_TABLE_DESC						\
170         "<table name=\"" FAVORDER_TABLE_NAME "\"> "			\
171         "   <column name=\"order_key\" type=\"gint\" pkey=\"TRUE\"/>"	\
172         "   <column name=\"fav_id\" type=\"gint\" pkey=\"TRUE\"/>"	\
173         "   <column name=\"rank\" type=\"gint\"/>"			\
174         "</table>"
175 
176 static gboolean
meta_store_addons_init(ToolsFavorites * bfav,GError ** error)177 meta_store_addons_init (ToolsFavorites *bfav, GError **error)
178 {
179 	GError *lerror = NULL;
180 	if (bfav->priv->store_cnc)
181 		return TRUE;
182 
183 	if (!gda_meta_store_schema_add_custom_object (bfav->priv->store, FAVORITES_TABLE_DESC, &lerror)) {
184                 g_set_error (error, GDA_TOOLS_ERROR, GDA_TOOLS_STORED_DATA_ERROR,
185 			     "%s", _("Can't initialize dictionary to store favorites"));
186 		g_warning ("Can't initialize dictionary to store favorites :%s",
187 			   lerror && lerror->message ? lerror->message : "No detail");
188 		if (lerror)
189 			g_error_free (lerror);
190                 return FALSE;
191         }
192 	if (!gda_meta_store_schema_add_custom_object (bfav->priv->store, FAVORDER_TABLE_DESC, &lerror)) {
193                 g_set_error (error, GDA_TOOLS_ERROR, GDA_TOOLS_STORED_DATA_ERROR,
194 			     "%s", _("Can't initialize dictionary to store favorites"));
195 		g_warning ("Can't initialize dictionary to store favorites :%s",
196 			   lerror && lerror->message ? lerror->message : "No detail");
197 		if (lerror)
198 			g_error_free (lerror);
199                 return FALSE;
200         }
201 
202 	bfav->priv->store_cnc = g_object_ref (gda_meta_store_get_internal_connection (bfav->priv->store));
203 	return TRUE;
204 }
205 
206 /**
207  * gda_tools_favorites_type_to_string:
208  * @type: a #ToolsFavoritesType
209  *
210  * Returns: a string representing @type
211  */
212 const gchar *
gda_tools_favorites_type_to_string(ToolsFavoritesType type)213 gda_tools_favorites_type_to_string (ToolsFavoritesType type)
214 {
215 	switch (type) {
216 	case GDA_TOOLS_FAVORITES_TABLES:
217 		return "TABLE";
218 	case GDA_TOOLS_FAVORITES_DIAGRAMS:
219 		return "DIAGRAM";
220 	case GDA_TOOLS_FAVORITES_QUERIES:
221 		return "QUERY";
222 	case GDA_TOOLS_FAVORITES_DATA_MANAGERS:
223 		return "DATAMAN";
224 	case GDA_TOOLS_FAVORITES_ACTIONS:
225 		return "ACTION";
226 	case GDA_TOOLS_FAVORITES_LDAP_DN:
227 		return "LDAP_DN";
228 	case GDA_TOOLS_FAVORITES_LDAP_CLASS:
229 		return "LDAP_CLASS";
230 	default:
231 		g_warning ("Unknown type of favorite");
232 	}
233 
234 	return "";
235 }
236 
237 static ToolsFavoritesType
favorite_string_to_type(const gchar * str)238 favorite_string_to_type (const gchar *str)
239 {
240 	if (*str == 'T')
241 		return GDA_TOOLS_FAVORITES_TABLES;
242 	else if (*str == 'D') {
243 		if (str[1] == 'I')
244 			return GDA_TOOLS_FAVORITES_DIAGRAMS;
245 		else
246 			return GDA_TOOLS_FAVORITES_DATA_MANAGERS;
247 	}
248 	else if (*str == 'Q')
249 		return GDA_TOOLS_FAVORITES_QUERIES;
250 	else if (*str == 'A')
251 		return GDA_TOOLS_FAVORITES_ACTIONS;
252 	else if (*str == 'L') {
253 		if (strlen (str) == 7)
254 			return GDA_TOOLS_FAVORITES_LDAP_DN;
255 		else
256 			return GDA_TOOLS_FAVORITES_LDAP_CLASS;
257 	}
258 	else
259 		g_warning ("Unknown type '%s' of favorite", str);
260 	return 0;
261 }
262 
263 static gint
find_favorite_position(ToolsFavorites * bfav,gint fav_id,gint order_key)264 find_favorite_position (ToolsFavorites *bfav, gint fav_id, gint order_key)
265 {
266 	GdaSqlBuilder *b;
267 	GdaStatement *stmt;
268 	GdaSet *params = NULL;
269 	GdaDataModel *model;
270 	gint pos = -1;
271 
272 	g_return_val_if_fail (fav_id >= 0, -1);
273 
274 	b = gda_sql_builder_new (GDA_SQL_STATEMENT_SELECT);
275 	gda_sql_builder_add_field_value_id (b,
276 					    gda_sql_builder_add_id (b, "rank"), 0);
277 	gda_sql_builder_select_add_target (b, FAVORDER_TABLE_NAME, NULL);
278 	gda_sql_builder_set_where (b,
279 				   gda_sql_builder_add_cond (b, GDA_SQL_OPERATOR_TYPE_AND,
280 							     gda_sql_builder_add_cond (b, GDA_SQL_OPERATOR_TYPE_EQ,
281 										       gda_sql_builder_add_id (b, "fav_id"),
282 										       gda_sql_builder_add_param (b, "favid", G_TYPE_INT, FALSE), 0),
283 							     gda_sql_builder_add_cond (b, GDA_SQL_OPERATOR_TYPE_EQ,
284 										       gda_sql_builder_add_id (b, "order_key"),
285 										       gda_sql_builder_add_param (b, "okey", G_TYPE_INT, FALSE), 0),
286 							     0));
287 
288 	stmt = gda_sql_builder_get_statement (b, NULL);
289 	g_object_unref (G_OBJECT (b));
290 	if (!stmt)
291 		return -1;
292 	params = gda_set_new_inline (2,
293 				     "favid", G_TYPE_INT, fav_id,
294 				     "okey", G_TYPE_INT, order_key);
295 	model = gda_connection_statement_execute_select (bfav->priv->store_cnc, stmt, params, NULL);
296 	g_object_unref (stmt);
297 	g_object_unref (params);
298 
299 	if (!model)
300 		return -1;
301 
302 	gint nrows;
303 	nrows = gda_data_model_get_n_rows (model);
304 	if (nrows == 1) {
305 		const GValue *cvalue;
306 		cvalue = gda_data_model_get_value_at (model, 0, 0, NULL);
307 		if (cvalue)
308 			pos = g_value_get_int (cvalue);
309 	}
310 
311 	g_object_unref (G_OBJECT (model));
312 	return pos;
313 }
314 
315 static gint
find_favorite_by_name(ToolsFavorites * bfav,guint session_id,const gchar * name,ToolsFavoritesType type,ToolsFavoritesAttributes * out_existing_fav,GError ** error)316 find_favorite_by_name (ToolsFavorites *bfav, guint session_id, const gchar *name, ToolsFavoritesType type,
317 		       ToolsFavoritesAttributes *out_existing_fav, GError **error)
318 {
319 	GdaSqlBuilder *b;
320 	GdaStatement *stmt;
321 	GdaSet *params = NULL;
322 	GdaDataModel *model;
323 	gint favid = -1;
324 
325 	if (out_existing_fav)
326 		memset (out_existing_fav, 0, sizeof (ToolsFavoritesAttributes));
327 	g_return_val_if_fail (name, -1);
328 
329 	b = gda_sql_builder_new (GDA_SQL_STATEMENT_SELECT);
330 	gda_sql_builder_add_field_value_id (b,
331 					    gda_sql_builder_add_id (b, "id"), 0);
332 	gda_sql_builder_add_field_value_id (b,
333 					    gda_sql_builder_add_id (b, "type"), 0);
334 	gda_sql_builder_add_field_value_id (b,
335 					    gda_sql_builder_add_id (b, "name"), 0);
336 	gda_sql_builder_add_field_value_id (b,
337 					    gda_sql_builder_add_id (b, "descr"), 0);
338 	gda_sql_builder_add_field_value_id (b,
339 					    gda_sql_builder_add_id (b, "contents"), 0);
340 	gda_sql_builder_select_add_target (b, FAVORITES_TABLE_NAME, NULL);
341 	gda_sql_builder_set_where (b,
342 				   gda_sql_builder_add_cond (b, GDA_SQL_OPERATOR_TYPE_AND,
343 							     gda_sql_builder_add_cond (b, GDA_SQL_OPERATOR_TYPE_EQ,
344 										       gda_sql_builder_add_id (b, "session"),
345 										       gda_sql_builder_add_param (b, "session", G_TYPE_INT, FALSE), 0),
346 							     gda_sql_builder_add_cond (b, GDA_SQL_OPERATOR_TYPE_EQ,
347 										       gda_sql_builder_add_id (b, "name"),
348 										       gda_sql_builder_add_param (b, "name", G_TYPE_INT, FALSE), 0),
349 							     gda_sql_builder_add_cond (b, GDA_SQL_OPERATOR_TYPE_EQ,
350 										       gda_sql_builder_add_id (b, "type"),
351 										       gda_sql_builder_add_param (b, "type", G_TYPE_STRING, FALSE), 0)));
352 
353  	stmt = gda_sql_builder_get_statement (b, error);
354 	g_object_unref (G_OBJECT (b));
355 	if (!stmt)
356 		return -1;
357 	params = gda_set_new_inline (3,
358 				     "session", G_TYPE_INT, session_id,
359 				     "type", G_TYPE_STRING, gda_tools_favorites_type_to_string (type),
360 				     "name", G_TYPE_STRING, name);
361 	model = gda_connection_statement_execute_select (bfav->priv->store_cnc, stmt, params, error);
362 	g_object_unref (stmt);
363 	g_object_unref (params);
364 
365 	if (model && gda_data_model_get_n_rows (model) == 1) {
366 		const GValue *cvalue;
367 		cvalue = gda_data_model_get_value_at (model, 0, 0, NULL);
368 		if (cvalue && (G_VALUE_TYPE (cvalue) == G_TYPE_INT))
369 			favid = g_value_get_int (cvalue);
370 
371 		if (out_existing_fav) {
372 			out_existing_fav->id = favid;
373 			cvalue = gda_data_model_get_value_at (model, 1, 0, error);
374 			if (cvalue)
375 				out_existing_fav->type = favorite_string_to_type (g_value_get_string (cvalue));
376 			cvalue = gda_data_model_get_value_at (model, 2, 0, error);
377 			if (cvalue && (G_VALUE_TYPE (cvalue) == G_TYPE_STRING))
378 				out_existing_fav->name = g_value_dup_string (cvalue);
379 			cvalue = gda_data_model_get_value_at (model, 3, 0, error);
380 			if (cvalue && (G_VALUE_TYPE (cvalue) == G_TYPE_STRING))
381 				out_existing_fav->descr = g_value_dup_string (cvalue);
382 			cvalue = gda_data_model_get_value_at (model, 4, 0, error);
383 			if (cvalue && (G_VALUE_TYPE (cvalue) == G_TYPE_STRING))
384 				out_existing_fav->contents = g_value_dup_string (cvalue);
385 		}
386 	}
387 	if (model)
388 		g_object_unref (model);
389 	return favid;
390 }
391 
392 /*
393  * Find a favorite ID from its ID or from its contents
394  *
395  * Returns: the ID or -1 if not found (and sets ERROR).
396  *
397  * if @out_existing_fav is not %NULL, then its attributes are set, use gda_tools_favorites_reset_attributes()
398  * to free.
399  */
400 static gint
find_favorite(ToolsFavorites * bfav,guint session_id,gint id,const gchar * contents,ToolsFavoritesAttributes * out_existing_fav,GError ** error)401 find_favorite (ToolsFavorites *bfav, guint session_id, gint id, const gchar *contents,
402 	       ToolsFavoritesAttributes *out_existing_fav, GError **error)
403 {
404 	GdaSqlBuilder *b;
405 	GdaStatement *stmt;
406 	GdaSet *params = NULL;
407 	GdaDataModel *model;
408 	gint favid = -1;
409 
410 	if (out_existing_fav)
411 		memset (out_existing_fav, 0, sizeof (ToolsFavoritesAttributes));
412 	g_return_val_if_fail ((id >= 0) || contents, -1);
413 
414 	b = gda_sql_builder_new (GDA_SQL_STATEMENT_SELECT);
415 	gda_sql_builder_add_field_value_id (b,
416 					    gda_sql_builder_add_id (b, "id"), 0);
417 	gda_sql_builder_add_field_value_id (b,
418 					    gda_sql_builder_add_id (b, "type"), 0);
419 	gda_sql_builder_add_field_value_id (b,
420 					    gda_sql_builder_add_id (b, "name"), 0);
421 	gda_sql_builder_add_field_value_id (b,
422 					    gda_sql_builder_add_id (b, "descr"), 0);
423 	gda_sql_builder_add_field_value_id (b,
424 					    gda_sql_builder_add_id (b, "contents"), 0);
425 	gda_sql_builder_select_add_target (b, FAVORITES_TABLE_NAME, NULL);
426 
427 	if (id >= 0) {
428 		/* lookup from ID */
429 		gda_sql_builder_set_where (b,
430 					   gda_sql_builder_add_cond (b, GDA_SQL_OPERATOR_TYPE_EQ,
431 								     gda_sql_builder_add_id (b, "id"),
432 								     gda_sql_builder_add_param (b, "id", G_TYPE_INT, FALSE), 0));
433 	}
434 	else {
435 		/* lookup using session and contents */
436 		gda_sql_builder_set_where (b,
437 					   gda_sql_builder_add_cond (b, GDA_SQL_OPERATOR_TYPE_AND,
438 								     gda_sql_builder_add_cond (b, GDA_SQL_OPERATOR_TYPE_EQ,
439 											       gda_sql_builder_add_id (b, "session"),
440 											       gda_sql_builder_add_param (b, "session", G_TYPE_INT, FALSE), 0),
441 								     gda_sql_builder_add_cond (b, GDA_SQL_OPERATOR_TYPE_EQ,
442 											       gda_sql_builder_add_id (b, "contents"),
443 											       gda_sql_builder_add_param (b, "contents", G_TYPE_INT, FALSE), 0), 0));
444 	}
445  	stmt = gda_sql_builder_get_statement (b, error);
446 	g_object_unref (G_OBJECT (b));
447 	if (!stmt)
448 		return -1;
449 	params = gda_set_new_inline (3,
450 				     "session", G_TYPE_INT, session_id,
451 				     "id", G_TYPE_INT, id,
452 				     "contents", G_TYPE_STRING, contents);
453 	model = gda_connection_statement_execute_select (bfav->priv->store_cnc, stmt, params, error);
454 	g_object_unref (stmt);
455 	g_object_unref (params);
456 
457 	if (!model)
458 		return -1;
459 
460 	gint nrows;
461 	nrows = gda_data_model_get_n_rows (model);
462 	if (nrows == 1) {
463 		const GValue *cvalue;
464 		cvalue = gda_data_model_get_value_at (model, 0, 0, error);
465 		if (cvalue)
466 			favid = g_value_get_int (cvalue);
467 		if (out_existing_fav) {
468 			out_existing_fav->id = favid;
469 			cvalue = gda_data_model_get_value_at (model, 1, 0, error);
470 			if (cvalue)
471 				out_existing_fav->type = favorite_string_to_type (g_value_get_string (cvalue));
472 			cvalue = gda_data_model_get_value_at (model, 2, 0, error);
473 			if (cvalue && (G_VALUE_TYPE (cvalue) == G_TYPE_STRING))
474 				out_existing_fav->name = g_value_dup_string (cvalue);
475 			cvalue = gda_data_model_get_value_at (model, 3, 0, error);
476 			if (cvalue && (G_VALUE_TYPE (cvalue) == G_TYPE_STRING))
477 				out_existing_fav->descr = g_value_dup_string (cvalue);
478 			cvalue = gda_data_model_get_value_at (model, 4, 0, error);
479 			if (cvalue && (G_VALUE_TYPE (cvalue) == G_TYPE_STRING))
480 				out_existing_fav->contents = g_value_dup_string (cvalue);
481 		}
482 	}
483 
484 	g_object_unref (G_OBJECT (model));
485 	return favid;
486 }
487 
488 /*
489  * Reorders the favorites for @order_key, making sure @id is at position @new_pos
490  */
491 static gboolean
favorites_reorder(ToolsFavorites * bfav,gint order_key,gint id,gint new_pos,GError ** error)492 favorites_reorder (ToolsFavorites *bfav, gint order_key, gint id, gint new_pos, GError **error)
493 {
494 	GdaSqlBuilder *b;
495 	GdaStatement *stmt;
496 	GdaSet *params = NULL;
497 	GdaDataModel *model;
498 
499 	g_assert (id >= 0);
500 	g_assert (order_key >= 0);
501 
502 	b = gda_sql_builder_new (GDA_SQL_STATEMENT_SELECT);
503 	gda_sql_builder_add_field_value_id (b, gda_sql_builder_add_id (b, "fav_id"), 0);
504 
505 	gda_sql_builder_select_add_target (b, FAVORDER_TABLE_NAME, NULL);
506 
507 	gda_sql_builder_set_where (b, gda_sql_builder_add_cond (b, GDA_SQL_OPERATOR_TYPE_EQ,
508 								gda_sql_builder_add_id (b, "order_key"),
509 								gda_sql_builder_add_param (b, "orderkey", G_TYPE_INT, FALSE), 0));
510 	gda_sql_builder_select_order_by (b,
511 					 gda_sql_builder_add_id (b, "rank"), TRUE, NULL);
512 	stmt = gda_sql_builder_get_statement (b, error);
513 	g_object_unref (G_OBJECT (b));
514 	if (!stmt)
515 		return FALSE;
516 	params = gda_set_new_inline (3,
517 				     "orderkey", G_TYPE_INT, order_key,
518 				     "rank", G_TYPE_INT, 0,
519 				     "id", G_TYPE_INT, id);
520 	model = gda_connection_statement_execute_select (bfav->priv->store_cnc, stmt, params, error);
521 	g_object_unref (stmt);
522 	if (!model) {
523 		g_object_unref (params);
524 		return FALSE;
525 	}
526 
527 	gint i, nrows;
528 	gboolean retval = TRUE;
529 	nrows = gda_data_model_get_n_rows (model);
530 	if (new_pos < 0)
531 		new_pos = 0;
532 	else if (new_pos > nrows)
533 		new_pos = nrows;
534 
535 	b = gda_sql_builder_new (GDA_SQL_STATEMENT_UPDATE);
536 	gda_sql_builder_set_table (b, FAVORDER_TABLE_NAME);
537 	gda_sql_builder_add_field_value_id (b,
538 					    gda_sql_builder_add_id (b, "rank"),
539 					    gda_sql_builder_add_param (b, "rank", G_TYPE_INT, FALSE));
540 	const GdaSqlBuilderId id_cond1 = gda_sql_builder_add_cond (b, GDA_SQL_OPERATOR_TYPE_EQ,
541 								   gda_sql_builder_add_id (b, "fav_id"),
542 								   gda_sql_builder_add_param (b, "id", G_TYPE_INT, FALSE),
543 								   0);
544 	const GdaSqlBuilderId id_cond2 = gda_sql_builder_add_cond (b, GDA_SQL_OPERATOR_TYPE_EQ,
545 								   gda_sql_builder_add_id (b, "order_key"),
546 								   gda_sql_builder_add_param (b, "orderkey", G_TYPE_INT, FALSE),
547 								   0);
548 	gda_sql_builder_set_where (b, gda_sql_builder_add_cond (b, GDA_SQL_OPERATOR_TYPE_AND, id_cond1, id_cond2, 0));
549 	stmt = gda_sql_builder_get_statement (b, error);
550 	if (!stmt) {
551 		retval = FALSE;
552 		goto out;
553 	}
554 
555 	/* reodering the rows */
556 	for (i = 0; i < nrows; i++) {
557 		const GValue *v;
558 		v = gda_data_model_get_value_at (model, 0, i, error);
559 		if (v) {
560 			g_assert (gda_holder_set_value (gda_set_get_holder (params, "id"), v, NULL));
561 			if (g_value_get_int (v) == id)
562 				g_assert (gda_set_set_holder_value (params, NULL, "rank", new_pos));
563 			else
564 				g_assert (gda_set_set_holder_value (params, NULL, "rank", i < new_pos ? i : i + 1));
565 			if (gda_connection_statement_execute_non_select (bfav->priv->store_cnc, stmt,
566 									 params, NULL, error) == -1) {
567 				retval = FALSE;
568 				goto out;
569 			}
570 		}
571 		else {
572 			retval = FALSE;
573 			goto out;
574 		}
575 	}
576 
577  out:
578 	g_object_unref (b);
579 	g_object_unref (params);
580 	g_object_unref (model);
581 	if (stmt)
582 		g_object_unref (stmt);
583 	return retval;
584 }
585 
586 /**
587  * gda_tools_favorites_add
588  * @bfav: a #ToolsFavorites object
589  * @session_id: session ID (0)
590  * @fav: a pointer to a #ToolsFavoritesAttributes structure
591  * @order_key: ordering key or -1 for none
592  * @pos: position (ignored if @order_key < 0)
593  * @error: a place to store errors, or %NULL
594  *
595  * Add a new favorite, or replace an existing one.
596  * NOTE:
597  * <itemizedlist>
598  *   <listitem><para>if @fav->id is < 0 then it's either an update or an insert (depending if fav->contents exists)
599  *     and if it's not it is an INSERT </para></listitem>
600  *   <listitem><para>@fav->type can't be 0</para></listitem>
601  *   <listitem><para>@fav->contents can't be %NULL</para></listitem>
602  * </itemizedlist>
603  *
604  * On success @fav->id contains the favorite's ID, otherwise it will contain -1.
605  *
606  * if @order_key is negative, then no ordering is done and @pos is ignored.
607  */
608 gboolean
gda_tools_favorites_add(ToolsFavorites * bfav,guint session_id,ToolsFavoritesAttributes * fav,gint order_key,gint pos,GError ** error)609 gda_tools_favorites_add (ToolsFavorites *bfav, guint session_id,
610 		     ToolsFavoritesAttributes *fav,
611 		     gint order_key, gint pos,
612 		     GError **error)
613 {
614 	GdaConnection *store_cnc;
615 	GdaSet *params = NULL;
616 	gint favid = -1;
617 	ToolsFavoritesAttributes efav; /* existing favorite */
618 
619 	g_return_val_if_fail (GDA_TOOLS_IS_FAVORITES (bfav), FALSE);
620 	g_return_val_if_fail (fav, FALSE);
621 	g_return_val_if_fail (fav->contents, FALSE);
622 
623 	if (! meta_store_addons_init (bfav, error))
624 		return FALSE;
625 
626 	store_cnc = bfav->priv->store_cnc;
627 	if (! gda_lockable_trylock (GDA_LOCKABLE (store_cnc))) {
628 		g_set_error (error, GDA_TOOLS_ERROR, GDA_TOOLS_STORED_DATA_ERROR,
629 			     "%s", _("Can't initialize transaction to access favorites"));
630 		return FALSE;
631 	}
632 	/* begin a transaction */
633 	if (! gda_connection_begin_transaction (store_cnc, NULL, GDA_TRANSACTION_ISOLATION_UNKNOWN, NULL)) {
634 		g_set_error (error, GDA_TOOLS_ERROR, GDA_TOOLS_STORED_DATA_ERROR,
635 			     "%s", _("Can't initialize transaction to access favorites"));
636 		gda_lockable_unlock (GDA_LOCKABLE (store_cnc));
637                 return FALSE;
638 	}
639 
640 	gint rtype;
641 	favid = find_favorite (bfav, session_id, fav->id, fav->contents, &efav, NULL);
642 	rtype = fav->type;
643 	if (efav.type)
644 		rtype = efav.type;
645 	if ((favid != -1) && (pos == G_MAXINT)) {
646 		/* find current position */
647 		pos = find_favorite_position (bfav, favid, order_key);
648 	}
649 	params = gda_set_new_inline (8,
650 				     "session", G_TYPE_INT, session_id,
651 				     "id", G_TYPE_INT, fav->id,
652 				     "type", G_TYPE_STRING, gda_tools_favorites_type_to_string (rtype),
653 				     "name", G_TYPE_STRING, fav->name ? fav->name : efav.name,
654 				     "contents", G_TYPE_STRING, fav->contents,
655 				     "rank", G_TYPE_INT, pos,
656 				     "orderkey", G_TYPE_INT, order_key,
657 				     "descr", G_TYPE_STRING, fav->descr ? fav->descr : efav.descr);
658 
659 	if (favid == -1) {
660 		/* insert a favorite */
661 		GdaSqlBuilder *builder;
662 		GdaStatement *stmt;
663 
664 		g_return_val_if_fail (fav->type, FALSE);
665 		builder = gda_sql_builder_new (GDA_SQL_STATEMENT_INSERT);
666 		gda_sql_builder_set_table (builder, FAVORITES_TABLE_NAME);
667 
668 		gda_sql_builder_add_field_value_id (builder,
669 						    gda_sql_builder_add_id (builder, "session"),
670 						    gda_sql_builder_add_param (builder, "session", G_TYPE_INT, FALSE));
671 		gda_sql_builder_add_field_value_id (builder,
672 						    gda_sql_builder_add_id (builder, "type"),
673 						    gda_sql_builder_add_param (builder, "type", G_TYPE_INT, FALSE));
674 		gda_sql_builder_add_field_value_id (builder,
675 						    gda_sql_builder_add_id (builder, "name"),
676 						    gda_sql_builder_add_param (builder, "name", G_TYPE_STRING, TRUE));
677 		gda_sql_builder_add_field_value_id (builder,
678 						    gda_sql_builder_add_id (builder, "contents"),
679 						    gda_sql_builder_add_param (builder, "contents", G_TYPE_STRING, FALSE));
680 		gda_sql_builder_add_field_value_id (builder,
681 						    gda_sql_builder_add_id (builder, "descr"),
682 						    gda_sql_builder_add_param (builder, "descr", G_TYPE_STRING, TRUE));
683 		stmt = gda_sql_builder_get_statement (builder, error);
684 		g_object_unref (G_OBJECT (builder));
685 		if (!stmt)
686 			goto err;
687 		if (gda_connection_statement_execute_non_select (store_cnc, stmt, params, NULL, error) == -1) {
688 			g_object_unref (stmt);
689 			goto err;
690 		}
691 		g_object_unref (stmt);
692 
693 		favid = find_favorite (bfav, session_id, fav->id, fav->contents, &efav, NULL);
694 		fav->id = favid;
695 	}
696 	else {
697 		/* update favorite's contents */
698 		GdaSqlBuilder *builder;
699 		GdaStatement *stmt;
700 
701 		gda_set_set_holder_value (params, NULL, "id", favid);
702 		builder = gda_sql_builder_new (GDA_SQL_STATEMENT_UPDATE);
703 		gda_sql_builder_set_table (builder, FAVORITES_TABLE_NAME);
704 
705 		gda_sql_builder_add_field_value_id (builder,
706 						    gda_sql_builder_add_id (builder, "name"),
707 						    gda_sql_builder_add_param (builder, "name", G_TYPE_STRING, TRUE));
708 		gda_sql_builder_add_field_value_id (builder,
709 						    gda_sql_builder_add_id (builder, "contents"),
710 						    gda_sql_builder_add_param (builder, "contents", G_TYPE_STRING, FALSE));
711 		gda_sql_builder_add_field_value_id (builder,
712 						    gda_sql_builder_add_id (builder, "descr"),
713 						    gda_sql_builder_add_param (builder, "descr", G_TYPE_STRING, TRUE));
714 
715 		gda_sql_builder_set_where (builder,
716 					   gda_sql_builder_add_cond (builder, GDA_SQL_OPERATOR_TYPE_EQ,
717 								     gda_sql_builder_add_id (builder, "id"),
718 								     gda_sql_builder_add_param (builder, "id", G_TYPE_INT, FALSE),
719 								     0));
720 		if (fav->id == favid) {
721 			/* alter name and description only if fav->id was OK */
722 			gda_sql_builder_add_field_value_id (builder,
723 							    gda_sql_builder_add_id (builder, "name"),
724 							    gda_sql_builder_add_param (builder, "name", G_TYPE_STRING,
725 										       TRUE));
726 			gda_sql_builder_add_field_value_id (builder,
727 							    gda_sql_builder_add_id (builder, "descr"),
728 							    gda_sql_builder_add_param (builder, "descr", G_TYPE_STRING,
729 										       TRUE));
730 		}
731 
732 		stmt = gda_sql_builder_get_statement (builder, error);
733 		g_object_unref (G_OBJECT (builder));
734 		if (!stmt)
735 			goto err;
736 		if (gda_connection_statement_execute_non_select (store_cnc, stmt, params, NULL, error) == -1) {
737 			g_object_unref (stmt);
738 			goto err;
739 		}
740 		g_object_unref (stmt);
741 		fav->id = favid;
742 	}
743 	gda_tools_favorites_reset_attributes (&efav);
744 
745 	if (order_key >= 0) {
746 		GdaSqlBuilder *builder;
747 		GdaStatement *stmt;
748 
749 		/* delete and insert favorite in orders table */
750 		favid = find_favorite (bfav, session_id, fav->id, fav->contents, NULL, error);
751 		if (favid < 0) {
752 			g_warning ("Could not identify favorite by its ID, make sure it's correct");
753 			goto err;
754 		}
755 
756 		gda_set_set_holder_value (params, NULL, "id", favid);
757 
758 		builder = gda_sql_builder_new (GDA_SQL_STATEMENT_DELETE);
759 		gda_sql_builder_set_table (builder, FAVORDER_TABLE_NAME);
760 		gda_sql_builder_set_where (builder,
761 					   gda_sql_builder_add_cond (builder, GDA_SQL_OPERATOR_TYPE_AND,
762 								     gda_sql_builder_add_cond (builder, GDA_SQL_OPERATOR_TYPE_EQ,
763 											       gda_sql_builder_add_id (builder, "fav_id"),
764 											       gda_sql_builder_add_param (builder, "id", G_TYPE_INT, FALSE),
765 											       0),
766 								     gda_sql_builder_add_cond (builder, GDA_SQL_OPERATOR_TYPE_EQ,
767 											       gda_sql_builder_add_id (builder, "order_key"),
768 											       gda_sql_builder_add_param (builder, "orderkey", G_TYPE_INT, FALSE),
769 											       0), 0));
770 		stmt = gda_sql_builder_get_statement (builder, error);
771 		g_object_unref (G_OBJECT (builder));
772 		if (!stmt)
773 			goto err;
774 		if (gda_connection_statement_execute_non_select (store_cnc, stmt, params, NULL, error) == -1) {
775 			g_object_unref (stmt);
776 			goto err;
777 		}
778 		g_object_unref (stmt);
779 
780 		builder = gda_sql_builder_new (GDA_SQL_STATEMENT_INSERT);
781 		gda_sql_builder_set_table (builder, FAVORDER_TABLE_NAME);
782 		gda_sql_builder_add_field_value_id (builder,
783 						    gda_sql_builder_add_id (builder, "fav_id"),
784 						    gda_sql_builder_add_param (builder, "id", G_TYPE_INT, FALSE));
785 		gda_sql_builder_add_field_value_id (builder,
786 						    gda_sql_builder_add_id (builder, "rank"),
787 						    gda_sql_builder_add_param (builder, "rank", G_TYPE_INT, FALSE));
788 		gda_sql_builder_add_field_value_id (builder,
789 						    gda_sql_builder_add_id (builder, "order_key"),
790 						    gda_sql_builder_add_param (builder, "orderkey", G_TYPE_STRING, TRUE));
791 		stmt = gda_sql_builder_get_statement (builder, error);
792 		g_object_unref (G_OBJECT (builder));
793 		if (!stmt)
794 			goto err;
795 		if (gda_connection_statement_execute_non_select (store_cnc, stmt, params, NULL, error) == -1) {
796 			g_object_unref (stmt);
797 			goto err;
798 		}
799 		g_object_unref (stmt);
800 
801 		/* reorder */
802 		if (!favorites_reorder (bfav, order_key, favid, pos, error))
803 			goto err;
804 	}
805 
806 	if (! gda_connection_commit_transaction (store_cnc, NULL, NULL)) {
807 		g_set_error (error, GDA_TOOLS_ERROR, GDA_TOOLS_STORED_DATA_ERROR,
808 			     "%s", _("Can't commit transaction to access favorites"));
809 		goto err;
810 	}
811 
812 	if (params)
813 		g_object_unref (params);
814 	gda_lockable_unlock (GDA_LOCKABLE (store_cnc));
815 	g_signal_emit (bfav, gda_tools_favorites_signals [FAV_CHANGED],
816 		       g_quark_from_string (gda_tools_favorites_type_to_string (rtype)));
817 	return TRUE;
818 
819  err:
820 	if (params)
821 		g_object_unref (params);
822 	gda_lockable_unlock (GDA_LOCKABLE (store_cnc));
823 	gda_connection_rollback_transaction (store_cnc, NULL, NULL);
824 	return FALSE;
825 }
826 
827 /**
828  * gda_tools_favorites_free_list
829  * @fav_list: a list of #ToolsFavoritesAttributes
830  *
831  * Frees all the #ToolsFavoritesAttributes of the @fav_list list, and frees the list
832  * itself.
833  */
834 void
gda_tools_favorites_free_list(GSList * fav_list)835 gda_tools_favorites_free_list (GSList *fav_list)
836 {
837 	GSList *list;
838 	if (!fav_list)
839 		return;
840 	for (list = fav_list; list; list = list->next) {
841 		ToolsFavoritesAttributes *fav = (ToolsFavoritesAttributes*) list->data;
842 		gda_tools_favorites_reset_attributes (fav);
843 		g_free (fav);
844 	}
845 	g_slist_free (fav_list);
846 }
847 
848 /**
849  * gda_tools_favorites_reset_attributes
850  * @fav: a pointer to a #ToolsFavoritesAttributes
851  *
852  * Resets @fav with empty attributes; it does not free @fav.
853  */
854 void
gda_tools_favorites_reset_attributes(ToolsFavoritesAttributes * fav)855 gda_tools_favorites_reset_attributes (ToolsFavoritesAttributes *fav)
856 {
857 	g_free (fav->name);
858 	g_free (fav->descr);
859 	g_free (fav->contents);
860 	memset (fav, 0, sizeof (ToolsFavoritesAttributes));
861 }
862 
863 /**
864  * gda_tools_favorites_list
865  * @bfav: a #ToolsFavorites
866  * @session_id: 0 for now
867  * @type: filter the type of attributes to be listed
868  * @order_key: a key to order the listed favorites, such as #ORDER_KEY_SCHEMA
869  * @error: a place to store errors, or %NULL
870  *
871  * Extract some favorites.
872  *
873  * Returns: a new list of #ToolsFavoritesAttributes pointers. The list has to
874  *          be freed using gda_tools_favorites_free_list()
875  */
876 GSList *
gda_tools_favorites_list(ToolsFavorites * bfav,guint session_id,ToolsFavoritesType type,gint order_key,GError ** error)877 gda_tools_favorites_list (ToolsFavorites *bfav, guint session_id, ToolsFavoritesType type,
878 		      gint order_key, GError **error)
879 {
880 	GdaSqlBuilder *b;
881 	GdaSet *params = NULL;
882 	GdaStatement *stmt;
883 	GdaSqlBuilderId t1, t2;
884 	GdaDataModel *model = NULL;
885 	GSList *fav_list = NULL;
886 
887 	guint and_cond_ids [3];
888 	int and_cond_size = 0;
889 	guint or_cond_ids [GDA_TOOLS_FAVORITES_NB_TYPES];
890 	int or_cond_size = 0;
891 
892 	g_return_val_if_fail (GDA_TOOLS_IS_FAVORITES (bfav), NULL);
893 	g_return_val_if_fail ((type != 0) || (order_key >= 0), NULL);
894 
895 	if (! meta_store_addons_init (bfav, error))
896 		return NULL;
897 
898 	b = gda_sql_builder_new (GDA_SQL_STATEMENT_SELECT);
899 	gda_sql_builder_add_field_value_id (b,
900 					    gda_sql_builder_add_id (b, "fav.contents"), 0);
901 	gda_sql_builder_add_field_value_id (b,
902 					    gda_sql_builder_add_id (b, "fav.descr"), 0);
903 	gda_sql_builder_add_field_value_id (b,
904 					    gda_sql_builder_add_id (b, "fav.name"), 0);
905 	gda_sql_builder_add_field_value_id (b,
906 					    gda_sql_builder_add_id (b, "fav.type"), 0);
907 	gda_sql_builder_add_field_value_id (b,
908 					    gda_sql_builder_add_id (b, "fav.id"), 0);
909 
910 	t1 = gda_sql_builder_select_add_target (b, FAVORITES_TABLE_NAME, "fav");
911 	if (order_key > 0) {
912 		t2 = gda_sql_builder_select_add_target (b, FAVORDER_TABLE_NAME, "o");
913 		gda_sql_builder_select_join_targets (b, t1, t2, GDA_SQL_SELECT_JOIN_LEFT,
914 						     gda_sql_builder_add_cond (b, GDA_SQL_OPERATOR_TYPE_EQ,
915 									       gda_sql_builder_add_id (b, "fav.id"),
916 									       gda_sql_builder_add_id (b, "o.fav_id"),
917 									       0));
918 		gda_sql_builder_select_order_by (b,
919 						 gda_sql_builder_add_id (b, "o.rank"), TRUE, NULL);
920 
921 		and_cond_ids [and_cond_size] = gda_sql_builder_add_cond (b, GDA_SQL_OPERATOR_TYPE_EQ,
922 									 gda_sql_builder_add_id (b, "o.order_key"),
923 									 gda_sql_builder_add_param (b, "okey", G_TYPE_INT, TRUE),
924 									 0);
925 		and_cond_size++;
926 	}
927 
928 	and_cond_ids [and_cond_size] = gda_sql_builder_add_cond (b, GDA_SQL_OPERATOR_TYPE_EQ,
929 								 gda_sql_builder_add_id (b, "fav.session"),
930 								 gda_sql_builder_add_param (b, "session", G_TYPE_INT, FALSE), 0);
931 	and_cond_size++;
932 
933 	gint i;
934 	gint flag;
935 	for (i = 0, flag = 1; i < GDA_TOOLS_FAVORITES_NB_TYPES; i++, flag <<= 1) {
936 		if (type & flag) {
937 			gchar *str;
938 			str = g_strdup_printf ("'%s'", gda_tools_favorites_type_to_string (flag));
939 			or_cond_ids [or_cond_size] = gda_sql_builder_add_cond (b, GDA_SQL_OPERATOR_TYPE_EQ,
940 									       gda_sql_builder_add_id (b, "fav.type"),
941 									       gda_sql_builder_add_id (b, str),
942 									       0);
943 			g_free (str);
944 			or_cond_size++;
945 		}
946 	}
947 	if (or_cond_size >= 1) {
948 		and_cond_ids [and_cond_size] = gda_sql_builder_add_cond_v (b, GDA_SQL_OPERATOR_TYPE_OR,
949 									   or_cond_ids, or_cond_size);
950 		and_cond_size++;
951 	}
952 
953 	gda_sql_builder_set_where (b,
954 				   gda_sql_builder_add_cond_v (b, GDA_SQL_OPERATOR_TYPE_AND, and_cond_ids, and_cond_size));
955 #ifdef GDA_DEBUG_NO
956 	{
957 		GdaSqlStatement *sqlst;
958 		sqlst = gda_sql_builder_get_sql_statement (b);
959 
960 		g_print ("=>%s\n", gda_sql_statement_serialize (sqlst));
961 	}
962 #endif
963 
964 	stmt = gda_sql_builder_get_statement (b, error);
965 	g_object_unref (G_OBJECT (b));
966 	if (!stmt)
967 		goto out;
968 
969 #ifdef GDA_DEBUG_NO
970 	{
971 		g_print ("=>%s\n", gda_statement_to_sql (stmt, NULL, NULL));
972 	}
973 #endif
974 
975 
976 	params = gda_set_new_inline (2,
977 				     "session", G_TYPE_INT, session_id,
978 				     "okey", G_TYPE_INT, order_key);
979 
980 	model = gda_connection_statement_execute_select (bfav->priv->store_cnc, stmt, params, error);
981 	g_object_unref (stmt);
982 	if (!model) {
983 		g_warning ("Malformed dictionary database, cannot get favorites list (this should happen only while in dev.).");
984 		goto out;
985 	}
986 
987 	gint nrows;
988 	nrows = gda_data_model_get_n_rows (model);
989 	for (i = 0; i < nrows; i++) {
990 		const GValue *contents, *descr = NULL, *name = NULL, *type = NULL, *id = NULL;
991 
992 		contents = gda_data_model_get_value_at (model, 0, i, error);
993 		if (contents)
994 			descr = gda_data_model_get_value_at (model, 1, i, error);
995 		if (descr)
996 			name = gda_data_model_get_value_at (model, 2, i, error);
997 		if (name)
998 			type = gda_data_model_get_value_at (model, 3, i, error);
999 		if (type)
1000 			id = gda_data_model_get_value_at (model, 4, i, error);
1001 		if (id) {
1002 			ToolsFavoritesAttributes *fav;
1003 			fav = g_new0 (ToolsFavoritesAttributes, 1);
1004 			fav->id = g_value_get_int (id);
1005 			fav->type = favorite_string_to_type (g_value_get_string (type));
1006 			if (G_VALUE_TYPE (descr) == G_TYPE_STRING)
1007 				fav->descr = g_value_dup_string (descr);
1008 			if (G_VALUE_TYPE (name) == G_TYPE_STRING)
1009 				fav->name = g_value_dup_string (name);
1010 			fav->contents = g_value_dup_string (contents);
1011 			fav_list = g_slist_prepend (fav_list, fav);
1012 		}
1013 		else {
1014 			gda_tools_favorites_free_list (fav_list);
1015 			fav_list = NULL;
1016 			goto out;
1017 		}
1018 	}
1019 
1020  out:
1021 	if (params)
1022 		g_object_unref (G_OBJECT (params));
1023 	if (model)
1024 		g_object_unref (G_OBJECT (model));
1025 
1026 	return g_slist_reverse (fav_list);
1027 }
1028 
1029 
1030 /**
1031  * gda_tools_favorites_delete
1032  * @bfav: a #ToolsFavorites
1033  * @session_id: 0 for now
1034  * @fav: a pointer to a #ToolsFavoritesAttributes definning which favorite to delete
1035  * @error: a place to store errors, or %NULL
1036  *
1037  * Delete a favorite
1038  *
1039  * Returns: %TRUE if no error occurred.
1040  */
1041 gboolean
gda_tools_favorites_delete(ToolsFavorites * bfav,guint session_id,ToolsFavoritesAttributes * fav,GError ** error)1042 gda_tools_favorites_delete (ToolsFavorites *bfav, guint session_id,
1043 			ToolsFavoritesAttributes *fav, GError **error)
1044 {
1045 	GdaSqlBuilder *b;
1046 	GdaSet *params = NULL;
1047 	GdaStatement *stmt;
1048 	gboolean retval = FALSE;
1049 	gint favid = -1;
1050 	ToolsFavoritesAttributes efav;
1051 
1052 	g_return_val_if_fail (GDA_TOOLS_IS_FAVORITES (bfav), FALSE);
1053 	g_return_val_if_fail (fav, FALSE);
1054 	g_return_val_if_fail ((fav->id >= 0) || fav->contents || fav->name , FALSE);
1055 
1056 	memset (&efav, 0, sizeof (ToolsFavoritesAttributes));
1057 	if (! meta_store_addons_init (bfav, error))
1058 		return FALSE;
1059 
1060 	if (! gda_lockable_trylock (GDA_LOCKABLE (bfav->priv->store_cnc))) {
1061 		g_set_error (error, GDA_TOOLS_ERROR, GDA_TOOLS_STORED_DATA_ERROR,
1062 			     "%s", _("Can't initialize transaction to access favorites"));
1063 		return FALSE;
1064 	}
1065 	/* begin a transaction */
1066 	if (! gda_connection_begin_transaction (bfav->priv->store_cnc, NULL,
1067 						GDA_TRANSACTION_ISOLATION_UNKNOWN, NULL)) {
1068 		g_set_error (error, GDA_TOOLS_ERROR, GDA_TOOLS_STORED_DATA_ERROR,
1069 			     "%s", _("Can't initialize transaction to access favorites"));
1070 		gda_lockable_unlock (GDA_LOCKABLE (bfav->priv->store_cnc));
1071                 return FALSE;
1072 	}
1073 
1074 	GError *lerror = NULL;
1075 	if ((fav->id >= 0) || fav->contents) {
1076 		favid = find_favorite (bfav, session_id, fav->id, fav->contents, &efav, &lerror);
1077 		if (lerror) {
1078 			g_propagate_error (error, lerror);
1079 			goto out;
1080 		}
1081 	}
1082 	if ((favid < 0) && fav->name) {
1083 		favid = find_favorite_by_name (bfav, session_id, fav->name, fav->type,
1084 					       &efav, &lerror);
1085 		if (lerror) {
1086 			g_propagate_error (error, lerror);
1087 			goto out;
1088 		}
1089 	}
1090 	if (favid < 0) {
1091 		g_set_error (error, GDA_TOOLS_ERROR, GDA_TOOLS_INTERNAL_COMMAND_ERROR,
1092 			     "%s", _("Could not find favorite"));
1093 		goto out;
1094 	}
1095 
1096 	/* remove entry from favorites' list */
1097 	b = gda_sql_builder_new (GDA_SQL_STATEMENT_DELETE);
1098 	gda_sql_builder_set_table (b, FAVORITES_TABLE_NAME);
1099 	gda_sql_builder_set_where (b, gda_sql_builder_add_cond (b, GDA_SQL_OPERATOR_TYPE_EQ,
1100 								gda_sql_builder_add_id (b, "id"),
1101 								gda_sql_builder_add_param (b, "id", G_TYPE_INT, FALSE),
1102 								0));
1103 
1104 	stmt = gda_sql_builder_get_statement (b, error);
1105 	g_object_unref (G_OBJECT (b));
1106 	if (!stmt)
1107 		goto out;
1108 
1109 	params = gda_set_new_inline (1, "id", G_TYPE_INT, favid);
1110 
1111 	if (gda_connection_statement_execute_non_select (bfav->priv->store_cnc, stmt, params, NULL, error) == -1) {
1112 		g_object_unref (stmt);
1113 		goto out;
1114 	}
1115 	g_object_unref (stmt);
1116 
1117 	/* remove entry from favorites' order */
1118 	b = gda_sql_builder_new (GDA_SQL_STATEMENT_DELETE);
1119 	gda_sql_builder_set_table (b, FAVORDER_TABLE_NAME);
1120 	gda_sql_builder_set_where (b, gda_sql_builder_add_cond (b, GDA_SQL_OPERATOR_TYPE_EQ,
1121 								gda_sql_builder_add_id (b, "fav_id"),
1122 								gda_sql_builder_add_param (b, "id", G_TYPE_INT, FALSE),
1123 								0));
1124 
1125 	stmt = gda_sql_builder_get_statement (b, error);
1126 	g_object_unref (G_OBJECT (b));
1127 	if (!stmt)
1128 		goto out;
1129 	if (gda_connection_statement_execute_non_select (bfav->priv->store_cnc, stmt, params, NULL, error) == -1) {
1130 		g_object_unref (stmt);
1131 		goto out;
1132 	}
1133 	g_object_unref (stmt);
1134 
1135 	if (! gda_connection_commit_transaction (bfav->priv->store_cnc, NULL, NULL)) {
1136 		g_set_error (error, GDA_TOOLS_ERROR, GDA_TOOLS_STORED_DATA_ERROR,
1137 			     "%s", _("Can't commit transaction to access favorites"));
1138 		goto out;
1139 	}
1140 	retval = TRUE;
1141 
1142  out:
1143 	if (!retval)
1144 		gda_connection_rollback_transaction (bfav->priv->store_cnc, NULL, NULL);
1145 
1146 	gda_lockable_unlock (GDA_LOCKABLE (bfav->priv->store_cnc));
1147 	if (retval)
1148 		g_signal_emit (bfav, gda_tools_favorites_signals [FAV_CHANGED],
1149 			       g_quark_from_string (gda_tools_favorites_type_to_string (efav.type)));
1150 	gda_tools_favorites_reset_attributes (&efav);
1151 	if (params)
1152 		g_object_unref (G_OBJECT (params));
1153 
1154 	return retval;
1155 }
1156 
1157 /**
1158  * gda_tools_favorites_find
1159  * @bfav: a #ToolsFavorites
1160  * @session_id: 0 for now
1161  * @contents: the favorite's contents
1162  * @out_fav: (allow-none): a #ToolsFavoritesAttributes to be filled with the favorite's attributes, or %NULL
1163  * @error: a place to store errors, or %NULL
1164  *
1165  * Get all the information about a favorite from its id: fills the @out_fav
1166  * pointed structure. Use gda_tools_favorites_reset_attributes() to reset @out_fav's contents.
1167  *
1168  * Retuns: the requested's favorite ID, or -1 if not found
1169  */
1170 gint
gda_tools_favorites_find(ToolsFavorites * bfav,guint session_id,const gchar * contents,ToolsFavoritesAttributes * out_fav,GError ** error)1171 gda_tools_favorites_find (ToolsFavorites *bfav, guint session_id, const gchar *contents,
1172 		      ToolsFavoritesAttributes *out_fav, GError **error)
1173 {
1174 	g_return_val_if_fail (GDA_TOOLS_IS_FAVORITES (bfav), -1);
1175 	g_return_val_if_fail (contents, -1);
1176 
1177 	if (! meta_store_addons_init (bfav, error))
1178 		return -1;
1179 	return find_favorite (bfav, session_id, -1, contents, out_fav, error);
1180 }
1181 
1182 /**
1183  * gda_tools_favorites_find_by_name:
1184  * @bfav: a #ToolsFavorites
1185  * @session_id: 0 for now
1186  * @type: the favorite's type
1187  * @name: the favorite's name
1188  * @out_fav: (allow-none): a #ToolsFavoritesAttributes to be filled with the favorite's attributes, or %NULL
1189  * @error: a place to store errors, or %NULL
1190  *
1191  * Get all the information about a favorite from its id: fills the @out_fav
1192  * pointed structure. Use gda_tools_favorites_reset_attributes() to reset @out_fav's contents.
1193  *
1194  * Retuns: the requested's favorite ID, or -1 if not found
1195  */
1196 gint
gda_tools_favorites_find_by_name(ToolsFavorites * bfav,guint session_id,ToolsFavoritesType type,const gchar * name,ToolsFavoritesAttributes * out_fav,GError ** error)1197 gda_tools_favorites_find_by_name (ToolsFavorites *bfav, guint session_id, ToolsFavoritesType type, const gchar *name,
1198 			      ToolsFavoritesAttributes *out_fav, GError **error)
1199 {
1200 	g_return_val_if_fail (GDA_TOOLS_IS_FAVORITES (bfav), -1);
1201 	g_return_val_if_fail (name, -1);
1202 
1203 	if (! meta_store_addons_init (bfav, error))
1204 		return -1;
1205 	return find_favorite_by_name (bfav, session_id, name, type, out_fav, error);
1206 }
1207 
1208 
1209 
1210 /**
1211  * gda_tools_favorites_get
1212  * @bfav: a #ToolsFavorites
1213  * @fav_id: the favorite's ID
1214  * @out_fav: a #ToolsFavoritesAttributes to be filled with the favorite's attributes
1215  * @error: a place to store errors, or %NULL
1216  *
1217  * Get all the information about a favorite from its id: fills the @out_fav
1218  * pointed structure. Use gda_tools_favorites_reset_attributes() to reset @out_fav's contents.
1219  *
1220  * Retuns: %TRUE if no error occurred.
1221  */
1222 gboolean
gda_tools_favorites_get(ToolsFavorites * bfav,gint fav_id,ToolsFavoritesAttributes * out_fav,GError ** error)1223 gda_tools_favorites_get (ToolsFavorites *bfav, gint fav_id,
1224 		     ToolsFavoritesAttributes *out_fav, GError **error)
1225 {
1226 	GdaSqlBuilder *b;
1227 	GdaStatement *stmt;
1228 	GdaSet *params = NULL;
1229 	GdaDataModel *model;
1230 	gboolean retval = FALSE;
1231 
1232 	g_return_val_if_fail (GDA_TOOLS_IS_FAVORITES (bfav), FALSE);
1233 	g_return_val_if_fail (out_fav, FALSE);
1234 	g_return_val_if_fail (fav_id >= 0, FALSE);
1235 
1236 	memset (out_fav, 0, sizeof (ToolsFavoritesAttributes));
1237 
1238 	b = gda_sql_builder_new (GDA_SQL_STATEMENT_SELECT);
1239 	gda_sql_builder_add_field_value_id (b,
1240 					    gda_sql_builder_add_id (b, "id"), 0);
1241 	gda_sql_builder_add_field_value_id (b,
1242 					    gda_sql_builder_add_id (b, "type"), 0);
1243 	gda_sql_builder_add_field_value_id (b,
1244 					    gda_sql_builder_add_id (b, "name"), 0);
1245 	gda_sql_builder_add_field_value_id (b,
1246 					    gda_sql_builder_add_id (b, "descr"), 0);
1247 	gda_sql_builder_add_field_value_id (b,
1248 					    gda_sql_builder_add_id (b, "contents"), 0);
1249 	gda_sql_builder_select_add_target (b, FAVORITES_TABLE_NAME, NULL);
1250 
1251 	gda_sql_builder_set_where (b,
1252 				   gda_sql_builder_add_cond (b, GDA_SQL_OPERATOR_TYPE_EQ,
1253 							     gda_sql_builder_add_id (b, "id"),
1254 							     gda_sql_builder_add_param (b, "id", G_TYPE_INT, FALSE), 0));
1255 	stmt = gda_sql_builder_get_statement (b, error);
1256 	g_object_unref (G_OBJECT (b));
1257 	if (!stmt)
1258 		return FALSE;
1259 	params = gda_set_new_inline (1,
1260 				     "id", G_TYPE_INT, fav_id);
1261 	model = gda_connection_statement_execute_select (bfav->priv->store_cnc, stmt, params, error);
1262 	g_object_unref (stmt);
1263 	g_object_unref (params);
1264 
1265 	if (!model)
1266 		return FALSE;
1267 
1268 	gint nrows;
1269 	nrows = gda_data_model_get_n_rows (model);
1270 	if (nrows == 1) {
1271 		gint i;
1272 		const GValue *cvalues[5];
1273 		for (i = 0; i < 5; i++) {
1274 			cvalues [i] = gda_data_model_get_value_at (model, i, 0, error);
1275 			if (!cvalues [i])
1276 				goto out;
1277 		}
1278 
1279 		out_fav->id = g_value_get_int (cvalues [0]);
1280 		out_fav->type = favorite_string_to_type (g_value_get_string (cvalues [1]));
1281 		if (G_VALUE_TYPE (cvalues [2]) == G_TYPE_STRING)
1282 			out_fav->name = g_value_dup_string (cvalues [2]);
1283 		if (G_VALUE_TYPE (cvalues [3]) == G_TYPE_STRING)
1284 			out_fav->descr = g_value_dup_string (cvalues [3]);
1285 		out_fav->contents = g_value_dup_string (cvalues [4]);
1286 		retval = TRUE;
1287 	}
1288 
1289  out:
1290 	g_object_unref (G_OBJECT (model));
1291 	return retval;
1292 }
1293