1 /* 2 * Copyright (C) 2008 - 2011 Vivien Malerba <malerba@gnome-db.org> 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the 16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 */ 19 20 #ifndef __GDA_META_STRUCT_H_ 21 #define __GDA_META_STRUCT_H_ 22 23 #include <glib-object.h> 24 #include <libgda/gda-data-model.h> 25 #include <libgda/gda-meta-store.h> 26 #include <libgda/gda-decl.h> 27 #include <libgda/gda-attributes-manager.h> 28 29 G_BEGIN_DECLS 30 31 #define GDA_TYPE_META_STRUCT (gda_meta_struct_get_type()) 32 #define GDA_META_STRUCT(obj) G_TYPE_CHECK_INSTANCE_CAST (obj, gda_meta_struct_get_type(), GdaMetaStruct) 33 #define GDA_META_STRUCT_CLASS(klass) G_TYPE_CHECK_CLASS_CAST (klass, gda_meta_struct_get_type (), GdaMetaStructClass) 34 #define GDA_IS_META_STRUCT(obj) G_TYPE_CHECK_INSTANCE_TYPE (obj, gda_meta_struct_get_type ()) 35 36 /* error reporting */ 37 extern GQuark gda_meta_struct_error_quark (void); 38 #define GDA_META_STRUCT_ERROR gda_meta_struct_error_quark () 39 40 typedef enum { 41 GDA_META_STRUCT_UNKNOWN_OBJECT_ERROR, 42 GDA_META_STRUCT_DUPLICATE_OBJECT_ERROR, 43 GDA_META_STRUCT_INCOHERENCE_ERROR, 44 GDA_META_STRUCT_XML_ERROR 45 } GdaMetaStructError; 46 47 48 /* struct for the object's data */ 49 struct _GdaMetaStruct 50 { 51 GObject object; 52 GdaMetaStructPrivate *priv; 53 }; 54 55 /* struct for the object's class */ 56 struct _GdaMetaStructClass 57 { 58 GObjectClass parent_class; 59 60 /*< private >*/ 61 /* Padding for future expansion */ 62 void (*_gda_reserved1) (void); 63 void (*_gda_reserved2) (void); 64 void (*_gda_reserved3) (void); 65 void (*_gda_reserved4) (void); 66 }; 67 68 /** 69 * GdaMetaDbObjectType: 70 * @GDA_META_DB_UNKNOWN: unknown type 71 * @GDA_META_DB_TABLE: represents a table 72 * @GDA_META_DB_VIEW: represents a view 73 * 74 * Type of database object which can be handled as a #GdaMetaDbObject 75 */ 76 typedef enum { 77 GDA_META_DB_UNKNOWN, 78 GDA_META_DB_TABLE, 79 GDA_META_DB_VIEW 80 } GdaMetaDbObjectType; 81 82 /* 83 * Controls which features are computed about database objects 84 */ 85 /** 86 * GdaMetaStructFeature: 87 * @GDA_META_STRUCT_FEATURE_NONE: database objects only have their own attributes 88 * @GDA_META_STRUCT_FEATURE_FOREIGN_KEYS: foreign keys are computed for tables 89 * @GDA_META_STRUCT_FEATURE_VIEW_DEPENDENCIES: for views, the tables they use are also computed 90 * @GDA_META_STRUCT_FEATURE_ALL: all the features are computed 91 * 92 * Controls which features are computed about database objects. 93 */ 94 typedef enum { 95 GDA_META_STRUCT_FEATURE_NONE = 0, 96 GDA_META_STRUCT_FEATURE_FOREIGN_KEYS = 1 << 0, 97 GDA_META_STRUCT_FEATURE_VIEW_DEPENDENCIES = 1 << 1, 98 99 GDA_META_STRUCT_FEATURE_ALL = GDA_META_STRUCT_FEATURE_FOREIGN_KEYS | 100 GDA_META_STRUCT_FEATURE_VIEW_DEPENDENCIES 101 } GdaMetaStructFeature; 102 103 /** 104 * GdaMetaSortType: 105 * @GDA_META_SORT_ALHAPETICAL: sort alphabetically 106 * @GDA_META_SORT_DEPENDENCIES: sort by dependencies 107 * 108 * Types of sorting 109 */ 110 typedef enum { 111 GDA_META_SORT_ALHAPETICAL, 112 GDA_META_SORT_DEPENDENCIES 113 } GdaMetaSortType; 114 115 /** 116 * GdaMetaTable: 117 * @columns: (element-type Gda.MetaTableColumn): list of #GdaMetaTableColumn structures, one for each column in the table 118 * @pk_cols_array: index of the columns part of the primary key for the table (WARNING: columns numbering 119 * here start at 0) 120 * @pk_cols_nb: size of the @pk_cols_array array 121 * @reverse_fk_list: (element-type Gda.MetaTableForeignKey): list of #GdaMetaTableForeignKey where the referenced table is this table 122 * @fk_list: (element-type Gda.MetaTableForeignKey): list of #GdaMetaTableForeignKey for this table 123 * 124 * This structure specifies a #GdaMetaDbObject to represent a table's specific attributes, 125 * its contents must not be modified. 126 * 127 * Note that in some cases, the columns cannot be determined for views, and in this case the 128 * @columns will be %NULL (this can be the case for example with SQLite where a view 129 * uses a function which is not natively provided by SQLite. 130 */ 131 typedef struct { 132 /*< public >*/ 133 GSList *columns; 134 135 /* PK fields index */ 136 gint *pk_cols_array; 137 gint pk_cols_nb; 138 139 /* Foreign keys */ 140 GSList *reverse_fk_list; /* list of GdaMetaTableForeignKey where @depend_on == this GdaMetaDbObject */ 141 GSList *fk_list; /* list of GdaMetaTableForeignKey where @meta_table == this GdaMetaDbObject */ 142 143 /*< private >*/ 144 /* Padding for future expansion */ 145 gpointer _gda_reserved1; 146 gpointer _gda_reserved2; 147 gpointer _gda_reserved3; 148 gpointer _gda_reserved4; 149 } GdaMetaTable; 150 151 /** 152 * GdaMetaView: 153 * @table: a view is also a table as it has columns 154 * @view_def: views' definition 155 * @is_updatable: tells if the view's contents can be updated 156 * 157 * This structure specifies a #GdaMetaDbObject to represent a view's specific attributes, 158 * its contents must not be modified. 159 */ 160 typedef struct { 161 /*< public >*/ 162 GdaMetaTable table; 163 gchar *view_def; 164 gboolean is_updatable; 165 166 /*< private >*/ 167 /* Padding for future expansion */ 168 gpointer _gda_reserved1; 169 gpointer _gda_reserved2; 170 gpointer _gda_reserved3; 171 gpointer _gda_reserved4; 172 } GdaMetaView; 173 174 /** 175 * GdaMetaDbObject: 176 * @extra: union for the actual object's contents, to be able to cast it using GDA_META_TABLE(), GDA_META_VIEW() 177 * @obj_type: the type of object (table, view) 178 * @outdated: set to %TRUE if the information in this #GdaMetaDbObject may be outdated because the #GdaMetaStore has been updated 179 * @obj_catalog: the catalog the object is in 180 * @obj_schema: the schema the object is in 181 * @obj_name: the object's name 182 * @obj_short_name: the shortest way to name the object 183 * @obj_full_name: the full name of the object (in the <schema>.<nameagt; notation 184 * @obj_owner: object's owner 185 * @depend_list: (element-type Gda.MetaDbObject): list of #GdaMetaDbObject pointers on which this object depends (through foreign keys 186 * or tables used for views) 187 * 188 * Struture to hold information about each database object (tables, views, ...), 189 * its contents must not be modified. 190 * 191 * Note: @obj_catalog, @obj_schema, @obj_name, @obj_short_name and @obj_full_name respect the 192 * <link linkend="information_schema:sql_identifiers">SQL identifiers</link> convention used in 193 * #GdaMetaStore objects. Before using these SQL identifiers, you should check the 194 * gda_sql_identifier_quote() to know if is it is necessary to surround by double quotes 195 * before using in an SQL statement. 196 */ 197 typedef struct { 198 /*< public >*/ 199 union { 200 GdaMetaTable meta_table; 201 GdaMetaView meta_view; 202 } extra; 203 GdaMetaDbObjectType obj_type; 204 gboolean outdated; 205 gchar *obj_catalog; 206 gchar *obj_schema; 207 gchar *obj_name; 208 gchar *obj_short_name; 209 gchar *obj_full_name; 210 gchar *obj_owner; 211 212 GSList *depend_list; 213 214 /*< private >*/ 215 /* Padding for future expansion */ 216 gpointer _gda_reserved1; 217 gpointer _gda_reserved2; 218 gpointer _gda_reserved3; 219 gpointer _gda_reserved4; 220 } GdaMetaDbObject; 221 222 /** 223 * GDA_META_DB_OBJECT: 224 * @dbo: a pointer 225 * 226 * Casts @dbo to a #GdaMetaDbObject, no check is made on the validity of @dbo 227 * 228 * Returns: a pointer to a #GdaMetaDbObject 229 */ 230 #define GDA_META_DB_OBJECT(dbo) ((GdaMetaDbObject*)(dbo)) 231 232 /** 233 * GDA_META_TABLE: 234 * @dbo: a pointer 235 * 236 * Casts @dbo to a #GdaMetaTable, no check is made on the validity of @dbo 237 * 238 * Returns: a pointer to a #GdaMetaTable 239 */ 240 #define GDA_META_TABLE(dbobj) (&((dbobj)->extra.meta_table)) 241 242 /** 243 * GDA_META_VIEW: 244 * @dbo: a pointer 245 * 246 * Casts @dbo to a #GdaMetaView, no check is made on the validity of @dbo 247 * 248 * Returns: a pointer to a #GdaMetaView 249 */ 250 #define GDA_META_VIEW(dbobj) (&((dbobj)->extra.meta_view)) 251 252 /** 253 * GdaMetaTableColumn: 254 * @column_name: the column's name 255 * @column_type: the column's DBMS's type 256 * @gtype: the detected column's #GType 257 * @pkey: tells if the column is part of a primary key 258 * @nullok: tells if the column can be %NULL 259 * @default_value: (allow-none): the column's default value, represented as a valid SQL value (surrounded by simple quotes for strings, ...), or %NULL if column has no default value 260 * 261 * This structure represents a table of view's column, its contents must not be modified. 262 */ 263 typedef struct { 264 /*< public >*/ 265 gchar *column_name; 266 gchar *column_type; 267 GType gtype; 268 gboolean pkey; 269 gboolean nullok; 270 gchar *default_value; 271 272 /*< private >*/ 273 /* Padding for future expansion */ 274 gpointer _gda_reserved1; 275 gpointer _gda_reserved2; 276 gpointer _gda_reserved3; 277 gpointer _gda_reserved4; 278 } GdaMetaTableColumn; 279 280 /** 281 * GDA_META_TABLE_COLUMN: 282 * @col: a pointer 283 * 284 * Casts @col to a #GdaMetaTableColumn, no check is made 285 * 286 * Returns: @col, casted to a #GdaMetaTableColumn 287 */ 288 #define GDA_META_TABLE_COLUMN(col) ((GdaMetaTableColumn*)(col)) 289 290 const GValue *gda_meta_table_column_get_attribute (GdaMetaTableColumn *tcol, const gchar *attribute); 291 void gda_meta_table_column_set_attribute (GdaMetaTableColumn *tcol, const gchar *attribute, const GValue *value, 292 GDestroyNotify destroy); 293 /** 294 * gda_meta_table_column_set_attribute_static: 295 * @column: a #GdaMetaTableColumn 296 * @attribute: attribute's name 297 * @value: (allow-none): a #GValue, or %NULL 298 * 299 * This function is similar to gda_meta_table_column_set_attribute() but for static strings 300 */ 301 #define gda_meta_table_column_set_attribute_static(column,attribute,value) gda_meta_table_column_set_attribute((column),(attribute),(value),NULL) 302 303 void gda_meta_table_column_foreach_attribute (GdaMetaTableColumn *tcol, GdaAttributesManagerFunc func, gpointer data); 304 305 /** 306 * GdaMetaForeignKeyPolicy: 307 * @GDA_META_FOREIGN_KEY_UNKNOWN: unspecified policy 308 * @GDA_META_FOREIGN_KEY_NONE: not enforced policy 309 * @GDA_META_FOREIGN_KEY_NO_ACTION: return an error, no action taken 310 * @GDA_META_FOREIGN_KEY_RESTRICT: same as @GDA_META_FOREIGN_KEY_NO_ACTION, not deferrable 311 * @GDA_META_FOREIGN_KEY_CASCADE: policy is to delete any rows referencing the deleted row, or update the value of the referencing column to the new value of the referenced column, respectively 312 * @GDA_META_FOREIGN_KEY_SET_NULL: policy is to set the referencing column to NULL 313 * @GDA_META_FOREIGN_KEY_SET_DEFAULT: policy is to set the referencing column to its default value 314 * 315 * Defines the filtering policy of a foreign key when invoked on an UPDATE 316 * or DELETE operation. 317 */ 318 typedef enum { 319 GDA_META_FOREIGN_KEY_UNKNOWN, 320 GDA_META_FOREIGN_KEY_NONE, 321 GDA_META_FOREIGN_KEY_NO_ACTION, 322 GDA_META_FOREIGN_KEY_RESTRICT, 323 GDA_META_FOREIGN_KEY_CASCADE, 324 GDA_META_FOREIGN_KEY_SET_NULL, 325 GDA_META_FOREIGN_KEY_SET_DEFAULT 326 } GdaMetaForeignKeyPolicy; 327 328 /** 329 * GdaMetaTableForeignKey: 330 * @meta_table: the #GdaMetaDbObject for which this structure represents a foreign key 331 * @depend_on: the #GdaMetaDbObject which is referenced by the foreign key 332 * @cols_nb: the size of the @fk_cols_array, @fk_names_array, @ref_pk_cols_array and @ref_pk_names_array arrays 333 * @fk_cols_array: the columns' indexes in @meta_table which participate in the constraint (WARNING: columns numbering 334 * here start at 1) 335 * @fk_names_array: the columns' names in @meta_table which participate in the constraint 336 * @ref_pk_cols_array: the columns' indexes in @depend_on which participate in the constraint (WARNING: columns numbering 337 * here start at 1) 338 * @ref_pk_names_array: the columns' names in @depend_on which participate in the constraint 339 * 340 * This structure represents a foreign key constraint, its contents must not be modified. 341 */ 342 typedef struct { 343 /*< public >*/ 344 GdaMetaDbObject *meta_table; 345 GdaMetaDbObject *depend_on; 346 347 gint cols_nb; 348 gint *fk_cols_array; /* FK fields index */ 349 gchar **fk_names_array; /* FK fields names */ 350 gint *ref_pk_cols_array; /* Ref PK fields index */ 351 gchar **ref_pk_names_array; /* Ref PK fields names */ 352 353 /*< private >*/ 354 GdaMetaForeignKeyPolicy on_update_policy; /* pointer containing the GdaMetaForeignKeyPolicy integer 355 * to keep ABI from 4.0, use GINT_TO_POINTER and 356 * GPOINTER_TO_INT */ 357 GdaMetaForeignKeyPolicy on_delete_policy; /* pointer containing the GdaMetaForeignKeyPolicy integer 358 * to keep ABI from 4.0, use GINT_TO_POINTER and 359 * GPOINTER_TO_INT */ 360 gboolean declared; /* pointer to a boolean to keep ABI from 4.0. 361 * Any non NULL if FK has been declared in meta data */ 362 363 /*< public >*/ 364 gchar *fk_name; 365 366 /*< private >*/ 367 /* Padding for future expansion */ 368 gpointer _gda_reserved1; 369 gpointer _gda_reserved2; 370 gpointer _gda_reserved3; 371 gpointer _gda_reserved4; 372 } GdaMetaTableForeignKey; 373 /** 374 * GDA_META_TABLE_FOREIGN_KEY: 375 * @fk: a pointer 376 * 377 * Casts @fk to a #GdaMetaTableForeignKey (no check is actuelly being done on @fk's validity) 378 * 379 * Returns: @col, casted to a #GdaMetaTableForeignKey 380 */ 381 #define GDA_META_TABLE_FOREIGN_KEY(fk) ((GdaMetaTableForeignKey*)(fk)) 382 383 /** 384 * GDA_META_TABLE_FOREIGN_KEY_ON_UPDATE_POLICY: 385 * @fk: a pointer to a #GdaMetaTableForeignKey 386 * 387 * Tells the actual policy implemented by @fk when used in the context of an UPDATE. 388 * 389 * Returns: the policy as a #GdaMetaForeignKeyPolicy 390 */ 391 #define GDA_META_TABLE_FOREIGN_KEY_ON_UPDATE_POLICY(fk) (((GdaMetaTableForeignKey*)(fk))->on_update_policy) 392 393 /** 394 * GDA_META_TABLE_FOREIGN_KEY_ON_DELETE_POLICY: 395 * @fk: a pointer to a #GdaMetaTableForeignKey 396 * 397 * Tells the actual policy implemented by @fk when used in the context of a DELETE. 398 * 399 * Returns: the policy as a #GdaMetaForeignKeyPolicy 400 */ 401 #define GDA_META_TABLE_FOREIGN_KEY_ON_DELETE_POLICY(fk) (((GdaMetaTableForeignKey*)(fk))->on_delete_policy) 402 403 /** 404 * GDA_META_TABLE_FOREIGN_KEY_IS_DECLARED: 405 * @fk: a pointer to a #GdaMetaTableForeignKey 406 * 407 * Tells if @fk is an actual foreign key defined in the database's schema, or if it is an indication which 408 * has been added to help Libgda understand the database schema. 409 * 410 * Returns: %TRUE if @fk has been declared in the database's meta data and %FALSE if @fk is an actual foreign key defined in the database's schema 411 */ 412 #define GDA_META_TABLE_FOREIGN_KEY_IS_DECLARED(fk) (((GdaMetaTableForeignKey*)(fk))->declared) 413 414 /** 415 * SECTION:gda-meta-struct 416 * @short_description: In memory representation of some database objects 417 * @title: GdaMetaStruct 418 * @stability: Stable 419 * @see_also: #GdaMetaStore 420 * 421 * The #GdaMetaStruct object reads data from a #GdaMetaStore object and 422 * creates an easy to use in memory representation for some database objects. For example one can easily 423 * analyze the columns of a table (or its foreign keys) using a #GdaMetaStruct. 424 * 425 * When created, the new #GdaMetaStruct object is empty (it does not have any information about any database object). 426 * Information about database objects is computed upon request using the gda_meta_struct_complement() method. Information 427 * about individual database objects is represented by #GdaMetaDbObject structures, which can be obtained using 428 * gda_meta_struct_get_db_object() or gda_meta_struct_get_all_db_objects(). 429 * 430 * Note that the #GdaMetaDbObject structures may change or may be removed or replaced by others, so it not 431 * advised to keep pointers to these structures: pointers to these structures should be considered valid 432 * as long as gda_meta_struct_complement() and other similar functions have not been called. 433 * 434 * In the following code sample, one prints the columns names and types of a table: 435 * <programlisting> 436 *GdaMetaStruct *mstruct; 437 *GdaMetaDbObject *dbo; 438 *GValue *catalog, *schema, *name; 439 * 440 * // Define name (and optionnally catalog and schema) 441 *[...] 442 * 443 *mstruct = gda_meta_struct_new (); 444 *gda_meta_struct_complement (mstruct, store, GDA_META_DB_TABLE, catalog, schema, name, NULL); 445 *dbo = gda_meta_struct_get_db_object (mstruct, catalog, schema, name); 446 *if (!dbo) 447 * g_print ("Table not found\n"); 448 *else { 449 * GSList *list; 450 * for (list = GDA_META_TABLE (dbo)->columns; list; list = list->next) { 451 * GdaMetaTableColumn *tcol = GDA_META_TABLE_COLUMN (list->data); 452 * g_print ("COLUMN: %s (%s)\n", tcol->column_name, tcol->column_type); 453 * } 454 *} 455 *gda_meta_struct_free (mstruct); 456 * </programlisting> 457 * If now the database object type is not known, one can use the following code: 458 * <programlisting> 459 *GdaMetaStruct *mstruct; 460 *GdaMetaDbObject *dbo; 461 *GValue *catalog, *schema, *name; 462 * 463 * // Define name (and optionnally catalog and schema) 464 *[...] 465 * 466 *mstruct = gda_meta_struct_new (); 467 *gda_meta_struct_complement (mstruct, store, GDA_META_DB_UNKNOWN, catalog, schema, name, NULL); 468 *dbo = gda_meta_struct_get_db_object (mstruct, catalog, schema, name); 469 *if (!dbo) 470 * g_print ("Object not found\n"); 471 *else { 472 * if ((dbo->obj_type == GDA_META_DB_TABLE) || (dbo->obj_type == GDA_META_DB_VIEW)) { 473 * if (dbo->obj_type == GDA_META_DB_TABLE) 474 * g_print ("Is a table\n"); 475 * else if (dbo->obj_type == GDA_META_DB_VIEW) { 476 * g_print ("Is a view, definition is:\n"); 477 * g_print ("%s\n", GDA_META_VIEW (dbo)->view_def); 478 * } 479 * 480 * GSList *list; 481 * for (list = GDA_META_TABLE (dbo)->columns; list; list = list->next) { 482 * GdaMetaTableColumn *tcol = GDA_META_TABLE_COLUMN (list->data); 483 * g_print ("COLUMN: %s (%s)\n", tcol->column_name, tcol->column_type); 484 * } 485 * } 486 * else 487 * g_print ("Not a table or a view\n"); 488 *} 489 *gda_meta_struct_free (mstruct); 490 * </programlisting> 491 */ 492 493 GType gda_meta_struct_get_type (void) G_GNUC_CONST; 494 GdaMetaStruct *gda_meta_struct_new (GdaMetaStore *store, GdaMetaStructFeature features); 495 gboolean gda_meta_struct_load_from_xml_file (GdaMetaStruct *mstruct, const gchar *catalog, 496 const gchar *schema, 497 const gchar *xml_spec_file, GError **error); 498 GdaMetaDbObject *gda_meta_struct_complement (GdaMetaStruct *mstruct, GdaMetaDbObjectType type, 499 const GValue *catalog, const GValue *schema, const GValue *name, 500 GError **error); 501 gboolean gda_meta_struct_complement_schema (GdaMetaStruct *mstruct, 502 const GValue *catalog, const GValue *schema, GError **error); 503 gboolean gda_meta_struct_complement_default (GdaMetaStruct *mstruct, GError **error); 504 gboolean gda_meta_struct_complement_all (GdaMetaStruct *mstruct, GError **error); 505 gboolean gda_meta_struct_complement_depend (GdaMetaStruct *mstruct, GdaMetaDbObject *dbo, 506 GError **error); 507 508 gboolean gda_meta_struct_sort_db_objects (GdaMetaStruct *mstruct, GdaMetaSortType sort_type, GError **error); 509 GSList *gda_meta_struct_get_all_db_objects (GdaMetaStruct *mstruct); 510 GdaMetaDbObject *gda_meta_struct_get_db_object (GdaMetaStruct *mstruct, 511 const GValue *catalog, const GValue *schema, const GValue *name); 512 GdaMetaTableColumn *gda_meta_struct_get_table_column (GdaMetaStruct *mstruct, GdaMetaTable *table, 513 const GValue *col_name); 514 515 typedef enum { 516 GDA_META_GRAPH_COLUMNS = 1 << 0 517 } GdaMetaGraphInfo; 518 519 gchar *gda_meta_struct_dump_as_graph (GdaMetaStruct *mstruct, GdaMetaGraphInfo info, GError **error); 520 521 G_END_DECLS 522 523 #endif 524