1 /* Widgets/DDL queries 2 * 3 * A DDL query is a query defining or modifying a database structure and properties. 4 * In Libgda, each type of DDL query corresponds to an "operation". 5 * Examples of "operation"s include creating a database, creating a table, 6 * adding a field to a table. 7 * 8 * Because the SQL corresponding to DDL queries varies widely between the 9 * DBMS, the information required to perform an operation is provided by 10 * each DBMS adapter (server provider), and specified as a set of named 11 * parameters. 12 * 13 * For each type of operation and for each type of provider, a GdaServerOperation 14 * object can be requested; this objects holds all the named parameters required 15 * or optional to perform the operation. Once values have been set to the 16 * named parameters, that object is passed back to the provider which can render 17 * it as SQL or perform the requested operation. 18 * 19 * The GdauiServerOperation widget can be used to display 20 * and assign value to the named parameters of a GdaServerOperation object. 21 */ 22 23 #include <libgda-ui/libgda-ui.h> 24 #include <string.h> 25 26 static GtkWidget *window = NULL; 27 28 typedef struct { 29 GdaServerOperation *op; 30 GtkWidget *op_container; 31 GtkWidget *op_form; 32 GdauiProviderSelector *prov_sel; 33 GtkWidget *op_combo; 34 GdaServerProvider *prov; 35 36 GtkWidget *top_window; 37 GtkWidget *sql_button; 38 GtkWidget *show_button; 39 } DemoData; 40 41 static void tested_provider_changed_cb (GdauiProviderSelector *prov_sel, DemoData *data); 42 static void tested_operation_changed_cb (GdauiCombo *combo, DemoData *data); 43 static void update_possible_operations (DemoData *data); 44 45 static void show_named_parameters (GtkButton *button, DemoData *data); 46 static void show_sql (GtkButton *button, DemoData *data); 47 48 static GdaServerProvider *get_provider_obj (DemoData *data); 49 50 GtkWidget * 51 do_ddl_queries (GtkWidget *do_widget) 52 { 53 if (!window) { 54 GtkWidget *grid; 55 GtkWidget *label; 56 GtkWidget *wid; 57 DemoData *data; 58 GtkWidget *bbox; 59 GtkWidget *sw, *vp; 60 61 data = g_new0 (DemoData, 1); 62 gda_report_document_class_init(GdaReportDocumentClass * klass)63 window = gtk_dialog_new_with_buttons ("DDL queries", 64 GTK_WINDOW (do_widget), 65 0, 66 GTK_STOCK_CLOSE, 67 GTK_RESPONSE_NONE, 68 NULL); 69 data->top_window = window; 70 71 g_signal_connect (window, "response", 72 G_CALLBACK (gtk_widget_destroy), NULL); 73 g_signal_connect (window, "destroy", 74 G_CALLBACK (gtk_widget_destroyed), &window); 75 76 grid = gtk_grid_new (); 77 gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (window))), 78 grid, TRUE, TRUE, 0); 79 gtk_container_set_border_width (GTK_CONTAINER (grid), 5); 80 81 label = gtk_label_new ("<b>Tested provider and operation:</b>"); 82 gtk_label_set_use_markup (GTK_LABEL (label), TRUE); 83 gtk_misc_set_alignment (GTK_MISC (label), 0., -1); gda_report_document_init(GdaReportDocument * doc,G_GNUC_UNUSED GdaReportDocumentClass * klass)84 gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 2, 1); 85 86 /* provider selection */ 87 label = gtk_label_new ("Tested provider:"); 88 gtk_misc_set_alignment (GTK_MISC (label), 0., -1); 89 gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1); gda_report_document_dispose(GObject * object)90 91 wid = gdaui_provider_selector_new (); 92 gdaui_provider_selector_set_provider (GDAUI_PROVIDER_SELECTOR (wid), 93 "SQLite"); 94 gtk_grid_attach (GTK_GRID (grid), wid, 1, 1, 1, 1); 95 data->prov_sel = GDAUI_PROVIDER_SELECTOR (wid); 96 g_signal_connect (G_OBJECT (data->prov_sel), "changed", 97 G_CALLBACK (tested_provider_changed_cb), data); 98 99 /* operation selection */ 100 label = gtk_label_new ("Tested operation:"); 101 gtk_misc_set_alignment (GTK_MISC (label), 0., -1); 102 gtk_grid_attach (GTK_GRID (grid), label, 0, 2, 1, 1); 103 104 wid = gdaui_combo_new (); 105 gtk_grid_attach (GTK_GRID (grid), wid, 1, 2, 1, 1); 106 g_signal_connect (G_OBJECT (wid), "changed", 107 G_CALLBACK (tested_operation_changed_cb), data); 108 data->op_combo = wid; 109 110 /* container for GdauiServerOperation */ 111 label = gtk_label_new ("<b>GdauiServerOperation widget:</b>"); 112 gtk_misc_set_alignment (GTK_MISC (label), 0., -1); 113 gtk_label_set_use_markup (GTK_LABEL (label), TRUE); 114 gtk_grid_attach (GTK_GRID (grid), label, 0, 3, 2, 1); 115 116 sw = gtk_scrolled_window_new (FALSE, 0); gda_report_document_get_type(void)117 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), 118 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); 119 gtk_widget_set_size_request (sw, 600, 450); 120 gtk_grid_attach (GTK_GRID (grid), sw, 0, 4, 2, 1); 121 vp = gtk_viewport_new (NULL, NULL); 122 gtk_widget_set_name (vp, "gdaui-transparent-background"); 123 gtk_viewport_set_shadow_type (GTK_VIEWPORT (vp), GTK_SHADOW_NONE); 124 gtk_container_add (GTK_CONTAINER (sw), vp); 125 data->op_container = vp; 126 127 /* bottom buttons */ 128 bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL); 129 gtk_grid_attach (GTK_GRID (grid), bbox, 0, 5, 2, 1); 130 131 wid = gtk_button_new_with_label ("Show named parameters"); 132 data->show_button = wid; 133 gtk_box_pack_start (GTK_BOX (bbox), wid, TRUE, TRUE, 0); 134 g_signal_connect (G_OBJECT (wid), "clicked", 135 G_CALLBACK (show_named_parameters), data); 136 137 wid = gtk_button_new_with_label ("Show SQL"); 138 data->sql_button = wid; 139 gtk_box_pack_start (GTK_BOX (bbox), wid, TRUE, TRUE, 0); 140 g_signal_connect (G_OBJECT (wid), "clicked", 141 G_CALLBACK (show_sql), data); 142 143 tested_provider_changed_cb (data->prov_sel, data); 144 gtk_combo_box_set_active (GTK_COMBO_BOX (data->op_combo), 1); gda_report_document_set_property(GObject * object,guint param_id,const GValue * value,GParamSpec * pspec)145 } 146 147 gboolean visible; 148 g_object_get (G_OBJECT (window), "visible", &visible, NULL); 149 if (!visible) 150 gtk_widget_show_all (window); 151 else { 152 gtk_widget_destroy (window); 153 window = NULL; 154 } 155 156 return window; 157 } 158 159 static void 160 tested_provider_changed_cb (G_GNUC_UNUSED GdauiProviderSelector *prov_sel, DemoData *data) 161 { 162 if (data->prov) { 163 g_object_unref (data->prov); 164 data->prov = NULL; 165 } 166 update_possible_operations (data); 167 } 168 169 static void 170 update_possible_operations (DemoData *data) 171 { 172 GdaServerOperationType type; 173 GdaDataModel *model; 174 gda_report_document_get_property(GObject * object,guint param_id,GValue * value,GParamSpec * pspec)175 model = gdaui_data_selector_get_model (GDAUI_DATA_SELECTOR (data->op_combo)); 176 if (!model) { 177 gint columns[] = {1}; 178 model = gda_data_model_array_new_with_g_types (2, G_TYPE_INT, G_TYPE_STRING); 179 gdaui_combo_set_model (GDAUI_COMBO (data->op_combo), model, 1, columns); 180 } 181 else 182 gda_data_model_array_clear (GDA_DATA_MODEL_ARRAY (model)); 183 184 for (type = 0; type < GDA_SERVER_OPERATION_LAST; type ++) 185 if (gda_server_provider_supports_operation (get_provider_obj (data), 186 NULL, type, NULL)) { 187 gint row; 188 189 row = gda_data_model_append_row (model, NULL); 190 if (row < 0) 191 g_error ("Cant' append data to a GdaDataModelArray"); 192 else { 193 GValue value; 194 195 memset (&value, 0, sizeof (GValue)); 196 g_value_init (&value, G_TYPE_INT); 197 g_value_set_int (&value, type); 198 gda_data_model_set_value_at (model, 0, row, &value, NULL); 199 200 memset (&value, 0, sizeof (GValue)); 201 g_value_init (&value, G_TYPE_STRING); 202 g_value_set_string (&value, gda_server_operation_op_type_to_string (type)); 203 gda_data_model_set_value_at (model, 1, row, &value, NULL); 204 } gda_report_document_set_template(GdaReportDocument * doc,const gchar * file)205 } 206 } 207 208 static GdaServerProvider * 209 get_provider_obj (DemoData *data) 210 { 211 GdaServerProvider *prov = NULL; 212 213 if (data->prov) 214 prov = data->prov; 215 else { 216 /* create the GdaServerProvider object */ 217 data->prov = gdaui_provider_selector_get_provider_obj (data->prov_sel); 218 prov = data->prov; 219 } 220 221 return prov; 222 } 223 224 static void 225 tested_operation_changed_cb (G_GNUC_UNUSED GdauiCombo *combo, DemoData *data) 226 { 227 GdaServerProvider *prov = NULL; 228 GdaServerOperationType type; 229 GError *error = NULL; 230 GdaDataModelIter *iter; 231 const GValue *cvalue = NULL; 232 233 if (data->op) { 234 g_object_unref (data->op); 235 data->op = NULL; 236 } 237 if (data->op_form) 238 gtk_widget_destroy (data->op_form); 239 _gda_report_document_run_converter_argv(GdaReportDocument * doc,const gchar * filename,gchar ** argv,gint argv_index_fname,const gchar * converter_name,GError ** error)240 gtk_widget_set_sensitive (data->show_button, FALSE); 241 gtk_widget_set_sensitive (data->sql_button, FALSE); 242 243 iter = gdaui_data_selector_get_data_set (GDAUI_DATA_SELECTOR (data->op_combo)); 244 if (iter) 245 cvalue = gda_data_model_iter_get_value_at (iter, 0); 246 if (!cvalue || !gda_value_isa ((GValue *) cvalue, G_TYPE_INT)) { 247 GtkWidget *label; 248 249 label = gtk_label_new ("Select an operation to perform"); 250 gtk_container_add (GTK_CONTAINER (data->op_container), label); 251 data->op_form = label; 252 gtk_widget_show (data->op_form); 253 return; 254 } 255 type = g_value_get_int ((GValue *) cvalue); 256 257 prov = get_provider_obj (data); 258 if (prov) 259 data->op = gda_server_provider_create_operation (prov, NULL, type, NULL, &error); 260 261 if (!data->op) { 262 GtkWidget *label; 263 gchar *str; 264 265 str = g_strdup_printf ("Can't create GdaServerOperation widget: %s", 266 error && error->message ? error->message : "No detail"); 267 label = gtk_label_new (str); 268 g_free (str); 269 gtk_container_add (GTK_CONTAINER (data->op_container), label); 270 data->op_form = label; 271 } 272 else { 273 GtkWidget *wid; 274 275 wid = gdaui_server_operation_new (data->op); 276 gtk_container_add (GTK_CONTAINER (data->op_container), wid); 277 data->op_form = wid; 278 gtk_widget_set_sensitive (data->show_button, TRUE); 279 gtk_widget_set_sensitive (data->sql_button, TRUE); 280 } 281 gtk_widget_show (data->op_form); 282 } 283 284 static void 285 extract_named_parameters (GdaServerOperation *op, const gchar *root_path, GtkTextBuffer *tbuffer) 286 { 287 GdaServerOperationNode *node; 288 GtkTextIter iter; 289 gchar *str; 290 291 node = gda_server_operation_get_node_info (op, root_path); 292 g_return_if_fail (node); 293 294 gtk_text_buffer_get_end_iter (tbuffer, &iter); 295 296 gtk_text_buffer_insert (tbuffer, &iter, " * ", -1); 297 if (node->status == GDA_SERVER_OPERATION_STATUS_REQUIRED) 298 gtk_text_buffer_insert_with_tags_by_name (tbuffer, &iter, root_path, -1, "req_pathname", NULL); 299 else 300 gtk_text_buffer_insert_with_tags_by_name (tbuffer, &iter, root_path, -1, "opt_pathname", NULL); 301 gtk_text_buffer_insert (tbuffer, &iter, " (", -1); 302 303 switch (node->type) { 304 case GDA_SERVER_OPERATION_NODE_PARAMLIST: { 305 GSList *params; 306 307 str = g_strdup_printf ("GdaSet @%p)\n", node->plist); 308 gtk_text_buffer_insert (tbuffer, &iter, str, -1); 309 g_free (str); 310 311 for (params = node->plist->holders; params; params = params->next) { 312 gchar *npath; 313 npath = g_strdup_printf ("%s/%s", root_path, gda_holder_get_id (GDA_HOLDER (params->data))); 314 extract_named_parameters (op, npath, tbuffer); 315 g_free (npath); 316 } 317 318 break; 319 } 320 case GDA_SERVER_OPERATION_NODE_DATA_MODEL: { 321 gint i, ncols; 322 323 str = g_strdup_printf ("GdaDataModel @%p)\n", node->model); 324 gtk_text_buffer_insert (tbuffer, &iter, str, -1); 325 g_free (str); 326 327 ncols = gda_data_model_get_n_columns (node->model); 328 for (i = 0; i < ncols; i++) { 329 GdaColumn *col = gda_data_model_describe_column (node->model, i); 330 gchar *npath, *str; 331 332 g_object_get (G_OBJECT (col), "id", &str, NULL); 333 npath = g_strdup_printf ("%s/@%s", root_path, str); 334 g_free (str); 335 extract_named_parameters (op, npath, tbuffer); 336 g_free (npath); 337 } gda_report_document_run_as_html(GdaReportDocument * doc,const gchar * filename,GError ** error)338 break; 339 } 340 case GDA_SERVER_OPERATION_NODE_PARAM: { 341 gchar *str; 342 const GValue *value; 343 344 gtk_text_buffer_insert (tbuffer, &iter, "GdaHolder) = ", -1); 345 346 value = gda_holder_get_value (node->param); 347 str = gda_value_stringify (value); 348 gtk_text_buffer_insert (tbuffer, &iter, str, -1); 349 gtk_text_buffer_insert (tbuffer, &iter, "\n", -1); 350 g_free (str); 351 break; 352 } 353 case GDA_SERVER_OPERATION_NODE_SEQUENCE: { 354 gtk_text_buffer_insert (tbuffer, &iter, "Sequence)\n", -1); 355 guint i, size = gda_server_operation_get_sequence_size (op, root_path); 356 for (i = 0; i < size; i++) { 357 gchar **names; 358 names = gda_server_operation_get_sequence_item_names (op, root_path); 359 guint n; 360 for (n = 0; names [n]; n++) { 361 gchar *npath; 362 npath = g_strdup_printf ("%s/%u%s", root_path, i, names [n]); gda_report_document_run_as_pdf(GdaReportDocument * doc,const gchar * filename,GError ** error)363 extract_named_parameters (op, npath, tbuffer); 364 g_free (npath); 365 } 366 g_strfreev (names); 367 } 368 break; 369 } 370 371 case GDA_SERVER_OPERATION_NODE_SEQUENCE_ITEM: 372 gtk_text_buffer_insert (tbuffer, &iter, "Sequence item)\n", -1); 373 break; 374 375 case GDA_SERVER_OPERATION_NODE_DATA_MODEL_COLUMN: { 376 gint j, nrows; 377 378 gtk_text_buffer_insert (tbuffer, &iter, "Model column)\n", -1); 379 380 nrows = gda_data_model_get_n_rows (node->model); 381 for (j = 0; j < nrows; j++) { 382 gchar *npath, *str; 383 const GValue *value; 384 385 npath = g_strdup_printf ("%s/%d", root_path, j); 386 value = gda_data_model_get_value_at (node->model, gda_column_get_position (node->column), j, NULL); 387 if (value) 388 str = gda_value_stringify (value); 389 else 390 str = g_strdup ("Error: could not read data model's value"); 391 gtk_text_buffer_insert (tbuffer, &iter, " * ", -1); 392 gtk_text_buffer_insert_with_tags_by_name (tbuffer, &iter, npath, -1, "opt_pathname", NULL); 393 g_free (npath); 394 gtk_text_buffer_insert (tbuffer, &iter, " (GValue) = ", -1); 395 gtk_text_buffer_insert (tbuffer, &iter, str, -1); 396 gtk_text_buffer_insert (tbuffer, &iter, "\n", -1); 397 g_free (str); 398 } 399 400 break; 401 } 402 default: 403 gtk_text_buffer_insert (tbuffer, &iter, "???", -1); 404 break; 405 } 406 } 407 408 static void 409 show_named_parameters (G_GNUC_UNUSED GtkButton *button, DemoData *data) 410 { 411 GtkWidget *dlg, *label; 412 gchar **root_nodes; 413 gint i; 414 GtkWidget *view; 415 GtkWidget *sw; 416 GtkTextBuffer *buffer; 417 GtkTextIter iter; 418 419 if (!data->op || !data->op_form || ! GDAUI_IS_SERVER_OPERATION (data->op_form)) 420 return; 421 422 /* dialog box */ 423 dlg = gtk_dialog_new_with_buttons ("Named parameters", 424 GTK_WINDOW (data->top_window), 425 GTK_DIALOG_MODAL, 426 GTK_STOCK_CLOSE, GTK_RESPONSE_REJECT, NULL); 427 428 label = gtk_label_new ("<b>Named parameters:</b>\n"); 429 gtk_misc_set_alignment (GTK_MISC (label), 0., -1); 430 gtk_label_set_use_markup (GTK_LABEL (label), TRUE); 431 gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))), 432 label, FALSE, FALSE, 0); 433 gtk_widget_show (label); 434 435 /* text area */ 436 view = gtk_text_view_new (); 437 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)); 438 gtk_text_buffer_get_start_iter (buffer, &iter); 439 gtk_text_buffer_create_tag (buffer, "opt_pathname", 440 "weight", PANGO_WEIGHT_BOLD, 441 "foreground", "grey", NULL); 442 gtk_text_buffer_create_tag (buffer, "req_pathname", 443 "weight", PANGO_WEIGHT_BOLD, 444 "foreground", "blue", NULL); 445 446 xmlNodePtr xml; 447 xml = gda_server_operation_save_data_to_xml (data->op, NULL); 448 if (xml) { 449 g_print ("XML rendering of the GdaServerOperation is:\n"); 450 xmlBufferPtr buffer; 451 buffer = xmlBufferCreate (); 452 xmlNodeDump (buffer, NULL, xml, 0, 1); 453 xmlFreeNode (xml); 454 xmlBufferDump (stdout, buffer); 455 xmlBufferFree (buffer); 456 g_print ("\n"); 457 } 458 else { 459 g_print ("XML rendering ERROR\n"); 460 } 461 462 root_nodes = gda_server_operation_get_root_nodes (data->op); 463 for (i = 0; root_nodes && root_nodes[i]; i++) 464 extract_named_parameters (data->op, root_nodes[i], buffer); 465 g_strfreev (root_nodes); 466 467 sw = gtk_scrolled_window_new (NULL, NULL); 468 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), 469 GTK_POLICY_AUTOMATIC, 470 GTK_POLICY_AUTOMATIC); 471 gtk_container_add (GTK_CONTAINER (sw), view); 472 gtk_widget_show_all (sw); 473 474 gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))), 475 sw, TRUE, TRUE, 0); 476 gtk_widget_set_size_request (dlg, 530, 350); 477 478 gtk_dialog_run (GTK_DIALOG (dlg)); 479 gtk_widget_destroy (dlg); 480 } 481 482 static void 483 show_sql (G_GNUC_UNUSED GtkButton *button, DemoData *data) 484 { 485 GdaServerProvider *prov; 486 487 if (!data->op) 488 return; 489 490 prov = get_provider_obj (data); 491 if (prov) { 492 gchar *sql, *msg; 493 GtkMessageType msg_type = GTK_MESSAGE_INFO; 494 GtkWidget *dlg; 495 GError *error = NULL; 496 497 sql = gda_server_provider_render_operation (prov, NULL, data->op, &error); 498 if (!sql) { 499 msg_type = GTK_MESSAGE_ERROR; 500 msg = g_strdup_printf ("<b>Can't render operation as SQL:</b>\n%s\n", 501 error && error->message ? error->message : 502 "No detail (This operation may not be accessible using SQL)"); 503 if (error) 504 g_error_free (error); 505 } 506 else 507 msg = g_strdup_printf ("<b>SQL:</b>\n%s", sql); 508 509 dlg = gtk_message_dialog_new (GTK_WINDOW (data->top_window), 510 GTK_DIALOG_MODAL, msg_type, GTK_BUTTONS_CLOSE, NULL); 511 gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dlg), msg); 512 g_free (sql); 513 g_free (msg); 514 515 gtk_dialog_run (GTK_DIALOG (dlg)); 516 gtk_widget_destroy (dlg); 517 } 518 else 519 g_warning ("Could not get provider object"); 520 } 521