1 /* 2 * Copyright (C) 2008 Murray Cumming <murrayc@murrayc.com> 3 * Copyright (C) 2008 - 2011 Vivien Malerba <malerba@gnome-db.org> 4 * Copyright (C) 2010 David King <davidk@openismus.com> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 2 9 * of the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 */ 20 21 #include <string.h> 22 #include <glib/gi18n-lib.h> 23 #include <gda-ddl-creator.h> 24 #include <libgda/gda-connection.h> 25 #include <libgda/gda-server-provider.h> 26 #include <libgda/gda-util.h> 27 #include <libxml/parser.h> 28 #include <libxml/tree.h> 29 #include <libgda/gda-connection.h> 30 #include <libgda/gda-meta-struct.h> 31 #include <libgda/gda-meta-struct-private.h> 32 #include <libgda/gda-config.h> 33 #include <libgda/gda-debug-macros.h> 34 #include <libgda/sql-parser/gda-statement-struct-util.h> 35 36 /* 37 * Main static functions 38 */ 39 static void gda_ddl_creator_class_init (GdaDDLCreatorClass *klass); 40 static void gda_ddl_creator_init (GdaDDLCreator *creator); 41 static void gda_ddl_creator_dispose (GObject *object); 42 static void gda_ddl_creator_finalize (GObject *object); 43 44 static void gda_ddl_creator_set_property (GObject *object, 45 guint param_id, 46 const GValue *value, 47 GParamSpec *pspec); 48 static void gda_ddl_creator_get_property (GObject *object, 49 guint param_id, 50 GValue *value, 51 GParamSpec *pspec); 52 53 static gboolean load_customization (GdaDDLCreator *ddlc, const gchar *xml_spec_file, GError **error); 54 static GdaServerOperation *prepare_dbo_server_operation (GdaDDLCreator *ddlc, GdaServerProvider *prov, GdaConnection *cnc, 55 GdaMetaDbObject *dbo, GError **error); 56 static GStaticRecMutex init_mutex = G_STATIC_REC_MUTEX_INIT; 57 58 typedef struct { 59 gchar *prov; 60 gchar *path; 61 gchar *expr; 62 } ProviderSpecificKey; 63 64 typedef struct { 65 gchar *repl; 66 } ProviderSpecificValue; 67 68 static guint ProviderSpecific_hash (gconstpointer key); 69 static gboolean ProviderSpecific_equal (gconstpointer a, gconstpointer b); 70 static void ProviderSpecific_key_free (ProviderSpecificKey *key); 71 static void ProviderSpecific_value_free (ProviderSpecificValue *value); 72 73 struct _GdaDDLCreatorPrivate { 74 GdaConnection *cnc; 75 GdaMetaStruct *d_mstruct; 76 77 GHashTable *provider_specifics; /* key = a ProviderSpecificKey , value = a ProviderSpecificValue */ 78 GValue *catalog; 79 GValue *schema; 80 gchar *quoted_catalog; 81 gchar *quoted_schema; 82 }; 83 84 /* get a pointer to the parents to be able to call their destructor */ 85 static GObjectClass *parent_class = NULL; 86 87 88 /* properties */ 89 enum { 90 PROP_0, 91 PROP_CNC_OBJECT, 92 PROP_CATALOG, 93 PROP_SCHEMA 94 }; 95 96 /* module error */ 97 GQuark gda_ddl_creator_error_quark (void) { 98 static GQuark quark; 99 if (!quark) 100 quark = g_quark_from_static_string ("gda_ddl_creator_error"); 101 return quark; 102 } 103 104 GType 105 gda_ddl_creator_get_type (void) { 106 static GType type = 0; 107 108 if (G_UNLIKELY (type == 0)) { 109 static const GTypeInfo info = { 110 sizeof (GdaDDLCreatorClass), 111 (GBaseInitFunc) NULL, 112 (GBaseFinalizeFunc) NULL, 113 (GClassInitFunc) gda_ddl_creator_class_init, 114 NULL, 115 NULL, 116 sizeof (GdaDDLCreator), 117 0, 118 (GInstanceInitFunc) gda_ddl_creator_init, 119 0 120 }; 121 122 g_static_rec_mutex_lock (&init_mutex); 123 if (type == 0) 124 type = g_type_register_static (G_TYPE_OBJECT, "GdaDDLCreator", &info, 0); 125 g_static_rec_mutex_unlock (&init_mutex); 126 } 127 return type; 128 } 129 130 static guint 131 ProviderSpecific_hash (gconstpointer key) 132 { 133 ProviderSpecificKey *pkey = (ProviderSpecificKey*) key; 134 return g_str_hash (pkey->path) + g_str_hash (pkey->prov) + 135 (pkey->expr ? g_str_hash (pkey->expr) : 0); 136 } 137 138 static gboolean 139 ProviderSpecific_equal (gconstpointer a, gconstpointer b) 140 { 141 ProviderSpecificKey *pa, *pb; 142 pa = (ProviderSpecificKey*) a; 143 pb = (ProviderSpecificKey*) b; 144 145 if (strcmp (pa->prov, pb->prov) || 146 (pa->expr && !pb->expr) || 147 (pb->expr && !pa->expr) || 148 (pa->expr && pb->expr && strcmp (pa->expr, pb->expr)) || 149 strcmp (pa->path, pb->path)) 150 return FALSE; 151 else 152 return TRUE; 153 } 154 155 static void 156 ProviderSpecific_key_free (ProviderSpecificKey *key) 157 { 158 g_free (key->prov); 159 g_free (key->path); 160 g_free (key->expr); 161 g_free (key); 162 } 163 164 static void 165 ProviderSpecific_value_free (ProviderSpecificValue *value) 166 { 167 g_free (value->repl); 168 g_free (value); 169 } 170 171 172 static void 173 gda_ddl_creator_class_init (GdaDDLCreatorClass *klass) 174 { 175 GObjectClass *object_class = G_OBJECT_CLASS (klass); 176 177 g_static_rec_mutex_lock (&init_mutex); 178 parent_class = g_type_class_peek_parent (klass); 179 180 /* Properties */ 181 object_class->set_property = gda_ddl_creator_set_property; 182 object_class->get_property = gda_ddl_creator_get_property; 183 g_object_class_install_property (object_class, PROP_CNC_OBJECT, 184 g_param_spec_object ("cnc", NULL, _ ("Connection object"), GDA_TYPE_CONNECTION, 185 (G_PARAM_READABLE | G_PARAM_WRITABLE))); 186 g_object_class_install_property (object_class, PROP_CATALOG, 187 g_param_spec_string ("catalog", NULL, _ ("Catalog in which the database objects will be created"), NULL, 188 (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY))); 189 g_object_class_install_property (object_class, PROP_SCHEMA, 190 g_param_spec_string ("schema", NULL, _ ("Schema in which the database objects will be created"), NULL, 191 (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY))); 192 193 object_class->dispose = gda_ddl_creator_dispose; 194 object_class->finalize = gda_ddl_creator_finalize; 195 196 g_static_rec_mutex_unlock (&init_mutex); 197 } 198 199 200 static void 201 gda_ddl_creator_init (GdaDDLCreator *creator) 202 { 203 creator->priv = g_new0 (GdaDDLCreatorPrivate, 1); 204 creator->priv->cnc = NULL; 205 creator->priv->d_mstruct = NULL; 206 creator->priv->provider_specifics = g_hash_table_new_full (ProviderSpecific_hash, ProviderSpecific_equal, 207 (GDestroyNotify) ProviderSpecific_key_free, 208 (GDestroyNotify) ProviderSpecific_value_free); 209 creator->priv->catalog = NULL; 210 creator->priv->schema = NULL; 211 creator->priv->quoted_catalog = NULL; 212 creator->priv->quoted_schema = NULL; 213 } 214 215 static void 216 gda_ddl_creator_dispose (GObject *object) 217 { 218 GdaDDLCreator *creator; 219 220 g_return_if_fail (GDA_IS_DDL_CREATOR (object)); 221 222 creator = GDA_DDL_CREATOR (object); 223 if (creator->priv) { 224 if (creator->priv->catalog) 225 gda_value_free (creator->priv->catalog); 226 if (creator->priv->schema) 227 gda_value_free (creator->priv->schema); 228 g_free (creator->priv->quoted_catalog); 229 g_free (creator->priv->quoted_schema); 230 231 if (creator->priv->cnc) { 232 g_object_unref (creator->priv->cnc); 233 creator->priv->cnc = NULL; 234 } 235 236 if (creator->priv->d_mstruct) { 237 g_object_unref (creator->priv->d_mstruct); 238 creator->priv->d_mstruct = NULL; 239 } 240 } 241 242 /* parent class */ 243 parent_class->dispose (object); 244 } 245 246 static void 247 gda_ddl_creator_finalize (GObject *object) 248 { 249 GdaDDLCreator *creator; 250 251 g_return_if_fail (object != NULL); 252 g_return_if_fail (GDA_IS_DDL_CREATOR (object)); 253 254 creator = GDA_DDL_CREATOR (object); 255 if (creator->priv) { 256 if (creator->priv->provider_specifics) 257 g_hash_table_destroy (creator->priv->provider_specifics); 258 g_free (creator->priv); 259 creator->priv = NULL; 260 } 261 262 /* parent class */ 263 parent_class->finalize (object); 264 } 265 266 static void 267 gda_ddl_creator_set_property (GObject *object, 268 guint param_id, 269 const GValue *value, 270 GParamSpec *pspec) 271 { 272 GdaDDLCreator *creator; 273 274 creator = GDA_DDL_CREATOR (object); 275 if (creator->priv) { 276 switch (param_id) { 277 case PROP_CNC_OBJECT: 278 if (creator->priv->cnc) 279 g_object_unref (creator->priv->cnc); 280 281 creator->priv->cnc = g_value_get_object (value); 282 if (creator->priv->cnc) 283 g_object_ref (creator->priv->cnc); 284 break; 285 case PROP_CATALOG: 286 if (creator->priv->catalog) 287 gda_value_free (creator->priv->catalog); 288 creator->priv->catalog = NULL; 289 g_free (creator->priv->quoted_catalog); 290 creator->priv->quoted_catalog = NULL; 291 if (g_value_get_string (value) && *g_value_get_string (value)) { 292 creator->priv->catalog = gda_value_copy (value); 293 if (!creator->priv->cnc) 294 g_warning ("The \"catalog\" property should be set after the \"cnc\" one"); 295 creator->priv->quoted_catalog = 296 gda_sql_identifier_quote (g_value_get_string (value), creator->priv->cnc, NULL, 297 FALSE, FALSE); 298 } 299 break; 300 case PROP_SCHEMA: 301 if (creator->priv->schema) 302 gda_value_free (creator->priv->schema); 303 creator->priv->schema = NULL; 304 g_free (creator->priv->quoted_schema); 305 creator->priv->quoted_schema = NULL; 306 if (g_value_get_string (value) && *g_value_get_string (value)) { 307 creator->priv->schema = gda_value_copy (value); 308 if (!creator->priv->cnc) 309 g_warning ("The \"schema\" property should be set after the \"cnc\" one"); 310 creator->priv->quoted_schema = 311 gda_sql_identifier_quote (g_value_get_string (value), creator->priv->cnc, NULL, 312 FALSE, FALSE); 313 } 314 break; 315 default: 316 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); 317 break; 318 } 319 } 320 } 321 322 static void 323 gda_ddl_creator_get_property (GObject *object, 324 guint param_id, 325 GValue *value, 326 GParamSpec *pspec) 327 { 328 GdaDDLCreator *creator; 329 creator = GDA_DDL_CREATOR (object); 330 331 if (creator->priv) { 332 switch (param_id) { 333 case PROP_CNC_OBJECT: 334 g_value_set_object (value, (GObject *) creator->priv->cnc); 335 break; 336 case PROP_CATALOG: 337 if (creator->priv->catalog) 338 g_value_set_string (value, g_value_get_string (creator->priv->catalog)); 339 else 340 g_value_set_string (value, NULL); 341 break; 342 case PROP_SCHEMA: 343 if (creator->priv->schema) 344 g_value_set_string (value, g_value_get_string (creator->priv->schema)); 345 else 346 g_value_set_string (value, NULL); 347 break; 348 default: 349 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); 350 break; 351 } 352 } 353 } 354 355 /** 356 * gda_ddl_creator_new 357 * Create a new #GdaDDLCreator object 358 * 359 * Returns: the newly created object 360 */ 361 GdaDDLCreator * 362 gda_ddl_creator_new (void) 363 { 364 return (GdaDDLCreator *) g_object_new (GDA_TYPE_DDL_CREATOR, NULL); 365 } 366 367 /** 368 * gda_ddl_creator_set_dest_from_file 369 * @ddlc: a #GdaDDLCreator object 370 * @xml_spec_file: a file name 371 * @error: a place to store errors, or %NULL 372 * 373 * Sets the destination structure 374 * 375 * Returns: TRUE if no error occurred 376 */ 377 gboolean 378 gda_ddl_creator_set_dest_from_file (GdaDDLCreator *ddlc, const gchar *xml_spec_file, GError **error) 379 { 380 g_return_val_if_fail (GDA_IS_DDL_CREATOR (ddlc), FALSE); 381 g_return_val_if_fail (xml_spec_file && *xml_spec_file, FALSE); 382 383 if (ddlc->priv->d_mstruct) 384 g_object_unref (ddlc->priv->d_mstruct); 385 386 ddlc->priv->d_mstruct = (GdaMetaStruct*) g_object_new (GDA_TYPE_META_STRUCT, NULL); 387 388 if (!gda_meta_struct_load_from_xml_file (ddlc->priv->d_mstruct, NULL, NULL, xml_spec_file, error) || 389 !load_customization (ddlc, xml_spec_file, error)) { 390 g_object_unref (ddlc->priv->d_mstruct); 391 ddlc->priv->d_mstruct = NULL; 392 return FALSE; 393 } 394 else 395 return TRUE; 396 } 397 398 static gboolean 399 load_customization (GdaDDLCreator *ddlc, const gchar *xml_spec_file, GError **error) 400 { 401 xmlNodePtr node; 402 xmlDocPtr doc; 403 404 /* load information schema's structure XML file */ 405 doc = xmlParseFile (xml_spec_file); 406 if (!doc) { 407 g_set_error (error, GDA_DDL_CREATOR_ERROR, GDA_DDL_CREATOR_SPECFILE_NOT_FOUND_ERROR, 408 _("Could not load file '%s'"), xml_spec_file); 409 return FALSE; 410 } 411 412 node = xmlDocGetRootElement (doc); 413 if (!node || strcmp ((gchar *) node->name, "schema")) { 414 g_set_error (error, GDA_DDL_CREATOR_ERROR, GDA_DDL_CREATOR_INCORRECT_SCHEMA_ERROR, 415 _("Root node of file '%s' should be <schema>."), xml_spec_file); 416 xmlFreeDoc (doc); 417 return FALSE; 418 } 419 420 /* walk through the xmlDoc */ 421 for (node = node->children; node; node = node->next) { 422 /* <specifics> tag to allow for provider specific transformations */ 423 if (!strcmp ((gchar *) node->name, "specifics")) { 424 xmlNodePtr snode; 425 for (snode = node->children; snode; snode = snode->next) { 426 if (strcmp ((gchar *) snode->name, "provider")) 427 continue; 428 xmlChar *pname; 429 pname = xmlGetProp (snode, BAD_CAST "name"); 430 if (!pname) { 431 g_warning ("<provider> section ignored because no provider name specified"); 432 continue; /* ignore this section */ 433 } 434 435 xmlNodePtr rnode; 436 for (rnode = snode->children; rnode; rnode = rnode->next) { 437 if (!strcmp ((gchar *) rnode->name, "replace") || 438 !strcmp ((gchar *) rnode->name, "ignore")) { 439 xmlChar *context, *tmp; 440 context = xmlGetProp (rnode, BAD_CAST "context"); 441 if (!context) { 442 g_warning ("<%s> section ignored because no context specified", 443 snode->name); 444 continue; 445 } 446 ProviderSpecificKey *key = g_new0 (ProviderSpecificKey, 1); 447 ProviderSpecificValue *val = g_new0 (ProviderSpecificValue, 1); 448 key->prov = g_strdup ((gchar *) pname); 449 key->path = g_strdup ((gchar *) context); 450 xmlFree (context); 451 tmp = xmlGetProp (rnode, BAD_CAST "expr"); 452 if (tmp) { 453 key->expr = g_strdup ((gchar *) tmp); 454 xmlFree (tmp); 455 } 456 tmp = xmlGetProp (rnode, BAD_CAST "replace_with"); 457 if (tmp) { 458 val->repl = g_strdup ((gchar *) tmp); 459 xmlFree (tmp); 460 } 461 g_hash_table_insert (ddlc->priv->provider_specifics, key, val); 462 /*g_print ("RULE: %s, %s, %s => %s\n", key->prov, 463 key->path, key->expr, val->repl);*/ 464 } 465 } 466 xmlFree (pname); 467 } 468 } 469 } 470 xmlFreeDoc (doc); 471 472 return TRUE; 473 } 474 475 static GdaServerOperation *create_server_operation_for_table (GdaDDLCreator *ddlc, GdaServerProvider *prov, GdaConnection *cnc, 476 GdaMetaDbObject *dbobj, GError **error); 477 static GdaServerOperation *create_server_operation_for_view (GdaDDLCreator *ddlc, GdaServerProvider *prov, GdaConnection *cnc, 478 GdaMetaDbObject *dbobj, GError **error); 479 480 static GdaServerOperation * 481 prepare_dbo_server_operation (GdaDDLCreator *ddlc, GdaServerProvider *prov, GdaConnection *cnc, GdaMetaDbObject *dbo, GError **error) 482 { 483 GdaServerOperation *op = NULL; 484 switch (dbo->obj_type) { 485 case GDA_META_DB_UNKNOWN: 486 g_set_error (error, GDA_DDL_CREATOR_ERROR, GDA_DDL_CREATOR_INCORRECT_SCHEMA_ERROR, 487 _("Unknown database object '%s'"), dbo->obj_full_name); 488 break; 489 490 case GDA_META_DB_TABLE: 491 op = create_server_operation_for_table (ddlc, prov, cnc, dbo, error); 492 break; 493 494 case GDA_META_DB_VIEW: 495 op = create_server_operation_for_view (ddlc, prov, cnc, dbo, error); 496 break; 497 default: 498 TO_IMPLEMENT; 499 break; 500 } 501 502 return op; 503 } 504 505 static const gchar * 506 provider_specific_match (GHashTable *specific_hash, GdaServerProvider *prov, const gchar *expr, const gchar *path) 507 { 508 ProviderSpecificKey spec; 509 ProviderSpecificValue *val; 510 511 spec.prov = (gchar *) gda_server_provider_get_name (prov); 512 spec.path = (gchar *) path; 513 spec.expr = (gchar *) expr; 514 val = g_hash_table_lookup (specific_hash, &spec); 515 /*g_print ("RULESEARCH %s, %s, %s => %s\n", spec.prov, spec.path, spec.expr, val ? val->repl : "-no rule found-");*/ 516 if (val) 517 return val->repl; 518 else 519 return expr; 520 } 521 522 typedef struct { 523 GdaServerOperation *op; 524 gint index; 525 GError **error; 526 gboolean allok; 527 } FData; 528 static void 529 meta_table_column_foreach_attribute_func (const gchar *att_name, const GValue *value, FData *fdata) 530 { 531 if (!fdata->allok) 532 return; 533 if (!strcmp (att_name, GDA_ATTRIBUTE_AUTO_INCREMENT) && 534 (G_VALUE_TYPE (value) == G_TYPE_BOOLEAN) && 535 g_value_get_boolean (value)) { 536 fdata->allok = gda_server_operation_set_value_at (fdata->op, "TRUE", fdata->error, 537 "/FIELDS_A/@COLUMN_AUTOINC/%d", 538 fdata->index); 539 } 540 } 541 542 static GdaServerOperation * 543 create_server_operation_for_table (GdaDDLCreator *ddlc, GdaServerProvider *prov, GdaConnection *cnc, 544 GdaMetaDbObject *dbobj, GError **error) 545 { 546 GdaServerOperation *op; 547 GSList *list; 548 gint index; 549 const gchar *repl; 550 551 op = gda_server_provider_create_operation (prov, cnc, GDA_SERVER_OPERATION_CREATE_TABLE, NULL, error); 552 if (!op) 553 return NULL; 554 if (! gda_server_operation_set_value_at (op, dbobj->obj_name, error, "/TABLE_DEF_P/TABLE_NAME")) 555 goto onerror; 556 557 /* columns */ 558 for (index = 0, list = GDA_META_TABLE (dbobj)->columns; list; list = list->next, index++) { 559 GdaMetaTableColumn *tcol = GDA_META_TABLE_COLUMN (list->data); 560 if (! gda_server_operation_set_value_at (op, tcol->column_name, error, 561 "/FIELDS_A/@COLUMN_NAME/%d", index)) 562 goto onerror; 563 repl = provider_specific_match (ddlc->priv->provider_specifics, prov, tcol->column_type ? tcol->column_type : "string", 564 "/FIELDS_A/@COLUMN_TYPE"); 565 if (! gda_server_operation_set_value_at (op, repl ? repl : "string", error, 566 "/FIELDS_A/@COLUMN_TYPE/%d", index)) 567 goto onerror; 568 if (! gda_server_operation_set_value_at (op, NULL, error, 569 "/FIELDS_A/@COLUMN_SIZE/%d", index)) 570 goto onerror; 571 if (! gda_server_operation_set_value_at (op, tcol->nullok ? "FALSE" : "TRUE", error, 572 "/FIELDS_A/@COLUMN_NNUL/%d", index)) 573 goto onerror; 574 if (! gda_server_operation_set_value_at (op, "FALSE", error, 575 "/FIELDS_A/@COLUMN_AUTOINC/%d", index)) 576 goto onerror; 577 if (! gda_server_operation_set_value_at (op, "FALSE", error, 578 "/FIELDS_A/@COLUMN_UNIQUE/%d", index)) 579 goto onerror; 580 FData fdata; 581 fdata.op = op; 582 fdata.index = index; 583 fdata.error = error; 584 fdata.allok = TRUE; 585 gda_meta_table_column_foreach_attribute (tcol, (GdaAttributesManagerFunc) meta_table_column_foreach_attribute_func, 586 &fdata); 587 if (!fdata.allok) 588 goto onerror; 589 590 repl = provider_specific_match (ddlc->priv->provider_specifics, prov, "dummy", "/FIELDS_A/@COLUMN_PKEY"); 591 if (repl) { 592 if (! gda_server_operation_set_value_at (op, tcol->pkey ? "TRUE" : "FALSE", error, 593 "/FIELDS_A/@COLUMN_PKEY/%d", index)) 594 goto onerror; 595 } 596 else { 597 if (! gda_server_operation_set_value_at (op, "FALSE", error, "/FIELDS_A/@COLUMN_PKEY/%d", index)) 598 goto onerror; 599 } 600 } 601 602 /* foreign keys */ 603 gint fkindex; 604 for (fkindex = 0, list = GDA_META_TABLE (dbobj)->fk_list; list; fkindex++, list = list->next) { 605 GdaMetaTableForeignKey *mfkey = GDA_META_TABLE_FOREIGN_KEY (list->data); 606 gint col; 607 if (! gda_server_operation_set_value_at (op, mfkey->depend_on->obj_full_name, error, "/FKEY_S/%d/FKEY_REF_TABLE", 608 fkindex)) 609 goto onerror; 610 for (col = 0; col < mfkey->cols_nb; col++) { 611 if (! gda_server_operation_set_value_at (op, mfkey->fk_names_array[col], error, 612 "/FKEY_S/%d/FKEY_FIELDS_A/@FK_FIELD/%d", 613 fkindex, col)) 614 goto onerror; 615 if (! gda_server_operation_set_value_at (op, mfkey->ref_pk_names_array[col], error, 616 "/FKEY_S/%d/FKEY_FIELDS_A/@FK_REF_PK_FIELD/%d", 617 fkindex, col)) 618 goto onerror; 619 } 620 } 621 622 #ifdef GDA_DEBUG_NO 623 { 624 xmlNodePtr node; 625 xmlBufferPtr buffer; 626 node = gda_server_operation_save_data_to_xml (op, NULL); 627 buffer = xmlBufferCreate (); 628 xmlNodeDump (buffer, NULL, node, 5, 1); 629 xmlFreeNode (node); 630 xmlBufferDump (stdout, buffer); 631 xmlBufferFree (buffer); 632 } 633 #endif 634 635 return op; 636 onerror: 637 g_object_unref (op); 638 return NULL; 639 } 640 641 static GdaServerOperation * 642 create_server_operation_for_view (G_GNUC_UNUSED GdaDDLCreator *ddlc, GdaServerProvider *prov, GdaConnection *cnc, 643 GdaMetaDbObject *dbobj, GError **error) 644 { 645 GdaServerOperation *op; 646 647 op = gda_server_provider_create_operation (prov, cnc, dbobj->obj_type, NULL, error); 648 if (!op) 649 return NULL; 650 if (! gda_server_operation_set_value_at (op, dbobj->obj_name, error, "/VIEW_DEF_P/VIEW_NAME")) 651 goto onerror; 652 if (! gda_server_operation_set_value_at (op, GDA_META_VIEW (dbobj)->view_def, error, "/VIEW_DEF_P/VIEW_DEF")) 653 goto onerror; 654 655 return op; 656 onerror: 657 g_object_unref (op); 658 return NULL; 659 } 660 661 /** 662 * gda_ddl_creator_set_connection 663 * @ddlc: a #GdaDDLCreator object 664 * @cnc: (allow-none): a #GdaConnection object or %NULL 665 * 666 * 667 */ 668 void 669 gda_ddl_creator_set_connection (GdaDDLCreator *ddlc, GdaConnection *cnc) 670 { 671 g_return_if_fail (GDA_IS_DDL_CREATOR (ddlc)); 672 g_return_if_fail (!cnc || GDA_IS_CONNECTION (cnc)); 673 674 g_object_set (G_OBJECT (ddlc), "cnc", cnc, NULL); 675 } 676 677 /** 678 * gda_ddl_creator_get_sql 679 * @ddlc: a #GdaDDLCreator object 680 * @error: a place to store errors, or %NULL 681 * 682 * Get the SQL code which would be executed to create the database objects 683 * 684 * Returns: a new string if no error occurred, or %NULL 685 */ 686 gchar * 687 gda_ddl_creator_get_sql (GdaDDLCreator *ddlc, GError **error) 688 { 689 GString *string; 690 gchar *sql; 691 g_return_val_if_fail (GDA_IS_DDL_CREATOR (ddlc), NULL); 692 g_return_val_if_fail (ddlc->priv, NULL); 693 if (!ddlc->priv->cnc) { 694 g_set_error (error, GDA_DDL_CREATOR_ERROR, GDA_DDL_CREATOR_NO_CONNECTION_ERROR, 695 "%s", _("No connection specified")); 696 return NULL; 697 } 698 699 /* render operations to SQL */ 700 GdaServerProvider *prov = gda_connection_get_provider (ddlc->priv->cnc); 701 GSList *objlist, *list; 702 objlist = gda_meta_struct_get_all_db_objects (ddlc->priv->d_mstruct); 703 704 string = g_string_new (""); 705 for (list = objlist; list; list = list->next) { 706 GdaServerOperation *op; 707 op = prepare_dbo_server_operation (ddlc, prov, NULL, GDA_META_DB_OBJECT (list->data), error); 708 if (!op) { 709 g_string_free (string, TRUE); 710 return NULL; 711 } 712 else { 713 sql = gda_server_provider_render_operation (prov, ddlc->priv->cnc, op, error); 714 if (!sql) { 715 g_string_free (string, TRUE); 716 return NULL; 717 } 718 else { 719 g_string_append_printf (string, "--\n-- Database object: %s\n--\n", 720 GDA_META_DB_OBJECT (list->data)->obj_full_name); 721 g_string_append (string, sql); 722 g_string_append (string, ";\n\n"); 723 g_free (sql); 724 } 725 } 726 g_object_unref (op); 727 } 728 729 sql = string->str; 730 g_string_free (string, FALSE); 731 return sql; 732 } 733 734 /** 735 * gda_ddl_creator_execute 736 * @ddlc: a #GdaDDLCreator object 737 * @error: a place to store errors, or %NULL 738 * 739 * 740 */ 741 gboolean 742 gda_ddl_creator_execute (GdaDDLCreator *ddlc, GError **error) 743 { 744 g_return_val_if_fail (GDA_IS_DDL_CREATOR (ddlc), FALSE); 745 g_return_val_if_fail (ddlc->priv, FALSE); 746 if (!ddlc->priv->cnc) { 747 g_set_error (error, GDA_DDL_CREATOR_ERROR, GDA_DDL_CREATOR_NO_CONNECTION_ERROR, 748 "%s", _("No connection specified")); 749 return FALSE; 750 } 751 if (!ddlc->priv->d_mstruct) { 752 g_set_error (error, GDA_DDL_CREATOR_ERROR, GDA_DDL_CREATOR_NO_CONNECTION_ERROR, 753 "%s", _("No destination database objects specified")); 754 return FALSE; 755 } 756 757 /* begin transaction */ 758 if (!gda_connection_begin_transaction (ddlc->priv->cnc, NULL, GDA_TRANSACTION_ISOLATION_UNKNOWN, 759 error)) 760 return FALSE; 761 762 /* execute operations */ 763 GdaServerProvider *prov = gda_connection_get_provider (ddlc->priv->cnc); 764 GSList *objlist, *list; 765 objlist = gda_meta_struct_get_all_db_objects (ddlc->priv->d_mstruct); 766 for (list = objlist; list; list = list->next) { 767 GdaServerOperation *op; 768 op = prepare_dbo_server_operation (ddlc, prov, NULL, GDA_META_DB_OBJECT (list->data), error); 769 if (!op) 770 goto onerror; 771 else { 772 if (!gda_server_provider_perform_operation (prov, ddlc->priv->cnc, op, error)) { 773 g_object_unref (op); 774 goto onerror; 775 } 776 } 777 g_object_unref (op); 778 } 779 780 if (!gda_connection_commit_transaction (ddlc->priv->cnc, NULL, error)) 781 goto onerror; 782 783 return TRUE; 784 785 onerror: 786 gda_connection_rollback_transaction (ddlc->priv->cnc, NULL, NULL); 787 return FALSE; 788 } 789 790