[libgda] Multi threading and GdaSqlBuilder improvements
- From: Vivien Malerba <vivien src gnome org>
- To: svn-commits-list gnome org
- Subject: [libgda] Multi threading and GdaSqlBuilder improvements
- Date: Fri, 17 Apr 2009 16:36:23 -0400 (EDT)
commit 981374e707a6276b2fd4003a6c27228d16643365
Author: Vivien Malerba <malerba gnome-db org>
Date: Fri Apr 17 21:34:06 2009 +0200
Multi threading and GdaSqlBuilder improvements
* providers/postgres/gda-postgres-provider.c: fix for bug
#578748
* libgda/thread-wrapper/gda-thread-wrapper.c: don't attempt to
create a GdaThreadWrapper object if g_thread_supported() is FALSE
* libgda/thread-wrapper/Makefile.am:
* libgda/thread-wrapper/gda-thread-meta.[ch]: meta data
retreival implementation
* libgda/thread-wrapper/gda-thread-provider.[ch]:
- reuse the same GdaThreadWrapper object for providers which
can only be
accessed from a single thread
- correctly behave when g_thread_supported() is FALSE
- use new implementation of meta data retreival
* libgda/gda-server-provider.c: doc. correction
* libgda/gda-connection.c:
- removed debug message
- corrected locking in gda_connection_update_meta_store()
- return an error if the GDA_CONNECTION_OPTIONS_THREAD_SAFE
flag is specified
but g_thread_supported() is FALSE
- gda_connection_update_meta_store()'s implementation is now
generic (no specific
implementation for connections which use a thread wrapper)
* tools/gda-sql.c:
- use the GDA_CONNECTION_OPTIONS_THREAD_SAFE flag when opening
connections
- meta data retreival is now done in the background
(statements can be executed
while it is being done)
* libgda/Makefile.am:
* libgda/libgda.symbols:
* libgda/gda-repetitive-statement.[ch]: new object to prepare
the execution of a statement with several differents variables' values sets
* libgda/gda-connection.c: added gda_connection_repetitive_statement_execute()
* doc/C: doc.update
* configure.in: a system installed SQLite is now only searched
for if the --enable-system-sqlite option is passed, and the presence of the
sqlite3CreateFunc symbol is not anymore required. The only drawback of using a
system installed SQLite is that meta data regarding functions will not be
available
* Makefile.am:
* samples/MetaStore/background.c:
* samples/MetaStore/README: new example showing how to update
the meta data in the background (in a sub thread) using the GdaThreadWrapper
object
* libgda/handlers/gda-handler-time.c: fix mem leak
* samples/SqlBuilder/example.c:
* libgda/gda-sql-builder.[ch]: improved API and features of the
GdaSqlBuilder object
* libgda.doap: project description
---
ChangeLog | 44 ++
Makefile.am | 1 +
configure.in | 33 +-
doc/C/libgda-4.0-docs.sgml | 2 +
doc/C/libgda-4.0-sections.txt | 26 +-
doc/C/tmpl/gda-connection.sgml | 15 +
doc/C/tmpl/gda-repetitive-statement.sgml | 71 +++
doc/C/tmpl/gda-sql-statement.sgml | 4 +-
libgda.doap | 26 +
libgda/Makefile.am | 2 +
libgda/gda-connection-internal.h | 13 +
libgda/gda-connection.c | 142 +++--
libgda/gda-connection.h | 9 +-
libgda/gda-decl.h | 3 +
libgda/gda-repetitive-statement.c | 224 +++++++
libgda/gda-repetitive-statement.h | 55 ++
libgda/gda-server-provider.c | 2 +-
libgda/gda-sql-builder.c | 328 ++++++++--
libgda/gda-sql-builder.h | 20 +-
libgda/handlers/gda-handler-time.c | 1 +
libgda/libgda.symbols | 6 +
libgda/sql-parser/gda-statement-struct-parts.h | 2 +-
libgda/thread-wrapper/Makefile.am | 2 +
libgda/thread-wrapper/gda-thread-meta.c | 795 ++++++++++++++++++++++++
libgda/thread-wrapper/gda-thread-meta.h | 197 ++++++
libgda/thread-wrapper/gda-thread-provider.c | 87 +++-
libgda/thread-wrapper/gda-thread-provider.h | 2 +
libgda/thread-wrapper/gda-thread-wrapper.c | 9 +-
providers/postgres/gda-postgres-provider.c | 5 +-
samples/MetaStore/Makefile | 7 +-
samples/MetaStore/README | 30 +-
samples/MetaStore/background.c | 107 ++++
samples/SqlBuilder/example.c | 60 ++-
tools/gda-sql.c | 6 +-
34 files changed, 2178 insertions(+), 158 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index d1ebd8e..d5e6f15 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,47 @@
+2009-04-17 Vivien Malerba <malerba gnome-db org>
+
+ * providers/postgres/gda-postgres-provider.c: fix for bug #578748
+ * libgda/thread-wrapper/gda-thread-wrapper.c: don't attempt to create a GdaThreadWrapper
+ object if g_thread_supported() is FALSE
+ * libgda/thread-wrapper/Makefile.am:
+ * libgda/thread-wrapper/gda-thread-meta.[ch]: meta data retreival implementation
+ * libgda/thread-wrapper/gda-thread-provider.[ch]:
+ - reuse the same GdaThreadWrapper object for providers which can only be
+ accessed from a single thread
+ - correctly behave when g_thread_supported() is FALSE
+ - use new implementation of meta data retreival
+ * libgda/gda-server-provider.c: doc. correction
+ * libgda/gda-connection.c:
+ - removed debug message
+ - corrected locking in gda_connection_update_meta_store()
+ - return an error if the GDA_CONNECTION_OPTIONS_THREAD_SAFE flag is specified
+ but g_thread_supported() is FALSE
+ - gda_connection_update_meta_store()'s implementation is now generic (no specific
+ implementation for connections which use a thread wrapper)
+ * tools/gda-sql.c:
+ - use the GDA_CONNECTION_OPTIONS_THREAD_SAFE flag when opening connections
+ - meta data retreival is now done in the background (statements can be executed
+ while it is being done)
+ * libgda/Makefile.am:
+ * libgda/libgda.symbols:
+ * libgda/gda-repetitive-statement.[ch]: new object to prepare the execution of
+ a statement with several differents variables' values sets
+ * libgda/gda-connection.c: added gda_connection_repetitive_statement_execute()
+ * doc/C: doc.update
+ * configure.in: a system installed SQLite is now only searched for if the
+ --enable-system-sqlite option is passed, and the presence of the sqlite3CreateFunc
+ symbol is not anymore required. The only drawback of using a system installed
+ SQLite is that meta data regarding functions will not be available
+ * Makefile.am:
+ * samples/MetaStore/background.c:
+ * samples/MetaStore/README: new example showing how to update the meta data
+ in the background (in a sub thread) using the GdaThreadWrapper object
+ * libgda/handlers/gda-handler-time.c: fix mem leak
+ * samples/SqlBuilder/example.c:
+ * libgda/gda-sql-builder.[ch]: improved API and features of the GdaSqlBuilder
+ object
+ * libgda.doap: project description
+
2009-04-14 Vivien Malerba <malerba gnome-db org>
* libgda/thread-wrapper/Makefile.am:
diff --git a/Makefile.am b/Makefile.am
index ead5a4d..fc7fa6d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -65,6 +65,7 @@ example_files = \
samples/XSLT/transform.c \
samples/MetaStore/Makefile \
samples/MetaStore/README \
+ samples/MetaStore/background.c \
samples/MetaStore/example.c \
samples/Tree/Makefile \
samples/Tree/README \
diff --git a/configure.in b/configure.in
index 7d82ce2..548667d 100644
--- a/configure.in
+++ b/configure.in
@@ -1106,31 +1106,30 @@ if test x"$platform_win32" = "xyes"
then
AM_CONDITIONAL(HAVE_SQLITE, 0)
else
- SQLITE_MODULES="sqlite3 >= 3.6.0"
- PKG_CHECK_MODULES(SQLITE, $SQLITE_MODULES, have_sqlite=yes, have_sqlite=no)
- if test x"$have_sqlite" = "xyes"
- then
- AC_CHECK_LIB(sqlite3, sqlite3_table_column_metadata,[sqlite3_api=1], [sqlite3_api=0], $SQLITE_CFLAGS $SQLITE_LIBS)
+ AC_ARG_ENABLE(system-sqlite,
+ [ --enable-system-sqlite Use SQLite installed on the system [default=no]],
+ use_syst_sqlite="Yes", use_syst_sqlite="No")
+
+ if test "x$use_syst_sqlite" = "xYes"; then
+ SQLITE_MODULES="sqlite3 >= 3.6.11"
+ PKG_CHECK_MODULES(SQLITE, $SQLITE_MODULES, have_sqlite=yes, have_sqlite=no)
+ if test x"$have_sqlite" = "xyes"
+ then
+ AC_CHECK_LIB(sqlite3, sqlite3_table_column_metadata,[sqlite3_api=1], [sqlite3_api=0], $SQLITE_CFLAGS $SQLITE_LIBS)
- if test $sqlite3_api = 0
- then
- AC_MSG_RESULT([Installed SQLite was not compiled with the SQLITE_ENABLE_COLUMN_METADATA, using embedded SQLite])
- have_sqlite=no
- else
- AC_CHECK_LIB(sqlite3, sqlite3CreateFunc,[sqlite3_api=1], [sqlite3_api=0], $SQLITE_CFLAGS $SQLITE_LIBS)
if test $sqlite3_api = 0
- then
- AC_MSG_RESULT([Could not find the sqlite3CreateFunc symbol in installed SQLite library, using embedded SQLite])
+ then
+ AC_MSG_RESULT([Installed SQLite was not compiled with the SQLITE_ENABLE_COLUMN_METADATA, using embedded SQLite])
have_sqlite=no
- else
- AC_MSG_RESULT(Using this version of SQLite)
+ else
+ AC_MSG_RESULT(Note: using system installed version of SQLite, meta data for functions will not be available)
have_sqlite=yes
SQLITE_CFLAGS="$SQLITE_CFLAGS -DHAVE_SQLITE"
AC_SUBST(SQLITE_CFLAGS)
AC_SUBST(SQLITE_LIBS)
AC_SUBST(SQLITE_VERS)
- fi
- fi
+ fi
+ fi
fi
AM_CONDITIONAL(HAVE_SQLITE, test x"$have_sqlite" = "xyes")
fi
diff --git a/doc/C/libgda-4.0-docs.sgml b/doc/C/libgda-4.0-docs.sgml
index 5e6892b..2b067cd 100644
--- a/doc/C/libgda-4.0-docs.sgml
+++ b/doc/C/libgda-4.0-docs.sgml
@@ -95,6 +95,7 @@
<!ENTITY libgda-GdaHolder SYSTEM "xml/gda-holder.xml">
<!ENTITY libgda-GdaSet SYSTEM "xml/gda-set.xml">
<!ENTITY libgda-GdaStatement SYSTEM "xml/gda-statement.xml">
+<!ENTITY libgda-GdaRepetitiveStatement SYSTEM "xml/gda-repetitive-statement.xml">
<!ENTITY libgda-GdaSqlStatement SYSTEM "xml/gda-sql-statement.xml">
<!ENTITY libgda-GdaBatch SYSTEM "xml/gda-batch.xml">
<!ENTITY libgda-GdaSqlParser SYSTEM "xml/gda-sql-parser.xml">
@@ -545,6 +546,7 @@
&libgda-GdaSqlParser;
&libgda-GdaSqlBuilder;
&libgda-GdaStatement;
+ &libgda-GdaRepetitiveStatement;
&libgda-GdaBatch;
&libgda-GdaHolder;
&libgda-GdaSet;
diff --git a/doc/C/libgda-4.0-sections.txt b/doc/C/libgda-4.0-sections.txt
index 0e5ae5a..aa74914 100644
--- a/doc/C/libgda-4.0-sections.txt
+++ b/doc/C/libgda-4.0-sections.txt
@@ -123,6 +123,7 @@ gda_connection_statement_execute_select
gda_connection_statement_execute_select_full
gda_connection_statement_execute_select_fullv
gda_connection_statement_execute_non_select
+gda_connection_repetitive_statement_execute
gda_connection_batch_execute
gda_connection_begin_transaction
gda_connection_commit_transaction
@@ -1644,13 +1645,17 @@ gda_sql_builder_get_statement
gda_sql_builder_get_sql_statement
<SUBSECTION>
gda_sql_builder_set_table
-gda_sql_builder_add_field_value
+gda_sql_builder_add_field
<SUBSECTION>
gda_sql_builder_literal
gda_sql_builder_expr
gda_sql_builder_param
<SUBSECTION>
-gda_sql_builder_cond2
+gda_sql_builder_cond
+<SUBSECTION>
+gda_sql_builder_select_add_target
+gda_sql_builder_select_join_targets
+gda_sql_builder_join_add_field
<SUBSECTION Standard>
GDA_SQL_BUILDER
GDA_SQL_BUILDER_GET_CLASS
@@ -1662,6 +1667,7 @@ gda_sql_builder_get_type
<SECTION>
<FILE>gda-thread-wrapper</FILE>
<TITLE>GdaThreadWrapper</TITLE>
+<INCLUDE>libgda/thread-wrapper/gda-thread-wrapper.h</INCLUDE>
GdaThreadWrapper
gda_thread_wrapper_new
GdaThreadWrapperFunc
@@ -1681,3 +1687,19 @@ GDA_IS_THREAD_WRAPPER
GDA_TYPE_THREAD_WRAPPER
gda_thread_wrapper_get_type
</SECTION>
+
+<SECTION>
+<FILE>gda-repetitive-statement</FILE>
+<TITLE>GdaRepetitiveStatement</TITLE>
+GdaRepetitiveStatement
+gda_repetitive_statement_new
+gda_repetitive_statement_get_template_set
+gda_repetitive_statement_get_all_sets
+gda_repetitive_statement_append_set
+<SUBSECTION Standard>
+GDA_REPETITIVE_STATEMENT
+GDA_REPETITIVE_STATEMENT_GET_CLASS
+GDA_IS_REPETITIVE_STATEMENT
+GDA_TYPE_REPETITIVE_STATEMENT
+gda_repetitive_statement_get_type
+</SECTION>
diff --git a/doc/C/tmpl/gda-connection.sgml b/doc/C/tmpl/gda-connection.sgml
index afef969..5b4b33d 100644
--- a/doc/C/tmpl/gda-connection.sgml
+++ b/doc/C/tmpl/gda-connection.sgml
@@ -165,6 +165,7 @@ A connection to a database
@GDA_CONNECTION_STATEMENT_TYPE_ERROR:
@GDA_CONNECTION_CANT_LOCK_ERROR:
@GDA_CONNECTION_TASK_NOT_FOUND_ERROR:
+ GDA_CONNECTION_UNSUPPORTED_THREADS_ERROR:
<!-- ##### MACRO GDA_CONNECTION_ERROR ##### -->
<para>
@@ -344,6 +345,20 @@ A connection to a database
@Returns:
+<!-- ##### FUNCTION gda_connection_repetitive_statement_execute ##### -->
+<para>
+
+</para>
+
+ cnc:
+ rstmt:
+ model_usage:
+ col_types:
+ stop_on_error:
+ error:
+ Returns:
+
+
<!-- ##### FUNCTION gda_connection_batch_execute ##### -->
<para>
diff --git a/doc/C/tmpl/gda-repetitive-statement.sgml b/doc/C/tmpl/gda-repetitive-statement.sgml
new file mode 100644
index 0000000..f3f75a7
--- /dev/null
+++ b/doc/C/tmpl/gda-repetitive-statement.sgml
@@ -0,0 +1,71 @@
+<!-- ##### SECTION Title ##### -->
+GdaRepetitiveStatement
+
+<!-- ##### SECTION Short_Description ##### -->
+Execute the same statement several times with different values
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+ The #GdaRepetitiveStatement object allows one to specify a statement to be executed
+ several times using different variables' values sets for each execution. Using the object
+ has almost no interrest at all if the statement to be executed several times has no parameter.
+</para>
+<para>
+ Use the gda_connection_repetitive_statement_execute() method to execute the repetitive statement.
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+ #GdaStatement, #GdaBatch, #GdaConnection
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### STRUCT GdaRepetitiveStatement ##### -->
+<para>
+
+</para>
+
+ parent_instance:
+
+<!-- ##### FUNCTION gda_repetitive_statement_new ##### -->
+<para>
+
+</para>
+
+ stmt:
+ Returns:
+
+
+<!-- ##### FUNCTION gda_repetitive_statement_get_template_set ##### -->
+<para>
+
+</para>
+
+ rstmt:
+ set:
+ error:
+ Returns:
+
+
+<!-- ##### FUNCTION gda_repetitive_statement_get_all_sets ##### -->
+<para>
+
+</para>
+
+ rstmt:
+ Returns:
+
+
+<!-- ##### FUNCTION gda_repetitive_statement_append_set ##### -->
+<para>
+
+</para>
+
+ rstmt:
+ values:
+ make_copy:
+ Returns:
+
+
diff --git a/doc/C/tmpl/gda-sql-statement.sgml b/doc/C/tmpl/gda-sql-statement.sgml
index 3964032..87c7460 100644
--- a/doc/C/tmpl/gda-sql-statement.sgml
+++ b/doc/C/tmpl/gda-sql-statement.sgml
@@ -1271,8 +1271,8 @@ Specifies the type of functions passed to gda_sql_any_part_foreach().
@any: inheritance structure
@type: type of join
@position: represents a join between a target at (pos < @position) and the one at @position
- expr: joining expression
- use:
+ expr: joining expression, or %NULL
+ use: list of #GdaSqlField pointers to use when joining, or %NULL
@_gda_reserved1:
@_gda_reserved2:
diff --git a/libgda.doap b/libgda.doap
new file mode 100644
index 0000000..116daa5
--- /dev/null
+++ b/libgda.doap
@@ -0,0 +1,26 @@
+<Project xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
+ xmlns:foaf="http://xmlns.com/foaf/0.1/"
+ xmlns:gnome="http://api.gnome.org/doap-extensions#"
+ xmlns="http://usefulinc.com/ns/doap#">
+
+ <!--
+ This is a DOAP template file. It contains Pulse's best guesses at
+ some basic content. You should verify the information in this file
+ and modify anything that isn't right. Add the corrected file to your
+ source code repository to help tools better understand your project.
+ -->
+
+ <name xml:lang="en">libgda</name>
+ <shortdesc xml:lang="en">Database access library</shortdesc>
+ <homepage rdf:resource="http://www.gnome-db.org/" />
+ <mailing-list rdf:resource="http://mail.gnome.org/mailman/listinfo/gnome-db-list" />
+
+ <maintainer>
+ <foaf:Person>
+ <foaf:name>Vivien Malerba</foaf:name>
+ <foaf:mbox rdf:resource="malerba gnome-db org" />
+ <gnome:userid>vivien</gnome:userid>
+ </foaf:Person>
+ </maintainer>
+</Project>
diff --git a/libgda/Makefile.am b/libgda/Makefile.am
index 6ab15df..563c45d 100644
--- a/libgda/Makefile.am
+++ b/libgda/Makefile.am
@@ -62,6 +62,7 @@ gda_headers = \
gda-meta-struct.h \
gda-mutex.h \
gda-quark-list.h \
+ gda-repetitive-statement.h \
gda-row.h \
gda-set.h \
gda-server-operation.h \
@@ -131,6 +132,7 @@ libgda_sources = \
gda-meta-struct-io.c \
gda-mutex.c \
gda-quark-list.c \
+ gda-repetitive-statement.c \
gda-row.c \
gda-set.c \
gda-server-operation.c \
diff --git a/libgda/gda-connection-internal.h b/libgda/gda-connection-internal.h
index 61d51cc..39a61bf 100644
--- a/libgda/gda-connection-internal.h
+++ b/libgda/gda-connection-internal.h
@@ -29,6 +29,19 @@
G_BEGIN_DECLS
+/*
+ * Warnings
+ */
+#ifdef GDA_DEBUG
+#define ASSERT_TABLE_NAME(x,y) g_assert (!strcmp ((x), (y)))
+#define WARN_METHOD_NOT_IMPLEMENTED(prov,method) g_warning ("Provider '%s' does not implement the META method '%s()', please report the error to bugzilla.gnome.org", gda_server_provider_get_name (prov), (method))
+#define WARN_META_UPDATE_FAILURE(x,method) if (!(x)) g_print ("%s (meta method => %s) ERROR: %s\n", __FUNCTION__, (method), error && *error && (*error)->message ? (*error)->message : "???")
+#else
+#define ASSERT_TABLE_NAME(x,y)
+#define WARN_METHOD_NOT_IMPLEMENTED(prov,method)
+#define WARN_META_UPDATE_FAILURE(x,method)
+#endif
+
/*
* Opens a connection to an SQLite database. This function is intended to be used
* internally when objects require an SQLite connection, for example for the GdaMetaStore
diff --git a/libgda/gda-connection.c b/libgda/gda-connection.c
index fad1f8e..52aac06 100644
--- a/libgda/gda-connection.c
+++ b/libgda/gda-connection.c
@@ -46,6 +46,7 @@
#include <libgda/gda-mutex.h>
#include <libgda/gda-lockable.h>
#include <libgda/thread-wrapper/gda-thread-provider.h>
+#include <libgda/gda-repetitive-statement.h>
#define PROV_CLASS(provider) (GDA_SERVER_PROVIDER_CLASS (G_OBJECT_GET_CLASS (provider)))
@@ -746,6 +747,13 @@ gda_connection_open_from_dsn (const gchar *dsn, const gchar *auth_string,
gchar *real_auth_string = NULL;
g_return_val_if_fail (dsn && *dsn, NULL);
+
+ if ((options & GDA_CONNECTION_OPTIONS_THREAD_SAFE) && !g_thread_supported ()) {
+ g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_UNSUPPORTED_THREADS_ERROR,
+ "%s", _("Multi threading is not supported or enabled"));
+ return NULL;
+ }
+
gda_dsn_split (dsn, &real_dsn, &user, &pass);
if (!real_dsn) {
g_free (user);
@@ -889,6 +897,13 @@ gda_connection_open_from_string (const gchar *provider_name, const gchar *cnc_st
gchar *real_auth_string = NULL;
g_return_val_if_fail (cnc_string && *cnc_string, NULL);
+
+ if ((options & GDA_CONNECTION_OPTIONS_THREAD_SAFE) && !g_thread_supported ()) {
+ g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_UNSUPPORTED_THREADS_ERROR,
+ "%s", _("Multi threading is not supported or enabled"));
+ return NULL;
+ }
+
gda_connection_string_split (cnc_string, &real_cnc, &real_provider, &user, &pass);
if (!real_cnc) {
g_free (user);
@@ -2433,6 +2448,81 @@ gda_connection_statement_execute_select_full (GdaConnection *cnc, GdaStatement *
return model;
}
+/**
+ * gda_connection_repetitive_statement_execute
+ * @cnc: a #GdaConnection
+ * @rstmt: a #GdaRepetitiveStatement object
+ * @model_usage: specifies how the returned data model will be used as a #GdaStatementModelUsage enum
+ * @col_types: an array of GType to request each returned GdaDataModel's column's GType, see gda_connection_statement_execute_select_full() for more information
+ * @stop_on_error: set to TRUE if the method has to stop on the first error.
+ * @error: a place to store errors, or %NULL
+ *
+ * Executes the statement upon which @rstmt is built. Note that as several statements can actually be executed by this
+ * method, it is recommended to be within a transaction.
+ *
+ * If @error is not %NULL and @stop_on_error is %FALSE, then it may contain the last error which occurred.
+ *
+ * Returns: a new list of #GObject pointers (see gda_connection_statement_execute() for more information about what they
+ * represent), one for each actual execution of the statement upon which @rstmt is built. If @stop_on_error is %FALSE, then
+ * the list may contain some %NULL pointers which refer to statements which failed to execute.
+ *
+ * Since: 4.2
+ */
+GSList *
+gda_connection_repetitive_statement_execute (GdaConnection *cnc, GdaRepetitiveStatement *rstmt,
+ GdaStatementModelUsage model_usage, GType *col_types,
+ gboolean stop_on_error, GError **error)
+{
+ GSList *sets_list, *list;
+ GSList *retlist = NULL;
+ GdaStatement *stmt;
+
+ g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+ g_return_val_if_fail (cnc->priv, NULL);
+ g_return_val_if_fail (cnc->priv->provider_obj, NULL);
+ g_return_val_if_fail (GDA_IS_REPETITIVE_STATEMENT (rstmt), NULL);
+ g_return_val_if_fail (PROV_CLASS (cnc->priv->provider_obj)->statement_execute, NULL);
+
+ g_object_get (rstmt, "statement", &stmt, NULL);
+ g_return_val_if_fail (stmt, NULL);
+
+ gda_connection_lock ((GdaLockable*) cnc);
+
+ if (! (model_usage & GDA_STATEMENT_MODEL_RANDOM_ACCESS) &&
+ ! (model_usage & GDA_STATEMENT_MODEL_CURSOR_FORWARD))
+ model_usage |= GDA_STATEMENT_MODEL_RANDOM_ACCESS;
+
+ sets_list = gda_repetitive_statement_get_all_sets (rstmt);
+ for (list = sets_list; list; list = list->next) {
+ GObject *obj;
+ GError *lerror = NULL;
+ obj = PROV_CLASS (cnc->priv->provider_obj)->statement_execute (cnc->priv->provider_obj, cnc, stmt,
+ GDA_SET (list->data),
+ model_usage, col_types, NULL,
+ NULL, NULL, NULL, &lerror);
+ if (!obj) {
+ if (stop_on_error)
+ break;
+ else {
+ if (error && *error) {
+ g_error_free (*error);
+ *error = NULL;
+ }
+ g_propagate_error (error, lerror);
+ }
+ }
+ else
+ retlist = g_slist_prepend (retlist, obj);
+ }
+ g_slist_free (sets_list);
+
+ gda_connection_unlock ((GdaLockable*) cnc);
+
+ g_object_unref (stmt);
+
+ return g_slist_reverse (retlist);
+}
+
/*
* Forces the GdaTransactionStatus. This is reserved to connections which are thread wrappers
*
@@ -2824,15 +2914,6 @@ check_parameters (GdaMetaContext *context, GError **error, gint nb, ...)
static gboolean
local_meta_update (GdaServerProvider *provider, GdaConnection *cnc, GdaMetaContext *context, GError **error)
{
-#ifdef GDA_DEBUG
-#define ASSERT_TABLE_NAME(x,y) g_assert (!strcmp ((x), (y)))
-#define WARN_METHOD_NOT_IMPLEMENTED(prov,method) g_warning ("Provider '%s' does not implement the META method '%s()', please report the error to bugzilla.gnome.org", gda_server_provider_get_name (prov), (method))
-#define WARN_META_UPDATE_FAILURE(x,method) if (!(x)) g_print ("%s (meta method => %s) ERROR: %s\n", __FUNCTION__, (method), error && *error && (*error)->message ? (*error)->message : "???")
-#else
-#define ASSERT_TABLE_NAME(x,y)
-#define WARN_METHOD_NOT_IMPLEMENTED(prov,method)
-#define WARN_META_UPDATE_FAILURE(x,method)
-#endif
const gchar *tname = context->table_name;
GdaMetaStore *store;
gboolean retval;
@@ -3531,21 +3612,6 @@ suggest_update_cb_downstream (GdaMetaStore *store, GdaMetaContext *suggest, Down
return NULL;
}
-typedef struct {
- GdaConnection *cnc;
- GdaMetaContext *context;
-} UpdateMetaStoreData;
-
-static gpointer
-sub_thread_update_meta_store (UpdateMetaStoreData *data, GError **error)
-{
- /* WARNING: function executed in sub thread! */
- gboolean retval;
- retval = gda_connection_update_meta_store (data->cnc, data->context, error);
- g_print ("/%s() => %s\n", __FUNCTION__, retval ? "TRUE" : "FALSE");
- return GINT_TO_POINTER (retval ? 1 : 0);
-}
-
/**
* gda_connection_update_meta_store
* @cnc: a #GdaConnection object.
@@ -3596,29 +3662,13 @@ gda_connection_update_meta_store (GdaConnection *cnc, GdaMetaContext *context, G
gda_connection_lock ((GdaLockable*) cnc);
- if (cnc->priv->is_thread_wrapper) {
- ThreadConnectionData *cdata;
- UpdateMetaStoreData data;
- gpointer res;
- guint jid;
-
- cdata = (ThreadConnectionData*) gda_connection_internal_get_provider_data (cnc);
- if (!cdata)
- return FALSE;
-
- data.cnc = cdata->sub_connection;
- data.context = context;
-
- jid = gda_thread_wrapper_execute (cdata->wrapper,
- (GdaThreadWrapperFunc) sub_thread_update_meta_store, &data, NULL, error);
- res = gda_thread_wrapper_fetch_result (cdata->wrapper, TRUE, jid, error);
- return GPOINTER_TO_INT (res) ? TRUE : FALSE;
- }
-
/* Get or create the GdaMetaStore object */
store = gda_connection_get_meta_store (cnc);
g_assert (store);
+ /* unlock connection */
+ gda_connection_unlock ((GdaLockable*) cnc);
+
/* prepare local context */
GdaMetaContext lcontext;
@@ -3638,7 +3688,6 @@ gda_connection_update_meta_store (GdaConnection *cnc, GdaMetaContext *context, G
if (!up_templates) {
if (lerror) {
g_propagate_error (error, lerror);
- gda_connection_unlock ((GdaLockable*) cnc);
return FALSE;
}
}
@@ -3646,7 +3695,6 @@ gda_connection_update_meta_store (GdaConnection *cnc, GdaMetaContext *context, G
if (!dn_templates) {
if (lerror) {
g_propagate_error (error, lerror);
- gda_connection_unlock ((GdaLockable*) cnc);
return FALSE;
}
}
@@ -3700,7 +3748,6 @@ gda_connection_update_meta_store (GdaConnection *cnc, GdaMetaContext *context, G
g_slist_free (cbd.context_templates);
g_hash_table_destroy (cbd.context_templates_hash);
- gda_connection_unlock ((GdaLockable*) cnc);
return retval;
}
else {
@@ -3764,7 +3811,6 @@ gda_connection_update_meta_store (GdaConnection *cnc, GdaMetaContext *context, G
g_assert (nb == sizeof (rmeta) / sizeof (RMeta));
if (! _gda_meta_store_begin_data_reset (store, error)) {
- gda_connection_unlock ((GdaLockable*) cnc);
return FALSE;
}
@@ -3791,12 +3837,10 @@ gda_connection_update_meta_store (GdaConnection *cnc, GdaMetaContext *context, G
}
}
retval = _gda_meta_store_finish_data_reset (store, error);
- gda_connection_unlock ((GdaLockable*) cnc);
return retval;
onerror:
_gda_meta_store_cancel_data_reset (store, NULL);
- gda_connection_unlock ((GdaLockable*) cnc);
return FALSE;
}
}
diff --git a/libgda/gda-connection.h b/libgda/gda-connection.h
index ae1604d..5e636a9 100644
--- a/libgda/gda-connection.h
+++ b/libgda/gda-connection.h
@@ -55,7 +55,8 @@ typedef enum {
GDA_CONNECTION_OPEN_ERROR,
GDA_CONNECTION_STATEMENT_TYPE_ERROR,
GDA_CONNECTION_CANT_LOCK_ERROR,
- GDA_CONNECTION_TASK_NOT_FOUND_ERROR
+ GDA_CONNECTION_TASK_NOT_FOUND_ERROR,
+ GDA_CONNECTION_UNSUPPORTED_THREADS_ERROR
} GdaConnectionError;
#define GDA_CONNECTION_NONEXIST_DSN_ERROR GDA_CONNECTION_DSN_NOT_FOUND_ERROR
@@ -197,6 +198,12 @@ GObject *gda_connection_async_fetch_result (GdaConnection *cnc,
gboolean gda_connection_async_cancel (GdaConnection *cnc, guint task_id, GError **error);
+/* repetitive statement */
+GSList *gda_connection_repetitive_statement_execute (GdaConnection *cnc, GdaRepetitiveStatement *rstmt,
+ GdaStatementModelUsage model_usage, GType *col_types,
+ gboolean stop_on_error, GError **error);
+
+/* transactions */
gboolean gda_connection_begin_transaction (GdaConnection *cnc, const gchar *name,
GdaTransactionIsolation level, GError **error);
gboolean gda_connection_commit_transaction (GdaConnection *cnc, const gchar *name, GError **error);
diff --git a/libgda/gda-decl.h b/libgda/gda-decl.h
index 646e9ec..0db3879 100644
--- a/libgda/gda-decl.h
+++ b/libgda/gda-decl.h
@@ -89,6 +89,9 @@ typedef struct _GdaStatement GdaStatement;
typedef struct _GdaStatementClass GdaStatementClass;
typedef struct _GdaStatementPrivate GdaStatementPrivate;
+typedef struct _GdaRepetitiveStatement GdaRepetitiveStatement;
+typedef struct _GdaRepetitiveStatementClass GdaRepetitiveStatementClass;
+
typedef struct _GdaSqlParser GdaSqlParser;
typedef struct _GdaSqlParserClass GdaSqlParserClass;
typedef struct _GdaSqlParserPrivate GdaSqlParserPrivate;
diff --git a/libgda/gda-repetitive-statement.c b/libgda/gda-repetitive-statement.c
new file mode 100644
index 0000000..3f0008c
--- /dev/null
+++ b/libgda/gda-repetitive-statement.c
@@ -0,0 +1,224 @@
+/* GDA library
+ *
+ * Copyright (C) Daniel Espinosa Ortiz 2008 <esodan gmail com>
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <gda-repetitive-statement.h>
+#include <libgda/gda-set.h>
+#include <libgda/gda-holder.h>
+#include <libgda/gda-connection.h>
+
+typedef struct _GdaRepetitiveStatementPrivate GdaRepetitiveStatementPrivate;
+struct _GdaRepetitiveStatementPrivate
+{
+ GdaStatement* statement;
+ GSList* values_sets; /* list of GdaSet pointers, objects referenced here */
+};
+
+#define GDA_REPETITIVE_STATEMENT_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDA_TYPE_REPETITIVE_STATEMENT, GdaRepetitiveStatementPrivate))
+
+enum {
+ PROP_0,
+ PROP_STATEMENT
+};
+
+G_DEFINE_TYPE (GdaRepetitiveStatement, gda_repetitive_statement, G_TYPE_OBJECT);
+
+static void
+gda_repetitive_statement_init (GdaRepetitiveStatement *object)
+{
+ GdaRepetitiveStatementPrivate *priv;
+
+ priv = GDA_REPETITIVE_STATEMENT_PRIVATE (object);
+
+ priv->statement = NULL;
+ priv->values_sets = NULL;
+}
+
+static void
+gda_repetitive_statement_finalize (GObject *object)
+{
+ GdaRepetitiveStatementPrivate *priv;
+
+ priv = GDA_REPETITIVE_STATEMENT_PRIVATE (object);
+
+ g_object_unref (priv->statement);
+ g_slist_foreach (priv->values_sets, (GFunc) g_object_unref, NULL);
+ g_slist_free (priv->values_sets);
+
+ G_OBJECT_CLASS (gda_repetitive_statement_parent_class)->finalize (object);
+}
+
+static void
+gda_repetitive_statement_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+ GdaRepetitiveStatementPrivate *priv;
+
+ g_return_if_fail (GDA_IS_REPETITIVE_STATEMENT (object));
+
+ priv = GDA_REPETITIVE_STATEMENT_PRIVATE (object);
+ switch (prop_id) {
+ case PROP_STATEMENT:
+ priv->statement = g_value_dup_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gda_repetitive_statement_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ GdaRepetitiveStatementPrivate *priv;
+
+ g_return_if_fail (GDA_IS_REPETITIVE_STATEMENT (object));
+
+ priv = GDA_REPETITIVE_STATEMENT_PRIVATE (object);
+ switch (prop_id) {
+ case PROP_STATEMENT:
+ g_value_set_object (value, priv->statement);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gda_repetitive_statement_class_init (GdaRepetitiveStatementClass *klass)
+{
+ GObjectClass* object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (GdaRepetitiveStatementPrivate));
+
+ object_class->finalize = gda_repetitive_statement_finalize;
+ object_class->set_property = gda_repetitive_statement_set_property;
+ object_class->get_property = gda_repetitive_statement_get_property;
+
+ g_object_class_install_property (object_class,
+ PROP_STATEMENT,
+ g_param_spec_object ("statement",
+ "stmt",
+ "Statement to Execute",
+ GDA_TYPE_STATEMENT,
+ G_PARAM_WRITABLE | G_PARAM_READABLE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+/**
+ * gda_repetitive_statement_new
+ * @stmt: a #GdaStatement object
+ *
+ * Creates a new #GdaRepetitiveStatement object which, when executed, will execute @stmt once for all
+ * the values set which will have been defined using gda_repetitive_statement_append_set().
+ * Use gda_connection_repetitive_statement_execute() to actually execute it.
+ *
+ * Returns: a new #GdaRepetitiveStatement object
+ *
+ * Since: 4.2
+ */
+GdaRepetitiveStatement*
+gda_repetitive_statement_new (GdaStatement *stmt)
+{
+ GdaRepetitiveStatement *rstmt;
+
+ rstmt = GDA_REPETITIVE_STATEMENT (g_object_new (GDA_TYPE_REPETITIVE_STATEMENT,
+ "statement", stmt, NULL));
+
+ return rstmt;
+}
+
+/**
+ * gda_repetitive_statement_get_template_set
+ * @rstmt: a #GdaRepetitiveStatement object
+ * @set: a place to store the returned template set
+ * @error: a place to store error, or %NULL
+ *
+ * Gets a new #GdaSet object with the parameters used by the template statement in the
+ * @rstmt object.
+ *
+ * Use this object with gda_repetitive_statement_append_set().
+ *
+ * Returns: TRUE on success, FALSE on error
+ *
+ * Since: 4.2
+ */
+gboolean
+gda_repetitive_statement_get_template_set (GdaRepetitiveStatement *rstmt, GdaSet **set, GError **error)
+{
+ GdaRepetitiveStatementPrivate *priv;
+
+ priv = GDA_REPETITIVE_STATEMENT_PRIVATE (rstmt);
+
+ return gda_statement_get_parameters (priv->statement, set, error);
+}
+
+/**
+ * gda_repetitive_statement_append_set
+ * @rstmt: a #GdaRepetitiveStatement object
+ * @values: a #GdaSet object with the values to be used
+ * @make_copy: %TRUE if @values is copied, and %FALSE if @values is only ref'ed
+ *
+ * Specifies that @rstmt be executed one time with the values contained in @values.
+ *
+ * A new #GdaSet to be used as the @values argument can be obtained using
+ * gda_repetitive_statement_get_template_set().
+ *
+ * Returns: a new #GdaRepetitiveStatement object
+ *
+ * Since: 4.2
+ */
+gboolean
+gda_repetitive_statement_append_set (GdaRepetitiveStatement *rstmt, GdaSet *values, gboolean make_copy)
+{
+ GdaRepetitiveStatementPrivate *priv;
+ GdaSet *set;
+
+ g_return_val_if_fail (GDA_IS_REPETITIVE_STATEMENT(rstmt), FALSE);
+ g_return_val_if_fail (GDA_IS_SET (values), FALSE);
+
+ priv = GDA_REPETITIVE_STATEMENT_PRIVATE (rstmt);
+
+ if (make_copy)
+ set = gda_set_copy (values);
+ else
+ set = g_object_ref (values);
+ priv->values_sets = g_slist_prepend (priv->values_sets, set);
+
+ return TRUE;
+}
+
+/**
+ * gda_repetitive_statement_get_all_sets
+ * @rstmt: a #GdaRepetitiveStatement object
+ *
+ * Get all the values sets which will have been added using gda_repetitive_statement_append_set().
+ *
+ * Returns: a new #GSList of #GdaSet objects (free with g_slist_free()).
+ *
+ * Since: 4.2
+ */
+GSList*
+gda_repetitive_statement_get_all_sets (GdaRepetitiveStatement *rstmt)
+{
+ GdaRepetitiveStatementPrivate *priv;
+
+ priv = GDA_REPETITIVE_STATEMENT_PRIVATE (rstmt);
+
+ return g_slist_reverse (priv->values_sets);
+}
diff --git a/libgda/gda-repetitive-statement.h b/libgda/gda-repetitive-statement.h
new file mode 100644
index 0000000..355362f
--- /dev/null
+++ b/libgda/gda-repetitive-statement.h
@@ -0,0 +1,55 @@
+/* GDA library
+ *
+ * Copyright (C) Daniel Espinosa Ortiz 2008 <esodan gmail com>
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _GDA_REPETITIVE_STATEMENT_H_
+#define _GDA_REPETITIVE_STATEMENT_H_
+
+#include <glib-object.h>
+#include <libgda/gda-decl.h>
+
+G_BEGIN_DECLS
+
+#define GDA_TYPE_REPETITIVE_STATEMENT (gda_repetitive_statement_get_type ())
+#define GDA_REPETITIVE_STATEMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDA_TYPE_REPETITIVE_STATEMENT, GdaRepetitiveStatement))
+#define GDA_REPETITIVE_STATEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDA_TYPE_REPETITIVE_STATEMENT, GdaRepetitiveStatementClass))
+#define GDA_IS_REPETITIVE_STATEMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDA_TYPE_REPETITIVE_STATEMENT))
+#define GDA_IS_REPETITIVE_STATEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDA_TYPE_REPETITIVE_STATEMENT))
+#define GDA_REPETITIVE_STATEMENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDA_TYPE_REPETITIVE_STATEMENT, GdaRepetitiveStatementClass))
+
+struct _GdaRepetitiveStatementClass
+{
+ GObjectClass parent_class;
+};
+
+struct _GdaRepetitiveStatement
+{
+ GObject parent_instance;
+};
+
+GType gda_repetitive_statement_get_type (void) G_GNUC_CONST;
+
+GdaRepetitiveStatement* gda_repetitive_statement_new (GdaStatement *stmt);
+gboolean gda_repetitive_statement_get_template_set (GdaRepetitiveStatement *rstmt, GdaSet **set, GError **error);
+GSList *gda_repetitive_statement_get_all_sets (GdaRepetitiveStatement *rstmt);
+gboolean gda_repetitive_statement_append_set (GdaRepetitiveStatement *rstmt, GdaSet *values, gboolean make_copy);
+
+G_END_DECLS
+
+#endif /* _GDA_REPETITIVE_STATEMENT_H_ */
diff --git a/libgda/gda-server-provider.c b/libgda/gda-server-provider.c
index aa0cb17..424ab4b 100644
--- a/libgda/gda-server-provider.c
+++ b/libgda/gda-server-provider.c
@@ -267,7 +267,7 @@ gda_server_provider_get_version (GdaServerProvider *provider)
}
/**
- * gda_server_provider_get_info
+ * gda_server_provider_get_name
* @provider: a #GdaServerProvider object.
*
* Get the name (identifier) of the provider
diff --git a/libgda/gda-sql-builder.c b/libgda/gda-sql-builder.c
index 21eebc1..8f4a278 100644
--- a/libgda/gda-sql-builder.c
+++ b/libgda/gda-sql-builder.c
@@ -48,7 +48,6 @@ static GStaticRecMutex init_mutex = G_STATIC_REC_MUTEX_INIT;
typedef struct {
GdaSqlAnyPart *part;
- gboolean to_free; /* TRUE if @part is not included in a GdaSqlStatement, and needs to be freed */
} SqlPart;
struct _GdaSqlBuilderPrivate {
@@ -124,9 +123,14 @@ gda_sql_builder_class_init (GdaSqlBuilderClass *klass)
static void
any_part_free (SqlPart *part)
{
- if (part->to_free) {
+ switch (part->part->type) {
+ case GDA_SQL_ANY_EXPR:
+ gda_sql_expr_free ((GdaSqlExpr*) part->part);
+ break;
+ default:
TO_IMPLEMENT;
}
+
g_free (part);
}
@@ -250,7 +254,6 @@ add_part (GdaSqlBuilder *builder, guint id, GdaSqlAnyPart *part)
*realid = id;
p = g_new0 (SqlPart, 1);
p->part = part;
- p->to_free = TRUE; /* p->part not used yet in GdaSqlStatement */
g_hash_table_insert (builder->priv->parts_hash, realid, p);
return id;
}
@@ -280,27 +283,19 @@ use_part (SqlPart *p, GdaSqlAnyPart *parent)
if (!p)
return NULL;
- if (p->to_free) {
- /* take ownership */
- p->to_free = FALSE;
- p->part->parent = parent;
- return p->part;
- }
- else {
- /* copy */
- GdaSqlAnyPart *anyp = NULL;
- switch (p->part->type) {
- case GDA_SQL_ANY_EXPR:
- anyp = (GdaSqlAnyPart*) gda_sql_expr_copy ((GdaSqlExpr*) p->part);
- break;
- default:
- TO_IMPLEMENT;
- return NULL;
- }
- if (anyp)
- anyp->parent = parent;
- return anyp;
+ /* copy */
+ GdaSqlAnyPart *anyp = NULL;
+ switch (p->part->type) {
+ case GDA_SQL_ANY_EXPR:
+ anyp = (GdaSqlAnyPart*) gda_sql_expr_copy ((GdaSqlExpr*) p->part);
+ break;
+ default:
+ TO_IMPLEMENT;
+ return NULL;
}
+ if (anyp)
+ anyp->parent = parent;
+ return anyp;
}
/**
@@ -469,52 +464,88 @@ gda_sql_builder_set_where (GdaSqlBuilder *builder, guint cond_id)
/**
- * gda_sql_builder_add_field_value
+ * gda_sql_builder_add_field
* @builder: a #GdaSqlBuilder object
- * @field_name: a field name
+ * @field_id: the ID of the field's name or definition
* @value_id: the ID of the value to set the field to
*
- * Valid only for: INSERT, UPDATE statements
+ * Valid only for: INSERT, UPDATE, SELECT statements
*
- * Specifies that the field named @field_name will be set to the value identified by @value_id.
+ * For INSERT and UPDATE: specifies that the field named @field_name will be set to the value identified by @value_id.
+ * For SELECT: add a selected item to the statement, and if @value_id is not %0, then use it as an alias
*
* Since: 4.2
*/
void
-gda_sql_builder_add_field_value (GdaSqlBuilder *builder, const gchar *field_name, guint value_id)
+gda_sql_builder_add_field (GdaSqlBuilder *builder, guint field_id, guint value_id)
{
g_return_if_fail (GDA_IS_SQL_BUILDER (builder));
g_return_if_fail (builder->priv->main_stmt);
- g_return_if_fail (field_name && *field_name);
- g_return_if_fail (value_id > 0);
- SqlPart *p;
- p = get_part (builder, value_id, GDA_SQL_ANY_EXPR);
- if (!p)
+ SqlPart *value_part, *field_part;
+ GdaSqlExpr *field_expr;
+ value_part = get_part (builder, value_id, GDA_SQL_ANY_EXPR);
+ field_part = get_part (builder, field_id, GDA_SQL_ANY_EXPR);
+ if (!field_part)
return;
+ field_expr = (GdaSqlExpr*) (field_part->part);
- GdaSqlField *field = gda_sql_field_new (GDA_SQL_ANY_PART (builder->priv->main_stmt->contents));
- field->field_name = g_strdup (field_name);
+ /* checks */
+ switch (builder->priv->main_stmt->stmt_type) {
+ case GDA_SQL_STATEMENT_UPDATE:
+ case GDA_SQL_STATEMENT_INSERT:
+ if (!value_part)
+ return;
+ if (!field_expr->value || (G_VALUE_TYPE (field_expr->value) != G_TYPE_STRING)) {
+ g_warning (_("Wrong field format"));
+ return;
+ }
+ break;
+ case GDA_SQL_STATEMENT_SELECT:
+ /* no specific check */
+ break;
+ default:
+ g_warning (_("Wrong statement type"));
+ return;
+ }
+ /* work */
switch (builder->priv->main_stmt->stmt_type) {
case GDA_SQL_STATEMENT_UPDATE: {
GdaSqlStatementUpdate *upd = (GdaSqlStatementUpdate*) builder->priv->main_stmt->contents;
+ GdaSqlField *field = gda_sql_field_new (GDA_SQL_ANY_PART (upd));
+ field->field_name = g_value_dup_string (field_expr->value);
upd->fields_list = g_slist_append (upd->fields_list, field);
- upd->expr_list = g_slist_append (upd->expr_list, use_part (p, GDA_SQL_ANY_PART (upd)));
-
+ upd->expr_list = g_slist_append (upd->expr_list, use_part (value_part, GDA_SQL_ANY_PART (upd)));
break;
}
case GDA_SQL_STATEMENT_INSERT:{
GdaSqlStatementInsert *ins = (GdaSqlStatementInsert*) builder->priv->main_stmt->contents;
- ins->fields_list = g_slist_append (ins->fields_list, field);
+ GdaSqlField *field = gda_sql_field_new (GDA_SQL_ANY_PART (ins));
+ field->field_name = g_value_dup_string (field_expr->value);
+ ins->fields_list = g_slist_append (ins->fields_list, field);
if (! ins->values_list)
ins->values_list = g_slist_append (NULL,
- g_slist_append (NULL, use_part (p, GDA_SQL_ANY_PART (ins))));
+ g_slist_append (NULL,
+ use_part (value_part, GDA_SQL_ANY_PART (ins))));
else
ins->values_list->data = g_slist_append ((GSList*) ins->values_list->data,
- use_part (p, GDA_SQL_ANY_PART (ins)));
+ use_part (value_part, GDA_SQL_ANY_PART (ins)));
+ break;
+ }
+ case GDA_SQL_STATEMENT_SELECT: {
+ GdaSqlStatementSelect *sel = (GdaSqlStatementSelect*) builder->priv->main_stmt->contents;
+ GdaSqlSelectField *field;
+ field = gda_sql_select_field_new (GDA_SQL_ANY_PART (sel));
+ field->expr = (GdaSqlExpr*) use_part (field_part, GDA_SQL_ANY_PART (field));
+ if (value_part) {
+ GdaSqlExpr *value_expr = (GdaSqlExpr*) (value_part->part);
+ if (G_VALUE_TYPE (value_expr->value) == G_TYPE_STRING)
+ field->as = g_value_dup_string (value_expr->value);
+ }
+ sel->expr_list = g_slist_append (sel->expr_list, field);
break;
}
default:
@@ -685,30 +716,23 @@ gda_sql_builder_param (GdaSqlBuilder *builder, guint id, const gchar *param_name
return add_part (builder, id, (GdaSqlAnyPart *) expr);
}
-guint
-gda_sql_builder_cond1 (GdaSqlBuilder *builder, guint id, GdaSqlOperatorType op, guint op1)
-{
- TO_IMPLEMENT;
- return 0;
-}
-
-
/**
- * gda_sql_builder_cond2
+ * gda_sql_builder_cond
* @builder: a #GdaSqlBuilder object
* @id: the requested ID, or 0 if to be determined by @builder
* @op: type of condition
* @op1: the ID of the 1st argument (not 0)
- * @op2: the ID of the 2nd argument (not 0)
+ * @op2: the ID of the 2nd argument (may be %0 if @op needs only one operand)
+ * @op3: the ID of the 3rd argument (may be %0 if @op needs only one or two operand)
*
- * Builds a new expression which reprenents a condition (or operation) with two operands.
+ * Builds a new expression which reprenents a condition (or operation).
*
* Returns: the ID of the new expression, or 0 if there was an error
*
* Since: 4.2
*/
guint
-gda_sql_builder_cond2 (GdaSqlBuilder *builder, guint id, GdaSqlOperatorType op, guint op1, guint op2)
+gda_sql_builder_cond (GdaSqlBuilder *builder, guint id, GdaSqlOperatorType op, guint op1, guint op2, guint op3)
{
g_return_val_if_fail (GDA_IS_SQL_BUILDER (builder), 0);
g_return_val_if_fail (builder->priv->main_stmt, 0);
@@ -718,23 +742,211 @@ gda_sql_builder_cond2 (GdaSqlBuilder *builder, guint id, GdaSqlOperatorType op,
if (!p1)
return 0;
p2 = get_part (builder, op2, GDA_SQL_ANY_EXPR);
- if (!p2)
- return 0;
GdaSqlExpr *expr;
expr = gda_sql_expr_new (NULL);
expr->cond = gda_sql_operation_new (GDA_SQL_ANY_PART (expr));
expr->cond->operator_type = op;
expr->cond->operands = g_slist_append (NULL, use_part (p1, GDA_SQL_ANY_PART (expr->cond)));
- expr->cond->operands = g_slist_append (expr->cond->operands, use_part (p2, GDA_SQL_ANY_PART (expr->cond)));
+ if (p2) {
+ SqlPart *p3;
+ expr->cond->operands = g_slist_append (expr->cond->operands,
+ use_part (p2, GDA_SQL_ANY_PART (expr->cond)));
+ p3 = get_part (builder, op3, GDA_SQL_ANY_EXPR);
+ if (p3)
+ expr->cond->operands = g_slist_append (expr->cond->operands,
+ use_part (p3, GDA_SQL_ANY_PART (expr->cond)));
+ }
return add_part (builder, id, (GdaSqlAnyPart *) expr);
}
+typedef struct {
+ GdaSqlSelectTarget target; /* inheritance! */
+ guint part_id; /* copied from this part ID */
+} BuildTarget;
+
+/**
+ * gda_sql_builder_select_add_target
+ * @builder: a #GdaSqlBuilder object
+ * @id: the requested ID, or 0 if to be determined by @builder
+ * @table_id: the ID of the expression holding a table reference (not %0)
+ * @alias: the alias to give to the target, or %NULL
+ *
+ * Adds a new target to a SELECT statement
+ *
+ * Returns: the ID of the new target, or 0 if there was an error
+ *
+ * Since: 4.2
+ */
+guint
+gda_sql_builder_select_add_target (GdaSqlBuilder *builder, guint id, guint table_id, const gchar *alias)
+{
+ g_return_val_if_fail (GDA_IS_SQL_BUILDER (builder), 0);
+ g_return_val_if_fail (builder->priv->main_stmt, 0);
+
+ if (builder->priv->main_stmt->stmt_type != GDA_SQL_STATEMENT_SELECT) {
+ g_warning (_("Wrong statement type"));
+ return 0;
+ }
+
+ SqlPart *p;
+ p = get_part (builder, table_id, GDA_SQL_ANY_EXPR);
+ if (!p)
+ return 0;
+
+ BuildTarget *btarget;
+ GdaSqlStatementSelect *sel = (GdaSqlStatementSelect*) builder->priv->main_stmt->contents;
+ btarget = g_new0 (BuildTarget, 1);
+ GDA_SQL_ANY_PART(btarget)->type = GDA_SQL_ANY_SQL_SELECT_TARGET;
+ GDA_SQL_ANY_PART(btarget)->parent = GDA_SQL_ANY_PART (sel->from);
+ if (id)
+ btarget->part_id = id;
+ else
+ btarget->part_id = builder->priv->next_assigned_id --;
+
+ ((GdaSqlSelectTarget*) btarget)->expr = (GdaSqlExpr*) use_part (p, GDA_SQL_ANY_PART (btarget));
+ if (alias)
+ ((GdaSqlSelectTarget*) btarget)->as = g_strdup (alias);
+
+ /* add target to sel->from. NOTE: @btarget is NOT added to the "repository" or GdaSqlAnyPart parts
+ * like others */
+ if (!sel->from)
+ sel->from = gda_sql_select_from_new (GDA_SQL_ANY_PART (sel));
+ sel->from->targets = g_slist_append (sel->from->targets, btarget);
+
+ return btarget->part_id;
+}
+
+typedef struct {
+ GdaSqlSelectJoin join; /* inheritance! */
+ guint part_id; /* copied from this part ID */
+} BuilderJoin;
+/**
+ * gda_sql_builder_select_join_targets
+ * @builder: a #GdaSqlBuilder object
+ * @id: the requested ID, or 0 if to be determined by @builder
+ * @left_target_id: the ID of the left target to use (not %0)
+ * @right_target_id: the ID of the right target to use (not %0)
+ * @join_type: the type of join
+ * @join_expr: joining expression's ID, or %0
+ *
+ * Joins two targets in a SELECT statement
+ *
+ * Returns: the ID of the new join, or 0 if there was an error
+ *
+ * Since: 4.2
+ */
guint
-gda_sql_builder_cond3 (GdaSqlBuilder *builder, guint id, GdaSqlOperatorType op, guint op1, guint op2, guint op3)
+gda_sql_builder_select_join_targets (GdaSqlBuilder *builder, guint id,
+ guint left_target_id, guint right_target_id,
+ GdaSqlSelectJoinType join_type,
+ guint join_expr)
{
- TO_IMPLEMENT;
- return 0;
+ g_return_val_if_fail (GDA_IS_SQL_BUILDER (builder), 0);
+ g_return_val_if_fail (builder->priv->main_stmt, 0);
+
+ if (builder->priv->main_stmt->stmt_type != GDA_SQL_STATEMENT_SELECT) {
+ g_warning (_("Wrong statement type"));
+ return 0;
+ }
+
+ /* determine join position */
+ GdaSqlStatementSelect *sel = (GdaSqlStatementSelect*) builder->priv->main_stmt->contents;
+ GSList *list;
+ gint left_pos = -1, right_pos = -1;
+ gint pos;
+ for (pos = 0, list = sel->from ? sel->from->targets : NULL;
+ list;
+ pos++, list = list->next) {
+ BuildTarget *btarget = (BuildTarget*) list->data;
+ if (btarget->part_id == left_target_id)
+ left_pos = pos;
+ else if (btarget->part_id == right_target_id)
+ right_pos = pos;
+ if ((left_pos != -1) && (right_pos != -1))
+ break;
+ }
+ if ((left_pos == -1) || (right_pos == -1)) {
+ g_warning (_("Unknown part ID %u"), (left_pos == -1) ? left_pos : right_pos);
+ return 0;
+ }
+
+ if (left_pos > right_pos) {
+ TO_IMPLEMENT;
+ }
+
+ /* create join */
+ BuilderJoin *bjoin;
+ GdaSqlSelectJoin *join;
+
+ bjoin = g_new0 (BuilderJoin, 1);
+ GDA_SQL_ANY_PART(bjoin)->type = GDA_SQL_ANY_SQL_SELECT_JOIN;
+ GDA_SQL_ANY_PART(bjoin)->parent = GDA_SQL_ANY_PART (sel->from);
+ if (id)
+ bjoin->part_id = id;
+ else
+ bjoin->part_id = builder->priv->next_assigned_id --;
+ join = (GdaSqlSelectJoin*) bjoin;
+ join->type = join_type;
+ join->position = right_pos;
+
+ SqlPart *ep;
+ ep = get_part (builder, join_expr, GDA_SQL_ANY_EXPR);
+ if (ep)
+ join->expr = (GdaSqlExpr*) use_part (ep, GDA_SQL_ANY_PART (join));
+
+ sel->from->joins = g_slist_append (sel->from->joins, bjoin);
+
+ return bjoin->part_id;
+}
+
+/**
+ * gda_sql_builder_join_add_field
+ * @builder: a #GdaSqlBuilder object
+ * @join_id: the ID of the join to modify (not %0)
+ * @field_name: the name of the field to use in the join condition (not %NULL)
+ *
+ * Alter a joins in a SELECT statement to make its condition on the field which name
+ * is @field_name
+ *
+ * Returns: the ID of the new join, or 0 if there was an error
+ *
+ * Since: 4.2
+ */
+void
+gda_sql_builder_join_add_field (GdaSqlBuilder *builder, guint join_id, const gchar *field_name)
+{
+ g_return_if_fail (GDA_IS_SQL_BUILDER (builder));
+ g_return_if_fail (builder->priv->main_stmt);
+ g_return_if_fail (field_name);
+
+ if (builder->priv->main_stmt->stmt_type != GDA_SQL_STATEMENT_SELECT) {
+ g_warning (_("Wrong statement type"));
+ return;
+ }
+
+ /* determine join */
+ GdaSqlStatementSelect *sel = (GdaSqlStatementSelect*) builder->priv->main_stmt->contents;
+ GdaSqlSelectJoin *join = NULL;
+ GSList *list;
+ for (list = sel->from ? sel->from->joins : NULL;
+ list;
+ list = list->next) {
+ BuilderJoin *bjoin = (BuilderJoin*) list->data;
+ if (bjoin->part_id == join_id) {
+ join = (GdaSqlSelectJoin*) bjoin;
+ break;
+ }
+ }
+ if (!join) {
+ g_warning (_("Unknown part ID %u"), join_id);
+ return;
+ }
+
+ GdaSqlField *field;
+ field = gda_sql_field_new (GDA_SQL_ANY_PART (join));
+ field->field_name = g_strdup (field_name);
+ join->use = g_slist_append (join->use, field);
}
diff --git a/libgda/gda-sql-builder.h b/libgda/gda-sql-builder.h
index ce3cf2e..c3cc362 100644
--- a/libgda/gda-sql-builder.h
+++ b/libgda/gda-sql-builder.h
@@ -74,15 +74,27 @@ guint gda_sql_builder_literal (GdaSqlBuilder *builder, guint id, co
guint gda_sql_builder_expr (GdaSqlBuilder *builder, guint id, GdaDataHandler *dh, GType type, ...);
guint gda_sql_builder_param (GdaSqlBuilder *builder, guint id, const gchar *param_name, GType type, gboolean nullok);
-guint gda_sql_builder_cond1 (GdaSqlBuilder *builder, guint id, GdaSqlOperatorType op, guint op1);
-guint gda_sql_builder_cond2 (GdaSqlBuilder *builder, guint id, GdaSqlOperatorType op, guint op1, guint op2);
-guint gda_sql_builder_cond3 (GdaSqlBuilder *builder, guint id, GdaSqlOperatorType op, guint op1, guint op2, guint op3);
+guint gda_sql_builder_cond (GdaSqlBuilder *builder, guint id, GdaSqlOperatorType op,
+ guint op1, guint op2, guint op3);
+
+
+/* SELECT Statement API */
+guint gda_sql_builder_select_add_target (GdaSqlBuilder *builder, guint id,
+ guint table_id, const gchar *alias);
+guint gda_sql_builder_select_join_targets (GdaSqlBuilder *builder, guint id,
+ guint left_target_id, guint right_target_id,
+ GdaSqlSelectJoinType join_type,
+ guint join_expr);
+void gda_sql_builder_join_add_field (GdaSqlBuilder *builder, guint join_id, const gchar *field_name);
+
/* General Statement API */
void gda_sql_builder_set_table (GdaSqlBuilder *builder, const gchar *table_name);
void gda_sql_builder_set_where (GdaSqlBuilder *builder, guint cond_id);
-void gda_sql_builder_add_field_value (GdaSqlBuilder *builder, const gchar *field_name, guint value_id);
+void gda_sql_builder_add_field (GdaSqlBuilder *builder, guint field_id, guint value_id);
+
+
G_END_DECLS
diff --git a/libgda/handlers/gda-handler-time.c b/libgda/handlers/gda-handler-time.c
index f56c336..7a4bbeb 100644
--- a/libgda/handlers/gda-handler-time.c
+++ b/libgda/handlers/gda-handler-time.c
@@ -273,6 +273,7 @@ handler_compute_locale (GdaHandlerTime *hdl)
date = g_date_new_dmy (4, 7, 1976); /* Same date used by GLib */
g_date_strftime (buf, 127, "%x", date);
+ g_date_free (date);
/* 1st number */
ptr = buf;
diff --git a/libgda/libgda.symbols b/libgda/libgda.symbols
index 6b35168..9b51887 100644
--- a/libgda/libgda.symbols
+++ b/libgda/libgda.symbols
@@ -148,6 +148,7 @@
gda_connection_open_from_string
gda_connection_options_get_type
gda_connection_perform_operation
+ gda_connection_repetitive_statement_execute
gda_connection_rollback_savepoint
gda_connection_rollback_transaction
gda_connection_schema_get_type
@@ -466,6 +467,11 @@
gda_quark_list_new
gda_quark_list_new_from_string
gda_quark_list_remove
+ gda_repetitive_statement_append_set
+ gda_repetitive_statement_get_all_sets
+ gda_repetitive_statement_get_template_set
+ gda_repetitive_statement_get_type
+ gda_repetitive_statement_new
gda_rfc1738_decode
gda_rfc1738_encode
gda_row_get_length
diff --git a/libgda/sql-parser/gda-statement-struct-parts.h b/libgda/sql-parser/gda-statement-struct-parts.h
index c18a624..406c8c7 100644
--- a/libgda/sql-parser/gda-statement-struct-parts.h
+++ b/libgda/sql-parser/gda-statement-struct-parts.h
@@ -286,7 +286,7 @@ struct _GdaSqlSelectJoin
GdaSqlSelectJoinType type;
gint position; /* between a target at (pos < @position) and the one @position */
GdaSqlExpr *expr;
- GSList *use;
+ GSList *use; /* list of GdaSqlField pointers */
/* Padding for future expansion */
gpointer _gda_reserved1;
diff --git a/libgda/thread-wrapper/Makefile.am b/libgda/thread-wrapper/Makefile.am
index f40aa0b..6ca6725 100644
--- a/libgda/thread-wrapper/Makefile.am
+++ b/libgda/thread-wrapper/Makefile.am
@@ -15,6 +15,8 @@ libgda_threadwrapper_4_0_la_SOURCES = \
$(libgda_threadwrapper_headers) \
gda-thread-blob-op.h \
gda-thread-blob-op.c \
+ gda-thread-meta.h \
+ gda-thread-meta.c \
gda-thread-provider.h \
gda-thread-provider.c \
gda-thread-recordset.h \
diff --git a/libgda/thread-wrapper/gda-thread-meta.c b/libgda/thread-wrapper/gda-thread-meta.c
new file mode 100644
index 0000000..8e0db09
--- /dev/null
+++ b/libgda/thread-wrapper/gda-thread-meta.c
@@ -0,0 +1,795 @@
+/* GDA capi provider
+ * Copyright (C) 2009 The GNOME Foundation.
+ *
+ * AUTHORS:
+ * Vivien Malerba <malerba gnome-db org>
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include "gda-thread-meta.h"
+#include "gda-thread-provider.h"
+#include <libgda/gda-meta-store.h>
+#include <libgda/gda-server-provider-extra.h>
+#include <libgda/gda-connection-private.h>
+#include <libgda/gda-connection-internal.h>
+
+#define PROV_CLASS(provider) (GDA_SERVER_PROVIDER_CLASS (G_OBJECT_GET_CLASS (provider)))
+
+/* common implementation of the functions used when no parameter is passed */
+typedef struct {
+ GdaServerProvider *prov;
+ GdaConnection *cnc;
+ GdaMetaStore *store;
+ GdaMetaContext *context;
+} BasicThreadData;
+
+#define main_thread_basic_core(func,prov,cnc,store,context,error) \
+ ThreadConnectionData *cdata; \
+ BasicThreadData wdata; \
+ gpointer res; \
+ guint jid; \
+ cdata = (ThreadConnectionData*) gda_connection_internal_get_provider_data ((cnc)); \
+ if (!cdata) \
+ return FALSE; \
+ wdata.prov = cdata->cnc_provider; \
+ wdata.cnc = cdata->sub_connection; \
+ wdata.store = (store); \
+ wdata.context = (context); \
+ jid = gda_thread_wrapper_execute (cdata->wrapper, \
+ (GdaThreadWrapperFunc) (func), &wdata, NULL, NULL); \
+ res = gda_thread_wrapper_fetch_result (cdata->wrapper, TRUE, jid, (error)); \
+ return GPOINTER_TO_INT (res) ? TRUE : FALSE
+
+#define sub_thread_basic_core(func,name) \
+ gboolean retval; \
+ if (! (func)) { \
+ WARN_METHOD_NOT_IMPLEMENTED (data->prov, (name)); \
+ return GINT_TO_POINTER (0); \
+ } \
+ retval = (func) (data->prov, data->cnc, data->store, data->context, error); \
+ /*g_print ("/%s() => %s\n", __FUNCTION__, retval ? "TRUE" : "FALSE");*/ \
+ return GINT_TO_POINTER (retval ? 1 : 0)
+
+typedef struct {
+ GdaServerProvider *prov;
+ GdaConnection *cnc;
+ GdaMetaStore *store;
+ GdaMetaContext *context;
+ const GValue *v1;
+ const GValue *v2;
+ const GValue *v3;
+ const GValue *v4;
+} DetailledThreadData;
+
+#define main_thread_detailled_core(func,prov,cnc,store,context,arg1,arg2,arg3,arg4,error) \
+ ThreadConnectionData *cdata; \
+ DetailledThreadData wdata; \
+ gpointer res; \
+ guint jid; \
+ cdata = (ThreadConnectionData*) gda_connection_internal_get_provider_data ((cnc)); \
+ if (!cdata) \
+ return FALSE; \
+ wdata.prov = cdata->cnc_provider; \
+ wdata.cnc = cdata->sub_connection; \
+ wdata.store = (store); \
+ wdata.context = (context); \
+ wdata.v1 = (arg1); \
+ wdata.v2 = (arg2); \
+ wdata.v3 = (arg3); \
+ wdata.v4 = (arg4); \
+ jid = gda_thread_wrapper_execute (cdata->wrapper, \
+ (GdaThreadWrapperFunc) (func), &wdata, NULL, NULL); \
+ res = gda_thread_wrapper_fetch_result (cdata->wrapper, TRUE, jid, (error)); \
+ return GPOINTER_TO_INT (res) ? TRUE : FALSE
+
+#define sub_thread_detailled1_core(func,name) \
+ gboolean retval; \
+ if (! (func)) { \
+ WARN_METHOD_NOT_IMPLEMENTED (data->prov, (name)); \
+ return GINT_TO_POINTER (0); \
+ } \
+ retval = (func) (data->prov, data->cnc, data->store, data->context, error, data->v1); \
+ /*g_print ("/%s() => %s\n", __FUNCTION__, retval ? "TRUE" : "FALSE");*/ \
+ return GINT_TO_POINTER (retval ? 1 : 0)
+
+#define sub_thread_detailled2_core(func,name) \
+ gboolean retval; \
+ if (! (func)) { \
+ WARN_METHOD_NOT_IMPLEMENTED (data->prov, (name)); \
+ return GINT_TO_POINTER (0); \
+ } \
+ retval = (func) (data->prov, data->cnc, data->store, data->context, error, data->v1, data->v2); \
+ /*g_print ("/%s() => %s\n", __FUNCTION__, retval ? "TRUE" : "FALSE");*/ \
+ return GINT_TO_POINTER (retval ? 1 : 0)
+
+#define sub_thread_detailled3_core(func,name) \
+ gboolean retval; \
+ if (! (func)) { \
+ WARN_METHOD_NOT_IMPLEMENTED (data->prov, (name)); \
+ return GINT_TO_POINTER (0); \
+ } \
+ retval = (func) (data->prov, data->cnc, data->store, data->context, error, data->v1, data->v2, data->v3); \
+ /*g_print ("/%s() => %s\n", __FUNCTION__, retval ? "TRUE" : "FALSE");*/ \
+ return GINT_TO_POINTER (retval ? 1 : 0)
+
+#define sub_thread_detailled4_core(func,name) \
+ gboolean retval; \
+ if (! (func)) { \
+ WARN_METHOD_NOT_IMPLEMENTED (data->prov, (name)); \
+ return GINT_TO_POINTER (0); \
+ } \
+ retval = (func) (data->prov, data->cnc, data->store, data->context, error, data->v1, data->v2, data->v3, data->v4); \
+ /*g_print ("/%s() => %s\n", __FUNCTION__, retval ? "TRUE" : "FALSE");*/ \
+ return GINT_TO_POINTER (retval ? 1 : 0)
+
+/*
+ * Meta initialization
+ */
+void
+_gda_thread_provider_meta_init (GdaServerProvider *provider)
+{
+ /* nothing to be done */
+}
+
+
+
+static gpointer
+sub_thread__gda_thread_meta__info (BasicThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_basic_core (PROV_CLASS (data->prov)->meta_funcs._info, "_info");
+}
+
+gboolean
+_gda_thread_meta__info (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ main_thread_basic_core (sub_thread__gda_thread_meta__info, prov, cnc, store, context, error);
+}
+
+
+
+static gpointer
+sub_thread__gda_thread_meta__btypes (BasicThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_basic_core (PROV_CLASS (data->prov)->meta_funcs._btypes, "_btypes");
+}
+
+gboolean
+_gda_thread_meta__btypes (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ main_thread_basic_core (sub_thread__gda_thread_meta__btypes, prov, cnc, store, context, error);
+}
+
+
+static gpointer
+sub_thread__gda_thread_meta__udt (BasicThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_basic_core (PROV_CLASS (data->prov)->meta_funcs._udt, "_udt");
+}
+gboolean
+_gda_thread_meta__udt (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ main_thread_basic_core (sub_thread__gda_thread_meta__udt, prov, cnc, store, context, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta_udt (DetailledThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_detailled2_core (PROV_CLASS (data->prov)->meta_funcs.udt, "_udt");
+}
+gboolean
+_gda_thread_meta_udt (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *udt_catalog, const GValue *udt_schema)
+{
+ main_thread_detailled_core (sub_thread__gda_thread_meta_udt, prov, cnc, store, context,
+ udt_catalog, udt_schema, NULL, NULL, error);
+}
+
+
+
+static gpointer
+sub_thread__gda_thread_meta__udt_cols (BasicThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_basic_core (PROV_CLASS (data->prov)->meta_funcs._udt_cols, "_udt_cols");
+}
+
+gboolean
+_gda_thread_meta__udt_cols (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ main_thread_basic_core (sub_thread__gda_thread_meta__udt_cols, prov, cnc, store, context, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta_udt_cols (DetailledThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_detailled3_core (PROV_CLASS (data->prov)->meta_funcs.udt_cols, "udt_cols");
+}
+
+gboolean
+_gda_thread_meta_udt_cols (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *udt_catalog, const GValue *udt_schema, const GValue *udt_name)
+{
+ main_thread_detailled_core (sub_thread__gda_thread_meta_udt_cols, prov, cnc, store, context,
+ udt_catalog, udt_schema, udt_name, NULL, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta__enums (BasicThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_basic_core (PROV_CLASS (data->prov)->meta_funcs._enums, "_enums");
+}
+
+gboolean
+_gda_thread_meta__enums (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ main_thread_basic_core (sub_thread__gda_thread_meta__enums, prov, cnc, store, context, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta_enums (DetailledThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_detailled3_core (PROV_CLASS (data->prov)->meta_funcs.enums, "enums");
+}
+
+gboolean
+_gda_thread_meta_enums (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *udt_catalog, const GValue *udt_schema, const GValue *udt_name)
+{
+ main_thread_detailled_core (sub_thread__gda_thread_meta_enums, prov, cnc, store, context,
+ udt_catalog, udt_schema, udt_name, NULL, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta__domains (BasicThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_basic_core (PROV_CLASS (data->prov)->meta_funcs._domains, "_domains");
+}
+
+gboolean
+_gda_thread_meta__domains (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ main_thread_basic_core (sub_thread__gda_thread_meta__domains, prov, cnc, store, context, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta_domains (DetailledThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_detailled2_core (PROV_CLASS (data->prov)->meta_funcs.domains, "domains");
+}
+
+gboolean
+_gda_thread_meta_domains (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *domain_catalog, const GValue *domain_schema)
+{
+ main_thread_detailled_core (sub_thread__gda_thread_meta_domains, prov, cnc, store, context,
+ domain_catalog, domain_schema, NULL, NULL, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta__constraints_dom (BasicThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_basic_core (PROV_CLASS (data->prov)->meta_funcs._constraints_dom, "_constraints_dom");
+}
+
+gboolean
+_gda_thread_meta__constraints_dom (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ main_thread_basic_core (sub_thread__gda_thread_meta__constraints_dom, prov, cnc, store, context, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta_constraints_dom (DetailledThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_detailled3_core (PROV_CLASS (data->prov)->meta_funcs.constraints_dom, "constraints_dom");
+}
+
+gboolean
+_gda_thread_meta_constraints_dom (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *domain_catalog, const GValue *domain_schema,
+ const GValue *domain_name)
+{
+ main_thread_detailled_core (sub_thread__gda_thread_meta_constraints_dom, prov, cnc, store, context,
+ domain_catalog, domain_schema, domain_name, NULL, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta__el_types (BasicThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_basic_core (PROV_CLASS (data->prov)->meta_funcs._el_types, "_el_types");
+}
+
+gboolean
+_gda_thread_meta__el_types (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ main_thread_basic_core (sub_thread__gda_thread_meta__el_types, prov, cnc, store, context, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta_el_types (DetailledThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_detailled1_core (PROV_CLASS (data->prov)->meta_funcs.el_types, "el_types");
+}
+
+gboolean
+_gda_thread_meta_el_types (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *specific_name)
+{
+ main_thread_detailled_core (sub_thread__gda_thread_meta_el_types, prov, cnc, store, context,
+ specific_name, NULL, NULL, NULL, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta__collations (BasicThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_basic_core (PROV_CLASS (data->prov)->meta_funcs._collations, "_collations");
+}
+
+gboolean
+_gda_thread_meta__collations (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ main_thread_basic_core (sub_thread__gda_thread_meta__collations, prov, cnc, store, context, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta_collations (DetailledThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_detailled3_core (PROV_CLASS (data->prov)->meta_funcs.collations, "collations");
+}
+
+gboolean
+_gda_thread_meta_collations (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *collation_catalog, const GValue *collation_schema,
+ const GValue *collation_name_n)
+{
+ main_thread_detailled_core (sub_thread__gda_thread_meta_collations, prov, cnc, store, context,
+ collation_catalog, collation_schema, collation_name_n, NULL, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta__character_sets (BasicThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_basic_core (PROV_CLASS (data->prov)->meta_funcs._character_sets, "_character_sets");
+}
+
+gboolean
+_gda_thread_meta__character_sets (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ main_thread_basic_core (sub_thread__gda_thread_meta__character_sets, prov, cnc, store, context, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta_character_sets (DetailledThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_detailled3_core (PROV_CLASS (data->prov)->meta_funcs.character_sets, "character_sets");
+}
+
+gboolean
+_gda_thread_meta_character_sets (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *chset_catalog, const GValue *chset_schema,
+ const GValue *chset_name_n)
+{
+ main_thread_detailled_core (sub_thread__gda_thread_meta_character_sets, prov, cnc, store, context,
+ chset_catalog, chset_schema, chset_name_n, NULL, error);
+}
+
+
+static gpointer
+sub_thread__gda_thread_meta__schemata (BasicThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_basic_core (PROV_CLASS (data->prov)->meta_funcs._schemata, "_schemata");
+}
+
+gboolean
+_gda_thread_meta__schemata (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ main_thread_basic_core (sub_thread__gda_thread_meta__schemata, prov, cnc, store, context, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta_schemata (DetailledThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_detailled2_core (PROV_CLASS (data->prov)->meta_funcs.schemata, "schemata");
+}
+
+gboolean
+_gda_thread_meta_schemata (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *catalog_name, const GValue *schema_name_n)
+{
+ main_thread_detailled_core (sub_thread__gda_thread_meta_schemata, prov, cnc, store, context,
+ catalog_name, schema_name_n, NULL, NULL, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta__tables_views (BasicThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_basic_core (PROV_CLASS (data->prov)->meta_funcs._tables_views, "_tables_views");
+}
+
+gboolean
+_gda_thread_meta__tables_views (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ main_thread_basic_core (sub_thread__gda_thread_meta__tables_views, prov, cnc, store, context, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta_tables_views (DetailledThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_detailled3_core (PROV_CLASS (data->prov)->meta_funcs.tables_views, "tables_views");
+}
+
+gboolean
+_gda_thread_meta_tables_views (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *table_catalog, const GValue *table_schema,
+ const GValue *table_name_n)
+{
+ main_thread_detailled_core (sub_thread__gda_thread_meta_tables_views, prov, cnc, store, context,
+ table_catalog, table_schema, table_name_n, NULL, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta__columns (BasicThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_basic_core (PROV_CLASS (data->prov)->meta_funcs._columns, "_columns");
+}
+
+gboolean
+_gda_thread_meta__columns (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ main_thread_basic_core (sub_thread__gda_thread_meta__columns, prov, cnc, store, context, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta_columns (DetailledThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_detailled3_core (PROV_CLASS (data->prov)->meta_funcs.columns, "columns");
+}
+
+gboolean
+_gda_thread_meta_columns (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *table_catalog, const GValue *table_schema,
+ const GValue *table_name)
+{
+ main_thread_detailled_core (sub_thread__gda_thread_meta_columns, prov, cnc, store, context,
+ table_catalog, table_schema, table_name, NULL, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta__view_cols (BasicThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_basic_core (PROV_CLASS (data->prov)->meta_funcs._view_cols, "_view_cols");
+}
+
+gboolean
+_gda_thread_meta__view_cols (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ main_thread_basic_core (sub_thread__gda_thread_meta__view_cols, prov, cnc, store, context, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta_view_cols (DetailledThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_detailled3_core (PROV_CLASS (data->prov)->meta_funcs.view_cols, "view_cols");
+}
+
+gboolean
+_gda_thread_meta_view_cols (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *view_catalog, const GValue *view_schema,
+ const GValue *view_name)
+{
+ main_thread_detailled_core (sub_thread__gda_thread_meta_view_cols, prov, cnc, store, context,
+ view_catalog, view_schema, view_name, NULL, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta__constraints_tab (BasicThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_basic_core (PROV_CLASS (data->prov)->meta_funcs._constraints_tab, "_constraints_tab");
+}
+
+gboolean
+_gda_thread_meta__constraints_tab (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ main_thread_basic_core (sub_thread__gda_thread_meta__constraints_tab, prov, cnc, store, context, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta_constraints_tab (DetailledThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_detailled4_core (PROV_CLASS (data->prov)->meta_funcs.constraints_tab, "constraints_tab");
+}
+
+gboolean
+_gda_thread_meta_constraints_tab (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *table_catalog, const GValue *table_schema,
+ const GValue *table_name, const GValue *constraint_name_n)
+{
+ main_thread_detailled_core (sub_thread__gda_thread_meta_constraints_tab, prov, cnc, store, context,
+ table_catalog, table_schema, table_name, constraint_name_n, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta__constraints_ref (BasicThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_basic_core (PROV_CLASS (data->prov)->meta_funcs._constraints_ref, "_constraints_ref");
+}
+
+gboolean
+_gda_thread_meta__constraints_ref (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ main_thread_basic_core (sub_thread__gda_thread_meta__constraints_ref, prov, cnc, store, context, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta_constraints_ref (DetailledThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_detailled4_core (PROV_CLASS (data->prov)->meta_funcs.constraints_ref, "constraints_ref");
+}
+
+gboolean
+_gda_thread_meta_constraints_ref (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *table_catalog, const GValue *table_schema, const GValue *table_name,
+ const GValue *constraint_name)
+{
+ main_thread_detailled_core (sub_thread__gda_thread_meta_constraints_ref, prov, cnc, store, context,
+ table_catalog, table_schema, table_name, constraint_name, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta__key_columns (BasicThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_basic_core (PROV_CLASS (data->prov)->meta_funcs._key_columns, "_key_columns");
+}
+
+gboolean
+_gda_thread_meta__key_columns (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ main_thread_basic_core (sub_thread__gda_thread_meta__key_columns, prov, cnc, store, context, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta_key_columns (DetailledThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_detailled4_core (PROV_CLASS (data->prov)->meta_funcs.key_columns, "key_columns");
+}
+
+gboolean
+_gda_thread_meta_key_columns (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *table_catalog, const GValue *table_schema,
+ const GValue *table_name, const GValue *constraint_name)
+{
+ main_thread_detailled_core (sub_thread__gda_thread_meta_key_columns, prov, cnc, store, context,
+ table_catalog, table_schema, table_name, constraint_name, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta__check_columns (BasicThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_basic_core (PROV_CLASS (data->prov)->meta_funcs._check_columns, "_check_columns");
+}
+
+gboolean
+_gda_thread_meta__check_columns (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ main_thread_basic_core (sub_thread__gda_thread_meta__check_columns, prov, cnc, store, context, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta_check_columns (DetailledThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_detailled4_core (PROV_CLASS (data->prov)->meta_funcs.check_columns, "check_columns");
+}
+
+gboolean
+_gda_thread_meta_check_columns (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *table_catalog, const GValue *table_schema,
+ const GValue *table_name, const GValue *constraint_name)
+{
+ main_thread_detailled_core (sub_thread__gda_thread_meta_check_columns, prov, cnc, store, context,
+ table_catalog, table_schema, table_name, constraint_name, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta__triggers (BasicThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_basic_core (PROV_CLASS (data->prov)->meta_funcs._triggers, "_triggers");
+}
+
+gboolean
+_gda_thread_meta__triggers (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ main_thread_basic_core (sub_thread__gda_thread_meta__triggers, prov, cnc, store, context, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta_triggers (DetailledThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_detailled3_core (PROV_CLASS (data->prov)->meta_funcs.triggers, "triggers");
+}
+
+gboolean
+_gda_thread_meta_triggers (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *table_catalog, const GValue *table_schema,
+ const GValue *table_name)
+{
+ main_thread_detailled_core (sub_thread__gda_thread_meta_triggers, prov, cnc, store, context,
+ table_catalog, table_schema, table_name, NULL, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta__routines (BasicThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_basic_core (PROV_CLASS (data->prov)->meta_funcs._routines, "_routines");
+}
+
+gboolean
+_gda_thread_meta__routines (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ main_thread_basic_core (sub_thread__gda_thread_meta__routines, prov, cnc, store, context, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta_routines (DetailledThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_detailled3_core (PROV_CLASS (data->prov)->meta_funcs.routines, "routines");
+}
+
+gboolean
+_gda_thread_meta_routines (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *routine_catalog, const GValue *routine_schema,
+ const GValue *routine_name_n)
+{
+ main_thread_detailled_core (sub_thread__gda_thread_meta_routines, prov, cnc, store, context,
+ routine_catalog, routine_schema, routine_name_n, NULL, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta__routine_col (BasicThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_basic_core (PROV_CLASS (data->prov)->meta_funcs._routine_col, "_routine_col");
+}
+
+gboolean
+_gda_thread_meta__routine_col (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ main_thread_basic_core (sub_thread__gda_thread_meta__routine_col, prov, cnc, store, context, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta_routine_col (DetailledThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_detailled3_core (PROV_CLASS (data->prov)->meta_funcs.routine_col, "routine_col");
+}
+
+gboolean
+_gda_thread_meta_routine_col (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *rout_catalog, const GValue *rout_schema,
+ const GValue *rout_name)
+{
+ main_thread_detailled_core (sub_thread__gda_thread_meta_routine_col, prov, cnc, store, context,
+ rout_catalog, rout_schema, rout_name, NULL, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta__routine_par (BasicThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_basic_core (PROV_CLASS (data->prov)->meta_funcs._routine_par, "_routine_par");
+}
+
+gboolean
+_gda_thread_meta__routine_par (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ main_thread_basic_core (sub_thread__gda_thread_meta__routine_par, prov, cnc, store, context, error);
+}
+
+static gpointer
+sub_thread__gda_thread_meta_routine_par (DetailledThreadData *data, GError **error)
+{
+ /* WARNING: function executed in sub thread! */
+ sub_thread_detailled3_core (PROV_CLASS (data->prov)->meta_funcs.routine_par, "routine_par");
+}
+
+gboolean
+_gda_thread_meta_routine_par (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *rout_catalog, const GValue *rout_schema,
+ const GValue *rout_name)
+{
+ main_thread_detailled_core (sub_thread__gda_thread_meta_routine_par, prov, cnc, store, context,
+ rout_catalog, rout_schema, rout_name, NULL, error);
+}
diff --git a/libgda/thread-wrapper/gda-thread-meta.h b/libgda/thread-wrapper/gda-thread-meta.h
new file mode 100644
index 0000000..e911786
--- /dev/null
+++ b/libgda/thread-wrapper/gda-thread-meta.h
@@ -0,0 +1,197 @@
+/* GDA capi provider
+ * Copyright (C) 2009 The GNOME Foundation.
+ *
+ * AUTHORS:
+ * Vivien Malerba <malerba gnome-db org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __GDA_THREAD_META_H__
+#define __GDA_THREAD_META_H__
+
+#include <libgda/gda-server-provider.h>
+
+G_BEGIN_DECLS
+
+void _gda_thread_provider_meta_init (GdaServerProvider *provider);
+
+/* _information_schema_catalog_name */
+gboolean _gda_thread_meta__info (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+
+/* _builtin_data_types */
+gboolean _gda_thread_meta__btypes (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+
+/* _udt */
+gboolean _gda_thread_meta__udt (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_thread_meta_udt (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *udt_catalog, const GValue *udt_schema);
+
+/* _udt_columns */
+gboolean _gda_thread_meta__udt_cols (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_thread_meta_udt_cols (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *udt_catalog, const GValue *udt_schema, const GValue *udt_name);
+
+/* _enums */
+gboolean _gda_thread_meta__enums (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_thread_meta_enums (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *udt_catalog, const GValue *udt_schema, const GValue *udt_name);
+
+/* _domains */
+gboolean _gda_thread_meta__domains (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_thread_meta_domains (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *domain_catalog, const GValue *domain_schema);
+
+/* _domain_constraints */
+gboolean _gda_thread_meta__constraints_dom (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_thread_meta_constraints_dom (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *domain_catalog, const GValue *domain_schema,
+ const GValue *domain_name);
+
+/* _element_types */
+gboolean _gda_thread_meta__el_types (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_thread_meta_el_types (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *specific_name);
+
+/* _collations */
+gboolean _gda_thread_meta__collations (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_thread_meta_collations (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *collation_catalog, const GValue *collation_schema,
+ const GValue *collation_name_n);
+
+/* _character_sets */
+gboolean _gda_thread_meta__character_sets (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_thread_meta_character_sets (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *chset_catalog, const GValue *chset_schema,
+ const GValue *chset_name_n);
+
+/* _schemata */
+gboolean _gda_thread_meta__schemata (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_thread_meta_schemata (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *catalog_name, const GValue *schema_name_n);
+
+/* _tables or _views */
+gboolean _gda_thread_meta__tables_views (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_thread_meta_tables_views (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *table_catalog, const GValue *table_schema,
+ const GValue *table_name_n);
+
+/* _columns */
+gboolean _gda_thread_meta__columns (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_thread_meta_columns (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *table_catalog, const GValue *table_schema,
+ const GValue *table_name);
+
+/* _view_column_usage */
+gboolean _gda_thread_meta__view_cols (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_thread_meta_view_cols (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *view_catalog, const GValue *view_schema,
+ const GValue *view_name);
+
+/* _table_constraints */
+gboolean _gda_thread_meta__constraints_tab (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_thread_meta_constraints_tab (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *table_catalog, const GValue *table_schema,
+ const GValue *table_name, const GValue *constraint_name_n);
+
+/* _referential_constraints */
+gboolean _gda_thread_meta__constraints_ref (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_thread_meta_constraints_ref (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *table_catalog, const GValue *table_schema, const GValue *table_name,
+ const GValue *constraint_name);
+
+/* _key_column_usage */
+gboolean _gda_thread_meta__key_columns (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_thread_meta_key_columns (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *table_catalog, const GValue *table_schema,
+ const GValue *table_name, const GValue *constraint_name);
+
+/* _check_column_usage */
+gboolean _gda_thread_meta__check_columns (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_thread_meta_check_columns (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *table_catalog, const GValue *table_schema,
+ const GValue *table_name, const GValue *constraint_name);
+
+/* _triggers */
+gboolean _gda_thread_meta__triggers (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_thread_meta_triggers (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *table_catalog, const GValue *table_schema,
+ const GValue *table_name);
+
+/* _routines */
+gboolean _gda_thread_meta__routines (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_thread_meta_routines (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *routine_catalog, const GValue *routine_schema,
+ const GValue *routine_name_n);
+
+/* _routine_columns */
+gboolean _gda_thread_meta__routine_col (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_thread_meta_routine_col (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *rout_catalog, const GValue *rout_schema,
+ const GValue *rout_name);
+
+/* _parameters */
+gboolean _gda_thread_meta__routine_par (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_thread_meta_routine_par (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *rout_catalog, const GValue *rout_schema,
+ const GValue *rout_name);
+
+
+G_END_DECLS
+
+#endif
+
diff --git a/libgda/thread-wrapper/gda-thread-provider.c b/libgda/thread-wrapper/gda-thread-provider.c
index 40e22a7..b3c8790 100644
--- a/libgda/thread-wrapper/gda-thread-provider.c
+++ b/libgda/thread-wrapper/gda-thread-provider.c
@@ -33,11 +33,18 @@
#include <sql-parser/gda-sql-parser.h>
#include <libgda/gda-connection-internal.h>
#include "gda-thread-provider.h"
+#include "gda-thread-meta.h"
#include "gda-thread-wrapper.h"
#include "gda-thread-recordset.h"
#define PROV_CLASS(provider) (GDA_SERVER_PROVIDER_CLASS (G_OBJECT_GET_CLASS (provider)))
+struct _GdaThreadProviderPrivate {
+ GHashTable *prov_wrappers; /* key = a provider name, value = a GdaThreadWrapper,
+ * set only if the key provider has the limiting_thread member set,
+ * because it means we must reuse the same GdaThreadWrapper */
+};
+
/*
* Per connection private data is defined as ThreadConnectionData
*/
@@ -182,6 +189,48 @@ gda_thread_provider_class_init (GdaThreadProviderClass *klass)
provider_class->create_connection = gda_thread_provider_create_connection;
memset (&(provider_class->meta_funcs), 0, sizeof (GdaServerProviderMeta));
+ provider_class->meta_funcs._info = _gda_thread_meta__info;
+ provider_class->meta_funcs._btypes = _gda_thread_meta__btypes;
+ provider_class->meta_funcs._udt = _gda_thread_meta__udt;
+ provider_class->meta_funcs.udt = _gda_thread_meta_udt;
+ provider_class->meta_funcs._udt_cols = _gda_thread_meta__udt_cols;
+ provider_class->meta_funcs.udt_cols = _gda_thread_meta_udt_cols;
+ provider_class->meta_funcs._enums = _gda_thread_meta__enums;
+ provider_class->meta_funcs.enums = _gda_thread_meta_enums;
+ provider_class->meta_funcs._domains = _gda_thread_meta__domains;
+ provider_class->meta_funcs.domains = _gda_thread_meta_domains;
+ provider_class->meta_funcs._constraints_dom = _gda_thread_meta__constraints_dom;
+ provider_class->meta_funcs.constraints_dom = _gda_thread_meta_constraints_dom;
+ provider_class->meta_funcs._el_types = _gda_thread_meta__el_types;
+ provider_class->meta_funcs.el_types = _gda_thread_meta_el_types;
+ provider_class->meta_funcs._collations = _gda_thread_meta__collations;
+ provider_class->meta_funcs.collations = _gda_thread_meta_collations;
+ provider_class->meta_funcs._character_sets = _gda_thread_meta__character_sets;
+ provider_class->meta_funcs.character_sets = _gda_thread_meta_character_sets;
+ provider_class->meta_funcs._schemata = _gda_thread_meta__schemata;
+ provider_class->meta_funcs.schemata = _gda_thread_meta_schemata;
+ provider_class->meta_funcs._tables_views = _gda_thread_meta__tables_views;
+ provider_class->meta_funcs.tables_views = _gda_thread_meta_tables_views;
+ provider_class->meta_funcs._columns = _gda_thread_meta__columns;
+ provider_class->meta_funcs.columns = _gda_thread_meta_columns;
+ provider_class->meta_funcs._view_cols = _gda_thread_meta__view_cols;
+ provider_class->meta_funcs.view_cols = _gda_thread_meta_view_cols;
+ provider_class->meta_funcs._constraints_tab = _gda_thread_meta__constraints_tab;
+ provider_class->meta_funcs.constraints_tab = _gda_thread_meta_constraints_tab;
+ provider_class->meta_funcs._constraints_ref = _gda_thread_meta__constraints_ref;
+ provider_class->meta_funcs.constraints_ref = _gda_thread_meta_constraints_ref;
+ provider_class->meta_funcs._key_columns = _gda_thread_meta__key_columns;
+ provider_class->meta_funcs.key_columns = _gda_thread_meta_key_columns;
+ provider_class->meta_funcs._check_columns = _gda_thread_meta__check_columns;
+ provider_class->meta_funcs.check_columns = _gda_thread_meta_check_columns;
+ provider_class->meta_funcs._triggers = _gda_thread_meta__triggers;
+ provider_class->meta_funcs.triggers = _gda_thread_meta_triggers;
+ provider_class->meta_funcs._routines = _gda_thread_meta__routines;
+ provider_class->meta_funcs.routines = _gda_thread_meta_routines;
+ provider_class->meta_funcs._routine_col = _gda_thread_meta__routine_col;
+ provider_class->meta_funcs.routine_col = _gda_thread_meta_routine_col;
+ provider_class->meta_funcs._routine_par = _gda_thread_meta__routine_par;
+ provider_class->meta_funcs.routine_par = _gda_thread_meta_routine_par;
/* distributed transactions: if not supported, then provider_class->xa_funcs should be set to NULL */
provider_class->xa_funcs = g_new0 (GdaServerProviderXa, 1);
@@ -191,11 +240,16 @@ gda_thread_provider_class_init (GdaThreadProviderClass *klass)
provider_class->xa_funcs->xa_commit = gda_thread_provider_xa_commit;
provider_class->xa_funcs->xa_rollback = gda_thread_provider_xa_rollback;
provider_class->xa_funcs->xa_recover = gda_thread_provider_xa_recover;
+
+ provider_class->limiting_thread = NULL;
}
static void
gda_thread_provider_init (GdaThreadProvider *thread_prv, GdaThreadProviderClass *klass)
{
+ thread_prv->priv = g_new0 (GdaThreadProviderPrivate, 1);
+ thread_prv->priv->prov_wrappers = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, g_object_unref);
}
GType
@@ -297,6 +351,9 @@ gda_thread_provider_open_connection (GdaServerProvider *provider, GdaConnection
GdaQuarkList *params, GdaQuarkList *auth,
guint *task_id, GdaServerProviderAsyncCallback async_cb, gpointer cb_data)
{
+ GdaThreadWrapper *wr = NULL;
+ gboolean wr_created = FALSE;
+
g_return_val_if_fail (GDA_IS_THREAD_PROVIDER (provider), FALSE);
g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
@@ -319,22 +376,41 @@ gda_thread_provider_open_connection (GdaServerProvider *provider, GdaConnection
if (dsn) {
data = g_new0 (OpenConnectionData, 1);
data->dsn = dsn;
+
+ GdaDsnInfo *dsninfo;
+ dsninfo = gda_config_get_dsn_info (dsn);
+ if (dsninfo)
+ wr = g_hash_table_lookup (GDA_THREAD_PROVIDER (provider)->priv->prov_wrappers,
+ dsninfo->provider);
}
else if (cnc_string) {
data = g_new0 (OpenConnectionData, 1);
data->prov_name = gda_quark_list_find (params, "PROVIDER_NAME");
data->cnc_string = cnc_string;
+ wr = g_hash_table_lookup (GDA_THREAD_PROVIDER (provider)->priv->prov_wrappers,
+ data->prov_name);
}
+ g_assert (data);
/* open sub connection */
- GdaThreadWrapper *wr;
GdaConnection *sub_cnc;
GError *error = NULL;
guint jid;
g_assert (data);
data->auth_string = auth_string;
data->options = options & (~GDA_CONNECTION_OPTIONS_THREAD_SAFE);
- wr = gda_thread_wrapper_new ();
+
+ if (!wr) {
+ wr_created = TRUE;
+ wr = gda_thread_wrapper_new ();
+ if (!wr) {
+ gda_connection_add_event_string (cnc, "%s", _("Multi threading is not supported or enabled"));
+ g_free (data);
+ return FALSE;
+ }
+ }
+ else
+ g_object_ref (wr);
jid = gda_thread_wrapper_execute (wr, (GdaThreadWrapperFunc) sub_thread_open_connection, data, NULL, NULL);
sub_cnc = gda_thread_wrapper_fetch_result (wr, TRUE, jid, &error);
g_free (dsn);
@@ -359,6 +435,13 @@ gda_thread_provider_open_connection (GdaServerProvider *provider, GdaConnection
gda_connection_internal_set_provider_data (cnc, cdata, (GDestroyNotify) gda_thread_free_cnc_data);
setup_signals (cnc, cdata);
+ if (wr_created && PROV_CLASS (cdata->cnc_provider)->limiting_thread) {
+ /* keep GdaThreadWrapper for other uses */
+ g_hash_table_insert (GDA_THREAD_PROVIDER (provider)->priv->prov_wrappers,
+ g_strdup (gda_server_provider_get_name (cdata->cnc_provider)),
+ g_object_ref (wr));
+ }
+
return TRUE;
}
diff --git a/libgda/thread-wrapper/gda-thread-provider.h b/libgda/thread-wrapper/gda-thread-provider.h
index 8cc7ec2..fd857ef 100644
--- a/libgda/thread-wrapper/gda-thread-provider.h
+++ b/libgda/thread-wrapper/gda-thread-provider.h
@@ -33,9 +33,11 @@
typedef struct _GdaThreadProvider GdaThreadProvider;
typedef struct _GdaThreadProviderClass GdaThreadProviderClass;
+typedef struct _GdaThreadProviderPrivate GdaThreadProviderPrivate;
struct _GdaThreadProvider {
GdaServerProvider provider;
+ GdaThreadProviderPrivate *priv;
};
struct _GdaThreadProviderClass {
diff --git a/libgda/thread-wrapper/gda-thread-wrapper.c b/libgda/thread-wrapper/gda-thread-wrapper.c
index cf1dd64..c6f7dd7 100644
--- a/libgda/thread-wrapper/gda-thread-wrapper.c
+++ b/libgda/thread-wrapper/gda-thread-wrapper.c
@@ -478,13 +478,15 @@ gda_thread_wrapper_get_property (GObject *object,
*
* Creates a new #GdaThreadWrapper object
*
- * Returns: a new #GdaThreadWrapper object
+ * Returns: a new #GdaThreadWrapper object, or %NULL if threads are not supported/enabled
*
* Since: 4.2
*/
GdaThreadWrapper *
gda_thread_wrapper_new (void)
{
+ if (! g_thread_supported ())
+ return NULL;
return (GdaThreadWrapper *) g_object_new (GDA_TYPE_THREAD_WRAPPER, NULL);
}
@@ -539,7 +541,7 @@ gda_thread_wrapper_execute (GdaThreadWrapper *wrapper, GdaThreadWrapperFunc func
job->shared = shared_data_ref (td->shared);
id = job->job_id;
- /*g_print ("... submitted job %d\n", id);*/
+ /* g_print ("... submitted job %d from thread %p\n", id, g_thread_self()); */
if (g_thread_self () == wrapper->priv->sub_thread) {
Result *res = g_new0 (Result, 1);
@@ -711,9 +713,6 @@ gda_thread_wrapper_iterate (GdaThreadWrapper *wrapper, gboolean may_block)
* Use this method to check if the execution of a function is finished. The function's execution must have
* been requested using gda_thread_wrapper_execute().
*
- * If @id is not %NULL, then it will contain the ID of the request if a function's execution has finished, or
- * %0 otherwise.
- *
* Returns: the pointer returned by the execution, or %NULL if no result is available
*
* Since: 4.2
diff --git a/providers/postgres/gda-postgres-provider.c b/providers/postgres/gda-postgres-provider.c
index 8d3ccbe..fcee13d 100644
--- a/providers/postgres/gda-postgres-provider.c
+++ b/providers/postgres/gda-postgres-provider.c
@@ -479,9 +479,8 @@ get_connection_type_list (PostgresConnectionData *cdata)
/* main query to fetch infos about the data types */
query = g_strdup_printf (
"SELECT t.oid, t.typname, u.usename, pg_catalog.obj_description(t.oid), t.typinput "
- "FROM pg_catalog.pg_type t, pg_catalog.pg_user u, pg_catalog.pg_namespace n "
- "WHERE t.typowner=u.usesysid "
- "AND n.oid = t.typnamespace "
+ "FROM pg_catalog.pg_type t LEFT JOIN pg_catalog.pg_user u ON (t.typowner=u.usesysid), pg_catalog.pg_namespace n "
+ "WHERE n.oid = t.typnamespace "
"AND pg_catalog.pg_type_is_visible(t.oid) "
/*--AND (n.nspname = 'public' OR n.nspname = 'pg_catalog')*/
"AND typname !~ '^_' "
diff --git a/samples/MetaStore/Makefile b/samples/MetaStore/Makefile
index ac54d74..ec09666 100644
--- a/samples/MetaStore/Makefile
+++ b/samples/MetaStore/Makefile
@@ -1,12 +1,15 @@
CFLAGS = -Wall -g -DGDA_DISABLE_DEPRECATED `pkg-config --cflags libgda-4.0`
LDFLAGS = `pkg-config --libs libgda-4.0`
-all: example
+all: example background
example: example.c
$(CC) -o example example.c $(CFLAGS) $(LDFLAGS)
+background: background.c
+ $(CC) -o background background.c $(CFLAGS) $(LDFLAGS)
+
clean:
rm -f *~
rm -f *.o
- rm -f example
+ rm -f example background
diff --git a/samples/MetaStore/README b/samples/MetaStore/README
index 490b9b3..e693aca 100644
--- a/samples/MetaStore/README
+++ b/samples/MetaStore/README
@@ -5,14 +5,22 @@ Description:
------------
The example in this directory illustrate how to get meta data information (information about
-the database's objects), and specifically the columns of some tables.
+the database's objects). There are 2 examples.
+example.c:
+----------
The following is done:
* display columns of the 'customers' table, there should be none as the meta data has not been
yet updated
* update the meta data for the 'customers' table, and show the columns now
* update the meta data for all the tables, and this time show the columns of the 'products' table
+background.c:
+-------------
+This example executes a complete meta data update in the background (in a sub thread) using
+the GdaThreadWrapper object, while it displays some messages.
+
+
Compiling and running:
----------------------
@@ -44,3 +52,23 @@ Tables' columns:
name: gchararray
price: gdouble
wh_stored: gint
+
+
+> ./background
+Output:
+-------
+Running should produce the following output:
+
+Requesting a meta data update in the background.
+Doing some business here...
+Doing some business here...
+[...]
+Doing some business here...
+Doing some business here...
+Meta data has been updated!
+Tables' columns:
+ ref: gchararray
+ category: gint
+ name: gchararray
+ price: gdouble
+ wh_stored: gint
\ No newline at end of file
diff --git a/samples/MetaStore/background.c b/samples/MetaStore/background.c
new file mode 100644
index 0000000..a530997
--- /dev/null
+++ b/samples/MetaStore/background.c
@@ -0,0 +1,107 @@
+#include <libgda/libgda.h>
+#include <libgda/thread-wrapper/gda-thread-wrapper.h>
+
+/*
+ * Display the contents of the 'data' data model
+ */
+static void
+list_table_columns (GdaDataModel* data)
+{
+ gint nrows;
+
+ nrows = gda_data_model_get_n_rows (data);
+ if (nrows == 0)
+ g_print ("No column...\n");
+ else {
+ gint i;
+ const GValue* col_name;
+ const GValue* col_type;
+
+ g_print ("Tables' columns:\n");
+ for (i = 0; i < nrows; ++ i) {
+ col_name = gda_data_model_get_value_at (data, 0, i, NULL);
+ g_assert (col_name);
+
+ col_type = gda_data_model_get_value_at (data, 2, i, NULL);
+ g_assert (col_type);
+
+ printf(" %s: %s\n", g_value_get_string (col_name), g_value_get_string (col_type));
+ }
+ }
+}
+
+/* this function is executed in a sub thread */
+gboolean *
+sub_thread_update_meta_store (GdaConnection *cnc, GError **error)
+{
+ gboolean *result;
+ result = g_new (gboolean, 1);
+ *result = gda_connection_update_meta_store (cnc, NULL, error);
+ return result;
+}
+
+int
+main (int argc, char *argv[])
+{
+ GdaConnection* connection;
+ GdaDataModel* data;
+ GError* error = NULL;
+ GValue *value;
+
+ gda_init();
+ error = NULL;
+
+ /* open connection to the SalesTest data source, using the GDA_CONNECTION_OPTIONS_THREAD_SAFE flag
+ * to make sure we can use the same connection from multiple threads at once */
+ connection = gda_connection_open_from_dsn ("SalesTest", NULL, GDA_CONNECTION_OPTIONS_THREAD_SAFE, &error);
+ if (!connection) {
+ fprintf (stderr, "%s\n", error->message);
+ return -1;
+ }
+
+ /* update meta data */
+ GdaThreadWrapper *wrapper;
+ guint job_id;
+
+ g_print ("Requesting a meta data update in the background.\n");
+ wrapper = gda_thread_wrapper_new ();
+ job_id = gda_thread_wrapper_execute (wrapper, (GdaThreadWrapperFunc) sub_thread_update_meta_store,
+ connection, NULL, &error);
+ if (job_id == 0) {
+ fprintf (stderr, "Can't use thread wrapper: %s\n", error->message);
+ return -1;
+ }
+
+ while (1) {
+ gboolean *result;
+ g_print ("Doing some business here...\n");
+ g_usleep (100000);
+ result = (gboolean *) gda_thread_wrapper_fetch_result (wrapper, FALSE, job_id, &error);
+ if (result) {
+ gboolean meta_ok;
+
+ g_object_unref (wrapper);
+ meta_ok = *result;
+ g_free (result);
+ if (!meta_ok) {
+ fprintf (stderr, "Could not update meta data: %s\n", error->message);
+ return -1;
+ }
+ g_print ("Meta data has been updated!\n");
+ break;
+ }
+ }
+
+ /*
+ * Get columns of the 'products' table
+ */
+ g_value_set_string ((value = gda_value_new (G_TYPE_STRING)), "products");
+ data = gda_connection_get_meta_store_data (connection, GDA_CONNECTION_META_FIELDS, &error, 1,
+ "name", value);
+ if (!data)
+ return -1;
+ list_table_columns (data);
+ g_object_unref (data);
+
+ return 0;
+}
diff --git a/samples/SqlBuilder/example.c b/samples/SqlBuilder/example.c
index 24ed28d..1b0cef2 100644
--- a/samples/SqlBuilder/example.c
+++ b/samples/SqlBuilder/example.c
@@ -15,9 +15,14 @@ main (int argc, char *argv[])
gda_sql_builder_set_table (b, "customers");
- gda_sql_builder_add_field_value (b, "e", gda_sql_builder_param (b, 0, "p1", G_TYPE_STRING, FALSE));
- gda_sql_builder_add_field_value (b, "f", gda_sql_builder_expr (b, 0, NULL, G_TYPE_INT, 15));
- gda_sql_builder_add_field_value (b, "g", gda_sql_builder_expr (b, 0, NULL, G_TYPE_STRING, "joe"));
+ gda_sql_builder_add_field (b,
+ gda_sql_builder_literal (b, 0, "e"),
+ gda_sql_builder_param (b, 0, "p1", G_TYPE_STRING, FALSE));
+ gda_sql_builder_add_field (b,
+ gda_sql_builder_literal (b, 0, "f"),
+ gda_sql_builder_expr (b, 0, NULL, G_TYPE_INT, 15));
+ gda_sql_builder_add_field (b, gda_sql_builder_literal (b, 0, "g"),
+ gda_sql_builder_expr (b, 0, NULL, G_TYPE_STRING, "joe"));
render_as_sql (b);
g_object_unref (b);
@@ -27,19 +32,58 @@ main (int argc, char *argv[])
b = gda_sql_builder_new (GDA_SQL_STATEMENT_UPDATE);
gda_sql_builder_set_table (b, "products");
- gda_sql_builder_add_field_value (b, "ref", gda_sql_builder_expr (b, 10, NULL, G_TYPE_STRING, "A0E'FESP"));
+ gda_sql_builder_add_field (b,
+ gda_sql_builder_literal (b, 0, "ref"),
+ gda_sql_builder_expr (b, 10, NULL, G_TYPE_STRING, "A0E'FESP"));
gda_sql_builder_literal (b, 1, "id");
gda_sql_builder_expr (b, 2, NULL, G_TYPE_INT, 14);
- gda_sql_builder_cond2 (b, 3, GDA_SQL_OPERATOR_TYPE_EQ, 1, 2);
+ gda_sql_builder_cond (b, 3, GDA_SQL_OPERATOR_TYPE_EQ, 1, 2, 0);
gda_sql_builder_set_where (b, 3);
render_as_sql (b);
/* reuse the same GdaSqlBuilder object to change the WHERE condition to: WHERE id = ##theid::int */
gda_sql_builder_set_where (b,
- gda_sql_builder_cond2 (b, 0, GDA_SQL_OPERATOR_TYPE_EQ,
- 1,
- gda_sql_builder_param (b, 0, "theid", G_TYPE_INT, FALSE)));
+ gda_sql_builder_cond (b, 0, GDA_SQL_OPERATOR_TYPE_EQ,
+ 1,
+ gda_sql_builder_param (b, 0, "theid", G_TYPE_INT, FALSE),
+ 0));
+ render_as_sql (b);
+ g_object_unref (b);
+
+ /* DELETE FROM items WHERE id = ##theid::int */
+ b = gda_sql_builder_new (GDA_SQL_STATEMENT_DELETE);
+
+ gda_sql_builder_set_table (b, "items");
+ gda_sql_builder_literal (b, 1, "id");
+ gda_sql_builder_param (b, 2, "theid", G_TYPE_INT, FALSE);
+ gda_sql_builder_cond (b, 3, GDA_SQL_OPERATOR_TYPE_EQ, 1, 2, 0);
+ gda_sql_builder_set_where (b, 3);
+
+ render_as_sql (b);
+ g_object_unref (b);
+
+ /* SELECT c.id, name, date AS person FROM customers as c, orders */
+ b = gda_sql_builder_new (GDA_SQL_STATEMENT_SELECT);
+
+ gda_sql_builder_literal (b, 1, "customers");
+ gda_sql_builder_select_add_target (b, 1, 1, "c");
+ gda_sql_builder_select_add_target (b, 2,
+ gda_sql_builder_literal (b, 0, "orders"),
+ NULL);
+ gda_sql_builder_select_join_targets (b, 5, 1, 2, GDA_SQL_SELECT_JOIN_INNER, 0);
+
+ gda_sql_builder_add_field (b,
+ gda_sql_builder_literal (b, 0, "c.id"), 0);
+ gda_sql_builder_add_field (b,
+ gda_sql_builder_literal (b, 0, "name"),
+ gda_sql_builder_literal (b, 0, "person"));
+
+ render_as_sql (b);
+
+ /* reuse the same GdaSqlBuilder object to change the INNER join's condition */
+ gda_sql_builder_join_add_field (b, 5, "id");
+
render_as_sql (b);
g_object_unref (b);
diff --git a/tools/gda-sql.c b/tools/gda-sql.c
index bf7aa3b..ad4b3cd 100644
--- a/tools/gda-sql.c
+++ b/tools/gda-sql.c
@@ -1349,9 +1349,11 @@ open_connection (SqlConsole *console, const gchar *cnc_name, const gchar *cnc_st
info = gda_config_get_dsn_info (real_cnc);
if (info && !real_provider)
- newcnc = gda_connection_open_from_dsn (real_cnc_string, real_auth_string, 0, error);
+ newcnc = gda_connection_open_from_dsn (real_cnc_string, real_auth_string,
+ GDA_CONNECTION_OPTIONS_THREAD_SAFE, error);
else
- newcnc = gda_connection_open_from_string (NULL, real_cnc_string, real_auth_string, 0, error);
+ newcnc = gda_connection_open_from_string (NULL, real_cnc_string, real_auth_string,
+ GDA_CONNECTION_OPTIONS_THREAD_SAFE, error);
g_free (real_cnc_string);
g_free (real_cnc);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]