1 /*
2 * Copyright (C) 2008 - 2010 Murray Cumming <murrayc@murrayc.com>
3 * Copyright (C) 2008 - 2012 Vivien Malerba <malerba@gnome-db.org>
4 * Copyright (C) 2009 Bas Driessen <bas.driessen@xobas.com>
5 * Copyright (C) 2010 David King <davidk@openismus.com>
6 * Copyright (C) 2010 Jonh Wendell <jwendell@gnome.org>
7 * Copyright (C) 2012 Daniel Espinosa <despinosa@src.gnome.org>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
23 */
24
25 #include <string.h>
26 #include <glib/gi18n-lib.h>
27 #include <libgda/gda-meta-struct.h>
28 #include <libgda/gda-util.h>
29 #include <sql-parser/gda-sql-parser.h>
30 #include <sql-parser/gda-sql-statement.h>
31 #include <sql-parser/gda-statement-struct-util.h>
32 #include <libgda/gda-attributes-manager.h>
33 #include <libgda/gda-debug-macros.h>
34
35 /*
36 * Main static functions
37 */
38 static void gda_meta_struct_class_init (GdaMetaStructClass *klass);
39 static void gda_meta_struct_init (GdaMetaStruct *mstruct);
40 static void gda_meta_struct_dispose (GObject *object);
41 static void gda_meta_struct_finalize (GObject *object);
42
43 static void gda_meta_struct_set_property (GObject *object,
44 guint param_id,
45 const GValue *value,
46 GParamSpec *pspec);
47 static void gda_meta_struct_get_property (GObject *object,
48 guint param_id,
49 GValue *value,
50 GParamSpec *pspec);
51
52
53 static void meta_store_changed_cb (GdaMetaStore *store, GSList *changes, GdaMetaStruct *mstruct);
54 static void meta_store_reset_cb (GdaMetaStore *store, GdaMetaStruct *mstruct);
55
56 struct _GdaMetaStructPrivate {
57 GdaMetaStore *store;
58 GSList *db_objects; /* list of GdaMetaDbObject structures */
59 GHashTable *index; /* key = [catalog].[schema].[name], value = a GdaMetaDbObject. Note: catalog, schema and name
60 * are case sensitive (and don't have any double quote around them) */
61 guint features;
62 };
63
64 static GdaMetaDbObject *_meta_struct_get_db_object (GdaMetaStruct *mstruct,
65 const GValue *catalog, const GValue *schema, const GValue *name);
66
67 static void gda_meta_db_object_free (GdaMetaDbObject *dbo);
68 static void gda_meta_db_object_free_contents (GdaMetaDbObject *dbo);
69 static void gda_meta_table_free_contents (GdaMetaTable *table);
70 static void gda_meta_view_free_contents (GdaMetaView *view);
71 static void gda_meta_table_column_free (GdaMetaTableColumn *tcol);
72 static void gda_meta_table_foreign_key_free (GdaMetaTableForeignKey *tfk);
73
74 /* get a pointer to the parents to be able to call their destructor */
75 static GObjectClass *parent_class = NULL;
76 static GdaAttributesManager *att_mgr;
77
78 /* properties */
79 enum {
80 PROP_0,
81 PROP_STORE,
82 PROP_FEATURES
83 };
84
85 /* module error */
gda_meta_struct_error_quark(void)86 GQuark gda_meta_struct_error_quark (void) {
87 static GQuark quark;
88 if (!quark)
89 quark = g_quark_from_static_string ("gda_meta_struct_error");
90 return quark;
91 }
92
93 GType
gda_meta_struct_get_type(void)94 gda_meta_struct_get_type (void) {
95 static GType type = 0;
96
97 if (G_UNLIKELY (type == 0)) {
98 static GMutex registering;
99 static const GTypeInfo info = {
100 sizeof (GdaMetaStructClass),
101 (GBaseInitFunc) NULL,
102 (GBaseFinalizeFunc) NULL,
103 (GClassInitFunc) gda_meta_struct_class_init,
104 NULL,
105 NULL,
106 sizeof (GdaMetaStruct),
107 0,
108 (GInstanceInitFunc) gda_meta_struct_init,
109 0
110 };
111
112 g_mutex_lock (®istering);
113 if (type == 0)
114 type = g_type_register_static (G_TYPE_OBJECT, "GdaMetaStruct", &info, 0);
115 g_mutex_unlock (®istering);
116 }
117 return type;
118 }
119
120
121 static void
gda_meta_struct_class_init(GdaMetaStructClass * klass)122 gda_meta_struct_class_init (GdaMetaStructClass *klass) {
123 GObjectClass *object_class = G_OBJECT_CLASS (klass);
124
125 parent_class = g_type_class_peek_parent (klass);
126
127 /* Properties */
128 object_class->set_property = gda_meta_struct_set_property;
129 object_class->get_property = gda_meta_struct_get_property;
130 g_object_class_install_property (object_class, PROP_STORE,
131 /* To translators: GdaMetaStore is an object holding meta data information
132 * which will be used as an information source */
133 g_param_spec_object ("meta-store", NULL,
134 _ ("GdaMetaStore object to fetch information from"),
135 GDA_TYPE_META_STORE,
136 (G_PARAM_WRITABLE | G_PARAM_READABLE |
137 G_PARAM_CONSTRUCT_ONLY)));
138 g_object_class_install_property (object_class, PROP_FEATURES,
139 /* To translators: The GdaMetaStruct object computes lists of tables, views,
140 * and some other information, the "Features to compute" allows one to avoid
141 * computing some features which won't be used */
142 g_param_spec_uint ("features", _ ("Features to compute"), NULL,
143 GDA_META_STRUCT_FEATURE_NONE, G_MAXINT,
144 GDA_META_STRUCT_FEATURE_ALL,
145 (G_PARAM_WRITABLE | G_PARAM_READABLE |
146 G_PARAM_CONSTRUCT_ONLY)));
147
148 /* virtual methods */
149 object_class->dispose = gda_meta_struct_dispose;
150 object_class->finalize = gda_meta_struct_finalize;
151
152 /* extra */
153 att_mgr = gda_attributes_manager_new (FALSE, NULL, NULL);
154 }
155
156
157 static void
gda_meta_struct_init(GdaMetaStruct * mstruct)158 gda_meta_struct_init (GdaMetaStruct *mstruct) {
159 mstruct->priv = g_new0 (GdaMetaStructPrivate, 1);
160 mstruct->priv->store = NULL;
161 mstruct->priv->db_objects = NULL;
162 mstruct->priv->index = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
163 }
164
165
166 /**
167 * gda_meta_struct_new:
168 * @store: a #GdaMetaStore from which the new #GdaMetaStruct object will fetch information
169 * @features: the kind of extra information the new #GdaMetaStruct object will compute
170 *
171 * Creates a new #GdaMetaStruct object. The @features specifies the extra features which will also be computed:
172 * the more features, the more time it takes to run. Features such as table's columns, each column's attributes, etc
173 * are not optional and will always be computed.
174 *
175 * Returns: (transfer full): the newly created #GdaMetaStruct object
176 */
177 GdaMetaStruct *
gda_meta_struct_new(GdaMetaStore * store,GdaMetaStructFeature features)178 gda_meta_struct_new (GdaMetaStore *store, GdaMetaStructFeature features)
179 {
180 g_return_val_if_fail (GDA_IS_META_STORE (store), NULL);
181 return (GdaMetaStruct*) g_object_new (GDA_TYPE_META_STRUCT, "meta-store", store, "features", features, NULL);
182 }
183
184 static void
gda_meta_struct_dispose(GObject * object)185 gda_meta_struct_dispose (GObject *object) {
186 GdaMetaStruct *mstruct;
187
188 g_return_if_fail (object != NULL);
189 g_return_if_fail (GDA_IS_META_STRUCT (object));
190
191 mstruct = GDA_META_STRUCT (object);
192 if (mstruct->priv->store) {
193 g_signal_handlers_disconnect_by_func (G_OBJECT (mstruct->priv->store),
194 G_CALLBACK (meta_store_changed_cb), mstruct);
195 g_signal_handlers_disconnect_by_func (G_OBJECT (mstruct->priv->store),
196 G_CALLBACK (meta_store_reset_cb), mstruct);
197 g_object_ref (mstruct->priv->store);
198 mstruct->priv->store = NULL;
199 }
200
201 /* parent class */
202 parent_class->finalize (object);
203 }
204
205 static void
gda_meta_struct_finalize(GObject * object)206 gda_meta_struct_finalize (GObject *object) {
207 GdaMetaStruct *mstruct;
208
209 g_return_if_fail (object != NULL);
210 g_return_if_fail (GDA_IS_META_STRUCT (object));
211
212 mstruct = GDA_META_STRUCT (object);
213 if (mstruct->priv) {
214 g_slist_foreach (mstruct->priv->db_objects, (GFunc) gda_meta_db_object_free, NULL);
215 g_slist_free (mstruct->priv->db_objects);
216 g_hash_table_destroy (mstruct->priv->index);
217 g_free (mstruct->priv);
218 mstruct->priv = NULL;
219 }
220
221 /* parent class */
222 parent_class->finalize (object);
223 }
224
225 static void
gda_meta_struct_set_property(GObject * object,guint param_id,const GValue * value,GParamSpec * pspec)226 gda_meta_struct_set_property (GObject *object,
227 guint param_id,
228 const GValue *value,
229 GParamSpec *pspec)
230 {
231 GdaMetaStruct *mstruct;
232
233 mstruct = GDA_META_STRUCT (object);
234 if (mstruct->priv) {
235 switch (param_id) {
236 case PROP_STORE:
237 mstruct->priv->store = g_value_get_object (value);
238 if (mstruct->priv->store) {
239 g_object_ref (mstruct->priv->store);
240 g_signal_connect (G_OBJECT (mstruct->priv->store), "meta-changed",
241 G_CALLBACK (meta_store_changed_cb), mstruct);
242 g_signal_connect (G_OBJECT (mstruct->priv->store), "meta-reset",
243 G_CALLBACK (meta_store_reset_cb), mstruct);
244 }
245 break;
246 case PROP_FEATURES:
247 mstruct->priv->features = g_value_get_uint (value);
248 break;
249 default:
250 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
251 break;
252 }
253 }
254 }
255
256 static void
gda_meta_struct_get_property(GObject * object,guint param_id,GValue * value,GParamSpec * pspec)257 gda_meta_struct_get_property (GObject *object,
258 guint param_id,
259 GValue *value,
260 GParamSpec *pspec)
261 {
262 GdaMetaStruct *mstruct;
263 mstruct = GDA_META_STRUCT (object);
264
265 if (mstruct->priv) {
266 switch (param_id) {
267 case PROP_STORE:
268 g_value_set_object (value, mstruct->priv->store);
269 break;
270 case PROP_FEATURES:
271 g_value_set_uint (value, mstruct->priv->features);
272 break;
273 default:
274 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
275 break;
276 }
277 }
278 }
279
280 static void
meta_store_changed_cb(GdaMetaStore * store,G_GNUC_UNUSED GSList * changes,GdaMetaStruct * mstruct)281 meta_store_changed_cb (GdaMetaStore *store, G_GNUC_UNUSED GSList *changes, GdaMetaStruct *mstruct)
282 {
283 /* for now we mark ALL the db objects as outdated */
284 meta_store_reset_cb (store, mstruct);
285 }
286
287 static void
meta_store_reset_cb(G_GNUC_UNUSED GdaMetaStore * store,GdaMetaStruct * mstruct)288 meta_store_reset_cb (G_GNUC_UNUSED GdaMetaStore *store, GdaMetaStruct *mstruct)
289 {
290 /* mark ALL the db objects as outdated */
291 GSList *list;
292 for (list = mstruct->priv->db_objects; list; list = list->next)
293 GDA_META_DB_OBJECT (list->data)->outdated = TRUE;
294 }
295
296
297 static void
compute_view_dependencies(GdaMetaStruct * mstruct,GdaMetaDbObject * view_dbobj,GdaSqlStatement * sqlst)298 compute_view_dependencies (GdaMetaStruct *mstruct, GdaMetaDbObject *view_dbobj, GdaSqlStatement *sqlst)
299 {
300 if (sqlst->stmt_type == GDA_SQL_STATEMENT_SELECT) {
301 GdaSqlStatementSelect *selst;
302 selst = (GdaSqlStatementSelect*) (sqlst->contents);
303 GSList *targets = NULL;
304 if (selst->from)
305 targets = selst->from->targets;
306 for (; targets; targets = targets->next) {
307 GdaSqlSelectTarget *t = (GdaSqlSelectTarget *) targets->data;
308 GValue *catalog, *schema, *name;
309 GdaMetaDbObject *ref_obj, *tmp_obj;
310 GdaMetaStruct *m2;
311 GValue *vname;
312
313 if (!t->table_name)
314 continue;
315
316 m2 = gda_meta_struct_new (mstruct->priv->store, GDA_META_STRUCT_FEATURE_NONE);
317 g_value_set_string ((vname = gda_value_new (G_TYPE_STRING)), t->table_name);
318 if (! (tmp_obj = gda_meta_struct_complement (m2,
319 GDA_META_DB_TABLE, NULL, NULL, vname, NULL)))
320 tmp_obj = gda_meta_struct_complement (m2,
321 GDA_META_DB_VIEW, NULL, NULL, vname, NULL);
322 gda_value_free (vname);
323
324 if (!tmp_obj) {
325 /* could not find dependency */
326 g_object_unref (m2);
327 continue;
328 }
329
330 /* the dependency exists, and is identified by tmp_obj->obj_catalog, tmp_obj->obj_schema
331 * and tmp_obj->obj_name */
332 g_value_set_string ((catalog = gda_value_new (G_TYPE_STRING)), tmp_obj->obj_catalog);
333 g_value_set_string ((schema = gda_value_new (G_TYPE_STRING)), tmp_obj->obj_schema);
334 g_value_set_string ((name = gda_value_new (G_TYPE_STRING)), tmp_obj->obj_name);
335 ref_obj = _meta_struct_get_db_object (mstruct, catalog, schema, name);
336 if (!ref_obj) {
337 gchar *str;
338 ref_obj = g_new0 (GdaMetaDbObject, 1);
339 ref_obj->obj_type = GDA_META_DB_UNKNOWN;
340 ref_obj->obj_catalog = g_strdup (tmp_obj->obj_catalog);
341 ref_obj->obj_schema = g_strdup (tmp_obj->obj_schema);
342 ref_obj->obj_name = g_strdup (tmp_obj->obj_name);
343
344 mstruct->priv->db_objects = g_slist_append (mstruct->priv->db_objects, ref_obj);
345 str = g_strdup_printf ("%s.%s.%s", tmp_obj->obj_catalog,
346 tmp_obj->obj_schema, tmp_obj->obj_name);
347 g_hash_table_insert (mstruct->priv->index, str, ref_obj);
348 }
349 g_object_unref (m2);
350 g_assert (ref_obj);
351 gda_value_free (catalog);
352 gda_value_free (schema);
353 gda_value_free (name);
354
355 view_dbobj->depend_list = g_slist_append (view_dbobj->depend_list, ref_obj);
356 }
357 }
358 else if (sqlst->stmt_type == GDA_SQL_STATEMENT_COMPOUND) {
359 GdaSqlStatementCompound *cst;
360 GSList *list;
361 cst = (GdaSqlStatementCompound*) (sqlst->contents);
362 for (list = cst->stmt_list; list; list = list->next)
363 compute_view_dependencies (mstruct, view_dbobj, (GdaSqlStatement*) list->data);
364 }
365 else
366 g_assert_not_reached ();
367 }
368
369 static GdaMetaDbObject * _meta_struct_complement (GdaMetaStruct *mstruct, GdaMetaDbObjectType type,
370 const GValue *icatalog, const GValue *ischema, const GValue *iname,
371 const GValue *short_name, const GValue *full_name,
372 const GValue *owner, GError **error);
373 static gboolean determine_db_object_from_schema_and_name (GdaMetaStruct *mstruct,
374 GdaMetaDbObjectType *int_out_type, GValue **out_catalog,
375 GValue **out_short_name, GValue **out_full_name,
376 GValue **out_owner, const GValue *schema, const GValue *name);
377 static gboolean determine_db_object_from_short_name (GdaMetaStruct *mstruct,
378 GdaMetaDbObjectType *int_out_type, GValue **out_catalog,
379 GValue **out_schema, GValue **out_name, GValue **out_short_name,
380 GValue **out_full_name, GValue **out_owner, const GValue *name);
381 static gboolean determine_db_object_from_missing_type (GdaMetaStruct *mstruct,
382 GdaMetaDbObjectType *out_type, GValue **out_short_name,
383 GValue **out_full_name, GValue **out_owner, const GValue *catalog,
384 const GValue *schema, const GValue *name);
385 static gchar *array_type_to_sql (GdaMetaStore *store, const GValue *specific_name);
386 static gchar *
get_user_obj_name(const GValue * catalog,const GValue * schema,const GValue * name)387 get_user_obj_name (const GValue *catalog, const GValue *schema, const GValue *name)
388 {
389 GString *string = NULL;
390 gchar *ret;
391 if (catalog && (G_VALUE_TYPE (catalog) != GDA_TYPE_NULL))
392 string = g_string_new (g_value_get_string (catalog));
393 if (schema && (G_VALUE_TYPE (schema) != GDA_TYPE_NULL)) {
394 if (string) {
395 g_string_append_c (string, '.');
396 g_string_append (string, g_value_get_string (schema));
397 }
398 else
399 string = g_string_new (g_value_get_string (schema));
400 }
401 if (name && (G_VALUE_TYPE (name) != GDA_TYPE_NULL)) {
402 if (string) {
403 g_string_append_c (string, '.');
404 g_string_append (string, g_value_get_string (name));
405 }
406 else
407 string = g_string_new (g_value_get_string (name));
408 }
409 ret = string->str;
410 g_string_free (string, FALSE);
411 return ret;
412 }
413
414 static gchar *
prepare_sql_identifier_for_compare(gchar * str)415 prepare_sql_identifier_for_compare (gchar *str)
416 {
417 if (!str || (*str == '"'))
418 return str;
419 else {
420 gchar *ptr;
421 for (ptr = str; *ptr; ptr++)
422 *ptr = g_ascii_tolower (*ptr);
423 return str;
424 }
425 }
426
427 /**
428 * gda_meta_struct_complement:
429 * @mstruct: a #GdaMetaStruct object
430 * @type: the type of object to add (which can be GDA_META_DB_UNKNOWN)
431 * @catalog: (allow-none): the catalog the object belongs to (as a G_TYPE_STRING GValue), or %NULL
432 * @schema: (allow-none): the schema the object belongs to (as a G_TYPE_STRING GValue), or %NULL
433 * @name: the object's name (as a G_TYPE_STRING GValue), not %NULL
434 * @error: (allow-none): a place to store errors, or %NULL
435 *
436 * Creates a new #GdaMetaDbObject structure in @mstruct to represent the database object (of type @type)
437 * which can be uniquely identified as @catalog.@schema.@name.
438 *
439 * If @catalog is not %NULL, then @schema should not be %NULL.
440 *
441 * If both @catalog and @schema are %NULL, then the database object will be the one which is
442 * "visible" by default (that is which can be accessed only by its short @name name).
443 *
444 * If @catalog is %NULL and @schema is not %NULL, then the database object will be the one which
445 * can be accessed by its @schema.@name name.
446 *
447 * Important note: @catalog, @schema and @name will be used using the following convention:
448 * <itemizedlist>
449 * <listitem><para>be surrounded by double quotes for a case sensitive search</para></listitem>
450 * <listitem><para>otherwise for case insensitive search</para></listitem>
451 * </itemizedlist>
452 *
453 * For more information, see the <link linkend="information_schema:sql_identifiers">
454 * meta data section about SQL identifiers</link>.
455 *
456 * Returns: (transfer none): the #GdaMetaDbObject corresponding to the database object if no error occurred, or %NULL
457 */
458 GdaMetaDbObject *
gda_meta_struct_complement(GdaMetaStruct * mstruct,GdaMetaDbObjectType type,const GValue * catalog,const GValue * schema,const GValue * name,GError ** error)459 gda_meta_struct_complement (GdaMetaStruct *mstruct, GdaMetaDbObjectType type,
460 const GValue *catalog, const GValue *schema, const GValue *name,
461 GError **error)
462 {
463 GdaMetaDbObject *dbo = NULL;
464 GdaMetaDbObjectType real_type = type;
465 GValue *short_name = NULL, *full_name=NULL, *owner=NULL;
466 GValue *icatalog = NULL, *ischema = NULL, *iname = NULL; /* GValue with identifiers ready to be compared */
467
468 /* checks */
469 g_return_val_if_fail (mstruct->priv->store, NULL);
470 g_return_val_if_fail (GDA_IS_META_STRUCT (mstruct), NULL);
471 g_return_val_if_fail (name && (G_VALUE_TYPE (name) == G_TYPE_STRING), NULL);
472 if (catalog && (gda_value_is_null (catalog) || !g_value_get_string (catalog)))
473 catalog = NULL;
474 if (schema && (gda_value_is_null (schema) || !g_value_get_string (schema)))
475 schema = NULL;
476 g_return_val_if_fail (!catalog || (catalog && schema), NULL);
477 g_return_val_if_fail (!catalog || (G_VALUE_TYPE (catalog) == G_TYPE_STRING), NULL);
478 g_return_val_if_fail (!schema || (G_VALUE_TYPE (schema) == G_TYPE_STRING), NULL);
479
480 /* create ready to compare strings for catalog, schema and name */
481 gchar *schema_s, *name_s;
482 if (_split_identifier_string (g_value_dup_string (name), &schema_s, &name_s)) {
483 g_value_take_string ((iname = gda_value_new (G_TYPE_STRING)), prepare_sql_identifier_for_compare (name_s));
484 if (schema_s)
485 g_value_take_string ((ischema = gda_value_new (G_TYPE_STRING)), prepare_sql_identifier_for_compare (schema_s));
486 }
487 else
488 g_value_take_string ((iname = gda_value_new (G_TYPE_STRING)),
489 prepare_sql_identifier_for_compare (g_value_dup_string (name)));
490 if (catalog)
491 g_value_take_string ((icatalog = gda_value_new (G_TYPE_STRING)),
492 prepare_sql_identifier_for_compare (g_value_dup_string (catalog)));
493 if (schema && !ischema)
494 g_value_take_string ((ischema = gda_value_new (G_TYPE_STRING)),
495 prepare_sql_identifier_for_compare (g_value_dup_string (schema)));
496
497 if (!icatalog) {
498 if (ischema) {
499 g_return_val_if_fail (ischema && (G_VALUE_TYPE (ischema) == G_TYPE_STRING), NULL);
500 if (! determine_db_object_from_schema_and_name (mstruct, &real_type, &icatalog,
501 &short_name, &full_name, &owner,
502 ischema, iname)) {
503 gchar *tmp;
504 tmp = get_user_obj_name (catalog, schema, name);
505 g_set_error (error, GDA_META_STRUCT_ERROR, GDA_META_STRUCT_UNKNOWN_OBJECT_ERROR,
506 _("Could not find object named '%s'"), tmp);
507 g_free (tmp);
508 gda_value_free (ischema);
509 gda_value_free (iname);
510 return NULL;
511 }
512 }
513 else {
514 GValue *real_name = NULL;
515 if (! determine_db_object_from_short_name (mstruct, &real_type, &icatalog,
516 &ischema, &real_name,
517 &short_name, &full_name, &owner, iname)) {
518 gchar *tmp;
519 tmp = get_user_obj_name (catalog, schema, name);
520 g_set_error (error, GDA_META_STRUCT_ERROR, GDA_META_STRUCT_UNKNOWN_OBJECT_ERROR,
521 _("Could not find object named '%s'"), tmp);
522 g_free (tmp);
523 gda_value_free (iname);
524 return NULL;
525 }
526 if (real_name) {
527 gda_value_free (iname);
528 iname = real_name;
529 }
530 }
531 }
532 else if (type == GDA_META_DB_UNKNOWN) {
533 if (! determine_db_object_from_missing_type (mstruct, &real_type, &short_name, &full_name, &owner,
534 icatalog, ischema, iname)) {
535 gchar *tmp;
536 tmp = get_user_obj_name (catalog, schema, name);
537 g_set_error (error, GDA_META_STRUCT_ERROR, GDA_META_STRUCT_UNKNOWN_OBJECT_ERROR,
538 _("Could not find object named '%s'"), tmp);
539 g_free (tmp);
540 gda_value_free (icatalog);
541 gda_value_free (ischema);
542 gda_value_free (iname);
543 return NULL;
544 }
545 }
546 type = real_type;
547 dbo = _meta_struct_complement (mstruct, type, icatalog, ischema, iname, short_name, full_name, owner, error);
548
549 gda_value_free (icatalog);
550 gda_value_free (ischema);
551 gda_value_free (iname);
552
553 if (short_name) gda_value_free (short_name);
554 if (full_name) gda_value_free (full_name);
555 if (owner) gda_value_free (owner);
556 return dbo;
557 }
558
559 static GdaMetaForeignKeyPolicy
policy_string_to_value(const gchar * string)560 policy_string_to_value (const gchar *string)
561 {
562 if (!string)
563 return GDA_META_FOREIGN_KEY_UNKNOWN;
564 if (*string == 'C')
565 return GDA_META_FOREIGN_KEY_CASCADE;
566 else if (*string == 'R')
567 return GDA_META_FOREIGN_KEY_RESTRICT;
568 else if (*string == 'N') {
569 if (!strcmp (string + 1, "ONE"))
570 return GDA_META_FOREIGN_KEY_NONE;
571 else
572 return GDA_META_FOREIGN_KEY_NO_ACTION;
573 }
574 else if (*string == 'S') {
575 if (!strcmp (string + 1, "ET NULL"))
576 return GDA_META_FOREIGN_KEY_SET_NULL;
577 else
578 return GDA_META_FOREIGN_KEY_SET_DEFAULT;
579 }
580 return GDA_META_FOREIGN_KEY_UNKNOWN;
581 }
582
583 /*
584 * Find if there is already a declared foreign for @dbo to @ref_dbo using the columns
585 * listed in @columns
586 *
587 * @columns contains 4 columns, with no NULL value, and with nrows>0
588 * - @dbo's column name (string)
589 * - @dbo's column name ordinal position (int)
590 * - @ref_dbo's column name (string)
591 * - @ref_dbo's column name ordinal position (int)
592 */
593 static GdaMetaTableForeignKey *
find_real_foreign_key(GdaMetaTable * table,GdaMetaDbObject * ref_dbo,GdaDataModel * columns)594 find_real_foreign_key (GdaMetaTable *table, GdaMetaDbObject *ref_dbo, GdaDataModel *columns)
595 {
596 GSList *list;
597 gint nrows = -1;
598 for (list = table->fk_list; list; list = list->next) {
599 GdaMetaTableForeignKey *fk = (GdaMetaTableForeignKey*) list->data;
600 gint i;
601 gboolean *mapping;
602 if (fk->depend_on != ref_dbo)
603 continue;
604
605 if (nrows == -1)
606 nrows = gda_data_model_get_n_rows (columns);
607
608 if (nrows != fk->cols_nb)
609 continue;
610
611 mapping = g_new0 (gboolean, nrows);
612 for (i = 0; i < nrows; i++) {
613 const GValue *cvalues[4];
614 const gchar *fk_colname, *ref_colname;
615 gint fk_pos, ref_pos;
616 gint j;
617 for (j = 0; j < 4; j++) {
618 cvalues[j] = gda_data_model_get_value_at (columns, j, i, NULL);
619 if (!cvalues[j]) {
620 g_free (mapping);
621 goto out;
622 }
623 }
624 fk_colname = g_value_get_string (cvalues[0]);
625 fk_pos = g_value_get_int (cvalues[1]);
626 ref_colname = g_value_get_string (cvalues[2]);
627 ref_pos = g_value_get_int (cvalues[3]);
628 if (!fk_colname || !*fk_colname ||
629 !ref_colname || !*ref_colname) {
630 g_free (mapping);
631 goto out;
632 }
633
634 for (j = 0; j < nrows; j++) {
635 if (mapping [j]) /* row already mapped? */
636 continue;
637 if ((fk_pos == fk->fk_cols_array[j]) &&
638 (ref_pos == fk->ref_pk_cols_array[j]) &&
639 !strcmp (fk_colname, fk->fk_names_array[j]) &&
640 !strcmp (ref_colname, fk->ref_pk_names_array[j])) {
641 mapping [j] = TRUE;
642 break;
643 }
644 }
645 if (j == nrows)
646 /* i'th row has not been mapped */
647 break;
648 }
649 g_free (mapping);
650 if (i == nrows)
651 /* all the rows have been mapped */
652 return fk;
653 else
654 continue;
655 }
656 out:
657 return NULL;
658 }
659
660 static gboolean
add_declared_foreign_keys(GdaMetaStruct * mstruct,GdaMetaTable * mt,GError ** error)661 add_declared_foreign_keys (GdaMetaStruct *mstruct, GdaMetaTable *mt, GError **error)
662 {
663 const gchar *sql1 = "SELECT DISTINCT constraint_name, ref_table_catalog, ref_table_schema, ref_table_name FROM __declared_fk WHERE table_catalog = ##tc::string AND table_schema = ##ts::string AND table_name = ##tname::string ORDER BY constraint_name, ref_table_catalog, ref_table_schema, ref_table_name";
664 const gchar *sql2 = "select de.column_name, c.ordinal_position, de.ref_column_name, rc.ordinal_position FROM __declared_fk de LEFT JOIN _columns c ON (de.table_catalog=c.table_catalog AND de.table_schema=c.table_schema AND de.table_name=c.table_name AND de.column_name=c.column_name) LEFT JOIN _columns rc ON (de.ref_table_catalog=rc.table_catalog AND de.ref_table_schema=rc.table_schema AND de.ref_table_name=rc.table_name AND de.ref_column_name=rc.column_name) WHERE de.constraint_name=##cname::string AND de.table_catalog=##tc::string AND de.table_schema=##ts::string AND de.table_name=##tname::string";
665 GdaDataModel *model, *cmodel = NULL;
666 gint i, nrows;
667 GValue *v1, *v2, *v3;
668 GdaMetaDbObject *dbo;
669
670 dbo = (GdaMetaDbObject*) mt;
671 g_value_set_string ((v1 = gda_value_new (G_TYPE_STRING)), dbo->obj_catalog);
672 g_value_set_string ((v2 = gda_value_new (G_TYPE_STRING)), dbo->obj_schema);
673 g_value_set_string ((v3 = gda_value_new (G_TYPE_STRING)), dbo->obj_name);
674 model = gda_meta_store_extract (mstruct->priv->store, sql1,
675 error, "tc", v1, "ts", v2, "tname", v3, NULL);
676 if (!model)
677 goto onerror;
678
679 nrows = gda_data_model_get_n_rows (model);
680 for (i = 0; i < nrows; i++) {
681 GdaMetaDbObject *ref_dbo = NULL;
682 GdaMetaTableForeignKey *tfk = NULL;
683 const GValue *fk_catalog, *fk_schema, *fk_tname, *fk_name;
684 gboolean ignore = FALSE;
685
686 fk_name = gda_data_model_get_value_at (model, 0, i, error);
687 if (!fk_name) goto onerror;
688 fk_catalog = gda_data_model_get_value_at (model, 1, i, error);
689 if (!fk_catalog) goto onerror;
690 fk_schema = gda_data_model_get_value_at (model, 2, i, error);
691 if (!fk_schema) goto onerror;
692 fk_tname = gda_data_model_get_value_at (model, 3, i, error);
693 if (!fk_tname) goto onerror;
694
695 /* get columns */
696 cmodel = gda_meta_store_extract (mstruct->priv->store, sql2,
697 error, "tc", v1, "ts", v2, "tname", v3,
698 "cname", fk_name, NULL);
699 if (!cmodel)
700 goto onerror;
701
702 /* create new FK structure */
703 tfk = g_new0 (GdaMetaTableForeignKey, 1);
704 tfk->meta_table = dbo;
705 tfk->declared = TRUE;
706 tfk->fk_name = g_value_dup_string (fk_name);
707 tfk->on_update_policy = GDA_META_FOREIGN_KEY_NONE;
708 tfk->on_delete_policy = GDA_META_FOREIGN_KEY_NONE;
709
710 /* ignore if some columns are not found in the schema
711 * (maybe wrong or outdated FK decl) */
712 gint j, cnrows;
713 cnrows = gda_data_model_get_n_rows (cmodel);
714 if (cnrows == 0)
715 ignore = TRUE;
716 else {
717 tfk->cols_nb = cnrows;
718 tfk->fk_cols_array = g_new0 (gint, cnrows);
719 tfk->fk_names_array = g_new0 (gchar *, cnrows);
720 tfk->ref_pk_cols_array = g_new0 (gint, cnrows);
721 tfk->ref_pk_names_array = g_new0 (gchar *, cnrows);
722 }
723 for (j = 0; j < cnrows; j++) {
724 const GValue *ov;
725 ov = gda_data_model_get_value_at (cmodel, 0, j, error);
726 if (!ov) goto onerror;
727 if (G_VALUE_TYPE (ov) != G_TYPE_STRING) {
728 ignore = TRUE;
729 break;
730 }
731 tfk->fk_names_array [j] = g_value_dup_string (ov);
732
733 ov = gda_data_model_get_value_at (cmodel, 1, j, error);
734 if (!ov) goto onerror;
735 if (G_VALUE_TYPE (ov) != G_TYPE_INT) {
736 ignore = TRUE;
737 break;
738 }
739 tfk->fk_cols_array [j] = g_value_get_int (ov);
740
741 ov = gda_data_model_get_value_at (cmodel, 2, j, error);
742 if (!ov) goto onerror;
743 if (G_VALUE_TYPE (ov) != G_TYPE_STRING) {
744 ignore = TRUE;
745 break;
746 }
747 tfk->ref_pk_names_array [j] = g_value_dup_string (ov);
748
749 ov = gda_data_model_get_value_at (cmodel, 3, j, error);
750 if (!ov) goto onerror;
751 if (G_VALUE_TYPE (ov) != G_TYPE_INT) {
752 ignore = TRUE;
753 break;
754 }
755 tfk->ref_pk_cols_array [j] = g_value_get_int (ov);
756 }
757
758 /* ignore if there is already an implemented FK */
759 if (! ignore) {
760 ref_dbo = _meta_struct_get_db_object (mstruct, fk_catalog,
761 fk_schema, fk_tname);
762 if (ref_dbo && find_real_foreign_key (mt, ref_dbo, cmodel))
763 ignore = TRUE;
764 }
765 if (ignore) {
766 /* ignore this FK end move on to the next one */
767 if (tfk)
768 gda_meta_table_foreign_key_free (tfk);
769 continue;
770 }
771
772 tfk->depend_on = ref_dbo;
773 if (!tfk->depend_on) {
774 gchar *str;
775 tfk->depend_on = g_new0 (GdaMetaDbObject, 1);
776 tfk->depend_on->obj_type = GDA_META_DB_UNKNOWN;
777 tfk->depend_on->obj_catalog = g_strdup (g_value_get_string (fk_catalog));
778 tfk->depend_on->obj_schema = g_strdup (g_value_get_string (fk_schema));
779 tfk->depend_on->obj_name = g_strdup (g_value_get_string (fk_tname));
780 mstruct->priv->db_objects = g_slist_append (mstruct->priv->db_objects, tfk->depend_on);
781 str = g_strdup_printf ("%s.%s.%s", g_value_get_string (fk_catalog),
782 g_value_get_string (fk_schema),
783 g_value_get_string (fk_tname));
784 g_hash_table_insert (mstruct->priv->index, str, tfk->depend_on);
785 }
786 else if (tfk->depend_on->obj_type == GDA_META_DB_TABLE) {
787 GdaMetaTable *dot = GDA_META_TABLE (tfk->depend_on);
788 dot->reverse_fk_list = g_slist_prepend (dot->reverse_fk_list, tfk);
789 }
790
791 dbo->depend_list = g_slist_append (dbo->depend_list, tfk->depend_on);
792 mt->fk_list = g_slist_prepend (mt->fk_list, tfk);
793 }
794 g_object_unref (model);
795 if (cmodel)
796 g_object_unref (cmodel);
797
798 gda_value_free (v1);
799 gda_value_free (v2);
800 gda_value_free (v3);
801
802 return TRUE;
803
804 onerror:
805 if (model)
806 g_object_unref (model);
807 if (cmodel)
808 g_object_unref (cmodel);
809 gda_value_free (v1);
810 gda_value_free (v2);
811 gda_value_free (v3);
812
813 return FALSE;
814 }
815
816 static GdaMetaDbObject *
_meta_struct_complement(GdaMetaStruct * mstruct,GdaMetaDbObjectType type,const GValue * icatalog,const GValue * ischema,const GValue * iname,const GValue * short_name,const GValue * full_name,const GValue * owner,GError ** error)817 _meta_struct_complement (GdaMetaStruct *mstruct, GdaMetaDbObjectType type,
818 const GValue *icatalog, const GValue *ischema, const GValue *iname,
819 const GValue *short_name, const GValue *full_name, const GValue *owner, GError **error)
820 {
821 /* at this point icatalog, ischema and iname are NOT NULL */
822 GdaMetaDbObject *dbo = NULL;
823 const GValue *cvalue;
824
825 /* create new GdaMetaDbObject or get already existing one */
826 dbo = _meta_struct_get_db_object (mstruct, icatalog, ischema, iname);
827 if (!dbo) {
828 dbo = g_new0 (GdaMetaDbObject, 1);
829 dbo->obj_catalog = g_strdup (g_value_get_string (icatalog));
830 dbo->obj_schema = g_strdup (g_value_get_string (ischema));
831 dbo->obj_name = g_strdup (g_value_get_string (iname));
832 if (short_name)
833 dbo->obj_short_name = g_strdup (g_value_get_string (short_name));
834 if (full_name)
835 dbo->obj_full_name = g_strdup (g_value_get_string (full_name));
836 if (owner && !gda_value_is_null (owner))
837 dbo->obj_owner = g_strdup (g_value_get_string (owner));
838 }
839 else if (dbo->obj_type == type)
840 return dbo; /* nothing to do */
841 else if (dbo->obj_type != GDA_META_DB_UNKNOWN) {
842 /* DB Object already exists, return an error */
843 g_set_error (error, GDA_META_STRUCT_ERROR, GDA_META_STRUCT_DUPLICATE_OBJECT_ERROR,
844 _("Object %s.%s.%s already exists in GdaMetaStruct and has a different object type"),
845 g_value_get_string (icatalog), g_value_get_string (ischema),
846 g_value_get_string (iname));
847 dbo = NULL;
848 goto onerror;
849 }
850 dbo->obj_type = type;
851
852 switch (type) {
853 case GDA_META_DB_VIEW: {
854 gchar *sql = "SELECT view_definition, is_updatable, table_short_name, table_full_name, table_owner "
855 "FROM _views NATURAL JOIN _tables "
856 "WHERE table_catalog = ##tc::string "
857 "AND table_schema = ##ts::string AND table_name = ##tname::string";
858 GdaDataModel *model;
859 gint nrows;
860 GdaMetaView *mv;
861
862 model = gda_meta_store_extract (mstruct->priv->store, sql,
863 error, "tc", icatalog, "ts", ischema, "tname", iname, NULL);
864 if (!model)
865 goto onerror;
866 nrows = gda_data_model_get_n_rows (model);
867 if (nrows < 1) {
868 g_object_unref (model);
869 g_set_error (error, GDA_META_STRUCT_ERROR, GDA_META_STRUCT_UNKNOWN_OBJECT_ERROR,
870 _("View %s.%s.%s not found in meta store object"),
871 g_value_get_string (icatalog), g_value_get_string (ischema),
872 g_value_get_string (iname));
873 goto onerror;
874 }
875
876 if (!dbo->obj_short_name) {
877 cvalue = gda_data_model_get_value_at (model, 2, 0, error);
878 if (!cvalue) goto onerror;
879 dbo->obj_short_name = g_value_dup_string (cvalue);
880 }
881 if (!dbo->obj_full_name) {
882 cvalue = gda_data_model_get_value_at (model, 3, 0, error);
883 if (!cvalue) goto onerror;
884 dbo->obj_full_name = g_value_dup_string (cvalue);
885 }
886 if (!dbo->obj_owner) {
887 cvalue = gda_data_model_get_value_at (model, 4, 0, error);
888 if (!cvalue) goto onerror;
889 if (!gda_value_is_null (cvalue))
890 dbo->obj_owner = g_value_dup_string (cvalue);
891 }
892
893 mv = GDA_META_VIEW (dbo);
894 cvalue = gda_data_model_get_value_at (model, 0, 0, error);
895 if (!cvalue) goto onerror;
896 if (G_VALUE_TYPE (cvalue) != GDA_TYPE_NULL)
897 mv->view_def = g_value_dup_string (cvalue);
898 else
899 mv->view_def = g_strdup ("");
900
901 cvalue = gda_data_model_get_value_at (model, 1, 0, error);
902 if (!cvalue) goto onerror;
903 if (G_VALUE_TYPE (cvalue) != GDA_TYPE_NULL)
904 mv->is_updatable = g_value_get_boolean (cvalue);
905 else
906 mv->is_updatable = FALSE;
907
908 /* view's dependencies, from its definition */
909 if ((mstruct->priv->features & GDA_META_STRUCT_FEATURE_VIEW_DEPENDENCIES) &&
910 mv->view_def && *mv->view_def) {
911 static GdaSqlParser *parser = NULL;
912 GdaStatement *stmt;
913 const gchar *remain;
914 if (!parser)
915 parser = gda_sql_parser_new ();
916 stmt = gda_sql_parser_parse_string (parser, mv->view_def, &remain, NULL);
917 if (stmt &&
918 ((gda_statement_get_statement_type (stmt) == GDA_SQL_STATEMENT_SELECT) ||
919 (gda_statement_get_statement_type (stmt) == GDA_SQL_STATEMENT_COMPOUND))) {
920 GdaSqlStatement *sqlst;
921 g_object_get (G_OBJECT (stmt), "structure", &sqlst, NULL);
922 compute_view_dependencies (mstruct, dbo, sqlst);
923 gda_sql_statement_free (sqlst);
924 g_object_unref (stmt);
925
926 #ifdef GDA_DEBUG_NO
927 g_print ("View %s depends on: ", dbo->obj_name);
928 GSList *list;
929 for (list = dbo->depend_list; list; list = list->next)
930 g_print ("%s ", GDA_META_DB_OBJECT (list->data)->obj_name);
931 g_print ("\n");
932 #endif
933 }
934 }
935 }
936 case GDA_META_DB_TABLE: {
937 /* columns */
938 gchar *sql = "SELECT c.column_name, c.data_type, c.gtype, c.is_nullable, t.table_short_name, t.table_full_name, c.column_default, t.table_owner, c.array_spec, c.extra, c.column_comments, coalesce (c.character_maximum_length, c.character_octet_length) FROM _tables as t LEFT NATURAL JOIN _columns as c WHERE table_catalog = ##tc::string AND table_schema = ##ts::string AND table_name = ##tname::string ORDER BY ordinal_position";
939 GdaMetaTable *mt;
940 GdaDataModel *model;
941 gint i, nrows;
942
943 model = gda_meta_store_extract (mstruct->priv->store, sql,
944 error, "tc", icatalog, "ts", ischema, "tname", iname, NULL);
945 if (!model)
946 goto onerror;
947
948 nrows = gda_data_model_get_n_rows (model);
949 if (nrows < 1) {
950 g_object_unref (model);
951 g_set_error (error, GDA_META_STRUCT_ERROR, GDA_META_STRUCT_UNKNOWN_OBJECT_ERROR,
952 _("Table %s.%s.%s not found (or missing columns information)"),
953 g_value_get_string (icatalog), g_value_get_string (ischema),
954 g_value_get_string (iname));
955 goto onerror;
956 }
957 if (!dbo->obj_short_name) {
958 cvalue = gda_data_model_get_value_at (model, 4, 0, error);
959 if (!cvalue) goto onerror;
960 dbo->obj_short_name = g_value_dup_string (cvalue);
961 }
962 if (!dbo->obj_full_name) {
963 cvalue = gda_data_model_get_value_at (model, 5, 0, error);
964 if (!cvalue) goto onerror;
965 dbo->obj_full_name = g_value_dup_string (cvalue);
966 }
967 if (!dbo->obj_owner) {
968 cvalue = gda_data_model_get_value_at (model, 7, 0, error);
969 if (!cvalue) goto onerror;
970 if (!gda_value_is_null (cvalue))
971 dbo->obj_owner = g_value_dup_string (cvalue);
972 }
973
974 cvalue = gda_data_model_get_value_at (model, 0, 0, error);
975 if (cvalue && (G_VALUE_TYPE (cvalue) == GDA_TYPE_NULL)) {
976 if (type == GDA_META_DB_VIEW) {
977 /* we don't have the list of columns for the view.
978 * This can sometimes happen in SQLite */
979 nrows = 0;
980 }
981 }
982 mt = GDA_META_TABLE (dbo);
983 for (i = 0; i < nrows; i++) {
984 GdaMetaTableColumn *tcol;
985 const gchar *cstr = NULL;
986 gint len = -1;
987 tcol = g_new0 (GdaMetaTableColumn, 1); /* Note: tcol->pkey is not determined here */
988 mt->columns = g_slist_prepend (mt->columns, tcol);
989
990 cvalue = gda_data_model_get_value_at (model, 0, i, error);
991 if (!cvalue) goto onerror;
992 tcol->column_name = g_value_dup_string (cvalue);
993
994 cvalue = gda_data_model_get_value_at (model, 1, i, error);
995 if (!cvalue) goto onerror;
996 if (!gda_value_is_null (cvalue))
997 cstr = g_value_get_string (cvalue);
998
999 cvalue = gda_data_model_get_value_at (model, 11, i, error);
1000 if (!cvalue) goto onerror;
1001 if (!gda_value_is_null (cvalue))
1002 len = g_value_get_int (cvalue);
1003
1004 if (cstr && *cstr) {
1005 if (len >= 0)
1006 tcol->column_type = g_strdup_printf ("%s (%d)", cstr, len);
1007 else
1008 tcol->column_type = g_strdup (cstr);
1009 }
1010 else {
1011 cvalue = gda_data_model_get_value_at (model, 8, i, error);
1012 if (!cvalue) goto onerror;
1013 tcol->column_type = array_type_to_sql (mstruct->priv->store, cvalue);
1014 if (!tcol->column_type)
1015 goto onerror;
1016 }
1017
1018 cvalue = gda_data_model_get_value_at (model, 2, i, error);
1019 if (!cvalue) goto onerror;
1020 tcol->gtype = gda_g_type_from_string (g_value_get_string (cvalue));
1021 if (tcol->gtype == G_TYPE_INVALID)
1022 tcol->gtype = GDA_TYPE_NULL;
1023
1024 cvalue = gda_data_model_get_value_at (model, 3, i, error);
1025 if (!cvalue) goto onerror;
1026 tcol->nullok = g_value_get_boolean (cvalue);
1027
1028 cvalue = gda_data_model_get_value_at (model, 6, i, error);
1029 if (!cvalue) goto onerror;
1030 if (!gda_value_is_null (cvalue))
1031 tcol->default_value = g_value_dup_string (cvalue);
1032
1033 cvalue = gda_data_model_get_value_at (model, 9, i, error);
1034 if (!cvalue) goto onerror;
1035 if (!gda_value_is_null (cvalue)) {
1036 gchar **array, *tmp;
1037 gint ai;
1038 GValue *true_value;
1039
1040 g_value_set_boolean ((true_value = gda_value_new (G_TYPE_BOOLEAN)), TRUE);
1041 cstr = g_value_get_string (cvalue);
1042 array = g_strsplit (cstr, ",", 0);
1043 for (ai = 0; array [ai]; ai++) {
1044 tmp = g_strstrip (array [ai]);
1045 if (!strcmp (tmp, GDA_EXTRA_AUTO_INCREMENT))
1046 gda_attributes_manager_set (att_mgr, tcol, GDA_ATTRIBUTE_AUTO_INCREMENT,
1047 true_value);
1048 else
1049 g_message ("Unknown EXTRA attribute '%s', please report this bug to "
1050 "http://bugzilla.gnome.org/ for the \"libgda\" product.", tmp);
1051 }
1052 gda_value_free (true_value);
1053 g_strfreev (array);
1054 }
1055
1056 cvalue = gda_data_model_get_value_at (model, 10, i, error);
1057 if (!cvalue) goto onerror;
1058 if (!gda_value_is_null (cvalue))
1059 gda_attributes_manager_set (att_mgr, tcol, GDA_ATTRIBUTE_DESCRIPTION,
1060 cvalue);
1061
1062 }
1063 mt->columns = g_slist_reverse (mt->columns);
1064 g_object_unref (model);
1065
1066 /* primary key */
1067 sql = "SELECT constraint_name FROM _table_constraints WHERE constraint_type='PRIMARY KEY' AND table_catalog = ##tc::string AND table_schema = ##ts::string AND table_name = ##tname::string";
1068 model = gda_meta_store_extract (mstruct->priv->store, sql,
1069 error, "tc", icatalog, "ts", ischema, "tname", iname, NULL);
1070 if (!model)
1071 goto onerror;
1072
1073 nrows = gda_data_model_get_n_rows (model);
1074 if (nrows >= 1) {
1075 GdaDataModel *pkmodel;
1076 sql = "SELECT column_name FROM _key_column_usage WHERE table_catalog = ##cc::string AND table_schema = ##cs::string AND table_name = ##tname::string AND constraint_name = ##cname::string ORDER BY ordinal_position";
1077 cvalue = gda_data_model_get_value_at (model, 0, 0, error);
1078 if (!cvalue) goto onerror;
1079 pkmodel = gda_meta_store_extract (mstruct->priv->store, sql, error,
1080 "cc", icatalog,
1081 "cs", ischema,
1082 "tname", iname,
1083 "cname", cvalue, NULL);
1084 if (!pkmodel) {
1085 g_object_unref (model);
1086 goto onerror;
1087 }
1088 nrows = gda_data_model_get_n_rows (pkmodel);
1089 mt->pk_cols_nb = nrows;
1090 mt->pk_cols_array = g_new0 (gint, mt->pk_cols_nb);
1091 for (i = 0; i < nrows; i++) {
1092 GdaMetaTableColumn *tcol;
1093 cvalue = gda_data_model_get_value_at (pkmodel, 0, i, error);
1094 if (!cvalue) goto onerror;
1095 tcol = gda_meta_struct_get_table_column (mstruct, mt, cvalue);
1096 if (!tcol) {
1097 mt->pk_cols_array [i] = -1;
1098 g_set_error (error, GDA_META_STRUCT_ERROR, GDA_META_STRUCT_INCOHERENCE_ERROR,
1099 _("Internal GdaMetaStore error: column %s not found"),
1100 g_value_get_string (cvalue));
1101 goto onerror;
1102 }
1103 else {
1104 mt->pk_cols_array [i] = g_slist_index (mt->columns, tcol);
1105 tcol->pkey = TRUE;
1106 }
1107 }
1108
1109 g_object_unref (pkmodel);
1110 }
1111 g_object_unref (model);
1112
1113 /* foreign keys */
1114 if (mstruct->priv->features & GDA_META_STRUCT_FEATURE_FOREIGN_KEYS) {
1115 sql = "SELECT ref_table_catalog, ref_table_schema, ref_table_name, constraint_name, ref_constraint_name, update_rule, delete_rule, constraint_name FROM _referential_constraints WHERE table_catalog = ##tc::string AND table_schema = ##ts::string AND table_name = ##tname::string";
1116 model = gda_meta_store_extract (mstruct->priv->store, sql, error,
1117 "tc", icatalog,
1118 "ts", ischema,
1119 "tname", iname, NULL);
1120 if (!model)
1121 goto onerror;
1122
1123 nrows = gda_data_model_get_n_rows (model);
1124 for (i = 0; i < nrows; i++) {
1125 GdaMetaTableForeignKey *tfk = NULL;
1126 const GValue *fk_catalog, *fk_schema, *fk_tname, *fk_name;
1127 const GValue *upd_policy, *del_policy;
1128
1129 GdaDataModel *fk_cols = NULL;
1130 GdaDataModel *ref_pk_cols = NULL;
1131
1132 fk_catalog = gda_data_model_get_value_at (model, 0, i, error);
1133 if (!fk_catalog) goto onfkerror;
1134 fk_schema = gda_data_model_get_value_at (model, 1, i, error);
1135 if (!fk_schema) goto onfkerror;
1136 fk_tname = gda_data_model_get_value_at (model, 2, i, error);
1137 if (!fk_tname) goto onfkerror;
1138 upd_policy = gda_data_model_get_value_at (model, 5, i, error);
1139 if (!upd_policy) goto onfkerror;
1140 del_policy = gda_data_model_get_value_at (model, 6, i, error);
1141 if (!del_policy) goto onfkerror;
1142 fk_name = gda_data_model_get_value_at (model, 7, i, error);
1143 if (!fk_name) goto onfkerror;
1144
1145 tfk = g_new0 (GdaMetaTableForeignKey, 1);
1146 tfk->meta_table = dbo;
1147 tfk->fk_name = g_value_dup_string (fk_name);
1148 tfk->depend_on = _meta_struct_get_db_object (mstruct, fk_catalog, fk_schema, fk_tname);
1149 if (!tfk->depend_on) {
1150 gchar *str;
1151 tfk->depend_on = g_new0 (GdaMetaDbObject, 1);
1152 tfk->depend_on->obj_type = GDA_META_DB_UNKNOWN;
1153 tfk->depend_on->obj_catalog = g_strdup (g_value_get_string (fk_catalog));
1154 tfk->depend_on->obj_schema = g_strdup (g_value_get_string (fk_schema));
1155 tfk->depend_on->obj_name = g_strdup (g_value_get_string (fk_tname));
1156 mstruct->priv->db_objects = g_slist_append (mstruct->priv->db_objects, tfk->depend_on);
1157 str = g_strdup_printf ("%s.%s.%s", g_value_get_string (fk_catalog),
1158 g_value_get_string (fk_schema),
1159 g_value_get_string (fk_tname));
1160 g_hash_table_insert (mstruct->priv->index, str, tfk->depend_on);
1161 }
1162 else if (tfk->depend_on->obj_type == GDA_META_DB_TABLE) {
1163 GdaMetaTable *dot = GDA_META_TABLE (tfk->depend_on);
1164 dot->reverse_fk_list = g_slist_prepend (dot->reverse_fk_list, tfk);
1165 }
1166 dbo->depend_list = g_slist_append (dbo->depend_list, tfk->depend_on);
1167
1168 if (G_VALUE_TYPE (upd_policy) == G_TYPE_STRING)
1169 tfk->on_update_policy = policy_string_to_value (g_value_get_string (upd_policy));
1170 else
1171 tfk->on_update_policy = GDA_META_FOREIGN_KEY_UNKNOWN;
1172
1173 if (G_VALUE_TYPE (upd_policy) == G_TYPE_STRING)
1174 tfk->on_delete_policy = policy_string_to_value (g_value_get_string (del_policy));
1175 else
1176 tfk->on_delete_policy = GDA_META_FOREIGN_KEY_UNKNOWN;
1177
1178 tfk->declared = FALSE;
1179
1180 /* FIXME: compute @cols_nb, and all the @*_array members (ref_pk_cols_array must be
1181 * initialized with -1 values everywhere */
1182 sql = "SELECT k.column_name, c.ordinal_position FROM _key_column_usage k INNER JOIN _columns c ON (c.table_catalog = k.table_catalog AND c.table_schema = k.table_schema AND c.table_name=k.table_name AND c.column_name=k.column_name) WHERE k.table_catalog = ##tc::string AND k.table_schema = ##ts::string AND k.table_name = ##tname::string AND k.constraint_name = ##cname::string ORDER BY k.ordinal_position";
1183 gboolean fkerror = FALSE;
1184 cvalue = gda_data_model_get_value_at (model, 3, i, error);
1185 if (!cvalue) goto onfkerror;
1186 fk_cols = gda_meta_store_extract (mstruct->priv->store, sql, error,
1187 "tc", icatalog,
1188 "ts", ischema,
1189 "tname", iname,
1190 "cname", cvalue, NULL);
1191 /*g_print ("tname=%s cvalue=%s\n", gda_value_stringify (iname),
1192 gda_value_stringify (cvalue));*/
1193
1194 cvalue = gda_data_model_get_value_at (model, 4, i, error);
1195 if (!cvalue) goto onfkerror;
1196 ref_pk_cols = gda_meta_store_extract (mstruct->priv->store, sql, error,
1197 "tc", fk_catalog,
1198 "ts", fk_schema,
1199 "tname", fk_tname,
1200 "cname", cvalue, NULL);
1201 /*g_print ("tname=%s cvalue=%s\n", gda_value_stringify (fk_tname),
1202 gda_value_stringify (cvalue));*/
1203
1204 if (fk_cols && ref_pk_cols) {
1205 gint fk_nrows, ref_pk_nrows;
1206 fk_nrows = gda_data_model_get_n_rows (fk_cols);
1207 ref_pk_nrows = gda_data_model_get_n_rows (ref_pk_cols);
1208 if (fk_nrows != ref_pk_nrows) {
1209 /*gda_data_model_dump (fk_cols, stdout);
1210 gda_data_model_dump (ref_pk_cols, stdout);*/
1211 if (ref_pk_nrows > 0)
1212 fkerror = TRUE;
1213 else {
1214 /* not an error, only the referenced table is not present
1215 * in the meta store, which is possible if the meta
1216 * store was only partially updated */
1217 }
1218 }
1219 else {
1220 gint n;
1221 tfk->cols_nb = fk_nrows;
1222 tfk->fk_cols_array = g_new0 (gint, fk_nrows);
1223 tfk->fk_names_array = g_new0 (gchar *, fk_nrows);
1224 tfk->ref_pk_cols_array = g_new0 (gint, fk_nrows);
1225 tfk->ref_pk_names_array = g_new0 (gchar *, fk_nrows);
1226 for (n = 0; n < fk_nrows; n++) {
1227 const GValue *cv;
1228 cv = gda_data_model_get_value_at (fk_cols, 1, n, error);
1229 if (!cv) goto onfkerror;
1230 tfk->fk_cols_array [n] = g_value_get_int (cv);
1231
1232 cv = gda_data_model_get_value_at (fk_cols, 0, n, error);
1233 if (!cv) goto onfkerror;
1234 tfk->fk_names_array [n] = g_value_dup_string (cv);
1235
1236 cv = gda_data_model_get_value_at (ref_pk_cols, 1, n, error);
1237 if (!cv) goto onfkerror;
1238 tfk->ref_pk_cols_array [n] = g_value_get_int (cv);
1239
1240 cv = gda_data_model_get_value_at (ref_pk_cols, 0, n, error);
1241 if (!cv) goto onfkerror;
1242 tfk->ref_pk_names_array [n] = g_value_dup_string (cv);
1243 }
1244 }
1245 }
1246 else
1247 fkerror = TRUE;
1248
1249 if (fkerror) {
1250 g_set_error (error, GDA_META_STRUCT_ERROR, GDA_META_STRUCT_INCOHERENCE_ERROR,
1251 _("Meta data incoherence in foreign key constraint for table %s.%s.%s "
1252 "referencing table %s.%s.%s"),
1253 g_value_get_string (icatalog),
1254 g_value_get_string (ischema),
1255 g_value_get_string (iname),
1256 g_value_get_string (fk_catalog),
1257 g_value_get_string (fk_schema),
1258 g_value_get_string (fk_tname));
1259 goto onfkerror;
1260 }
1261 if (fk_cols)
1262 g_object_unref (fk_cols);
1263 if (ref_pk_cols)
1264 g_object_unref (ref_pk_cols);
1265
1266 mt->fk_list = g_slist_prepend (mt->fk_list, tfk);
1267 continue;
1268
1269 onfkerror:
1270 if (fk_cols)
1271 g_object_unref (fk_cols);
1272 if (ref_pk_cols)
1273 g_object_unref (ref_pk_cols);
1274 if (tfk)
1275 mt->fk_list = g_slist_prepend (mt->fk_list, tfk);
1276 goto onerror;
1277 }
1278 mt->fk_list = g_slist_reverse (mt->fk_list);
1279 g_object_unref (model);
1280 /* Note: mt->reverse_fk_list is not determined here */
1281
1282 add_declared_foreign_keys (mstruct, mt, NULL);
1283 }
1284
1285 break;
1286 }
1287 default:
1288 TO_IMPLEMENT;
1289 }
1290
1291 if (dbo && !g_slist_find (mstruct->priv->db_objects, dbo)) {
1292 gchar *str;
1293 mstruct->priv->db_objects = g_slist_append (mstruct->priv->db_objects, dbo);
1294 str = g_strdup_printf ("%s.%s.%s", g_value_get_string (icatalog),
1295 g_value_get_string (ischema),
1296 g_value_get_string (iname));
1297 g_hash_table_insert (mstruct->priv->index, str, dbo);
1298 }
1299 if (dbo && (dbo->obj_type == GDA_META_DB_TABLE) &&
1300 (mstruct->priv->features & GDA_META_STRUCT_FEATURE_FOREIGN_KEYS)) {
1301 /* compute GdaMetaTableForeignKey's @ref_pk_cols_array arrays and GdaMetaTable' @reverse_fk_list lists*/
1302 GSList *list;
1303 for (list = mstruct->priv->db_objects; list; list = list->next) {
1304 GdaMetaDbObject *tmpdbo;
1305 tmpdbo = GDA_META_DB_OBJECT (list->data);
1306 if (tmpdbo->obj_type != GDA_META_DB_TABLE)
1307 continue;
1308
1309 GdaMetaTable *mt = GDA_META_TABLE (tmpdbo);
1310 GSList *klist;
1311 for (klist = mt->fk_list; klist; klist = klist->next) {
1312 GdaMetaTableForeignKey *tfk = GDA_META_TABLE_FOREIGN_KEY (klist->data);
1313 GdaMetaTable *ref_mt = GDA_META_TABLE (tfk->depend_on);
1314 gint i;
1315
1316 if (tfk->depend_on != dbo)
1317 continue;
1318
1319 for (i = 0; i < tfk->cols_nb; i++) {
1320 gint col;
1321 GdaMetaTableColumn *r_tcol;
1322 GValue *r_val;
1323
1324 if (tfk->ref_pk_cols_array[i] != -1) /* already correctly set */
1325 continue;
1326
1327 if (tfk->depend_on->obj_type != GDA_META_DB_TABLE)
1328 continue; /* can't be set now */
1329
1330 g_value_set_string ((r_val = gda_value_new (G_TYPE_STRING)), tfk->ref_pk_names_array[i]);
1331 r_tcol = gda_meta_struct_get_table_column (mstruct, ref_mt, r_val);
1332 gda_value_free (r_val);
1333 col = g_slist_index (ref_mt->columns, r_tcol);
1334 if (!r_tcol || (col < 0)) {
1335 g_set_error (error, GDA_META_STRUCT_ERROR, GDA_META_STRUCT_INCOHERENCE_ERROR,
1336 _("Foreign key column '%s' not found in table '%s'"),
1337 tfk->ref_pk_names_array[i], tfk->depend_on->obj_name);
1338 dbo = NULL;
1339 goto onerror;
1340 }
1341 tfk->ref_pk_cols_array[i] = col;
1342 }
1343
1344 GDA_META_TABLE (dbo)->reverse_fk_list = g_slist_append (GDA_META_TABLE (dbo)->reverse_fk_list,
1345 tfk);
1346 }
1347 }
1348 }
1349 return dbo;
1350
1351 onerror:
1352 if (dbo)
1353 dbo->obj_type = GDA_META_DB_UNKNOWN;
1354
1355 return NULL;
1356 }
1357
1358 static gchar *
array_type_to_sql(GdaMetaStore * store,const GValue * specific_name)1359 array_type_to_sql (GdaMetaStore *store, const GValue *specific_name)
1360 {
1361 gchar *str;
1362 GdaDataModel *model;
1363 gint nrows;
1364 const GValue *cvalue;
1365
1366 if (!specific_name || gda_value_is_null (specific_name))
1367 return g_strdup ("[]");
1368
1369 model = gda_meta_store_extract (store, "SELECT data_type, array_spec FROM _element_types WHERE specific_name = ##name::string",
1370 NULL, "name", specific_name, NULL);
1371 if (!model)
1372 return g_strdup ("[]");
1373 nrows = gda_data_model_get_n_rows (model);
1374 if (nrows != 1) {
1375 g_object_unref (model);
1376 return g_strdup ("[]");
1377 }
1378
1379 cvalue = gda_data_model_get_value_at (model, 0, 0, NULL);
1380 if (!cvalue)
1381 return NULL;
1382 if (gda_value_is_null (cvalue) || !g_value_get_string (cvalue)) {
1383 /* use array_spec */
1384 gchar *str2;
1385 cvalue = gda_data_model_get_value_at (model, 1, 0, NULL);
1386 if (!cvalue)
1387 return NULL;
1388 str2 = array_type_to_sql (store, cvalue);
1389 str = g_strdup_printf ("%s[]", str2);
1390 g_free (str2);
1391 }
1392 else {
1393 cvalue = gda_data_model_get_value_at (model, 0, 0, NULL);
1394 if (!cvalue)
1395 return NULL;
1396 str = g_strdup_printf ("%s[]", g_value_get_string (cvalue));
1397 }
1398 g_object_unref (model);
1399 return str;
1400 }
1401
1402
1403 /**
1404 * gda_meta_struct_complement_schema:
1405 * @mstruct: a #GdaMetaStruct object
1406 * @catalog: (allow-none): name of a catalog, or %NULL
1407 * @schema: (allow-none): name of a schema, or %NULL
1408 * @error: (allow-none): a place to store errors, or %NULL
1409 *
1410 * This method is similar to gda_meta_struct_complement() but creates #GdaMetaDbObject for all the
1411 * database object which are in the @schema schema (and in the @catalog catalog).
1412 * If @catalog is %NULL, then any catalog will be used, and
1413 * if @schema is %NULL then any schema will be used (if @schema is %NULL then catalog must also be %NULL).
1414 *
1415 * Please refer to gda_meta_struct_complement() form more information.
1416 *
1417 * Returns: TRUE if no error occurred
1418 */
1419 gboolean
gda_meta_struct_complement_schema(GdaMetaStruct * mstruct,const GValue * catalog,const GValue * schema,GError ** error)1420 gda_meta_struct_complement_schema (GdaMetaStruct *mstruct, const GValue *catalog, const GValue *schema,
1421 GError **error)
1422 {
1423 GdaDataModel *tables_model = NULL, *views_model = NULL;
1424 gint i, nrows, k;
1425 const GValue *cvalues[6];
1426
1427 /* schema and catalog are known */
1428 const gchar *sql1 = "SELECT table_name "
1429 "FROM _tables WHERE table_short_name, table_full_name, table_owner, table_catalog = ##cat::string AND table_schema = ##schema::string "
1430 "AND table_type LIKE '%TABLE%' "
1431 "ORDER BY table_schema, table_name";
1432 const gchar *sql2 = "SELECT table_short_name, table_full_name, table_owner, table_name "
1433 "FROM _tables WHERE table_catalog = ##cat::string AND table_schema = ##schema::string "
1434 "AND table_type LIKE '%VIEW%' "
1435 "ORDER BY table_schema, table_name";
1436
1437 /* schema is known, catalog unknown */
1438 const gchar *sql3 = "SELECT table_short_name, table_full_name, table_owner, table_name, table_catalog, table_schema "
1439 "FROM _tables WHERE table_schema = ##schema::string AND table_type LIKE '%TABLE%' "
1440 "ORDER BY table_schema, table_name";
1441 const gchar *sql4 = "SELECT table_short_name, table_full_name, table_owner, table_name, table_catalog, table_schema "
1442 "FROM _tables WHERE table_schema = ##schema::string AND table_type LIKE '%VIEW%' "
1443 "ORDER BY table_schema, table_name";
1444
1445 /* schema and catalog are unknown */
1446 const gchar *sql5 = "SELECT table_short_name, table_full_name, table_owner, table_name, table_catalog, table_schema "
1447 "FROM _tables WHERE table_type LIKE '%TABLE%' "
1448 "ORDER BY table_schema, table_name";
1449 const gchar *sql6 = "SELECT table_short_name, table_full_name, table_owner, table_name, table_catalog, table_schema "
1450 "FROM _tables WHERE table_type LIKE '%VIEW%' "
1451 "ORDER BY table_schema, table_name";
1452
1453 g_return_val_if_fail (GDA_IS_META_STRUCT (mstruct), FALSE);
1454 g_return_val_if_fail (mstruct->priv->store, FALSE);
1455 g_return_val_if_fail (!catalog || (catalog && schema), FALSE);
1456 g_return_val_if_fail (!catalog || (G_VALUE_TYPE (catalog) == G_TYPE_STRING), FALSE);
1457 g_return_val_if_fail (!schema || (G_VALUE_TYPE (schema) == G_TYPE_STRING), FALSE);
1458
1459 if (schema) {
1460 if (catalog) {
1461 tables_model = gda_meta_store_extract (mstruct->priv->store, sql1, error,
1462 "cat", catalog, "schema", schema, NULL);
1463 if (tables_model)
1464 views_model = gda_meta_store_extract (mstruct->priv->store, sql2, error,
1465 "cat", catalog, "schema", schema, NULL);
1466 }
1467 else {
1468 tables_model = gda_meta_store_extract (mstruct->priv->store, sql3,
1469 error, "schema", schema, NULL);
1470 if (tables_model)
1471 views_model = gda_meta_store_extract (mstruct->priv->store, sql4,
1472 error, "schema", schema, NULL);
1473 }
1474 }
1475 else {
1476 tables_model = gda_meta_store_extract (mstruct->priv->store, sql5, error, NULL);
1477 if (tables_model)
1478 views_model = gda_meta_store_extract (mstruct->priv->store, sql6, error, NULL);
1479 }
1480
1481 if (!tables_model || !views_model)
1482 return FALSE;
1483
1484 /* tables */
1485 nrows = gda_data_model_get_n_rows (tables_model);
1486 for (i = 0; i < nrows; i++) {
1487 for (k = 0; k <= 5; k++) {
1488 cvalues [k] = gda_data_model_get_value_at (tables_model, k, i, error);
1489 if (!cvalues [k]) {
1490 g_object_unref (tables_model);
1491 g_object_unref (views_model);
1492 return FALSE;
1493 }
1494 }
1495 if (!_meta_struct_complement (mstruct, GDA_META_DB_TABLE,
1496 catalog ? catalog : cvalues [4],
1497 schema ? schema : cvalues [5],
1498 cvalues [3],
1499 cvalues [0],
1500 cvalues [1],
1501 cvalues [2], error)) {
1502 g_object_unref (tables_model);
1503 g_object_unref (views_model);
1504 return FALSE;
1505 }
1506 }
1507 g_object_unref (tables_model);
1508
1509 /* views */
1510 nrows = gda_data_model_get_n_rows (views_model);
1511 for (i = 0; i < nrows; i++) {
1512 for (k = 0; k <= 5; k++) {
1513 cvalues [k] = gda_data_model_get_value_at (views_model, k, i, error);
1514 if (!cvalues [k]) {
1515 g_object_unref (views_model);
1516 return FALSE;
1517 }
1518 }
1519 if (!_meta_struct_complement (mstruct, GDA_META_DB_VIEW,
1520 catalog ? catalog : cvalues [4],
1521 schema ? schema : cvalues [5],
1522 cvalues [3],
1523 cvalues [0],
1524 cvalues [1],
1525 cvalues [2], error)) {
1526 g_object_unref (views_model);
1527 return FALSE;
1528 }
1529 }
1530 g_object_unref (views_model);
1531
1532 return TRUE;
1533 }
1534
1535 static gboolean
real_gda_meta_struct_complement_all(GdaMetaStruct * mstruct,gboolean default_only,GError ** error)1536 real_gda_meta_struct_complement_all (GdaMetaStruct *mstruct, gboolean default_only, GError **error)
1537 {
1538 GdaDataModel *model;
1539 gint i, nrows, k;
1540 const GValue *cvalues[6];
1541 const gchar *sql1 = "SELECT table_catalog, table_schema, table_name, table_short_name, table_full_name, table_owner "
1542 "FROM _tables WHERE table_short_name = table_name AND table_type LIKE '%TABLE%' "
1543 "ORDER BY table_schema, table_name";
1544 const gchar *sql2 = "SELECT table_catalog, table_schema, table_name, table_short_name, table_full_name, table_owner "
1545 "FROM _tables WHERE table_short_name = table_name AND table_type='VIEW' "
1546 "ORDER BY table_schema, table_name";
1547 const gchar *sql3 = "SELECT table_catalog, table_schema, table_name, table_short_name, table_full_name, table_owner "
1548 "FROM _tables WHERE table_type LIKE '%TABLE%' "
1549 "ORDER BY table_schema, table_name";
1550 const gchar *sql4 = "SELECT table_catalog, table_schema, table_name, table_short_name, table_full_name, table_owner "
1551 "FROM _tables WHERE table_type='VIEW' "
1552 "ORDER BY table_schema, table_name";
1553
1554 g_return_val_if_fail (GDA_IS_META_STRUCT (mstruct), FALSE);
1555 g_return_val_if_fail (mstruct->priv->store, FALSE);
1556
1557 /* tables */
1558 model = gda_meta_store_extract (mstruct->priv->store, default_only ? sql1 : sql3, error, NULL);
1559 if (!model)
1560 return FALSE;
1561 nrows = gda_data_model_get_n_rows (model);
1562 for (i = 0; i < nrows; i++) {
1563 for (k = 0; k <= 5; k++) {
1564 cvalues [k] = gda_data_model_get_value_at (model, k, i, error);
1565 if (!cvalues [k]) {
1566 g_object_unref (model);
1567 return FALSE;
1568 }
1569 }
1570 if (!_meta_struct_complement (mstruct, GDA_META_DB_TABLE,
1571 cvalues [0], cvalues [1],
1572 cvalues [2], cvalues [3],
1573 cvalues [4], cvalues [5], error)) {
1574 g_object_unref (model);
1575 return FALSE;
1576 }
1577 }
1578 g_object_unref (model);
1579
1580 /* views */
1581 model = gda_meta_store_extract (mstruct->priv->store, default_only ? sql2 : sql4, error, NULL);
1582 if (!model)
1583 return FALSE;
1584 nrows = gda_data_model_get_n_rows (model);
1585 for (i = 0; i < nrows; i++) {
1586 for (k = 0; k <= 5; k++) {
1587 cvalues [k] = gda_data_model_get_value_at (model, k, i, error);
1588 if (!cvalues [k]) {
1589 g_object_unref (model);
1590 return FALSE;
1591 }
1592 }
1593 if (!_meta_struct_complement (mstruct, GDA_META_DB_VIEW,
1594 cvalues [0], cvalues [1],
1595 cvalues [2], cvalues [3],
1596 cvalues [4], cvalues [5], error)) {
1597 g_object_unref (model);
1598 return FALSE;
1599 }
1600 }
1601 g_object_unref (model);
1602 return TRUE;
1603 }
1604
1605 /**
1606 * gda_meta_struct_complement_default:
1607 * @mstruct: a #GdaMetaStruct object
1608 * @error: (allow-none): a place to store errors, or %NULL
1609 *
1610 * This method is similar to gda_meta_struct_complement() and gda_meta_struct_complement_all()
1611 * but creates #GdaMetaDbObject for all the
1612 * database object which are usable using only their short name (that is which do not need to be prefixed by
1613 * the schema in which they are to be used).
1614 *
1615 * Please refer to gda_meta_struct_complement() form more information.
1616 *
1617 * Returns: TRUE if no error occurred
1618 */
1619 gboolean
gda_meta_struct_complement_default(GdaMetaStruct * mstruct,GError ** error)1620 gda_meta_struct_complement_default (GdaMetaStruct *mstruct, GError **error)
1621 {
1622 return real_gda_meta_struct_complement_all (mstruct, TRUE, error);
1623 }
1624
1625 /**
1626 * gda_meta_struct_complement_all:
1627 * @mstruct: a #GdaMetaStruct object
1628 * @error: (allow-none): a place to store errors, or %NULL
1629 *
1630 * This method is similar to gda_meta_struct_complement() and gda_meta_struct_complement_default()
1631 * but creates #GdaMetaDbObject for all the database object.
1632 *
1633 * Please refer to gda_meta_struct_complement() form more information.
1634 *
1635 * Returns: TRUE if no error occurred
1636 */
1637 gboolean
gda_meta_struct_complement_all(GdaMetaStruct * mstruct,GError ** error)1638 gda_meta_struct_complement_all (GdaMetaStruct *mstruct, GError **error)
1639 {
1640 return real_gda_meta_struct_complement_all (mstruct, FALSE, error);
1641 }
1642
1643 /**
1644 * gda_meta_struct_complement_depend:
1645 * @mstruct: a #GdaMetaStruct object
1646 * @dbo: a #GdaMetaDbObject part of @mstruct
1647 * @error: (allow-none): a place to store errors, or %NULL
1648 *
1649 * This method is similar to gda_meta_struct_complement() but creates #GdaMetaDbObject for all the dependencies
1650 * of @dbo.
1651 *
1652 * Please refer to gda_meta_struct_complement() form more information.
1653 *
1654 * Returns: TRUE if no error occurred
1655 */
1656 gboolean
gda_meta_struct_complement_depend(GdaMetaStruct * mstruct,GdaMetaDbObject * dbo,GError ** error)1657 gda_meta_struct_complement_depend (GdaMetaStruct *mstruct, GdaMetaDbObject *dbo,
1658 GError **error)
1659 {
1660 GSList *list;
1661
1662 g_return_val_if_fail (GDA_IS_META_STRUCT (mstruct), FALSE);
1663 g_return_val_if_fail (mstruct->priv->store, FALSE);
1664 g_return_val_if_fail (dbo, FALSE);
1665 g_return_val_if_fail (g_slist_find (mstruct->priv->db_objects, dbo), FALSE);
1666
1667 for (list = dbo->depend_list; list; list = list->next) {
1668 GdaMetaDbObject *dep_dbo = GDA_META_DB_OBJECT (list->data);
1669 if (dep_dbo->obj_type != GDA_META_DB_UNKNOWN)
1670 continue;
1671
1672 GValue *cat = NULL, *schema = NULL, *name = NULL;
1673 GdaMetaDbObject *tmpobj;
1674 g_return_val_if_fail (dep_dbo->obj_name, FALSE);
1675 if (dep_dbo->obj_catalog)
1676 g_value_take_string ((cat = gda_value_new (G_TYPE_STRING)),
1677 g_strdup_printf ("\"%s\"", dep_dbo->obj_catalog));
1678 if (dep_dbo->obj_schema)
1679 g_value_take_string ((schema = gda_value_new (G_TYPE_STRING)),
1680 g_strdup_printf ("\"%s\"", dep_dbo->obj_schema));
1681 g_value_take_string ((name = gda_value_new (G_TYPE_STRING)),
1682 g_strdup_printf ("\"%s\"", dep_dbo->obj_name));
1683 tmpobj = gda_meta_struct_complement (mstruct, GDA_META_DB_UNKNOWN, cat, schema, name, error);
1684 if (cat) gda_value_free (cat);
1685 if (schema) gda_value_free (schema);
1686 gda_value_free (name);
1687 if (!tmpobj)
1688 return FALSE;
1689 }
1690 return TRUE;
1691 }
1692
1693
1694 /*
1695 * Makes a list of all the GdaMetaDbObject structures listed in @objects
1696 * which are not present in @ordered_list and for which no dependency is in @ordered_list
1697 */
1698 static GSList *
build_pass(GSList * objects,GSList * ordered_list)1699 build_pass (GSList *objects, GSList *ordered_list)
1700 {
1701 GSList *retlist = NULL, *list;
1702
1703 for (list = objects; list; list = list->next) {
1704 gboolean has_dep = FALSE;
1705 GSList *dep_list;
1706 if (g_slist_find (ordered_list, list->data))
1707 continue;
1708 for (dep_list = GDA_META_DB_OBJECT (list->data)->depend_list; dep_list; dep_list = dep_list->next) {
1709 if (!g_slist_find (ordered_list, dep_list->data)) {
1710 has_dep = TRUE;
1711 break;
1712 }
1713 }
1714 if (has_dep)
1715 continue;
1716 retlist = g_slist_prepend (retlist, list->data);
1717 }
1718
1719 #ifdef GDA_DEBUG_NO
1720 g_print (">> PASS\n");
1721 for (list = retlist; list; list = list->next)
1722 g_print ("--> %s\n", GDA_META_DB_OBJECT (list->data)->obj_name);
1723 g_print ("<<\n");
1724 #endif
1725
1726 return retlist;
1727 }
1728
1729 static gint
db_object_sort_func(GdaMetaDbObject * dbo1,GdaMetaDbObject * dbo2)1730 db_object_sort_func (GdaMetaDbObject *dbo1, GdaMetaDbObject *dbo2)
1731 {
1732 gint retval = 0;
1733 if (dbo1->obj_schema && dbo2->obj_schema) {
1734 retval = strcmp (dbo1->obj_schema, dbo2->obj_schema);
1735 if (retval)
1736 return retval;
1737 }
1738 else if (dbo1->obj_schema)
1739 return 1;
1740 else if (dbo2->obj_schema)
1741 return -1;
1742
1743 if (dbo1->obj_name && dbo2->obj_name)
1744 return strcmp (dbo1->obj_name, dbo2->obj_name);
1745 else if (dbo1->obj_name)
1746 return 1;
1747 else if (dbo2->obj_name)
1748 return -1;
1749 return 0;
1750 }
1751
1752 /**
1753 * gda_meta_struct_sort_db_objects:
1754 * @mstruct: a #GdaMetaStruct object
1755 * @sort_type: the kind of sorting requested
1756 * @error: (allow-none): a place to store errors, or %NULL
1757 *
1758 * Reorders the list of database objects within @mstruct in a way specified by @sort_type.
1759 *
1760 * Returns: TRUE if no error occurred
1761 */
1762 gboolean
gda_meta_struct_sort_db_objects(GdaMetaStruct * mstruct,GdaMetaSortType sort_type,G_GNUC_UNUSED GError ** error)1763 gda_meta_struct_sort_db_objects (GdaMetaStruct *mstruct, GdaMetaSortType sort_type,
1764 G_GNUC_UNUSED GError **error)
1765 {
1766 GSList *pass_list;
1767 GSList *ordered_list = NULL;
1768
1769 g_return_val_if_fail (GDA_IS_META_STRUCT (mstruct), FALSE);
1770
1771 switch (sort_type) {
1772 case GDA_META_SORT_ALHAPETICAL:
1773 mstruct->priv->db_objects = g_slist_sort (mstruct->priv->db_objects, (GCompareFunc) db_object_sort_func);
1774 ordered_list = mstruct->priv->db_objects;
1775 break;
1776 case GDA_META_SORT_DEPENDENCIES:
1777 g_return_val_if_fail (mstruct, FALSE);
1778 for (pass_list = build_pass (mstruct->priv->db_objects, ordered_list);
1779 pass_list;
1780 pass_list = build_pass (mstruct->priv->db_objects, ordered_list))
1781 ordered_list = g_slist_concat (ordered_list, pass_list);
1782 g_slist_free (mstruct->priv->db_objects);
1783 mstruct->priv->db_objects = ordered_list;
1784 break;
1785 default:
1786 TO_IMPLEMENT;
1787 break;
1788 }
1789
1790 #ifdef GDA_DEBUG_NO
1791 GSList *list;
1792 for (list = ordered_list; list; list = list->next)
1793 g_print ("--> %s\n", GDA_META_DB_OBJECT (list->data)->obj_name);
1794 #endif
1795 return TRUE;
1796 }
1797
1798 /*
1799 * Same as gda_meta_struct_get_db_object except that @catalog, @schema and @name are ready to be
1800 * compared (no need to double quote)
1801 */
1802 static GdaMetaDbObject *
_meta_struct_get_db_object(GdaMetaStruct * mstruct,const GValue * catalog,const GValue * schema,const GValue * name)1803 _meta_struct_get_db_object (GdaMetaStruct *mstruct, const GValue *catalog, const GValue *schema, const GValue *name)
1804 {
1805 gchar *key;
1806 GdaMetaDbObject *dbo;
1807
1808 if (catalog && schema) {
1809 g_return_val_if_fail (G_VALUE_TYPE (catalog) == G_TYPE_STRING, NULL);
1810 g_return_val_if_fail (G_VALUE_TYPE (schema) == G_TYPE_STRING, NULL);
1811
1812 key = g_strdup_printf ("%s.%s.%s", g_value_get_string (catalog), g_value_get_string (schema),
1813 g_value_get_string (name));
1814 dbo = g_hash_table_lookup (mstruct->priv->index, key);
1815 g_free (key);
1816 return dbo;
1817 }
1818 else {
1819 /* walk through all the objects, and pick the ones with a matching name */
1820 GSList *list;
1821 GSList *matching = NULL;
1822 const gchar *obj_name = g_value_get_string (name);
1823 const gchar *obj_schema = NULL, *obj_catalog = NULL;
1824 if (catalog) {
1825 g_return_val_if_fail (G_VALUE_TYPE (catalog) == G_TYPE_STRING, NULL);
1826 obj_catalog = g_value_get_string (catalog);
1827 }
1828 if (schema) {
1829 g_return_val_if_fail (G_VALUE_TYPE (schema) == G_TYPE_STRING, NULL);
1830 obj_schema = g_value_get_string (schema);
1831 }
1832
1833 for (list = mstruct->priv->db_objects; list; list = list->next) {
1834 GdaMetaDbObject *dbo;
1835 dbo = GDA_META_DB_OBJECT (list->data);
1836 if (gda_identifier_equal (dbo->obj_name, obj_name) &&
1837 (!obj_schema || gda_identifier_equal (dbo->obj_schema, obj_schema)) &&
1838 (!obj_catalog || gda_identifier_equal (dbo->obj_catalog, obj_catalog)))
1839 matching = g_slist_prepend (matching, dbo);
1840 }
1841
1842 if (matching && !matching->next) {
1843 GdaMetaDbObject *dbo = GDA_META_DB_OBJECT (matching->data);
1844 g_slist_free (matching);
1845 return dbo;
1846 }
1847 else {
1848 /* none or more than one found => return NULL */
1849 if (matching)
1850 g_slist_free (matching);
1851 return NULL;
1852 }
1853 }
1854 }
1855
1856 /**
1857 * gda_meta_struct_get_all_db_objects:
1858 * @mstruct: a #GdaMetaStruct object
1859 *
1860 * Get a list of all the #GdaMetaDbObject structures representing database objects in @mstruct. Note that
1861 * no #GdaMetaDbObject structure must not be modified.
1862 *
1863 * Returns: (transfer container) (element-type Gda.MetaDbObject): a new #GSList list of pointers to
1864 * #GdaMetaDbObject structures which must be destroyed after usage using g_slist_free(). The individual
1865 * #GdaMetaDbObject must not be modified.
1866 */
1867 GSList *
gda_meta_struct_get_all_db_objects(GdaMetaStruct * mstruct)1868 gda_meta_struct_get_all_db_objects (GdaMetaStruct *mstruct)
1869 {
1870 g_return_val_if_fail (GDA_IS_META_STRUCT (mstruct), NULL);
1871 if (mstruct->priv->db_objects)
1872 return g_slist_copy (mstruct->priv->db_objects);
1873 else
1874 return NULL;
1875 }
1876
1877 /**
1878 * gda_meta_struct_get_db_object:
1879 * @mstruct: a #GdaMetaStruct object
1880 * @catalog: (allow-none): the catalog the object belongs to (as a G_TYPE_STRING GValue), or %NULL
1881 * @schema: (allow-none): the schema the object belongs to (as a G_TYPE_STRING GValue), or %NULL
1882 * @name: the object's name (as a G_TYPE_STRING GValue), not %NULL
1883 *
1884 * Tries to locate the #GdaMetaDbObject structure representing the database object named after
1885 * @catalog, @schema and @name.
1886 *
1887 * If one or both of @catalog and @schema are %NULL, and more than one database object matches the name, then
1888 * the return value is also %NULL.
1889 *
1890 * Returns: (transfer none): the #GdaMetaDbObject or %NULL if not found
1891 */
1892 GdaMetaDbObject *
gda_meta_struct_get_db_object(GdaMetaStruct * mstruct,const GValue * catalog,const GValue * schema,const GValue * name)1893 gda_meta_struct_get_db_object (GdaMetaStruct *mstruct, const GValue *catalog, const GValue *schema, const GValue *name)
1894 {
1895 GdaMetaDbObject *dbo;
1896 GValue *icatalog = NULL, *ischema = NULL, *iname = NULL; /* GValue with identifiers ready to be compared */
1897
1898 g_return_val_if_fail (GDA_IS_META_STRUCT (mstruct), NULL);
1899 g_return_val_if_fail (name && (G_VALUE_TYPE (name) == G_TYPE_STRING), NULL);
1900 g_return_val_if_fail (!catalog || (catalog && schema), NULL);
1901 g_return_val_if_fail (!catalog || (G_VALUE_TYPE (catalog) == G_TYPE_STRING), NULL);
1902 g_return_val_if_fail (!schema || (G_VALUE_TYPE (schema) == G_TYPE_STRING), NULL);
1903
1904 /* prepare identifiers */
1905 g_value_take_string ((iname = gda_value_new (G_TYPE_STRING)), prepare_sql_identifier_for_compare (g_value_dup_string (name)));
1906 if (catalog)
1907 g_value_take_string ((icatalog = gda_value_new (G_TYPE_STRING)),
1908 prepare_sql_identifier_for_compare (g_value_dup_string (catalog)));
1909 if (schema)
1910 g_value_take_string ((ischema = gda_value_new (G_TYPE_STRING)),
1911 prepare_sql_identifier_for_compare (g_value_dup_string (schema)));
1912
1913 dbo = _meta_struct_get_db_object (mstruct, icatalog, ischema, iname);
1914 if (icatalog) gda_value_free (icatalog);
1915 if (ischema) gda_value_free (ischema);
1916 gda_value_free (iname);
1917
1918 return dbo;
1919 }
1920
1921 /**
1922 * gda_meta_struct_get_table_column: (skip)
1923 * @mstruct: a #GdaMetaStruct object
1924 * @table: the #GdaMetaTable structure to find the column for
1925 * @col_name: the name of the column to find (as a G_TYPE_STRING GValue)
1926 *
1927 * Tries to find the #GdaMetaTableColumn representing the column named @col_name in @table.
1928 *
1929 * Returns: (transfer none): the #GdaMetaTableColumn or %NULL if not found
1930 */
1931 GdaMetaTableColumn *
gda_meta_struct_get_table_column(GdaMetaStruct * mstruct,GdaMetaTable * table,const GValue * col_name)1932 gda_meta_struct_get_table_column (GdaMetaStruct *mstruct, GdaMetaTable *table, const GValue *col_name)
1933 {
1934 GSList *list;
1935 const gchar *cname;
1936
1937 g_return_val_if_fail (GDA_IS_META_STRUCT (mstruct), NULL);
1938 g_return_val_if_fail (table, NULL);
1939 g_return_val_if_fail (col_name && (G_VALUE_TYPE (col_name) == G_TYPE_STRING), NULL);
1940 cname = g_value_get_string (col_name);
1941
1942 for (list = table->columns; list; list = list->next) {
1943 GdaMetaTableColumn *tcol = GDA_META_TABLE_COLUMN (list->data);
1944 if (gda_identifier_equal (tcol->column_name, cname))
1945 return tcol;
1946 }
1947 return NULL;
1948 }
1949
1950 /**
1951 * gda_meta_struct_dump_as_graph:
1952 * @mstruct: a #GdaMetaStruct object
1953 * @info: informs what kind of information to show in the resulting graph
1954 * @error: (allow-none): a place to store errors, or %NULL
1955 *
1956 * Creates a new graph (in the GraphViz syntax) representation of @mstruct.
1957 *
1958 * Returns: (transfer full): a new string, or %NULL if an error occurred.
1959 */
1960 gchar *
gda_meta_struct_dump_as_graph(GdaMetaStruct * mstruct,GdaMetaGraphInfo info,G_GNUC_UNUSED GError ** error)1961 gda_meta_struct_dump_as_graph (GdaMetaStruct *mstruct, GdaMetaGraphInfo info, G_GNUC_UNUSED GError **error)
1962 {
1963 GString *string;
1964 gchar *result;
1965
1966 g_return_val_if_fail (GDA_IS_META_STRUCT (mstruct), NULL);
1967
1968 string = g_string_new ("digraph G {\nrankdir = BT;\nnode [shape = plaintext];\n");
1969 GSList *dbo_list;
1970 for (dbo_list = mstruct->priv->db_objects; dbo_list; dbo_list = dbo_list->next) {
1971 gchar *objname, *fullname;
1972 GdaMetaDbObject *dbo = GDA_META_DB_OBJECT (dbo_list->data);
1973 GSList *list;
1974 gboolean use_html = (info & GDA_META_GRAPH_COLUMNS) ? TRUE : FALSE;
1975
1976 /* obj human readable name, and full name */
1977 fullname = g_strdup_printf ("%s.%s.%s", dbo->obj_catalog, dbo->obj_schema, dbo->obj_name);
1978 if (dbo->obj_short_name)
1979 objname = g_strdup (dbo->obj_short_name);
1980 else if (dbo->obj_schema)
1981 objname = g_strdup_printf ("%s.%s", dbo->obj_schema, dbo->obj_name);
1982 else
1983 objname = g_strdup (dbo->obj_name);
1984
1985 /* node */
1986 switch (dbo->obj_type) {
1987 case GDA_META_DB_UNKNOWN:
1988 break;
1989 case GDA_META_DB_TABLE:
1990 if (use_html) {
1991 g_string_append_printf (string, "\"%s\" [label=<<TABLE BORDER=\"1\" CELLBORDER=\"0\" CELLSPACING=\"0\">", fullname);
1992 g_string_append_printf (string, "<TR><TD COLSPAN=\"2\" BGCOLOR=\"grey\" BORDER=\"1\">%s</TD></TR>", objname);
1993 }
1994 else
1995 g_string_append_printf (string, "\"%s\" [ shape = box label = \"%s\" ]", fullname, objname);
1996 break;
1997 case GDA_META_DB_VIEW:
1998 if (use_html) {
1999 g_string_append_printf (string, "\"%s\" [label=<<TABLE BORDER=\"1\" CELLBORDER=\"0\" CELLSPACING=\"0\">", fullname);
2000 g_string_append_printf (string, "<TR><TD BGCOLOR=\"yellow\" BORDER=\"1\">%s</TD></TR>", objname);
2001 }
2002 else
2003 g_string_append_printf (string, "\"%s\" [ shape = ellipse, label = \"%s\" ]", fullname, objname);
2004 break;
2005 default:
2006 TO_IMPLEMENT;
2007 g_string_append_printf (string, "\"%s\" [ shape = note label = \"%s\" ]", fullname, objname);
2008 break;
2009 }
2010
2011 /* columns, only for tables */
2012 if (dbo->obj_type == GDA_META_DB_TABLE) {
2013 GdaMetaTable *mt = GDA_META_TABLE (dbo);
2014 GSList *depend_dbo_list = NULL;
2015 if (info & GDA_META_GRAPH_COLUMNS) {
2016 for (list = mt->columns; list; list = list->next) {
2017 GdaMetaTableColumn *tcol = GDA_META_TABLE_COLUMN (list->data);
2018 GString *extra = g_string_new ("");
2019 if (tcol->pkey)
2020 g_string_append_printf (extra, "key");
2021 g_string_append_printf (string, "<TR><TD ALIGN=\"left\">%s</TD><TD ALIGN=\"right\">%s</TD></TR>",
2022 tcol->column_name, extra->str);
2023 g_string_free (extra, TRUE);
2024 }
2025 }
2026 if (use_html)
2027 g_string_append (string, "</TABLE>>];\n");
2028 /* foreign keys */
2029 for (list = mt->fk_list; list; list = list->next) {
2030 GdaMetaTableForeignKey *tfk = GDA_META_TABLE_FOREIGN_KEY (list->data);
2031 if (tfk->depend_on->obj_type != GDA_META_DB_UNKNOWN) {
2032 g_string_append_printf (string, "\"%s\" -> \"%s.%s.%s\";\n", fullname,
2033 tfk->depend_on->obj_catalog, tfk->depend_on->obj_schema,
2034 tfk->depend_on->obj_name);
2035 depend_dbo_list = g_slist_prepend (depend_dbo_list, tfk->depend_on);
2036 }
2037 }
2038
2039 /* dependencies other than foreign keys */
2040 for (list = dbo->depend_list; list; list = list->next) {
2041 if (!g_slist_find (depend_dbo_list, list->data)) {
2042 GdaMetaDbObject *dep_dbo = GDA_META_DB_OBJECT (list->data);
2043 if (dep_dbo->obj_type != GDA_META_DB_UNKNOWN)
2044 g_string_append_printf (string, "\"%s\" -> \"%s.%s.%s\";\n",
2045 fullname,
2046 dep_dbo->obj_catalog, dep_dbo->obj_schema,
2047 dep_dbo->obj_name);
2048 }
2049 }
2050
2051 g_slist_free (depend_dbo_list);
2052 }
2053 else if (dbo->obj_type == GDA_META_DB_VIEW) {
2054 GdaMetaTable *mt = GDA_META_TABLE (dbo);
2055 if (info & GDA_META_GRAPH_COLUMNS) {
2056 for (list = mt->columns; list; list = list->next) {
2057 GdaMetaTableColumn *tcol = GDA_META_TABLE_COLUMN (list->data);
2058 g_string_append_printf (string, "<TR><TD ALIGN=\"left\">%s</TD></TR>", tcol->column_name);
2059 }
2060 }
2061 if (use_html)
2062 g_string_append (string, "</TABLE>>];\n");
2063 /* dependencies */
2064 for (list = dbo->depend_list; list; list = list->next) {
2065 GdaMetaDbObject *ddbo = GDA_META_DB_OBJECT (list->data);
2066 if (ddbo->obj_type != GDA_META_DB_UNKNOWN)
2067 g_string_append_printf (string, "\"%s\" -> \"%s.%s.%s\";\n", fullname,
2068 ddbo->obj_catalog, ddbo->obj_schema,
2069 ddbo->obj_name);
2070 }
2071 }
2072
2073 g_free (objname);
2074 g_free (fullname);
2075 }
2076 g_string_append_c (string, '}');
2077
2078 result = string->str;
2079 g_string_free (string, FALSE);
2080 return result;
2081 }
2082
2083 static void
gda_meta_db_object_free_contents(GdaMetaDbObject * dbo)2084 gda_meta_db_object_free_contents (GdaMetaDbObject *dbo)
2085 {
2086 g_free (dbo->obj_catalog);
2087 g_free (dbo->obj_schema);
2088 g_free (dbo->obj_name);
2089 g_free (dbo->obj_short_name);
2090 g_free (dbo->obj_full_name);
2091 g_free (dbo->obj_owner);
2092 switch (dbo->obj_type) {
2093 case GDA_META_DB_UNKNOWN:
2094 break;
2095 case GDA_META_DB_TABLE:
2096 gda_meta_table_free_contents (GDA_META_TABLE (dbo));
2097 break;
2098 case GDA_META_DB_VIEW:
2099 gda_meta_view_free_contents (GDA_META_VIEW (dbo));
2100 break;
2101 default:
2102 TO_IMPLEMENT;
2103 }
2104 g_slist_free (dbo->depend_list);
2105 memset (dbo, 0, sizeof (GdaMetaDbObject));
2106 }
2107
2108 static void
gda_meta_db_object_free(GdaMetaDbObject * dbo)2109 gda_meta_db_object_free (GdaMetaDbObject *dbo)
2110 {
2111 gda_meta_db_object_free_contents (dbo);
2112 g_free (dbo);
2113 }
2114
2115 static void
gda_meta_table_free_contents(GdaMetaTable * table)2116 gda_meta_table_free_contents (GdaMetaTable *table)
2117 {
2118 g_slist_foreach (table->columns, (GFunc) gda_meta_table_column_free, NULL);
2119 g_slist_free (table->columns);
2120 g_free (table->pk_cols_array);
2121 g_slist_foreach (table->fk_list, (GFunc) gda_meta_table_foreign_key_free, NULL);
2122 g_slist_free (table->fk_list);
2123 g_slist_free (table->reverse_fk_list);
2124 }
2125
2126 static void
gda_meta_view_free_contents(GdaMetaView * view)2127 gda_meta_view_free_contents (GdaMetaView *view)
2128 {
2129 gda_meta_table_free_contents ((GdaMetaTable*) view);
2130 g_free (view->view_def);
2131 }
2132
2133 static void
gda_meta_table_column_free(GdaMetaTableColumn * tcol)2134 gda_meta_table_column_free (GdaMetaTableColumn *tcol)
2135 {
2136 g_free (tcol->column_name);
2137 g_free (tcol->column_type);
2138 g_free (tcol->default_value);
2139 gda_attributes_manager_clear (att_mgr, tcol);
2140 g_free (tcol);
2141 }
2142
2143 static void
gda_meta_table_foreign_key_free(GdaMetaTableForeignKey * tfk)2144 gda_meta_table_foreign_key_free (GdaMetaTableForeignKey *tfk)
2145 {
2146 gint i;
2147 for (i = 0; i < tfk->cols_nb; i++) {
2148 g_free (tfk->fk_names_array[i]);
2149 g_free (tfk->ref_pk_names_array[i]);
2150 }
2151 g_free (tfk->fk_cols_array);
2152 g_free (tfk->fk_names_array);
2153 g_free (tfk->ref_pk_cols_array);
2154 g_free (tfk->ref_pk_names_array);
2155 g_free (tfk->fk_name);
2156 g_free (tfk);
2157 }
2158
2159 static gboolean
determine_db_object_from_schema_and_name(GdaMetaStruct * mstruct,GdaMetaDbObjectType * in_out_type,GValue ** out_catalog,GValue ** out_short_name,GValue ** out_full_name,GValue ** out_owner,const GValue * schema,const GValue * name)2160 determine_db_object_from_schema_and_name (GdaMetaStruct *mstruct,
2161 GdaMetaDbObjectType *in_out_type, GValue **out_catalog,
2162 GValue **out_short_name,
2163 GValue **out_full_name, GValue **out_owner,
2164 const GValue *schema, const GValue *name)
2165 {
2166 const GValue *cvalue;
2167 GdaDataModel *model = NULL;
2168 *out_catalog = NULL;
2169 *out_short_name = NULL;
2170 *out_full_name = NULL;
2171 *out_owner = NULL;
2172
2173 switch (*in_out_type) {
2174 case GDA_META_DB_UNKNOWN: {
2175 GdaMetaDbObjectType type = GDA_META_DB_TABLE;
2176 if (determine_db_object_from_schema_and_name (mstruct, &type, out_catalog,
2177 out_short_name, out_full_name, out_owner,
2178 schema, name)) {
2179 *in_out_type = GDA_META_DB_TABLE;
2180 return TRUE;
2181 }
2182 type = GDA_META_DB_VIEW;
2183 if (determine_db_object_from_schema_and_name (mstruct, &type, out_catalog,
2184 out_short_name, out_full_name, out_owner,
2185 schema, name)) {
2186 *in_out_type = GDA_META_DB_VIEW;
2187 return TRUE;
2188 }
2189 return FALSE;
2190 break;
2191 }
2192
2193 case GDA_META_DB_TABLE: {
2194 const gchar *sql = "SELECT table_catalog, table_short_name, table_full_name, table_owner FROM _tables as t WHERE table_schema = ##ts::string AND table_name = ##tname::string AND table_name NOT IN (SELECT v.table_name FROM _views as v WHERE v.table_catalog=t.table_catalog AND v.table_schema=t.table_schema)";
2195 gint nrows;
2196 model = gda_meta_store_extract (mstruct->priv->store, sql, NULL, "ts", schema, "tname", name, NULL);
2197 if (!model)
2198 return FALSE;
2199
2200 nrows = gda_data_model_get_n_rows (model);
2201 if (nrows != 1) {
2202 g_object_unref (model);
2203 return FALSE;
2204 }
2205 cvalue = gda_data_model_get_value_at (model, 0, 0, NULL);
2206 if (!cvalue) goto copyerror;
2207 *out_catalog = gda_value_copy (cvalue);
2208
2209 cvalue = gda_data_model_get_value_at (model, 1, 0, NULL);
2210 if (!cvalue) goto copyerror;
2211 *out_short_name = gda_value_copy (cvalue);
2212
2213 cvalue = gda_data_model_get_value_at (model, 2, 0, NULL);
2214 if (!cvalue) goto copyerror;
2215 *out_full_name = gda_value_copy (cvalue);
2216
2217 cvalue = gda_data_model_get_value_at (model, 3, 0, NULL);
2218 if (!cvalue) goto copyerror;
2219 *out_owner = gda_value_copy (cvalue);
2220
2221 g_object_unref (model);
2222 return TRUE;
2223 }
2224
2225 case GDA_META_DB_VIEW:{
2226 const gchar *sql = "SELECT table_catalog, table_short_name, table_full_name, table_owner FROM _tables NATURAL JOIN _views WHERE table_schema = ##ts::string AND table_name = ##tname::string";
2227 gint nrows;
2228 model = gda_meta_store_extract (mstruct->priv->store, sql, NULL, "ts", schema, "tname", name, NULL);
2229 if (!model)
2230 return FALSE;
2231
2232 nrows = gda_data_model_get_n_rows (model);
2233 if (nrows != 1) {
2234 g_object_unref (model);
2235 return FALSE;
2236 }
2237 cvalue = gda_data_model_get_value_at (model, 0, 0, NULL);
2238 if (!cvalue) goto copyerror;
2239 *out_catalog = gda_value_copy (cvalue);
2240
2241 cvalue = gda_data_model_get_value_at (model, 1, 0, NULL);
2242 if (!cvalue) goto copyerror;
2243 *out_short_name = gda_value_copy (cvalue);
2244
2245 cvalue = gda_data_model_get_value_at (model, 2, 0, NULL);
2246 if (!cvalue) goto copyerror;
2247 *out_full_name = gda_value_copy (cvalue);
2248
2249 cvalue = gda_data_model_get_value_at (model, 3, 0, NULL);
2250 if (!cvalue) goto copyerror;
2251 *out_owner = gda_value_copy (cvalue);
2252
2253 g_object_unref (model);
2254 return TRUE;
2255 }
2256 default:
2257 TO_IMPLEMENT;
2258 }
2259
2260 copyerror:
2261 if (model)
2262 g_object_unref (model);
2263 if (*out_catalog) {
2264 gda_value_free (*out_catalog);
2265 *out_catalog = NULL;
2266 }
2267 if (*out_short_name) {
2268 gda_value_free (*out_short_name);
2269 *out_short_name = NULL;
2270 }
2271 if (*out_full_name) {
2272 gda_value_free (*out_full_name);
2273 *out_full_name = NULL;
2274 }
2275 if (*out_owner) {
2276 gda_value_free (*out_owner);
2277 *out_owner = NULL;
2278 }
2279
2280 return FALSE;
2281 }
2282
2283 static gboolean
determine_db_object_from_short_name(GdaMetaStruct * mstruct,GdaMetaDbObjectType * in_out_type,GValue ** out_catalog,GValue ** out_schema,GValue ** out_name,GValue ** out_short_name,GValue ** out_full_name,GValue ** out_owner,const GValue * name)2284 determine_db_object_from_short_name (GdaMetaStruct *mstruct,
2285 GdaMetaDbObjectType *in_out_type, GValue **out_catalog,
2286 GValue **out_schema, GValue **out_name, GValue **out_short_name,
2287 GValue **out_full_name, GValue **out_owner, const GValue *name)
2288 {
2289 const GValue *cvalue;
2290 GdaDataModel *model = NULL;
2291 *out_name = NULL;
2292 *out_schema = NULL;
2293 *out_catalog = NULL;
2294 *out_short_name = NULL;
2295 *out_full_name = NULL;
2296 *out_owner = NULL;
2297
2298 /* general lookup */
2299 switch (*in_out_type) {
2300 case GDA_META_DB_UNKNOWN: {
2301 GdaMetaDbObjectType type = GDA_META_DB_TABLE;
2302 if (determine_db_object_from_short_name (mstruct, &type, out_catalog, out_schema, out_name,
2303 out_short_name, out_full_name, out_owner, name)) {
2304 *in_out_type = GDA_META_DB_TABLE;
2305 return TRUE;
2306 }
2307 type = GDA_META_DB_VIEW;
2308 if (determine_db_object_from_short_name (mstruct, &type, out_catalog, out_schema, out_name,
2309 out_short_name, out_full_name, out_owner, name)) {
2310 *in_out_type = GDA_META_DB_VIEW;
2311 return TRUE;
2312 }
2313 return FALSE;
2314 break;
2315 }
2316
2317 case GDA_META_DB_TABLE: {
2318 const gchar *sql = "SELECT table_catalog, table_schema, table_name, table_short_name, table_full_name, table_owner FROM _tables as t WHERE table_short_name = ##tname::string AND table_name NOT IN (SELECT v.table_name FROM _views as v WHERE v.table_catalog=t.table_catalog AND v.table_schema=t.table_schema)";
2319 gint nrows;
2320 model = gda_meta_store_extract (mstruct->priv->store, sql, NULL, "tname", name, NULL);
2321 if (!model)
2322 return FALSE;
2323
2324 nrows = gda_data_model_get_n_rows (model);
2325 if (nrows != 1) {
2326 g_object_unref (model);
2327 goto next;
2328 }
2329
2330 cvalue = gda_data_model_get_value_at (model, 0, 0, NULL);
2331 if (!cvalue) goto copyerror;
2332 *out_catalog = gda_value_copy (cvalue);
2333
2334 cvalue = gda_data_model_get_value_at (model, 1, 0, NULL);
2335 if (!cvalue) goto copyerror;
2336 *out_schema = gda_value_copy (cvalue);
2337
2338 cvalue = gda_data_model_get_value_at (model, 2, 0, NULL);
2339 if (!cvalue) goto copyerror;
2340 *out_name = gda_value_copy (cvalue);
2341
2342 cvalue = gda_data_model_get_value_at (model, 3, 0, NULL);
2343 if (!cvalue) goto copyerror;
2344 *out_short_name = gda_value_copy (cvalue);
2345
2346 cvalue = gda_data_model_get_value_at (model, 4, 0, NULL);
2347 if (!cvalue) goto copyerror;
2348 *out_full_name = gda_value_copy (cvalue);
2349
2350 cvalue = gda_data_model_get_value_at (model, 5, 0, NULL);
2351 if (!cvalue) goto copyerror;
2352 *out_owner = gda_value_copy (cvalue);
2353
2354 g_object_unref (model);
2355 return TRUE;
2356 }
2357
2358 case GDA_META_DB_VIEW:{
2359 const gchar *sql = "SELECT table_catalog, table_schema, table_name, table_short_name, table_full_name, table_owner FROM _tables NATURAL JOIN _views WHERE table_short_name = ##tname::string";
2360 gint nrows;
2361 model = gda_meta_store_extract (mstruct->priv->store, sql, NULL, "tname", name, NULL);
2362 if (!model)
2363 return FALSE;
2364
2365 nrows = gda_data_model_get_n_rows (model);
2366 if (nrows != 1) {
2367 g_object_unref (model);
2368 goto next;
2369 }
2370
2371 cvalue = gda_data_model_get_value_at (model, 0, 0, NULL);
2372 if (!cvalue) goto copyerror;
2373 *out_catalog = gda_value_copy (cvalue);
2374
2375 cvalue = gda_data_model_get_value_at (model, 1, 0, NULL);
2376 if (!cvalue) goto copyerror;
2377 *out_schema = gda_value_copy (cvalue);
2378
2379 cvalue = gda_data_model_get_value_at (model, 2, 0, NULL);
2380 if (!cvalue) goto copyerror;
2381 *out_name = gda_value_copy (cvalue);
2382
2383 cvalue = gda_data_model_get_value_at (model, 3, 0, NULL);
2384 if (!cvalue) goto copyerror;
2385 *out_short_name = gda_value_copy (cvalue);
2386
2387 cvalue = gda_data_model_get_value_at (model, 4, 0, NULL);
2388 if (!cvalue) goto copyerror;
2389 *out_full_name = gda_value_copy (cvalue);
2390
2391 cvalue = gda_data_model_get_value_at (model, 5, 0, NULL);
2392 if (!cvalue) goto copyerror;
2393 *out_owner = gda_value_copy (cvalue);
2394
2395 g_object_unref (model);
2396 return TRUE;
2397 }
2398 default:
2399 TO_IMPLEMENT;
2400 }
2401
2402 next:
2403 model = NULL;
2404 {
2405 /* treat the case where name is in fact <schema>.<name> */
2406 gchar *obj_schema;
2407 gchar *obj_name;
2408 if (_split_identifier_string (g_strdup ((gchar *) g_value_get_string (name)), &obj_schema, &obj_name)) {
2409 GValue *sv, *nv;
2410 gboolean retval;
2411 if (!obj_schema) {
2412 g_free (obj_name);
2413 return FALSE;
2414 }
2415 if (!obj_name) {
2416 g_free (obj_schema);
2417 return FALSE;
2418 }
2419 g_value_take_string ((sv = gda_value_new (G_TYPE_STRING)), prepare_sql_identifier_for_compare (obj_schema));
2420 g_value_take_string ((nv = gda_value_new (G_TYPE_STRING)), prepare_sql_identifier_for_compare (obj_name));
2421 retval = determine_db_object_from_schema_and_name (mstruct, in_out_type, out_catalog,
2422 out_short_name, out_full_name, out_owner,
2423 sv, nv);
2424 if (retval) {
2425 *out_schema = sv;
2426 *out_name = nv;
2427 }
2428 else {
2429 gda_value_free (sv);
2430 gda_value_free (nv);
2431 }
2432 return retval;
2433 }
2434 }
2435
2436 copyerror:
2437 if (model)
2438 g_object_unref (model);
2439 if (*out_catalog) {
2440 gda_value_free (*out_catalog);
2441 *out_catalog = NULL;
2442 }
2443 if (*out_schema) {
2444 gda_value_free (*out_schema);
2445 *out_schema = NULL;
2446 }
2447 if (*out_name) {
2448 gda_value_free (*out_name);
2449 *out_name = NULL;
2450 }
2451 if (*out_short_name) {
2452 gda_value_free (*out_short_name);
2453 *out_short_name = NULL;
2454 }
2455 if (*out_full_name) {
2456 gda_value_free (*out_full_name);
2457 *out_full_name = NULL;
2458 }
2459 if (*out_owner) {
2460 gda_value_free (*out_owner);
2461 *out_owner = NULL;
2462 }
2463
2464 return FALSE;
2465 }
2466
2467 static gboolean
determine_db_object_from_missing_type(GdaMetaStruct * mstruct,GdaMetaDbObjectType * out_type,GValue ** out_short_name,GValue ** out_full_name,GValue ** out_owner,const GValue * catalog,const GValue * schema,const GValue * name)2468 determine_db_object_from_missing_type (GdaMetaStruct *mstruct,
2469 GdaMetaDbObjectType *out_type, GValue **out_short_name,
2470 GValue **out_full_name, GValue **out_owner, const GValue *catalog,
2471 const GValue *schema, const GValue *name)
2472 {
2473 /* try as a view first */
2474 const gchar *sql = "SELECT table_short_name, table_full_name, table_owner FROM _tables NATURAL JOIN _views WHERE table_catalog = ##tc::string AND table_schema = ##ts::string AND table_name = ##tname::string";
2475 GdaDataModel *model = NULL;
2476 const GValue *cvalue;
2477
2478 *out_type = GDA_META_DB_UNKNOWN;
2479 *out_short_name = NULL;
2480 *out_full_name = NULL;
2481 *out_owner = NULL;
2482
2483 model = gda_meta_store_extract (mstruct->priv->store, sql, NULL, "tc", catalog, "ts", schema, "tname", name, NULL);
2484 if (model && (gda_data_model_get_n_rows (model) == 1)) {
2485 *out_type = GDA_META_DB_VIEW;
2486
2487 cvalue = gda_data_model_get_value_at (model, 0, 0, NULL);
2488 if (!cvalue) goto copyerror;
2489 *out_short_name = gda_value_copy (cvalue);
2490
2491 cvalue = gda_data_model_get_value_at (model, 1, 0, NULL);
2492 if (!cvalue) goto copyerror;
2493 *out_full_name = gda_value_copy (cvalue);
2494
2495 cvalue = gda_data_model_get_value_at (model, 2, 0, NULL);
2496 if (!cvalue) goto copyerror;
2497 *out_owner = gda_value_copy (cvalue);
2498
2499 g_object_unref (model);
2500 return TRUE;
2501 }
2502 if (model)
2503 g_object_unref (model);
2504
2505 /* try as a table */
2506 sql = "SELECT table_short_name, table_full_name, table_owner FROM _tables WHERE table_catalog = ##tc::string AND table_schema = ##ts::string AND table_name = ##tname::string";
2507 model = gda_meta_store_extract (mstruct->priv->store, sql, NULL, "tc", catalog, "ts", schema, "tname", name, NULL);
2508 if (model && (gda_data_model_get_n_rows (model) == 1)) {
2509 *out_type = GDA_META_DB_TABLE;
2510
2511 cvalue = gda_data_model_get_value_at (model, 0, 0, NULL);
2512 if (!cvalue) goto copyerror;
2513 *out_short_name = gda_value_copy (cvalue);
2514
2515 cvalue = gda_data_model_get_value_at (model, 1, 0, NULL);
2516 if (!cvalue) goto copyerror;
2517 *out_full_name = gda_value_copy (cvalue);
2518
2519 cvalue = gda_data_model_get_value_at (model, 2, 0, NULL);
2520 if (!cvalue) goto copyerror;
2521 *out_owner = gda_value_copy (cvalue);
2522
2523 g_object_unref (model);
2524 return TRUE;
2525 }
2526 if (model) {
2527 g_object_unref (model);
2528 model = NULL;
2529 }
2530
2531 copyerror:
2532 if (model)
2533 g_object_unref (model);
2534
2535 *out_type = GDA_META_DB_UNKNOWN;
2536 if (*out_short_name) {
2537 gda_value_free (*out_short_name);
2538 *out_short_name = NULL;
2539 }
2540 if (*out_full_name) {
2541 gda_value_free (*out_full_name);
2542 *out_full_name = NULL;
2543 }
2544 if (*out_owner) {
2545 gda_value_free (*out_owner);
2546 *out_owner = NULL;
2547 }
2548 return FALSE;
2549 }
2550
2551 /**
2552 * _gda_meta_struct_add_db_object:
2553 * @mstruct: a #GdaMetaStruct object
2554 * @dbo: a #GdaMetaDbObject structure
2555 * @error: (allow-none): a place to store errors, or %NULL
2556 *
2557 * Adds @dbo to the database objects known to @mstruct. In any case (whether an error occured or not)
2558 * @dbo's ownership is then transferred to @smtruct and should
2559 * not be used after calling this function (it may have been destroyed). If you need a pointer to the #GdaMetaDbObject
2560 * for a database object, use gda_meta_struct_get_db_object().
2561 *
2562 * Returns: (transfer none): a pointer to the #GdaMetaDbObject used in @mstruct to represent the added database object (may be @dbo or not)
2563 */
2564 GdaMetaDbObject *
_gda_meta_struct_add_db_object(GdaMetaStruct * mstruct,GdaMetaDbObject * dbo,GError ** error)2565 _gda_meta_struct_add_db_object (GdaMetaStruct *mstruct, GdaMetaDbObject *dbo, GError **error)
2566 {
2567 GdaMetaDbObject *edbo;
2568 GValue *v1 = NULL, *v2 = NULL, *v3 = NULL;
2569 g_return_val_if_fail (GDA_IS_META_STRUCT (mstruct), NULL);
2570 g_return_val_if_fail (dbo, NULL);
2571
2572 if (!dbo->obj_name) {
2573 g_set_error (error, GDA_META_STRUCT_ERROR, GDA_META_STRUCT_INCOHERENCE_ERROR,
2574 "%s", _("Missing object name in GdaMetaDbObject structure"));
2575 gda_meta_db_object_free (dbo);
2576 return NULL;
2577 }
2578 if (dbo->obj_catalog)
2579 g_value_set_string ((v1 = gda_value_new (G_TYPE_STRING)), dbo->obj_catalog);
2580 if (dbo->obj_schema)
2581 g_value_set_string ((v2 = gda_value_new (G_TYPE_STRING)), dbo->obj_schema);
2582 g_value_set_string ((v3 = gda_value_new (G_TYPE_STRING)), dbo->obj_name);
2583
2584 edbo = gda_meta_struct_get_db_object (mstruct, v1, v2, v3);
2585 if (v1) gda_value_free (v1);
2586 if (v2) gda_value_free (v2);
2587 gda_value_free (v3);
2588
2589 if (edbo) {
2590 if (edbo->obj_type == GDA_META_DB_UNKNOWN) {
2591 /* overwrite */
2592 gda_meta_db_object_free_contents (edbo);
2593 *edbo = *dbo;
2594 g_free (dbo);
2595 return edbo;
2596 }
2597 else {
2598 g_set_error (error, GDA_META_STRUCT_ERROR, GDA_META_STRUCT_DUPLICATE_OBJECT_ERROR,
2599 _("Database object '%s' already exists"), edbo->obj_full_name);
2600 gda_meta_db_object_free (dbo);
2601 return NULL;
2602 }
2603 }
2604 else {
2605 mstruct->priv->db_objects = g_slist_append (mstruct->priv->db_objects, dbo);
2606 g_hash_table_insert (mstruct->priv->index, g_strdup (dbo->obj_full_name), dbo);
2607 return dbo;
2608 }
2609 }
2610
2611 /**
2612 * gda_meta_table_column_get_attribute:
2613 * @tcol: a #GdaMetaTableColumn
2614 * @attribute: attribute name as a string
2615 *
2616 * Get the value associated to a named attribute.
2617 *
2618 * Attributes can have any name, but Libgda proposes some default names, see <link linkend="libgda-5.0-Attributes-manager.synopsis">this section</link>.
2619 *
2620 * Returns: (transfer none): a read-only #GValue, or %NULL if not attribute named @attribute has been set for @column
2621 */
2622 const GValue *
gda_meta_table_column_get_attribute(GdaMetaTableColumn * tcol,const gchar * attribute)2623 gda_meta_table_column_get_attribute (GdaMetaTableColumn *tcol, const gchar *attribute)
2624 {
2625 return gda_attributes_manager_get (att_mgr, tcol, attribute);
2626 }
2627
2628 /**
2629 * gda_meta_table_column_set_attribute:
2630 * @tcol: a #GdaMetaTableColumn
2631 * @attribute: attribute name as a static string
2632 * @value: (allow-none): a #GValue, or %NULL
2633 * @destroy: (allow-none): function called when @attribute has to be freed, or %NULL
2634 *
2635 * Set the value associated to a named attribute.
2636 *
2637 * Attributes can have any name, but Libgda proposes some default names, see <link linkend="libgda-40-Attributes-manager.synopsis">this section</link>.
2638 * If there is already an attribute named @attribute set, then its value is replaced with the new @value,
2639 * except if @value is %NULL, in which case the attribute is removed.
2640 *
2641 * Warning: @attribute is not copied, if it needs to be freed when not used anymore, then @destroy should point to
2642 * the functions which will free it (typically g_free()). If @attribute does not need to be freed, then @destroy can be %NULL.
2643 */
2644 void
gda_meta_table_column_set_attribute(GdaMetaTableColumn * tcol,const gchar * attribute,const GValue * value,GDestroyNotify destroy)2645 gda_meta_table_column_set_attribute (GdaMetaTableColumn *tcol, const gchar *attribute, const GValue *value,
2646 GDestroyNotify destroy)
2647 {
2648 const GValue *cvalue;
2649 cvalue = gda_attributes_manager_get (att_mgr, tcol, attribute);
2650 if ((value && cvalue && !gda_value_differ (cvalue, value)) ||
2651 (!value && !cvalue))
2652 return;
2653
2654 gda_attributes_manager_set_full (att_mgr, tcol, attribute, value, destroy);
2655 }
2656
2657 /**
2658 * gda_meta_table_column_foreach_attribute:
2659 * @tcol: a #GdaMetaTableColumn
2660 * @func: (scope call): a #GdaAttributesManagerFunc function
2661 * @data: (closure): user data to be passed as last argument of @func each time it is called
2662 *
2663 * Calls @func for each attribute set to tcol
2664 */
2665 void
gda_meta_table_column_foreach_attribute(GdaMetaTableColumn * tcol,GdaAttributesManagerFunc func,gpointer data)2666 gda_meta_table_column_foreach_attribute (GdaMetaTableColumn *tcol, GdaAttributesManagerFunc func, gpointer data)
2667 {
2668 gda_attributes_manager_foreach (att_mgr, tcol, func, data);
2669 }
2670