1 /* 2 * Copyright (C) 2000 - 2001 Reinhard Müller <reinhard@src.gnome.org> 3 * Copyright (C) 2000 - 2004 Rodrigo Moya <rodrigo@gnome-db.org> 4 * Copyright (C) 2001 - 2003 Gonzalo Paniagua Javier <gonzalo@gnome-db.org> 5 * Copyright (C) 2001 - 2013 Vivien Malerba <malerba@gnome-db.org> 6 * Copyright (C) 2002 Andrew Hill <andru@src.gnome.org> 7 * Copyright (C) 2002 Cleber Rodrigues <cleberrrjr@bol.com.br> 8 * Copyright (C) 2002 Zbigniew Chyla <cyba@gnome.pl> 9 * Copyright (C) 2003 Laurent Sansonetti <lrz@src.gnome.org> 10 * Copyright (C) 2003 Paisa Seeluangsawat <paisa@users.sf.net> 11 * Copyright (C) 2004 - 2005 Alan Knowles <alank@src.gnome.org> 12 * Copyright (C) 2004 Dani Baeyens <daniel.baeyens@hispalinux.es> 13 * Copyright (C) 2004 José María Casanova Crespo <jmcasanova@igalia.com> 14 * Copyright (C) 2004 Szalai Ferenc <szferi@einstein.ki.iif.hu> 15 * Copyright (C) 2005 - 2009 Bas Driessen <bas.driessen@xobas.com> 16 * Copyright (C) 2005 Álvaro Peña <alvaropg@telefonica.net> 17 * Copyright (C) 2006 - 2012 Murray Cumming <murrayc@murrayc.com> 18 * Copyright (C) 2007 Armin Burgmeier <armin@openismus.com> 19 * Copyright (C) 2007 Leonardo Boshell <lb@kmc.com.co> 20 * Copyright (C) 2008 Johannes Schmid <jschmid@openismus.com> 21 * Copyright (C) 2010 David King <davidk@openismus.com> 22 * Copyright (C) 2010 Jonh Wendell <jwendell@gnome.org> 23 * Copyright (C) 2011,2018 Daniel Espinosa <esodan@gmail.com> 24 * 25 * This library is free software; you can redistribute it and/or 26 * modify it under the terms of the GNU Lesser General Public 27 * License as published by the Free Software Foundation; either 28 * version 2 of the License, or (at your option) any later version. 29 * 30 * This library is distributed in the hope that it will be useful, 31 * but WITHOUT ANY WARRANTY; without even the implied warranty of 32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 33 * Lesser General Public License for more details. 34 * 35 * You should have received a copy of the GNU Lesser General Public 36 * License along with this library; if not, write to the 37 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 38 * Boston, MA 02110-1301, USA. 39 */ 40 41 #undef GDA_DISABLE_DEPRECATED 42 #include <stdio.h> 43 #include <libgda/gda-config.h> 44 #include <libgda/gda-connection.h> 45 #include <libgda/gda-connection-private.h> 46 #include <libgda/gda-connection-internal.h> 47 #include <libgda/gda-connection-event.h> 48 #include <glib/gi18n-lib.h> 49 #include <libgda/gda-log.h> 50 #include <libgda/gda-server-provider.h> 51 #include <libgda/gda-server-provider-extra.h> 52 #include "gda-marshal.h" 53 #include <libgda/gda-transaction-status-private.h> 54 #include <string.h> 55 #include <libgda/gda-enum-types.h> 56 #include <libgda/gda-holder.h> 57 #include <libgda/gda-set.h> 58 #include <sql-parser/gda-sql-parser.h> 59 #include <sql-parser/gda-statement-struct-trans.h> 60 #include <libgda/gda-meta-store-extra.h> 61 #include <libgda/gda-util.h> 62 #include <libgda/gda-mutex.h> 63 #include <libgda/gda-lockable.h> 64 #include <libgda/thread-wrapper/gda-thread-provider.h> 65 #include <libgda/gda-repetitive-statement.h> 66 #include <gda-statement-priv.h> 67 #include <sqlite/virtual/gda-vconnection-data-model.h> 68 #include <libgda/gda-debug-macros.h> 69 #include <libgda/gda-data-handler.h> 70 71 #include <glib/gstdio.h> 72 #include <fcntl.h> 73 #include <unistd.h> 74 75 static GMutex parser_mutex; 76 static GdaSqlParser *internal_parser = NULL; 77 78 #define PROV_CLASS(provider) (GDA_SERVER_PROVIDER_CLASS (G_OBJECT_GET_CLASS (provider))) 79 80 /* number of GdaConnectionEvent kept by each connection. Should be enough to avoid losing any 81 * event, considering that the events are reseted after each statement execution */ 82 #define EVENTS_ARRAY_SIZE 5 83 84 struct _GdaConnectionPrivate { 85 GdaServerProvider *provider_obj; 86 GdaConnectionOptions options; /* ORed flags */ 87 gchar *dsn; 88 gchar *cnc_string; 89 gchar *auth_string; 90 gboolean is_thread_wrapper; 91 guint monitor_id; 92 93 GdaMetaStore *meta_store; 94 95 gboolean auto_clear_events; /* TRUE if events_list is cleared before any statement execution */ 96 GdaConnectionEvent **events_array; /* circular array */ 97 gint events_array_size; 98 gboolean events_array_full; 99 gint events_array_next; 100 GList *events_list; /* for API compat */ 101 102 GdaTransactionStatus *trans_status; 103 GHashTable *prepared_stmts; 104 105 gpointer provider_data; 106 GDestroyNotify provider_data_destroy_func; 107 108 /* multi threading locking */ 109 GThread *unique_possible_thread; /* non NULL => only that thread can use this connection */ 110 GCond unique_possible_cond; 111 GMutex object_mutex; 112 GRecMutex rmutex; 113 /* Asynchronous statement execution */ 114 guint next_task_id; /* starts at 1 as 0 is an error */ 115 GArray *waiting_tasks; /* array of CncTask pointers to tasks to be executed */ 116 GArray *completed_tasks; /* array of CncTask pointers to tasks already executed */ 117 118 /* auto meta data update */ 119 GArray *trans_meta_context; /* Array of GdaMetaContext pointers */ 120 121 gboolean exec_times; 122 guint exec_slowdown; 123 124 ThreadConnectionData *th_data; /* used if connection is used by the GdaThreadProvider, NULL otherwise */ 125 }; 126 127 /* represents an asynchronous execution task */ 128 typedef struct { 129 guint task_id; /* ID assigned by GdaConnection object */ 130 guint prov_task_id; /* ID assigned by GdaServerProvider */ 131 gboolean being_processed; /* TRUE if currently being processed */ 132 GRecMutex rmutex; 133 GdaStatement *stmt; /* statement to execute */ 134 GdaStatementModelUsage model_usage; 135 GType *col_types; 136 GdaSet *params; 137 gboolean need_last_insert_row; 138 GdaSet *last_insert_row; 139 GObject *result; 140 GError *error; 141 GTimer *exec_timer; 142 } CncTask; 143 #define CNC_TASK(x) ((CncTask*)(x)) 144 145 static CncTask *cnc_task_new (guint id, GdaStatement *stmt, GdaStatementModelUsage model_usage, 146 GType *col_types, GdaSet *params, gboolean need_last_insert_row); 147 static void cnc_task_free (CncTask *task); 148 #define cnc_task_lock(task) g_rec_mutex_lock (&((task)->rmutex)) 149 #define cnc_task_unlock(task) g_rec_mutex_unlock (&((task)->rmutex)) 150 151 static void add_exec_time_to_object (GObject *obj, GTimer *timer); 152 153 static void gda_connection_class_init (GdaConnectionClass *klass); 154 static void gda_connection_init (GdaConnection *cnc, GdaConnectionClass *klass); 155 static void gda_connection_dispose (GObject *object); 156 static void gda_connection_finalize (GObject *object); 157 static void gda_connection_set_property (GObject *object, 158 guint param_id, 159 const GValue *value, 160 GParamSpec *pspec); 161 static void gda_connection_get_property (GObject *object, 162 guint param_id, 163 GValue *value, 164 GParamSpec *pspec); 165 166 /* GdaLockable interface */ 167 static void gda_connection_lockable_init (GdaLockableIface *iface); 168 static void gda_connection_lock (GdaLockable *lockable); 169 static gboolean gda_connection_trylock (GdaLockable *lockable); 170 static void gda_connection_unlock (GdaLockable *lockable); 171 172 static void update_meta_store_after_statement_exec (GdaConnection *cnc, GdaStatement *stmt, GdaSet *params); 173 static void change_events_array_max_size (GdaConnection *cnc, gint size); 174 175 enum { 176 ERROR, 177 CONN_OPENED, 178 CONN_TO_CLOSE, 179 CONN_CLOSED, 180 DSN_CHANGED, 181 TRANSACTION_STATUS_CHANGED, 182 LAST_SIGNAL 183 }; 184 185 static gint gda_connection_signals[LAST_SIGNAL] = { 0, 0, 0, 0, 0, 0 }; 186 187 /* properties */ 188 enum 189 { 190 PROP_0, 191 PROP_DSN, 192 PROP_CNC_STRING, 193 PROP_PROVIDER_OBJ, 194 PROP_AUTH_STRING, 195 PROP_OPTIONS, 196 PROP_META_STORE, 197 PROP_THREAD_OWNER, 198 PROP_IS_THREAD_WRAPPER, 199 PROP_MONITOR_WRAPPED_IN_MAINLOOP, 200 PROP_EVENTS_HISTORY_SIZE, 201 PROP_EXEC_TIMES, 202 PROP_EXEC_SLOWDOWN 203 }; 204 205 static GObjectClass *parent_class = NULL; 206 extern GdaServerProvider *_gda_config_sqlite_provider; /* defined in gda-config.c */ 207 static GdaServerProvider *_gda_thread_wrapper_provider = NULL; 208 209 static gint debug_level = -1; 210 static void 211 dump_exec_params (GdaConnection *cnc, GdaStatement *stmt, GdaSet *params) 212 { 213 if (params && (debug_level & 8)) { 214 GSList *list; 215 gchar *sql; 216 sql = gda_statement_to_sql_extended (stmt, cnc, params, GDA_STATEMENT_SQL_PARAMS_SHORT, 217 NULL, NULL); 218 g_print ("EVENT> COMMAND: parameters (on cnx %p) for statement [%s]\n", cnc, sql); 219 for (list = params->holders; list; list = list->next) { 220 GdaHolder *holder = GDA_HOLDER (list->data); 221 gchar *str; 222 const GValue *value; 223 value = gda_holder_get_value (holder); 224 str = value ? gda_value_stringify (value) : "NULL"; 225 g_print ("\t%s: type=>%s, value=>%s\n", gda_holder_get_id (holder), 226 gda_g_type_to_string (gda_holder_get_g_type (holder)), 227 str); 228 if (value) 229 g_free (str); 230 } 231 g_free (sql); 232 } 233 } 234 235 236 /* 237 * GdaConnection class implementation 238 * @klass: 239 */ 240 static void 241 gda_connection_class_init (GdaConnectionClass *klass) 242 { 243 GObjectClass *object_class = G_OBJECT_CLASS (klass); 244 245 parent_class = g_type_class_peek_parent (klass); 246 247 /** 248 * GdaConnection::error: 249 * @cnc: the #GdaConnection 250 * @event: a #GdaConnectionEvent object 251 * 252 * Gets emitted whenever a connection event occurs. Check the nature of @event to 253 * see if it's an error or a simple notification 254 */ 255 gda_connection_signals[ERROR] = 256 g_signal_new ("error", 257 G_TYPE_FROM_CLASS (object_class), 258 G_SIGNAL_RUN_LAST, 259 G_STRUCT_OFFSET (GdaConnectionClass, error), 260 NULL, NULL, 261 g_cclosure_marshal_VOID__OBJECT, 262 G_TYPE_NONE, 1, GDA_TYPE_CONNECTION_EVENT); 263 /** 264 * GdaConnection::conn-opened: 265 * @cnc: the #GdaConnection 266 * 267 * Gets emitted when the connection has been opened to the database 268 */ 269 gda_connection_signals[CONN_OPENED] = 270 g_signal_new ("conn-opened", 271 G_TYPE_FROM_CLASS (object_class), 272 G_SIGNAL_RUN_FIRST, 273 G_STRUCT_OFFSET (GdaConnectionClass, conn_opened), 274 NULL, NULL, 275 _gda_marshal_VOID__VOID, 276 G_TYPE_NONE, 0); 277 /** 278 * GdaConnection::conn-to-close: 279 * @cnc: the #GdaConnection 280 * 281 * Gets emitted when the connection to the database is about to be closed 282 */ 283 gda_connection_signals[CONN_TO_CLOSE] = 284 g_signal_new ("conn-to-close", 285 G_TYPE_FROM_CLASS (object_class), 286 G_SIGNAL_RUN_FIRST, 287 G_STRUCT_OFFSET (GdaConnectionClass, conn_to_close), 288 NULL, NULL, 289 _gda_marshal_VOID__VOID, 290 G_TYPE_NONE, 0); 291 /** 292 * GdaConnection::conn-closed: 293 * @cnc: the #GdaConnection 294 * 295 * Gets emitted when the connection to the database has been closed 296 */ 297 gda_connection_signals[CONN_CLOSED] = /* runs after user handlers */ 298 g_signal_new ("conn-closed", 299 G_TYPE_FROM_CLASS (object_class), 300 G_SIGNAL_RUN_LAST, 301 G_STRUCT_OFFSET (GdaConnectionClass, conn_closed), 302 NULL, NULL, 303 _gda_marshal_VOID__VOID, 304 G_TYPE_NONE, 0); 305 /** 306 * GdaConnection::dsn-changed: 307 * @cnc: the #GdaConnection 308 * 309 * Gets emitted when the DSN used by @cnc has been changed 310 */ 311 gda_connection_signals[DSN_CHANGED] = 312 g_signal_new ("dsn-changed", 313 G_TYPE_FROM_CLASS (object_class), 314 G_SIGNAL_RUN_LAST, 315 G_STRUCT_OFFSET (GdaConnectionClass, dsn_changed), 316 NULL, NULL, 317 g_cclosure_marshal_VOID__VOID, 318 G_TYPE_NONE, 0); 319 /** 320 * GdaConnection::transaction-status-changed: 321 * @cnc: the #GdaConnection 322 * 323 * Gets emitted when the transaction status of @cnc has changed (a transaction has been 324 * started, rolled back, a savepoint added,...) 325 */ 326 gda_connection_signals[TRANSACTION_STATUS_CHANGED] = 327 g_signal_new ("transaction-status-changed", 328 G_TYPE_FROM_CLASS (object_class), 329 G_SIGNAL_RUN_LAST, 330 G_STRUCT_OFFSET (GdaConnectionClass, transaction_status_changed), 331 NULL, NULL, 332 g_cclosure_marshal_VOID__VOID, 333 G_TYPE_NONE, 0); 334 335 /* Properties */ 336 object_class->set_property = gda_connection_set_property; 337 object_class->get_property = gda_connection_get_property; 338 339 g_object_class_install_property (object_class, PROP_DSN, 340 g_param_spec_string ("dsn", NULL, _("DSN to use"), NULL, 341 (G_PARAM_READABLE | G_PARAM_WRITABLE))); 342 g_object_class_install_property (object_class, PROP_CNC_STRING, 343 g_param_spec_string ("cnc-string", NULL, _("Connection string to use"), NULL, 344 (G_PARAM_READABLE | G_PARAM_WRITABLE))); 345 g_object_class_install_property (object_class, PROP_PROVIDER_OBJ, 346 g_param_spec_object ("provider", NULL, _("Provider to use"), 347 GDA_TYPE_SERVER_PROVIDER, 348 (G_PARAM_READABLE | G_PARAM_WRITABLE))); 349 350 g_object_class_install_property (object_class, PROP_AUTH_STRING, 351 g_param_spec_string ("auth-string", NULL,_("Authentication string to use"), 352 NULL, 353 (G_PARAM_READABLE | G_PARAM_WRITABLE))); 354 g_object_class_install_property (object_class, PROP_OPTIONS, 355 g_param_spec_flags ("options", NULL, _("Options"), 356 GDA_TYPE_CONNECTION_OPTIONS, GDA_CONNECTION_OPTIONS_NONE, 357 (G_PARAM_READABLE | G_PARAM_WRITABLE))); 358 g_object_class_install_property (object_class, PROP_META_STORE, 359 /* To translators: Don't translate "GdaMetaStore", it's a class name */ 360 g_param_spec_object ("meta-store", NULL, _ ("GdaMetaStore used by the connection"), 361 GDA_TYPE_META_STORE, 362 (G_PARAM_READABLE | G_PARAM_WRITABLE))); 363 364 g_object_class_install_property (object_class, PROP_THREAD_OWNER, 365 g_param_spec_pointer ("thread-owner", NULL, 366 _("Unique GThread from which the connection will be available." 367 "This should only be modified by the database providers' implementation"), 368 (G_PARAM_READABLE | G_PARAM_WRITABLE))); 369 370 /** 371 * GdaConnection:is-wrapper: 372 * 373 * This property, if set to %TRUE, specifies that the connection is not a real connection, but rather 374 * a #GdaConnection object which "proxies" all the calls to another connection which executes in a sub 375 * thread. 376 * 377 * Note: this property is used internally by Libgda and should not be directly used by any programs. Setting 378 * this property has no effect, reading it is supported, though. 379 * 380 * Since: 4.2 381 **/ 382 g_object_class_install_property (object_class, PROP_IS_THREAD_WRAPPER, 383 g_param_spec_boolean ("is-wrapper", NULL, 384 _("Determines if the connection acts as a thread wrapper around another connection, making it completely thread safe"), 385 FALSE, 386 G_PARAM_READABLE | G_PARAM_WRITABLE)); 387 388 /** 389 * GdaConnection:monitor-wrapped-in-mainloop: 390 * 391 * Useful only when there is a mainloop and when the connection acts as a thread wrapper around another connection, 392 * it sets up a timeout to handle signals coming from the wrapped connection. 393 * 394 * If the connection is not a thread wrapper, then this property has no effect. 395 * 396 * Since: 4.2 397 **/ 398 g_object_class_install_property (object_class, PROP_MONITOR_WRAPPED_IN_MAINLOOP, 399 g_param_spec_boolean ("monitor-wrapped-in-mainloop", NULL, 400 _("Make the connection set up a monitoring function in the mainloop to monitor the wrapped connection"), 401 FALSE, 402 (G_PARAM_READABLE | G_PARAM_WRITABLE))); 403 404 /** 405 * GdaConnection:events-history-size: 406 * 407 * Defines the number of #GdaConnectionEvent objects kept in memory which can 408 * be fetched using gda_connection_get_events(). 409 * 410 * Since: 4.2 411 */ 412 g_object_class_install_property (object_class, PROP_EVENTS_HISTORY_SIZE, 413 g_param_spec_int ("events-history-size", NULL, 414 _("Number of history events to keep in memory"), EVENTS_ARRAY_SIZE, G_MAXINT, 415 EVENTS_ARRAY_SIZE, 416 (G_PARAM_READABLE | G_PARAM_WRITABLE))); 417 418 /** 419 * GdaConnection:execution-timer: 420 * 421 * Computes execution times for each statement executed. 422 * 423 * Since: 4.2.9 424 **/ 425 g_object_class_install_property (object_class, PROP_EXEC_TIMES, 426 g_param_spec_boolean ("execution-timer", NULL, 427 _("Computes execution delay for each executed statement"), 428 FALSE, 429 (G_PARAM_READABLE | G_PARAM_WRITABLE))); 430 /** 431 * GdaConnection:execution-slowdown: 432 * 433 * Artificially slows down the execution of queries. This property can be used to 434 * debug some problems. If non zero, this value is the number of microseconds waited before actually 435 * executing each query. 436 * 437 * Since: 5.2.0 438 **/ 439 g_object_class_install_property (object_class, PROP_EXEC_SLOWDOWN, 440 g_param_spec_uint ("execution-slowdown", NULL, 441 _("Artificially slows down the execution of queries"), 442 0, G_MAXUINT, 0, 443 (G_PARAM_READABLE | G_PARAM_WRITABLE))); 444 445 object_class->dispose = gda_connection_dispose; 446 object_class->finalize = gda_connection_finalize; 447 448 /* computing debug level */ 449 if (debug_level == -1) { 450 const gchar *str; 451 debug_level = 0; 452 str = getenv ("GDA_CONNECTION_EVENTS_SHOW"); /* Flawfinder: ignore */ 453 if (str) { 454 gchar **array; 455 guint i; 456 guint array_len; 457 array = g_strsplit_set (str, " ,/;:", 0); 458 array_len = g_strv_length (array); 459 for (i = 0; i < array_len; i++) { 460 if (!g_ascii_strcasecmp (array[i], "notice")) 461 debug_level += 1; 462 else if (!g_ascii_strcasecmp (array[i], "warning")) 463 debug_level += 2; 464 else if (!g_ascii_strcasecmp (array[i], "error")) 465 debug_level += 4; 466 else if (!g_ascii_strcasecmp (array[i], "command")) 467 debug_level += 8; 468 } 469 g_strfreev (array); 470 } 471 } 472 } 473 474 static void 475 gda_connection_lockable_init (GdaLockableIface *iface) 476 { 477 iface->i_lock = gda_connection_lock; 478 iface->i_trylock = gda_connection_trylock; 479 iface->i_unlock = gda_connection_unlock; 480 } 481 482 static void 483 gda_connection_init (GdaConnection *cnc, G_GNUC_UNUSED GdaConnectionClass *klass) 484 { 485 g_return_if_fail (GDA_IS_CONNECTION (cnc)); 486 487 cnc->priv = g_new0 (GdaConnectionPrivate, 1); 488 cnc->priv->unique_possible_thread = NULL; 489 g_mutex_init (&cnc->priv->object_mutex); 490 g_rec_mutex_init (&cnc->priv->rmutex); 491 g_cond_init (& cnc->priv->unique_possible_cond); 492 cnc->priv->provider_obj = NULL; 493 cnc->priv->dsn = NULL; 494 cnc->priv->cnc_string = NULL; 495 cnc->priv->auth_string = NULL; 496 cnc->priv->auto_clear_events = TRUE; 497 cnc->priv->events_array_size = EVENTS_ARRAY_SIZE; 498 cnc->priv->events_array = g_new0 (GdaConnectionEvent*, EVENTS_ARRAY_SIZE); 499 cnc->priv->events_array_full = FALSE; 500 cnc->priv->events_array_next = 0; 501 cnc->priv->trans_status = NULL; /* no transaction yet */ 502 cnc->priv->prepared_stmts = NULL; 503 504 cnc->priv->is_thread_wrapper = FALSE; 505 cnc->priv->monitor_id = 0; 506 507 cnc->priv->next_task_id = 1; 508 cnc->priv->waiting_tasks = g_array_new (FALSE, FALSE, sizeof (gpointer)); 509 cnc->priv->completed_tasks = g_array_new (FALSE, FALSE, sizeof (gpointer)); 510 511 cnc->priv->trans_meta_context = NULL; 512 cnc->priv->provider_data = NULL; 513 514 cnc->priv->exec_times = FALSE; 515 cnc->priv->exec_slowdown = 0; 516 } 517 518 static void auto_update_meta_context_free (GdaMetaContext *context); 519 static void prepared_stms_foreach_func (GdaStatement *gda_stmt, GdaPStmt *prepared_stmt, GdaConnection *cnc); 520 static void 521 gda_connection_dispose (GObject *object) 522 { 523 GdaConnection *cnc = (GdaConnection *) object; 524 525 g_return_if_fail (GDA_IS_CONNECTION (cnc)); 526 527 /* free memory */ 528 cnc->priv->unique_possible_thread = NULL; 529 gda_connection_close_no_warning (cnc); 530 531 if (cnc->priv->th_data) { 532 _gda_thread_connection_data_free (cnc->priv->th_data); 533 cnc->priv->th_data = NULL; 534 } 535 536 /* get rid of prepared statements to avoid problems */ 537 if (cnc->priv->prepared_stmts) { 538 g_hash_table_foreach (cnc->priv->prepared_stmts, 539 (GHFunc) prepared_stms_foreach_func, cnc); 540 g_hash_table_destroy (cnc->priv->prepared_stmts); 541 cnc->priv->prepared_stmts = NULL; 542 } 543 544 if (cnc->priv->provider_obj) { 545 _gda_server_provider_handlers_clear_for_cnc (cnc->priv->provider_obj, cnc); 546 g_object_unref (G_OBJECT (cnc->priv->provider_obj)); 547 cnc->priv->provider_obj = NULL; 548 } 549 550 if (cnc->priv->events_list) { 551 g_list_foreach (cnc->priv->events_list, (GFunc) g_object_unref, NULL); 552 g_list_free (cnc->priv->events_list); 553 cnc->priv->events_list = NULL; 554 } 555 556 if (cnc->priv->events_array) { 557 gint i; 558 for (i = 0; i < cnc->priv->events_array_size ; i++) { 559 GdaConnectionEvent *ev; 560 ev = cnc->priv->events_array [i]; 561 if (ev) 562 g_object_unref (ev); 563 } 564 g_free (cnc->priv->events_array); 565 cnc->priv->events_array = NULL; 566 } 567 568 if (cnc->priv->trans_status) { 569 g_object_unref (cnc->priv->trans_status); 570 cnc->priv->trans_status = NULL; 571 } 572 573 if (cnc->priv->meta_store != NULL) { 574 g_object_unref (cnc->priv->meta_store); 575 cnc->priv->meta_store = NULL; 576 } 577 578 if (cnc->priv->waiting_tasks) { 579 gint i, len = cnc->priv->waiting_tasks->len; 580 for (i = 0; i < len; i++) 581 cnc_task_free (CNC_TASK (g_array_index (cnc->priv->waiting_tasks, gpointer, i))); 582 g_array_free (cnc->priv->waiting_tasks, TRUE); 583 cnc->priv->waiting_tasks = NULL; 584 } 585 586 if (cnc->priv->completed_tasks) { 587 gssize i, len = cnc->priv->completed_tasks->len; 588 for (i = 0; i < len; i++) 589 cnc_task_free (CNC_TASK (g_array_index (cnc->priv->completed_tasks, gpointer, i))); 590 g_array_free (cnc->priv->completed_tasks, TRUE); 591 cnc->priv->completed_tasks = NULL; 592 } 593 594 if (cnc->priv->trans_meta_context) { 595 gsize i; 596 for (i = 0; i < cnc->priv->trans_meta_context->len; i++) { 597 GdaMetaContext *context; 598 context = g_array_index (cnc->priv->trans_meta_context, GdaMetaContext*, i); 599 auto_update_meta_context_free (context); 600 } 601 g_array_free (cnc->priv->trans_meta_context, TRUE); 602 cnc->priv->trans_meta_context = NULL; 603 } 604 605 /* chain to parent class */ 606 parent_class->dispose (object); 607 } 608 609 static void 610 gda_connection_finalize (GObject *object) 611 { 612 GdaConnection *cnc = (GdaConnection *) object; 613 614 g_return_if_fail (GDA_IS_CONNECTION (cnc)); 615 616 /* free memory */ 617 g_free (cnc->priv->dsn); 618 g_free (cnc->priv->cnc_string); 619 g_free (cnc->priv->auth_string); 620 621 g_cond_clear (& cnc->priv->unique_possible_cond); 622 g_mutex_clear (& cnc->priv->object_mutex); 623 g_rec_mutex_clear (&cnc->priv->rmutex); 624 625 g_free (cnc->priv); 626 cnc->priv = NULL; 627 628 /* chain to parent class */ 629 parent_class->finalize (object); 630 } 631 632 /* module error */ 633 GQuark gda_connection_error_quark (void) 634 { 635 static GQuark quark; 636 if (!quark) 637 quark = g_quark_from_static_string ("gda_connection_error"); 638 return quark; 639 } 640 641 /** 642 * gda_connection_get_type: 643 * 644 * Registers the #GdaConnection class on the GLib type system. 645 * 646 * Returns: the GType identifying the class. 647 */ 648 GType 649 gda_connection_get_type (void) 650 { 651 static GType type = 0; 652 653 if (G_UNLIKELY (type == 0)) { 654 static GMutex registering; 655 static GTypeInfo info = { 656 sizeof (GdaConnectionClass), 657 (GBaseInitFunc) NULL, 658 (GBaseFinalizeFunc) NULL, 659 (GClassInitFunc) gda_connection_class_init, 660 NULL, NULL, 661 sizeof (GdaConnection), 662 0, 663 (GInstanceInitFunc) gda_connection_init, 664 0 665 }; 666 667 static GInterfaceInfo lockable_info = { 668 (GInterfaceInitFunc) gda_connection_lockable_init, 669 NULL, 670 NULL 671 }; 672 673 g_mutex_lock (®istering); 674 if (type == 0) { 675 type = g_type_register_static (G_TYPE_OBJECT, "GdaConnection", &info, 0); 676 g_type_add_interface_static (type, GDA_TYPE_LOCKABLE, &lockable_info); 677 } 678 g_mutex_unlock (®istering); 679 } 680 681 return type; 682 } 683 684 static gboolean 685 monitor_wrapped_cnc (GdaThreadWrapper *wrapper) 686 { 687 gda_thread_wrapper_iterate (wrapper, FALSE); 688 return TRUE; /* don't remove the monitoring */ 689 } 690 691 void 692 _gda_connection_define_as_thread_wrapper (GdaConnection *cnc) 693 { 694 cnc->priv->is_thread_wrapper = TRUE; 695 } 696 697 static void 698 gda_connection_set_property (GObject *object, 699 guint param_id, 700 const GValue *value, 701 GParamSpec *pspec) 702 { 703 GdaConnection *cnc; 704 705 cnc = GDA_CONNECTION (object); 706 if (cnc->priv) { 707 if (cnc->priv->th_data && ! gda_connection_internal_get_provider_data (cnc)) { 708 _gda_thread_connection_data_free (cnc->priv->th_data); 709 cnc->priv->th_data = NULL; 710 } 711 712 switch (param_id) { 713 case PROP_THREAD_OWNER: 714 g_mutex_lock (&cnc->priv->object_mutex); 715 g_rec_mutex_lock (&cnc->priv->rmutex); 716 cnc->priv->unique_possible_thread = g_value_get_pointer (value); 717 #ifdef GDA_DEBUG_CNC_LOCK 718 g_print ("Unique set to %p\n", cnc->priv->unique_possible_thread); 719 g_print ("Signalling on %p\n", cnc->priv->unique_possible_cond); 720 #endif 721 g_cond_broadcast (& cnc->priv->unique_possible_cond); 722 723 g_rec_mutex_unlock (&cnc->priv->rmutex); 724 g_mutex_unlock (&cnc->priv->object_mutex); 725 break; 726 case PROP_DSN: { 727 const gchar *datasource = g_value_get_string (value); 728 GdaDsnInfo *dsn; 729 730 gda_connection_lock ((GdaLockable*) cnc); 731 _gda_thread_connection_set_data (cnc, NULL); 732 if (cnc->priv->provider_data) { 733 g_warning (_("Could not set the '%s' property when the connection is opened"), 734 pspec->name); 735 gda_connection_unlock ((GdaLockable*) cnc); 736 return; 737 } 738 739 dsn = gda_config_get_dsn_info (datasource); 740 if (!dsn) { 741 g_warning (_("No DSN named '%s' defined"), datasource); 742 gda_connection_unlock ((GdaLockable*) cnc); 743 return; 744 } 745 746 g_free (cnc->priv->dsn); 747 cnc->priv->dsn = g_strdup (datasource); 748 #ifdef GDA_DEBUG_signal 749 g_print (">> 'DSN_CHANGED' from %s\n", __FUNCTION__); 750 #endif 751 g_signal_emit (G_OBJECT (cnc), gda_connection_signals[DSN_CHANGED], 0); 752 #ifdef GDA_DEBUG_signal 753 g_print ("<< 'DSN_CHANGED' from %s\n", __FUNCTION__); 754 #endif 755 gda_connection_unlock ((GdaLockable*) cnc); 756 break; 757 } 758 case PROP_CNC_STRING: 759 gda_connection_lock ((GdaLockable*) cnc); 760 _gda_thread_connection_set_data (cnc, NULL); 761 if (cnc->priv->provider_data) { 762 g_warning (_("Could not set the '%s' property when the connection is opened"), 763 pspec->name); 764 gda_connection_unlock ((GdaLockable*) cnc); 765 return; 766 } 767 g_free (cnc->priv->cnc_string); 768 cnc->priv->cnc_string = NULL; 769 if (g_value_get_string (value)) 770 cnc->priv->cnc_string = g_strdup (g_value_get_string (value)); 771 gda_connection_unlock ((GdaLockable*) cnc); 772 break; 773 case PROP_PROVIDER_OBJ: 774 gda_connection_lock ((GdaLockable*) cnc); 775 _gda_thread_connection_set_data (cnc, NULL); 776 if (cnc->priv->provider_data) { 777 g_warning (_("Could not set the '%s' property when the connection is opened"), 778 pspec->name); 779 gda_connection_unlock ((GdaLockable*) cnc); 780 return; 781 } 782 if (cnc->priv->provider_obj) 783 g_object_unref (cnc->priv->provider_obj); 784 785 cnc->priv->provider_obj = g_value_get_object (value); 786 g_object_ref (G_OBJECT (cnc->priv->provider_obj)); 787 gda_connection_unlock ((GdaLockable*) cnc); 788 break; 789 case PROP_AUTH_STRING: 790 gda_connection_lock ((GdaLockable*) cnc); 791 _gda_thread_connection_set_data (cnc, NULL); 792 if (cnc->priv->provider_data) { 793 g_warning (_("Could not set the '%s' property when the connection is opened"), 794 pspec->name); 795 gda_connection_unlock ((GdaLockable*) cnc); 796 return; 797 } 798 else { 799 const gchar *str = g_value_get_string (value); 800 g_free (cnc->priv->auth_string); 801 cnc->priv->auth_string = NULL; 802 if (str) 803 cnc->priv->auth_string = g_strdup (str); 804 } 805 gda_connection_unlock ((GdaLockable*) cnc); 806 break; 807 case PROP_OPTIONS: { 808 GdaConnectionOptions flags; 809 flags = g_value_get_flags (value); 810 g_rec_mutex_lock (&cnc->priv->rmutex); 811 _gda_thread_connection_set_data (cnc, NULL); 812 if (cnc->priv->provider_data && 813 ((flags & (~GDA_CONNECTION_OPTIONS_SQL_IDENTIFIERS_CASE_SENSITIVE)) != 814 (cnc->priv->options & (~GDA_CONNECTION_OPTIONS_SQL_IDENTIFIERS_CASE_SENSITIVE)))) { 815 g_warning (_("Can't set the '%s' property once the connection is opened"), 816 pspec->name); 817 g_rec_mutex_unlock (&cnc->priv->rmutex); 818 return; 819 } 820 cnc->priv->options = flags; 821 g_rec_mutex_unlock (&cnc->priv->rmutex); 822 break; 823 } 824 case PROP_META_STORE: 825 g_rec_mutex_lock (&cnc->priv->rmutex); 826 if (cnc->priv->meta_store) { 827 g_object_unref (cnc->priv->meta_store); 828 cnc->priv->meta_store = NULL; 829 } 830 cnc->priv->meta_store = g_value_get_object (value); 831 if (cnc->priv->meta_store) 832 g_object_ref (cnc->priv->meta_store); 833 if (cnc->priv->is_thread_wrapper) { 834 ThreadConnectionData *cdata; 835 cdata = (ThreadConnectionData*) gda_connection_internal_get_provider_data (cnc); 836 if (cdata) 837 g_object_set (G_OBJECT (cdata->sub_connection), "meta-store", 838 cnc->priv->meta_store, NULL); 839 } 840 g_rec_mutex_unlock (&cnc->priv->rmutex); 841 break; 842 case PROP_IS_THREAD_WRAPPER: 843 g_warning ("This property should not be modified!"); 844 break; 845 case PROP_MONITOR_WRAPPED_IN_MAINLOOP: 846 if (cnc->priv->is_thread_wrapper) { 847 /* cancel any existing signal monitoring */ 848 if (cnc->priv->monitor_id > 0) { 849 g_source_remove (cnc->priv->monitor_id); 850 cnc->priv->monitor_id = 0; 851 } 852 if (g_value_get_boolean (value)) { 853 /* set up signal monitoring */ 854 ThreadConnectionData *cdata = NULL; 855 cdata = (ThreadConnectionData*) gda_connection_internal_get_provider_data (cnc); 856 if (cdata) { 857 cnc->priv->monitor_id = g_timeout_add_seconds (1, 858 (GSourceFunc) monitor_wrapped_cnc, 859 cdata->wrapper); 860 /* steal signals for current thread */ 861 gsize i; 862 for (i = 0; i < cdata->handlers_ids->len; i++) { 863 gulong id; 864 id = g_array_index (cdata->handlers_ids, gulong, i); 865 gda_thread_wrapper_steal_signal (cdata->wrapper, id); 866 } 867 } 868 } 869 } 870 break; 871 case PROP_EVENTS_HISTORY_SIZE: 872 gda_connection_lock ((GdaLockable*) cnc); 873 change_events_array_max_size (cnc, g_value_get_int (value)); 874 gda_connection_unlock ((GdaLockable*) cnc); 875 break; 876 case PROP_EXEC_TIMES: 877 cnc->priv->exec_times = g_value_get_boolean (value); 878 break; 879 case PROP_EXEC_SLOWDOWN: 880 cnc->priv->exec_slowdown = g_value_get_uint (value); 881 if (cnc->priv->is_thread_wrapper) { 882 ThreadConnectionData *cdata; 883 cdata = (ThreadConnectionData*) gda_connection_internal_get_provider_data (cnc); 884 if (cdata) 885 g_object_set (G_OBJECT (cdata->sub_connection), "execution-slowdown", 886 cnc->priv->exec_slowdown, NULL); 887 } 888 break; 889 } 890 } 891 } 892 893 static void 894 gda_connection_get_property (GObject *object, 895 guint param_id, 896 GValue *value, 897 GParamSpec *pspec) 898 { 899 GdaConnection *cnc; 900 901 cnc = GDA_CONNECTION (object); 902 if (cnc->priv) { 903 switch (param_id) { 904 case PROP_DSN: 905 g_value_set_string (value, cnc->priv->dsn); 906 break; 907 case PROP_CNC_STRING: 908 g_value_set_string (value, cnc->priv->cnc_string); 909 break; 910 case PROP_PROVIDER_OBJ: 911 g_value_set_object (value, (GObject*) cnc->priv->provider_obj); 912 break; 913 case PROP_AUTH_STRING: 914 g_value_set_string (value, cnc->priv->auth_string); 915 break; 916 case PROP_OPTIONS: 917 g_value_set_flags (value, cnc->priv->options); 918 break; 919 case PROP_META_STORE: 920 g_value_set_object (value, cnc->priv->meta_store); 921 break; 922 case PROP_IS_THREAD_WRAPPER: 923 g_value_set_boolean (value, cnc->priv->is_thread_wrapper); 924 break; 925 case PROP_MONITOR_WRAPPED_IN_MAINLOOP: 926 g_value_set_boolean (value, cnc->priv->is_thread_wrapper && (cnc->priv->monitor_id > 0) ? 927 TRUE : FALSE); 928 break; 929 case PROP_EVENTS_HISTORY_SIZE: 930 g_value_set_int (value, cnc->priv->events_array_size); 931 break; 932 case PROP_EXEC_TIMES: 933 g_value_set_boolean (value, cnc->priv->exec_times); 934 break; 935 case PROP_EXEC_SLOWDOWN: 936 g_value_set_uint (value, cnc->priv->exec_slowdown); 937 break; 938 default: 939 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); 940 break; 941 } 942 } 943 } 944 945 /* 946 * Returns: a new GType array, free using g_free(), or %NULL if none to compute 947 */ 948 static GType * 949 merge_column_types (const GType *struct_types, const GType *user_types) 950 { 951 if (! user_types || !struct_types) 952 return NULL; 953 GArray *array; 954 guint i; 955 array = g_array_new (TRUE, FALSE, sizeof (GType)); 956 for (i = 0; 957 (user_types [i] != G_TYPE_NONE) && (struct_types [i] != G_TYPE_NONE); 958 i++) { 959 GType type; 960 if (user_types [i] == 0) 961 type = struct_types [i]; 962 else 963 type = user_types [i]; 964 g_array_append_val (array, type); 965 } 966 if (user_types [i] != G_TYPE_NONE) { 967 for (; user_types [i] != G_TYPE_NONE; i++) { 968 GType type = user_types [i]; 969 g_array_append_val (array, type); 970 } 971 } 972 else { 973 for (; struct_types [i] != G_TYPE_NONE; i++) { 974 GType type = struct_types [i]; 975 g_array_append_val (array, type); 976 } 977 } 978 GType *retval; 979 guint len; 980 len = array->len; 981 retval = (GType*) g_array_free (array, FALSE); 982 retval [len] = G_TYPE_NONE; 983 return retval; 984 } 985 986 /* 987 * helper functions to manage CncTask 988 */ 989 static void task_stmt_reset_cb (GdaStatement *stmt, CncTask *task); 990 static CncTask * 991 cnc_task_new (guint id, GdaStatement *stmt, GdaStatementModelUsage model_usage, GType *col_types, 992 GdaSet *params, gboolean need_last_insert_row) 993 { 994 CncTask *task; 995 996 task = g_new0 (CncTask, 1); 997 task->being_processed = FALSE; 998 task->task_id = id; 999 task->stmt = g_object_ref (stmt); 1000 task->exec_timer = NULL; 1001 g_signal_connect (stmt, "reset", /* monitor statement changes */ 1002 G_CALLBACK (task_stmt_reset_cb), task); 1003 task->model_usage = model_usage; 1004 GType *req_types; 1005 req_types = merge_column_types (_gda_statement_get_requested_types (stmt), col_types); 1006 if (req_types) 1007 task->col_types = req_types; 1008 else { 1009 if (_gda_statement_get_requested_types (stmt)) 1010 col_types = (GType*) _gda_statement_get_requested_types (stmt); 1011 if (col_types) { 1012 gint i; 1013 for (i = 0; ; i++) { 1014 if (col_types [i] == G_TYPE_NONE) 1015 break; 1016 } 1017 i++; 1018 task->col_types = g_new (GType, i); 1019 memcpy (task->col_types, col_types, i * sizeof (GType)); /* Flawfinder: ignore */ 1020 } 1021 } 1022 if (params) 1023 task->params = gda_set_copy (params); 1024 task->need_last_insert_row = need_last_insert_row; 1025 1026 g_rec_mutex_init (&(task->rmutex)); 1027 1028 return task; 1029 } 1030 1031 static void 1032 task_stmt_reset_cb (G_GNUC_UNUSED GdaStatement *stmt, CncTask *task) 1033 { 1034 g_rec_mutex_lock (&(task->rmutex)); 1035 g_signal_handlers_disconnect_by_func (task->stmt, 1036 G_CALLBACK (task_stmt_reset_cb), task); 1037 g_object_unref (task->stmt); 1038 task->stmt = NULL; 1039 g_rec_mutex_unlock (&(task->rmutex)); 1040 } 1041 1042 static void 1043 cnc_task_free (CncTask *task) 1044 { 1045 g_rec_mutex_lock (&(task->rmutex)); 1046 if (task->stmt) { 1047 g_signal_handlers_disconnect_by_func (task->stmt, 1048 G_CALLBACK (task_stmt_reset_cb), task); 1049 g_object_unref (task->stmt); 1050 } 1051 if (task->params) 1052 g_object_unref (task->params); 1053 if (task->col_types) 1054 g_free (task->col_types); 1055 if (task->last_insert_row) 1056 g_object_unref (task->last_insert_row); 1057 if (task->result) 1058 g_object_unref (task->result); 1059 if (task->error) 1060 g_error_free (task->error); 1061 if (task->exec_timer) 1062 g_timer_destroy (task->exec_timer); 1063 1064 g_rec_mutex_unlock (&(task->rmutex)); 1065 g_rec_mutex_clear (&(task->rmutex)); 1066 g_free (task); 1067 } 1068 1069 /** 1070 * _gda_connection_get_internal_thread_provider: 1071 */ 1072 GdaServerProvider * 1073 _gda_connection_get_internal_thread_provider (void) 1074 { 1075 static GMutex mutex; 1076 1077 g_mutex_lock (&mutex); 1078 if (!_gda_thread_wrapper_provider) 1079 _gda_thread_wrapper_provider = GDA_SERVER_PROVIDER (g_object_new (GDA_TYPE_THREAD_PROVIDER, NULL)); 1080 g_mutex_unlock (&mutex); 1081 return _gda_thread_wrapper_provider; 1082 } 1083 1084 1085 /** 1086 * gda_connection_new_from_dsn: 1087 * @dsn: data source name. 1088 * @auth_string: (allow-none): authentication string, or %NULL 1089 * @options: options for the connection (see #GdaConnectionOptions). 1090 * @error: a place to store an error, or %NULL 1091 * 1092 * This function is similar to gda_connection_open_from_dsn(), except it does not actually open the 1093 * connection, you have to open it using gda_connection_open(). 1094 * 1095 * Returns: (transfer full): a new #GdaConnection if connection opening was successful or %NULL if there was an error. 1096 * 1097 * Since: 5.0.2 1098 */ 1099 GdaConnection * 1100 gda_connection_new_from_dsn (const gchar *dsn, const gchar *auth_string, 1101 GdaConnectionOptions options, GError **error) 1102 { 1103 GdaConnection *cnc = NULL; 1104 GdaDsnInfo *dsn_info; 1105 gchar *user, *pass, *real_dsn; 1106 gchar *real_auth_string = NULL; 1107 1108 g_return_val_if_fail (dsn && *dsn, NULL); 1109 1110 if (((options & GDA_CONNECTION_OPTIONS_THREAD_SAFE) || (options & GDA_CONNECTION_OPTIONS_THREAD_SAFE)) && 1111 !g_thread_supported ()) { 1112 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_UNSUPPORTED_THREADS_ERROR, 1113 "%s", _("Multi threading is not supported or enabled")); 1114 return NULL; 1115 } 1116 1117 gda_dsn_split (dsn, &real_dsn, &user, &pass); 1118 if (!real_dsn) { 1119 g_free (user); 1120 g_free (pass); 1121 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_DSN_NOT_FOUND_ERROR, 1122 _("Malformed data source specification '%s'"), dsn); 1123 return NULL; 1124 } 1125 1126 /* get the data source info */ 1127 dsn_info = gda_config_get_dsn_info (real_dsn); 1128 if (!dsn_info) { 1129 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_DSN_NOT_FOUND_ERROR, 1130 _("Data source %s not found in configuration"), real_dsn); 1131 g_free (real_dsn); 1132 g_free (user); 1133 g_free (pass); 1134 return NULL; 1135 } 1136 if (!auth_string && user) { 1137 gchar *s1; 1138 s1 = gda_rfc1738_encode (user); 1139 if (pass) { 1140 gchar *s2; 1141 s2 = gda_rfc1738_encode (pass); 1142 real_auth_string = g_strdup_printf ("USERNAME=%s;PASSWORD=%s", s1, s2); 1143 g_free (s2); 1144 } 1145 else 1146 real_auth_string = g_strdup_printf ("USERNAME=%s", s1); 1147 g_free (s1); 1148 } 1149 1150 /* try to find provider */ 1151 if (dsn_info->provider != NULL) { 1152 GdaProviderInfo *pinfo; 1153 GdaServerProvider *prov = NULL; 1154 1155 pinfo = gda_config_get_provider_info (dsn_info->provider); 1156 if (pinfo) { 1157 prov = gda_config_get_provider (dsn_info->provider, error); 1158 if (((options & GDA_CONNECTION_OPTIONS_THREAD_SAFE) && 1159 !gda_server_provider_supports_feature (prov, NULL, 1160 GDA_CONNECTION_FEATURE_MULTI_THREADING)) || 1161 (options & GDA_CONNECTION_OPTIONS_THREAD_ISOLATED)) { 1162 options |= GDA_CONNECTION_OPTIONS_THREAD_ISOLATED; 1163 prov = _gda_connection_get_internal_thread_provider (); 1164 } 1165 } 1166 else 1167 g_set_error (error, GDA_CONFIG_ERROR, GDA_CONFIG_PROVIDER_NOT_FOUND_ERROR, 1168 _("No provider '%s' installed"), dsn_info->provider); 1169 1170 if (prov) { 1171 if (PROV_CLASS (prov)->create_connection) { 1172 cnc = PROV_CLASS (prov)->create_connection (prov); 1173 if (cnc) 1174 g_object_set (G_OBJECT (cnc), 1175 "provider", prov, 1176 "dsn", real_dsn, 1177 "auth-string", auth_string ? auth_string : real_auth_string, 1178 "options", options, NULL); 1179 } 1180 else 1181 cnc = g_object_new (GDA_TYPE_CONNECTION, 1182 "provider", prov, 1183 "dsn", real_dsn, 1184 "auth-string", auth_string ? auth_string : real_auth_string, 1185 "options", options, NULL); 1186 } 1187 } 1188 else 1189 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_PROVIDER_NOT_FOUND_ERROR, 1190 "%s", _("Datasource configuration error: no provider specified")); 1191 1192 g_free (real_auth_string); 1193 g_free (real_dsn); 1194 g_free (user); 1195 g_free (pass); 1196 return cnc; 1197 } 1198 1199 /** 1200 * gda_connection_open_from_dsn: 1201 * @dsn: data source name. 1202 * @auth_string: (allow-none): authentication string, or %NULL 1203 * @options: options for the connection (see #GdaConnectionOptions). 1204 * @error: a place to store an error, or %NULL 1205 * 1206 * This function is the way of opening database connections with libgda, using a pre-defined data source (DSN), 1207 * see gda_config_define_dsn() for more information about how to define a DSN. If you don't want to define 1208 * a DSN, it is possible to use gda_connection_open_from_string() instead of this method. 1209 * 1210 * The @dsn string must have the following format: "[<username>[:<password>]@]<DSN>" 1211 * (if <username> and/or <password> are provided, and @auth_string is %NULL, then these username 1212 * and passwords will be used). Note that if provided, <username> and <password> 1213 * must be encoded as per RFC 1738, see gda_rfc1738_encode() for more information. 1214 * 1215 * The @auth_string can contain the authentication information for the server 1216 * to accept the connection. It is a string containing semi-colon seperated named value, usually 1217 * like "USERNAME=...;PASSWORD=..." where the ... are replaced by actual values. Note that each 1218 * name and value must be encoded as per RFC 1738, see gda_rfc1738_encode() for more information. 1219 * 1220 * The actual named parameters required depend on the provider being used, and that list is available 1221 * as the <parameter>auth_params</parameter> member of the #GdaProviderInfo structure for each installed 1222 * provider (use gda_config_get_provider_info() to get it). Also one can use the "gda-sql-5.0 -L" command to 1223 * list the possible named parameters. 1224 * 1225 * This method may fail with a GDA_CONNECTION_ERROR domain error (see the #GdaConnectionError error codes) 1226 * or a %GDA_CONFIG_ERROR domain error (see the #GdaConfigError error codes). 1227 * 1228 * Returns: (transfer full): a new #GdaConnection if connection opening was successful or %NULL if there was an error. 1229 */ 1230 GdaConnection * 1231 gda_connection_open_from_dsn (const gchar *dsn, const gchar *auth_string, 1232 GdaConnectionOptions options, GError **error) 1233 { 1234 GdaConnection *cnc; 1235 cnc = gda_connection_new_from_dsn (dsn, auth_string, options, error); 1236 if (cnc && !gda_connection_open (cnc, error)) { 1237 g_object_unref (cnc); 1238 cnc = NULL; 1239 } 1240 return cnc; 1241 } 1242 1243 1244 /** 1245 * gda_connection_new_from_string: 1246 * @provider_name: (allow-none): provider ID to connect to, or %NULL 1247 * @cnc_string: connection string. 1248 * @auth_string: (allow-none): authentication string, or %NULL 1249 * @options: options for the connection (see #GdaConnectionOptions). 1250 * @error: a place to store an error, or %NULL 1251 * 1252 * This function is similar to gda_connection_open_from_string(), except it does not actually open the 1253 * connection, you have to open it using gda_connection_open(). 1254 * 1255 * Returns: (transfer full): a new #GdaConnection if connection opening was successful or %NULL if there was an error. 1256 * 1257 * Since: 5.0.2 1258 */ 1259 GdaConnection * 1260 gda_connection_new_from_string (const gchar *provider_name, const gchar *cnc_string, const gchar *auth_string, 1261 GdaConnectionOptions options, GError **error) 1262 { 1263 GdaConnection *cnc = NULL; 1264 gchar *user, *pass, *real_cnc, *real_provider; 1265 gchar *real_auth_string = NULL; 1266 1267 g_return_val_if_fail (cnc_string && *cnc_string, NULL); 1268 1269 if (options & GDA_CONNECTION_OPTIONS_THREAD_SAFE && 1270 !g_thread_supported ()) { 1271 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_UNSUPPORTED_THREADS_ERROR, 1272 "%s", _("Multi threading is not supported or enabled")); 1273 return NULL; 1274 } 1275 1276 gda_connection_string_split (cnc_string, &real_cnc, &real_provider, &user, &pass); 1277 if (!real_cnc) { 1278 g_free (user); 1279 g_free (pass); 1280 g_free (real_provider); 1281 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_DSN_NOT_FOUND_ERROR, 1282 _("Malformed connection string '%s'"), cnc_string); 1283 return NULL; 1284 } 1285 1286 if (!provider_name && !real_provider) { 1287 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_PROVIDER_NOT_FOUND_ERROR, 1288 "%s", _("No database driver specified")); 1289 g_free (user); 1290 g_free (pass); 1291 g_free (real_cnc); 1292 return NULL; 1293 } 1294 1295 if (!auth_string && user) { 1296 gchar *s1; 1297 s1 = gda_rfc1738_encode (user); 1298 if (pass) { 1299 gchar *s2; 1300 s2 = gda_rfc1738_encode (pass); 1301 real_auth_string = g_strdup_printf ("USERNAME=%s;PASSWORD=%s", s1, s2); 1302 g_free (s2); 1303 } 1304 else 1305 real_auth_string = g_strdup_printf ("USERNAME=%s", s1); 1306 g_free (s1); 1307 } 1308 1309 /* try to find provider */ 1310 if (provider_name || real_provider) { 1311 GdaProviderInfo *pinfo; 1312 GdaServerProvider *prov = NULL; 1313 1314 pinfo = gda_config_get_provider_info (provider_name ? provider_name : real_provider); 1315 if (pinfo) { 1316 prov = gda_config_get_provider (provider_name ? provider_name : real_provider, error); 1317 if (((options & GDA_CONNECTION_OPTIONS_THREAD_SAFE) && 1318 !gda_server_provider_supports_feature (prov, NULL, 1319 GDA_CONNECTION_FEATURE_MULTI_THREADING)) || 1320 (options & GDA_CONNECTION_OPTIONS_THREAD_ISOLATED)) { 1321 gchar *tmp; 1322 tmp = g_strdup_printf ("%s;PROVIDER_NAME=%s", real_cnc, pinfo->id); 1323 g_free (real_cnc); 1324 real_cnc = tmp; 1325 options |= GDA_CONNECTION_OPTIONS_THREAD_ISOLATED; 1326 prov = _gda_connection_get_internal_thread_provider (); 1327 } 1328 } 1329 else 1330 g_set_error (error, GDA_CONFIG_ERROR, GDA_CONFIG_PROVIDER_NOT_FOUND_ERROR, 1331 _("No provider '%s' installed"), provider_name ? provider_name : real_provider); 1332 1333 if (prov) { 1334 if (PROV_CLASS (prov)->create_connection) { 1335 cnc = PROV_CLASS (prov)->create_connection (prov); 1336 if (cnc) 1337 g_object_set (G_OBJECT (cnc), 1338 "provider", prov, 1339 "cnc-string", real_cnc, 1340 "auth-string", auth_string ? auth_string : real_auth_string, 1341 "options", options, NULL); 1342 } 1343 else 1344 cnc = (GdaConnection *) g_object_new (GDA_TYPE_CONNECTION, 1345 "provider", prov, 1346 "cnc-string", real_cnc, 1347 "auth-string", auth_string ? auth_string : real_auth_string, 1348 "options", options, NULL); 1349 } 1350 } 1351 1352 g_free (real_auth_string); 1353 g_free (real_cnc); 1354 g_free (user); 1355 g_free (pass); 1356 g_free (real_provider); 1357 1358 return cnc; 1359 } 1360 1361 /** 1362 * gda_connection_open_from_string: 1363 * @provider_name: (allow-none): provider ID to connect to, or %NULL 1364 * @cnc_string: connection string. 1365 * @auth_string: (allow-none): authentication string, or %NULL 1366 * @options: options for the connection (see #GdaConnectionOptions). 1367 * @error: a place to store an error, or %NULL 1368 * 1369 * Opens a connection given a provider ID and a connection string. This 1370 * allows applications to open connections without having to create 1371 * a data source (DSN) in the configuration. The format of @cnc_string is 1372 * similar to PostgreSQL and MySQL connection strings. It is a semicolumn-separated 1373 * series of <key>=<value> pairs, where each key and value are encoded as per RFC 1738, 1374 * see gda_rfc1738_encode() for more information. 1375 * 1376 * The possible keys depend on the provider, the "gda-sql-5.0 -L" command 1377 * can be used to list the actual keys for each installed database provider. 1378 * 1379 * For example the connection string to open an SQLite connection to a database 1380 * file named "my_data.db" in the current directory would be <constant>"DB_DIR=.;DB_NAME=my_data"</constant>. 1381 * 1382 * The @cnc_string string must have the following format: 1383 * "[<provider>://][<username>[:<password>]@]<connection_params>" 1384 * (if <username> and/or <password> are provided, and @auth_string is %NULL, then these username 1385 * and passwords will be used, and if <provider> is provided and @provider_name is %NULL then this 1386 * provider will be used). Note that if provided, <username>, <password> and <provider> 1387 * must be encoded as per RFC 1738, see gda_rfc1738_encode() for more information. 1388 * 1389 * The @auth_string must contain the authentication information for the server 1390 * to accept the connection. It is a string containing semi-colon seperated named values, usually 1391 * like "USERNAME=...;PASSWORD=..." where the ... are replaced by actual values. Note that each 1392 * name and value must be encoded as per RFC 1738, see gda_rfc1738_encode() for more information. 1393 * 1394 * The actual named parameters required depend on the provider being used, and that list is available 1395 * as the <parameter>auth_params</parameter> member of the #GdaProviderInfo structure for each installed 1396 * provider (use gda_config_get_provider_info() to get it). Similarly to the format of the connection 1397 * string, use the "gda-sql-5.0 -L" command to list the possible named parameters. 1398 * 1399 * Additionally, it is possible to have the connection string 1400 * respect the "<provider_name>://<real cnc string>" format, in which case the provider name 1401 * and the real connection string will be extracted from that string (note that if @provider_name 1402 * is not %NULL then it will still be used as the provider ID).\ 1403 * 1404 * This method may fail with a GDA_CONNECTION_ERROR domain error (see the #GdaConnectionError error codes) 1405 * or a %GDA_CONFIG_ERROR domain error (see the #GdaConfigError error codes). 1406 * 1407 * Returns: (transfer full): a new #GdaConnection if connection opening was successful or %NULL if there was an error. 1408 */ 1409 GdaConnection * 1410 gda_connection_open_from_string (const gchar *provider_name, const gchar *cnc_string, const gchar *auth_string, 1411 GdaConnectionOptions options, GError **error) 1412 { 1413 GdaConnection *cnc; 1414 cnc = gda_connection_new_from_string (provider_name, cnc_string, auth_string, options, error); 1415 if (cnc && !gda_connection_open (cnc, error)) { 1416 g_object_unref (cnc); 1417 cnc = NULL; 1418 } 1419 return cnc; 1420 } 1421 1422 1423 /* 1424 * Uses _gda_config_sqlite_provider to open a connection 1425 */ 1426 GdaConnection * 1427 _gda_open_internal_sqlite_connection (const gchar *cnc_string) 1428 { 1429 GdaConnection *cnc; 1430 GdaServerProvider *prov = _gda_config_sqlite_provider; 1431 gchar *user, *pass, *real_cnc, *real_provider; 1432 1433 /*g_print ("%s(%s)\n", __FUNCTION__, cnc_string);*/ 1434 gda_connection_string_split (cnc_string, &real_cnc, &real_provider, &user, &pass); 1435 if (!real_cnc) { 1436 g_free (user); 1437 g_free (pass); 1438 g_free (real_provider); 1439 return NULL; 1440 } 1441 if (PROV_CLASS (prov)->create_connection) { 1442 cnc = PROV_CLASS (prov)->create_connection (prov); 1443 if (cnc) 1444 g_object_set (G_OBJECT (cnc), 1445 "provider", prov, 1446 "cnc-string", real_cnc, 1447 NULL); 1448 } 1449 else 1450 cnc = (GdaConnection *) g_object_new (GDA_TYPE_CONNECTION, 1451 "provider", prov, 1452 "cnc-string", real_cnc, 1453 NULL); 1454 1455 g_free (real_cnc); 1456 g_free (user); 1457 g_free (pass); 1458 g_free (real_provider); 1459 1460 /* open the connection */ 1461 if (!gda_connection_open (cnc, NULL)) { 1462 g_object_unref (cnc); 1463 cnc = NULL; 1464 } 1465 return cnc; 1466 } 1467 1468 static void 1469 sqlite_connection_closed_cb (GdaConnection *cnc, G_GNUC_UNUSED gpointer data) 1470 { 1471 gchar *filename; 1472 filename = g_object_get_data (G_OBJECT (cnc), "__gda_fname"); 1473 g_assert (filename && *filename); 1474 g_unlink (filename); 1475 } 1476 1477 /** 1478 * gda_connection_open_sqlite: 1479 * @directory: (allow-none): the directory the database file will be in, or %NULL for the default TMP directory 1480 * @filename: the database file name 1481 * @auto_unlink: if %TRUE, then the database file will be removed afterwards 1482 * 1483 * Opens an SQLite connection even if the SQLite provider is not installed, 1484 * to be used by database providers which need a temporary database to store 1485 * some information. 1486 * 1487 * Returns: (transfer full): a new #GdaConnection, or %NULL if an error occurred 1488 */ 1489 GdaConnection * 1490 gda_connection_open_sqlite (const gchar *directory, const gchar *filename, gboolean auto_unlink) 1491 { 1492 GdaConnection *cnc; 1493 gchar *fname; 1494 gint fd; 1495 1496 if (!directory) 1497 directory = g_get_tmp_dir(); /* Flawfinder: ignore */ 1498 else 1499 g_return_val_if_fail (*directory, NULL); 1500 g_return_val_if_fail (filename && *filename, NULL); 1501 1502 fname = g_build_filename (directory, filename, NULL); 1503 #ifdef G_OS_WIN32 1504 fd = g_open (fname, O_WRONLY | O_CREAT | O_TRUNC, 1505 S_IRUSR | S_IWUSR); 1506 #else 1507 fd = g_open (fname, O_WRONLY | O_CREAT | O_NOCTTY | O_TRUNC, 1508 S_IRUSR | S_IWUSR); 1509 #endif 1510 if (fd == -1) { 1511 g_free (fname); 1512 return NULL; 1513 } 1514 close (fd); 1515 1516 gchar *tmp1, *tmp2, *cncstring; 1517 tmp1 = gda_rfc1738_encode (directory); 1518 tmp2 = gda_rfc1738_encode (filename); 1519 cncstring = g_strdup_printf ("SQLite://DB_DIR=%s;DB_NAME=%s", tmp1, tmp2); 1520 g_free (tmp1); 1521 g_free (tmp2); 1522 1523 cnc = _gda_open_internal_sqlite_connection (cncstring); 1524 g_free (cncstring); 1525 1526 if (auto_unlink) { 1527 g_object_set_data_full (G_OBJECT (cnc), "__gda_fname", fname, g_free); 1528 g_signal_connect (cnc, "conn-closed", 1529 G_CALLBACK (sqlite_connection_closed_cb), NULL); 1530 } 1531 else 1532 g_free (fname); 1533 return cnc; 1534 } 1535 1536 /** 1537 * gda_connection_open: 1538 * @cnc: a #GdaConnection object 1539 * @error: a place to store errors, or %NULL 1540 * 1541 * Tries to open the connection. 1542 * 1543 * Returns: TRUE if the connection is opened, and FALSE otherwise. 1544 */ 1545 gboolean 1546 gda_connection_open (GdaConnection *cnc, GError **error) 1547 { 1548 GdaDsnInfo *dsn_info = NULL; 1549 GdaQuarkList *params, *auth; 1550 char *real_auth_string = NULL; 1551 1552 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 1553 1554 /* don't do anything if connection is already opened */ 1555 if (cnc->priv->provider_data) 1556 return TRUE; 1557 1558 gda_connection_lock ((GdaLockable*) cnc); 1559 1560 /* connection string */ 1561 if (cnc->priv->dsn) { 1562 /* get the data source info */ 1563 dsn_info = gda_config_get_dsn_info (cnc->priv->dsn); 1564 if (!dsn_info) { 1565 gda_log_error (_("Data source %s not found in configuration"), cnc->priv->dsn); 1566 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_DSN_NOT_FOUND_ERROR, 1567 _("Data source %s not found in configuration"), cnc->priv->dsn); 1568 gda_connection_unlock ((GdaLockable*) cnc); 1569 return FALSE; 1570 } 1571 1572 g_free (cnc->priv->cnc_string); 1573 cnc->priv->cnc_string = g_strdup (dsn_info->cnc_string); 1574 } 1575 else { 1576 if (!cnc->priv->cnc_string) { 1577 gda_log_error (_("No DSN or connection string specified")); 1578 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_NO_CNC_SPEC_ERROR, 1579 "%s", _("No DSN or connection string specified")); 1580 gda_connection_unlock ((GdaLockable*) cnc); 1581 return FALSE; 1582 } 1583 /* try to see if connection string has the <provider>://<rest of the string> format */ 1584 } 1585 1586 /* provider test */ 1587 if (!cnc->priv->provider_obj) { 1588 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_NO_PROVIDER_SPEC_ERROR, 1589 "%s", _("No provider specified")); 1590 gda_connection_unlock ((GdaLockable*) cnc); 1591 return FALSE; 1592 } 1593 1594 /* if there is a limiting thread but it's not yet set, then initialize it to the current 1595 * thread */ 1596 if (PROV_CLASS (cnc->priv->provider_obj)->limiting_thread == 1597 GDA_SERVER_PROVIDER_UNDEFINED_LIMITING_THREAD) 1598 PROV_CLASS (cnc->priv->provider_obj)->limiting_thread = g_thread_self (); 1599 1600 if (PROV_CLASS (cnc->priv->provider_obj)->limiting_thread && 1601 (PROV_CLASS (cnc->priv->provider_obj)->limiting_thread != g_thread_self ())) { 1602 /* WARNING: 1603 * Prior to GLib 2.32, this code used to check if the 1604 * PROV_CLASS (cnc->priv->provider_obj)->limiting_thread 1605 * was still active (i.e. not finished) and if so, the 1606 * PROV_CLASS (cnc->priv->provider_obj)->limiting_thread would 1607 * become g_thread_self(). 1608 * 1609 * Now, if PROV_CLASS (cnc->priv->provider_obj)->limiting_thread is set and 1610 * if it's not equal to g_thread_self() then an error is returned. 1611 */ 1612 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_PROVIDER_ERROR, 1613 "%s", _("Provider does not allow usage from this thread")); 1614 gda_connection_unlock ((GdaLockable*) cnc); 1615 return FALSE; 1616 } 1617 1618 if (!PROV_CLASS (cnc->priv->provider_obj)->open_connection) { 1619 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_PROVIDER_ERROR, 1620 "%s", _("Internal error: provider does not implement the open_connection() virtual method")); 1621 gda_connection_unlock ((GdaLockable*) cnc); 1622 return FALSE; 1623 } 1624 1625 params = gda_quark_list_new_from_string (cnc->priv->cnc_string); 1626 1627 /* retrieve correct auth_string */ 1628 if (cnc->priv->auth_string) 1629 real_auth_string = g_strdup (cnc->priv->auth_string); 1630 else { 1631 if (dsn_info && dsn_info->auth_string) 1632 real_auth_string = g_strdup (dsn_info->auth_string); 1633 else 1634 /* look for authentication parameters in cnc string */ 1635 real_auth_string = g_strdup (cnc->priv->cnc_string); 1636 } 1637 1638 /* try to open the connection */ 1639 auth = gda_quark_list_new_from_string (real_auth_string); 1640 gboolean opened; 1641 1642 opened = PROV_CLASS (cnc->priv->provider_obj)->open_connection (cnc->priv->provider_obj, cnc, params, auth, 1643 NULL, NULL, NULL); 1644 gda_quark_list_protect_values (params); 1645 gda_quark_list_protect_values (auth); 1646 1647 if (opened && !cnc->priv->provider_data) { 1648 g_warning ("Internal error: connection reported as opened, yet no provider data set"); 1649 opened = FALSE; 1650 } 1651 1652 if (!opened) { 1653 const GList *events; 1654 1655 events = gda_connection_get_events (cnc); 1656 if (events) { 1657 GList *l; 1658 1659 for (l = g_list_last ((GList*) events); l; l = l->prev) { 1660 GdaConnectionEvent *event; 1661 1662 event = GDA_CONNECTION_EVENT (l->data); 1663 if (gda_connection_event_get_event_type (event) == GDA_CONNECTION_EVENT_ERROR) { 1664 if (error && !(*error)) 1665 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_OPEN_ERROR, 1666 "%s", gda_connection_event_get_description (event)); 1667 } 1668 } 1669 } 1670 } 1671 1672 /* free memory */ 1673 gda_quark_list_free (params); 1674 gda_quark_list_free (auth); 1675 g_free (real_auth_string); 1676 1677 if (cnc->priv->provider_data) { 1678 #ifdef GDA_DEBUG_signal 1679 g_print (">> 'CONN_OPENED' from %s\n", __FUNCTION__); 1680 #endif 1681 g_signal_emit (G_OBJECT (cnc), gda_connection_signals[CONN_OPENED], 0); 1682 #ifdef GDA_DEBUG_signal 1683 g_print ("<< 'CONN_OPENED' from %s\n", __FUNCTION__); 1684 #endif 1685 } 1686 1687 /* limit connection's usable thread */ 1688 if (PROV_CLASS (cnc->priv->provider_obj)->limiting_thread) 1689 g_object_set (G_OBJECT (cnc), "thread-owner", 1690 PROV_CLASS (cnc->priv->provider_obj)->limiting_thread, NULL); 1691 1692 1693 gda_connection_unlock ((GdaLockable*) cnc); 1694 return cnc->priv->provider_data ? TRUE : FALSE; 1695 } 1696 1697 1698 /** 1699 * gda_connection_close: 1700 * @cnc: a #GdaConnection object. 1701 * 1702 * Closes the connection to the underlying data source, but first emits the 1703 * "conn-to-close" signal. 1704 */ 1705 void 1706 gda_connection_close (GdaConnection *cnc) 1707 { 1708 g_return_if_fail (GDA_IS_CONNECTION (cnc)); 1709 1710 if (! cnc->priv->provider_data) 1711 return; 1712 1713 gda_connection_lock ((GdaLockable*) cnc); 1714 #ifdef GDA_DEBUG_signal 1715 g_print (">> 'CONN_TO_CLOSE' from %s\n", __FUNCTION__); 1716 #endif 1717 g_signal_emit (G_OBJECT (cnc), gda_connection_signals[CONN_TO_CLOSE], 0); 1718 #ifdef GDA_DEBUG_signal 1719 g_print ("<< 'CONN_TO_CLOSE' from %s\n", __FUNCTION__); 1720 #endif 1721 1722 gda_connection_close_no_warning (cnc); 1723 gda_connection_unlock ((GdaLockable*) cnc); 1724 } 1725 1726 static void 1727 add_connection_event_from_error (GdaConnection *cnc, GError **error) 1728 { 1729 GdaConnectionEvent *event; 1730 gchar *str; 1731 event = GDA_CONNECTION_EVENT (g_object_new (GDA_TYPE_CONNECTION_EVENT, 1732 "type", (int)GDA_CONNECTION_EVENT_WARNING, NULL)); 1733 str = g_strdup_printf (_("Error while maintaining the meta data up to date: %s"), 1734 error && *error && (*error)->message ? (*error)->message : _("No detail")); 1735 gda_connection_event_set_description (event, str); 1736 g_free (str); 1737 if (error) 1738 g_clear_error (error); 1739 gda_connection_add_event (cnc, event); 1740 } 1741 1742 /** 1743 * gda_connection_close_no_warning: 1744 * @cnc: a #GdaConnection object. 1745 * 1746 * Closes the connection to the underlying data source, without emiting any warning signal. 1747 */ 1748 void 1749 gda_connection_close_no_warning (GdaConnection *cnc) 1750 { 1751 g_return_if_fail (GDA_IS_CONNECTION (cnc)); 1752 1753 g_object_ref (cnc); 1754 gda_connection_lock ((GdaLockable*) cnc); 1755 1756 if (cnc->priv->monitor_id > 0) { 1757 g_source_remove (cnc->priv->monitor_id); 1758 cnc->priv->monitor_id = 0; 1759 } 1760 1761 if (! cnc->priv->provider_data) { 1762 g_object_unref (cnc); 1763 gda_connection_unlock ((GdaLockable*) cnc); 1764 return; 1765 } 1766 1767 if (cnc->priv->meta_store && 1768 cnc->priv->trans_meta_context && 1769 gda_connection_get_transaction_status (cnc)) { 1770 GdaConnection *mscnc; 1771 mscnc = gda_meta_store_get_internal_connection (cnc->priv->meta_store); 1772 if (cnc != mscnc) { 1773 gsize i; 1774 for (i = 0; i < cnc->priv->trans_meta_context->len; i++) { 1775 GdaMetaContext *context; 1776 GError *lerror = NULL; 1777 context = g_array_index (cnc->priv->trans_meta_context, GdaMetaContext*, i); 1778 if (! gda_connection_update_meta_store (cnc, context, &lerror)) 1779 add_connection_event_from_error (cnc, &lerror); 1780 auto_update_meta_context_free (context); 1781 } 1782 g_array_free (cnc->priv->trans_meta_context, TRUE); 1783 cnc->priv->trans_meta_context = NULL; 1784 } 1785 } 1786 1787 /* get rid of prepared statements to avoid problems */ 1788 if (cnc->priv->prepared_stmts) { 1789 g_hash_table_foreach (cnc->priv->prepared_stmts, 1790 (GHFunc) prepared_stms_foreach_func, cnc); 1791 g_hash_table_destroy (cnc->priv->prepared_stmts); 1792 cnc->priv->prepared_stmts = NULL; 1793 } 1794 1795 /* really close connection */ 1796 if (PROV_CLASS (cnc->priv->provider_obj)->close_connection) 1797 PROV_CLASS (cnc->priv->provider_obj)->close_connection (cnc->priv->provider_obj, 1798 cnc); 1799 if (cnc->priv->provider_data) { 1800 if (cnc->priv->provider_data_destroy_func) 1801 cnc->priv->provider_data_destroy_func (cnc->priv->provider_data); 1802 else if (cnc->priv->provider_data != cnc->priv->th_data) 1803 g_warning ("Provider did not clean its connection data"); 1804 cnc->priv->provider_data = NULL; 1805 } 1806 1807 gda_connection_unlock ((GdaLockable*) cnc); 1808 #ifdef GDA_DEBUG_signal 1809 g_print (">> 'CONN_CLOSED' from %s\n", __FUNCTION__); 1810 #endif 1811 g_signal_emit (G_OBJECT (cnc), gda_connection_signals[CONN_CLOSED], 0); 1812 #ifdef GDA_DEBUG_signal 1813 g_print ("<< 'CONN_CLOSED' from %s\n", __FUNCTION__); 1814 #endif 1815 g_object_unref (cnc); 1816 } 1817 1818 1819 /** 1820 * gda_connection_is_opened: 1821 * @cnc: a #GdaConnection object. 1822 * 1823 * Checks whether a connection is open or not. 1824 * 1825 * Returns: %TRUE if the connection is open, %FALSE if it's not. 1826 */ 1827 gboolean 1828 gda_connection_is_opened (GdaConnection *cnc) 1829 { 1830 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 1831 1832 return cnc->priv->provider_data ? TRUE : FALSE; 1833 } 1834 1835 1836 /** 1837 * gda_connection_get_options: 1838 * @cnc: a #GdaConnection object. 1839 * 1840 * Gets the #GdaConnectionOptions used to open this connection. 1841 * 1842 * Returns: the connection options. 1843 */ 1844 GdaConnectionOptions 1845 gda_connection_get_options (GdaConnection *cnc) 1846 { 1847 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), -1); 1848 1849 return cnc->priv->options; 1850 } 1851 1852 /** 1853 * gda_connection_get_provider: 1854 * @cnc: a #GdaConnection object 1855 * 1856 * Gets a pointer to the #GdaServerProvider object used to access the database 1857 * 1858 * Returns: (transfer none): the #GdaServerProvider (NEVER NULL) 1859 */ 1860 GdaServerProvider * 1861 gda_connection_get_provider (GdaConnection *cnc) 1862 { 1863 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 1864 1865 return cnc->priv->provider_obj; 1866 } 1867 1868 /** 1869 * gda_connection_get_provider_name: 1870 * @cnc: a #GdaConnection object 1871 * 1872 * Gets the name (identifier) of the database provider used by @cnc 1873 * 1874 * Returns: a non modifiable string 1875 */ 1876 const gchar * 1877 gda_connection_get_provider_name (GdaConnection *cnc) 1878 { 1879 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 1880 if (!cnc->priv->provider_obj) 1881 return NULL; 1882 1883 return gda_server_provider_get_name (cnc->priv->provider_obj); 1884 } 1885 1886 /** 1887 * gda_connection_get_dsn: 1888 * @cnc: a #GdaConnection object 1889 * 1890 * Returns: the data source name the connection object is connected 1891 * to. 1892 */ 1893 const gchar * 1894 gda_connection_get_dsn (GdaConnection *cnc) 1895 { 1896 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 1897 1898 return (const gchar *) cnc->priv->dsn; 1899 } 1900 1901 /** 1902 * gda_connection_get_cnc_string: 1903 * @cnc: a #GdaConnection object. 1904 * 1905 * Gets the connection string used to open this connection. 1906 * 1907 * The connection string is the string sent over to the underlying 1908 * database provider, which describes the parameters to be used 1909 * to open a connection on the underlying data source. 1910 * 1911 * Returns: the connection string used when opening the connection. 1912 */ 1913 const gchar * 1914 gda_connection_get_cnc_string (GdaConnection *cnc) 1915 { 1916 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 1917 1918 return (const gchar *) cnc->priv->cnc_string; 1919 } 1920 1921 /** 1922 * gda_connection_get_authentication: 1923 * @cnc: a #GdaConnection object. 1924 * 1925 * Gets the user name used to open this connection. 1926 * 1927 * Returns: the user name. 1928 */ 1929 const gchar * 1930 gda_connection_get_authentication (GdaConnection *cnc) 1931 { 1932 const gchar *str; 1933 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 1934 1935 str = (const gchar *) cnc->priv->auth_string; 1936 if (!str) 1937 str = ""; 1938 return str; 1939 } 1940 1941 /** 1942 * gda_connection_get_date_format: 1943 * @cnc: a #GdaConnection object 1944 * @out_first: (out) (allow-none): the place to store the first part of the date, or %NULL 1945 * @out_second: (out) (allow-none): the place to store the second part of the date, or %NULL 1946 * @out_third: (out) (allow-none): the place to store the third part of the date, or %NULL 1947 * @out_sep: (out) (allow-none): the place to store the separator (used between year, month and day parts) part of the date, or %NULL 1948 * @error: (allow-none): a place to store errors, or %NULL 1949 * 1950 * This function allows you to determine the actual format for the date values. 1951 * 1952 * Returns: %TRUE if no error occurred 1953 * 1954 * Since: 5.2 1955 */ 1956 gboolean 1957 gda_connection_get_date_format (GdaConnection *cnc, GDateDMY *out_first, 1958 GDateDMY *out_second, GDateDMY *out_third, gchar *out_sep, 1959 GError **error) 1960 { 1961 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 1962 1963 GdaDataHandler *dh; 1964 dh = gda_server_provider_get_data_handler_g_type (cnc->priv->provider_obj, cnc, G_TYPE_DATE); 1965 if (!dh) { 1966 g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_METHOD_NON_IMPLEMENTED_ERROR, 1967 "%s", _("Provider does not provide a GdaDataHandler for dates")); 1968 return FALSE; 1969 } 1970 1971 GDate *tdate; 1972 tdate = g_date_new_dmy (15, 12, 2003); 1973 g_assert (tdate && g_date_valid (tdate)); 1974 1975 GValue *value; 1976 value = gda_value_new (G_TYPE_DATE); 1977 g_value_set_boxed (value, tdate); 1978 g_date_free (tdate); 1979 1980 gchar *str; 1981 str = gda_data_handler_get_str_from_value (dh, value); 1982 gda_value_free (value); 1983 1984 /* parsing */ 1985 guint nb; 1986 gchar *ptr; 1987 GDateDMY order[3]; 1988 gchar sep; 1989 1990 /* 1st part */ 1991 for (nb = 0, ptr = str; *ptr; ptr++) { 1992 if ((*ptr <= '9') && (*ptr >= '0')) 1993 nb = nb * 10 + (*ptr - '0'); 1994 else 1995 break; 1996 } 1997 if (nb == 2003) 1998 order[0] = G_DATE_YEAR; 1999 else if (nb == 12) 2000 order[0] = G_DATE_MONTH; 2001 else if (nb == 15) 2002 order[0] = G_DATE_DAY; 2003 else { 2004 g_free (str); 2005 return FALSE; 2006 } 2007 2008 /* separator */ 2009 sep = *ptr; 2010 if (!sep) { 2011 g_free (str); 2012 return FALSE; 2013 } 2014 2015 /* 2nd part */ 2016 for (nb = 0, ptr++; *ptr; ptr++) { 2017 if ((*ptr <= '9') && (*ptr >= '0')) 2018 nb = nb * 10 + (*ptr - '0'); 2019 else 2020 break; 2021 } 2022 if (nb == 2003) 2023 order[1] = G_DATE_YEAR; 2024 else if (nb == 12) 2025 order[1] = G_DATE_MONTH; 2026 else if (nb == 15) 2027 order[1] = G_DATE_DAY; 2028 else { 2029 g_free (str); 2030 return FALSE; 2031 } 2032 2033 if (sep != *ptr) { 2034 g_free (str); 2035 return FALSE; 2036 } 2037 2038 /* 3rd part */ 2039 for (nb = 0, ptr++; *ptr; ptr++) { 2040 if ((*ptr <= '9') && (*ptr >= '0')) 2041 nb = nb * 10 + (*ptr - '0'); 2042 else 2043 break; 2044 } 2045 if (nb == 2003) 2046 order[2] = G_DATE_YEAR; 2047 else if (nb == 12) 2048 order[2] = G_DATE_MONTH; 2049 else if (nb == 15) 2050 order[2] = G_DATE_DAY; 2051 else { 2052 g_free (str); 2053 return FALSE; 2054 } 2055 g_free (str); 2056 2057 /* result */ 2058 if (out_first) 2059 *out_first = order [0]; 2060 if (out_second) 2061 *out_second = order [1]; 2062 if (out_third) 2063 *out_third = order [2]; 2064 if (out_sep) 2065 *out_sep = sep; 2066 2067 return TRUE; 2068 } 2069 2070 /** 2071 * gda_connection_insert_row_into_table: 2072 * @cnc: an opened connection 2073 * @table: table's name to insert into 2074 * @error: a place to store errors, or %NULL 2075 * @...: a list of string/GValue pairs with the name of the column to use and the 2076 * GValue pointer containing the value to insert for the column (value can be %NULL), finished by a %NULL. There must be 2077 * at least one column name and value 2078 * 2079 * This is a convenience function, which creates an INSERT statement and executes it using the values 2080 * provided. It internally relies on variables which makes it immune to SQL injection problems. 2081 * 2082 * The equivalent SQL command is: INSERT INTO <table> (<column_name> [,...]) VALUES (<column_name> = <new_value> [,...]). 2083 * 2084 * Returns: TRUE if no error occurred 2085 * 2086 * Since: 4.2.3 2087 */ 2088 G_GNUC_NULL_TERMINATED 2089 gboolean 2090 gda_connection_insert_row_into_table (GdaConnection *cnc, const gchar *table, GError **error, ...) 2091 { 2092 GSList *clist = NULL; 2093 GSList *vlist = NULL; 2094 gboolean retval; 2095 va_list args; 2096 gchar *col_name; 2097 2098 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 2099 g_return_val_if_fail (table && *table, FALSE); 2100 2101 va_start (args, error); 2102 while ((col_name = va_arg (args, gchar*))) { 2103 clist = g_slist_prepend (clist, col_name); 2104 GValue *value; 2105 value = va_arg (args, GValue *); 2106 vlist = g_slist_prepend (vlist, value); 2107 } 2108 2109 va_end (args); 2110 2111 if (!clist) { 2112 g_warning ("No specified column or value"); 2113 return FALSE; 2114 } 2115 2116 clist = g_slist_reverse (clist); 2117 vlist = g_slist_reverse (vlist); 2118 retval = gda_connection_insert_row_into_table_v (cnc, table, clist, vlist, error); 2119 g_slist_free (clist); 2120 g_slist_free (vlist); 2121 2122 return retval; 2123 } 2124 2125 /** 2126 * gda_connection_insert_row_into_table_v: 2127 * @cnc: an opened connection 2128 * @table: table's name to insert into 2129 * @col_names: (element-type utf8): a list of column names (as const gchar *) 2130 * @values: (element-type GValue): a list of values (as #GValue) 2131 * @error: a place to store errors, or %NULL 2132 * 2133 * @col_names and @values must have length (>= 1). 2134 * 2135 * This is a convenience function, which creates an INSERT statement and executes it using the values 2136 * provided. It internally relies on variables which makes it immune to SQL injection problems. 2137 * 2138 * The equivalent SQL command is: INSERT INTO <table> (<column_name> [,...]) VALUES (<column_name> = <new_value> [,...]). 2139 * 2140 * Returns: TRUE if no error occurred, FALSE otherwise 2141 * 2142 * Since: 4.2.3 2143 */ 2144 gboolean 2145 gda_connection_insert_row_into_table_v (GdaConnection *cnc, const gchar *table, 2146 GSList *col_names, GSList *values, 2147 GError **error) 2148 { 2149 gboolean retval; 2150 GSList *fields = NULL; 2151 GSList *expr_values = NULL; 2152 GdaSqlStatement *sql_stm; 2153 GdaSqlStatementInsert *ssi; 2154 GdaStatement *insert; 2155 gint i; 2156 2157 GSList *holders = NULL; 2158 GSList *l1, *l2; 2159 2160 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 2161 g_return_val_if_fail (table && *table, FALSE); 2162 g_return_val_if_fail (col_names, FALSE); 2163 g_return_val_if_fail (g_slist_length (col_names) == g_slist_length (values), FALSE); 2164 2165 /* Construct insert query and list of GdaHolders */ 2166 sql_stm = gda_sql_statement_new (GDA_SQL_STATEMENT_INSERT); 2167 ssi = (GdaSqlStatementInsert*) sql_stm->contents; 2168 g_assert (GDA_SQL_ANY_PART (ssi)->type == GDA_SQL_ANY_STMT_INSERT); 2169 2170 ssi->table = gda_sql_table_new (GDA_SQL_ANY_PART (ssi)); 2171 ssi->table->table_name = gda_sql_identifier_quote (table, cnc, NULL, FALSE, FALSE); 2172 2173 i = 0; 2174 for (l1 = col_names, l2 = values; 2175 l1; 2176 l1 = l1->next, l2 = l2->next) { 2177 GdaSqlField *field; 2178 GdaSqlExpr *expr; 2179 GValue *value = (GValue *) l2->data; 2180 const gchar *col_name = (const gchar*) l1->data; 2181 2182 /* field */ 2183 field = gda_sql_field_new (GDA_SQL_ANY_PART (ssi)); 2184 field->field_name = gda_sql_identifier_quote (col_name, cnc, NULL, FALSE, FALSE); 2185 fields = g_slist_prepend (fields, field); 2186 2187 /* value */ 2188 expr = gda_sql_expr_new (GDA_SQL_ANY_PART (ssi)); 2189 if (value && (G_VALUE_TYPE (value) != GDA_TYPE_NULL)) { 2190 /* create a GdaSqlExpr with a parameter */ 2191 GdaSqlParamSpec *param; 2192 param = g_new0 (GdaSqlParamSpec, 1); 2193 param->name = g_strdup_printf ("+%d", i); 2194 param->g_type = G_VALUE_TYPE (value); 2195 param->is_param = TRUE; 2196 expr->param_spec = param; 2197 2198 GdaHolder *holder; 2199 holder = (GdaHolder*) g_object_new (GDA_TYPE_HOLDER, "g-type", G_VALUE_TYPE (value), 2200 "id", param->name, NULL); 2201 g_assert (gda_holder_set_value (holder, value, NULL)); 2202 holders = g_slist_prepend (holders, holder); 2203 } 2204 else { 2205 /* create a NULL GdaSqlExpr => nothing to do */ 2206 } 2207 expr_values = g_slist_prepend (expr_values, expr); 2208 2209 i++; 2210 } 2211 2212 ssi->fields_list = g_slist_reverse (fields); 2213 ssi->values_list = g_slist_prepend (NULL, g_slist_reverse (expr_values)); 2214 2215 insert = gda_statement_new (); 2216 g_object_set (G_OBJECT (insert), "structure", sql_stm, NULL); 2217 gda_sql_statement_free (sql_stm); 2218 2219 /* execute statement */ 2220 GdaSet *set = NULL; 2221 if (holders) { 2222 set = gda_set_new (holders); 2223 g_slist_foreach (holders, (GFunc) g_object_unref, NULL); 2224 g_slist_free (holders); 2225 } 2226 2227 retval = (gda_connection_statement_execute_non_select (cnc, insert, set, NULL, error) == -1) ? FALSE : TRUE; 2228 2229 if (set) 2230 g_object_unref (set); 2231 g_object_unref (insert); 2232 2233 return retval; 2234 } 2235 2236 /** 2237 * gda_connection_update_row_in_table: 2238 * @cnc: an opened connection 2239 * @table: the table's name with the row's values to be updated 2240 * @condition_column_name: the name of the column to used in the WHERE condition clause 2241 * @condition_value: the @condition_column_type's GType 2242 * @error: a place to store errors, or %NULL 2243 * @...: a list of string/GValue pairs with the name of the column to use and the 2244 * GValue pointer containing the value to update the column to (value can be %NULL), finished by a %NULL. There must be 2245 * at least one column name and value 2246 * 2247 * This is a convenience function, which creates an UPDATE statement and executes it using the values 2248 * provided. It internally relies on variables which makes it immune to SQL injection problems. 2249 * 2250 * The equivalent SQL command is: UPDATE <table> SET <column_name> = <new_value> [,...] WHERE <condition_column_name> = <condition_value>. 2251 * 2252 * Returns: TRUE if no error occurred, FALSE otherwise 2253 * 2254 * Since: 4.2.3 2255 */ 2256 G_GNUC_NULL_TERMINATED 2257 gboolean 2258 gda_connection_update_row_in_table (GdaConnection *cnc, const gchar *table, 2259 const gchar *condition_column_name, 2260 GValue *condition_value, GError **error, ...) 2261 { 2262 GSList *clist = NULL; 2263 GSList *vlist = NULL; 2264 gboolean retval; 2265 va_list args; 2266 gchar *col_name; 2267 2268 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 2269 g_return_val_if_fail (table && *table, FALSE); 2270 2271 va_start (args, error); 2272 while ((col_name = va_arg (args, gchar*))) { 2273 clist = g_slist_prepend (clist, col_name); 2274 GValue *value; 2275 value = va_arg (args, GValue *); 2276 vlist = g_slist_prepend (vlist, value); 2277 } 2278 2279 va_end (args); 2280 2281 if (!clist) { 2282 g_warning ("No specified column or value"); 2283 return FALSE; 2284 } 2285 2286 clist = g_slist_reverse (clist); 2287 vlist = g_slist_reverse (vlist); 2288 retval = gda_connection_update_row_in_table_v (cnc, table, condition_column_name, condition_value, clist, vlist, error); 2289 g_slist_free (clist); 2290 g_slist_free (vlist); 2291 2292 return retval; 2293 } 2294 2295 /** 2296 * gda_connection_update_row_in_table_v: 2297 * @cnc: an opened connection 2298 * @table: the table's name with the row's values to be updated 2299 * @condition_column_name: the name of the column to used in the WHERE condition clause 2300 * @condition_value: the @condition_column_type's GType 2301 * @col_names: (element-type utf8): a list of column names (as const gchar *) 2302 * @values: (element-type GValue): a list of values (as #GValue) 2303 * @error: a place to store errors, or %NULL 2304 * 2305 * @col_names and @values must have length (>= 1). 2306 * 2307 * This is a convenience function, which creates an UPDATE statement and executes it using the values 2308 * provided. It internally relies on variables which makes it immune to SQL injection problems. 2309 * 2310 * The equivalent SQL command is: UPDATE <table> SET <column_name> = <new_value> [,...] WHERE <condition_column_name> = <condition_value>. 2311 * 2312 * Returns: TRUE if no error occurred, FALSE otherwise 2313 * 2314 * Since: 4.2.3 2315 */ 2316 gboolean 2317 gda_connection_update_row_in_table_v (GdaConnection *cnc, const gchar *table, 2318 const gchar *condition_column_name, 2319 GValue *condition_value, 2320 GSList *col_names, GSList *values, 2321 GError **error) 2322 { 2323 gboolean retval; 2324 GSList *fields = NULL; 2325 GSList *expr_values = NULL; 2326 GdaSqlStatement *sql_stm; 2327 GdaSqlStatementUpdate *ssu; 2328 GdaStatement *update; 2329 gint i; 2330 2331 GSList *holders = NULL; 2332 GSList *l1, *l2; 2333 2334 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 2335 g_return_val_if_fail (table && *table, FALSE); 2336 g_return_val_if_fail (col_names, FALSE); 2337 g_return_val_if_fail (g_slist_length (col_names) == g_slist_length (values), FALSE); 2338 2339 /* Construct update query and list of GdaHolders */ 2340 sql_stm = gda_sql_statement_new (GDA_SQL_STATEMENT_UPDATE); 2341 ssu = (GdaSqlStatementUpdate*) sql_stm->contents; 2342 g_assert (GDA_SQL_ANY_PART (ssu)->type == GDA_SQL_ANY_STMT_UPDATE); 2343 2344 ssu->table = gda_sql_table_new (GDA_SQL_ANY_PART (ssu)); 2345 ssu->table->table_name = gda_sql_identifier_quote (table, cnc, NULL, FALSE, FALSE); 2346 2347 if (condition_column_name) { 2348 GdaSqlExpr *where, *op; 2349 where = gda_sql_expr_new (GDA_SQL_ANY_PART (ssu)); 2350 ssu->cond = where; 2351 2352 where->cond = gda_sql_operation_new (GDA_SQL_ANY_PART (where)); 2353 where->cond->operator_type = GDA_SQL_OPERATOR_TYPE_EQ; 2354 2355 op = gda_sql_expr_new (GDA_SQL_ANY_PART (where->cond)); 2356 where->cond->operands = g_slist_prepend (NULL, op); 2357 op->value = gda_value_new (G_TYPE_STRING); 2358 g_value_take_string (op->value, gda_sql_identifier_quote (condition_column_name, cnc, NULL, 2359 FALSE, FALSE)); 2360 2361 op = gda_sql_expr_new (GDA_SQL_ANY_PART (where->cond)); 2362 where->cond->operands = g_slist_append (where->cond->operands, op); 2363 if (condition_value) { 2364 GdaSqlParamSpec *param; 2365 param = g_new0 (GdaSqlParamSpec, 1); 2366 param->name = g_strdup ("cond"); 2367 param->g_type = G_VALUE_TYPE (condition_value); 2368 param->is_param = TRUE; 2369 op->param_spec = param; 2370 2371 GdaHolder *holder; 2372 holder = (GdaHolder*) g_object_new (GDA_TYPE_HOLDER, "g-type", G_VALUE_TYPE (condition_value), 2373 "id", param->name, NULL); 2374 g_assert (gda_holder_set_value (holder, condition_value, NULL)); 2375 holders = g_slist_prepend (holders, holder); 2376 } 2377 else { 2378 /* nothing to do: NULL */ 2379 } 2380 } 2381 2382 i = 0; 2383 for (l1 = col_names, l2 = values; 2384 l1; 2385 l1 = l1->next, l2 = l2->next) { 2386 GValue *value = (GValue *) l2->data; 2387 const gchar *col_name = (const gchar*) l1->data; 2388 GdaSqlField *field; 2389 GdaSqlExpr *expr; 2390 2391 /* field */ 2392 field = gda_sql_field_new (GDA_SQL_ANY_PART (ssu)); 2393 field->field_name = gda_sql_identifier_quote (col_name, cnc, NULL, FALSE, FALSE); 2394 fields = g_slist_prepend (fields, field); 2395 2396 /* value */ 2397 expr = gda_sql_expr_new (GDA_SQL_ANY_PART (ssu)); 2398 if (value && (G_VALUE_TYPE (value) != GDA_TYPE_NULL)) { 2399 /* create a GdaSqlExpr with a parameter */ 2400 GdaSqlParamSpec *param; 2401 param = g_new0 (GdaSqlParamSpec, 1); 2402 param->name = g_strdup_printf ("+%d", i); 2403 param->g_type = G_VALUE_TYPE (value); 2404 param->is_param = TRUE; 2405 expr->param_spec = param; 2406 2407 GdaHolder *holder; 2408 holder = (GdaHolder*) g_object_new (GDA_TYPE_HOLDER, "g-type", G_VALUE_TYPE (value), 2409 "id", param->name, NULL); 2410 g_assert (gda_holder_set_value (holder, value, NULL)); 2411 holders = g_slist_prepend (holders, holder); 2412 } 2413 else { 2414 /* create a NULL GdaSqlExpr => nothing to do */ 2415 } 2416 expr_values = g_slist_prepend (expr_values, expr); 2417 2418 i++; 2419 } 2420 2421 ssu->fields_list = g_slist_reverse (fields); 2422 ssu->expr_list = g_slist_reverse (expr_values); 2423 2424 update = gda_statement_new (); 2425 g_object_set (G_OBJECT (update), "structure", sql_stm, NULL); 2426 gda_sql_statement_free (sql_stm); 2427 2428 /* execute statement */ 2429 GdaSet *set = NULL; 2430 if (holders) { 2431 set = gda_set_new (holders); 2432 g_slist_foreach (holders, (GFunc) g_object_unref, NULL); 2433 g_slist_free (holders); 2434 } 2435 2436 retval = (gda_connection_statement_execute_non_select (cnc, update, set, NULL, error) == -1) ? FALSE : TRUE; 2437 2438 if (set) 2439 g_object_unref (set); 2440 g_object_unref (update); 2441 2442 return retval; 2443 } 2444 2445 /** 2446 * gda_connection_delete_row_from_table: 2447 * @cnc: an opened connection 2448 * @table: the table's name with the row's values to be updated 2449 * @condition_column_name: the name of the column to used in the WHERE condition clause 2450 * @condition_value: the @condition_column_type's GType 2451 * @error: a place to store errors, or %NULL 2452 * 2453 * This is a convenience function, which creates a DELETE statement and executes it using the values 2454 * provided. It internally relies on variables which makes it immune to SQL injection problems. 2455 * 2456 * The equivalent SQL command is: DELETE FROM <table> WHERE <condition_column_name> = <condition_value>. 2457 * 2458 * Returns: TRUE if no error occurred, FALSE otherwise 2459 * 2460 * Since: 4.2.3 2461 */ 2462 gboolean 2463 gda_connection_delete_row_from_table (GdaConnection *cnc, const gchar *table, 2464 const gchar *condition_column_name, 2465 GValue *condition_value, GError **error) 2466 { 2467 gboolean retval; 2468 GdaSqlStatement *sql_stm; 2469 GdaSqlStatementDelete *ssd; 2470 GdaStatement *delete; 2471 2472 GSList *holders = NULL; 2473 2474 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 2475 g_return_val_if_fail (table && *table, FALSE); 2476 2477 /* Construct delete query and list of GdaHolders */ 2478 sql_stm = gda_sql_statement_new (GDA_SQL_STATEMENT_DELETE); 2479 ssd = (GdaSqlStatementDelete*) sql_stm->contents; 2480 g_assert (GDA_SQL_ANY_PART (ssd)->type == GDA_SQL_ANY_STMT_DELETE); 2481 2482 ssd->table = gda_sql_table_new (GDA_SQL_ANY_PART (ssd)); 2483 ssd->table->table_name = gda_sql_identifier_quote (table, cnc, NULL, FALSE, FALSE); 2484 2485 if (condition_column_name) { 2486 GdaSqlExpr *where, *op; 2487 where = gda_sql_expr_new (GDA_SQL_ANY_PART (ssd)); 2488 ssd->cond = where; 2489 2490 where->cond = gda_sql_operation_new (GDA_SQL_ANY_PART (where)); 2491 where->cond->operator_type = GDA_SQL_OPERATOR_TYPE_EQ; 2492 2493 op = gda_sql_expr_new (GDA_SQL_ANY_PART (where->cond)); 2494 where->cond->operands = g_slist_prepend (NULL, op); 2495 op->value = gda_value_new (G_TYPE_STRING); 2496 g_value_take_string (op->value, gda_sql_identifier_quote (condition_column_name, cnc, NULL, 2497 FALSE, FALSE)); 2498 2499 op = gda_sql_expr_new (GDA_SQL_ANY_PART (where->cond)); 2500 where->cond->operands = g_slist_append (where->cond->operands, op); 2501 if (condition_value) { 2502 GdaSqlParamSpec *param; 2503 param = g_new0 (GdaSqlParamSpec, 1); 2504 param->name = g_strdup ("cond"); 2505 param->g_type = G_VALUE_TYPE (condition_value); 2506 param->is_param = TRUE; 2507 op->param_spec = param; 2508 2509 GdaHolder *holder; 2510 holder = (GdaHolder*) g_object_new (GDA_TYPE_HOLDER, "g-type", G_VALUE_TYPE (condition_value), 2511 "id", param->name, NULL); 2512 g_assert (gda_holder_set_value (holder, condition_value, NULL)); 2513 holders = g_slist_prepend (holders, holder); 2514 } 2515 else { 2516 /* nothing to do: NULL */ 2517 } 2518 } 2519 2520 delete = gda_statement_new (); 2521 g_object_set (G_OBJECT (delete), "structure", sql_stm, NULL); 2522 gda_sql_statement_free (sql_stm); 2523 2524 /* execute statement */ 2525 GdaSet *set = NULL; 2526 if (holders) { 2527 set = gda_set_new (holders); 2528 g_slist_foreach (holders, (GFunc) g_object_unref, NULL); 2529 g_slist_free (holders); 2530 } 2531 2532 retval = (gda_connection_statement_execute_non_select (cnc, delete, set, NULL, error) == -1) ? FALSE : TRUE; 2533 2534 if (set) 2535 g_object_unref (set); 2536 g_object_unref (delete); 2537 2538 return retval; 2539 } 2540 2541 /** 2542 * gda_connection_parse_sql_string: 2543 * @cnc: (allow-none): a #GdaConnection object, or %NULL 2544 * @sql: an SQL command to parse, not %NULL 2545 * @params: (out) (allow-none) (transfer full): a place to store a new #GdaSet, for parameters used in SQL command, or %NULL 2546 * @error: a place to store errors, or %NULL 2547 * 2548 * This function helps to parse a SQL string which uses parameters and store them at @params. 2549 * 2550 * Returns: (transfer full): a #GdaStatement representing the SQL command, or %NULL if an error occurred 2551 * 2552 * Since: 4.2.3 2553 */ 2554 GdaStatement* 2555 gda_connection_parse_sql_string (GdaConnection *cnc, const gchar *sql, GdaSet **params, GError **error) 2556 { 2557 GdaStatement *stmt; 2558 GdaSqlParser *parser = NULL; 2559 2560 g_return_val_if_fail (!cnc || GDA_IS_CONNECTION (cnc), NULL); 2561 g_return_val_if_fail (sql, NULL); 2562 2563 if (params) 2564 *params = NULL; 2565 if (cnc) 2566 parser = gda_connection_create_parser (cnc); 2567 if (!parser) 2568 parser = gda_sql_parser_new (); 2569 2570 stmt = gda_sql_parser_parse_string (parser, sql, NULL, error); 2571 g_object_unref (parser); 2572 if (! stmt) 2573 return NULL; 2574 2575 if (params && !gda_statement_get_parameters (stmt, params, error)) { 2576 g_object_unref (stmt); 2577 return NULL; 2578 } 2579 2580 return stmt; 2581 } 2582 2583 /** 2584 * gda_connection_point_available_event: 2585 * @cnc: a #GdaConnection object 2586 * @type: a #GdaConnectionEventType 2587 * 2588 * Use this method to get a pointer to the next available connection event which can then be customized 2589 * and taken into account using gda_connection_add_event(). 2590 * 2591 * Returns: (transfer full): a pointer to the next available connection event, or %NULL if event should 2592 * be ignored 2593 * 2594 * Since: 4.2 2595 */ 2596 GdaConnectionEvent * 2597 gda_connection_point_available_event (GdaConnection *cnc, GdaConnectionEventType type) 2598 { 2599 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 2600 2601 /* ownership is transfered to the caller ! */ 2602 2603 GdaConnectionEvent *eev; 2604 eev = cnc->priv->events_array [cnc->priv->events_array_next]; 2605 if (!eev) 2606 eev = GDA_CONNECTION_EVENT (g_object_new (GDA_TYPE_CONNECTION_EVENT, 2607 "type", (int)type, NULL)); 2608 else { 2609 gda_connection_event_set_event_type (eev, type); 2610 cnc->priv->events_array [cnc->priv->events_array_next] = NULL; 2611 } 2612 2613 return eev; 2614 } 2615 2616 #ifdef GDA_DEBUG_NO 2617 static void 2618 dump_events_array (GdaConnection *cnc) 2619 { 2620 gint i; 2621 g_print ("=== Array dump for %p ===\n", cnc); 2622 for (i = 0; i < cnc->priv->events_array_size; i++) { 2623 g_print (" [%d] => %p\n", i, cnc->priv->events_array [i]); 2624 } 2625 2626 const GList *list; 2627 for (list = gda_connection_get_events (cnc); list; list = list->next) { 2628 GdaConnectionEvent *ev = GDA_CONNECTION_EVENT (list->data); 2629 g_print (" => %p\n", ev); 2630 } 2631 } 2632 #endif 2633 2634 /** 2635 * gda_connection_add_event: 2636 * @cnc: a #GdaConnection object. 2637 * @event: (transfer full): is stored internally, so you don't need to unref it. 2638 * 2639 * Adds an event to the given connection. This function is usually 2640 * called by providers, to inform clients of events that happened 2641 * during some operation. 2642 * 2643 * As soon as a provider (or a client, it does not matter) calls this 2644 * function with an @event object which is an error, 2645 * the connection object emits the "error" signal, to which clients can connect to be 2646 * informed of events. 2647 * 2648 * WARNING: the reference to the @event object is stolen by this function! 2649 */ 2650 void 2651 gda_connection_add_event (GdaConnection *cnc, GdaConnectionEvent *event) 2652 { 2653 g_return_if_fail (GDA_IS_CONNECTION (cnc)); 2654 g_return_if_fail (GDA_IS_CONNECTION_EVENT (event)); 2655 2656 g_rec_mutex_lock (& cnc->priv->rmutex); 2657 2658 /* clear external list of events */ 2659 if (cnc->priv->events_list) { 2660 g_list_foreach (cnc->priv->events_list, (GFunc) g_object_unref, NULL); 2661 g_list_free (cnc->priv->events_list); 2662 cnc->priv->events_list = NULL; 2663 } 2664 2665 /* add event, ownership is transfered to @cnc */ 2666 GdaConnectionEvent *eev; 2667 eev = cnc->priv->events_array [cnc->priv->events_array_next]; 2668 if (eev != event) { 2669 if (eev) 2670 g_object_unref (eev); 2671 cnc->priv->events_array [cnc->priv->events_array_next] = event; 2672 } 2673 2674 /* handle indexes */ 2675 cnc->priv->events_array_next ++; 2676 if (cnc->priv->events_array_next == cnc->priv->events_array_size) { 2677 cnc->priv->events_array_next = 0; 2678 cnc->priv->events_array_full = TRUE; 2679 } 2680 2681 if (debug_level > 0) { 2682 const gchar *str = NULL; 2683 switch (gda_connection_event_get_event_type (event)) { 2684 case GDA_CONNECTION_EVENT_NOTICE: 2685 if (debug_level & 1) str = "NOTICE"; 2686 break; 2687 case GDA_CONNECTION_EVENT_WARNING: 2688 if (debug_level & 2) str = "WARNING"; 2689 break; 2690 case GDA_CONNECTION_EVENT_ERROR: 2691 if (debug_level & 4) str = "ERROR"; 2692 break; 2693 case GDA_CONNECTION_EVENT_COMMAND: 2694 if (debug_level & 8) str = "COMMAND"; 2695 break; 2696 default: 2697 break; 2698 } 2699 if (str) 2700 g_print ("EVENT> %s: %s (on cnx %p, %s)\n", str, 2701 gda_connection_event_get_description (event), cnc, 2702 gda_connection_event_get_sqlstate (event)); 2703 } 2704 2705 if (gda_connection_event_get_event_type (event) == GDA_CONNECTION_EVENT_ERROR) 2706 g_signal_emit (G_OBJECT (cnc), gda_connection_signals[ERROR], 0, event); 2707 2708 #ifdef GDA_DEBUG_NO 2709 dump_events_array (cnc); 2710 #endif 2711 g_rec_mutex_unlock (& cnc->priv->rmutex); 2712 } 2713 2714 /** 2715 * gda_connection_add_event_string: (skip) 2716 * @cnc: a #GdaConnection object. 2717 * @str: a format string (see the printf(3) documentation). 2718 * @...: the arguments to insert in the error message. 2719 * 2720 * Adds a new error to the given connection object. This is just a convenience 2721 * function that simply creates a #GdaConnectionEvent and then calls 2722 * #gda_server_connection_add_error. 2723 * 2724 * Returns: (transfer none): a new #GdaConnectionEvent object, however the caller does not hold a reference to the returned object, and if need be the caller must call g_object_ref() on it. 2725 */ 2726 GdaConnectionEvent * 2727 gda_connection_add_event_string (GdaConnection *cnc, const gchar *str, ...) 2728 { 2729 GdaConnectionEvent *error; 2730 2731 va_list args; 2732 gchar sz[2048]; 2733 2734 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 2735 g_return_val_if_fail (str != NULL, NULL); 2736 2737 /* build the message string */ 2738 va_start (args, str); 2739 g_vsnprintf (sz, 2048, str, args); 2740 va_end (args); 2741 2742 error = gda_connection_point_available_event (cnc, GDA_CONNECTION_EVENT_ERROR); 2743 gda_connection_event_set_description (error, sz); 2744 gda_connection_event_set_code (error, -1); 2745 gda_connection_event_set_source (error, gda_connection_get_provider_name (cnc)); 2746 gda_connection_event_set_sqlstate (error, "-1"); 2747 2748 gda_connection_add_event (cnc, error); 2749 2750 return error; 2751 } 2752 2753 static void 2754 _clear_connection_events (GdaConnection *locked_cnc) 2755 { 2756 if (locked_cnc->priv->auto_clear_events) { 2757 locked_cnc->priv->events_array_full = FALSE; 2758 locked_cnc->priv->events_array_next = 0; 2759 } 2760 } 2761 2762 /** 2763 * gda_connection_clear_events_list: 2764 * @cnc: a #GdaConnection object. 2765 * 2766 * This function lets you clear the list of #GdaConnectionEvent's of the 2767 * given connection. 2768 */ 2769 void 2770 gda_connection_clear_events_list (GdaConnection *cnc) 2771 { 2772 g_return_if_fail (GDA_IS_CONNECTION (cnc)); 2773 gda_connection_lock ((GdaLockable*) cnc); 2774 _clear_connection_events (cnc); 2775 gda_connection_unlock ((GdaLockable*) cnc); 2776 } 2777 2778 /** 2779 * gda_connection_create_operation: 2780 * @cnc: a #GdaConnection object 2781 * @type: the type of operation requested 2782 * @options: (allow-none): an optional list of parameters 2783 * @error: a place to store an error, or %NULL 2784 * 2785 * Creates a new #GdaServerOperation object which can be modified in order 2786 * to perform the type type of action. It is a wrapper around the gda_server_provider_create_operation() 2787 * method. 2788 * 2789 * Returns: (transfer full): a new #GdaServerOperation object, or %NULL in the connection's provider does not support the @type type 2790 * of operation or if an error occurred 2791 */ 2792 GdaServerOperation* 2793 gda_connection_create_operation (GdaConnection *cnc, GdaServerOperationType type, 2794 GdaSet *options, GError **error) 2795 { 2796 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 2797 g_return_val_if_fail (cnc->priv->provider_obj, NULL); 2798 2799 return gda_server_provider_create_operation (cnc->priv->provider_obj, cnc, type, options, error); 2800 } 2801 2802 /** 2803 * gda_connection_perform_operation: 2804 * @cnc: a #GdaConnection object 2805 * @op: a #GdaServerOperation object 2806 * @error: a place to store an error, or %NULL 2807 * 2808 * Performs the operation described by @op (which should have been created using 2809 * gda_connection_create_operation()). It is a wrapper around the gda_server_provider_perform_operation() 2810 * method. 2811 * 2812 * Returns: TRUE if no error occurred 2813 */ 2814 gboolean 2815 gda_connection_perform_operation (GdaConnection *cnc, GdaServerOperation *op, GError **error) 2816 { 2817 gboolean retval; 2818 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 2819 g_return_val_if_fail (cnc->priv->provider_obj, FALSE); 2820 g_return_val_if_fail (GDA_IS_SERVER_OPERATION (op), FALSE); 2821 2822 cnc->priv->auto_clear_events = FALSE; 2823 retval = gda_server_provider_perform_operation (cnc->priv->provider_obj, cnc, op, error); 2824 cnc->priv->auto_clear_events = TRUE; 2825 return retval; 2826 } 2827 2828 /** 2829 * gda_connection_create_parser: 2830 * @cnc: a #GdaConnection object 2831 * 2832 * Creates a new parser object able to parse the SQL dialect understood by @cnc. 2833 * If the #GdaServerProvider object internally used by @cnc does not have its own parser, 2834 * then %NULL is returned, and a general SQL parser can be obtained 2835 * using gda_sql_parser_new(). 2836 * 2837 * Returns: (transfer full): a new #GdaSqlParser object, or %NULL 2838 */ 2839 GdaSqlParser * 2840 gda_connection_create_parser (GdaConnection *cnc) 2841 { 2842 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 2843 g_return_val_if_fail (cnc->priv->provider_obj, NULL); 2844 2845 return gda_server_provider_create_parser (cnc->priv->provider_obj, cnc); 2846 } 2847 2848 /* 2849 * Also resets the events list (as perceived when calling gda_connection_get_events() 2850 */ 2851 static void 2852 change_events_array_max_size (GdaConnection *cnc, gint size) 2853 { 2854 size ++; /* add 1 to compensate the "lost" slot when rotating the events array */ 2855 if (size == cnc->priv->events_array_size) 2856 return; 2857 2858 if (size > cnc->priv->events_array_size) { 2859 gint i; 2860 cnc->priv->events_array = g_renew (GdaConnectionEvent*, cnc->priv->events_array, 2861 size); 2862 for (i = cnc->priv->events_array_size; i < size; i++) 2863 cnc->priv->events_array [i] = NULL; 2864 } 2865 else if (size >= EVENTS_ARRAY_SIZE) { 2866 gint i; 2867 for (i = size; i < cnc->priv->events_array_size; i++) { 2868 if (cnc->priv->events_array [i]) 2869 g_object_unref (cnc->priv->events_array [i]); 2870 } 2871 cnc->priv->events_array = g_renew (GdaConnectionEvent*, cnc->priv->events_array, 2872 size); 2873 } 2874 cnc->priv->events_array_size = size; 2875 cnc->priv->events_array_full = FALSE; 2876 cnc->priv->events_array_next = 0; 2877 } 2878 2879 /** 2880 * gda_connection_batch_execute: 2881 * @cnc: a #GdaConnection object 2882 * @batch: a #GdaBatch object which contains all the statements to execute 2883 * @params: (allow-none): a #GdaSet object (which can be obtained using gda_batch_get_parameters()), or %NULL 2884 * @model_usage: specifies how the returned data model(s) will be used, as a #GdaStatementModelUsage enum 2885 * @error: a place to store errors, or %NULL 2886 * 2887 * Executes all the statements contained in @batch (in the order in which they were added to @batch), and 2888 * returns a list of #GObject objects, at most one #GObject for each statement; see gda_connection_statement_execute() 2889 * for details about the returned objects. 2890 * 2891 * If one of the statement fails, then none of the subsequent statement will be executed, and the method returns 2892 * the list of #GObject created by the correct execution of the previous statements. If a transaction is required, 2893 * then it should be started before calling this method. 2894 * 2895 * Returns: (transfer full) (element-type GObject): a new list of #GObject objects 2896 */ 2897 GSList * 2898 gda_connection_batch_execute (GdaConnection *cnc, GdaBatch *batch, GdaSet *params, 2899 GdaStatementModelUsage model_usage, GError **error) 2900 { 2901 GSList *retlist = NULL, *stmt_list; 2902 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 2903 g_return_val_if_fail (GDA_IS_BATCH (batch), NULL); 2904 2905 gda_connection_lock ((GdaLockable*) cnc); 2906 cnc->priv->auto_clear_events = FALSE; 2907 2908 /* increase the size of cnc->priv->events_array to be able to store all the 2909 * connection events */ 2910 stmt_list = (GSList*) gda_batch_get_statements (batch); 2911 change_events_array_max_size (cnc, g_slist_length (stmt_list) * 2); 2912 2913 for (; stmt_list; stmt_list = stmt_list->next) { 2914 GObject *obj; 2915 obj = gda_connection_statement_execute (cnc, GDA_STATEMENT (stmt_list->data), params, 2916 model_usage, NULL, error); 2917 if (!obj) 2918 break; 2919 retlist = g_slist_prepend (retlist, obj); 2920 } 2921 cnc->priv->auto_clear_events = TRUE; 2922 gda_connection_unlock ((GdaLockable*) cnc); 2923 2924 return g_slist_reverse (retlist); 2925 } 2926 2927 2928 /** 2929 * gda_connection_quote_sql_identifier: 2930 * @cnc: a #GdaConnection object 2931 * @id: an SQL identifier 2932 * 2933 * Use this method to get a correctly quoted (if necessary) SQL identifier which can be used 2934 * in SQL statements, from @id. If @id is already correctly quoted for @cnc, then a copy of @id 2935 * may be returned. 2936 * 2937 * This method may add double quotes (or other characters) around @id: 2938 * <itemizedlist> 2939 * <listitem><para>if @id is a reserved SQL keyword (such as SELECT, INSERT, ...)</para></listitem> 2940 * <listitem><para>if @id contains non allowed characters such as spaces, or if it starts with a digit</para></listitem> 2941 * <listitem><para>in any other event as necessary for @cnc, depending on the the options passed when opening the @cnc 2942 * connection, and specifically the <link linkend="GDA-CONNECTION-OPTIONS-SQL-IDENTIFIERS-CASE-SENSITIVE:CAPS"> 2943 * GDA_CONNECTION_OPTIONS_SQL_IDENTIFIERS_CASE_SENSITIVE</link> option.</para></listitem> 2944 * </itemizedlist> 2945 * 2946 * One can safely pass an already quoted @id to this method, either with quoting characters allowed by @cnc or using the 2947 * double quote (") character. 2948 * 2949 * Returns: a new string, to free with g_free() once not needed anymore 2950 * 2951 * Since: 4.0.3 2952 */ 2953 gchar * 2954 gda_connection_quote_sql_identifier (GdaConnection *cnc, const gchar *id) 2955 { 2956 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 2957 g_return_val_if_fail (id, NULL); 2958 2959 return gda_sql_identifier_quote (id, cnc, NULL, FALSE, 2960 cnc->priv->options & GDA_CONNECTION_OPTIONS_SQL_IDENTIFIERS_CASE_SENSITIVE); 2961 } 2962 2963 /** 2964 * gda_connection_statement_to_sql: 2965 * @cnc: a #GdaConnection object 2966 * @stmt: a #GdaStatement object 2967 * @params: (allow-none): a #GdaSet object (which can be obtained using gda_statement_get_parameters()), or %NULL 2968 * @flags: SQL rendering flags, as #GdaStatementSqlFlag OR'ed values 2969 * @params_used: (allow-none) (element-type Gda.Holder) (out) (transfer container): a place to store the list of individual #GdaHolder objects within @params which have been used 2970 * @error: a place to store errors, or %NULL 2971 * 2972 * Renders @stmt as an SQL statement, adapted to the SQL dialect used by @cnc 2973 * 2974 * Returns: (transfer full): a new string, or %NULL if an error occurred 2975 */ 2976 gchar * 2977 gda_connection_statement_to_sql (GdaConnection *cnc, GdaStatement *stmt, GdaSet *params, GdaStatementSqlFlag flags, 2978 GSList **params_used, GError **error) 2979 { 2980 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 2981 g_return_val_if_fail (cnc->priv->provider_obj, NULL); 2982 g_return_val_if_fail (GDA_IS_STATEMENT (stmt), NULL); 2983 2984 if (PROV_CLASS (cnc->priv->provider_obj)->statement_to_sql) 2985 return (PROV_CLASS (cnc->priv->provider_obj)->statement_to_sql) (cnc->priv->provider_obj, 2986 cnc, stmt, params, flags, 2987 params_used, error); 2988 else 2989 return gda_statement_to_sql_extended (stmt, cnc, params, flags, params_used, error); 2990 } 2991 2992 /** 2993 * gda_connection_statement_prepare: 2994 * @cnc: a #GdaConnection 2995 * @stmt: a #GdaStatement object 2996 * @error: a place to store errors, or %NULL 2997 * 2998 * Ask the database accessed through the @cnc connection to prepare the usage of @stmt. This is only useful 2999 * if @stmt will be used more than once (however some database providers may always prepare statements 3000 * before executing them). 3001 * 3002 * This function is also useful to make sure @stmt is fully understood by the database before actually executing it. 3003 * 3004 * Note however that it is also possible that gda_connection_statement_prepare() fails when 3005 * gda_connection_statement_execute() does not fail (this will usually be the case with statements such as 3006 * <![CDATA["SELECT * FROM ##tablename::string"]]> because database usually don't allow variables to be used in place of a 3007 * table name). 3008 * 3009 * Returns: TRUE if no error occurred. 3010 */ 3011 gboolean 3012 gda_connection_statement_prepare (GdaConnection *cnc, GdaStatement *stmt, GError **error) 3013 { 3014 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 3015 g_return_val_if_fail (cnc->priv->provider_obj, FALSE); 3016 g_return_val_if_fail (GDA_IS_STATEMENT (stmt), FALSE); 3017 3018 if (PROV_CLASS (cnc->priv->provider_obj)->statement_prepare) 3019 return (PROV_CLASS (cnc->priv->provider_obj)->statement_prepare)(cnc->priv->provider_obj, 3020 cnc, stmt, error); 3021 else { 3022 g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_METHOD_NON_IMPLEMENTED_ERROR, 3023 "%s", _("Provider does not support statement preparation")); 3024 return FALSE; 3025 } 3026 } 3027 3028 /* 3029 * @args is consumed as a succession of (column number, GType) arguments 3030 * which ends with a column number of -1. The returned array is always terminated by G_TYPE_NONE, 3031 * and contains 0 where no column type information has been provided 3032 */ 3033 static GType * 3034 make_col_types_array (va_list args) 3035 { 3036 GType *types; 3037 gint max = 10; 3038 gint col, lastidx = 0; 3039 3040 col = va_arg (args, gint); 3041 if (col < 0) 3042 return NULL; 3043 3044 types = g_new0 (GType, max + 1); 3045 types [max] = G_TYPE_NONE; 3046 for (; col >= 0; col = va_arg (args, gint)) { 3047 if (col >= max) { 3048 gint i; 3049 types = g_renew (GType, types, col + 5 + 1); 3050 for (i = max; i <= col + 5; i ++) 3051 types[i] = 0; 3052 max = col + 5; 3053 types [max] = G_TYPE_NONE; 3054 } 3055 types [col] = va_arg (args, GType); 3056 lastidx = col+1; 3057 } 3058 3059 if (lastidx == 0) { 3060 g_free (types); 3061 types = NULL; 3062 } 3063 else 3064 types [lastidx] = G_TYPE_NONE; 3065 3066 return types; 3067 } 3068 3069 static void 3070 add_exec_time_to_object (GObject *obj, GTimer *timer) 3071 { 3072 gdouble etime; 3073 etime = g_timer_elapsed (timer, NULL); 3074 if (GDA_IS_DATA_SELECT (obj)) 3075 g_object_set (obj, "execution-delay", etime, NULL); 3076 else if (GDA_IS_SET (obj)) { 3077 GdaHolder *holder; 3078 holder = gda_holder_new_inline (G_TYPE_DOUBLE, "EXEC_DELAY", etime); 3079 gda_set_add_holder ((GdaSet*) obj, holder); 3080 g_object_unref ((GObject*) holder); 3081 } 3082 else 3083 TO_IMPLEMENT; 3084 } 3085 3086 /* 3087 * No locking is done here must be done before calling 3088 * 3089 * Returns: -1 if task not found 3090 */ 3091 static gint 3092 get_task_index (GdaConnection *cnc, guint task_id, gboolean *out_completed, gboolean id_is_prov) 3093 { 3094 gint i, len; 3095 CncTask *task; 3096 len = cnc->priv->completed_tasks->len; 3097 for (i = 0; i < len; i++) { 3098 task = CNC_TASK (g_array_index (cnc->priv->completed_tasks, gpointer, i)); 3099 if ((! id_is_prov && (task->task_id == task_id)) || 3100 (id_is_prov && (task->prov_task_id == task_id))) { 3101 *out_completed = TRUE; 3102 return i; 3103 } 3104 } 3105 3106 len = cnc->priv->waiting_tasks->len; 3107 for (i = 0; i < len; i++) { 3108 task = CNC_TASK (g_array_index (cnc->priv->waiting_tasks, gpointer, i)); 3109 if ((! id_is_prov && (task->task_id == task_id)) || 3110 (id_is_prov && (task->prov_task_id == task_id))) { 3111 *out_completed = FALSE; 3112 return i; 3113 } 3114 } 3115 3116 return -1; 3117 } 3118 3119 /* 3120 * This callback is called from the GdaServerProvider object, from the handle_async() method 3121 */ 3122 static void 3123 async_stmt_exec_cb (G_GNUC_UNUSED GdaServerProvider *provider, GdaConnection *cnc, guint task_id, 3124 GObject *result_obj, const GError *error, G_GNUC_UNUSED CncTask *task) 3125 { 3126 gint i; 3127 gboolean is_completed; 3128 3129 g_object_ref ((GObject*) cnc); 3130 gda_connection_lock (GDA_LOCKABLE (cnc)); 3131 3132 i = get_task_index (cnc, task_id, &is_completed, TRUE); 3133 if (i >= 0) { 3134 CncTask *task; 3135 g_assert (!is_completed); 3136 3137 /* complete @task and free some memory */ 3138 task = CNC_TASK (g_array_index (cnc->priv->waiting_tasks, gpointer, i)); 3139 cnc_task_lock (task); 3140 3141 task->being_processed = FALSE; 3142 if (task->exec_timer) 3143 g_timer_stop (task->exec_timer); 3144 3145 if (error) 3146 task->error = g_error_copy (error); 3147 if (result_obj) { 3148 task->result = g_object_ref (result_obj); 3149 if (task->exec_timer) 3150 add_exec_time_to_object (task->result, task->exec_timer); 3151 } 3152 if (task->stmt) { 3153 g_signal_handlers_disconnect_by_func (task->stmt, 3154 G_CALLBACK (task_stmt_reset_cb), task); 3155 g_object_unref (task->stmt); 3156 task->stmt = NULL; 3157 } 3158 if (task->params) { 3159 g_object_unref (task->params); 3160 task->params = NULL; 3161 } 3162 if (task->col_types) { 3163 g_free (task->col_types); 3164 task->col_types = NULL; 3165 } 3166 3167 g_array_remove_index (cnc->priv->waiting_tasks, i); 3168 g_array_append_val (cnc->priv->completed_tasks, task); 3169 3170 cnc_task_unlock (task); 3171 3172 /* execute next waiting task if there is one */ 3173 while (cnc->priv->waiting_tasks->len >= 1) { 3174 /* execute statement now as there are no other ones to be executed */ 3175 GError *lerror = NULL; 3176 task = CNC_TASK (g_array_index (cnc->priv->waiting_tasks, gpointer, 0)); 3177 cnc_task_lock (task); 3178 task->being_processed = TRUE; 3179 dump_exec_params (cnc, task->stmt, task->params); 3180 if (cnc->priv->exec_times) 3181 g_timer_start (task->exec_timer); 3182 if (cnc->priv->exec_slowdown && !cnc->priv->is_thread_wrapper) 3183 g_usleep (cnc->priv->exec_slowdown); 3184 3185 PROV_CLASS (cnc->priv->provider_obj)->statement_execute (cnc->priv->provider_obj, cnc, 3186 task->stmt, 3187 task->params, 3188 task->model_usage, 3189 task->col_types, 3190 &(task->last_insert_row), 3191 &(task->prov_task_id), 3192 (GdaServerProviderExecCallback) async_stmt_exec_cb, 3193 task, &lerror); 3194 if (lerror) { 3195 /* task execution failed => move it to completed tasks array */ 3196 task->error = lerror; 3197 task->being_processed = FALSE; 3198 if (cnc->priv->exec_times) 3199 g_timer_stop (task->exec_timer); 3200 g_array_remove_index (cnc->priv->waiting_tasks, 0); 3201 g_array_append_val (cnc->priv->completed_tasks, task); 3202 cnc_task_unlock (task); 3203 } 3204 else { 3205 update_meta_store_after_statement_exec (cnc, task->stmt, task->params); 3206 cnc_task_unlock (task); 3207 break; 3208 } 3209 } 3210 } 3211 else 3212 g_warning ("Provider called back for the execution of task %u (provider numbering) which does not exist, " 3213 "ignored.\n", task_id); 3214 3215 gda_connection_unlock (GDA_LOCKABLE (cnc)); 3216 g_object_unref ((GObject*) cnc); 3217 } 3218 3219 /** 3220 * gda_connection_async_statement_execute: 3221 * @cnc: a #GdaConnection 3222 * @stmt: a #GdaStatement object 3223 * @params: (allow-none): a #GdaSet object (which can be obtained using gda_statement_get_parameters()), or %NULL 3224 * @model_usage: in the case where @stmt is a SELECT statement, specifies how the returned data model will be used 3225 * @col_types: (array) (allow-none): an array of GType to request each returned #GdaDataModel's column's GType, terminated with the G_TYPE_NONE 3226 * @need_last_insert_row: TRUE if the values of the last interted row must be computed 3227 * @error: a place to store errors, or %NULL 3228 * 3229 * This method is similar to gda_connection_statement_execute() but is asynchronous as it method returns 3230 * immediately with a task ID. It's up to the caller to use gda_connection_async_fetch_result() regularly to check 3231 * if the statement's execution is finished. 3232 * 3233 * It is possible to call the method several times to request several statements to be executed asynchronously, the 3234 * statements will be executed in the order in which they were requested. 3235 * 3236 * The parameters, if present, are copied and can be discarded or modified before the statement is actually executed. 3237 * The @stmt object is not copied but simply referenced (for performance reasons), and if it is modified before 3238 * it is actually executed, then its execution will not occur. It is however safe to call g_object_unref() on it if 3239 * it's not needed anymore. 3240 * 3241 * The execution failure of any statement has no impact on the execution of other statements except for example if 3242 * the connection has a transaction started and the failure invalidates the transaction (as decided by the database 3243 * server). 3244 * 3245 * Note that for asynchronous calls to succeed, it is gererally necessary to specify the 3246 * %GDA_CONNECTION_OPTIONS_THREAD_ISOLATED flag when opening the connection to be sure it is opened in a separate thread 3247 * in which asynchronous calls are made (failing to use this flag make the asynchronous call dependant on the database 3248 * provider implementation and at the moment none support this feature). 3249 * 3250 * Returns: a task ID, or 0 if an error occurred (not an error regarding @stmt itself as its execution has not yet started 3251 * but any other error) 3252 * 3253 * Since: 4.2 3254 */ 3255 guint 3256 gda_connection_async_statement_execute (GdaConnection *cnc, GdaStatement *stmt, GdaSet *params, 3257 GdaStatementModelUsage model_usage, GType *col_types, 3258 gboolean need_last_insert_row, 3259 GError **error) 3260 { 3261 guint id; 3262 CncTask *task; 3263 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), 0); 3264 g_return_val_if_fail (cnc->priv->provider_obj, 0); 3265 g_return_val_if_fail (GDA_IS_STATEMENT (stmt), 0); 3266 g_return_val_if_fail (PROV_CLASS (cnc->priv->provider_obj)->statement_execute, 0); 3267 3268 3269 g_object_ref ((GObject*) cnc); 3270 if (! gda_connection_trylock ((GdaLockable*) cnc)) { 3271 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_CANT_LOCK_ERROR, 3272 _("Can't obtain connection lock")); 3273 g_object_unref ((GObject*) cnc); 3274 return 0; 3275 } 3276 3277 if (!cnc->priv->provider_data) { 3278 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_CLOSED_ERROR, 3279 _("Connection is closed")); 3280 gda_connection_unlock (GDA_LOCKABLE (cnc)); 3281 g_object_unref ((GObject*) cnc); 3282 return 0; 3283 } 3284 3285 if (!PROV_CLASS (cnc->priv->provider_obj)->handle_async) { 3286 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_UNSUPPORTED_ASYNC_EXEC_ERROR, 3287 _("Asynchronous execution is not supported")); 3288 gda_connection_unlock (GDA_LOCKABLE (cnc)); 3289 g_object_unref ((GObject*) cnc); 3290 return 0; 3291 } 3292 3293 id = cnc->priv->next_task_id ++; 3294 task = cnc_task_new (id, stmt, model_usage, col_types, params, need_last_insert_row); 3295 g_array_append_val (cnc->priv->waiting_tasks, task); 3296 if (cnc->priv->exec_times) { 3297 task->exec_timer = g_timer_new (); 3298 g_timer_stop (task->exec_timer); 3299 } 3300 3301 if (cnc->priv->waiting_tasks->len == 1) { 3302 /* execute statement now as there are no other ones to be executed */ 3303 GError *lerror = NULL; 3304 3305 cnc_task_lock (task); 3306 task->being_processed = TRUE; 3307 dump_exec_params (cnc, task->stmt, task->params); 3308 if (cnc->priv->exec_times) 3309 g_timer_start (task->exec_timer); 3310 if (cnc->priv->exec_slowdown && !cnc->priv->is_thread_wrapper) 3311 g_usleep (cnc->priv->exec_slowdown); 3312 3313 PROV_CLASS (cnc->priv->provider_obj)->statement_execute (cnc->priv->provider_obj, cnc, 3314 task->stmt, 3315 task->params, 3316 task->model_usage, 3317 task->col_types, 3318 &(task->last_insert_row), 3319 &(task->prov_task_id), 3320 (GdaServerProviderExecCallback) async_stmt_exec_cb, 3321 task, &lerror); 3322 if (lerror) { 3323 /* task execution failed => move it to completed tasks array */ 3324 gint i; 3325 gboolean is_completed; 3326 3327 task->error = lerror; 3328 task->being_processed = FALSE; 3329 if (cnc->priv->exec_times) 3330 g_timer_stop (task->exec_timer); 3331 i = get_task_index (cnc, id, &is_completed, FALSE); 3332 g_assert ((i >= 0) && !is_completed); 3333 g_array_remove_index (cnc->priv->waiting_tasks, i); 3334 g_array_append_val (cnc->priv->completed_tasks, task); 3335 } 3336 else 3337 update_meta_store_after_statement_exec (cnc, task->stmt, task->params); 3338 cnc_task_unlock (task); 3339 } 3340 3341 gda_connection_unlock ((GdaLockable*) cnc); 3342 g_object_unref ((GObject*) cnc); 3343 3344 return id; 3345 } 3346 3347 /** 3348 * gda_connection_async_fetch_result: 3349 * @cnc: a #GdaConnection 3350 * @task_id: a task ID returned by gda_connection_async_statement_execute() 3351 * @last_insert_row: (out) (transfer full) (allow-none): a place to store a new #GdaSet object which contains the values of the last inserted row, or %NULL 3352 * @error: a place to store errors, or %NULL 3353 * 3354 * Use this method to obtain the result of the execution of a statement which has been executed asynchronously by 3355 * calling gda_connection_async_statement_execute(). This function is non locking and will return %NULL (and no 3356 * error will be set) if the statement has not been executed yet. 3357 * 3358 * If the statement has been executed, this method returns the same value as gda_connection_statement_execute() 3359 * would have if the statement had been 3360 * executed synchronously. 3361 * 3362 * Returns: (transfer full): a #GObject, or %NULL if an error occurred 3363 * 3364 * Since: 4.2 3365 */ 3366 GObject * 3367 gda_connection_async_fetch_result (GdaConnection *cnc, guint task_id, GdaSet **last_insert_row, GError **error) 3368 { 3369 gint i; 3370 gboolean is_completed; 3371 GObject *obj = NULL; 3372 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 3373 g_return_val_if_fail (cnc->priv->provider_obj, NULL); 3374 3375 if (! gda_connection_trylock ((GdaLockable*) cnc)) { 3376 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_CANT_LOCK_ERROR, 3377 _("Can't obtain connection lock")); 3378 return NULL; 3379 } 3380 3381 /* if provider needs to be awaken, then do it now */ 3382 if (PROV_CLASS (cnc->priv->provider_obj)->handle_async) { 3383 if (! (PROV_CLASS (cnc->priv->provider_obj)->handle_async (cnc->priv->provider_obj, cnc, error))) { 3384 gda_connection_unlock ((GdaLockable*) cnc); 3385 return NULL; 3386 } 3387 } 3388 3389 i = get_task_index (cnc, task_id, &is_completed, FALSE); 3390 if (i < 0) { 3391 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_TASK_NOT_FOUND_ERROR, 3392 _("Can't find task %u"), task_id); 3393 } 3394 else if (is_completed) { 3395 /* task completed */ 3396 CncTask *task; 3397 task = CNC_TASK (g_array_index (cnc->priv->completed_tasks, gpointer, i)); 3398 g_array_remove_index (cnc->priv->completed_tasks, i); 3399 3400 cnc_task_lock (task); 3401 if (task->result) 3402 obj = g_object_ref (task->result); 3403 if (task->error) { 3404 g_propagate_error (error, task->error); 3405 task->error = NULL; 3406 } 3407 if (last_insert_row) { 3408 if (task->last_insert_row) 3409 *last_insert_row = g_object_ref (task->last_insert_row); 3410 else 3411 *last_insert_row = NULL; 3412 } 3413 cnc_task_unlock (task); 3414 cnc_task_free (task); 3415 } 3416 else { 3417 /* task not yet completed */ 3418 /* nothing to do */ 3419 } 3420 3421 gda_connection_unlock ((GdaLockable*) cnc); 3422 return obj; 3423 } 3424 3425 /** 3426 * gda_connection_async_cancel: 3427 * @cnc: a #GdaConnection 3428 * @task_id: a task ID returned by gda_connection_async_statement_execute() 3429 * @error: a place to store errors, or %NULL 3430 * 3431 * Requests that a task be cancelled. This operation may of may not have any effect 3432 * depending on the task's status, even if it returns %TRUE. If it returns %FALSE, 3433 * then the task has not been cancelled. 3434 * 3435 * Returns: TRUE if no error occurred 3436 * 3437 * Since: 4.2 3438 */ 3439 gboolean 3440 gda_connection_async_cancel (GdaConnection *cnc, guint task_id, GError **error) 3441 { 3442 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 3443 g_return_val_if_fail (cnc->priv->provider_obj, FALSE); 3444 3445 if (! gda_connection_trylock ((GdaLockable*) cnc)) { 3446 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_CANT_LOCK_ERROR, 3447 _("Can't obtain connection lock")); 3448 return FALSE; 3449 } 3450 3451 gint i; 3452 gboolean is_completed; 3453 gboolean retval = TRUE; 3454 i = get_task_index (cnc, task_id, &is_completed, FALSE); 3455 if ((i >= 0) && (!is_completed)) { 3456 CncTask *task; 3457 task = CNC_TASK (g_array_index (cnc->priv->waiting_tasks, gpointer, i)); 3458 if (task->being_processed) { 3459 if (PROV_CLASS (cnc->priv->provider_obj)->cancel) { 3460 retval = PROV_CLASS (cnc->priv->provider_obj)->cancel (cnc->priv->provider_obj, cnc, 3461 task->prov_task_id, error); 3462 if (retval) { 3463 /* cancellation may have succeeded => remove this task from the tasks to execute */ 3464 g_array_remove_index (cnc->priv->waiting_tasks, i); 3465 cnc_task_free (task); 3466 } 3467 } 3468 else { 3469 g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_METHOD_NON_IMPLEMENTED_ERROR, 3470 "%s", _("Provider does not support asynchronous server operation")); 3471 retval = FALSE; 3472 } 3473 task->being_processed = FALSE; 3474 if (cnc->priv->exec_times) 3475 g_timer_stop (task->exec_timer); 3476 } 3477 else { 3478 /* simply remove this task from the tasks to execute */ 3479 g_array_remove_index (cnc->priv->waiting_tasks, i); 3480 cnc_task_free (task); 3481 } 3482 } 3483 else if (i < 0) { 3484 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_TASK_NOT_FOUND_ERROR, 3485 _("Can't find task %u"), task_id); 3486 retval = FALSE; 3487 } 3488 3489 gda_connection_unlock ((GdaLockable*) cnc); 3490 return retval; 3491 } 3492 3493 /* 3494 * Wrapper which adds @... 3495 */ 3496 static GObject * 3497 gda_connection_statement_execute_v (GdaConnection *cnc, GdaStatement *stmt, GdaSet *params, 3498 GdaStatementModelUsage model_usage, GdaSet **last_inserted_row, GError **error, ...) 3499 { 3500 va_list ap; 3501 GObject *obj; 3502 GType *types, *req_types; 3503 GTimer *timer = NULL; 3504 va_start (ap, error); 3505 types = make_col_types_array (ap); 3506 va_end (ap); 3507 3508 g_object_ref ((GObject*) cnc); 3509 gda_connection_lock ((GdaLockable*) cnc); 3510 3511 _clear_connection_events (cnc); 3512 3513 if (last_inserted_row) 3514 *last_inserted_row = NULL; 3515 3516 if (!cnc->priv->provider_data) { 3517 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_CLOSED_ERROR, 3518 _("Connection is closed")); 3519 gda_connection_unlock (GDA_LOCKABLE (cnc)); 3520 g_object_unref ((GObject*) cnc); 3521 g_free (types); 3522 return NULL; 3523 } 3524 3525 req_types = merge_column_types (_gda_statement_get_requested_types (stmt), types); 3526 if (req_types) { 3527 g_free (types); 3528 types = req_types; 3529 req_types = NULL; 3530 } 3531 else if (_gda_statement_get_requested_types (stmt)) 3532 req_types = (GType*) _gda_statement_get_requested_types (stmt); 3533 3534 if (! (model_usage & GDA_STATEMENT_MODEL_RANDOM_ACCESS) && 3535 ! (model_usage & GDA_STATEMENT_MODEL_CURSOR_FORWARD)) 3536 model_usage |= GDA_STATEMENT_MODEL_RANDOM_ACCESS; 3537 3538 dump_exec_params (cnc, stmt, params); 3539 if (cnc->priv->exec_times) 3540 timer = g_timer_new (); 3541 if (cnc->priv->exec_slowdown && !cnc->priv->is_thread_wrapper) 3542 g_usleep (cnc->priv->exec_slowdown); 3543 3544 obj = PROV_CLASS (cnc->priv->provider_obj)->statement_execute (cnc->priv->provider_obj, cnc, stmt, params, 3545 model_usage, 3546 req_types ? req_types : types, 3547 last_inserted_row, 3548 NULL, NULL, NULL, error); 3549 if (timer) 3550 g_timer_stop (timer); 3551 g_free (types); 3552 3553 if (obj) { 3554 if (timer) 3555 add_exec_time_to_object (obj, timer); 3556 update_meta_store_after_statement_exec (cnc, stmt, params); 3557 if (GDA_IS_DATA_SELECT (obj) && (model_usage & GDA_STATEMENT_MODEL_OFFLINE) && 3558 ! gda_data_select_prepare_for_offline ((GdaDataSelect*) obj, error)) { 3559 g_object_unref (obj); 3560 obj = NULL; 3561 } 3562 } 3563 gda_connection_unlock ((GdaLockable*) cnc); 3564 g_object_unref ((GObject*) cnc); 3565 if (timer) 3566 g_timer_destroy (timer); 3567 3568 return obj; 3569 } 3570 3571 3572 /** 3573 * gda_connection_execute_select_command: 3574 * @cnc: an opened connection 3575 * @sql: a query statement that must begin with "SELECT" 3576 * @error: a place to store errors, or %NULL 3577 * 3578 * Execute a SQL SELECT command over an opened connection. 3579 * 3580 * Returns: (transfer full): a new #GdaDataModel if successful, %NULL otherwise 3581 * 3582 * Since: 4.2.3 3583 */ 3584 GdaDataModel * 3585 gda_connection_execute_select_command (GdaConnection *cnc, const gchar *sql, GError **error) 3586 { 3587 GdaStatement *stmt; 3588 GdaDataModel *model; 3589 3590 g_return_val_if_fail (sql != NULL 3591 || GDA_IS_CONNECTION (cnc) 3592 || !gda_connection_is_opened (cnc) 3593 || g_str_has_prefix (sql, "SELECT"), 3594 NULL); 3595 3596 g_mutex_lock (&parser_mutex); 3597 if (!internal_parser) 3598 internal_parser = gda_sql_parser_new (); 3599 g_mutex_unlock (&parser_mutex); 3600 3601 stmt = gda_sql_parser_parse_string (internal_parser, sql, NULL, error); 3602 if (!stmt) 3603 return NULL; 3604 model = gda_connection_statement_execute_select (cnc, stmt, NULL, error); 3605 g_object_unref (stmt); 3606 3607 return model; 3608 } 3609 3610 /** 3611 * gda_connection_execute_non_select_command: 3612 * @cnc: an opened connection 3613 * @sql: a query statement that must not begin with "SELECT" 3614 * @error: a place to store errors, or %NULL 3615 * 3616 * This is a convenience function to execute a SQL command over the opened connection. For the 3617 * returned value, see gda_connection_statement_execute_non_select()'s documentation. 3618 * 3619 * Returns: the number of rows affected or -1, or -2 3620 * 3621 * Since: 4.2.3 3622 */ 3623 gint 3624 gda_connection_execute_non_select_command (GdaConnection *cnc, const gchar *sql, GError **error) 3625 { 3626 GdaStatement *stmt; 3627 gint retval; 3628 3629 g_return_val_if_fail (sql != NULL 3630 || GDA_IS_CONNECTION (cnc) 3631 || !gda_connection_is_opened (cnc), -1); 3632 3633 g_mutex_lock (&parser_mutex); 3634 if (!internal_parser) 3635 internal_parser = gda_sql_parser_new (); 3636 g_mutex_unlock (&parser_mutex); 3637 3638 stmt = gda_sql_parser_parse_string (internal_parser, sql, NULL, error); 3639 if (!stmt) 3640 return -1; 3641 3642 retval = gda_connection_statement_execute_non_select (cnc, stmt, NULL, NULL, error); 3643 g_object_unref (stmt); 3644 return retval; 3645 } 3646 3647 /** 3648 * gda_connection_statement_execute: 3649 * @cnc: a #GdaConnection 3650 * @stmt: a #GdaStatement object 3651 * @params: (allow-none): a #GdaSet object (which can be obtained using gda_statement_get_parameters()), or %NULL 3652 * @model_usage: in the case where @stmt is a SELECT statement, specifies how the returned data model will be used 3653 * @last_insert_row: (out) (transfer full) (allow-none): a place to store a new #GdaSet object which contains the values of the last inserted row, or %NULL 3654 * @error: a place to store errors, or %NULL 3655 * 3656 * Executes @stmt. 3657 * 3658 * As @stmt can, by design (and if not abused), contain only one SQL statement, the 3659 * return object will either be: 3660 * <itemizedlist> 3661 * <listitem><para>a #GdaDataSelect object (which is also a #GdaDataModel) if @stmt is a SELECT statement 3662 * (usually a GDA_SQL_STATEMENT_SELECT, see #GdaSqlStatementType) 3663 * containing the results of the SELECT. The resulting data model is by default read only, but 3664 * modifications can be enabled, see the #GdaDataSelect's documentation for more information.</para></listitem> 3665 * <listitem><para>a #GdaSet for any other SQL statement which correctly executed. In this case 3666 * (if the provider supports it), then the #GdaSet may contain value holders named: 3667 * <itemizedlist> 3668 * <listitem><para>a (gint) #GdaHolder named "IMPACTED_ROWS"</para></listitem> 3669 * <listitem><para>a (GObject) #GdaHolder named "EVENT" which contains a #GdaConnectionEvent</para></listitem> 3670 * </itemizedlist></para></listitem> 3671 * </itemizedlist> 3672 * 3673 * If @last_insert_row is not %NULL and @stmt is an INSERT statement, then it will contain (if the 3674 * provider used by @cnc supports it) a new #GdaSet object composed of value holders named "+<column number>" 3675 * starting at column 0 which contain the actual inserted values. For example if a table is composed of an 'id' column 3676 * which is auto incremented and a 'name' column then the execution of a "INSERT INTO mytable (name) VALUES ('joe')" 3677 * query will return a #GdaSet with two holders: 3678 * <itemizedlist> 3679 * <listitem><para>one with the '+0' ID which may for example contain 1 (note that its "name" property should be "id")</para></listitem> 3680 * <listitem><para>one with the '+1' ID which will contain 'joe' (note that its "name" property should be "name")</para></listitem> 3681 * </itemizedlist> 3682 * 3683 * This method may fail with a %GDA_SERVER_PROVIDER_ERROR domain error (see the #GdaServerProviderError error codes). 3684 * 3685 * Note1: If @stmt is a SELECT statement which has some parameters and if @params is %NULL, then the statement can't 3686 * be executed and this method will return %NULL. 3687 * 3688 * Note2: If @stmt is a SELECT statement which has some parameters and if @params is not %NULL but contains some 3689 * invalid parameters, then the statement can't be executed and this method will return %NULL, unless the 3690 * @model_usage has the GDA_STATEMENT_MODEL_ALLOW_NOPARAM flag. 3691 * 3692 * Note3: If @stmt is a SELECT statement which has some parameters and if @params is not %NULL but contains some 3693 * invalid parameters and if @model_usage has the GDA_STATEMENT_MODEL_ALLOW_NOPARAM flag, then the returned 3694 * data model will contain no row but will have all the correct columns (even though some of the columns might 3695 * report as GDA_TYPE_NULL). In this case, if (after this method call) any of @params' parameters change 3696 * then the resulting data model will re-run itself, see the GdaDataSelect's 3697 * <link linkend="GdaDataSelect--auto-reset">auto-reset</link> property for more information. 3698 * 3699 * Note4: if @model_usage does not contain the GDA_STATEMENT_MODEL_RANDOM_ACCESS or 3700 * GDA_STATEMENT_MODEL_CURSOR_FORWARD flags, then the default will be to return a random access data model 3701 * 3702 * Note5: If @stmt is a SELECT statement which returns blob values (of type %GDA_TYPE_BLOB), then an implicit 3703 * transaction will have been started by the database provider, and it's up to the caller to close the transaction 3704 * (which will then be locked) once all the blob ressources have been 3705 * liberated (when the returned data model is destroyed). See the section about 3706 * <link linkend="gen:blobs">Binary large objects (BLOBs)</link> for more information. 3707 * 3708 * Also see the <link linkend="limitations">provider's limitations</link>, and the 3709 * <link linkend="data-select">Advanced GdaDataSelect usage</link> sections. 3710 * 3711 * Returns: (transfer full): a #GObject, or %NULL if an error occurred 3712 */ 3713 GObject * 3714 gda_connection_statement_execute (GdaConnection *cnc, GdaStatement *stmt, GdaSet *params, 3715 GdaStatementModelUsage model_usage, GdaSet **last_inserted_row, GError **error) 3716 { 3717 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 3718 g_return_val_if_fail (cnc->priv->provider_obj, NULL); 3719 g_return_val_if_fail (GDA_IS_STATEMENT (stmt), NULL); 3720 g_return_val_if_fail (PROV_CLASS (cnc->priv->provider_obj)->statement_execute, NULL); 3721 3722 if (last_inserted_row) 3723 *last_inserted_row = NULL; 3724 3725 return gda_connection_statement_execute_v (cnc, stmt, params, model_usage, last_inserted_row, error, -1); 3726 } 3727 3728 /** 3729 * gda_connection_statement_execute_non_select: 3730 * @cnc: a #GdaConnection object. 3731 * @stmt: a #GdaStatement object. 3732 * @params: (allow-none): a #GdaSet object (which can be obtained using gda_statement_get_parameters()), or %NULL 3733 * @last_insert_row: (out) (transfer full) (allow-none): a place to store a new #GdaSet object which contains the values of the last inserted row, or %NULL 3734 * @error: a place to store an error, or %NULL 3735 * 3736 * Executes a non-selection statement on the given connection. 3737 * 3738 * This function returns the number of rows affected by the execution of @stmt, or -1 3739 * if an error occurred, or -2 if the connection's provider does not return the number of rows affected. 3740 * 3741 * This function is just a convenience function around the gda_connection_statement_execute() 3742 * function. 3743 * See the documentation of the gda_connection_statement_execute() for information 3744 * about the @params list of parameters. 3745 * 3746 * See gda_connection_statement_execute() form more information about @last_insert_row. 3747 * 3748 * Returns: the number of rows affected (>=0) or -1 or -2 3749 */ 3750 gint 3751 gda_connection_statement_execute_non_select (GdaConnection *cnc, GdaStatement *stmt, 3752 GdaSet *params, GdaSet **last_insert_row, GError **error) 3753 { 3754 GdaSet *set; 3755 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), -1); 3756 g_return_val_if_fail (cnc->priv->provider_obj, -1); 3757 g_return_val_if_fail (GDA_IS_STATEMENT (stmt), -1); 3758 g_return_val_if_fail (PROV_CLASS (cnc->priv->provider_obj)->statement_execute, -1); 3759 3760 if ((gda_statement_get_statement_type (stmt) == GDA_SQL_STATEMENT_SELECT) || 3761 (gda_statement_get_statement_type (stmt) == GDA_SQL_STATEMENT_COMPOUND)) { 3762 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_STATEMENT_TYPE_ERROR, 3763 "%s", _("Statement is a selection statement")); 3764 return -1; 3765 } 3766 3767 if (last_insert_row) 3768 *last_insert_row = NULL; 3769 3770 set = (GdaSet *) gda_connection_statement_execute_v (cnc, stmt, params, 3771 GDA_STATEMENT_MODEL_RANDOM_ACCESS, last_insert_row, 3772 error, -1); 3773 if (!set) 3774 return -1; 3775 3776 if (!GDA_IS_SET (set)) { 3777 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_STATEMENT_TYPE_ERROR, 3778 "%s", _("Statement is a selection statement")); 3779 g_object_unref (set); 3780 return -1; 3781 } 3782 else { 3783 GdaHolder *h; 3784 gint retval = -2; 3785 3786 h = gda_set_get_holder (set, "IMPACTED_ROWS"); 3787 if (h) { 3788 const GValue *value; 3789 value = gda_holder_get_value (h); 3790 if (value && (G_VALUE_TYPE (value) == G_TYPE_INT)) 3791 retval = g_value_get_int (value); 3792 } 3793 g_object_unref (set); 3794 return retval; 3795 } 3796 } 3797 3798 /** 3799 * gda_connection_statement_execute_select: 3800 * @cnc: a #GdaConnection object. 3801 * @stmt: a #GdaStatement object. 3802 * @params: (allow-none): a #GdaSet object (which can be obtained using gda_statement_get_parameters()), or %NULL 3803 * @error: a place to store an error, or %NULL 3804 * 3805 * Executes a selection command on the given connection. 3806 * 3807 * This function returns a #GdaDataModel resulting from the SELECT statement, or %NULL 3808 * if an error occurred. 3809 * 3810 * This function is just a convenience function around the gda_connection_statement_execute() 3811 * function. 3812 * 3813 * See the documentation of the gda_connection_statement_execute() for information 3814 * about the @params list of parameters. 3815 * 3816 * Returns: (transfer full): a #GdaDataModel containing the data returned by the 3817 * data source, or %NULL if an error occurred 3818 */ 3819 GdaDataModel * 3820 gda_connection_statement_execute_select (GdaConnection *cnc, GdaStatement *stmt, 3821 GdaSet *params, GError **error) 3822 { 3823 GdaDataModel *model; 3824 3825 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 3826 g_return_val_if_fail (cnc->priv->provider_obj, NULL); 3827 g_return_val_if_fail (GDA_IS_STATEMENT (stmt), NULL); 3828 g_return_val_if_fail (PROV_CLASS (cnc->priv->provider_obj)->statement_execute, NULL); 3829 3830 model = (GdaDataModel *) gda_connection_statement_execute_v (cnc, stmt, params, 3831 GDA_STATEMENT_MODEL_RANDOM_ACCESS, NULL, 3832 error, -1); 3833 if (model && !GDA_IS_DATA_MODEL (model)) { 3834 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_STATEMENT_TYPE_ERROR, 3835 "%s", _("Statement is not a selection statement")); 3836 g_object_unref (model); 3837 model = NULL; 3838 } 3839 return model; 3840 } 3841 3842 /** 3843 * gda_connection_statement_execute_select_fullv: (skip) 3844 * @cnc: a #GdaConnection object. 3845 * @stmt: a #GdaStatement object. 3846 * @params: (allow-none): a #GdaSet object (which can be obtained using gda_statement_get_parameters()), or %NULL 3847 * @model_usage: specifies how the returned data model will be used as a #GdaStatementModelUsage enum 3848 * @error: a place to store an error, or %NULL 3849 * @...: a (-1 terminated) list of (column number, GType) specifying for each column mentioned the GType 3850 * of the column in the returned #GdaDataModel. 3851 * 3852 * Executes a selection command on the given connection. 3853 * 3854 * This function returns a #GdaDataModel resulting from the SELECT statement, or %NULL 3855 * if an error occurred. 3856 * 3857 * This function is just a convenience function around the gda_connection_statement_execute() 3858 * function. 3859 * 3860 * See the documentation of the gda_connection_statement_execute() for information 3861 * about the @params list of parameters. 3862 * 3863 * Returns: (transfer full): a #GdaDataModel containing the data returned by the 3864 * data source, or %NULL if an error occurred 3865 */ 3866 GdaDataModel * 3867 gda_connection_statement_execute_select_fullv (GdaConnection *cnc, GdaStatement *stmt, 3868 GdaSet *params, GdaStatementModelUsage model_usage, 3869 GError **error, ...) 3870 { 3871 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 3872 g_return_val_if_fail (cnc->priv->provider_obj, NULL); 3873 g_return_val_if_fail (GDA_IS_STATEMENT (stmt), NULL); 3874 g_return_val_if_fail (PROV_CLASS (cnc->priv->provider_obj)->statement_execute, NULL); 3875 3876 va_list ap; 3877 GdaDataModel *model; 3878 GType *types, *req_types; 3879 GTimer *timer = NULL; 3880 3881 va_start (ap, error); 3882 types = make_col_types_array (ap); 3883 va_end (ap); 3884 3885 g_object_ref ((GObject*) cnc); 3886 gda_connection_lock ((GdaLockable*) cnc); 3887 3888 _clear_connection_events (cnc); 3889 3890 if (!cnc->priv->provider_data) { 3891 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_CLOSED_ERROR, 3892 _("Connection is closed")); 3893 gda_connection_unlock (GDA_LOCKABLE (cnc)); 3894 g_object_unref ((GObject*) cnc); 3895 g_free (types); 3896 return NULL; 3897 } 3898 3899 req_types = merge_column_types (_gda_statement_get_requested_types (stmt), types); 3900 if (req_types) { 3901 g_free (types); 3902 types = req_types; 3903 req_types = NULL; 3904 } 3905 else if (_gda_statement_get_requested_types (stmt)) 3906 req_types = (GType*) _gda_statement_get_requested_types (stmt); 3907 3908 if (! (model_usage & GDA_STATEMENT_MODEL_RANDOM_ACCESS) && 3909 ! (model_usage & GDA_STATEMENT_MODEL_CURSOR_FORWARD)) 3910 model_usage |= GDA_STATEMENT_MODEL_RANDOM_ACCESS; 3911 3912 dump_exec_params (cnc, stmt, params); 3913 if (cnc->priv->exec_times) 3914 timer = g_timer_new (); 3915 if (cnc->priv->exec_slowdown && !cnc->priv->is_thread_wrapper) 3916 g_usleep (cnc->priv->exec_slowdown); 3917 3918 model = (GdaDataModel *) PROV_CLASS (cnc->priv->provider_obj)->statement_execute (cnc->priv->provider_obj, 3919 cnc, stmt, params, model_usage, 3920 req_types ? req_types : types, 3921 NULL, NULL, 3922 NULL, NULL, error); 3923 if (timer) 3924 g_timer_stop (timer); 3925 gda_connection_unlock ((GdaLockable*) cnc); 3926 g_object_unref ((GObject*) cnc); 3927 g_free (types); 3928 if (model && timer) 3929 add_exec_time_to_object ((GObject*) model, timer); 3930 if (timer) 3931 g_timer_destroy (timer); 3932 if (model) { 3933 if (GDA_IS_DATA_SELECT (model) && (model_usage & GDA_STATEMENT_MODEL_OFFLINE) && 3934 ! gda_data_select_prepare_for_offline ((GdaDataSelect*) model, error)) { 3935 g_object_unref (model); 3936 model = NULL; 3937 } 3938 else if (!GDA_IS_DATA_MODEL (model)) { 3939 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_STATEMENT_TYPE_ERROR, 3940 "%s", _("Statement is not a selection statement")); 3941 g_object_unref (model); 3942 model = NULL; 3943 update_meta_store_after_statement_exec (cnc, stmt, params); 3944 } 3945 } 3946 return model; 3947 } 3948 3949 /** 3950 * gda_connection_statement_execute_select_full: 3951 * @cnc: a #GdaConnection object. 3952 * @stmt: a #GdaStatement object. 3953 * @params: (allow-none): a #GdaSet object (which can be obtained using gda_statement_get_parameters()), or %NULL 3954 * @model_usage: specifies how the returned data model will be used as a #GdaStatementModelUsage enum 3955 * @col_types: (array) (allow-none): an array of GType to request each returned #GdaDataModel's column's GType, terminated with the G_TYPE_NONE 3956 * value. Any value left to 0 will make the database provider determine the real GType. @col_types can also be %NULL if no 3957 * column type is specified. 3958 * @error: a place to store an error, or %NULL 3959 * 3960 * Executes a selection command on the given connection. 3961 * 3962 * This function returns a #GdaDataModel resulting from the SELECT statement, or %NULL 3963 * if an error occurred. 3964 * 3965 * This function is just a convenience function around the gda_connection_statement_execute() 3966 * function. 3967 * 3968 * See the documentation of the gda_connection_statement_execute() for information 3969 * about the @params list of parameters. 3970 * 3971 * Returns: (transfer full): a #GdaDataModel containing the data returned by the 3972 * data source, or %NULL if an error occurred 3973 */ 3974 GdaDataModel * 3975 gda_connection_statement_execute_select_full (GdaConnection *cnc, GdaStatement *stmt, 3976 GdaSet *params, GdaStatementModelUsage model_usage, 3977 GType *col_types, GError **error) 3978 { 3979 GdaDataModel *model; 3980 GTimer *timer = NULL; 3981 3982 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 3983 g_return_val_if_fail (cnc->priv->provider_obj, NULL); 3984 g_return_val_if_fail (GDA_IS_STATEMENT (stmt), NULL); 3985 g_return_val_if_fail (PROV_CLASS (cnc->priv->provider_obj)->statement_execute, NULL); 3986 3987 g_object_ref ((GObject*) cnc); 3988 gda_connection_lock ((GdaLockable*) cnc); 3989 3990 if (!cnc->priv->provider_data) { 3991 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_CLOSED_ERROR, 3992 _("Connection is closed")); 3993 gda_connection_unlock (GDA_LOCKABLE (cnc)); 3994 g_object_unref ((GObject*) cnc); 3995 return NULL; 3996 } 3997 3998 GType *req_types; 3999 req_types = merge_column_types (_gda_statement_get_requested_types (stmt), col_types); 4000 if (!req_types && !col_types) 4001 col_types = (GType*) _gda_statement_get_requested_types (stmt); 4002 4003 if (! (model_usage & GDA_STATEMENT_MODEL_RANDOM_ACCESS) && 4004 ! (model_usage & GDA_STATEMENT_MODEL_CURSOR_FORWARD)) 4005 model_usage |= GDA_STATEMENT_MODEL_RANDOM_ACCESS; 4006 4007 dump_exec_params (cnc, stmt, params); 4008 if (cnc->priv->exec_times) 4009 timer = g_timer_new (); 4010 if (cnc->priv->exec_slowdown && !cnc->priv->is_thread_wrapper) 4011 g_usleep (cnc->priv->exec_slowdown); 4012 4013 model = (GdaDataModel *) PROV_CLASS (cnc->priv->provider_obj)->statement_execute (cnc->priv->provider_obj, 4014 cnc, stmt, params, 4015 model_usage, 4016 req_types ? req_types : col_types, 4017 NULL, 4018 NULL, NULL, NULL, error); 4019 if (timer) 4020 g_timer_stop (timer); 4021 g_free (req_types); 4022 gda_connection_unlock ((GdaLockable*) cnc); 4023 g_object_unref ((GObject*) cnc); 4024 4025 if (model && timer) 4026 add_exec_time_to_object ((GObject*) model, timer); 4027 if (model) { 4028 if (GDA_IS_DATA_SELECT (model) && (model_usage & GDA_STATEMENT_MODEL_OFFLINE) && 4029 ! gda_data_select_prepare_for_offline ((GdaDataSelect*) model, error)) { 4030 g_object_unref (model); 4031 model = NULL; 4032 } 4033 else if (!GDA_IS_DATA_MODEL (model)) { 4034 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_STATEMENT_TYPE_ERROR, 4035 "%s", _("Statement is not a selection statement")); 4036 g_object_unref (model); 4037 model = NULL; 4038 update_meta_store_after_statement_exec (cnc, stmt, params); 4039 } 4040 } 4041 if (timer) 4042 g_timer_destroy (timer); 4043 return model; 4044 } 4045 4046 /** 4047 * gda_connection_repetitive_statement_execute: 4048 * @cnc: a #GdaConnection 4049 * @rstmt: a #GdaRepetitiveStatement object 4050 * @model_usage: specifies how the returned data model will be used as a #GdaStatementModelUsage enum 4051 * @col_types: (array) (allow-none): an array of GType to request each returned GdaDataModel's column's GType, see gda_connection_statement_execute_select_full() for more information 4052 * @stop_on_error: set to TRUE if the method has to stop on the first error. 4053 * @error: a place to store errors, or %NULL 4054 * 4055 * Executes the statement upon which @rstmt is built. Note that as several statements can actually be executed by this 4056 * method, it is recommended to be within a transaction. 4057 * 4058 * If @error is not %NULL and @stop_on_error is %FALSE, then it may contain the last error which occurred. 4059 * 4060 * Returns: (transfer full) (element-type GObject): a new list of #GObject pointers (see gda_connection_statement_execute() for more information about what they 4061 * represent), one for each actual execution of the statement upon which @rstmt is built. If @stop_on_error is %FALSE, then 4062 * the list may contain some %NULL pointers which refer to statements which failed to execute. 4063 * 4064 * Since: 4.2 4065 */ 4066 GSList * 4067 gda_connection_repetitive_statement_execute (GdaConnection *cnc, GdaRepetitiveStatement *rstmt, 4068 GdaStatementModelUsage model_usage, GType *col_types, 4069 gboolean stop_on_error, GError **error) 4070 { 4071 GSList *sets_list, *list; 4072 GSList *retlist = NULL; 4073 GdaStatement *stmt; 4074 4075 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 4076 g_return_val_if_fail (cnc->priv->provider_obj, NULL); 4077 g_return_val_if_fail (GDA_IS_REPETITIVE_STATEMENT (rstmt), NULL); 4078 g_return_val_if_fail (PROV_CLASS (cnc->priv->provider_obj)->statement_execute, NULL); 4079 4080 g_object_get (rstmt, "statement", &stmt, NULL); 4081 g_return_val_if_fail (stmt, NULL); 4082 4083 g_object_ref ((GObject*) cnc); 4084 gda_connection_lock ((GdaLockable*) cnc); 4085 4086 if (!cnc->priv->provider_data) { 4087 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_CLOSED_ERROR, 4088 _("Connection is closed")); 4089 gda_connection_unlock (GDA_LOCKABLE (cnc)); 4090 g_object_unref ((GObject*) cnc); 4091 return NULL; 4092 } 4093 4094 GType *req_types; 4095 req_types = merge_column_types (_gda_statement_get_requested_types (stmt), col_types); 4096 if (!req_types && !col_types) 4097 col_types = (GType*) _gda_statement_get_requested_types (stmt); 4098 4099 if (! (model_usage & GDA_STATEMENT_MODEL_RANDOM_ACCESS) && 4100 ! (model_usage & GDA_STATEMENT_MODEL_CURSOR_FORWARD)) 4101 model_usage |= GDA_STATEMENT_MODEL_RANDOM_ACCESS; 4102 4103 sets_list = gda_repetitive_statement_get_all_sets (rstmt); 4104 for (list = sets_list; list; list = list->next) { 4105 GObject *obj; 4106 GError *lerror = NULL; 4107 GTimer *timer = NULL; 4108 4109 dump_exec_params (cnc, stmt, (GdaSet*) list->data); 4110 if (cnc->priv->exec_times) 4111 timer = g_timer_new (); 4112 if (cnc->priv->exec_slowdown && !cnc->priv->is_thread_wrapper) 4113 g_usleep (cnc->priv->exec_slowdown); 4114 4115 obj = PROV_CLASS (cnc->priv->provider_obj)->statement_execute (cnc->priv->provider_obj, cnc, stmt, 4116 GDA_SET (list->data), 4117 model_usage, 4118 req_types ? req_types : col_types, 4119 NULL, 4120 NULL, NULL, NULL, &lerror); 4121 if (timer) 4122 g_timer_stop (timer); 4123 if (!obj) { 4124 if (stop_on_error) { 4125 if (timer) 4126 g_timer_destroy (timer); 4127 break; 4128 } 4129 else { 4130 if (error && *error) { 4131 g_error_free (*error); 4132 *error = NULL; 4133 } 4134 g_propagate_error (error, lerror); 4135 } 4136 } 4137 else { 4138 if (timer) 4139 add_exec_time_to_object (obj, timer); 4140 update_meta_store_after_statement_exec (cnc, stmt, (GdaSet*) list->data); 4141 4142 if (GDA_IS_DATA_SELECT (obj) && (model_usage & GDA_STATEMENT_MODEL_OFFLINE) && 4143 ! gda_data_select_prepare_for_offline ((GdaDataSelect*) obj, error)) { 4144 g_object_unref (obj); 4145 obj = NULL; 4146 } 4147 4148 if (obj) 4149 retlist = g_slist_prepend (retlist, obj); 4150 } 4151 if (timer) 4152 g_timer_destroy (timer); 4153 } 4154 g_slist_free (sets_list); 4155 g_free (req_types); 4156 4157 gda_connection_unlock ((GdaLockable*) cnc); 4158 g_object_unref ((GObject*) cnc); 4159 g_object_unref (stmt); 4160 4161 return g_slist_reverse (retlist); 4162 } 4163 4164 /* 4165 * Forces the GdaTransactionStatus. This is reserved to connections which are thread wrappers 4166 * 4167 * @trans_status may be NULL 4168 * if @trans_status is not NULL, then its ref count is increased. 4169 */ 4170 void 4171 _gda_connection_force_transaction_status (GdaConnection *cnc, GdaConnection *wrapped_cnc) 4172 { 4173 g_assert (cnc->priv->is_thread_wrapper); 4174 if (cnc->priv->trans_status) 4175 g_object_unref (cnc->priv->trans_status); 4176 4177 cnc->priv->trans_status = wrapped_cnc->priv->trans_status; 4178 if (cnc->priv->trans_status) 4179 g_object_ref (cnc->priv->trans_status); 4180 4181 #ifdef GDA_DEBUG_signal 4182 g_print (">> 'TRANSACTION_STATUS_CHANGED' from %s\n", __FUNCTION__); 4183 #endif 4184 g_signal_emit (G_OBJECT (cnc), gda_connection_signals[TRANSACTION_STATUS_CHANGED], 0); 4185 #ifdef GDA_DEBUG_signal 4186 g_print ("<< 'TRANSACTION_STATUS_CHANGED' from %s\n", __FUNCTION__); 4187 #endif 4188 4189 #ifdef GDA_DEBUG_NO 4190 if (cnc->priv->trans_status) 4191 gda_transaction_status_dump (cnc->priv->trans_status, 5); 4192 #endif 4193 } 4194 4195 /** 4196 * gda_connection_begin_transaction: 4197 * @cnc: a #GdaConnection object. 4198 * @name: (allow-none): the name of the transation to start, or %NULL 4199 * @level: the requested transaction level (%GDA_TRANSACTION_ISOLATION_UNKNOWN if not specified) 4200 * @error: a place to store errors, or %NULL 4201 * 4202 * Starts a transaction on the data source, identified by the 4203 * @name parameter. 4204 * 4205 * Before starting a transaction, you can check whether the underlying 4206 * provider does support transactions or not by using the 4207 * gda_connection_supports_feature() function. 4208 * 4209 * Returns: %TRUE if the transaction was started successfully, %FALSE 4210 * otherwise. 4211 */ 4212 gboolean 4213 gda_connection_begin_transaction (GdaConnection *cnc, const gchar *name, GdaTransactionIsolation level, 4214 GError **error) 4215 { 4216 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 4217 g_return_val_if_fail (cnc->priv->provider_obj, FALSE); 4218 4219 if (PROV_CLASS (cnc->priv->provider_obj)->begin_transaction) 4220 return PROV_CLASS (cnc->priv->provider_obj)->begin_transaction (cnc->priv->provider_obj, cnc, name, level, error); 4221 else 4222 return FALSE; 4223 } 4224 4225 /** 4226 * gda_connection_commit_transaction: 4227 * @cnc: a #GdaConnection object. 4228 * @name: (allow-none): the name of the transation to commit, or %NULL 4229 * @error: a place to store errors, or %NULL 4230 * 4231 * Commits the given transaction to the backend database. You need to call 4232 * gda_connection_begin_transaction() first. 4233 * 4234 * Returns: %TRUE if the transaction was finished successfully, 4235 * %FALSE otherwise. 4236 */ 4237 gboolean 4238 gda_connection_commit_transaction (GdaConnection *cnc, const gchar *name, GError **error) 4239 { 4240 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 4241 g_return_val_if_fail (cnc->priv->provider_obj, FALSE); 4242 4243 if (PROV_CLASS (cnc->priv->provider_obj)->commit_transaction) 4244 return PROV_CLASS (cnc->priv->provider_obj)->commit_transaction (cnc->priv->provider_obj, cnc, name, error); 4245 else 4246 return FALSE; 4247 } 4248 4249 /** 4250 * gda_connection_rollback_transaction: 4251 * @cnc: a #GdaConnection object. 4252 * @name: (allow-none): the name of the transation to commit, or %NULL 4253 * @error: a place to store errors, or %NULL 4254 * 4255 * Rollbacks the given transaction. This means that all changes 4256 * made to the underlying data source since the last call to 4257 * #gda_connection_begin_transaction() or #gda_connection_commit_transaction() 4258 * will be discarded. 4259 * 4260 * Returns: %TRUE if the operation was successful, %FALSE otherwise. 4261 */ 4262 gboolean 4263 gda_connection_rollback_transaction (GdaConnection *cnc, const gchar *name, GError **error) 4264 { 4265 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 4266 g_return_val_if_fail (cnc->priv->provider_obj, FALSE); 4267 4268 if (PROV_CLASS (cnc->priv->provider_obj)->rollback_transaction) 4269 return PROV_CLASS (cnc->priv->provider_obj)->rollback_transaction (cnc->priv->provider_obj, cnc, name, error); 4270 else 4271 return FALSE; 4272 } 4273 4274 /** 4275 * gda_connection_add_savepoint: 4276 * @cnc: a #GdaConnection object 4277 * @name: (allow-none): name of the savepoint to add 4278 * @error: a place to store errors or %NULL 4279 * 4280 * Adds a SAVEPOINT named @name. 4281 * 4282 * Returns: TRUE if no error occurred 4283 */ 4284 gboolean 4285 gda_connection_add_savepoint (GdaConnection *cnc, const gchar *name, GError **error) 4286 { 4287 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 4288 g_return_val_if_fail (cnc->priv->provider_obj, FALSE); 4289 4290 if (PROV_CLASS (cnc->priv->provider_obj)->add_savepoint) 4291 return PROV_CLASS (cnc->priv->provider_obj)->add_savepoint (cnc->priv->provider_obj, cnc, name, error); 4292 else 4293 return FALSE; 4294 } 4295 4296 /** 4297 * gda_connection_rollback_savepoint: 4298 * @cnc: a #GdaConnection object 4299 * @name: (allow-none): name of the savepoint to rollback to 4300 * @error: a place to store errors or %NULL 4301 * 4302 * Rollback all the modifications made after the SAVEPOINT named @name. 4303 * 4304 * Returns: TRUE if no error occurred 4305 */ 4306 gboolean 4307 gda_connection_rollback_savepoint (GdaConnection *cnc, const gchar *name, GError **error) 4308 { 4309 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 4310 g_return_val_if_fail (cnc->priv->provider_obj, FALSE); 4311 4312 if (PROV_CLASS (cnc->priv->provider_obj)->rollback_savepoint) 4313 return PROV_CLASS (cnc->priv->provider_obj)->rollback_savepoint (cnc->priv->provider_obj, cnc, name, error); 4314 else 4315 return FALSE; 4316 } 4317 4318 /** 4319 * gda_connection_delete_savepoint: 4320 * @cnc: a #GdaConnection object 4321 * @name: (allow-none): name of the savepoint to delete 4322 * @error: a place to store errors or %NULL 4323 * 4324 * Delete the SAVEPOINT named @name when not used anymore. 4325 * 4326 * Returns: TRUE if no error occurred 4327 */ 4328 gboolean 4329 gda_connection_delete_savepoint (GdaConnection *cnc, const gchar *name, GError **error) 4330 { 4331 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 4332 g_return_val_if_fail (cnc->priv->provider_obj, FALSE); 4333 4334 if (PROV_CLASS (cnc->priv->provider_obj)->delete_savepoint) 4335 return PROV_CLASS (cnc->priv->provider_obj)->delete_savepoint (cnc->priv->provider_obj, cnc, name, error); 4336 else 4337 return FALSE; 4338 } 4339 4340 /** 4341 * gda_connection_get_transaction_status: 4342 * @cnc: a #GdaConnection object 4343 * 4344 * Get the status of @cnc regarding transactions. The returned object should not be modified 4345 * or destroyed; however it may be modified or destroyed by the connection itself. 4346 * 4347 * If %NULL is returned, then no transaction has been associated with @cnc 4348 * 4349 * Returns: (transfer none): a #GdaTransactionStatus object, or %NULL 4350 */ 4351 GdaTransactionStatus * 4352 gda_connection_get_transaction_status (GdaConnection *cnc) 4353 { 4354 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 4355 4356 return cnc->priv->trans_status; 4357 } 4358 4359 /** 4360 * gda_connection_supports_feature: 4361 * @cnc: a #GdaConnection object. 4362 * @feature: feature to ask for. 4363 * 4364 * Asks the underlying provider for if a specific feature is supported. 4365 * 4366 * Returns: %TRUE if the provider supports it, %FALSE if not. 4367 */ 4368 gboolean 4369 gda_connection_supports_feature (GdaConnection *cnc, GdaConnectionFeature feature) 4370 { 4371 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 4372 g_return_val_if_fail (cnc->priv->provider_obj, FALSE); 4373 4374 if (feature == GDA_CONNECTION_FEATURE_ASYNC_EXEC) 4375 return PROV_CLASS (cnc->priv->provider_obj)->handle_async ? TRUE : FALSE; 4376 return gda_server_provider_supports_feature (cnc->priv->provider_obj, cnc, feature); 4377 } 4378 4379 /* builds a list of #GdaMetaContext contexts templates: contexts which have a non NULL table_name, 4380 * and empty or partially filled column names and values specifications */ 4381 static GSList * 4382 build_upstream_context_templates (GdaMetaStore *store, GdaMetaContext *context, GSList *elist, GError **error) 4383 { 4384 GSList *depend_on_contexts; 4385 GSList *retlist; 4386 GError *lerror = NULL; 4387 depend_on_contexts = _gda_meta_store_schema_get_upstream_contexts (store, context, &lerror); 4388 if (!depend_on_contexts) { 4389 if (lerror) { 4390 /* error while getting dependencies */ 4391 g_propagate_error (error, lerror); 4392 return FALSE; 4393 } 4394 return elist; 4395 } 4396 else { 4397 GSList *list; 4398 retlist = NULL; 4399 for (list = depend_on_contexts; list; list = list->next) 4400 retlist = build_upstream_context_templates (store, (GdaMetaContext *) list->data, 4401 retlist, error); 4402 list = g_slist_concat (depend_on_contexts, elist); 4403 retlist = g_slist_concat (retlist, list); 4404 return retlist; 4405 } 4406 } 4407 4408 4409 /* builds a list of #GdaMetaContext contexts templates: contexts which have a non NULL table_name, 4410 * and empty or partially filled column names and values specifications */ 4411 static GSList * 4412 build_downstream_context_templates (GdaMetaStore *store, GdaMetaContext *context, GSList *elist, GError **error) 4413 { 4414 GSList *depending_contexts; 4415 GSList *retlist; 4416 GError *lerror = NULL; 4417 depending_contexts = _gda_meta_store_schema_get_downstream_contexts (store, context, &lerror); 4418 if (!depending_contexts) { 4419 if (lerror) { 4420 /* error while getting dependencies */ 4421 g_propagate_error (error, lerror); 4422 return NULL; 4423 } 4424 return elist; 4425 } 4426 else { 4427 GSList *list; 4428 retlist = NULL; 4429 for (list = depending_contexts; list; list = list->next) 4430 retlist = build_downstream_context_templates (store, (GdaMetaContext *) list->data, 4431 retlist, error); 4432 list = g_slist_concat (elist, depending_contexts); 4433 retlist = g_slist_concat (list, retlist); 4434 return retlist; 4435 } 4436 } 4437 4438 static gchar * 4439 meta_context_stringify (GdaMetaContext *context) 4440 { 4441 gint i; 4442 gchar *str; 4443 GString *string = g_string_new (""); 4444 4445 for (i = 0; i < context->size; i++) { 4446 if (i > 0) 4447 g_string_append_c (string, ' '); 4448 str = gda_value_stringify (context->column_values[i]); 4449 g_string_append_printf (string, " [%s => %s]", context->column_names[i], str); 4450 g_free (str); 4451 } 4452 if (i == 0) 4453 g_string_append (string, "no constraint in context"); 4454 str = string->str; 4455 g_string_free (string, FALSE); 4456 return str; 4457 } 4458 4459 /*#define GDA_DEBUG_META_STORE_UPDATE*/ 4460 #ifdef GDA_DEBUG_META_STORE_UPDATE 4461 static void 4462 meta_context_dump (GdaMetaContext *context) 4463 { 4464 gchar *str; 4465 str = meta_context_stringify (context); 4466 g_print ("GdaMetaContext for table %s: %s\n", context->table_name, str); 4467 g_free (str); 4468 } 4469 #endif 4470 4471 /* 4472 * 4473 */ 4474 static gint 4475 check_parameters (GdaMetaContext *context, GError **error, gint nb, ...) 4476 { 4477 #define MAX_PARAMS 10 4478 gint i; 4479 va_list ap; 4480 gint retval = -1; 4481 GValue **pvalue; 4482 struct { 4483 GValue **pvalue; 4484 GType type; 4485 } spec_array [MAX_PARAMS]; 4486 gint nb_params = 0; 4487 4488 va_start (ap, nb); 4489 /* make a list of all the GValue pointers */ 4490 for (pvalue = va_arg (ap, GValue **); pvalue; pvalue = va_arg (ap, GValue **), nb_params++) { 4491 g_assert (nb_params < MAX_PARAMS); /* hard limit, recompile to change it (should never be needed) */ 4492 spec_array[nb_params].pvalue = pvalue; 4493 spec_array[nb_params].type = va_arg (ap, GType); 4494 } 4495 4496 /* test against each test case */ 4497 for (i = 0; i < nb; i++) { 4498 gchar *pname; 4499 gboolean allfound = TRUE; 4500 gint j; 4501 for (j = 0; j < nb_params; j++) 4502 *(spec_array[j].pvalue) = NULL; 4503 4504 for (pname = va_arg (ap, gchar*); pname; pname = va_arg (ap, gchar*)) { 4505 gint j; 4506 pvalue = va_arg (ap, GValue **); 4507 *pvalue = NULL; 4508 for (j = 0; allfound && (j < context->size); j++) { 4509 if (!strcmp (context->column_names[j], pname)) { 4510 *pvalue = context->column_values[j]; 4511 break; 4512 } 4513 } 4514 if (j == context->size) 4515 allfound = FALSE; 4516 } 4517 if (allfound) { 4518 retval = i; 4519 break; 4520 } 4521 } 4522 va_end (ap); 4523 4524 if (retval >= 0) { 4525 gint j; 4526 for (j = 0; j < nb_params; j++) { 4527 GValue *v = *(spec_array[j].pvalue); 4528 if (v && (gda_value_is_null (v) || (G_VALUE_TYPE (v) != spec_array[j].type))) { 4529 g_set_error (error, GDA_CONNECTION_ERROR, 4530 GDA_CONNECTION_META_DATA_CONTEXT_ERROR, 4531 "%s", _("Invalid argument")); 4532 retval = -1; 4533 } 4534 } 4535 } 4536 else { 4537 gchar *str; 4538 str = meta_context_stringify (context); 4539 g_set_error (error, GDA_CONNECTION_ERROR, 4540 GDA_CONNECTION_META_DATA_CONTEXT_ERROR, 4541 _("Missing or wrong arguments for table '%s': %s"), 4542 context->table_name, str); 4543 g_free (str); 4544 } 4545 4546 /*g_print ("Check arguments context => found %d\n", retval);*/ 4547 return retval; 4548 } 4549 4550 static gboolean 4551 local_meta_update (GdaServerProvider *provider, GdaConnection *cnc, GdaMetaContext *context, GError **error) 4552 { 4553 const gchar *tname = context->table_name; 4554 GdaMetaStore *store; 4555 gboolean retval; 4556 4557 const GValue *catalog = NULL; 4558 const GValue *schema = NULL; 4559 const GValue *name = NULL; 4560 gint i; 4561 4562 4563 #ifdef GDA_DEBUG_META_STORE_UPDATE 4564 g_print ("%s() => ", __FUNCTION__); 4565 meta_context_dump (context); 4566 #endif 4567 4568 if (*tname != '_') 4569 return TRUE; 4570 tname ++; 4571 4572 store = gda_connection_get_meta_store (cnc); 4573 switch (*tname) { 4574 case 'b': { 4575 /* _builtin_data_types, params: 4576 * - none 4577 */ 4578 ASSERT_TABLE_NAME (tname, "builtin_data_types"); 4579 if (!PROV_CLASS (provider)->meta_funcs._btypes) { 4580 WARN_METHOD_NOT_IMPLEMENTED (provider, "_btypes"); 4581 break; 4582 } 4583 retval = PROV_CLASS (provider)->meta_funcs._btypes (provider, cnc, store, context, error); 4584 WARN_META_UPDATE_FAILURE (retval, "_btypes"); 4585 return retval; 4586 } 4587 4588 case 'c': 4589 if ((tname[1] == 'o') && (tname[2] == 'l') && (tname[3] == 'u')) { 4590 /* _columns, params: 4591 * -0- @table_catalog, @table_schema, @table_name 4592 * -1- @character_set_catalog, @character_set_schema, @character_set_name 4593 * -2- @collation_catalog, @collation_schema, @collation_name 4594 */ 4595 i = check_parameters (context, error, 3, 4596 &catalog, G_TYPE_STRING, 4597 &schema, G_TYPE_STRING, 4598 &name, G_TYPE_STRING, NULL, 4599 "table_catalog", &catalog, "table_schema", &schema, "table_name", &name, NULL, 4600 "character_set_catalog", &catalog, "character_set_schema", &schema, "character_set_name", &name, NULL, 4601 "collation_catalog", &catalog, "collation_schema", &schema, "collation_name", &name, NULL); 4602 if (i < 0) 4603 return FALSE; 4604 4605 ASSERT_TABLE_NAME (tname, "columns"); 4606 if (i == 0) { 4607 if (!PROV_CLASS (provider)->meta_funcs.columns) { 4608 WARN_METHOD_NOT_IMPLEMENTED (provider, "columns"); 4609 break; 4610 } 4611 retval = PROV_CLASS (provider)->meta_funcs.columns (provider, cnc, store, context, error, 4612 catalog, schema, name); 4613 WARN_META_UPDATE_FAILURE (retval, "columns"); 4614 return retval; 4615 } 4616 else { 4617 /* nothing to do */ 4618 return TRUE; 4619 } 4620 } 4621 else if ((tname[1] == 'o') && (tname[2] == 'l')) { 4622 /* _collations, params: 4623 * -0- @collation_catalog, @collation_schema, @collation_name 4624 * -1- @collation_catalog, @collation_schema 4625 */ 4626 i = check_parameters (context, error, 2, 4627 &catalog, G_TYPE_STRING, 4628 &schema, G_TYPE_STRING, 4629 &name, G_TYPE_STRING, NULL, 4630 "collation_catalog", &catalog, "collation_schema", &schema, "collation_name", &name, NULL, 4631 "collation_catalog", &catalog, "collation_schema", &schema, NULL); 4632 if (i < 0) 4633 return FALSE; 4634 4635 ASSERT_TABLE_NAME (tname, "collations"); 4636 if (!PROV_CLASS (provider)->meta_funcs.collations) { 4637 WARN_METHOD_NOT_IMPLEMENTED (provider, "collations"); 4638 break; 4639 } 4640 retval = PROV_CLASS (provider)->meta_funcs.collations (provider, cnc, store, context, error, 4641 catalog, schema, name); 4642 WARN_META_UPDATE_FAILURE (retval, "collations"); 4643 return retval; 4644 } 4645 else if ((tname[1] == 'h') && (tname[2] == 'a')) { 4646 /* _character_sets, params: 4647 * -0- @character_set_catalog, @character_set_schema, @character_set_name 4648 * -1- @character_set_catalog, @character_set_schema 4649 */ 4650 i = check_parameters (context, error, 2, 4651 &catalog, G_TYPE_STRING, 4652 &schema, G_TYPE_STRING, 4653 &name, G_TYPE_STRING, NULL, 4654 "character_set_catalog", &catalog, "character_set_schema", &schema, "character_set_name", &name, NULL, 4655 "character_set_catalog", &catalog, "character_set_schema", &schema, NULL); 4656 if (i < 0) 4657 return FALSE; 4658 4659 ASSERT_TABLE_NAME (tname, "character_sets"); 4660 if (!PROV_CLASS (provider)->meta_funcs.character_sets) { 4661 WARN_METHOD_NOT_IMPLEMENTED (provider, "character_sets"); 4662 break; 4663 } 4664 retval = PROV_CLASS (provider)->meta_funcs.character_sets (provider, cnc, store, context, error, 4665 catalog, schema, name); 4666 WARN_META_UPDATE_FAILURE (retval, "character_sets"); 4667 return retval; 4668 } 4669 else if ((tname[1] == 'h') && (tname[2] == 'e')) { 4670 /* _check_column_usage, params: 4671 * -0- @table_catalog, @table_schema, @table_name, @constraint_name 4672 * -1- @table_catalog, @table_schema, @table_name, @column_name 4673 */ 4674 const GValue *tabname = NULL; 4675 const GValue *cname = NULL; 4676 i = check_parameters (context, error, 2, 4677 &catalog, G_TYPE_STRING, 4678 &schema, G_TYPE_STRING, 4679 &tabname, G_TYPE_STRING, 4680 &cname, G_TYPE_STRING, NULL, 4681 "table_catalog", &catalog, "table_schema", &schema, "table_name", &tabname, "constraint_name", &cname, NULL, 4682 "table_catalog", &catalog, "table_schema", &schema, "table_name", &tabname, "column_name", &cname, NULL); 4683 if (i < 0) 4684 return FALSE; 4685 4686 ASSERT_TABLE_NAME (tname, "check_column_usage"); 4687 if (i == 0) { 4688 if (!PROV_CLASS (provider)->meta_funcs.check_columns) { 4689 WARN_METHOD_NOT_IMPLEMENTED (provider, "check_columns"); 4690 break; 4691 } 4692 retval = PROV_CLASS (provider)->meta_funcs.check_columns (provider, cnc, store, context, error, 4693 catalog, schema, tabname, cname); 4694 WARN_META_UPDATE_FAILURE (retval, "check_columns"); 4695 return retval; 4696 } 4697 else { 4698 /* nothing to do */ 4699 return TRUE; 4700 } 4701 } 4702 break; 4703 4704 case 'd': 4705 if ((tname[1] == 'o') && (tname[2] == 'm') && (tname[3] == 'a') && (tname[4] == 'i') && (tname[5] == 'n') && 4706 (tname[6] == 's')) { 4707 /* _domains, params: 4708 * -0- @domain_catalog, @domain_schema 4709 */ 4710 i = check_parameters (context, error, 1, 4711 &catalog, G_TYPE_STRING, 4712 &schema, G_TYPE_STRING, NULL, 4713 "domain_catalog", &catalog, "domain_schema", &schema, NULL); 4714 if (i < 0) 4715 return FALSE; 4716 4717 ASSERT_TABLE_NAME (tname, "domains"); 4718 if (!PROV_CLASS (provider)->meta_funcs.domains) { 4719 WARN_METHOD_NOT_IMPLEMENTED (provider, "domains"); 4720 break; 4721 } 4722 retval = PROV_CLASS (provider)->meta_funcs.domains (provider, cnc, store, context, error, 4723 catalog, schema); 4724 WARN_META_UPDATE_FAILURE (retval, "domains"); 4725 return retval; 4726 } 4727 else { 4728 /* _domain_constraints, params: 4729 * -0- @domain_catalog, @domain_schema, @domain_name 4730 * -1- @constraint_catalog, @constraint_schema 4731 */ 4732 const GValue *domname = NULL; 4733 i = check_parameters (context, error, 2, 4734 &catalog, G_TYPE_STRING, 4735 &schema, G_TYPE_STRING, 4736 &domname, G_TYPE_STRING, NULL, 4737 "domain_catalog", &catalog, "domain_schema", &schema, "domain_name", &domname, NULL, 4738 "constraint_catalog", &catalog, "constraint_schema", &schema, NULL); 4739 4740 if (i < 0) 4741 return FALSE; 4742 if (i == 1) 4743 return TRUE; /* nothing to do */ 4744 4745 ASSERT_TABLE_NAME (tname, "domain_constraints"); 4746 if (!PROV_CLASS (provider)->meta_funcs.constraints_dom) { 4747 WARN_METHOD_NOT_IMPLEMENTED (provider, "constraints_dom"); 4748 break; 4749 } 4750 retval = PROV_CLASS (provider)->meta_funcs.constraints_dom (provider, cnc, store, context, error, 4751 catalog, schema, domname); 4752 WARN_META_UPDATE_FAILURE (retval, "constraints_dom"); 4753 return retval; 4754 } 4755 break; 4756 4757 case 'e': 4758 if (tname[1] == 'n') { 4759 /* _enums, params: 4760 * -0- @udt_catalog, @udt_schema, @udt_name 4761 */ 4762 i = check_parameters (context, error, 1, 4763 &catalog, G_TYPE_STRING, 4764 &schema, G_TYPE_STRING, 4765 &name, G_TYPE_STRING, NULL, 4766 "udt_catalog", &catalog, "udt_schema", &schema, "udt_name", &name, NULL); 4767 if (i < 0) 4768 return FALSE; 4769 4770 ASSERT_TABLE_NAME (tname, "enums"); 4771 if (!PROV_CLASS (provider)->meta_funcs.enums) { 4772 WARN_METHOD_NOT_IMPLEMENTED (provider, "enums"); 4773 break; 4774 } 4775 retval = PROV_CLASS (provider)->meta_funcs.enums (provider, cnc, store, context, error, 4776 catalog, schema, name); 4777 WARN_META_UPDATE_FAILURE (retval, "enums"); 4778 return retval; 4779 } 4780 else { 4781 /* _element_types, params: 4782 * - none 4783 * -0- @specific_name 4784 */ 4785 i = check_parameters (context, error, 1, 4786 &name, G_TYPE_STRING, NULL, 4787 "specific_name", &name, NULL); 4788 ASSERT_TABLE_NAME (tname, "element_types"); 4789 if (i < 0) { 4790 if (!PROV_CLASS (provider)->meta_funcs._el_types) { 4791 WARN_METHOD_NOT_IMPLEMENTED (provider, "_el_types"); 4792 break; 4793 } 4794 retval = PROV_CLASS (provider)->meta_funcs._el_types (provider, cnc, store, context, error); 4795 WARN_META_UPDATE_FAILURE (retval, "_el_types"); 4796 } 4797 else { 4798 if (!PROV_CLASS (provider)->meta_funcs.el_types) { 4799 WARN_METHOD_NOT_IMPLEMENTED (provider, "el_types"); 4800 break; 4801 } 4802 retval = PROV_CLASS (provider)->meta_funcs.el_types (provider, cnc, store, context, error, name); 4803 WARN_META_UPDATE_FAILURE (retval, "el_types"); 4804 } 4805 return retval; 4806 } 4807 break; 4808 4809 case 'i': 4810 if ((tname[1] == 'n') && (tname[2] == 'f')) { 4811 /* _information_schema_catalog_name, params: 4812 * - none 4813 */ 4814 ASSERT_TABLE_NAME (tname, "information_schema_catalog_name"); 4815 if (!PROV_CLASS (provider)->meta_funcs._info) { 4816 WARN_METHOD_NOT_IMPLEMENTED (provider, "_info"); 4817 break; 4818 } 4819 retval = PROV_CLASS (provider)->meta_funcs._info (provider, cnc, store, context, error); 4820 WARN_META_UPDATE_FAILURE (retval, "_info"); 4821 return retval; 4822 } 4823 else { 4824 /* _index_column_usage, params: 4825 * -0- @table_catalog, @table_schema, @table_name, @index_name 4826 */ 4827 const GValue *iname = NULL; 4828 i = check_parameters (context, error, 1, 4829 &catalog, G_TYPE_STRING, 4830 &schema, G_TYPE_STRING, 4831 &name, G_TYPE_STRING, 4832 &iname, G_TYPE_STRING, NULL, 4833 "table_catalog", &catalog, "table_schema", &schema, "table_name", &name, "index_name", &iname, NULL); 4834 4835 if (i < 0) 4836 return FALSE; 4837 4838 ASSERT_TABLE_NAME (tname, "index_column_usage"); 4839 if (!PROV_CLASS (provider)->meta_funcs.index_cols) { 4840 WARN_METHOD_NOT_IMPLEMENTED (provider, "index_cols"); 4841 break; 4842 } 4843 retval = PROV_CLASS (provider)->meta_funcs.index_cols (provider, cnc, store, context, error, 4844 catalog, schema, name, iname); 4845 WARN_META_UPDATE_FAILURE (retval, "index_cols"); 4846 return retval; 4847 } 4848 break; 4849 case 'k': { 4850 /* _key_column_usage, params: 4851 * -0- @table_catalog, @table_schema, @table_name, @constraint_name 4852 * -0- @ref_table_catalog, @ref_table_schema, @ref_table_name, @ref_constraint_name 4853 */ 4854 const GValue *tabname = NULL; 4855 const GValue *cname = NULL; 4856 i = check_parameters (context, error, 2, 4857 &catalog, G_TYPE_STRING, 4858 &schema, G_TYPE_STRING, 4859 &tabname, G_TYPE_STRING, 4860 &cname, G_TYPE_STRING, NULL, 4861 "table_catalog", &catalog, "table_schema", &schema, "table_name", &tabname, "constraint_name", &cname, NULL, 4862 "table_catalog", &catalog, "table_schema", &schema, "table_name", &tabname, "column_name", &cname, NULL); 4863 if (i < 0) 4864 return FALSE; 4865 4866 ASSERT_TABLE_NAME (tname, "key_column_usage"); 4867 if (i == 0) { 4868 if (!PROV_CLASS (provider)->meta_funcs.key_columns) { 4869 WARN_METHOD_NOT_IMPLEMENTED (provider, "key_columns"); 4870 break; 4871 } 4872 retval = PROV_CLASS (provider)->meta_funcs.key_columns (provider, cnc, store, context, error, 4873 catalog, schema, tabname, cname); 4874 WARN_META_UPDATE_FAILURE (retval, "key_columns"); 4875 return retval; 4876 } 4877 else { 4878 /* nothing to do */ 4879 return TRUE; 4880 } 4881 break; 4882 } 4883 4884 case 'p': 4885 /* _parameters, params: 4886 * -0- @specific_catalog, @specific_schema, @specific_name 4887 */ 4888 i = check_parameters (context, error, 1, 4889 &catalog, G_TYPE_STRING, 4890 &schema, G_TYPE_STRING, 4891 &name, G_TYPE_STRING, NULL, 4892 "specific_catalog", &catalog, "specific_schema", &schema, "specific_name", &name, NULL); 4893 if (i < 0) 4894 return FALSE; 4895 4896 ASSERT_TABLE_NAME (tname, "parameters"); 4897 if (!PROV_CLASS (provider)->meta_funcs.routine_par) { 4898 WARN_METHOD_NOT_IMPLEMENTED (provider, "routine_par"); 4899 break; 4900 } 4901 retval = PROV_CLASS (provider)->meta_funcs.routine_par (provider, cnc, store, context, error, 4902 catalog, schema, name); 4903 WARN_META_UPDATE_FAILURE (retval, "routine_par"); 4904 return retval; 4905 4906 case 'r': 4907 if ((tname[1] == 'e') && (tname[2] == 'f')) { 4908 /* _referential_constraints, params: 4909 * -0- @table_catalog, @table_schema, @table_name, @constraint_name 4910 * -0- @ref_table_catalog, @ref_table_schema, @ref_table_name, @ref_constraint_name 4911 */ 4912 const GValue *tabname = NULL; 4913 const GValue *cname = NULL; 4914 i = check_parameters (context, error, 2, 4915 &catalog, G_TYPE_STRING, 4916 &schema, G_TYPE_STRING, 4917 &tabname, G_TYPE_STRING, 4918 &cname, G_TYPE_STRING, NULL, 4919 "table_catalog", &catalog, "table_schema", &schema, "table_name", &tabname, "constraint_name", &cname, NULL, 4920 "ref_table_catalog", &catalog, "ref_table_schema", &schema, "ref_table_name", &tabname, "ref_constraint_name", &cname, NULL); 4921 if (i < 0) 4922 return FALSE; 4923 4924 ASSERT_TABLE_NAME (tname, "referential_constraints"); 4925 if (i == 0) { 4926 if (!PROV_CLASS (provider)->meta_funcs.constraints_ref) { 4927 WARN_METHOD_NOT_IMPLEMENTED (provider, "constraints_ref"); 4928 break; 4929 } 4930 retval = PROV_CLASS (provider)->meta_funcs.constraints_ref (provider, cnc, store, context, error, 4931 catalog, schema, tabname, cname); 4932 WARN_META_UPDATE_FAILURE (retval, "constraints_ref"); 4933 return retval; 4934 } 4935 else { 4936 /* nothing to do */ 4937 return TRUE; 4938 } 4939 } 4940 if ((tname[1] == 'o') && (tname[2] == 'u') && (tname[3] == 't') && (tname[4] == 'i') && 4941 (tname[5] == 'n') && (tname[6] == 'e') && (tname[7] == 's')) { 4942 /* _routines, params: 4943 * -0- @specific_catalog, @specific_schema, @specific_name 4944 * -1- @specific_catalog, @specific_schema 4945 */ 4946 i = check_parameters (context, error, 2, 4947 &catalog, G_TYPE_STRING, 4948 &schema, G_TYPE_STRING, 4949 &name, G_TYPE_STRING, NULL, 4950 "specific_catalog", &catalog, "specific_schema", &schema, "specific_name", &name, NULL, 4951 "specific_catalog", &catalog, "specific_schema", &schema, NULL); 4952 if (i < 0) 4953 return FALSE; 4954 4955 ASSERT_TABLE_NAME (tname, "routines"); 4956 if (!PROV_CLASS (provider)->meta_funcs.routines) { 4957 WARN_METHOD_NOT_IMPLEMENTED (provider, "routines"); 4958 break; 4959 } 4960 retval = PROV_CLASS (provider)->meta_funcs.routines (provider, cnc, store, context, error, 4961 catalog, schema, name); 4962 WARN_META_UPDATE_FAILURE (retval, "routines"); 4963 return retval; 4964 } 4965 else { 4966 /* _routine_columns, params: 4967 * -0- @specific_catalog, @specific_schema, @specific_name 4968 */ 4969 i = check_parameters (context, error, 1, 4970 &catalog, G_TYPE_STRING, 4971 &schema, G_TYPE_STRING, 4972 &name, G_TYPE_STRING, NULL, 4973 "specific_catalog", &catalog, "specific_schema", &schema, "specific_name", &name, NULL); 4974 if (i < 0) 4975 return FALSE; 4976 4977 ASSERT_TABLE_NAME (tname, "routine_columns"); 4978 if (!PROV_CLASS (provider)->meta_funcs.routine_col) { 4979 WARN_METHOD_NOT_IMPLEMENTED (provider, "routine_col"); 4980 break; 4981 } 4982 retval = PROV_CLASS (provider)->meta_funcs.routine_col (provider, cnc, store, context, error, 4983 catalog, schema, name); 4984 WARN_META_UPDATE_FAILURE (retval, "routine_col"); 4985 return retval; 4986 } 4987 break; 4988 4989 case 's': { 4990 /* _schemata, params: 4991 * -0- @catalog_name, @schema_name 4992 * -1- @catalog_name 4993 */ 4994 i = check_parameters (context, error, 2, 4995 &schema, G_TYPE_STRING, NULL, 4996 "catalog_name", &catalog, "schema_name", &schema, NULL, 4997 "catalog_name", &catalog, NULL); 4998 if (i < 0) 4999 return FALSE; 5000 ASSERT_TABLE_NAME (tname, "schemata"); 5001 5002 if (!PROV_CLASS (provider)->meta_funcs.schemata) { 5003 WARN_METHOD_NOT_IMPLEMENTED (provider, "schemata"); 5004 break; 5005 } 5006 retval = PROV_CLASS (provider)->meta_funcs.schemata (provider, cnc, store, context, error, 5007 catalog, schema); 5008 WARN_META_UPDATE_FAILURE (retval, "schemata"); 5009 return retval; 5010 } 5011 case 't': 5012 if ((tname[1] == 'a') && (tname[2] == 'b') && (tname[3] == 'l') && (tname[4] == 'e') && (tname[5] == 's')) { 5013 /* _tables, params: 5014 * -0- @table_catalog, @table_schema, @table_name 5015 * -1- @table_catalog, @table_schema 5016 */ 5017 i = check_parameters (context, error, 2, 5018 &catalog, G_TYPE_STRING, 5019 &schema, G_TYPE_STRING, 5020 &name, G_TYPE_STRING, NULL, 5021 "table_catalog", &catalog, "table_schema", &schema, "table_name", &name, NULL, 5022 "table_catalog", &catalog, "table_schema", &schema, NULL); 5023 if (i < 0) 5024 return FALSE; 5025 5026 ASSERT_TABLE_NAME (tname, "tables"); 5027 if (!PROV_CLASS (provider)->meta_funcs.tables_views) { 5028 WARN_METHOD_NOT_IMPLEMENTED (provider, "tables_views"); 5029 break; 5030 } 5031 retval = PROV_CLASS (provider)->meta_funcs.tables_views (provider, cnc, store, context, error, 5032 catalog, schema, name); 5033 WARN_META_UPDATE_FAILURE (retval, "tables_views"); 5034 return retval; 5035 } 5036 else if ((tname[1] == 'a') && (tname[2] == 'b') && (tname[3] == 'l') && (tname[4] == 'e') && 5037 (tname[5] == '_') && (tname[6] == 'c')) { 5038 /* _tables_constraints, params: 5039 * -0- @table_catalog, @table_schema, @table_name, @constraint_name 5040 * -1- @table_catalog, @table_schema, @table_name 5041 */ 5042 const GValue *cname = NULL; 5043 const GValue *tabname = NULL; 5044 i = check_parameters (context, error, 2, 5045 &catalog, G_TYPE_STRING, 5046 &schema, G_TYPE_STRING, 5047 &cname, G_TYPE_STRING, 5048 &tabname, G_TYPE_STRING, NULL, 5049 "table_catalog", &catalog, "table_schema", &schema, "table_name", &tabname, "constraint_name", &cname, NULL, 5050 "table_catalog", &catalog, "table_schema", &schema, "table_name", &tabname, NULL); 5051 5052 if (i < 0) 5053 return FALSE; 5054 5055 ASSERT_TABLE_NAME (tname, "table_constraints"); 5056 if (!PROV_CLASS (provider)->meta_funcs.constraints_tab) { 5057 WARN_METHOD_NOT_IMPLEMENTED (provider, "constraints_tab"); 5058 break; 5059 } 5060 retval = PROV_CLASS (provider)->meta_funcs.constraints_tab (provider, cnc, store, context, error, 5061 catalog, schema, tabname, cname); 5062 WARN_META_UPDATE_FAILURE (retval, "constraints_tab"); 5063 return retval; 5064 } 5065 else if ((tname[1] == 'a') && (tname[2] == 'b') && (tname[3] == 'l') && (tname[4] == 'e') && 5066 (tname[5] == '_') && (tname[6] == 'i')) { 5067 /* _table_indexes, params: 5068 * -0- @table_catalog, @table_schema, @table_name, @index_name 5069 * -1- @table_catalog, @table_schema, @table_name 5070 */ 5071 const GValue *iname = NULL; 5072 const GValue *tabname = NULL; 5073 i = check_parameters (context, error, 2, 5074 &catalog, G_TYPE_STRING, 5075 &schema, G_TYPE_STRING, 5076 &iname, G_TYPE_STRING, 5077 &tabname, G_TYPE_STRING, NULL, 5078 "table_catalog", &catalog, "table_schema", &schema, "table_name", &tabname, "index_name", &iname, NULL, 5079 "table_catalog", &catalog, "table_schema", &schema, "table_name", &tabname, NULL); 5080 5081 if (i < 0) 5082 return FALSE; 5083 5084 ASSERT_TABLE_NAME (tname, "table_indexes"); 5085 if (!PROV_CLASS (provider)->meta_funcs.indexes_tab) { 5086 WARN_METHOD_NOT_IMPLEMENTED (provider, "indexes_tab"); 5087 break; 5088 } 5089 retval = PROV_CLASS (provider)->meta_funcs.indexes_tab (provider, cnc, store, context, error, 5090 catalog, schema, tabname, iname); 5091 WARN_META_UPDATE_FAILURE (retval, "indexes_tab"); 5092 return retval; 5093 } 5094 else if ((tname[1] == 'r') && (tname[2] == 'i')) { 5095 /* _triggers, params: 5096 * -0- @trigger_catalog, @trigger_schema 5097 * -1- @event_object_catalog, @event_object_schema, @event_object_table 5098 */ 5099 i = check_parameters (context, error, 2, 5100 &catalog, G_TYPE_STRING, 5101 &schema, G_TYPE_STRING, 5102 &name, G_TYPE_STRING, NULL, 5103 "trigger_catalog", &catalog, "trigger_schema", &schema, NULL, 5104 "event_object_catalog", &catalog, "event_object_schema", &schema, "event_object_table", &name, NULL); 5105 if (i < 0) 5106 return FALSE; 5107 5108 ASSERT_TABLE_NAME (tname, "triggers"); 5109 if (i == 1) { 5110 if (!PROV_CLASS (provider)->meta_funcs.triggers) { 5111 WARN_METHOD_NOT_IMPLEMENTED (provider, "triggers"); 5112 break; 5113 } 5114 retval = PROV_CLASS (provider)->meta_funcs.triggers (provider, cnc, store, context, error, 5115 catalog, schema, name); 5116 WARN_META_UPDATE_FAILURE (retval, "triggers"); 5117 return retval; 5118 } 5119 else { 5120 /* nothing to do */ 5121 return TRUE; 5122 } 5123 } 5124 break; 5125 5126 case 'u': 5127 if ((tname[1] == 'd') && (tname[2] == 't') && (tname[3] == 0)) { 5128 /* _udt, params: 5129 * -0- @udt_catalog, @udt_schema 5130 */ 5131 i = check_parameters (context, error, 1, 5132 &catalog, G_TYPE_STRING, 5133 &schema, G_TYPE_STRING, NULL, 5134 "udt_catalog", &catalog, "udt_schema", &schema, NULL); 5135 if (i < 0) 5136 return FALSE; 5137 5138 ASSERT_TABLE_NAME (tname, "udt"); 5139 if (!PROV_CLASS (provider)->meta_funcs.udt) { 5140 WARN_METHOD_NOT_IMPLEMENTED (provider, "udt"); 5141 break; 5142 } 5143 retval = PROV_CLASS (provider)->meta_funcs.udt (provider, cnc, store, context, error, 5144 catalog, schema); 5145 WARN_META_UPDATE_FAILURE (retval, "udt"); 5146 return retval; 5147 } 5148 else if ((tname[1] == 'd') && (tname[2] == 't') && (tname[3] == '_')) { 5149 /* _udt_columns, params: 5150 * -0- @udt_catalog, @udt_schema, @udt_name 5151 */ 5152 i = check_parameters (context, error, 1, 5153 &catalog, G_TYPE_STRING, 5154 &schema, G_TYPE_STRING, 5155 &name, G_TYPE_STRING, NULL, 5156 "udt_catalog", &catalog, "udt_schema", &schema, "udt_name", &name, NULL); 5157 if (i < 0) 5158 return FALSE; 5159 5160 ASSERT_TABLE_NAME (tname, "udt_columns"); 5161 if (!PROV_CLASS (provider)->meta_funcs.udt_cols) { 5162 WARN_METHOD_NOT_IMPLEMENTED (provider, "udt_cols"); 5163 break; 5164 } 5165 retval = PROV_CLASS (provider)->meta_funcs.udt_cols (provider, cnc, store, context, error, 5166 catalog, schema, name); 5167 WARN_META_UPDATE_FAILURE (retval, "udt_cols"); 5168 return retval; 5169 } 5170 break; 5171 5172 case 'v': { 5173 /* _view_column_usage, params: 5174 * -0- @view_catalog, @view_schema, @view_name 5175 * -1- @table_catalog, @table_schema, @table_name, @column_name 5176 */ 5177 const GValue *colname = NULL; 5178 i = check_parameters (context, error, 2, 5179 &catalog, G_TYPE_STRING, 5180 &schema, G_TYPE_STRING, 5181 &colname, G_TYPE_STRING, 5182 &name, G_TYPE_STRING, NULL, 5183 "view_catalog", &catalog, "view_schema", &schema, "view_name", &name, NULL, 5184 "table_catalog", &catalog, "table_schema", &schema, "table_name", &name, 5185 "column_name", &colname, NULL); 5186 if (i < 0) 5187 return FALSE; 5188 5189 ASSERT_TABLE_NAME (tname, "view_column_usage"); 5190 if (i == 0) { 5191 if (!PROV_CLASS (provider)->meta_funcs.view_cols) { 5192 WARN_METHOD_NOT_IMPLEMENTED (provider, "view_cols"); 5193 break; 5194 } 5195 retval = PROV_CLASS (provider)->meta_funcs.view_cols (provider, cnc, store, context, error, 5196 catalog, schema, name); 5197 WARN_META_UPDATE_FAILURE (retval, "view_cols"); 5198 return retval; 5199 } 5200 else { 5201 /* nothing to do */ 5202 return TRUE; 5203 } 5204 break; 5205 } 5206 default: 5207 break; 5208 } 5209 return TRUE; 5210 } 5211 5212 typedef struct { 5213 GdaServerProvider *prov; 5214 GdaConnection *cnc; 5215 GError *error; 5216 GSList *context_templates; 5217 GHashTable *context_templates_hash; 5218 } DownstreamCallbackData; 5219 5220 static GError * 5221 suggest_update_cb_downstream (G_GNUC_UNUSED GdaMetaStore *store, GdaMetaContext *suggest, DownstreamCallbackData *data) 5222 { 5223 #define MAX_CONTEXT_SIZE 10 5224 if (data->error) 5225 return data->error; 5226 5227 GdaMetaContext *templ_context; 5228 GdaMetaContext loc_suggest; 5229 gchar *column_names[MAX_CONTEXT_SIZE]; 5230 GValue *column_values[MAX_CONTEXT_SIZE]; 5231 5232 /* if there is no context with the same table name in the templates, then exit right now */ 5233 templ_context = g_hash_table_lookup (data->context_templates_hash, suggest->table_name); 5234 if (!templ_context) 5235 return NULL; 5236 5237 if (templ_context->size > 0) { 5238 /* setup @loc_suggest */ 5239 gint i, j; 5240 5241 if (suggest->size > MAX_CONTEXT_SIZE) { 5242 g_warning ("Internal limitation at %s(), limitation should be at least %d, please report a bug", 5243 __FUNCTION__, suggest->size); 5244 return NULL; 5245 } 5246 loc_suggest.size = suggest->size; 5247 loc_suggest.table_name = suggest->table_name; 5248 loc_suggest.column_names = column_names; 5249 loc_suggest.column_values = column_values; 5250 memcpy (loc_suggest.column_names, suggest->column_names, sizeof (gchar *) * suggest->size); /* Flawfinder: ignore */ 5251 memcpy (loc_suggest.column_values, suggest->column_values, sizeof (GValue *) * suggest->size); /* Flawfinder: ignore */ 5252 5253 /* check that any @suggest's columns which is in @templ_context's has the same values */ 5254 for (j = 0; j < suggest->size; j++) { 5255 for (i = 0; i < templ_context->size; i++) { 5256 if (!strcmp (templ_context->column_names[i], suggest->column_names[j])) { 5257 /* same column name, now check column value */ 5258 if (G_VALUE_TYPE (templ_context->column_values[i]) != 5259 G_VALUE_TYPE (suggest->column_values[j])) { 5260 g_warning ("Internal error: column types mismatch for GdaMetaContext " 5261 "table '%s' and column '%s' (%s/%s)", 5262 templ_context->table_name, templ_context->column_names[i], 5263 g_type_name (G_VALUE_TYPE (templ_context->column_values[i])), 5264 g_type_name (G_VALUE_TYPE (suggest->column_values[j]))); 5265 return NULL; 5266 } 5267 if (gda_value_compare (templ_context->column_values[i], suggest->column_values[j])) 5268 /* different values */ 5269 return NULL; 5270 break; 5271 } 5272 } 5273 } 5274 5275 /* @templ_context may contain some more columns => add them to @loc_suggest */ 5276 for (i = 0; i < templ_context->size; i++) { 5277 for (j = 0; j < suggest->size; j++) { 5278 if (!strcmp (templ_context->column_names[i], suggest->column_names[j])) { 5279 j = -1; 5280 break; 5281 } 5282 } 5283 if (j >= 0) { 5284 if (loc_suggest.size >= MAX_CONTEXT_SIZE) { 5285 g_warning ("Internal limitation at %s(), limitation should be at least %d, please report a bug", 5286 __FUNCTION__, loc_suggest.size + 1); 5287 return NULL; 5288 } 5289 loc_suggest.column_names [loc_suggest.size] = templ_context->column_names [i]; 5290 loc_suggest.column_values [loc_suggest.size] = templ_context->column_values [i]; 5291 loc_suggest.size ++; 5292 } 5293 } 5294 5295 suggest = &loc_suggest; 5296 } 5297 5298 GError *lerror = NULL; 5299 if (!local_meta_update (data->prov, data->cnc, suggest, &lerror)) { 5300 if (lerror) 5301 data->error = lerror; 5302 else { 5303 g_set_error (&lerror,GDA_CONNECTION_ERROR, 5304 GDA_CONNECTION_META_DATA_CONTEXT_ERROR, 5305 "%s", _("Meta update error")); 5306 data->error = lerror; 5307 } 5308 5309 return data->error; 5310 } 5311 5312 return NULL; 5313 } 5314 5315 /** 5316 * gda_connection_update_meta_store: 5317 * @cnc: a #GdaConnection object. 5318 * @context: (allow-none): description of which part of @cnc's associated #GdaMetaStore should be updated, or %NULL 5319 * @error: a place to store errors, or %NULL 5320 * 5321 * Updates @cnc's associated #GdaMetaStore. If @context is not %NULL, then only the parts described by 5322 * @context will be updated, and if it is %NULL, then the complete meta store will be updated. Detailed 5323 * explanations follow: 5324 * 5325 * In order to keep the meta store's contents in a consistent state, the update process involves updating 5326 * the contents of all the tables related to one where the contents change. For example the "_columns" 5327 * table (which lists all the columns of a table) depends on the "_tables" table (which lists all the tables 5328 * in a schema), so if a row is added, removed or modified in the "_tables", then the "_columns" table's contents 5329 * needs to be updated as well regarding that row. 5330 * 5331 * If @context is %NULL, then the update process will simply overwrite any data that was present in all the 5332 * meta store's tables with new (up to date) data even if nothing has changed, without having to build the 5333 * tables' dependency tree. This is the recommended way of proceeding when dealing with a meta store which 5334 * might be outdated. 5335 * 5336 * On the other hand, if @context is not %NULL, then a tree of the dependencies has to be built (depending on 5337 * @context) and only some parts of the meta store are updated following that dependencies tree. Specifying a 5338 * context may be useful for example in the following situations: 5339 * <itemizedlist> 5340 * <listitem><para>One knows that a database object has changed (for example a table created), and 5341 * may use the @context to request that only the information about that table be updated 5342 * </para></listitem> 5343 * <listitem><para>One is only interested in the list of views, and may request that only the information 5344 * about views may be updated</para></listitem> 5345 * </itemizedlist> 5346 * 5347 * When @context is not %NULL, and contains specified SQL identifiers (for example the "table_name" of the "_tables" 5348 * table), then each SQL identifier has to match the convention the #GdaMetaStore has adopted regarding 5349 * case sensitivity, using gda_connection_quote_sql_identifier() or gda_meta_store_sql_identifier_quote(). 5350 * 5351 * see the <link linkend="information_schema:sql_identifiers"> 5352 * meta data section about SQL identifiers</link> for more information, and the documentation about the 5353 * gda_sql_identifier_quote() function which will be most useful. 5354 * 5355 * Note however that usually <emphasis>more</emphasis> information will be updated than strictly requested by 5356 * the @context argument. 5357 * 5358 * For more information, see the <link linkend="information_schema">Database structure</link> section, and 5359 * the <link linkend="howto-meta2">Update the meta data about a table</link> howto. 5360 * 5361 * Returns: TRUE if no error occurred 5362 */ 5363 gboolean 5364 gda_connection_update_meta_store (GdaConnection *cnc, GdaMetaContext *context, GError **error) 5365 { 5366 GdaMetaStore *store; 5367 5368 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 5369 g_return_val_if_fail (cnc->priv->provider_obj, FALSE); 5370 5371 gda_connection_lock ((GdaLockable*) cnc); 5372 5373 /* Get or create the GdaMetaStore object */ 5374 store = gda_connection_get_meta_store (cnc); 5375 g_assert (store); 5376 5377 /* unlock connection */ 5378 gda_connection_unlock ((GdaLockable*) cnc); 5379 5380 if (context) { 5381 GdaMetaContext *lcontext; 5382 GSList *list; 5383 GSList *up_templates; 5384 GSList *dn_templates; 5385 GError *lerror = NULL; 5386 5387 lcontext = _gda_meta_store_validate_context (store, context, error); 5388 if (!lcontext) 5389 return FALSE; 5390 /* alter local context because "_tables" and "_views" always go together so only 5391 "_tables" should be updated and providers should always update "_tables" and "_views" 5392 */ 5393 if (!strcmp (lcontext->table_name, "_views")) 5394 lcontext->table_name = "_tables"; 5395 5396 /* build context templates */ 5397 up_templates = build_upstream_context_templates (store, lcontext, NULL, &lerror); 5398 if (!up_templates) { 5399 if (lerror) { 5400 g_propagate_error (error, lerror); 5401 return FALSE; 5402 } 5403 } 5404 dn_templates = build_downstream_context_templates (store, lcontext, NULL, &lerror); 5405 if (!dn_templates) { 5406 if (lerror) { 5407 g_propagate_error (error, lerror); 5408 return FALSE; 5409 } 5410 } 5411 5412 #ifdef GDA_DEBUG_META_STORE_UPDATE 5413 g_print ("\n*********** TEMPLATES:\n"); 5414 for (list = up_templates; list; list = list->next) { 5415 g_print ("UP: "); 5416 meta_context_dump ((GdaMetaContext*) list->data); 5417 } 5418 g_print ("->: "); 5419 meta_context_dump (lcontext); 5420 for (list = dn_templates; list; list = list->next) { 5421 g_print ("DN: "); 5422 meta_context_dump ((GdaMetaContext*) list->data); 5423 } 5424 #endif 5425 5426 gulong signal_id; 5427 DownstreamCallbackData cbd; 5428 gboolean retval = TRUE; 5429 5430 cbd.prov = cnc->priv->provider_obj; 5431 cbd.cnc = cnc; 5432 cbd.error = NULL; 5433 cbd.context_templates = g_slist_concat (g_slist_append (up_templates, lcontext), dn_templates); 5434 cbd.context_templates_hash = g_hash_table_new (g_str_hash, g_str_equal); 5435 for (list = cbd.context_templates; list; list = list->next) 5436 g_hash_table_insert (cbd.context_templates_hash, ((GdaMetaContext*)list->data)->table_name, 5437 list->data); 5438 5439 signal_id = g_signal_connect (store, "suggest-update", 5440 G_CALLBACK (suggest_update_cb_downstream), &cbd); 5441 5442 retval = local_meta_update (cnc->priv->provider_obj, cnc, 5443 (GdaMetaContext*) (cbd.context_templates->data), error); 5444 5445 g_signal_handler_disconnect (store, signal_id); 5446 5447 /* free the memory associated with each template */ 5448 for (list = cbd.context_templates; list; list = list->next) { 5449 GdaMetaContext *c = (GdaMetaContext *) list->data; 5450 if (c == lcontext) { 5451 gint i; 5452 for (i = 0; i < c->size; i++) { 5453 g_free (c->column_names [i]); 5454 if (c->column_values [i]) 5455 gda_value_free (c->column_values [i]); 5456 } 5457 } 5458 if (c->size > 0) { 5459 g_free (c->column_names); 5460 g_free (c->column_values); 5461 } 5462 g_free (c); 5463 } 5464 g_slist_free (cbd.context_templates); 5465 g_hash_table_destroy (cbd.context_templates_hash); 5466 5467 return retval; 5468 } 5469 else { 5470 typedef gboolean (*RFunc) (GdaServerProvider *, GdaConnection *, GdaMetaStore *, 5471 GdaMetaContext *, GError **); 5472 typedef struct { 5473 gchar *table_name; 5474 gchar *func_name; 5475 RFunc func; 5476 } RMeta; 5477 5478 GdaMetaContext lcontext; 5479 gint nb = 0, i; 5480 RMeta rmeta[] = { 5481 {"_information_schema_catalog_name", "_info", NULL}, 5482 {"_builtin_data_types", "_btypes", NULL}, 5483 {"_udt", "_udt", NULL}, 5484 {"_udt_columns", "_udt_cols", NULL}, 5485 {"_enums", "_enums", NULL}, 5486 {"_domains", "_domains", NULL}, 5487 {"_domain_constraints", "_constraints_dom", NULL}, 5488 {"_element_types", "_el_types", NULL}, 5489 {"_collations", "_collations", NULL}, 5490 {"_character_sets", "_character_sets", NULL}, 5491 {"_schemata", "_schemata", NULL}, 5492 {"_tables_views", "_tables_views", NULL}, 5493 {"_columns", "_columns", NULL}, 5494 {"_view_column_usage", "_view_cols", NULL}, 5495 {"_table_constraints", "_constraints_tab", NULL}, 5496 {"_referential_constraints", "_constraints_ref", NULL}, 5497 {"_key_column_usage", "_key_columns", NULL}, 5498 {"_check_column_usage", "_check_columns", NULL}, 5499 {"_triggers", "_triggers", NULL}, 5500 {"_routines", "_routines", NULL}, 5501 {"_routine_columns", "_routine_col", NULL}, 5502 {"_parameters", "_routine_par", NULL}, 5503 {"_table_indexes", "_indexes_tab", NULL}, 5504 {"_index_column_usage", "_index_cols", NULL} 5505 }; 5506 GdaServerProvider *provider = cnc->priv->provider_obj; 5507 gboolean retval; 5508 rmeta [nb++].func = PROV_CLASS (provider)->meta_funcs._info; 5509 rmeta [nb++].func = PROV_CLASS (provider)->meta_funcs._btypes; 5510 rmeta [nb++].func = PROV_CLASS (provider)->meta_funcs._udt; 5511 rmeta [nb++].func = PROV_CLASS (provider)->meta_funcs._udt_cols; 5512 rmeta [nb++].func = PROV_CLASS (provider)->meta_funcs._enums; 5513 rmeta [nb++].func = PROV_CLASS (provider)->meta_funcs._domains; 5514 rmeta [nb++].func = PROV_CLASS (provider)->meta_funcs._constraints_dom; 5515 rmeta [nb++].func = PROV_CLASS (provider)->meta_funcs._el_types; 5516 rmeta [nb++].func = PROV_CLASS (provider)->meta_funcs._collations; 5517 rmeta [nb++].func = PROV_CLASS (provider)->meta_funcs._character_sets; 5518 rmeta [nb++].func = PROV_CLASS (provider)->meta_funcs._schemata; 5519 rmeta [nb++].func = PROV_CLASS (provider)->meta_funcs._tables_views; 5520 rmeta [nb++].func = PROV_CLASS (provider)->meta_funcs._columns; 5521 rmeta [nb++].func = PROV_CLASS (provider)->meta_funcs._view_cols; 5522 rmeta [nb++].func = PROV_CLASS (provider)->meta_funcs._constraints_tab; 5523 rmeta [nb++].func = PROV_CLASS (provider)->meta_funcs._constraints_ref; 5524 rmeta [nb++].func = PROV_CLASS (provider)->meta_funcs._key_columns; 5525 rmeta [nb++].func = PROV_CLASS (provider)->meta_funcs._check_columns; 5526 rmeta [nb++].func = PROV_CLASS (provider)->meta_funcs._triggers; 5527 rmeta [nb++].func = PROV_CLASS (provider)->meta_funcs._routines; 5528 rmeta [nb++].func = PROV_CLASS (provider)->meta_funcs._routine_col; 5529 rmeta [nb++].func = PROV_CLASS (provider)->meta_funcs._routine_par; 5530 rmeta [nb++].func = PROV_CLASS (provider)->meta_funcs._indexes_tab; 5531 rmeta [nb++].func = PROV_CLASS (provider)->meta_funcs._index_cols; 5532 g_assert (nb == sizeof (rmeta) / sizeof (RMeta)); 5533 5534 if (! _gda_meta_store_begin_data_reset (store, error)) { 5535 return FALSE; 5536 } 5537 5538 lcontext.size = 0; 5539 for (i = 0; i < nb; i++) { 5540 /*g_print ("TH %p %s(cnc=>%p store=>%p)\n", g_thread_self(), rmeta [i].func_name, cnc, store);*/ 5541 if (! rmeta [i].func) 5542 WARN_METHOD_NOT_IMPLEMENTED (provider, rmeta [i].func_name); 5543 else { 5544 lcontext.table_name = rmeta [i].table_name; 5545 if (!rmeta [i].func (provider, cnc, store, &lcontext, error)) { 5546 /* 5547 g_print ("TH %p CNC %p ERROR, prov=%p (%s)\n", g_thread_self(), cnc, 5548 gda_connection_get_provider (cnc), 5549 gda_connection_get_provider_name (cnc)); 5550 */ 5551 /*if (error && *error) 5552 g_warning ("%s (Provider %s)\n", (*error)->message, 5553 gda_connection_get_provider_name (cnc)); 5554 */ 5555 5556 WARN_META_UPDATE_FAILURE (FALSE, rmeta [i].func_name); 5557 goto onerror; 5558 } 5559 } 5560 } 5561 retval = _gda_meta_store_finish_data_reset (store, error); 5562 return retval; 5563 5564 onerror: 5565 _gda_meta_store_cancel_data_reset (store, NULL); 5566 return FALSE; 5567 } 5568 } 5569 5570 /* 5571 * predefined statements for meta store data retrieval 5572 */ 5573 typedef struct { 5574 GdaConnectionMetaType meta_type; 5575 gint nb_filters; 5576 gchar **filters; 5577 } MetaKey; 5578 5579 static guint 5580 meta_key_hash (gconstpointer key) 5581 { 5582 return ((((MetaKey*) key)->meta_type) << 2) + ((MetaKey*) key)->nb_filters; 5583 } 5584 5585 static gboolean 5586 meta_key_equal (gconstpointer a, gconstpointer b) 5587 { 5588 MetaKey* ak = (MetaKey*) a; 5589 MetaKey* bk = (MetaKey*) b; 5590 gint i; 5591 5592 if ((ak->meta_type != bk->meta_type) || 5593 (ak->nb_filters != bk->nb_filters)) 5594 return FALSE; 5595 for (i = 0; i < ak->nb_filters; i++) 5596 if (strcmp (ak->filters[i], bk->filters[i])) 5597 return FALSE; 5598 5599 return TRUE; 5600 } 5601 5602 static GHashTable * 5603 prepare_meta_statements_hash (void) 5604 { 5605 GHashTable *h; 5606 MetaKey *key; 5607 GdaStatement *stmt; 5608 GdaSqlParser *parser = gda_sql_parser_new (); 5609 const gchar *sql; 5610 5611 gchar **name_array = g_new (gchar *, 1); 5612 name_array[0] = "name"; 5613 5614 gchar **name_col_array = g_new (gchar *, 2); 5615 name_col_array[0] = "name"; 5616 name_col_array[1] = "field_name"; 5617 5618 gchar **name_index_array = g_new (gchar *, 2); 5619 name_index_array[0] = "name"; 5620 name_index_array[1] = "index_name"; 5621 5622 h = g_hash_table_new (meta_key_hash, meta_key_equal); 5623 5624 /* GDA_CONNECTION_META_NAMESPACES */ 5625 key = g_new0 (MetaKey, 1); 5626 key->meta_type = GDA_CONNECTION_META_NAMESPACES; 5627 sql = "SELECT schema_name, schema_owner, schema_internal FROM _schemata"; 5628 stmt = gda_sql_parser_parse_string (parser, sql, NULL, NULL); 5629 if (!stmt) 5630 g_error ("Could not parse internal statement: %s\n", sql); 5631 g_hash_table_insert (h, key, stmt); 5632 5633 key = g_new0 (MetaKey, 1); 5634 key->meta_type = GDA_CONNECTION_META_NAMESPACES; 5635 key->nb_filters = 1; 5636 key->filters = name_array; 5637 sql = "SELECT schema_name, schema_owner, schema_internal FROM _schemata WHERE schema_name=##name::string"; 5638 stmt = gda_sql_parser_parse_string (parser, sql, NULL, NULL); 5639 if (!stmt) 5640 g_error ("Could not parse internal statement: %s\n", sql); 5641 g_hash_table_insert (h, key, stmt); 5642 5643 /* GDA_CONNECTION_META_TYPES */ 5644 key = g_new0 (MetaKey, 1); 5645 key->meta_type = GDA_CONNECTION_META_TYPES; 5646 sql = "SELECT short_type_name, gtype, comments, synonyms FROM _all_types WHERE NOT internal"; 5647 stmt = gda_sql_parser_parse_string (parser, sql, NULL, NULL); 5648 if (!stmt) 5649 g_error ("Could not parse internal statement: %s\n", sql); 5650 g_hash_table_insert (h, key, stmt); 5651 5652 key = g_new0 (MetaKey, 1); 5653 key->meta_type = GDA_CONNECTION_META_TYPES; 5654 key->nb_filters = 1; 5655 key->filters = name_array; 5656 sql = "SELECT short_type_name, gtype, comments, synonyms FROM _all_types WHERE NOT internal AND short_type_name=##name::string"; 5657 stmt = gda_sql_parser_parse_string (parser, sql, NULL, NULL); 5658 if (!stmt) 5659 g_error ("Could not parse internal statement: %s\n", sql); 5660 g_hash_table_insert (h, key, stmt); 5661 5662 /* GDA_CONNECTION_META_TABLES */ 5663 key = g_new0 (MetaKey, 1); 5664 key->meta_type = GDA_CONNECTION_META_TABLES; 5665 sql = "SELECT table_short_name, table_schema, table_full_name, table_owner, table_comments FROM _tables WHERE table_type LIKE '%TABLE%' AND table_short_name != table_full_name"; 5666 stmt = gda_sql_parser_parse_string (parser, sql, NULL, NULL); 5667 if (!stmt) 5668 g_error ("Could not parse internal statement: %s\n", sql); 5669 g_hash_table_insert (h, key, stmt); 5670 5671 key = g_new0 (MetaKey, 1); 5672 key->meta_type = GDA_CONNECTION_META_TABLES; 5673 key->nb_filters = 1; 5674 key->filters = name_array; 5675 sql = "SELECT table_short_name, table_schema, table_full_name, table_owner, table_comments FROM _tables WHERE table_type LIKE '%TABLE%' AND table_short_name != table_full_name AND table_short_name=##name::string"; 5676 stmt = gda_sql_parser_parse_string (parser, sql, NULL, NULL); 5677 if (!stmt) 5678 g_error ("Could not parse internal statement: %s\n", sql); 5679 g_hash_table_insert (h, key, stmt); 5680 5681 /* GDA_CONNECTION_META_VIEWS */ 5682 key = g_new0 (MetaKey, 1); 5683 key->meta_type = GDA_CONNECTION_META_VIEWS; 5684 sql = "SELECT t.table_short_name, t.table_schema, t.table_full_name, t.table_owner, t.table_comments, v.view_definition FROM _views as v NATURAL JOIN _tables as t WHERE t.table_short_name != t.table_full_name"; 5685 stmt = gda_sql_parser_parse_string (parser, sql, NULL, NULL); 5686 if (!stmt) 5687 g_error ("Could not parse internal statement: %s\n", sql); 5688 g_hash_table_insert (h, key, stmt); 5689 5690 key = g_new0 (MetaKey, 1); 5691 key->meta_type = GDA_CONNECTION_META_VIEWS; 5692 key->nb_filters = 1; 5693 key->filters = name_array; 5694 sql = "SELECT t.table_short_name, t.table_schema, t.table_full_name, t.table_owner, t.table_comments, v.view_definition FROM _views as v NATURAL JOIN _tables as t WHERE t.table_short_name != t.table_full_name AND table_short_name=##name::string"; 5695 stmt = gda_sql_parser_parse_string (parser, sql, NULL, NULL); 5696 if (!stmt) 5697 g_error ("Could not parse internal statement: %s\n", sql); 5698 g_hash_table_insert (h, key, stmt); 5699 5700 /* GDA_CONNECTION_META_FIELDS */ 5701 key = g_new0 (MetaKey, 1); 5702 key->meta_type = GDA_CONNECTION_META_FIELDS; 5703 key->nb_filters = 1; 5704 key->filters = name_array; 5705 sql = "SELECT c.column_name, c.data_type, c.gtype, c.numeric_precision, c.numeric_scale, c.is_nullable AS 'Nullable', c.column_default, c.extra FROM _columns as c NATURAL JOIN _tables as t WHERE t.table_short_name=##name::string ORDER BY c.ordinal_position"; 5706 stmt = gda_sql_parser_parse_string (parser, sql, NULL, NULL); 5707 if (!stmt) 5708 g_error ("Could not parse internal statement: %s\n", sql); 5709 g_hash_table_insert (h, key, stmt); 5710 5711 key = g_new0 (MetaKey, 1); 5712 key->meta_type = GDA_CONNECTION_META_FIELDS; 5713 key->nb_filters = 2; 5714 key->filters = name_col_array; 5715 sql = "SELECT c.column_name, c.data_type, c.gtype, c.numeric_precision, c.numeric_scale, c.is_nullable AS 'Nullable', c.column_default, c.extra FROM _columns as c NATURAL JOIN _tables as t WHERE t.table_short_name=##name::string AND c.column_name = ##field_name::string ORDER BY c.ordinal_position"; 5716 stmt = gda_sql_parser_parse_string (parser, sql, NULL, NULL); 5717 if (!stmt) 5718 g_error ("Could not parse internal statement: %s\n", sql); 5719 g_hash_table_insert (h, key, stmt); 5720 5721 /* GDA_CONNECTION_META_INDEXES */ 5722 key = g_new0 (MetaKey, 1); 5723 key->meta_type = GDA_CONNECTION_META_INDEXES; 5724 key->nb_filters = 1; 5725 key->filters = name_array; 5726 sql = "SELECT i.table_name, i.table_schema, i.index_name, d.column_name, d.ordinal_position, i.index_type FROM _table_indexes as i INNER JOIN _index_column_usage as d ON (d.table_catalog = i.table_catalog AND d.table_schema = i.table_schema AND d.table_name = i.table_name) INNER JOIN _tables t ON (t.table_catalog = i.table_catalog AND t.table_schema = i.table_schema AND t.table_name = i.table_name) WHERE t.table_short_name=##name::string"; 5727 stmt = gda_sql_parser_parse_string (parser, sql, NULL, NULL); 5728 if (!stmt) 5729 g_error ("Could not parse internal statement: %s\n", sql); 5730 g_hash_table_insert (h, key, stmt); 5731 5732 key = g_new0 (MetaKey, 1); 5733 key->meta_type = GDA_CONNECTION_META_INDEXES; 5734 key->nb_filters = 2; 5735 key->filters = name_index_array; 5736 sql = "SELECT i.table_name, i.table_schema, i.index_name, d.column_name, d.ordinal_position, i.index_type FROM _table_indexes as i INNER JOIN _index_column_usage as d ON (d.table_catalog = i.table_catalog AND d.table_schema = i.table_schema AND d.table_name = i.table_name) INNER JOIN _tables t ON (t.table_catalog = i.table_catalog AND t.table_schema = i.table_schema AND t.table_name = i.table_name) WHERE t.table_short_name=##name::string AND i.index_name=##index_name::string"; 5737 stmt = gda_sql_parser_parse_string (parser, sql, NULL, NULL); 5738 if (!stmt) 5739 g_error ("Could not parse internal statement: %s\n", sql); 5740 g_hash_table_insert (h, key, stmt); 5741 5742 return h; 5743 } 5744 5745 /** 5746 * gda_connection_get_meta_store_data: 5747 * @cnc: a #GdaConnection object. 5748 * @meta_type: describes which data to get. 5749 * @error: a place to store errors, or %NULL 5750 * @nb_filters: the number of filters in the @... argument 5751 * @...: a list of (filter name (gchar *), filter value (GValue*)) pairs specifying 5752 * the filter to apply to the returned data model's contents (there must be @nb_filters pairs) 5753 * 5754 * Retrieves data stored in @cnc's associated #GdaMetaStore object. This method is useful 5755 * to easily get some information about the meta-data associated to @cnc, such as the list of 5756 * tables, views, and other database objects. 5757 * 5758 * Note: it's up to the caller to make sure the information contained within @cnc's associated #GdaMetaStore 5759 * is up to date using gda_connection_update_meta_store() (it can become outdated if the database's schema 5760 * is modified). 5761 * 5762 * For more information about the returned data model's attributes, or about the @meta_type and ... filter arguments, 5763 * see <link linkend="GdaConnectionMetaTypeHead">this description</link>. 5764 * 5765 * Also, when using filters involving data which are SQL identifiers, make sure each SQL identifier 5766 * is represented using the #GdaMetaStore convention, using gda_meta_store_sql_identifier_quote() or 5767 * gda_meta_store_sql_identifier_quote(). 5768 * 5769 * See the <link linkend="information_schema:sql_identifiers"> 5770 * meta data section about SQL identifiers</link> for more information, and the documentation about the 5771 * gda_sql_identifier_quote() function which will be most useful. 5772 * 5773 * Returns: (transfer full): a #GdaDataModel containing the data required. The caller is responsible 5774 * for freeing the returned model using g_object_unref(). 5775 */ 5776 GdaDataModel * 5777 gda_connection_get_meta_store_data (GdaConnection *cnc, 5778 GdaConnectionMetaType meta_type, 5779 GError **error, gint nb_filters, ...) 5780 { 5781 GList* filters = NULL; 5782 GdaDataModel* model = NULL; 5783 gint i; 5784 5785 if (nb_filters > 0) { 5786 va_list ap; 5787 va_start (ap, nb_filters); 5788 for (i = 0; (i < nb_filters); i++) { 5789 GdaHolder *h; 5790 GValue *v; 5791 gchar* fname; 5792 5793 fname = va_arg (ap, gchar*); 5794 if (!fname) 5795 break; 5796 v = va_arg (ap, GValue*); 5797 if (!v || gda_value_is_null (v)) 5798 continue; 5799 h = g_object_new (GDA_TYPE_HOLDER, "g-type", G_VALUE_TYPE (v), "id", fname, NULL); 5800 filters = g_list_append (filters, h); 5801 if (!gda_holder_set_value (h, v, error)) { 5802 va_end (ap); 5803 goto onerror; 5804 } 5805 } 5806 va_end (ap); 5807 } 5808 model = gda_connection_get_meta_store_data_v (cnc, meta_type, filters, error); 5809 5810 onerror: 5811 g_list_foreach (filters, (GFunc) g_object_unref, NULL); 5812 g_list_free (filters); 5813 5814 return model; 5815 } 5816 5817 /** 5818 * gda_connection_get_meta_store_data_v: 5819 * @cnc: a #GdaConnection object. 5820 * @meta_type: describes which data to get. 5821 * @error: a place to store errors, or %NULL 5822 * @filters: (element-type GdaHolder): a #GList of #GdaHolder objects 5823 * 5824 * see #gda_connection_get_meta_store_data 5825 * 5826 * Returns: (transfer full): a #GdaDataModel containing the data required. The caller is responsible 5827 * for freeing the returned model using g_object_unref(). 5828 */ 5829 GdaDataModel * 5830 gda_connection_get_meta_store_data_v (GdaConnection *cnc, GdaConnectionMetaType meta_type, 5831 GList* filters, GError **error) 5832 { 5833 GdaMetaStore *store; 5834 GdaDataModel *model = NULL; 5835 static GHashTable *stmt_hash = NULL; 5836 GdaStatement *stmt; 5837 GdaSet *set = NULL; 5838 GList* node; 5839 5840 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 5841 g_return_val_if_fail (cnc->priv->provider_obj, NULL); 5842 5843 /* Get or create the GdaMetaStore object */ 5844 store = gda_connection_get_meta_store (cnc); 5845 g_assert (store); 5846 5847 /* fetch the statement */ 5848 MetaKey key; 5849 gint i; 5850 if (!stmt_hash) 5851 stmt_hash = prepare_meta_statements_hash (); 5852 key.meta_type = meta_type; 5853 key.nb_filters = g_list_length (filters); 5854 key.filters = NULL; 5855 if (key.nb_filters > 0) 5856 key.filters = g_new (gchar *, key.nb_filters); 5857 for (node = filters, i = 0; 5858 node; 5859 node = node->next, i++) { 5860 if (!set) 5861 set = g_object_new (GDA_TYPE_SET, NULL); 5862 gda_set_add_holder (set, GDA_HOLDER (node->data)); 5863 key.filters[i] = (gchar*) gda_holder_get_id (GDA_HOLDER (node->data)); 5864 } 5865 stmt = g_hash_table_lookup (stmt_hash, &key); 5866 g_free (key.filters); 5867 if (!stmt) { 5868 g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_MISSING_PARAM_ERROR, 5869 "%s", _("Wrong filter arguments")); 5870 if (set) 5871 g_object_unref (set); 5872 return NULL; 5873 } 5874 5875 /* execute statement to fetch the requested result from the meta store's connection 5876 * REM: at a latter time the data model should be specific and update itself whenever 5877 * the meta store is updated 5878 */ 5879 model = gda_connection_statement_execute_select (gda_meta_store_get_internal_connection (store), 5880 stmt, set, error); 5881 if (set) 5882 g_object_unref (set); 5883 5884 return model; 5885 } 5886 5887 5888 /** 5889 * gda_connection_get_events: 5890 * @cnc: a #GdaConnection. 5891 * 5892 * Retrieves a list of the last errors occurred during the connection. The returned list is 5893 * chronologically ordered such as that the most recent event is the #GdaConnectionEvent of the first node. 5894 * 5895 * Warning: the @cnc object may change the list if connection events occur 5896 * 5897 * Returns: (transfer none) (element-type Gda.ConnectionEvent): a #GList of #GdaConnectionEvent objects (the list should not be modified) 5898 */ 5899 const GList * 5900 gda_connection_get_events (GdaConnection *cnc) 5901 { 5902 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 5903 5904 if (cnc->priv->events_list) 5905 return cnc->priv->events_list; 5906 5907 5908 /* a new list of the GdaConnectionEvent objects is created, the 5909 * ownership of each GdaConnectionEvent object is transfered to the list */ 5910 GList *list = NULL; 5911 if (cnc->priv->events_array_full) { 5912 gint i; 5913 for (i = cnc->priv->events_array_next + 1; ; i++) { 5914 if (i == cnc->priv->events_array_size) 5915 i = 0; 5916 if (i == cnc->priv->events_array_next) 5917 break; 5918 GdaConnectionEvent *ev; 5919 ev = cnc->priv->events_array [i]; 5920 cnc->priv->events_array [i] = NULL; 5921 g_assert (ev); 5922 list = g_list_prepend (list, ev); 5923 } 5924 } 5925 else { 5926 gint i; 5927 for (i = 0; i < cnc->priv->events_array_next; i++) { 5928 GdaConnectionEvent *ev; 5929 ev = cnc->priv->events_array [i]; 5930 g_assert (ev); 5931 list = g_list_prepend (list, ev); 5932 cnc->priv->events_array [i] = NULL; 5933 } 5934 } 5935 cnc->priv->events_list = g_list_reverse (list); 5936 5937 /* reset events */ 5938 cnc->priv->events_array_full = FALSE; 5939 cnc->priv->events_array_next = 0; 5940 5941 return cnc->priv->events_list; 5942 } 5943 5944 /** 5945 * gda_connection_value_to_sql_string: 5946 * @cnc: a #GdaConnection object. 5947 * @from: #GValue to convert from 5948 * 5949 * Produces a fully quoted and escaped string from a GValue 5950 * 5951 * Returns: escaped and quoted value or NULL if not supported. 5952 */ 5953 gchar * 5954 gda_connection_value_to_sql_string (GdaConnection *cnc, GValue *from) 5955 { 5956 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); 5957 g_return_val_if_fail (from != NULL, FALSE); 5958 g_return_val_if_fail (cnc->priv->provider_obj, FALSE); 5959 5960 /* execute the command on the provider */ 5961 return gda_server_provider_value_to_sql_string (cnc->priv->provider_obj, cnc, from); 5962 } 5963 5964 /** 5965 * gda_connection_internal_transaction_started: (skip) 5966 * @cnc: a #GdaConnection 5967 * @parent_trans: (allow-none): name of the parent transaction, or %NULL 5968 * @trans_name: transaction's name, or %NULL 5969 * @isol_level: isolation level. 5970 * 5971 * Internal functions to be called by database providers when a transaction has been started 5972 * to keep track of the transaction status of the connection. 5973 * 5974 * Note: this function should not be called if gda_connection_internal_statement_executed() 5975 * has already been called because a statement's execution was necessary to perform 5976 * the action. 5977 */ 5978 void 5979 gda_connection_internal_transaction_started (GdaConnection *cnc, const gchar *parent_trans, const gchar *trans_name, 5980 GdaTransactionIsolation isol_level) 5981 { 5982 GdaTransactionStatus *parent, *st; 5983 5984 g_return_if_fail (GDA_IS_CONNECTION (cnc)); 5985 5986 st = gda_transaction_status_new (trans_name); 5987 st->isolation_level = isol_level; 5988 5989 gda_connection_lock ((GdaLockable*) cnc); 5990 5991 parent = gda_transaction_status_find (cnc->priv->trans_status, parent_trans, NULL); 5992 if (!parent) 5993 cnc->priv->trans_status = st; 5994 else { 5995 gda_transaction_status_add_event_sub (parent, st); 5996 g_object_unref (st); 5997 } 5998 #ifdef GDA_DEBUG_signal 5999 g_print (">> 'TRANSACTION_STATUS_CHANGED' from %s\n", __FUNCTION__); 6000 #endif 6001 g_signal_emit (G_OBJECT (cnc), gda_connection_signals[TRANSACTION_STATUS_CHANGED], 0); 6002 #ifdef GDA_DEBUG_signal 6003 g_print ("<< 'TRANSACTION_STATUS_CHANGED' from %s\n", __FUNCTION__); 6004 #endif 6005 6006 #ifdef GDA_DEBUG_NO 6007 if (cnc->priv->trans_status) 6008 gda_transaction_status_dump (cnc->priv->trans_status, 5); 6009 #endif 6010 6011 gda_connection_unlock ((GdaLockable*) cnc); 6012 } 6013 6014 /** 6015 * gda_connection_internal_transaction_rolledback: (skip) 6016 * @cnc: a #GdaConnection 6017 * @trans_name: (allow-none): transaction's name, or %NULL 6018 * 6019 * Internal functions to be called by database providers when a transaction has been rolled 6020 * back to keep track of the transaction status of the connection 6021 * 6022 * Note: this function should not be called if gda_connection_internal_statement_executed() 6023 * has already been called because a statement's execution was necessary to perform 6024 * the action. 6025 */ 6026 void 6027 gda_connection_internal_transaction_rolledback (GdaConnection *cnc, const gchar *trans_name) 6028 { 6029 GdaTransactionStatus *st = NULL; 6030 GdaTransactionStatusEvent *ev = NULL; 6031 6032 g_return_if_fail (GDA_IS_CONNECTION (cnc)); 6033 6034 gda_connection_lock ((GdaLockable*) cnc); 6035 6036 if (cnc->priv->trans_status) 6037 st = gda_transaction_status_find (cnc->priv->trans_status, trans_name, &ev); 6038 if (st) { 6039 if (ev) { 6040 /* there is a parent transaction */ 6041 gda_transaction_status_free_events (ev->trans, ev, TRUE); 6042 } 6043 else { 6044 /* no parent transaction */ 6045 g_object_unref (cnc->priv->trans_status); 6046 cnc->priv->trans_status = NULL; 6047 } 6048 #ifdef GDA_DEBUG_signal 6049 g_print (">> 'TRANSACTION_STATUS_CHANGED' from %s\n", __FUNCTION__); 6050 #endif 6051 g_signal_emit (G_OBJECT (cnc), gda_connection_signals[TRANSACTION_STATUS_CHANGED], 0); 6052 #ifdef GDA_DEBUG_signal 6053 g_print ("<< 'TRANSACTION_STATUS_CHANGED' from %s\n", __FUNCTION__); 6054 #endif 6055 } 6056 else { 6057 g_warning (_("Connection transaction status tracking: no transaction exists for %s"), "ROLLBACK"); 6058 } 6059 #ifdef GDA_DEBUG_NO 6060 if (cnc->priv->trans_status) 6061 gda_transaction_status_dump (cnc->priv->trans_status, 5); 6062 #endif 6063 6064 gda_connection_unlock ((GdaLockable*) cnc); 6065 } 6066 6067 /** 6068 * gda_connection_internal_transaction_committed: (skip) 6069 * @cnc: a #GdaConnection 6070 * @trans_name: (allow-none): transaction's name, or %NULL 6071 * 6072 * Internal functions to be called by database providers when a transaction has been committed 6073 * to keep track of the transaction status of the connection 6074 * 6075 * Note: this function should not be called if gda_connection_internal_statement_executed() 6076 * has already been called because a statement's execution was necessary to perform 6077 * the action. 6078 */ 6079 void 6080 gda_connection_internal_transaction_committed (GdaConnection *cnc, const gchar *trans_name) 6081 { 6082 GdaTransactionStatus *st = NULL; 6083 GdaTransactionStatusEvent *ev = NULL; 6084 6085 g_return_if_fail (GDA_IS_CONNECTION (cnc)); 6086 6087 gda_connection_lock ((GdaLockable*) cnc); 6088 6089 if (cnc->priv->trans_status) 6090 st = gda_transaction_status_find (cnc->priv->trans_status, trans_name, &ev); 6091 if (st) { 6092 if (ev) { 6093 /* there is a parent transaction */ 6094 gda_transaction_status_free_events (ev->trans, ev, TRUE); 6095 } 6096 else { 6097 /* no parent transaction */ 6098 g_object_unref (cnc->priv->trans_status); 6099 cnc->priv->trans_status = NULL; 6100 } 6101 #ifdef GDA_DEBUG_signal 6102 g_print (">> 'TRANSACTION_STATUS_CHANGED' from %s\n", __FUNCTION__); 6103 #endif 6104 g_signal_emit (G_OBJECT (cnc), gda_connection_signals[TRANSACTION_STATUS_CHANGED], 0); 6105 #ifdef GDA_DEBUG_signal 6106 g_print ("<< 'TRANSACTION_STATUS_CHANGED' from %s\n", __FUNCTION__); 6107 #endif 6108 } 6109 else { 6110 g_warning (_("Connection transaction status tracking: no transaction exists for %s"), "COMMIT"); 6111 } 6112 #ifdef GDA_DEBUG_NO 6113 if (cnc->priv->trans_status) 6114 gda_transaction_status_dump (cnc->priv->trans_status, 5); 6115 #endif 6116 6117 gda_connection_unlock ((GdaLockable*) cnc); 6118 } 6119 6120 /** 6121 * gda_connection_internal_savepoint_added: (skip) 6122 * @cnc: a #GdaConnection 6123 * @parent_trans: (allow-none): name of the parent transaction, or %NULL 6124 * @svp_name: savepoint's name, or %NULL 6125 * 6126 * Internal functions to be called by database providers when a savepoint has been added 6127 * to keep track of the transaction status of the connection 6128 * 6129 * Note: this function should not be called if gda_connection_internal_statement_executed() 6130 * has already been called because a statement's execution was necessary to perform 6131 * the action. 6132 */ 6133 void 6134 gda_connection_internal_savepoint_added (GdaConnection *cnc, const gchar *parent_trans, const gchar *svp_name) 6135 { 6136 GdaTransactionStatus *st; 6137 6138 g_return_if_fail (GDA_IS_CONNECTION (cnc)); 6139 6140 gda_connection_lock ((GdaLockable*) cnc); 6141 6142 st = gda_transaction_status_find (cnc->priv->trans_status, parent_trans, NULL); 6143 if (st) { 6144 gda_transaction_status_add_event_svp (st, svp_name); 6145 #ifdef GDA_DEBUG_signal 6146 g_print (">> 'TRANSACTION_STATUS_CHANGED' from %s\n", __FUNCTION__); 6147 #endif 6148 g_signal_emit (G_OBJECT (cnc), gda_connection_signals[TRANSACTION_STATUS_CHANGED], 0); 6149 #ifdef GDA_DEBUG_signal 6150 g_print ("<< 'TRANSACTION_STATUS_CHANGED' from %s\n", __FUNCTION__); 6151 #endif 6152 } 6153 else { 6154 g_warning (_("Connection transaction status tracking: no transaction exists for %s"), "ADD SAVEPOINT"); 6155 } 6156 #ifdef GDA_DEBUG_NO 6157 if (cnc->priv->trans_status) 6158 gda_transaction_status_dump (cnc->priv->trans_status, 5); 6159 #endif 6160 6161 gda_connection_unlock ((GdaLockable*) cnc); 6162 } 6163 6164 /** 6165 * gda_connection_internal_savepoint_rolledback: (skip) 6166 * @cnc: a #GdaConnection 6167 * @svp_name: (allow-none): savepoint's name, or %NULL 6168 * 6169 * Internal functions to be called by database providers when a savepoint has been rolled back 6170 * to keep track of the transaction status of the connection 6171 * 6172 * Note: this function should not be called if gda_connection_internal_statement_executed() 6173 * has already been called because a statement's execution was necessary to perform 6174 * the action. 6175 */ 6176 void 6177 gda_connection_internal_savepoint_rolledback (GdaConnection *cnc, const gchar *svp_name) 6178 { 6179 GdaTransactionStatus *st; 6180 GdaTransactionStatusEvent *ev = NULL; 6181 6182 g_return_if_fail (GDA_IS_CONNECTION (cnc)); 6183 6184 gda_connection_lock ((GdaLockable*) cnc); 6185 6186 st = gda_transaction_status_find (cnc->priv->trans_status, svp_name, &ev); 6187 if (st) { 6188 gda_transaction_status_free_events (st, ev, TRUE); 6189 #ifdef GDA_DEBUG_signal 6190 g_print (">> 'TRANSACTION_STATUS_CHANGED' from %s\n", __FUNCTION__); 6191 #endif 6192 g_signal_emit (G_OBJECT (cnc), gda_connection_signals[TRANSACTION_STATUS_CHANGED], 0); 6193 #ifdef GDA_DEBUG_signal 6194 g_print ("<< 'TRANSACTION_STATUS_CHANGED' from %s\n", __FUNCTION__); 6195 #endif 6196 } 6197 else { 6198 g_warning (_("Connection transaction status tracking: no transaction exists for %s"), "ROLLBACK SAVEPOINT"); 6199 } 6200 #ifdef GDA_DEBUG_NO 6201 if (cnc->priv->trans_status) 6202 gda_transaction_status_dump (cnc->priv->trans_status, 5); 6203 #endif 6204 6205 gda_connection_unlock ((GdaLockable*) cnc); 6206 } 6207 6208 /** 6209 * gda_connection_internal_savepoint_removed: (skip) 6210 * @cnc: a #GdaConnection 6211 * @svp_name: (allow-none): savepoint's name, or %NULL 6212 * 6213 * Internal functions to be called by database providers when a savepoint has been removed 6214 * to keep track of the transaction status of the connection 6215 * 6216 * Note: this function should not be called if gda_connection_internal_statement_executed() 6217 * has already been called because a statement's execution was necessary to perform 6218 * the action. 6219 */ 6220 void 6221 gda_connection_internal_savepoint_removed (GdaConnection *cnc, const gchar *svp_name) 6222 { 6223 GdaTransactionStatus *st; 6224 GdaTransactionStatusEvent *ev = NULL; 6225 6226 g_return_if_fail (GDA_IS_CONNECTION (cnc)); 6227 6228 gda_connection_lock ((GdaLockable*) cnc); 6229 6230 st = gda_transaction_status_find (cnc->priv->trans_status, svp_name, &ev); 6231 if (st) { 6232 gda_transaction_status_free_events (st, ev, FALSE); 6233 #ifdef GDA_DEBUG_signal 6234 g_print (">> 'TRANSACTION_STATUS_CHANGED' from %s\n", __FUNCTION__); 6235 #endif 6236 g_signal_emit (G_OBJECT (cnc), gda_connection_signals[TRANSACTION_STATUS_CHANGED], 0); 6237 #ifdef GDA_DEBUG_signal 6238 g_print ("<< 'TRANSACTION_STATUS_CHANGED' from %s\n", __FUNCTION__); 6239 #endif 6240 } 6241 else { 6242 g_warning (_("Connection transaction status tracking: no transaction exists for %s"), "REMOVE SAVEPOINT"); 6243 } 6244 #ifdef GDA_DEBUG_NO 6245 if (cnc->priv->trans_status) 6246 gda_transaction_status_dump (cnc->priv->trans_status, 5); 6247 #endif 6248 6249 gda_connection_unlock ((GdaLockable*) cnc); 6250 } 6251 6252 /** 6253 * gda_connection_internal_statement_executed: (skip) 6254 * @cnc: a #GdaConnection 6255 * @stmt: a #GdaStatement which has been executed 6256 * @params: (allow-none): execution's parameters 6257 * @error: a #GdaConnectionEvent if the execution failed, or %NULL 6258 * 6259 * Internal functions to be called by database providers when a statement has been executed 6260 * to keep track of the transaction status of the connection 6261 */ 6262 void 6263 gda_connection_internal_statement_executed (GdaConnection *cnc, GdaStatement *stmt, 6264 G_GNUC_UNUSED GdaSet *params, GdaConnectionEvent *error) 6265 { 6266 if (!error || (error && (gda_connection_event_get_event_type (error) != GDA_CONNECTION_EVENT_ERROR))) { 6267 const GdaSqlStatement *sqlst; 6268 GdaSqlStatementTransaction *trans; 6269 sqlst = _gda_statement_get_internal_struct (stmt); 6270 trans = (GdaSqlStatementTransaction*) sqlst->contents; /* warning: this may be inaccurate if stmt_type is not 6271 a transaction type, but the compiler does not care */ 6272 6273 switch (sqlst->stmt_type) { 6274 case GDA_SQL_STATEMENT_BEGIN: 6275 gda_connection_internal_transaction_started (cnc, NULL, trans->trans_name, 6276 trans->isolation_level); 6277 break; 6278 case GDA_SQL_STATEMENT_ROLLBACK: 6279 gda_connection_internal_transaction_rolledback (cnc, trans->trans_name); 6280 break; 6281 case GDA_SQL_STATEMENT_COMMIT: 6282 gda_connection_internal_transaction_committed (cnc, trans->trans_name); 6283 break; 6284 case GDA_SQL_STATEMENT_SAVEPOINT: 6285 gda_connection_internal_savepoint_added (cnc, NULL, trans->trans_name); 6286 break; 6287 case GDA_SQL_STATEMENT_ROLLBACK_SAVEPOINT: 6288 gda_connection_internal_savepoint_rolledback (cnc, trans->trans_name); 6289 break; 6290 case GDA_SQL_STATEMENT_DELETE_SAVEPOINT: 6291 gda_connection_internal_savepoint_removed (cnc, trans->trans_name); 6292 break; 6293 default: { 6294 GdaTransactionStatus *st = NULL; 6295 6296 gda_connection_lock ((GdaLockable*) cnc); 6297 6298 if (cnc->priv->trans_status) 6299 st = gda_transaction_status_find_current (cnc->priv->trans_status, NULL, FALSE); 6300 if (st) { 6301 if (sqlst->sql) 6302 gda_transaction_status_add_event_sql (st, sqlst->sql, error); 6303 else { 6304 gchar *sql; 6305 sql = gda_statement_to_sql_extended (stmt, cnc, NULL, 6306 GDA_STATEMENT_SQL_PARAMS_SHORT, 6307 NULL, NULL); 6308 gda_transaction_status_add_event_sql (st, sql, error); 6309 g_free (sql); 6310 } 6311 } 6312 #ifdef GDA_DEBUG_signal 6313 g_print (">> 'TRANSACTION_STATUS_CHANGED' from %s\n", __FUNCTION__); 6314 #endif 6315 g_signal_emit (G_OBJECT (cnc), gda_connection_signals[TRANSACTION_STATUS_CHANGED], 0); 6316 #ifdef GDA_DEBUG_signal 6317 g_print ("<< 'TRANSACTION_STATUS_CHANGED' from %s\n", __FUNCTION__); 6318 #endif 6319 #ifdef GDA_DEBUG_NO 6320 if (cnc->priv->trans_status) 6321 gda_transaction_status_dump (cnc->priv->trans_status, 5); 6322 #endif 6323 gda_connection_unlock ((GdaLockable*) cnc); 6324 break; 6325 } 6326 } 6327 } 6328 } 6329 6330 /** 6331 * gda_connection_internal_change_transaction_state: (skip) 6332 * @cnc: a #GdaConnection 6333 * @newstate: the new state 6334 * 6335 * Internal function to be called by database providers to force a transaction status 6336 * change. 6337 */ 6338 void 6339 gda_connection_internal_change_transaction_state (GdaConnection *cnc, 6340 GdaTransactionStatusState newstate) 6341 { 6342 g_return_if_fail (GDA_IS_CONNECTION (cnc)); 6343 6344 gda_connection_lock ((GdaLockable*) cnc); 6345 6346 g_return_if_fail (cnc->priv->trans_status); 6347 6348 if (cnc->priv->trans_status->state == newstate) 6349 return; 6350 6351 cnc->priv->trans_status->state = newstate; 6352 #ifdef GDA_DEBUG_signal 6353 g_print (">> 'TRANSACTION_STATUS_CHANGED' from %s\n", __FUNCTION__); 6354 #endif 6355 g_signal_emit (G_OBJECT (cnc), gda_connection_signals[TRANSACTION_STATUS_CHANGED], 0); 6356 #ifdef GDA_DEBUG_signal 6357 g_print ("<< 'TRANSACTION_STATUS_CHANGED' from %s\n", __FUNCTION__); 6358 #endif 6359 gda_connection_unlock ((GdaLockable*) cnc); 6360 } 6361 6362 /** 6363 * gda_connection_internal_reset_transaction_status: (skip) 6364 * @cnc: a #GdaConnection 6365 * 6366 * Internal function to be called by database providers to reset the transaction status. 6367 */ 6368 void 6369 gda_connection_internal_reset_transaction_status (GdaConnection *cnc) 6370 { 6371 g_return_if_fail (GDA_IS_CONNECTION (cnc)); 6372 6373 gda_connection_lock ((GdaLockable*) cnc); 6374 if (cnc->priv->trans_status) { 6375 g_object_unref (cnc->priv->trans_status); 6376 cnc->priv->trans_status = NULL; 6377 #ifdef GDA_DEBUG_signal 6378 g_print (">> 'TRANSACTION_STATUS_CHANGED' from %s\n", __FUNCTION__); 6379 #endif 6380 g_signal_emit (G_OBJECT (cnc), gda_connection_signals[TRANSACTION_STATUS_CHANGED], 0); 6381 #ifdef GDA_DEBUG_signal 6382 g_print ("<< 'TRANSACTION_STATUS_CHANGED' from %s\n", __FUNCTION__); 6383 #endif 6384 } 6385 gda_connection_unlock ((GdaLockable*) cnc); 6386 } 6387 6388 /* 6389 * Prepared statements handling 6390 */ 6391 6392 static void prepared_stmts_stmt_reset_cb (GdaStatement *gda_stmt, GdaConnection *cnc); 6393 6394 static void 6395 prepared_stmts_stmt_reset_cb (GdaStatement *gda_stmt, GdaConnection *cnc) 6396 { 6397 gda_connection_lock ((GdaLockable*) cnc); 6398 g_object_ref (gda_stmt); 6399 6400 g_signal_handlers_disconnect_by_func (gda_stmt, G_CALLBACK (prepared_stmts_stmt_reset_cb), cnc); 6401 g_assert (cnc->priv->prepared_stmts); 6402 g_hash_table_remove (cnc->priv->prepared_stmts, gda_stmt); 6403 6404 g_object_unref (gda_stmt); 6405 gda_connection_unlock ((GdaLockable*) cnc); 6406 } 6407 6408 static void 6409 prepared_stms_foreach_func (GdaStatement *gda_stmt, G_GNUC_UNUSED GdaPStmt *prepared_stmt, GdaConnection *cnc) 6410 { 6411 g_object_ref (gda_stmt); 6412 g_signal_handlers_disconnect_by_func (gda_stmt, G_CALLBACK (prepared_stmts_stmt_reset_cb), cnc); 6413 g_object_unref (gda_stmt); 6414 } 6415 6416 typedef struct { 6417 GdaStatement *statement; 6418 GdaPStmt *prepared_stmt; 6419 } PreparedStatementRef; 6420 6421 PreparedStatementRef* 6422 _gda_prepared_estatement_new (GdaStatement *stmt, GdaPStmt *pstmt) { 6423 PreparedStatementRef *nps = g_new0(PreparedStatementRef,1); 6424 nps->statement = g_object_ref (stmt); 6425 nps->prepared_stmt = g_object_ref (pstmt); 6426 return nps; 6427 } 6428 6429 void 6430 _gda_prepared_estatement_free (PreparedStatementRef *ps) { 6431 g_object_unref (ps->statement); 6432 g_object_unref (ps->prepared_stmt); 6433 } 6434 6435 /** 6436 * gda_connection_add_prepared_statement: 6437 * @cnc: a #GdaConnection object 6438 * @gda_stmt: a #GdaStatement object 6439 * @prepared_stmt: a prepared statement object (as a #GdaPStmt object, or more likely a descendant) 6440 * 6441 * Declares that @prepared_stmt is a prepared statement object associated to @gda_stmt within the connection 6442 * (meaning the connection increments the reference counter of @prepared_stmt). 6443 * 6444 * If @gda_stmt changes or is destroyed, the the association will be lost and the connection will lose the 6445 * reference it has on @prepared_stmt. 6446 */ 6447 void 6448 gda_connection_add_prepared_statement (GdaConnection *cnc, GdaStatement *gda_stmt, GdaPStmt *prepared_stmt) 6449 { 6450 g_return_if_fail (GDA_IS_CONNECTION (cnc)); 6451 g_return_if_fail (GDA_IS_STATEMENT (gda_stmt)); 6452 g_return_if_fail (GDA_IS_PSTMT (prepared_stmt)); 6453 // Hold a reference until the end of the method 6454 g_object_ref (prepared_stmt); 6455 g_object_ref (gda_stmt); 6456 6457 gda_connection_lock ((GdaLockable*) cnc); 6458 6459 if (!cnc->priv->prepared_stmts) 6460 cnc->priv->prepared_stmts = g_hash_table_new_full (g_direct_hash, g_direct_equal, 6461 NULL, _gda_prepared_estatement_free); 6462 g_hash_table_remove (cnc->priv->prepared_stmts, gda_stmt); 6463 PreparedStatementRef *ref = _gda_prepared_estatement_new (gda_stmt, prepared_stmt); 6464 g_hash_table_insert (cnc->priv->prepared_stmts, gda_stmt, ref); 6465 6466 g_signal_connect (G_OBJECT (gda_stmt), "reset", 6467 G_CALLBACK (prepared_stmts_stmt_reset_cb), cnc); 6468 6469 gda_connection_unlock ((GdaLockable*) cnc); 6470 g_object_unref (prepared_stmt); 6471 g_object_unref (gda_stmt); 6472 } 6473 6474 /** 6475 * gda_connection_get_prepared_statement: 6476 * @cnc: a #GdaConnection object 6477 * @gda_stmt: a #GdaStatement object 6478 * 6479 * Retrieves a pointer to an object representing a prepared statement for @gda_stmt within @cnc. The 6480 * association must have been done using gda_connection_add_prepared_statement(). 6481 * 6482 * Returns: (transfer none): the prepared statement, or %NULL if no association exists 6483 */ 6484 GdaPStmt * 6485 gda_connection_get_prepared_statement (GdaConnection *cnc, GdaStatement *gda_stmt) 6486 { 6487 GdaPStmt *retval = NULL; 6488 6489 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 6490 6491 gda_connection_lock ((GdaLockable*) cnc); 6492 if (cnc->priv->prepared_stmts) { 6493 PreparedStatementRef *ref = g_hash_table_lookup (cnc->priv->prepared_stmts, gda_stmt); 6494 if (ref) 6495 retval = ref->prepared_stmt; 6496 } 6497 gda_connection_unlock ((GdaLockable*) cnc); 6498 6499 return retval; 6500 } 6501 6502 /** 6503 * gda_connection_del_prepared_statement: 6504 * @cnc: a #GdaConnection object 6505 * @gda_stmt: a #GdaStatement object 6506 * 6507 * Removes any prepared statement associated to @gda_stmt in @cnc: this undoes what 6508 * gda_connection_add_prepared_statement() does. 6509 */ 6510 void 6511 gda_connection_del_prepared_statement (GdaConnection *cnc, GdaStatement *gda_stmt) 6512 { 6513 g_return_if_fail (cnc != NULL); 6514 6515 gda_connection_lock ((GdaLockable*) cnc); 6516 g_return_if_fail (GDA_IS_CONNECTION (cnc)); 6517 g_object_ref (gda_stmt); 6518 if (gda_connection_get_prepared_statement (cnc, gda_stmt)) 6519 prepared_stmts_stmt_reset_cb (gda_stmt, cnc); 6520 g_object_unref (gda_stmt); 6521 gda_connection_unlock ((GdaLockable*) cnc); 6522 } 6523 6524 /* 6525 * Provider's specific connection data management 6526 */ 6527 6528 /** 6529 * gda_connection_internal_set_provider_data: (skip) 6530 * @cnc: a #GdaConnection object 6531 * @data: an opaque structure, known only to the provider for which @cnc is opened 6532 * @destroy_func: function to call when the connection closes and @data needs to be destroyed 6533 * 6534 * Note: calling this function more than once will not make it call @destroy_func on any previously 6535 * set opaque @data, you'll have to do it yourself. 6536 */ 6537 void 6538 gda_connection_internal_set_provider_data (GdaConnection *cnc, gpointer data, GDestroyNotify destroy_func) 6539 { 6540 6541 g_return_if_fail (GDA_IS_CONNECTION (cnc)); 6542 6543 gda_connection_lock ((GdaLockable*) cnc); 6544 cnc->priv->provider_data = data; 6545 cnc->priv->provider_data_destroy_func = destroy_func; 6546 gda_connection_unlock ((GdaLockable*) cnc); 6547 } 6548 6549 /** 6550 * gda_connection_internal_get_provider_data: (skip) 6551 * @cnc: a #GdaConnection object 6552 * 6553 * Get the opaque pointer previously set using gda_connection_internal_set_provider_data(). 6554 * If it's not set, then add a connection event and returns %NULL 6555 * 6556 * Returns: (allow-none): the pointer to the opaque structure set using gda_connection_internal_set_provider_data(), or %NULL 6557 */ 6558 gpointer 6559 gda_connection_internal_get_provider_data (GdaConnection *cnc) 6560 { 6561 return gda_connection_internal_get_provider_data_error (cnc, NULL); 6562 } 6563 6564 /** 6565 * gda_connection_internal_get_provider_data_error: (skip) 6566 * @cnc: a #GdaConnection object 6567 * @error: (allow-none): a place to store errors, or %NULL 6568 * 6569 * Get the opaque pointer previously set using gda_connection_internal_set_provider_data(). 6570 * If it's not set, then add a connection event and returns %NULL 6571 * 6572 * Returns: (allow-none): the pointer to the opaque structure set using gda_connection_internal_set_provider_data(), or %NULL 6573 * 6574 * Since: 5.0.2 6575 */ 6576 gpointer 6577 gda_connection_internal_get_provider_data_error (GdaConnection *cnc, GError **error) 6578 { 6579 gpointer retval; 6580 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 6581 6582 retval = cnc->priv->provider_data; 6583 if (!retval) 6584 g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_CLOSED_ERROR, 6585 _("Connection is closed")); 6586 return retval; 6587 } 6588 6589 /** 6590 * gda_connection_get_meta_store: 6591 * @cnc: a #GdaConnection object 6592 * 6593 * Get or initializes the #GdaMetaStore associated to @cnc 6594 * 6595 * Returns: (transfer none): a #GdaMetaStore object 6596 */ 6597 GdaMetaStore * 6598 gda_connection_get_meta_store (GdaConnection *cnc) 6599 { 6600 GdaMetaStore *store = NULL; 6601 6602 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); 6603 g_mutex_lock (& cnc->priv->object_mutex); 6604 if (!cnc->priv->meta_store) { 6605 ThreadConnectionData *cdata = NULL; 6606 if (cnc->priv->is_thread_wrapper) { 6607 cdata = (ThreadConnectionData*) gda_connection_internal_get_provider_data (cnc); 6608 if (cdata && cdata->sub_connection->priv->meta_store) { 6609 cnc->priv->meta_store = g_object_ref (cdata->sub_connection->priv->meta_store); 6610 store = cnc->priv->meta_store; 6611 } 6612 } 6613 if (!store) { 6614 cnc->priv->meta_store = gda_meta_store_new (NULL); 6615 if (cnc->priv->is_thread_wrapper) 6616 cdata->sub_connection->priv->meta_store = 6617 g_object_ref (cnc->priv->meta_store); 6618 } 6619 } 6620 store = cnc->priv->meta_store; 6621 g_mutex_unlock (& cnc->priv->object_mutex); 6622 return store; 6623 } 6624 6625 /* 6626 * This method is useful only in a multi threading environment (it has no effect in a 6627 * single thread program). 6628 * Locks @cnc for the current thread. If the lock can't be obtained, then the current thread 6629 * will be blocked until it can acquire @cnc's lock. 6630 * 6631 * The cases when the connection can't be locked are: 6632 * <itemizedlist> 6633 * <listitem><para>another thread is already using the connection</para></listitem> 6634 * <listitem><para>the connection can only be used by a single thread (see the 6635 * <link linkend="GdaConnection--thread-owner">thread-owner</link> property)</para></listitem> 6636 * </itemizedlist> 6637 * 6638 * To avoid the thread being blocked (possibly forever if the single thread which can use the 6639 * connection is not the current thead), then it is possible to use gda_connection_trylock() instead. 6640 */ 6641 static void 6642 gda_connection_lock (GdaLockable *lockable) 6643 { 6644 GdaConnection *cnc = (GdaConnection *) lockable; 6645 6646 g_rec_mutex_lock (& cnc->priv->rmutex); 6647 if (cnc->priv->unique_possible_thread && 6648 (cnc->priv->unique_possible_thread != g_thread_self ())) { 6649 g_rec_mutex_unlock (& cnc->priv->rmutex); 6650 g_mutex_lock (& cnc->priv->object_mutex); 6651 6652 while (1) { 6653 if (cnc->priv->unique_possible_thread && 6654 (cnc->priv->unique_possible_thread != g_thread_self ())) { 6655 #ifdef GDA_DEBUG_CNC_LOCK 6656 g_print ("Wainting th %p, now %p (cond %p, mutex%p)\n", g_thread_self(), 6657 cnc->priv->unique_possible_thread, &cnc->priv->unique_possible_cond, 6658 cnc->priv->object_mutex); 6659 #endif 6660 gint64 end_time; 6661 end_time = g_get_monotonic_time () + 5 * G_TIME_SPAN_SECOND; 6662 while (! g_cond_wait_until (& cnc->priv->unique_possible_cond, 6663 & cnc->priv->object_mutex, end_time)); 6664 } 6665 else if (g_rec_mutex_trylock (& cnc->priv->rmutex)) { 6666 g_mutex_unlock (& cnc->priv->object_mutex); 6667 break; 6668 } 6669 } 6670 } 6671 } 6672 6673 /* 6674 * Tries to lock @cnc for the exclusive usage of the current thread, as gda_connection_lock(), except 6675 * that if it can't, then the calling thread is not locked by it simply returns FALSE. 6676 * 6677 * Returns: TRUE if successfully locked, or FALSE if lock could not be acquired 6678 */ 6679 static gboolean 6680 gda_connection_trylock (GdaLockable *lockable) 6681 { 6682 gboolean retval; 6683 GdaConnection *cnc = (GdaConnection *) lockable; 6684 6685 retval = g_rec_mutex_trylock (& cnc->priv->rmutex); 6686 if (retval && cnc->priv->unique_possible_thread && 6687 (cnc->priv->unique_possible_thread != g_thread_self ())) { 6688 retval = FALSE; 6689 g_rec_mutex_unlock (& cnc->priv->rmutex); 6690 } 6691 return retval; 6692 } 6693 6694 /* 6695 * Unlocks @cnc's usage. Any other thread blocked (after having called gda_connection_lock()) gets 6696 * the opportunity to lock the connection. 6697 */ 6698 static void 6699 gda_connection_unlock (GdaLockable *lockable) 6700 { 6701 GdaConnection *cnc = (GdaConnection *) lockable; 6702 g_rec_mutex_unlock (& cnc->priv->rmutex); 6703 } 6704 6705 /* 6706 * REM: if @for_ident is %FALSE, then the keywords are converted to upper case 6707 */ 6708 static gchar * 6709 get_next_word (gchar *str, gboolean for_ident, gchar **out_next) 6710 { 6711 if (!str) { 6712 *out_next = NULL; 6713 return NULL; 6714 } 6715 6716 gchar *start; 6717 gchar *ptr; 6718 gboolean inquotes = FALSE; 6719 for (ptr = str; *ptr; ptr++) { 6720 if ((*ptr == ' ') || (*ptr == '\n') || (*ptr == '\t') || (*ptr == '\r')) 6721 continue; 6722 break; 6723 } 6724 start = ptr; 6725 /*g_print ("%s ([%s]) => [%s]", __FUNCTION__, str, start);*/ 6726 for (; *ptr; ptr++) { 6727 if ((*ptr >= 'a') && (*ptr <= 'z')) { 6728 if (! for_ident) 6729 *ptr += 'A' - 'a'; 6730 continue; 6731 } 6732 else if ((*ptr >= 'A') && (*ptr <= 'Z')) 6733 continue; 6734 else if ((*ptr >= '0') && (*ptr <= '9')) 6735 continue; 6736 else if (*ptr == '_') 6737 continue; 6738 else if (for_ident) { 6739 if ((*ptr == '"') || (*ptr == '\'') || (*ptr == '`')) { 6740 if (inquotes) { 6741 *ptr = '"'; 6742 inquotes = FALSE; 6743 ptr++; 6744 break; 6745 } 6746 else { 6747 *ptr = '"'; 6748 inquotes = TRUE; 6749 } 6750 continue; 6751 } 6752 } 6753 else if (inquotes) 6754 continue; 6755 break; 6756 } 6757 if (ptr != start) { 6758 if (*ptr) { 6759 *ptr = 0; 6760 *out_next = ptr + 1; 6761 } 6762 else 6763 *out_next = ptr; 6764 } 6765 else 6766 *out_next = NULL; 6767 /*g_print (" -- [%s]\n", *out_next);*/ 6768 return start; 6769 } 6770 6771 6772 /* 6773 * the contexts in returned list have: 6774 * - the @table_name attribute as a static string 6775 * - the @column_names[x] as a static string, not the @column_names array itself which has to be freed 6776 * 6777 * Returns: a new list of new #GdaMetaContext 6778 */ 6779 static GSList * 6780 meta_data_context_from_statement (GdaConnection *cnc, GdaStatement *stmt, GdaSet *params) 6781 { 6782 gboolean ignore_create_drop = FALSE; 6783 if (GDA_IS_VCONNECTION_DATA_MODEL (cnc)) 6784 /* meta data is updated when the virtual connection emits the 6785 * "vtable-created" or "vtable-dropped" signals 6786 */ 6787 ignore_create_drop = TRUE; 6788 6789 GdaMetaContext *context = NULL; 6790 gchar *sql, *current, *next; 6791 sql = gda_statement_to_sql (stmt, params, NULL); 6792 if (!sql) 6793 return NULL; 6794 6795 GSList *clist = NULL; 6796 current = get_next_word (sql, FALSE, &next); 6797 if (!current) 6798 goto out; 6799 6800 if (!strcmp (current, "ALTER") || 6801 (!ignore_create_drop && (!strcmp (current, "CREATE") || !strcmp (current, "DROP")))) { 6802 const gchar *tname = NULL; 6803 const gchar *opname; 6804 opname = current; 6805 current = get_next_word (next, FALSE, &next); 6806 if (current && (!strcmp (current, "TABLE") || !strcmp (current, "VIEW"))) { 6807 tname = get_next_word (next, TRUE, &next); 6808 if ((! strcmp (opname, "CREATE") || !strcmp (opname, "DROP")) 6809 && !g_ascii_strcasecmp (tname, "IF")) { 6810 gchar *tmpnext; 6811 tmpnext = next; 6812 if (! strcmp (opname, "CREATE")) { 6813 const gchar *s1, *s2; 6814 s1 = get_next_word (tmpnext, FALSE, &tmpnext); 6815 s2 = get_next_word (tmpnext, FALSE, &tmpnext); 6816 if (! strcmp (s1, "NOT") && 6817 ! strcmp (s2, "EXISTS")) { 6818 next = tmpnext; 6819 tname = get_next_word (next, TRUE, &next); 6820 } 6821 } 6822 else { 6823 const gchar *s1; 6824 s1 = get_next_word (tmpnext, FALSE, &tmpnext); 6825 if (! strcmp (s1, "EXISTS")) { 6826 next = tmpnext; 6827 tname = get_next_word (next, TRUE, &next); 6828 } 6829 } 6830 } 6831 } 6832 if (tname) { 6833 gchar *tmp; 6834 /*g_print ("CONTEXT: update for table [%s]\n", tname);*/ 6835 context = g_new0 (GdaMetaContext, 1); 6836 context->table_name = "_tables"; 6837 context->size = 1; 6838 context->column_names = g_new0 (gchar *, 1); 6839 context->column_names[0] = "table_name"; 6840 context->column_values = g_new0 (GValue *, 1); 6841 tmp = gda_sql_identifier_quote (tname, cnc, cnc->priv->provider_obj, 6842 TRUE, 6843 cnc->priv->options & GDA_CONNECTION_OPTIONS_SQL_IDENTIFIERS_CASE_SENSITIVE); 6844 g_value_take_string ((context->column_values[0] = gda_value_new (G_TYPE_STRING)), 6845 tmp); 6846 clist = g_slist_prepend (clist, context); 6847 6848 /* seek RENAME TO */ 6849 current = get_next_word (next, FALSE, &next); 6850 if (!current || strcmp (current, "RENAME")) 6851 goto out; 6852 current = get_next_word (next, FALSE, &next); 6853 if (!current || strcmp (current, "TO")) 6854 goto out; 6855 tname = get_next_word (next, TRUE, &next); 6856 if (tname) { 6857 gchar *tmp; 6858 /*g_print ("CONTEXT: update for table [%s]\n", tname);*/ 6859 context = g_new0 (GdaMetaContext, 1); 6860 context->table_name = "_tables"; 6861 context->size = 1; 6862 context->column_names = g_new0 (gchar *, 1); 6863 context->column_names[0] = "table_name"; 6864 context->column_values = g_new0 (GValue *, 1); 6865 tmp = gda_sql_identifier_quote (tname, cnc, cnc->priv->provider_obj, 6866 TRUE, 6867 cnc->priv->options & GDA_CONNECTION_OPTIONS_SQL_IDENTIFIERS_CASE_SENSITIVE); 6868 g_value_take_string ((context->column_values[0] = gda_value_new (G_TYPE_STRING)), 6869 tmp); 6870 clist = g_slist_prepend (clist, context); 6871 } 6872 } 6873 } 6874 6875 out: 6876 g_free (sql); 6877 return clist; 6878 } 6879 6880 /* 6881 * update_meta_store_after_statement_exec 6882 * 6883 * Updates the meta store associated to @cnc if it exists and if @cnc has the 6884 * GDA_CONNECTION_OPTIONS_AUTO_META_DATA flag. 6885 */ 6886 static void 6887 update_meta_store_after_statement_exec (GdaConnection *cnc, GdaStatement *stmt, GdaSet *params) 6888 { 6889 if (! cnc->priv->meta_store || 6890 ! (cnc->priv->options & GDA_CONNECTION_OPTIONS_AUTO_META_DATA)) 6891 return; 6892 6893 GdaSqlStatementType type; 6894 type = gda_statement_get_statement_type (stmt); 6895 if (type == GDA_SQL_STATEMENT_BEGIN) { 6896 /* initialize cnc->priv->trans_meta_context if meta store's connection is not @cnc */ 6897 GdaConnection *mscnc; 6898 mscnc = gda_meta_store_get_internal_connection (cnc->priv->meta_store); 6899 if (cnc != mscnc) { 6900 g_assert (! cnc->priv->trans_meta_context); 6901 cnc->priv->trans_meta_context = g_array_new (FALSE, FALSE, sizeof (GdaMetaContext*)); 6902 } 6903 return; 6904 } 6905 else if (type == GDA_SQL_STATEMENT_ROLLBACK) { 6906 /* re-run all the meta store updates started since the BEGIN */ 6907 GdaConnection *mscnc; 6908 mscnc = gda_meta_store_get_internal_connection (cnc->priv->meta_store); 6909 if (cnc != mscnc) { 6910 gsize i; 6911 g_assert (cnc->priv->trans_meta_context); 6912 for (i = 0; i < cnc->priv->trans_meta_context->len; i++) { 6913 GdaMetaContext *context; 6914 GError *lerror = NULL; 6915 context = g_array_index (cnc->priv->trans_meta_context, GdaMetaContext*, i); 6916 if (! gda_connection_update_meta_store (cnc, context, &lerror)) 6917 add_connection_event_from_error (cnc, &lerror); 6918 auto_update_meta_context_free (context); 6919 } 6920 g_array_free (cnc->priv->trans_meta_context, TRUE); 6921 cnc->priv->trans_meta_context = NULL; 6922 } 6923 return; 6924 } 6925 else if (type == GDA_SQL_STATEMENT_COMMIT) { 6926 /* get rid of the meta store updates */ 6927 GdaConnection *mscnc; 6928 mscnc = gda_meta_store_get_internal_connection (cnc->priv->meta_store); 6929 if (cnc != mscnc) { 6930 gsize i; 6931 g_assert (cnc->priv->trans_meta_context); 6932 for (i = 0; i < cnc->priv->trans_meta_context->len; i++) { 6933 GdaMetaContext *context; 6934 context = g_array_index (cnc->priv->trans_meta_context, GdaMetaContext*, i); 6935 auto_update_meta_context_free (context); 6936 } 6937 g_array_free (cnc->priv->trans_meta_context, TRUE); 6938 cnc->priv->trans_meta_context = NULL; 6939 } 6940 return; 6941 } 6942 else if (type != GDA_SQL_STATEMENT_UNKNOWN) 6943 return; 6944 6945 GSList *clist, *list; 6946 clist = meta_data_context_from_statement (cnc, stmt, params); 6947 for (list = clist; list; list = list->next) { 6948 GdaMetaContext *context; 6949 context = (GdaMetaContext*) list->data; 6950 if (context) { 6951 GError *lerror = NULL; 6952 if (! gda_connection_update_meta_store (cnc, context, &lerror)) 6953 add_connection_event_from_error (cnc, &lerror); 6954 6955 if (cnc->priv->trans_meta_context) 6956 g_array_prepend_val (cnc->priv->trans_meta_context, context); 6957 else 6958 auto_update_meta_context_free (context); 6959 } 6960 } 6961 g_slist_free (clist); 6962 } 6963 6964 void 6965 _gda_connection_signal_meta_table_update (GdaConnection *cnc, const gchar *table_name) 6966 { 6967 if (! cnc->priv->meta_store || 6968 ! (cnc->priv->options & GDA_CONNECTION_OPTIONS_AUTO_META_DATA)) 6969 return; 6970 6971 GdaMetaContext *context; 6972 gchar **split; 6973 gchar *tmp; 6974 /*g_print ("CONTEXT: update for table [%s]\n", table_name);*/ 6975 split = gda_sql_identifier_split (table_name); 6976 if (!split) 6977 return; 6978 if (!split [0]) { 6979 g_strfreev (split); 6980 return; 6981 } 6982 6983 context = g_new0 (GdaMetaContext, 1); 6984 context->table_name = "_tables"; 6985 6986 if (split [1]) { 6987 context->size = 2; 6988 context->column_names = g_new0 (gchar *, context->size); 6989 context->column_names[0] = "table_schema"; 6990 context->column_names[1] = "table_name"; 6991 context->column_values = g_new0 (GValue *, context->size); 6992 tmp = gda_sql_identifier_quote (split[0], cnc, cnc->priv->provider_obj, 6993 TRUE, 6994 cnc->priv->options & GDA_CONNECTION_OPTIONS_SQL_IDENTIFIERS_CASE_SENSITIVE); 6995 g_value_take_string ((context->column_values[0] = gda_value_new (G_TYPE_STRING)), 6996 tmp); 6997 tmp = gda_sql_identifier_quote (split[1], cnc, cnc->priv->provider_obj, 6998 TRUE, 6999 cnc->priv->options & GDA_CONNECTION_OPTIONS_SQL_IDENTIFIERS_CASE_SENSITIVE); 7000 g_value_take_string ((context->column_values[1] = gda_value_new (G_TYPE_STRING)), 7001 tmp); 7002 } 7003 else { 7004 context->size = 1; 7005 context->column_names = g_new0 (gchar *, context->size); 7006 context->column_names[0] = "table_name"; 7007 context->column_values = g_new0 (GValue *, context->size); 7008 tmp = gda_sql_identifier_quote (split[0], cnc, cnc->priv->provider_obj, 7009 TRUE, 7010 cnc->priv->options & GDA_CONNECTION_OPTIONS_SQL_IDENTIFIERS_CASE_SENSITIVE); 7011 g_value_take_string ((context->column_values[0] = gda_value_new (G_TYPE_STRING)), 7012 tmp); 7013 } 7014 7015 GError *lerror = NULL; 7016 if (! gda_connection_update_meta_store (cnc, context, &lerror)) 7017 add_connection_event_from_error (cnc, &lerror); 7018 7019 if (cnc->priv->trans_meta_context) 7020 g_array_prepend_val (cnc->priv->trans_meta_context, context); 7021 else 7022 auto_update_meta_context_free (context); 7023 7024 g_strfreev (split); 7025 } 7026 7027 /* 7028 * Free @context which must have been created by meta_data_context_from_statement() 7029 */ 7030 static void 7031 auto_update_meta_context_free (GdaMetaContext *context) 7032 { 7033 gint i; 7034 context->table_name = NULL; /* don't free */ 7035 g_free (context->column_names); /* don't free the strings in the array */ 7036 for (i = 0; i < context->size; i++) 7037 gda_value_free (context->column_values[i]); 7038 g_free (context->column_values); 7039 g_free (context); 7040 } 7041 7042 7043 /* 7044 * _gda_connection_get_table_virtual_name 7045 * @table_name: a non %NULL string 7046 * 7047 * Returns: a new string. 7048 */ 7049 gchar * 7050 _gda_connection_compute_table_virtual_name (GdaConnection *cnc, const gchar *table_name) 7051 { 7052 gchar **array; 7053 7054 g_assert (table_name && *table_name); 7055 array = gda_sql_identifier_split (table_name); 7056 if (array) { 7057 GString *string = NULL; 7058 gint i; 7059 gchar *tmp; 7060 for (i = 0; ; i++) { 7061 if (array [i]) { 7062 tmp = gda_sql_identifier_quote (array[i], cnc, NULL, TRUE, FALSE); 7063 if (string) { 7064 g_string_append_c (string, '.'); 7065 g_string_append (string, tmp); 7066 } 7067 else 7068 string = g_string_new (tmp); 7069 } 7070 else 7071 break; 7072 } 7073 g_strfreev (array); 7074 return g_string_free (string, FALSE); 7075 } 7076 else { 7077 /* 7078 ** If X is a character that can be used in an identifier then 7079 ** IdChar(X) will be true. Otherwise it is false. 7080 ** 7081 ** For ASCII, any character with the high-order bit set is 7082 ** allowed in an identifier. For 7-bit characters, 7083 ** sqlite3IsIdChar[X] must be 1. 7084 */ 7085 static const char AsciiIdChar[] = { 7086 /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ 7087 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */ 7088 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */ 7089 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */ 7090 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */ 7091 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */ 7092 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */ 7093 }; 7094 #define IdChar(C) (((c=C)&0x80)!=0 || (c>0x1f && AsciiIdChar[c-0x20])) 7095 gchar *tmp, *ptr, c; 7096 tmp = g_strdup (table_name); 7097 7098 /* first try removing some double quotes only */ 7099 for (ptr = tmp; *ptr; ptr++) { 7100 if (! IdChar(*ptr)) { 7101 if ((*ptr == '"') && (ptr[1] == '"')) { 7102 gchar *ptr2; 7103 for (ptr2 = ptr; ptr2[2]; ptr2++) 7104 *ptr2 = ptr2[2]; 7105 *ptr2 = 0; 7106 } 7107 else if ((*ptr != '"') && (*ptr != '.')) 7108 *ptr = '_'; 7109 } 7110 } 7111 7112 ptr = NULL; 7113 if (strcmp (tmp, table_name)) 7114 ptr = _gda_connection_compute_table_virtual_name (cnc, tmp); 7115 7116 /* if it dow not work, replace all non IdChar character with '_' */ 7117 if (!ptr) { 7118 for (ptr = tmp; *ptr; ptr++) { 7119 if (! IdChar(*ptr)) 7120 *ptr = '_'; 7121 } 7122 ptr = _gda_connection_compute_table_virtual_name (cnc, tmp); 7123 } 7124 g_free (tmp); 7125 return ptr; 7126 } 7127 } 7128 7129 /* 7130 * Free connection's specific data 7131 */ 7132 static gpointer 7133 sub_thread_unref_connection (GdaConnection *cnc, G_GNUC_UNUSED GError **error) 7134 { 7135 /* WARNING: function executed in sub thread! */ 7136 g_object_unref (cnc); 7137 #ifdef GDA_DEBUG_NO 7138 g_print ("/%s()\n", __FUNCTION__); 7139 #endif 7140 return NULL; 7141 } 7142 7143 void 7144 _gda_thread_connection_data_free (ThreadConnectionData *cdata) 7145 { 7146 if (!cdata) 7147 return; 7148 7149 /* disconnect signals handlers */ 7150 gsize i; 7151 for (i = 0; i < cdata->handlers_ids->len; i++) { 7152 gulong hid = g_array_index (cdata->handlers_ids, gulong, i); 7153 gda_thread_wrapper_disconnect (cdata->wrapper, hid); 7154 } 7155 7156 /* unref cdata->sub_connection in sub thread */ 7157 guint jid; 7158 jid = gda_thread_wrapper_execute (cdata->wrapper, 7159 (GdaThreadWrapperFunc) sub_thread_unref_connection, 7160 cdata->sub_connection, NULL, NULL); 7161 gda_thread_wrapper_fetch_result (cdata->wrapper, TRUE, jid, NULL); 7162 g_object_unref (cdata->wrapper); 7163 7164 /* free async data */ 7165 if (cdata->async_tasks) { 7166 g_slist_foreach (cdata->async_tasks, (GFunc) _ThreadConnectionAsyncTask_free, NULL); 7167 g_slist_free (cdata->async_tasks); 7168 } 7169 7170 g_object_unref (cdata->cnc_provider); 7171 7172 g_free (cdata); 7173 } 7174 7175 void 7176 _gda_thread_connection_set_data (GdaConnection *cnc, ThreadConnectionData *cdata) 7177 { 7178 g_rec_mutex_lock (& cnc->priv->rmutex); 7179 if (cnc->priv->th_data) 7180 _gda_thread_connection_data_free (cnc->priv->th_data); 7181 cnc->priv->th_data = cdata; 7182 g_rec_mutex_unlock (& cnc->priv->rmutex); 7183 } 7184 7185 ThreadConnectionData * 7186 _gda_thread_connection_get_data (GdaConnection *cnc) 7187 { 7188 return cnc->priv->th_data; 7189 } 7190