libgda r3146 - in trunk: . doc/C doc/C/tmpl libgda libgda/sql-parser providers/mysql providers/postgres providers/skel-implementation/capi tools
- From: vivien svn gnome org
- To: svn-commits-list gnome org
- Subject: libgda r3146 - in trunk: . doc/C doc/C/tmpl libgda libgda/sql-parser providers/mysql providers/postgres providers/skel-implementation/capi tools
- Date: Tue, 15 Apr 2008 09:26:33 +0100 (BST)
Author: vivien
Date: Tue Apr 15 09:26:32 2008
New Revision: 3146
URL: http://svn.gnome.org/viewvc/libgda?rev=3146&view=rev
Log:
2008-04-15 Vivien Malerba <malerba gnome-db org>
* configure.in: Rename libext variable to avoid contaminating libtool-2.2
variable by same name, for bug #527892 (from Cygwin Ports maintainer)
* libgda/gda-connection.c: corrected a bug in gda_connection_get_events(): the
returned list is now read-only, the last GdaConnectionEvent being first in the list
* libgda/gda-connection-event.c: removed gda_connection_event_free() as
g_object_unref() should be used instead, removed gda_connection_event_list_free()
and gda_connection_event_list_copy()
* libgda/gda-util.[ch]: added a new gda_completion_list_get() function to make
Libgda compute a list of possible completions when writinf a SQL statement
* tools/command-exec.c:
* tools/gda-sql.c:
* tools/tools-input.c: improved completion mechanism using gda_completion_list_get()
* libgda/sql-parser/gda-statement-struct-util.[ch]:
* libgda/gda-meta-struct.[ch]: improved handling of double quoted SQL identifiers
* tools/gda-sql.c: removed the -p (Provider name), -s (Data source) and
-c (Direct connection string) options: now any number of connection can be opened
by listing them one after the other using either a DSN name or a connection string
like "PostgreSQL://DB_NAME=mydb"
* providers/postgres/gda-postgres-meta.c: bug fixed in the I_STMT_REF_CONSTRAINTS and
I_STMT_REF_CONSTRAINTS_ALL statements
Made a review of the DSN and connection strings in Libgda, and decided to require
string encoded using RFC 1738 (Uniform Resource Locators (URL)): the non ascii
(and some special characters) must be represented in their "%ab" form where
"ab" is their hexa. representation; this will solve problems where DSN and/or
auth string must contain some ";" character.
* libgda/gda-util.[ch]: added the gda_rfc1738_encode(), gda_rfc1738_decode(),
gda_dsn_split() and gda_connection_string_split() functions
* libgda/gda-quark-list.c: modified gda_quark_list_new_from_string() and
gda_quark_list_add_from_string() to decode the key and value for each pair.
* libgda/gda-config.[ch]: use gda_rfc1738_encode() when reading provider name, username
and password from config file.
* libgda/gda-connection.c: changed gda_connection_open_from_dsn() to accept DSN in
the form [<username>[:<password>] ]<DSN> where <username> and <password> are RFC 1738
encoded.
* libgda/sql-parser/gda-statement-struct-parts.c: applied patch by Daniel Espinosa for
bug #528057
Modified:
trunk/ChangeLog
trunk/configure.in
trunk/doc/C/libgda-4.0-docs.sgml
trunk/doc/C/libgda-4.0-sections.txt
trunk/doc/C/prov-writing.xml
trunk/doc/C/tmpl/gda-connection-event.sgml
trunk/doc/C/tmpl/gda-connection.sgml
trunk/doc/C/tmpl/gda-util.sgml
trunk/doc/C/tmpl/gda-value.sgml
trunk/libgda/gda-config.c
trunk/libgda/gda-config.h
trunk/libgda/gda-connection-event.c
trunk/libgda/gda-connection-event.h
trunk/libgda/gda-connection.c
trunk/libgda/gda-connection.h
trunk/libgda/gda-meta-struct.c
trunk/libgda/gda-meta-struct.h
trunk/libgda/gda-quark-list.c
trunk/libgda/gda-util.c
trunk/libgda/gda-util.h
trunk/libgda/sql-parser/gda-statement-struct-parts.c
trunk/libgda/sql-parser/gda-statement-struct-util.c
trunk/libgda/sql-parser/gda-statement-struct-util.h
trunk/providers/mysql/gda-mysql-blob-op.c
trunk/providers/postgres/gda-postgres-meta.c
trunk/providers/skel-implementation/capi/gda-capi-blob-op.c
trunk/tools/command-exec.c
trunk/tools/gda-sql.c
trunk/tools/tools-input.c
trunk/tools/tools-input.h
Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in (original)
+++ trunk/configure.in Tue Apr 15 09:26:32 2008
@@ -250,8 +250,8 @@
dnl this is the shared link library extension, which varies by platform
case $host_os in
- cygwin*) libext=".dll.a" ;;
- *) libext=".so" ;;
+ cygwin*) linklibext=".dll.a" ;;
+ *) linklibext=".so" ;;
esac
dnl Test for Berkeley DB
@@ -282,7 +282,7 @@
AC_MSG_CHECKING(for Berkeley DB files)
for d in $dir /usr /usr/local
do
- if test -f $d/$lib/libdb$libext -a -f $d/include/db.h
+ if test -f $d/$lib/libdb$linklibext -a -f $d/include/db.h
then
AC_MSG_RESULT(found Berkeley DB in $d)
bdblib="-ldb"
@@ -330,14 +330,14 @@
AC_MSG_CHECKING(for ODBC files)
for d in $dir /usr /usr/local
do
- if test -f $d/$lib/libodbc$libext -a -f $d/include/sql.h
+ if test -f $d/$lib/libodbc$linklibext -a -f $d/include/sql.h
then
AC_MSG_RESULT(found ODBC in $d)
odbclib="-lodbc"
odbcdir=$d
break
fi
- if test -f $d/$lib/libiodbc$libext -a -f $d/include/sql.h
+ if test -f $d/$lib/libiodbc$linklibext -a -f $d/include/sql.h
then
AC_MSG_RESULT(found iODBC in $d)
odbclib="-liodbc"
@@ -393,14 +393,14 @@
else
mysqldir_suffix=
fi
- if test -f $d/$lib/mysql/libmysqlclient.a -o -f $d/$lib/mysql/libmysqlclient$libext
+ if test -f $d/$lib/mysql/libmysqlclient.a -o -f $d/$lib/mysql/libmysqlclient$linklibext
then
AC_MSG_RESULT(found mysql in $d)
mysqldir=$d
mysqllibdir_suffix=/mysql
break
fi
- if test -f $d/$lib/libmysqlclient.a -o -f $d/$lib/libmysqlclient$libext
+ if test -f $d/$lib/libmysqlclient.a -o -f $d/$lib/libmysqlclient$linklibext
then
AC_MSG_RESULT(found mysql in $d)
mysqldir=$d
@@ -452,14 +452,14 @@
else
msqldir_suffix=
fi
- if test -f $d/$lib/msql/libmsql.a -o -f $d/$lib/msql/libmsql$libext
+ if test -f $d/$lib/msql/libmsql.a -o -f $d/$lib/msql/libmsql$linklibext
then
AC_MSG_RESULT(found mSQL in $d)
msqldir=$d
msqllibdir_suffix=/msql
break
fi
- if test -f $d/$lib/libmsql.a -o -f $d/$lib/libmsql$libext
+ if test -f $d/$lib/libmsql.a -o -f $d/$lib/libmsql$linklibext
then
AC_MSG_RESULT(found mSQL in $d)
msqldir=$d
@@ -509,7 +509,7 @@
AC_MSG_CHECKING(for Postgres files)
for d in $dir /usr /usr/local/postgres /opt/postgres /opt/packages/postgres /disk/postgres /usr/local/pgsql
do
- if test -f $d/$lib/libpq.a -o -f $d/$lib/libpq$libext
+ if test -f $d/$lib/libpq.a -o -f $d/$lib/libpq$linklibext
then
AC_MSG_RESULT(found Postgres in $d)
postgresdir=$d
@@ -569,13 +569,13 @@
AC_MSG_CHECKING(for freetds files)
for d in $dir /usr/local/freetds /usr /opt/freetds /opt/packages/freetds /opt/freetds-0.50
do
- if test -f "$d/include/tds.h" -a -e "$d/$lib/libtds$libext" -a -f "$d/include/tdsver.h"
+ if test -f "$d/include/tds.h" -a -e "$d/$lib/libtds$linklibext" -a -f "$d/include/tdsver.h"
then
AC_MSG_RESULT(found freetds in $d)
freetdsdir="$d"
freetds_incdir="$d/include"
break
- elif test -f "$d/include/freetds/tds.h" -a -e "$d/$lib/libtds$libext" -a -f "$d/include/freetds/tdsver.h"
+ elif test -f "$d/include/freetds/tds.h" -a -e "$d/$lib/libtds$linklibext" -a -f "$d/include/freetds/tdsver.h"
then
AC_MSG_RESULT(found freetds in $d and includes in $d/include/freetds)
freetdsdir="$d"
@@ -932,7 +932,7 @@
mdbdir=""
for d in $dir /usr /usr/local /opt/gnome
do
- if test -f $d/include/mdbtools.h -a -f $d/$lib/libmdb$libext -o -f $d/include/mdbtools.h -a -f $d/$lib/libmdb.a
+ if test -f $d/include/mdbtools.h -a -f $d/$lib/libmdb$linklibext -o -f $d/include/mdbtools.h -a -f $d/$lib/libmdb.a
then
AC_MSG_RESULT(found MDB Tools in $d)
mdbdir=$d
Modified: trunk/doc/C/libgda-4.0-docs.sgml
==============================================================================
--- trunk/doc/C/libgda-4.0-docs.sgml (original)
+++ trunk/doc/C/libgda-4.0-docs.sgml Tue Apr 15 09:26:32 2008
@@ -791,7 +791,7 @@
</mediaobject>
</para>
- <sect2>
+ <sect2 id="information_schema:data_types">
<title>Data types</title>
<para>
Data types (as reported for example for table's columns) can be one of the following kinds:
@@ -844,6 +844,21 @@
</para>
</sect2>
+ <sect2 id="information_schema:sql_identifiers">
+ <title>SQL identifiers</title>
+ <para>
+ SQL identifiers (database object's names) are case insitive, but it is still possible to specify
+ that an SQL identifier be case sensitive by putting it between double quotes. &LIBGDA; has chosen
+ the convention that case insitive SQL identifiers should all be in lower case in the meta data's tables
+ whereas case sensitive SQL identifiers can soncain some upper case ASCII characters.
+ </para>
+ <para>
+ This convention must be respected by database providers' implementations or the
+ <link linkend="GdaMetaStruct">GdaMetaStruct</link> object and the associated features
+ (such as keyword completion) will not work properly.
+ </para>
+ </sect2>
+
<sect2>
<title>Short and full names</title>
<para>
@@ -927,19 +942,61 @@
Sales | PostgreSQL | Sales | DB_NAME=sales |
[...]
</programlisting>
- To run an interractive session, just specify a DSN (using the <option>-s DSN</option> option) or
- a connection string (using the <option>-c "connection string"</option> and <option>-p provider</option> options).
- Alternatively, it is also possible to use the "<provider>://<connection string>"
- format (such as for example "Firebird://DATABASE=/path/to/dbfile.fdb")for an all-in-one connection
- specification (pass this string without any option specifier), or set
- the GDA_SQL_CNC environment variable to contain that string, and run the command without any argument.
+ To run an interractive session, just specify a DSN or a connection string using
+ the "<provider>://<connection string>"
+ format (such as for example "Firebird://DATABASE=/path/to/dbfile.fdb"), or set
+ the GDA_SQL_CNC environment variable to contain that string, and run the command without any argument,
+ for example:
+ <programlisting>
+[prompt]> gda-sql-4.0 PostgreSQL://DB_NAME=sales
+Welcome to the GDA SQL console, version 3.99.3
+
+Type: .copyright to show usage and distribution terms
+ .? for help with internal commands
+ .q (or CTRL-D) to quit
+ (the '.' can be replaced by a '\')
+ or any query terminated by a semicolon
+
+Opening connection 'c0' for: PostgreSQL://DB_NAME=sales
+ Getting database schema information, this may take some time... Done.
+c0>
+ </programlisting>
+ Note that the "c0" is the prompt for the first opened connection.
</para>
<para>
- Several connections can be opened at once (with only one "active" at any given time), use the <option>\c</option>
+ Several connections can be opened at once (with only one "active" at any given time), by specifying
+ all of them on the command line, or by using the <option>\c</option>
and <option>\close</option> to manage (open, change, close) the connections; the prompt contains
- the name of the current connection used.
+ the name of the current connection used. The following example opens two connections, one for the "pgsales"
+ DSN, and one for the "PostgreSQL://DB_NAME=sales" connection string, and shows the usage of the ".c" command
+ to list the opened connections:
+ <programlisting>
+[prompt]> gda-sql-4.0 pgsales PostgreSQL://DB_NAME=sales
+Welcome to the GDA SQL console, version 3.99.3
+
+Type: .copyright to show usage and distribution terms
+ .? for help with internal commands
+ .q (or CTRL-D) to quit
+ (the '.' can be replaced by a '\')
+ or any query terminated by a semicolon
+
+Opening connection 'pgsales' for: pgsales
+Opening connection 'c1' for: PostgreSQL://DB_NAME=sales
+ Getting database schema information, this may take some time... Done.
+c1> .c
+ List of opened connections
+Name | Provider | DSN or connection string | Username
+--------+------------+--------------------------+---------
+pgsales | PostgreSQL | pgsales |
+c1 | PostgreSQL | DB_NAME=sales |
+(2 rows)
+
+c1>
+ </programlisting>
</para>
- <programlisting><![CDATA[
+ <para>
+ Here is another sample session showing how to use variables in statements:
+ <programlisting><![CDATA[
[prompt]> gda-sql-4.0 -p SQLite -c "DB_DIR=.;DB_NAME=sales_test"
Welcome to the GDA SQL console, version 3.1.2
@@ -962,7 +1019,8 @@
---+-------------+-------------------+---------+-----
9 | Greg Popoff | 2 | SP | MDR
c0> ]]>
- </programlisting>
+ </programlisting>
+ </para>
<para>
The &gda-sql; tool uses the following environment variables, when set:
<itemizedlist>
Modified: trunk/doc/C/libgda-4.0-sections.txt
==============================================================================
--- trunk/doc/C/libgda-4.0-sections.txt (original)
+++ trunk/doc/C/libgda-4.0-sections.txt Tue Apr 15 09:26:32 2008
@@ -684,16 +684,19 @@
<SECTION>
<FILE>gda-util</FILE>
<TITLE>Utility functions</TITLE>
-g_type_to_string
-g_type_from_string
-gda_string_hash_to_list
+gda_g_type_to_string
+gda_g_type_from_string
+<SUBSECTION>
gda_default_escape_string
-gda_sql_replace_placeholders
-gda_file_load
-gda_file_save
-gda_server_provider_get_schema_nb_columns
-gda_server_provider_init_schema_model
-<SUBSECTION Standard>
+gda_default_unescape_string
+gda_identifier_hash
+gda_identifier_equal
+gda_completion_list_get
+<SUBSECTION>
+gda_rfc1738_encode
+gda_rfc1738_decode
+gda_dsn_split
+gda_connection_string_split
</SECTION>
<SECTION>
Modified: trunk/doc/C/prov-writing.xml
==============================================================================
--- trunk/doc/C/prov-writing.xml (original)
+++ trunk/doc/C/prov-writing.xml Tue Apr 15 09:26:32 2008
@@ -320,8 +320,10 @@
are in the specified catalog and schema.
</para>
<para>
- For further information about the tables, see the schema displayed in
- the <link linkend="GdaMetaStore">GdaMetaStore</link>'s documentation.
+ Make sure you read the information about the meta data's database structure in the
+ <link linkend="information_schema">Database structure</link>, and specifically the
+ <link linkend="information_schema:data_types">data types</link> section and the
+ <link linkend="information_schema:sql_identifiers">SQL identifiers</link> section.
</para>
<sect2>
<title>_info()</title>
Modified: trunk/doc/C/tmpl/gda-connection-event.sgml
==============================================================================
--- trunk/doc/C/tmpl/gda-connection-event.sgml (original)
+++ trunk/doc/C/tmpl/gda-connection-event.sgml Tue Apr 15 09:26:32 2008
@@ -80,31 +80,6 @@
@Returns:
-<!-- ##### FUNCTION gda_connection_event_free ##### -->
-<para>
-
-</para>
-
- event:
-
-
-<!-- ##### FUNCTION gda_connection_event_list_copy ##### -->
-<para>
-
-</para>
-
- events:
- Returns:
-
-
-<!-- ##### FUNCTION gda_connection_event_list_free ##### -->
-<para>
-
-</para>
-
- events:
-
-
<!-- ##### FUNCTION gda_connection_event_set_event_type ##### -->
<para>
Modified: trunk/doc/C/tmpl/gda-connection.sgml
==============================================================================
--- trunk/doc/C/tmpl/gda-connection.sgml (original)
+++ trunk/doc/C/tmpl/gda-connection.sgml Tue Apr 15 09:26:32 2008
@@ -403,15 +403,6 @@
@Returns:
-<!-- ##### FUNCTION gda_connection_get_authentication ##### -->
-<para>
-
-</para>
-
- cnc:
- Returns:
-
-
<!-- ##### FUNCTION gda_connection_add_event ##### -->
<para>
Modified: trunk/doc/C/tmpl/gda-util.sgml
==============================================================================
--- trunk/doc/C/tmpl/gda-util.sgml (original)
+++ trunk/doc/C/tmpl/gda-util.sgml Tue Apr 15 09:26:32 2008
@@ -17,6 +17,24 @@
<!-- ##### SECTION Stability_Level ##### -->
+<!-- ##### FUNCTION gda_g_type_to_string ##### -->
+<para>
+
+</para>
+
+ type:
+ Returns:
+
+
+<!-- ##### FUNCTION gda_g_type_from_string ##### -->
+<para>
+
+</para>
+
+ str:
+ Returns:
+
+
<!-- ##### FUNCTION gda_default_escape_string ##### -->
<para>
@@ -26,22 +44,84 @@
@Returns:
-<!-- ##### FUNCTION gda_server_provider_get_schema_nb_columns ##### -->
+<!-- ##### FUNCTION gda_default_unescape_string ##### -->
+<para>
+
+</para>
+
+ string:
+ Returns:
+
+
+<!-- ##### FUNCTION gda_identifier_hash ##### -->
<para>
</para>
- schema:
+ id:
@Returns:
-<!-- ##### FUNCTION gda_server_provider_init_schema_model ##### -->
+<!-- ##### FUNCTION gda_identifier_equal ##### -->
<para>
</para>
- model:
- schema:
+ id1:
+ id2:
@Returns:
+<!-- ##### FUNCTION gda_completion_list_get ##### -->
+<para>
+
+</para>
+
+ cnc:
+ text:
+ start:
+ end:
+ Returns:
+
+
+<!-- ##### FUNCTION gda_rfc1738_encode ##### -->
+<para>
+
+</para>
+
+ string:
+ Returns:
+
+
+<!-- ##### FUNCTION gda_rfc1738_decode ##### -->
+<para>
+
+</para>
+
+ string:
+ Returns:
+
+
+<!-- ##### FUNCTION gda_dsn_split ##### -->
+<para>
+
+</para>
+
+ string:
+ out_dsn:
+ out_username:
+ out_password:
+
+
+<!-- ##### FUNCTION gda_connection_string_split ##### -->
+<para>
+
+</para>
+
+ string:
+ out_cnc_params:
+ out_provider:
+ out_username:
+ out_password:
+
+
Modified: trunk/doc/C/tmpl/gda-value.sgml
==============================================================================
--- trunk/doc/C/tmpl/gda-value.sgml (original)
+++ trunk/doc/C/tmpl/gda-value.sgml Tue Apr 15 09:26:32 2008
@@ -546,6 +546,16 @@
@Returns:
+<!-- ##### FUNCTION gda_value_bcompare ##### -->
+<para>
+
+</para>
+
+ value1:
+ value2:
+ Returns:
+
+
<!-- ##### FUNCTION gda_value_compare ##### -->
<para>
Modified: trunk/libgda/gda-config.c
==============================================================================
--- trunk/libgda/gda-config.c (original)
+++ trunk/libgda/gda-config.c Tue Apr 15 09:26:32 2008
@@ -32,6 +32,7 @@
#include <libgda/gda-set.h>
#include <libgda/gda-holder.h>
#include <libgda/gda-log.h>
+#include <libgda/gda-util.h>
#ifdef HAVE_FAM
#include <fam.h>
#include <glib/giochannel.h>
@@ -255,9 +256,9 @@
xmlFree (prop);
continue;
}
- if (!strcmp ((gchar *) prop, "DSN"))
+ if (!strcmp ((gchar *) prop, "DSN"))
info->cnc_string = g_strdup ((gchar *)value);
- else if (!strcmp ((gchar *) prop, "Provider"))
+ else if (!strcmp ((gchar *) prop, "Provider"))
info->provider = g_strdup ((gchar *)value);
else if (!strcmp ((gchar *) prop, "Description"))
info->description = g_strdup ((gchar *)value);
@@ -274,11 +275,17 @@
if (username) {
if (!info->auth_string) {
/* migrate username/password to auth_string */
- if (password)
- info->auth_string = g_strdup_printf ("USERNAME=%s;PASSWORD=%s",
- username, password);
+ gchar *s1;
+ s1 = gda_rfc1738_encode (username);
+ if (password) {
+ gchar *s2;
+ s2 = gda_rfc1738_encode (password);
+ info->auth_string = g_strdup_printf ("USERNAME=%s;PASSWORD=%s", s1, s2);
+ g_free (s2);
+ }
else
- info->auth_string = g_strdup_printf ("USERNAME=%s", username);
+ info->auth_string = g_strdup_printf ("USERNAME=%s", s1);
+ g_free (s1);
}
g_free (username);
g_free (password);
Modified: trunk/libgda/gda-config.h
==============================================================================
--- trunk/libgda/gda-config.h (original)
+++ trunk/libgda/gda-config.h Tue Apr 15 09:26:32 2008
@@ -50,11 +50,11 @@
} GdaConfigError;
struct _GdaDataSourceInfo {
- gchar *name;
- gchar *provider;
- gchar *description;
- gchar *cnc_string;
- gchar *auth_string;
+ gchar *name; /* plain text, not RFC 1738 encoded */
+ gchar *provider; /* plain text, not RFC 1738 encoded */
+ gchar *description; /* plain text, not RFC 1738 encoded */
+ gchar *cnc_string; /* semi-colon separated <key>=<value> list where <key> and <value> are RFC 1738 encoded */
+ gchar *auth_string; /* semi-colon separated <key>=<value> list where <key> and <value> are RFC 1738 encoded */
gboolean is_system;
};
Modified: trunk/libgda/gda-connection-event.c
==============================================================================
--- trunk/libgda/gda-connection-event.c (original)
+++ trunk/libgda/gda-connection-event.c Tue Apr 15 09:26:32 2008
@@ -187,56 +187,6 @@
}
/**
- * gda_connection_event_free:
- * @event: the event object.
- *
- * Frees the memory allocated by the event object.
- */
-void
-gda_connection_event_free (GdaConnectionEvent *event)
-{
- g_object_unref (G_OBJECT (event));
-}
-
-/**
- * gda_connection_event_list_copy:
- * @events: a GList holding event objects.
- *
- * Creates a new list which contains the same events as @events and
- * adds a reference for each event in the list.
- *
- * You must free the list using #gda_connection_event_list_free.
- * Returns: a list of events.
- */
-GList *
-gda_connection_event_list_copy (const GList * events)
-{
- GList *l;
- GList *new_list;
-
- new_list = g_list_copy ((GList *) events);
- for (l = new_list; l; l = l->next)
- g_object_ref (G_OBJECT (l->data));
-
- return new_list;
-}
-
-/**
- * gda_connection_event_list_free:
- * @events: a GList holding event objects.
- *
- * Frees all event objects in the list and the list itself.
- * After this function has been called, the @events parameter doesn't point
- * to valid storage any more.
- */
-void
-gda_connection_event_list_free (GList * events)
-{
- g_list_foreach (events, (GFunc) gda_connection_event_free, NULL);
- g_list_free (events);
-}
-
-/**
* gda_connection_event_set_event_type
* @event: a #GdaConnectionEvent object
* @type: the severity of the event
Modified: trunk/libgda/gda-connection-event.h
==============================================================================
--- trunk/libgda/gda-connection-event.h (original)
+++ trunk/libgda/gda-connection-event.h Tue Apr 15 09:26:32 2008
@@ -81,9 +81,6 @@
GType gda_connection_event_get_type (void) G_GNUC_CONST;
GdaConnectionEvent *gda_connection_event_new (GdaConnectionEventType type);
-void gda_connection_event_free (GdaConnectionEvent * event);
-GList *gda_connection_event_list_copy (const GList * events);
-void gda_connection_event_list_free (GList * events);
void gda_connection_event_set_event_type (GdaConnectionEvent *event, GdaConnectionEventType type);
GdaConnectionEventType gda_connection_event_get_event_type (GdaConnectionEvent *event);
Modified: trunk/libgda/gda-connection.c
==============================================================================
--- trunk/libgda/gda-connection.c (original)
+++ trunk/libgda/gda-connection.c Tue Apr 15 09:26:32 2008
@@ -41,6 +41,7 @@
#include <sql-parser/gda-sql-parser.h>
#include <sql-parser/gda-statement-struct-trans.h>
#include <libgda/gda-meta-store-extra.h>
+#include <libgda/gda-util.h>
#define PROV_CLASS(provider) (GDA_SERVER_PROVIDER_CLASS (G_OBJECT_GET_CLASS (provider)))
@@ -231,8 +232,10 @@
cnc->priv->provider_obj = NULL;
}
- if (cnc->priv->events_list)
- gda_connection_event_list_free (cnc->priv->events_list);
+ if (cnc->priv->events_list) {
+ g_list_foreach (cnc->priv->events_list, (GFunc) g_object_unref, NULL);
+ cnc->priv->events_list = NULL;
+ }
if (cnc->priv->trans_status) {
g_object_unref (cnc->priv->trans_status);
@@ -388,17 +391,24 @@
/**
* gda_connection_open_from_dsn
* @dsn: data source name.
- * @auth_string: authentication string
+ * @auth_string: authentication string, or %NULL
* @options: options for the connection (see #GdaConnectionOptions).
* @error: a place to store an error, or %NULL
*
- * This function is the way of opening database connections with libgda.
- *
- * Establishes a connection to a data source.
+ * This function is the way of opening database connections with libgda, using a pre-defined data source (DSN),
+ * see gda_config_define_dsn() for more information about how to define a DSN. If you don't want to define
+ * a DSN, it is possible to use gda_connection_open_from_string() instead of this method.
+ *
+ * The @dsn string must have the following format: "[<username>[:<password>] ]<DSN>"
+ * (if <username> and/or <password> are provided, and @auth_string is %NULL, then these username
+ * and passwords will be used). Note that if provided, <username> and <password>
+ * must be encoded as per RFC 1738, see gda_rfc1738_encode() for more information.
*
- * The @auth_string must contain the authentication information for the server
+ * The @auth_string can contain the authentication information for the server
* to accept the connection. It is a string containing semi-colon seperated named value, usually
- * like "USERNAME=...;PASSWORD=..." where the ... are replaced by actual values.
+ * like "USERNAME=...;PASSWORD=..." where the ... are replaced by actual values. Note that each
+ * name and value must be encoded as per RFC 1738, see gda_rfc1738_encode() for more information.
+ *
* The actual named parameters required depend on the provider being used, and that list is available
* as the <parameter>auth_params</parameter> member of the #GdaProviderInfo structure for each installed
* provider (use gda_config_get_provider_info() to get it). Also one can use the "gda-sql-4.0 -L" command to
@@ -412,16 +422,42 @@
{
GdaConnection *cnc = NULL;
GdaDataSourceInfo *dsn_info;
+ gchar *user, *pass, *real_dsn;
+ gchar *real_auth_string = NULL;
g_return_val_if_fail (dsn && *dsn, NULL);
+ gda_dsn_split (dsn, &real_dsn, &user, &pass);
+ if (!real_dsn) {
+ g_free (user);
+ g_free (pass);
+ g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_DSN_NOT_FOUND_ERROR,
+ _("Malformed data source specification '%s'"), dsn);
+ return NULL;
+ }
/* get the data source info */
- dsn_info = gda_config_get_dsn (dsn);
+ dsn_info = gda_config_get_dsn (real_dsn);
if (!dsn_info) {
g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_DSN_NOT_FOUND_ERROR,
- _("Data source %s not found in configuration"), dsn);
+ _("Data source %s not found in configuration"), real_dsn);
+ g_free (real_dsn);
+ g_free (user);
+ g_free (pass);
return NULL;
}
+ if (!auth_string && user) {
+ gchar *s1;
+ s1 = gda_rfc1738_encode (user);
+ if (pass) {
+ gchar *s2;
+ s2 = gda_rfc1738_encode (pass);
+ real_auth_string = g_strdup_printf ("USERNAME=%s;PASSWORD=%s", s1, s2);
+ g_free (s2);
+ }
+ else
+ real_auth_string = g_strdup_printf ("USERNAME=%s", s1);
+ g_free (s1);
+ }
/* try to find provider */
if (dsn_info->provider != NULL) {
@@ -431,16 +467,18 @@
if (prov) {
if (PROV_CLASS (prov)->create_connection) {
cnc = PROV_CLASS (prov)->create_connection (prov);
- if (cnc) {
- g_object_set (G_OBJECT (cnc), "provider_obj", prov, NULL);
- if (dsn && *dsn)
- g_object_set (G_OBJECT (cnc), "dsn", dsn, NULL);
- g_object_set (G_OBJECT (cnc), "auth_string", auth_string, "options", options, NULL);
- }
+ if (cnc)
+ g_object_set (G_OBJECT (cnc),
+ "provider_obj", prov,
+ "dsn", real_dsn,
+ "auth_string", auth_string ? auth_string : real_auth_string,
+ "options", options, NULL);
}
else
- cnc = g_object_new (GDA_TYPE_CONNECTION, "provider_obj", prov,
- "dsn", dsn, "auth_string", auth_string,
+ cnc = g_object_new (GDA_TYPE_CONNECTION,
+ "provider_obj", prov,
+ "dsn", real_dsn,
+ "auth_string", auth_string ? auth_string : real_auth_string,
"options", options, NULL);
/* open connection */
@@ -454,6 +492,10 @@
g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_PROVIDER_NOT_FOUND_ERROR,
_("Datasource configuration error: no provider specified"));
+ g_free (real_auth_string);
+ g_free (real_dsn);
+ g_free (user);
+ g_free (pass);
return cnc;
}
@@ -461,24 +503,35 @@
* gda_connection_open_from_string
* @provider_name: provider ID to connect to, or %NULL
* @cnc_string: connection string.
- * @auth_string: authentication string
+ * @auth_string: authentication string, or %NULL
* @options: options for the connection (see #GdaConnectionOptions).
* @error: a place to store an error, or %NULL
*
* Opens a connection given a provider ID and a connection string. This
* allows applications to open connections without having to create
- * a data source in the configuration. The format of @cnc_string is
+ * a data source (DSN) in the configuration. The format of @cnc_string is
* similar to PostgreSQL and MySQL connection strings. It is a semicolumn-separated
- * series of key=value pairs. Do not add extra whitespace after the semicolumn
- * separator. The possible keys depend on the provider, the "gda-sql-4.0 -L" command
+ * series of <key>=<value> pairs, where each key and value are encoded as per RFC 1738,
+ * see gda_rfc1738_encode() for more information.
+ *
+ * The possible keys depend on the provider, the "gda-sql-4.0 -L" command
* can be used to list the actual keys for each installed database provider.
*
* For example the connection string to open an SQLite connection to a database
- * file named "my_data.db" in the current directory would be "DB_DIR=.;DB_NAME=my_data".
+ * file named "my_data.db" in the current directory would be <constant>"DB_DIR=.;DB_NAME=my_data"</constant>.
+ *
+ * The @cnc_string string must have the following format:
+ * "[<provider>://][<username>[:<password>] ]<connection_params>"
+ * (if <username> and/or <password> are provided, and @auth_string is %NULL, then these username
+ * and passwords will be used, and if <provider> is provided and @provider_name is %NULL then this
+ * provider will be used). Note that if provided, <username>, <password> and <provider>
+ * must be encoded as per RFC 1738, see gda_rfc1738_encode() for more information.
*
* The @auth_string must contain the authentication information for the server
* to accept the connection. It is a string containing semi-colon seperated named values, usually
- * like "USERNAME=...;PASSWORD=..." where the ... are replaced by actual values.
+ * like "USERNAME=...;PASSWORD=..." where the ... are replaced by actual values. Note that each
+ * name and value must be encoded as per RFC 1738, see gda_rfc1738_encode() for more information.
+ *
* The actual named parameters required depend on the provider being used, and that list is available
* as the <parameter>auth_params</parameter> member of the #GdaProviderInfo structure for each installed
* provider (use gda_config_get_provider_info() to get it). Similarly to the format of the connection
@@ -496,46 +549,63 @@
GdaConnectionOptions options, GError **error)
{
GdaConnection *cnc = NULL;
- gchar *ptr, *dup;
+ gchar *user, *pass, *real_cnc, *real_provider;
+ gchar *real_auth_string = NULL;
g_return_val_if_fail (cnc_string && *cnc_string, NULL);
-
- /* try to see if connection string has the "<provider>://<real cnc string>" format */
- dup = g_strdup (cnc_string);
- for (ptr = dup; *ptr; ptr++) {
- if ((*ptr == ':') && (*(ptr+1) == '/') && (*(ptr+2) == '/')) {
- if (!provider_name)
- provider_name = dup;
- *ptr = 0;
- cnc_string = ptr + 3;
- }
+ gda_connection_string_split (cnc_string, &real_cnc, &real_provider, &user, &pass);
+ if (!real_cnc) {
+ g_free (user);
+ g_free (pass);
+ g_free (real_provider);
+ g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_DSN_NOT_FOUND_ERROR,
+ _("Malformed connection string '%s'"), cnc_string);
+ return NULL;
}
-
- if (!provider_name) {
+
+ if (!provider_name && !real_provider) {
g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_PROVIDER_NOT_FOUND_ERROR,
_("No provider specified"));
- g_free (dup);
+ g_free (user);
+ g_free (pass);
+ g_free (real_cnc);
return NULL;
}
+ if (!auth_string && user) {
+ gchar *s1;
+ s1 = gda_rfc1738_encode (user);
+ if (pass) {
+ gchar *s2;
+ s2 = gda_rfc1738_encode (pass);
+ real_auth_string = g_strdup_printf ("USERNAME=%s;PASSWORD=%s", s1, s2);
+ g_free (s2);
+ }
+ else
+ real_auth_string = g_strdup_printf ("USERNAME=%s", s1);
+ g_free (s1);
+ }
+
/* try to find provider */
- if (provider_name) {
+ if (provider_name || real_provider) {
GdaServerProvider *prov;
- prov = gda_config_get_provider_object (provider_name, error);
+ prov = gda_config_get_provider_object (provider_name ? provider_name : real_provider, error);
if (prov) {
if (PROV_CLASS (prov)->create_connection) {
cnc = PROV_CLASS (prov)->create_connection (prov);
- if (cnc) {
- g_object_set (G_OBJECT (cnc), "provider_obj", prov, NULL);
- if (cnc_string && *cnc_string)
- g_object_set (G_OBJECT (cnc), "cnc_string", cnc_string, NULL);
- g_object_set (G_OBJECT (cnc), "auth_string", auth_string, "options", options, NULL);
- }
+ if (cnc)
+ g_object_set (G_OBJECT (cnc),
+ "provider_obj", prov,
+ "cnc_string", real_cnc,
+ "auth_string", auth_string ? auth_string : real_auth_string,
+ "options", options, NULL);
}
else
- cnc = (GdaConnection *) g_object_new (GDA_TYPE_CONNECTION, "provider_obj", prov,
- "cnc-string", cnc_string, "auth_string", auth_string,
+ cnc = (GdaConnection *) g_object_new (GDA_TYPE_CONNECTION,
+ "provider_obj", prov,
+ "cnc-string", real_cnc,
+ "auth_string", auth_string ? auth_string : real_auth_string,
"options", options, NULL);
/* open the connection */
@@ -546,7 +616,10 @@
}
}
- g_free (dup);
+ g_free (real_cnc);
+ g_free (user);
+ g_free (pass);
+ g_free (real_provider);
return cnc;
}
@@ -631,13 +704,13 @@
NULL, NULL, NULL))
cnc->priv->is_open = TRUE;
else {
- GList *events;
+ const GList *events;
events = gda_connection_get_events (cnc);
if (events) {
GList *l;
- for (l = events; l; l = l->next) {
+ for (l = g_list_last ((GList*) events); l; l = l->prev) {
GdaConnectionEvent *event;
event = GDA_CONNECTION_EVENT (l->data);
@@ -647,7 +720,6 @@
gda_connection_event_get_description (event));
}
}
- g_list_free (events);
}
cnc->priv->is_open = FALSE;
@@ -660,11 +732,11 @@
if (cnc->priv->is_open) {
#ifdef GDA_DEBUG_signal
- g_print (">> 'CONN_OPENED' from %s\n", __FUNCTION__);
+ g_print (">> 'CONN_OPENED' from %s\n", __FUNCTION__);
#endif
- g_signal_emit (G_OBJECT (cnc), gda_connection_signals[CONN_OPENED], 0);
+ g_signal_emit (G_OBJECT (cnc), gda_connection_signals[CONN_OPENED], 0);
#ifdef GDA_DEBUG_signal
- g_print ("<< 'CONN_OPENED' from %s\n", __FUNCTION__);
+ g_print ("<< 'CONN_OPENED' from %s\n", __FUNCTION__);
#endif
}
@@ -1071,7 +1143,7 @@
g_return_if_fail (cnc->priv);
if (cnc->priv->events_list != NULL) {
- gda_connection_event_list_free (cnc->priv->events_list);
+ g_list_foreach (cnc->priv->events_list, (GFunc) g_object_unref, NULL);
cnc->priv->events_list = NULL;
}
}
@@ -3026,20 +3098,19 @@
* @cnc: a #GdaConnection.
*
* Retrieves a list of the last errors occurred during the connection. The returned list is
- * chronologically ordered such as that the most recent event is the #GdaConnectionEvent of the last node.
+ * chronologically ordered such as that the most recent event is the #GdaConnectionEvent of the first node.
*
- * The caller is responsible for freeing the returned list (but not the contents of each node) using
- * g_list_free().
- *
- * Returns: a new GList of #GdaConnectionEvent.
+ * Warning: the @cnc object may change the list if connection events occur
+ *
+ * Returns: a GList of #GdaConnectionEvent objects (the list should not be modified)
*/
-GList *
+const GList *
gda_connection_get_events (GdaConnection *cnc)
{
g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
g_return_val_if_fail (cnc->priv, FALSE);
- return g_list_reverse (cnc->priv->events_list);
+ return cnc->priv->events_list;
}
/**
Modified: trunk/libgda/gda-connection.h
==============================================================================
--- trunk/libgda/gda-connection.h (original)
+++ trunk/libgda/gda-connection.h Tue Apr 15 09:26:32 2008
@@ -158,7 +158,7 @@
GdaConnectionEvent *gda_connection_add_event_string (GdaConnection *cnc, const gchar *str, ...);
void gda_connection_add_events_list (GdaConnection *cnc, GList *events_list);
void gda_connection_clear_events_list (GdaConnection *cnc);
-GList *gda_connection_get_events (GdaConnection *cnc);
+const GList *gda_connection_get_events (GdaConnection *cnc);
GdaSqlParser *gda_connection_create_parser (GdaConnection *cnc);
GObject *gda_connection_batch_execute (GdaConnection *cnc,
Modified: trunk/libgda/gda-meta-struct.c
==============================================================================
--- trunk/libgda/gda-meta-struct.c (original)
+++ trunk/libgda/gda-meta-struct.c Tue Apr 15 09:26:32 2008
@@ -24,6 +24,7 @@
#include <libgda/gda-util.h>
#include <sql-parser/gda-sql-parser.h>
#include <sql-parser/gda-sql-statement.h>
+#include <sql-parser/gda-statement-struct-util.h>
/*
* Main static functions
@@ -43,10 +44,14 @@
struct _GdaMetaStructPrivate {
- GHashTable *index; /* key = [catalog].[schema].[name], value = a GdaMetaDbObject */
+ GHashTable *index; /* key = [catalog].[schema].[name], value = a GdaMetaDbObject. Note: catalog, schema and name
+ * are case sensitive (and don't have any double quote around them) */
guint features;
};
+static GdaMetaDbObject *_meta_struct_get_db_object (GdaMetaStruct *mstruct,
+ const GValue *catalog, const GValue *schema, const GValue *name);
+
static void gda_meta_db_object_free (GdaMetaDbObject *dbo);
static void gda_meta_table_free_contents (GdaMetaTable *table);
static void gda_meta_view_free_contents (GdaMetaView *view);
@@ -234,7 +239,7 @@
g_value_set_string ((catalog = gda_value_new (G_TYPE_STRING)), tmp_obj->obj_catalog);
g_value_set_string ((schema = gda_value_new (G_TYPE_STRING)), tmp_obj->obj_schema);
g_value_set_string ((name = gda_value_new (G_TYPE_STRING)), tmp_obj->obj_name);
- ref_obj = gda_meta_struct_get_db_object (mstruct, catalog, schema, name);
+ ref_obj = _meta_struct_get_db_object (mstruct, catalog, schema, name);
if (!ref_obj) {
gchar *str;
ref_obj = g_new0 (GdaMetaDbObject, 1);
@@ -295,12 +300,20 @@
* Creates a new #GdaMetaDbObject structure in @mstruct to represent the database object (of type @type)
* which can be uniquely identified as @catalog schema @name.
*
+ * If @catalog is not %NULL, then @schema should not be %NULL.
+ *
* If @catalog is %NULL and @schema is not %NULL, then the database object will be the one which is
* "visible" by default (that is which can be accessed only by its short @name name).
*
* If both @catalog and @schema are %NULL, then the database object will be the one which
* can be accessed by its @schema name name.
*
+ * Important note: @catalog, @schema and @name must respect the following convention:
+ * <itemizedlist>
+ * <listitem><para>be surrounded by double quotes for a case sensitive search</para></listitem>
+ * <listitem><para>otherwise they will be converted to lower case for search</para></listitem>
+ * </itemizedlist>
+ *
* Returns: the #GdaMetaDbObject corresponding to the database object if no error occurred, or %NULL
*/
GdaMetaDbObject *
@@ -310,60 +323,86 @@
{
GdaMetaDbObject *dbo = NULL;
GdaMetaDbObjectType real_type = type;
- GValue *real_catalog = NULL, *real_schema = NULL, *real_name = NULL;
GValue *short_name = NULL, *full_name=NULL, *owner=NULL;
+ GValue *icatalog = NULL, *ischema = NULL, *iname = NULL; /* GValue with identifiers ready to be compared */
+ /* checks */
g_return_val_if_fail (GDA_IS_META_STORE (store), NULL);
g_return_val_if_fail (GDA_IS_META_STRUCT (mstruct), NULL);
g_return_val_if_fail (name && (G_VALUE_TYPE (name) == G_TYPE_STRING), NULL);
+ g_return_val_if_fail (!catalog || (catalog && schema), NULL);
+ g_return_val_if_fail (!catalog || (G_VALUE_TYPE (catalog) == G_TYPE_STRING), NULL);
+ g_return_val_if_fail (!schema || (G_VALUE_TYPE (schema) == G_TYPE_STRING), NULL);
+
+ /* create ready to compare strings for catalog, schema and name */
+ gchar *schema_s, *name_s;
+ if (_split_identifier_string (g_value_dup_string (name), &schema_s, &name_s)) {
+ g_value_take_string ((iname = gda_value_new (G_TYPE_STRING)), _identifier_unquote (name_s));
+ if (schema_s)
+ g_value_take_string ((ischema = gda_value_new (G_TYPE_STRING)), _identifier_unquote (schema_s));
+ }
+ else
+ g_value_take_string ((iname = gda_value_new (G_TYPE_STRING)),
+ _identifier_unquote (g_value_dup_string (name)));
+ if (catalog)
+ g_value_take_string ((icatalog = gda_value_new (G_TYPE_STRING)),
+ _identifier_unquote (g_value_dup_string (catalog)));
+ if (schema && !ischema)
+ g_value_take_string ((ischema = gda_value_new (G_TYPE_STRING)),
+ _identifier_unquote (g_value_dup_string (schema)));
if (!catalog) {
if (schema) {
g_return_val_if_fail (schema && (G_VALUE_TYPE (schema) == G_TYPE_STRING), NULL);
- if (! determine_db_object_from_schema_and_name (mstruct, store, &real_type, &real_catalog,
+ if (! determine_db_object_from_schema_and_name (mstruct, store, &real_type, &icatalog,
&short_name, &full_name, &owner,
- schema, name)) {
+ ischema, iname)) {
g_set_error (error, GDA_META_STRUCT_ERROR, GDA_META_STRUCT_UNKNOWN_OBJECT_ERROR,
_("Could not find object named '%s.%s'"),
g_value_get_string (schema), g_value_get_string (name));
+ gda_value_free (ischema);
+ gda_value_free (iname);
return NULL;
}
- catalog = real_catalog;
}
else {
- if (! determine_db_object_from_short_name (mstruct, store, &real_type, &real_catalog,
- &real_schema, &real_name,
- &short_name, &full_name, &owner, name)) {
+ GValue *real_name = NULL;
+ if (! determine_db_object_from_short_name (mstruct, store, &real_type, &icatalog,
+ &ischema, &real_name,
+ &short_name, &full_name, &owner, iname)) {
g_set_error (error, GDA_META_STRUCT_ERROR, GDA_META_STRUCT_UNKNOWN_OBJECT_ERROR,
_("Could not find object named '%s'"), g_value_get_string (name));
+ gda_value_free (iname);
return NULL;
}
- if (real_name)
- name = real_name;
- catalog = real_catalog;
- schema = real_schema;
+ if (real_name) {
+ gda_value_free (iname);
+ iname = real_name;
+ }
}
}
else if (type == GDA_META_DB_UNKNOWN) {
- g_return_val_if_fail (catalog && (G_VALUE_TYPE (catalog) == G_TYPE_STRING), NULL);
- g_return_val_if_fail (schema && (G_VALUE_TYPE (schema) == G_TYPE_STRING), NULL);
-
if (! determine_db_object_from_missing_type (mstruct, store, &real_type, &short_name, &full_name, &owner,
- catalog, schema, name)) {
+ icatalog, ischema, iname)) {
g_set_error (error, GDA_META_STRUCT_ERROR, GDA_META_STRUCT_UNKNOWN_OBJECT_ERROR,
_("Could not find object named '%s.%s.%s'"), g_value_get_string (catalog),
g_value_get_string (schema), g_value_get_string (name));
+ gda_value_free (icatalog);
+ gda_value_free (ischema);
+ gda_value_free (iname);
return NULL;
}
}
type = real_type;
+
+ /* at this point icatalog, ischema and iname are NOT NULL */
/* create new GdaMetaDbObject or get already existing one */
- dbo = gda_meta_struct_get_db_object (mstruct, catalog, schema, name);
+ dbo = _meta_struct_get_db_object (mstruct, icatalog, ischema, iname);
if (!dbo) {
dbo = g_new0 (GdaMetaDbObject, 1);
- dbo->obj_catalog = g_strdup (g_value_get_string (catalog));
- dbo->obj_schema = g_strdup (g_value_get_string (schema));
+ dbo->obj_catalog = g_strdup (g_value_get_string (icatalog));
+ dbo->obj_schema = g_strdup (g_value_get_string (ischema));
dbo->obj_name = g_strdup (g_value_get_string (name));
if (short_name)
dbo->obj_short_name = g_strdup (g_value_get_string (short_name));
@@ -372,14 +411,18 @@
if (owner)
dbo->obj_owner = g_strdup (g_value_get_string (owner));
}
- else if (dbo->obj_type == type)
+ else if (dbo->obj_type == type) {
+ if (icatalog) gda_value_free (icatalog);
+ if (ischema) gda_value_free (ischema);
+ gda_value_free (iname);
return dbo; /* nothing to do */
+ }
else if (dbo->obj_type != GDA_META_DB_UNKNOWN) {
/* DB Object already exists, return an error */
g_set_error (error, GDA_META_STRUCT_ERROR, GDA_META_STRUCT_DUPLICATE_OBJECT_ERROR,
_("Object %s.%s.%s already exists in GdaMetaStruct and has a different object type"),
- g_value_get_string (catalog), g_value_get_string (schema),
- g_value_get_string (name));
+ g_value_get_string (icatalog), g_value_get_string (ischema),
+ g_value_get_string (iname));
dbo = NULL;
goto onerror;
}
@@ -395,7 +438,7 @@
gint nrows;
GdaMetaView *mv;
- model = gda_meta_store_extract (store, sql, error, "tc", catalog, "ts", schema, "tname", name, NULL);
+ model = gda_meta_store_extract (store, sql, error, "tc", icatalog, "ts", ischema, "tname", iname, NULL);
if (!model)
goto onerror;
nrows = gda_data_model_get_n_rows (model);
@@ -403,8 +446,8 @@
g_object_unref (model);
g_set_error (error, GDA_META_STRUCT_ERROR, GDA_META_STRUCT_UNKNOWN_OBJECT_ERROR,
_("View %s.%s.%s not found in meta store object"),
- g_value_get_string (catalog), g_value_get_string (schema),
- g_value_get_string (name));
+ g_value_get_string (icatalog), g_value_get_string (ischema),
+ g_value_get_string (iname));
goto onerror;
}
@@ -454,7 +497,7 @@
GdaDataModel *model;
gint i, nrows;
- model = gda_meta_store_extract (store, sql, error, "tc", catalog, "ts", schema, "tname", name, NULL);
+ model = gda_meta_store_extract (store, sql, error, "tc", icatalog, "ts", ischema, "tname", iname, NULL);
if (!model)
goto onerror;
@@ -463,8 +506,8 @@
g_object_unref (model);
g_set_error (error, GDA_META_STRUCT_ERROR, GDA_META_STRUCT_UNKNOWN_OBJECT_ERROR,
_("Table %s.%s.%s not found in meta store object"),
- g_value_get_string (catalog), g_value_get_string (schema),
- g_value_get_string (name));
+ g_value_get_string (icatalog), g_value_get_string (ischema),
+ g_value_get_string (iname));
goto onerror;
}
if (!dbo->obj_short_name)
@@ -503,7 +546,7 @@
/* primary key */
sql = "SELECT constraint_name FROM _table_constraints WHERE constraint_type='PRIMARY KEY' AND table_catalog = ##tc::string AND table_schema = ##ts::string AND table_name = ##tname::string";
- model = gda_meta_store_extract (store, sql, error, "tc", catalog, "ts", schema, "tname", name, NULL);
+ model = gda_meta_store_extract (store, sql, error, "tc", icatalog, "ts", ischema, "tname", iname, NULL);
if (!model)
goto onerror;
@@ -512,9 +555,9 @@
GdaDataModel *pkmodel;
sql = "SELECT column_name FROM _key_column_usage WHERE table_catalog = ##cc::string AND table_schema = ##cs::string AND table_name = ##tname::string AND constraint_name = ##cname::string ORDER BY ordinal_position";
pkmodel = gda_meta_store_extract (store, sql, error,
- "cc", catalog,
- "cs", schema,
- "tname", name,
+ "cc", icatalog,
+ "cs", ischema,
+ "tname", iname,
"cname", gda_data_model_get_value_at (model, 0, 0), NULL);
if (!pkmodel) {
g_object_unref (model);
@@ -545,7 +588,7 @@
/* foreign keys */
if (mstruct->priv->features & GDA_META_STRUCT_FEATURE_FOREIGN_KEYS) {
sql = "SELECT ref_table_catalog, ref_table_schema, ref_table_name FROM _referential_constraints WHERE table_catalog = ##tc::string AND table_schema = ##ts::string AND table_name = ##tname::string";
- model = gda_meta_store_extract (store, sql, error, "tc", catalog, "ts", schema, "tname", name, NULL);
+ model = gda_meta_store_extract (store, sql, error, "tc", icatalog, "ts", ischema, "tname", iname, NULL);
if (!model)
goto onerror;
@@ -559,7 +602,7 @@
fk_name = gda_data_model_get_value_at (model, 2, i);
tfk = g_new0 (GdaMetaTableForeignKey, 1);
tfk->meta_table = dbo;
- tfk->depend_on = gda_meta_struct_get_db_object (mstruct, fk_catalog, fk_schema, fk_name);
+ tfk->depend_on = _meta_struct_get_db_object (mstruct, fk_catalog, fk_schema, fk_name);
if (!tfk->depend_on) {
gchar *str;
tfk->depend_on = g_new0 (GdaMetaDbObject, 1);
@@ -594,9 +637,9 @@
if (dbo && !g_slist_find (mstruct->db_objects, dbo)) {
gchar *str;
mstruct->db_objects = g_slist_append (mstruct->db_objects, dbo);
- str = g_strdup_printf ("%s.%s.%s", g_value_get_string (catalog),
- g_value_get_string (schema),
- g_value_get_string (name));
+ str = g_strdup_printf ("%s.%s.%s", g_value_get_string (icatalog),
+ g_value_get_string (ischema),
+ g_value_get_string (iname));
g_hash_table_insert (mstruct->priv->index, str, dbo);
}
if (dbo && (mstruct->priv->features & GDA_META_STRUCT_FEATURE_FOREIGN_KEYS)) {
@@ -641,20 +684,20 @@
}
}
}
- if (real_catalog) gda_value_free (real_catalog);
- if (real_schema) gda_value_free (real_schema);
- if (real_name) gda_value_free (real_name);
+ gda_value_free (icatalog);
+ gda_value_free (ischema);
+ gda_value_free (iname);
if (short_name) gda_value_free (short_name);
if (full_name) gda_value_free (full_name);
if (owner) gda_value_free (owner);
return dbo;
onerror:
+ gda_value_free (icatalog);
+ gda_value_free (ischema);
+ gda_value_free (iname);
if (dbo)
gda_meta_db_object_free (dbo);
- if (real_catalog) gda_value_free (real_catalog);
- if (real_schema) gda_value_free (real_schema);
- if (real_name) gda_value_free (real_name);
if (short_name) gda_value_free (short_name);
if (full_name) gda_value_free (full_name);
if (owner) gda_value_free (owner);
@@ -788,30 +831,16 @@
return TRUE;
}
-/**
- * gda_meta_struct_get_db_object
- * @mstruct: a #GdaMetaStruct object
- * @catalog: the catalog the object belongs to (as a G_TYPE_STRING GValue), or %NULL
- * @schema: the schema the object belongs to (as a G_TYPE_STRING GValue), or %NULL
- * @name: the object's name (as a G_TYPE_STRING GValue), not %NULL
- *
- * Tries to locate the #GdaMetaDbObject structure representing the database object named after
- * @catalog, @schema and @name.
- *
- * If one or both of @catalog and @schema are %NULL, and more than one database object matches the name, then
- * the return value is also %NULL.
- *
- * Returns: the #GdaMetaDbObject or %NULL if not found
+/*
+ * Same as gda_meta_struct_get_db_object except that @catalog, @schema and @name are ready to be
+ * compared (no need to double quote)
*/
-GdaMetaDbObject *
-gda_meta_struct_get_db_object (GdaMetaStruct *mstruct, const GValue *catalog, const GValue *schema, const GValue *name)
+static GdaMetaDbObject *
+_meta_struct_get_db_object (GdaMetaStruct *mstruct, const GValue *catalog, const GValue *schema, const GValue *name)
{
gchar *key;
GdaMetaDbObject *dbo;
- g_return_val_if_fail (GDA_IS_META_STRUCT (mstruct), NULL);
- g_return_val_if_fail (name && (G_VALUE_TYPE (name) == G_TYPE_STRING), NULL);
-
if (catalog && schema) {
g_return_val_if_fail (G_VALUE_TYPE (catalog) == G_TYPE_STRING, NULL);
g_return_val_if_fail (G_VALUE_TYPE (schema) == G_TYPE_STRING, NULL);
@@ -861,6 +890,50 @@
}
/**
+ * gda_meta_struct_get_db_object
+ * @mstruct: a #GdaMetaStruct object
+ * @catalog: the catalog the object belongs to (as a G_TYPE_STRING GValue), or %NULL
+ * @schema: the schema the object belongs to (as a G_TYPE_STRING GValue), or %NULL
+ * @name: the object's name (as a G_TYPE_STRING GValue), not %NULL
+ *
+ * Tries to locate the #GdaMetaDbObject structure representing the database object named after
+ * @catalog, @schema and @name.
+ *
+ * If one or both of @catalog and @schema are %NULL, and more than one database object matches the name, then
+ * the return value is also %NULL.
+ *
+ * Returns: the #GdaMetaDbObject or %NULL if not found
+ */
+GdaMetaDbObject *
+gda_meta_struct_get_db_object (GdaMetaStruct *mstruct, const GValue *catalog, const GValue *schema, const GValue *name)
+{
+ GdaMetaDbObject *dbo;
+ GValue *icatalog = NULL, *ischema = NULL, *iname = NULL; /* GValue with identifiers ready to be compared */
+
+ g_return_val_if_fail (GDA_IS_META_STRUCT (mstruct), NULL);
+ g_return_val_if_fail (name && (G_VALUE_TYPE (name) == G_TYPE_STRING), NULL);
+ g_return_val_if_fail (!catalog || (catalog && schema), NULL);
+ g_return_val_if_fail (!catalog || (G_VALUE_TYPE (catalog) == G_TYPE_STRING), NULL);
+ g_return_val_if_fail (!schema || (G_VALUE_TYPE (schema) == G_TYPE_STRING), NULL);
+
+ /* prepare identifiers */
+ g_value_take_string ((iname = gda_value_new (G_TYPE_STRING)), _identifier_unquote (g_value_dup_string (name)));
+ if (catalog)
+ g_value_take_string ((icatalog = gda_value_new (G_TYPE_STRING)),
+ _identifier_unquote (g_value_dup_string (catalog)));
+ if (schema)
+ g_value_take_string ((ischema = gda_value_new (G_TYPE_STRING)),
+ _identifier_unquote (g_value_dup_string (schema)));
+
+ dbo = _meta_struct_get_db_object (mstruct, icatalog, ischema, iname);
+ if (icatalog) gda_value_free (icatalog);
+ if (ischema) gda_value_free (ischema);
+ gda_value_free (iname);
+
+ return dbo;
+}
+
+/**
* gda_meta_struct_get_table_column
* @mstruct: a #GdaMetaStruct object
* @table: the #GdaMetaTable structure to find the column for
@@ -1250,18 +1323,21 @@
next:
{
/* treat the case where name is in fact <schema>.<name> */
- const gchar *sname;
- gchar *ptr;
- sname = g_value_get_string (name);
- for (ptr = (gchar *) sname; *ptr && (*ptr != '.'); ptr++);
- if (*ptr == '.') {
- gchar *tmp = g_strdup (sname);
+ gchar *obj_schema;
+ gchar *obj_name;
+ if (_split_identifier_string (g_strdup ((gchar *) g_value_get_string (name)), &obj_schema, &obj_name)) {
GValue *sv, *nv;
gboolean retval;
- ptr = tmp + (ptr - sname);
- *ptr = 0;
- g_value_set_string ((sv = gda_value_new (G_TYPE_STRING)), tmp);
- g_value_set_string ((nv = gda_value_new (G_TYPE_STRING)), ptr + 1);
+ if (!obj_schema) {
+ g_free (obj_name);
+ return FALSE;
+ }
+ if (!obj_name) {
+ g_free (obj_schema);
+ return FALSE;
+ }
+ g_value_take_string ((sv = gda_value_new (G_TYPE_STRING)), _identifier_unquote (obj_schema));
+ g_value_take_string ((nv = gda_value_new (G_TYPE_STRING)), _identifier_unquote (obj_name));
retval = determine_db_object_from_schema_and_name (mstruct, store, in_out_type, out_catalog,
out_short_name, out_full_name, out_owner,
sv, nv);
@@ -1273,7 +1349,6 @@
gda_value_free (sv);
gda_value_free (nv);
}
- g_free (tmp);
return retval;
}
}
Modified: trunk/libgda/gda-meta-struct.h
==============================================================================
--- trunk/libgda/gda-meta-struct.h (original)
+++ trunk/libgda/gda-meta-struct.h Tue Apr 15 09:26:32 2008
@@ -117,6 +117,10 @@
* Struture to hold information about each object
* which can be created in the internal GdaMetaStore's connection.
* It is available for tables, views, triggers, ...
+ *
+ * Note: @obj_catalog, @obj_schema, @obj_name, @obj_short_name and @obj_full_name are case sensitive:
+ * one must call _identifier_needs_quotes() to know is it is necessary to surround by double quotes
+ * before using in an SQL statement
*/
typedef struct {
GdaMetaDbObjectType obj_type;
Modified: trunk/libgda/gda-quark-list.c
==============================================================================
--- trunk/libgda/gda-quark-list.c (original)
+++ trunk/libgda/gda-quark-list.c Tue Apr 15 09:26:32 2008
@@ -1,5 +1,5 @@
/* GDA Common Library
- * Copyright (C) 1998 - 2007 The GNOME Foundation.
+ * Copyright (C) 1998 - 2008 The GNOME Foundation.
*
* Authors:
* Rodrigo Moya <rodrigo gnome-db org>
@@ -22,6 +22,7 @@
*/
#include <libgda/gda-quark-list.h>
+#include <libgda/gda-util.h>
#include <glib/ghash.h>
#include <glib/gmem.h>
#include <glib/gmessages.h>
@@ -84,9 +85,17 @@
/**
* gda_quark_list_new_from_string
- * @string: a connection string.
+ * @string: a string.
*
- * Creates a new #GdaQuarkList given a connection string.
+ * Creates a new #GdaQuarkList given a string.
+ *
+ * @string must be a semi-colon separated list of "<key>=<value>" strings (for example
+ * "DB_NAME=notes;USERNAME=alfred"). Each key and value must respect the RFC 1738 recommendations: the
+ * <constant><>"#%{}|\^~[]'`;/?:@=&</constant> and space characters are replaced by
+ * <constant>"%%ab"</constant> where
+ * <constant>ab</constant> is the hexadecimal number corresponding to the character (for example the
+ * "DB_NAME=notes;USERNAME=al%%20fred" string will specify a username as "al fred"). If this formalism
+ * is not respected, then some unexpected results may occur.
*
* Returns: the newly created #GdaQuarkList.
*/
@@ -158,17 +167,23 @@
/**
* gda_quark_list_add_from_string
* @qlist: a #GdaQuarkList.
- * @string: a connection string.
+ * @string: a string.
* @cleanup: whether to cleanup the previous content or not.
*
+ * @string must be a semi-colon separated list of "<key>=<value>" strings (for example
+ * "DB_NAME=notes;USERNAME=alfred"). Each key and value must respect the RFC 1738 recommendations: the
+ * <constant><>"#%{}|\^~[]'`;/?:@=&</constant> and space characters are replaced by
+ * <constant>"%%ab"</constant> where
+ * <constant>ab</constant> is the hexadecimal number corresponding to the character (for example the
+ * "DB_NAME=notes;USERNAME=al%%20fred" string will specify a username as "al fred"). If this formalism
+ * is not respected, then some unexpected results may occur.
+ *
* Adds new key->value pairs from the given @string. If @cleanup is
* set to %TRUE, the previous contents will be discarded before adding
* the new pairs.
*/
void
-gda_quark_list_add_from_string (GdaQuarkList *qlist,
- const gchar *string,
- gboolean cleanup)
+gda_quark_list_add_from_string (GdaQuarkList *qlist, const gchar *string, gboolean cleanup)
{
gchar **arr;
@@ -189,10 +204,10 @@
if (pair && pair[0]) {
gchar *name = pair[0];
gchar *value = pair[1];
- g_hash_table_insert (qlist->hash_table,
- (gpointer) g_strdup (name),
- (gpointer) g_strdup (value));
- g_strfreev (pair);
+ gda_rfc1738_decode (name);
+ gda_rfc1738_decode (value);
+ g_hash_table_insert (qlist->hash_table, (gpointer) name, (gpointer) value);
+ g_free (pair);
}
n++;
}
Modified: trunk/libgda/gda-util.c
==============================================================================
--- trunk/libgda/gda-util.c (original)
+++ trunk/libgda/gda-util.c Tue Apr 15 09:26:32 2008
@@ -39,6 +39,7 @@
#include <locale.h>
#endif
#include <libgda/sql-parser/gda-sql-statement.h>
+#include <sql-parser/gda-statement-struct-util.h>
#include <libgda/binreloc/gda-binreloc.h>
@@ -998,3 +999,591 @@
}
return TRUE;
}
+
+
+static char *copy_ident (const gchar *ident);
+static char *concat_ident (const gchar *prefix, const gchar *ident);
+
+static gchar *sql_start_words[] = {
+ "ALTER",
+ "SELECT",
+ "INSERT",
+ "DELETE",
+ "UPDATE",
+ "CREATE",
+ "DROP",
+ "ALTER",
+ "COMMENT",
+ "BEGIN",
+ "COMMIT",
+ "ROLLBACK"
+};
+
+static gchar *sql_middle_words[] = {
+ "FROM",
+ "INNER",
+ "JOIN",
+ "LEFT",
+ "OUTER",
+ "RIGHT",
+ "OUTER",
+ "WHERE",
+ "HAVING",
+ "LIMIT",
+ "AND",
+ "OR",
+ "NOT",
+ "SET"
+};
+
+/**
+ * gda_completion_list_get
+ * @cnc: a #GdaConnection object
+ * @sql: a partial SQL statement which is the context of the completion proposal
+ * @start: starting position within @sql of the "token" to complete (starts at 0)
+ * @end: ending position within @sql of the "token" to complete
+ *
+ * Creates an array of strings (terminated by a %NULL) corresponding to possible completions.
+ * If no completion is available, then the returned array contains just one NULL entry, and
+ * if it was not possible to try to compute a completions list, then %NULL is returned.
+ *
+ * Returns: a new array of strings, or %NULL (use g_strfreev() to free the returned array)
+ */
+gchar **
+gda_completion_list_get (GdaConnection *cnc, const gchar *sql, gint start, gint end)
+{
+ GArray *compl = NULL;
+ gchar *text;
+
+ if (!cnc)
+ return NULL;
+ g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+ if (end < start)
+ return NULL;
+
+ /* init */
+ compl = g_array_new (TRUE, TRUE, sizeof (gchar *));
+ text = g_new0 (gchar, end - start + 2);
+ memcpy (text, sql + start, end - start + 1);
+ text [end - start + 1] = 0;
+
+ if (start == 0) {
+ /*
+ * start of a statement => complete with SQL start of statement words
+ */
+ gint len;
+ gint i;
+ len = strlen (text);
+ for (i = 0; i < (sizeof (sql_start_words) / sizeof (gchar*)); i++) {
+ gint clen = strlen (sql_start_words[i]);
+ if (!g_ascii_strncasecmp (sql_start_words[i], text, MIN (clen, len))) {
+ gchar *str;
+ str = g_strdup (sql_start_words[i]);
+ g_array_append_val (compl, str);
+ }
+ }
+ goto compl_finished;
+ }
+
+ if (!*text)
+ goto compl_finished;
+
+ gchar *obj_schema, *obj_name;
+ GValue *schema_value = NULL;
+
+ if (!_split_identifier_string (g_strdup (text), &obj_schema, &obj_name) &&
+ !_split_identifier_string (g_strdup_printf ("%s\"", text), &obj_schema, &obj_name)) {
+ if (text [strlen(text) - 1] == '.') {
+ obj_schema = g_strdup (text);
+ obj_schema [strlen(text) - 1] = 0;
+ obj_name = g_strdup ("");
+ }
+ else
+ goto compl_finished;
+ }
+
+ if (*obj_name == '"')
+ _remove_quotes (obj_name);
+
+ if (obj_schema) {
+ if (*obj_schema == '"')
+ _remove_quotes (obj_schema);
+ g_value_take_string ((schema_value = gda_value_new (G_TYPE_STRING)), obj_schema);
+ }
+
+ /*
+ * complete with "table" or "schema.table"
+ */
+ GdaDataModel *model;
+ GdaMetaStore *store;
+ store = gda_connection_get_meta_store (cnc);
+ if (schema_value)
+ model = gda_meta_store_extract (store,
+ "SELECT table_name FROM _tables WHERE table_schema = ##schema::string",
+ NULL, "schema", schema_value, NULL);
+ else
+ model = gda_meta_store_extract (store,
+ "SELECT table_name FROM _tables WHERE table_short_name != table_full_name",
+ NULL);
+ if (model) {
+ gint i, nrows;
+ gint len = strlen (obj_name);
+
+ nrows = gda_data_model_get_n_rows (model);
+ for (i = 0; i < nrows; i++) {
+ const gchar *tname;
+ tname = g_value_get_string (gda_data_model_get_value_at (model, 0, i));
+ if (!strncmp (tname, obj_name, len)) {
+ gchar *str;
+ if (schema_value)
+ str = concat_ident (obj_schema, tname);
+ else
+ str = copy_ident (tname);
+ g_array_append_val (compl, str);
+ }
+ }
+ g_object_unref (model);
+ }
+
+ /*
+ * complete with "table.column"
+ */
+ model = NULL;
+ if (!schema_value)
+ model = gda_meta_store_extract (store,
+ "SELECT column_name FROM _columns", NULL);
+ if (model) {
+ gint i, nrows;
+ gint len = strlen (obj_name);
+
+ nrows = gda_data_model_get_n_rows (model);
+ for (i = 0; i < nrows; i++) {
+ const gchar *cname;
+ cname = g_value_get_string (gda_data_model_get_value_at (model, 0, i));
+ if (!strncmp (cname, obj_name, len)) {
+ gchar *str;
+ str = copy_ident (cname);
+ g_array_append_val (compl, str);
+ }
+ }
+ g_object_unref (model);
+ }
+
+ /*
+ * complete with "schema.table"
+ */
+ model = NULL;
+ if (! schema_value)
+ model = gda_meta_store_extract (store, "SELECT schema_name FROM _schemata", NULL);
+ if (model) {
+ gint i, nrows;
+ gint len = strlen (obj_name);
+
+ nrows = gda_data_model_get_n_rows (model);
+ for (i = 0; i < nrows; i++) {
+ const gchar *tname;
+ tname = g_value_get_string (gda_data_model_get_value_at (model, 0, i));
+ if (!strncmp (tname, obj_name, len)) {
+ char *str;
+ GdaDataModel *m2;
+ str = copy_ident (tname);
+
+ m2 = gda_meta_store_extract (store,
+ "SELECT table_name FROM _tables WHERE table_schema = ##schema::string",
+ NULL, "schema", gda_data_model_get_value_at (model, 0, i),
+ NULL);
+ if (m2) {
+ gint i2, nrows2;
+ nrows2 = gda_data_model_get_n_rows (m2);
+ for (i2 = 0; i2 < nrows2; i2++) {
+ gchar *str2;
+ tname = g_value_get_string (gda_data_model_get_value_at (m2, 0, i2));
+ str2 = concat_ident (str, tname);
+ g_array_append_val (compl, str2);
+ }
+
+ g_object_unref (m2);
+ }
+ free (str);
+ }
+ }
+ g_object_unref (model);
+ if (compl->len > 0)
+ goto compl_finished;
+ }
+
+ if (schema_value)
+ gda_value_free (schema_value);
+ g_free (obj_name);
+
+ /*
+ * middle of a statement and no completion yet => complete with SQL statement words
+ */
+ {
+ gint len;
+ gint i;
+ len = strlen (text);
+ for (i = 0; i < (sizeof (sql_middle_words) / sizeof (gchar*)); i++) {
+ gint clen = strlen (sql_middle_words[i]);
+ if (!g_ascii_strncasecmp (sql_middle_words[i], text, MIN (clen, len))) {
+ gchar *str;
+ str = g_strdup (sql_middle_words[i]);
+ g_array_append_val (compl, str);
+ }
+ }
+ }
+
+ compl_finished:
+ g_free (text);
+ if (compl) {
+ gchar **ptr;
+ ptr = (gchar**) compl->data;
+ g_array_free (compl, FALSE);
+ return ptr;
+ }
+ else
+ return NULL;
+}
+
+
+static char *
+copy_ident (const gchar *ident)
+{
+ char *str;
+ gint tlen = strlen (ident);
+ if (_identifier_needs_quotes (ident)) {
+ str = malloc (sizeof (char) * (tlen + 3));
+ *str = '"';
+ strcpy (str+1, ident);
+ str [tlen + 1] = '"';
+ str [tlen + 2] = 0;
+ }
+ else {
+ str = malloc (sizeof (char) * (tlen + 1));
+ strcpy (str, ident);
+ }
+ return str;
+}
+
+static char *
+concat_ident (const char *prefix, const gchar *ident)
+{
+ char *str;
+ gint tlen = strlen (ident);
+ gint plen = 0;
+
+ if (prefix)
+ plen = strlen (prefix) + 1;
+
+ if (_identifier_needs_quotes (ident)) {
+ str = malloc (sizeof (char) * (plen + tlen + 3));
+ if (prefix) {
+ strcpy (str, prefix);
+ str [plen - 1] = '.';
+ str [plen] = '"';
+ strcpy (str + plen + 1, ident);
+ }
+ else {
+ *str = '"';
+ strcpy (str+1, ident);
+ }
+ str [plen + tlen + 1] = '"';
+ str [plen + tlen + 2] = 0;
+ }
+ else {
+ str = malloc (sizeof (char) * (plen + tlen + 1));
+ if (prefix) {
+ strcpy (str, prefix);
+ str [plen - 1] = '.';
+ strcpy (str + plen, ident);
+ }
+ else
+ strcpy (str, ident);
+ }
+ return str;
+}
+
+/*
+ * RFC 1738 defines that these characters should be escaped, as well
+ * any non-US-ASCII character or anything between 0x00 - 0x1F.
+ */
+static char rfc1738_unsafe_chars[] =
+{
+ (char) 0x3C, /* < */
+ (char) 0x3E, /* > */
+ (char) 0x22, /* " */
+ (char) 0x23, /* # */
+ (char) 0x25, /* % */
+ (char) 0x7B, /* { */
+ (char) 0x7D, /* } */
+ (char) 0x7C, /* | */
+ (char) 0x5C, /* \ */
+ (char) 0x5E, /* ^ */
+ (char) 0x7E, /* ~ */
+ (char) 0x5B, /* [ */
+ (char) 0x5D, /* ] */
+ (char) 0x60, /* ` */
+ (char) 0x27, /* ' */
+ (char) 0x20 /* space */
+};
+
+static char rfc1738_reserved_chars[] =
+{
+ (char) 0x3b, /* ; */
+ (char) 0x2f, /* / */
+ (char) 0x3f, /* ? */
+ (char) 0x3a, /* : */
+ (char) 0x40, /* @ */
+ (char) 0x3d, /* = */
+ (char) 0x26 /* & */
+};
+
+/**
+ * gda_rfc1738_encode
+ * @string: a string to encode
+ *
+ * Encodes @string using the RFC 1738 recommendations: the
+ * <constant><>"#%{}|\^~[]'`;/?:@=&</constant> and space characters are replaced by
+ * <constant>"%%ab"</constant> where
+ * <constant>ab</constant> is the hexadecimal number corresponding to the character.
+ *
+ * Returns: a new string
+ */
+gchar *
+gda_rfc1738_encode (const gchar *string)
+{
+ gchar *ret, *wptr;
+ const gchar *rptr;
+ gint i;
+
+ if (!string)
+ return NULL;
+ if (!*string)
+ return g_strdup ("");
+
+ ret = g_new0 (gchar, (strlen (string) * 3) + 1);
+ for (wptr = ret, rptr = string; *rptr; rptr++) {
+ gboolean enc = FALSE;
+
+ /* RFC 1738 defines these chars as unsafe */
+ for (i = 0; i < sizeof (rfc1738_reserved_chars) / sizeof (char); i++) {
+ if (*rptr == rfc1738_reserved_chars [i]) {
+ enc = TRUE;
+ break;
+ }
+ }
+ if (!enc) {
+ for (i = 0; i < sizeof (rfc1738_unsafe_chars) / sizeof (char); i++) {
+ if (*rptr == rfc1738_unsafe_chars [i]) {
+ enc = TRUE;
+ break;
+ }
+ }
+ }
+ if (!enc) {
+ /* RFC 1738 says any control chars (0x00-0x1F) are encoded */
+ if ((unsigned char) *rptr <= (unsigned char) 0x1F)
+ enc = TRUE;
+ /* RFC 1738 says 0x7f is encoded */
+ else if (*rptr == (char) 0x7F)
+ enc = TRUE;
+ /* RFC 1738 says any non-US-ASCII are encoded */
+ else if (((unsigned char) *rptr >= (unsigned char) 0x80))
+ enc = TRUE;
+ }
+
+ if (enc) {
+ sprintf (wptr, "%%%02x", (unsigned char) *rptr);
+ wptr += 3;
+ }
+ else {
+ *wptr = *rptr;
+ wptr++;
+ }
+ }
+ return ret;
+}
+
+/**
+ * gda_rfc1738_decode
+ * @string: a string to encode
+ *
+ * Decodes @string using the RFC 1738 recommendations: the
+ * <constant><>"#%{}|\^~[]'`;/?:@=&</constant> and space characters are replaced by
+ * <constant>"%%ab"</constant> where
+ * <constant>ab</constant> is the hexadecimal number corresponding to the character.
+ *
+ * @string should respect the RFC 1738 encoding. If this is not the case (for example if there
+ * is a "%2z" because 2z is not an hexadecimal value), then the part with the problem
+ * is not decoded, and the function returns FALSE.
+ *
+ * @string is decoded in place, no new string gets created.
+ *
+ * Returns: TRUE if no error occurred.
+ */
+gboolean
+gda_rfc1738_decode (gchar *string)
+{
+ gchar *wptr, *rptr;
+ gboolean retval = TRUE;
+
+ if (!string || !*string)
+ return TRUE;
+
+ for (wptr = rptr = string; *rptr; wptr++, rptr++) {
+ *wptr = *rptr;
+ if (*rptr == '%') {
+ rptr++;
+ if ((((*rptr >= 'A') && (*rptr <= 'F')) ||
+ ((*rptr >= 'a') && (*rptr <= 'f')) ||
+ ((*rptr >= '0') && (*rptr <= '9'))) &&
+ (((rptr[1] >= 'A') && (rptr[1] <= 'F')) ||
+ ((rptr[1] >= 'a') && (rptr[1] <= 'f')) ||
+ ((rptr[1] >= '0') && (rptr[1] <= '9')))) {
+ *wptr = 0;
+ if ((*rptr >= 'A') && (*rptr <= 'F'))
+ *wptr = *rptr - 'A' + 10;
+ else if ((*rptr >= 'a') && (*rptr <= 'f'))
+ *wptr = *rptr - 'a' + 10;
+ else
+ *wptr = *rptr - '0';
+ rptr++;
+ *wptr = *wptr << 4; /* multiply by 16 */
+ if (((*rptr >= 'A') && (*rptr <= 'F')) ||
+ ((*rptr >= 'a') && (*rptr <= 'f')) ||
+ ((*rptr >= '0') && (*rptr <= '9'))) {
+ if ((*rptr >= 'A') && (*rptr <= 'F'))
+ *wptr += *rptr - 'A' + 10;
+ else if ((*rptr >= 'a') && (*rptr <= 'f'))
+ *wptr += *rptr - 'a' + 10;
+ else
+ *wptr += *rptr - '0';
+ }
+ }
+ else {
+ /* error */
+ retval = FALSE;
+ rptr--;
+ }
+ }
+ }
+ *wptr = 0;
+ return TRUE;
+}
+
+
+/**
+ * gda_dsn_split
+ * @string: a string in the "[<username>[:<password>] ]<DSN>" form
+ * @out_dsn: a place to store the new string containing the <DSN> part
+ * @out_username: a place to store the new string containing the <username> part
+ * @out_password: a place to store the new string containing the <password> part
+ * @error: a place to store errors, or %NULL
+ *
+ * Extract the DSN, username and password from @string. in @string, the various parts are strings
+ * which are expected to be encoded using an RFC 1738 compliant encoding. If they are specified,
+ * the returned username and password strings are correclty decoded.
+ *
+ * @out_username and @out_password may be set to %NULL depending on @string's format.
+ */
+void
+gda_dsn_split (const gchar *string, gchar **out_dsn, gchar **out_username, gchar **out_password)
+{
+ const gchar *ptr;
+ g_return_if_fail (string);
+ g_return_if_fail (out_dsn);
+ g_return_if_fail (out_username);
+ g_return_if_fail (out_password);
+
+ *out_dsn = NULL;
+ *out_username = NULL;
+ *out_password = NULL;
+ for (ptr = string; *ptr; ptr++) {
+ if (*ptr == '@') {
+ const gchar *tmp = ptr;
+ *out_dsn = g_strdup (ptr+1);
+ for (ptr = string; ptr < tmp; ptr++) {
+ if (*ptr == ':') {
+ *out_username = g_strndup (string, ptr - string);
+ *out_password = g_strndup (ptr+1, tmp - ptr - 1);
+ }
+ }
+ if (!*out_username)
+ *out_username = g_strndup (string, tmp - string);
+ break;
+ }
+ }
+ if (!*out_dsn)
+ *out_dsn = g_strdup (string);
+
+ /* RFC 1738 decode username and password strings */
+ gda_rfc1738_decode (*out_username);
+ gda_rfc1738_decode (*out_password);
+}
+
+/**
+ * gda_connection_string_split
+ * @string: a string in the "[<provider>://][<username>[:<password>] ]<connection_params>" form
+ * @out_cnc_params: a place to store the new string containing the <connection_params> part
+ * @out_provider: a place to store the new string containing the <provider> part
+ * @out_username: a place to store the new string containing the <username> part
+ * @out_password: a place to store the new string containing the <password> part
+ * @error: a place to store errors, or %NULL
+ *
+ * Extract the provider, connection parameters, username and password from @string.
+ * in @string, the various parts are strings
+ * which are expected to be encoded using an RFC 1738 compliant encoding. If they are specified,
+ * the returned provider, username and password strings are correclty decoded.
+ */
+void
+gda_connection_string_split (const gchar *string, gchar **out_cnc_params, gchar **out_provider,
+ gchar **out_username, gchar **out_password)
+{
+ const gchar *ptr;
+ const gchar *ap;
+ g_return_if_fail (string);
+ g_return_if_fail (out_cnc_params);
+ g_return_if_fail (out_provider);
+ g_return_if_fail (out_username);
+ g_return_if_fail (out_password);
+
+ *out_cnc_params = NULL;
+ *out_provider = NULL;
+ *out_username = NULL;
+ *out_password = NULL;
+ for (ap = ptr = string; *ptr; ptr++) {
+ if ((ap == string) && (*ptr == '/') && (ptr[1] == '/')) {
+ if ((ptr == string) || (ptr[-1] != ':')) {
+ g_free (*out_cnc_params); *out_cnc_params = NULL;
+ g_free (*out_provider); *out_provider = NULL;
+ g_free (*out_username); *out_username = NULL;
+ g_free (*out_password); *out_password = NULL;
+ return;
+ }
+ *out_provider = g_strndup (string, ptr - string - 1);
+ ap = ptr+2;
+ ptr++;
+ }
+
+ if (*ptr == '@') {
+ const gchar *tmp = ptr;
+ *out_cnc_params = g_strdup (ptr+1);
+ for (ptr = ap; ptr < tmp; ptr++) {
+ if (*ptr == ':') {
+ *out_username = g_strndup (ap, ptr - ap);
+ *out_password = g_strndup (ptr+1, tmp - ptr - 1);
+ }
+ }
+ if (!*out_username)
+ *out_username = g_strndup (ap, tmp - ap);
+ break;
+ }
+ }
+ if (!*out_cnc_params)
+ *out_cnc_params = g_strdup (ap);
+
+ /* RFC 1738 decode provider, username and password strings */
+ gda_rfc1738_decode (*out_provider);
+ gda_rfc1738_decode (*out_username);
+ gda_rfc1738_decode (*out_password);
+}
Modified: trunk/libgda/gda-util.h
==============================================================================
--- trunk/libgda/gda-util.h (original)
+++ trunk/libgda/gda-util.h Tue Apr 15 09:26:32 2008
@@ -45,6 +45,7 @@
gchar *gda_default_unescape_string (const gchar *string);
guint gda_identifier_hash (const gchar *id);
gboolean gda_identifier_equal (const gchar *id1, const gchar *id2);
+gchar **gda_completion_list_get (GdaConnection *cnc, const gchar *text, gint start, gint end);
/*
* Param & model utilities
@@ -67,6 +68,16 @@
gboolean gda_compute_dml_statements (GdaConnection *cnc, GdaStatement *select_stmt, gboolean require_pk,
GdaStatement **insert, GdaStatement **update, GdaStatement **delete,
GError **error);
+
+/*
+ * DSN and connection string manipulations
+ */
+gchar *gda_rfc1738_encode (const gchar *string);
+gboolean gda_rfc1738_decode (gchar *string);
+void gda_dsn_split (const gchar *string, gchar **out_dsn,
+ gchar **out_username, gchar **out_password);
+void gda_connection_string_split (const gchar *string, gchar **out_cnc_params, gchar **out_provider,
+ gchar **out_username, gchar **out_password);
G_END_DECLS
#endif
Modified: trunk/libgda/sql-parser/gda-statement-struct-parts.c
==============================================================================
--- trunk/libgda/sql-parser/gda-statement-struct-parts.c (original)
+++ trunk/libgda/sql-parser/gda-statement-struct-parts.c Tue Apr 15 09:26:32 2008
@@ -32,6 +32,15 @@
* Sql expression
*
*/
+
+/**
+ * gda_sql_expr_new
+ * @parent: a #GdaSqlStatementInsert, #GdaSqlStatementUpdate, #GdaSqlSelectField, #GdaSqlSelectTarget, #GdaSqlOperation
+ *
+ * Creates a new #GdaSqlField structure, using @parent as its parent part.
+ *
+ * Returns: a new #GdaSqlField structure.
+ */
GdaSqlExpr *
gda_sql_expr_new (GdaSqlAnyPart *parent)
{
@@ -42,6 +51,13 @@
return expr;
}
+/**
+ * gda_sql_expr_free
+ * @expr: a #GdaSqlExpr to be freed.
+ *
+ * Frees a #GdaSqlExpr structure and its members.
+ *
+ */
void
gda_sql_expr_free (GdaSqlExpr *expr)
{
@@ -69,6 +85,14 @@
g_free (expr);
}
+/**
+ * gda_sql_expr_copy
+ * @expr: a #GdaSqlExpr
+ *
+ * Creates a new #GdaSqlExpr structure initated with the values stored in @expr.
+ *
+ * Returns: a new #GdaSqlExpr structure.
+ */
GdaSqlExpr *
gda_sql_expr_copy (GdaSqlExpr *expr)
{
@@ -110,6 +134,15 @@
return copy;
}
+/**
+ * gda_sql_expr_serialize
+ * @expr: a #GdaSqlExpr structure
+ *
+ * Creates a new string representing a field. You need to free the returned string
+ * using g_free();
+ *
+ * Returns: a new string with the name of the field or "null" in case @expr is invalid.
+ */
gchar *
gda_sql_expr_serialize (GdaSqlExpr *expr)
{
@@ -174,6 +207,15 @@
return str;
}
+/**
+ * gda_sql_expr_take_select
+ * @expr: a #GdaSqlExpr structure
+ * @stmt: a #GdaSqlStatement holding the #GdaSqlStatementSelect to take from
+ *
+ * Sets the expression's parent to the #GdaSqlStatementSelect holded by @stmt. After
+ * calling this function @stmt is freed.
+ *
+ */
void
gda_sql_expr_take_select (GdaSqlExpr *expr, GdaSqlStatement *stmt)
{
@@ -187,8 +229,13 @@
}
}
-/*
- * Any Table's field
+/**
+ * gda_sql_field_new
+ * @parent: a #GdaSqlStatementSelect, #GdaSqlStatementInsert, #GdaSqlStatementDelete, #GdaSqlStatementUpdate
+ *
+ * Creates a new #GdaSqlField structure, using @parent as its parent part.
+ *
+ * Returns: a new #GdaSqlField structure.
*/
GdaSqlField *
gda_sql_field_new (GdaSqlAnyPart *parent)
@@ -200,6 +247,13 @@
return field;
}
+/**
+ * gda_sql_field_free
+ * @field: a #GdaSqlField to be freed.
+ *
+ * Frees a #GdaSqlField structure and its members.
+ *
+ */
void
gda_sql_field_free (GdaSqlField *field)
{
@@ -210,6 +264,14 @@
g_free (field);
}
+/**
+ * gda_sql_field_copy
+ * @field: a #GdaSqlAnyPart
+ *
+ * Creates a new GdaSqlField structure initated with the values stored in @field.
+ *
+ * Returns: a new #GdaSqlField structure.
+ */
GdaSqlField *
gda_sql_field_copy (GdaSqlField *field)
{
@@ -224,6 +286,15 @@
return copy;
}
+/**
+ * gda_sql_field_serialize
+ * @field: a #GdaSqlField structure
+ *
+ * Creates a new string representing a field. You need to free the returned string
+ * using g_free();
+ *
+ * Returns: a new string with the name of the field or "null" in case @field is invalid.
+ */
gchar *
gda_sql_field_serialize (GdaSqlField *field)
{
@@ -233,18 +304,31 @@
return _json_quote_string (field->field_name);
}
+/**
+ * gda_sql_field_take_name
+ * @field: a #GdaSqlField structure
+ * @value: a #GValue holding a string to take from
+ *
+ * Sets the field's name using the string holded by @value. When call, @value is freed using
+ * #gda_value_free().
+ *
+ */
void
gda_sql_field_take_name (GdaSqlField *field, GValue *value)
{
if (value) {
field->field_name = g_value_dup_string (value);
- g_value_reset (value);
- g_free (value);
+ gda_value_free (value);
}
}
-/*
- * Structure to hold one table
+/**
+ * gda_sql_table_new
+ * @parent: a #GdaSqlStatementSelect, #GdaSqlStatementInsert, #GdaSqlStatementDelete, #GdaSqlStatementUpdate
+ *
+ * Creates a new #GdaSqlTable structure, using @parent as its parent part.
+ *
+ * Returns: a new #GdaSqlTable structure.
*/
GdaSqlTable *
gda_sql_table_new (GdaSqlAnyPart *parent)
@@ -256,6 +340,12 @@
return table;
}
+/**
+ * gda_sql_table_free
+ * @table: a #GdaSqlTable structure to be freed
+ *
+ * Frees a #GdaSqlTable structure and its members.
+ */
void
gda_sql_table_free (GdaSqlTable *table)
{
@@ -266,6 +356,14 @@
g_free (table);
}
+/**
+ * gda_sql_table_copy
+ * @table: a #GdaSqlTable structure to be copied
+ *
+ * Creates a new #GdaSqlTable structure initated with the values stored in @table.
+ *
+ * Returns: a new #GdaSqlTable structure.
+ */
GdaSqlTable *
gda_sql_table_copy (GdaSqlTable *table)
{
@@ -280,6 +378,15 @@
return copy;
}
+/**
+ * gda_sql_table_serialize
+ * @field: a #GdaSqlTable structure
+ *
+ * Creates a new string representing a table. You need to free the returned string
+ * using g_free();
+ *
+ * Returns: a new string with the name of the field or "null" in case @table is invalid.
+ */
gchar *
gda_sql_table_serialize (GdaSqlTable *table)
{
@@ -289,21 +396,32 @@
return _json_quote_string (table->table_name);
}
+/**
+ * gda_sql_table_take_name
+ * @field: a #GdaSqlTable structure
+ * @value: a #GValue holding a string to take from
+ *
+ * Sets the table's name using the string holded by @value. When call, @value is freed using
+ * #gda_value_free().
+ *
+ */
void
gda_sql_table_take_name (GdaSqlTable *table, GValue *value)
{
if (value) {
table->table_name = g_value_dup_string (value);
- g_value_reset (value);
- g_free (value);
+ gda_value_free (value);
}
}
-
-/*
- * A function with any number of arguments
+/**
+ * gda_sql_function_new
+ * @parent: a #GdaSqlExpr structure
+ *
+ * Creates a new #GdaSqlFunction structure initated.
+ *
+ * Returns: a new #GdaSqlFunction structure.
*/
-
GdaSqlFunction *
gda_sql_function_new (GdaSqlAnyPart *parent)
{
@@ -314,6 +432,12 @@
return function;
}
+/**
+ * gda_sql_function_free
+ * @function: a #GdaSqlFunction structure to be freed
+ *
+ * Frees a #GdaSqlFunction structure and its members.
+ */
void
gda_sql_function_free (GdaSqlFunction *function)
{
@@ -328,6 +452,14 @@
g_free (function);
}
+/**
+ * gda_sql_function_copy
+ * @function: a #GdaSqlFunction structure to be copied
+ *
+ * Creates a new #GdaSqlFunction structure initated with the values stored in @function.
+ *
+ * Returns: a new #GdaSqlFunction structure.
+ */
GdaSqlFunction *
gda_sql_function_copy (GdaSqlFunction *function)
{
@@ -353,6 +485,15 @@
return copy;
}
+/**
+ * gda_sql_function_serialize
+ * @function: a #GdaSqlFunction structure
+ *
+ * Creates a new string representing a function. You need to free the returned string
+ * using g_free();
+ *
+ * Returns: a new string with the description of the function or "null" in case @function is invalid.
+ */
gchar *
gda_sql_function_serialize (GdaSqlFunction *function)
{
@@ -391,16 +532,33 @@
}
}
+/**
+ * gda_sql_function_take_name
+ * @function: a #GdaSqlFunction structure
+ * @value: a #GValue holding a string to take from
+ *
+ * Sets the function's name using the string holded by @value. When call, @value is freed using
+ * #gda_value_free().
+ *
+ */
void
gda_sql_function_take_name (GdaSqlFunction *function, GValue *value)
{
if (value) {
function->function_name = g_value_dup_string (value);
- g_value_reset (value);
- g_free (value);
+ gda_value_free (value);
}
}
+/**
+ * gda_sql_function_take_name
+ * @function: a #GdaSqlFunction structure
+ * @args: a #GSList to take from
+ *
+ * Sets the function's arguments to point to @args, then sets the
+ * list's data elements' parent to @function.
+ *
+ */
void gda_sql_function_take_args_list (GdaSqlFunction *function, GSList *args)
{
GSList *list;
@@ -410,8 +568,13 @@
gda_sql_any_part_set_parent (list->data, function);
}
-/*
- * An operation
+/**
+ * gda_sql_operation_new
+ * @parent: a #GdaSqlExpr structure
+ *
+ * Creates a new #GdaSqlOperation structure and sets its parent to @parent.
+ *
+ * Returns: a new #GdaSqlOperation structure.
*/
GdaSqlOperation *
gda_sql_operation_new (GdaSqlAnyPart *parent)
@@ -423,6 +586,12 @@
return operation;
}
+/**
+ * gda_sql_operation_free
+ * @operation: a #GdaSqlOperation structure to be freed
+ *
+ * Frees a #GdaSqlOperation structure and its members.
+ */
void
gda_sql_operation_free (GdaSqlOperation *operation)
{
@@ -435,6 +604,14 @@
g_free (operation);
}
+/**
+ * gda_sql_operation_copy
+ * @operation: a #GdaSqlOperation structure to be copied
+ *
+ * Creates a new #GdaSqlOperation structure initated with the values stored in @operation.
+ *
+ * Returns: a new #GdaSqlOperation structure.
+ */
GdaSqlOperation *
gda_sql_operation_copy (GdaSqlOperation *operation)
{
@@ -456,6 +633,15 @@
return copy;
}
+/**
+ * gda_sql_operation_serialize
+ * @operation: a #GdaSqlOperation structure
+ *
+ * Creates a new string representing an operator. You need to free the returned string
+ * using g_free();
+ *
+ * Returns: a new string with the description of the operator or "null" in case @operation is invalid.
+ */
gchar *
gda_sql_operation_serialize (GdaSqlOperation *operation)
{
@@ -492,6 +678,15 @@
}
}
+/**
+ * gda_sql_operation_operator_to_string
+ * @op: a #GdaSqlOperation structure
+ *
+ * Returns a constant string representing a operator name. You don't need to free
+ * the returned string.
+ *
+ * Returns: a string with the operator's name or NULL in case @op is invalid.
+ */
const gchar *
gda_sql_operation_operator_to_string (GdaSqlOperator op)
{
@@ -562,6 +757,14 @@
}
}
+/**
+ * gda_sql_operator_from_string
+ * @op: a #GdaSqlOperation structure
+ *
+ * Returns #GdaSqlOperator that correspond with the string @op.
+ *
+ * Returns: #GdaSqlOperator
+ */
GdaSqlOperator
gda_sql_operation_operator_from_string (const gchar *op)
{
@@ -631,8 +834,13 @@
return 0;
}
-/*
- * A CASE expression
+/**
+ * gda_sql_case_new
+ * @parent: a #GdaSqlExpr structure
+ *
+ * Creates a new #GdaSqlCase structure and sets its parent to @parent.
+ *
+ * Returns: a new #GdaSqlCase structure.
*/
GdaSqlCase *
gda_sql_case_new (GdaSqlAnyPart *parent)
@@ -644,6 +852,12 @@
return sc;
}
+/**
+ * gda_sql_case_free
+ * @sc: a #GdaSqlCase structure to be freed
+ *
+ * Frees a #GdaSqlCase structure and its members.
+ */
void
gda_sql_case_free (GdaSqlCase *sc)
{
@@ -662,6 +876,14 @@
g_free (sc);
}
+/**
+ * gda_sql_case_copy
+ * @sc: a #GdaSqlCase structure to be copied
+ *
+ * Creates a new #GdaSqlCase structure initated with the values stored in @sc.
+ *
+ * Returns: a new #GdaSqlCase structure.
+ */
GdaSqlCase *
gda_sql_case_copy (GdaSqlCase *sc)
{
@@ -693,6 +915,15 @@
return copy;
}
+/**
+ * gda_sql_case_serialize
+ * @sc: a #GdaSqlCase structure
+ *
+ * Creates a new string representing a CASE clausure. You need to free the returned string
+ * using g_free();
+ *
+ * Returns: a new string with the description of the CASE clausure or "null" in case @sc is invalid.
+ */
gchar *
gda_sql_case_serialize (GdaSqlCase *sc)
{
@@ -741,8 +972,14 @@
}
}
-/*
- * Any expression in a SELECT ... before the FROM
+/**
+ * gda_sql_select_field_new
+ * @parent: a #GdaSqlStatementSelect structure
+ *
+ * Creates a new #GdaSqlSelectField structure and sets its parent to @parent. A
+ * #GdaSqlSelectField is any expression in SELECT statements before the FROM clausure.
+ *
+ * Returns: a new #GdaSqlSelectField structure.
*/
GdaSqlSelectField *
gda_sql_select_field_new (GdaSqlAnyPart *parent)
@@ -754,6 +991,12 @@
return field;
}
+/**
+ * gda_sql_select_field_free
+ * @field: a #GdaSqlSelectField structure to be freed
+ *
+ * Frees a #GdaSqlSelectField structure and its members.
+ */
void
gda_sql_select_field_free (GdaSqlSelectField *field)
{
@@ -768,6 +1011,14 @@
g_free (field);
}
+/**
+ * gda_sql_select_field_copy
+ * @field: a #GdaSqlSelectField structure to be copied
+ *
+ * Creates a new #GdaSqlSelectField structure initated with the values stored in @field.
+ *
+ * Returns: a new #GdaSqlSelectField structure.
+ */
GdaSqlSelectField *
gda_sql_select_field_copy (GdaSqlSelectField *field)
{
@@ -792,6 +1043,15 @@
return copy;
}
+/**
+ * gda_sql_select_field_serialize
+ * @field: a #GdaSqlSelectField structure
+ *
+ * Creates a new string representing an expresion used as field in a SELECT statement
+ * before the FROM clausure.
+ *
+ * Returns: a new string with the description of the expression or "null" in case @field is invalid.
+ */
gchar *
gda_sql_select_field_serialize (GdaSqlSelectField *field)
{
@@ -834,6 +1094,14 @@
}
}
+/**
+ * gda_sql_select_field_take_expr
+ * @field: a #GdaSqlSelectField structure
+ * @expr: a #GdaSqlExpr to take from
+ *
+ * Sets the expression field in the #GdaSqlSelectField structure to point to @expr
+ * and modify it to sets its parent to @field.
+ */
void
gda_sql_select_field_take_expr (GdaSqlSelectField *field, GdaSqlExpr *expr)
{
@@ -844,6 +1112,15 @@
_split_identifier_string (g_value_dup_string (expr->value), &(field->table_name), &(field->field_name));
}
+/**
+ * gda_sql_select_field_take_star_value
+ * @field: a #GdaSqlSelectField structure
+ * @value: a #GValue to take from
+ *
+ * Sets the expression field's value in the #GdaSqlSelectField structure to point to @value;
+ * after this @field is the owner of @value.
+ *
+ */
void
gda_sql_select_field_take_star_value (GdaSqlSelectField *field, GValue *value)
{
@@ -853,18 +1130,32 @@
}
}
+/**
+ * gda_sql_select_field_take_alias
+ * @field: a #GdaSqlSelectField structure
+ * @alias: a #GValue to take from
+ *
+ * Sets the 'as' field's string in the #GdaSqlSelectField structure. @alias is freed
+ * after call this function.
+ *
+ */
void
gda_sql_select_field_take_alias (GdaSqlSelectField *field, GValue *alias)
{
if (alias) {
field->as = g_value_dup_string (alias);
- g_value_reset (alias);
- g_free (alias);
+ gda_value_free (alias);
}
}
-/*
- * Any TARGET ... in a SELECT statement
+/**
+ * gda_sql_select_target_new
+ * @parent: a #GdaSqlSelectFrom
+ *
+ * Creates a new #GdaSqlSelectTarget structure and sets its parent to @parent. A
+ * #GdaSqlSelectTarget is the table in a SELECT statement.
+ *
+ * Returns: a new #GdaSqlSelectTarget structure.
*/
GdaSqlSelectTarget *
gda_sql_select_target_new (GdaSqlAnyPart *parent)
@@ -876,6 +1167,12 @@
return target;
}
+/**
+ * gda_sql_select_target_free
+ * @target: a #GdaSqlSelectTarget structure to be freed
+ *
+ * Frees a #GdaSqlSelectTarget structure and its members.
+ */
void
gda_sql_select_target_free (GdaSqlSelectTarget *target)
{
@@ -889,6 +1186,14 @@
g_free (target);
}
+/**
+ * gda_sql_select_target_copy
+ * @target: a #GdaSqlSelectTarget structure to be copied
+ *
+ * Creates a new #GdaSqlSelectTarget structure initated with the values stored in @target.
+ *
+ * Returns: a new #GdaSqlSelectTarget structure.
+ */
GdaSqlSelectTarget *
gda_sql_select_target_copy (GdaSqlSelectTarget *target)
{
@@ -910,6 +1215,15 @@
return copy;
}
+/**
+ * gda_sql_select_target_serialize
+ * @target: a #GdaSqlSelectTarget structure
+ *
+ * Creates a new string representing a target used in a SELECT statement
+ * after the FROM clausure.
+ *
+ * Returns: a new string with the description of the expression or "null" in case @field is invalid.
+ */
gchar *
gda_sql_select_target_serialize (GdaSqlSelectTarget *target)
{
@@ -946,6 +1260,15 @@
}
}
+/**
+ * gda_sql_select_target_take_table_name
+ * @target: a #GdaSqlSelectTarget structure
+ * @value: a #GValue to take from
+ *
+ * Sets the target's name using the string stored in @value and the expression
+ * to set its value to point to value; after call this function the target owns
+ * @value, then you must not free it.
+ */
void
gda_sql_select_target_take_table_name (GdaSqlSelectTarget *target, GValue *value)
{
@@ -956,6 +1279,14 @@
}
}
+/**
+ * gda_sql_select_target_take_table_name
+ * @target: a #GdaSqlSelectTarget structure
+ * @stmt: a #GValue to take from
+ *
+ * Sets the target to be a SELECT subquery setting target's expression to use
+ * @stmt; after call this function the target owns @stmt, then you must not free it.
+ */
void
gda_sql_select_target_take_select (GdaSqlSelectTarget *target, GdaSqlStatement *stmt)
{
@@ -965,19 +1296,35 @@
}
}
+/**
+ * gda_sql_select_target_take_table_alias
+ * @target: a #GdaSqlSelectTarget structure
+ * @alias: a #GValue holding the alias string to take from
+ *
+ * Sets the target alias (AS) to the string holded by @alias; after call
+ * this function @alias is freed.
+ */
void
gda_sql_select_target_take_alias (GdaSqlSelectTarget *target, GValue *alias)
{
if (alias) {
target->as = g_value_dup_string (alias);
- g_value_reset (alias);
- g_free (alias);
+ gda_value_free (alias);
}
}
/*
* Any JOIN ... in a SELECT statement
*/
+
+/**
+ * gda_sql_select_join_new
+ * @parent: a #GdaSqlSelectFrom
+ *
+ * Creates a new #GdaSqlSelectJoin structure and sets its parent to @parent.
+ *
+ * Returns: a new #GdaSqlSelectJoin structure
+ */
GdaSqlSelectJoin *
gda_sql_select_join_new (GdaSqlAnyPart *parent)
{
@@ -988,6 +1335,12 @@
return join;
}
+/**
+ * gda_sql_select_join_free
+ * @join: a #GdaSqlSelectJoin structure to be freed
+ *
+ * Frees a #GdaSqlSelectJoin structure and its members.
+ */
void
gda_sql_select_join_free (GdaSqlSelectJoin *join)
{
@@ -1000,6 +1353,14 @@
g_free (join);
}
+/**
+ * gda_sql_select_join_copy
+ * @join: a #GdaSqlSelectJoin structure to be copied
+ *
+ * Creates a new #GdaSqlSelectJoin structure initated with the values stored in @join.
+ *
+ * Returns: a new #GdaSqlSelectJoin structure.
+ */
GdaSqlSelectJoin *
gda_sql_select_join_copy (GdaSqlSelectJoin *join)
{
@@ -1025,6 +1386,14 @@
return copy;
}
+/**
+ * gda_sql_select_join_type_to_string
+ * @type: a #GdaSqlSelectJoinType structure to be copied
+ *
+ * Creates a new string representing the join type.
+ *
+ * Returns: a string representing the Join type.
+ */
const gchar *
gda_sql_select_join_type_to_string (GdaSqlSelectJoinType type)
{
@@ -1047,6 +1416,14 @@
}
}
+/**
+ * gda_sql_select_join_serialize
+ * @join: a #GdaSqlSelectJoin structure
+ *
+ * Creates a new string description of the join used in a SELECT statement.
+ *
+ * Returns: a new string with the description of the join or "null" in case @join is invalid.
+ */
gchar *
gda_sql_select_join_serialize (GdaSqlSelectJoin *join)
{
@@ -1099,6 +1476,15 @@
/*
* Any FROM ... in a SELECT statement
*/
+
+/**
+ * gda_sql_select_from_new
+ * @parent: a #GdaSqlStatementSelect
+ *
+ * Creates a new #GdaSqlSelectFrom structure and sets its parent to @parent.
+ *
+ * Returns: a new #GdaSqlSelectFrom structure
+ */
GdaSqlSelectFrom *
gda_sql_select_from_new (GdaSqlAnyPart *parent)
{
@@ -1109,6 +1495,12 @@
return from;
}
+/**
+ * gda_sql_select_from_free
+ * @from: a #GdaSqlSelectFrom structure to be freed
+ *
+ * Frees a #GdaSqlSelectFrom structure and its members.
+ */
void
gda_sql_select_from_free (GdaSqlSelectFrom *from)
{
@@ -1126,6 +1518,14 @@
g_free (from);
}
+/**
+ * gda_sql_select_from_copy
+ * @from: a #GdaSqlSelectFrom structure to be copied
+ *
+ * Creates a new #GdaSqlSelectFrom structure initated with the values stored in @from.
+ *
+ * Returns: a new #GdaSqlSelectFrom structure.
+ */
GdaSqlSelectFrom *
gda_sql_select_from_copy (GdaSqlSelectFrom *from)
{
@@ -1152,6 +1552,14 @@
return copy;
}
+/**
+ * gda_sql_select_from_serialize
+ * @from: a #GdaSqlSelectFrom structure
+ *
+ * Creates a new string description of the FROM clausure used in a SELECT statement.
+ *
+ * Returns: a new string with the description of the FROM or "null" in case @from is invalid.
+ */
gchar *
gda_sql_select_from_serialize (GdaSqlSelectFrom *from)
{
@@ -1199,6 +1607,14 @@
}
}
+/**
+ * gda_sql_select_from_take_new_target
+ * @from: a #GdaSqlSelectFrom structure
+ * @target: a #GdaSqlSelectTarget to take from
+ *
+ * Append @target to the targets in the FROM clausure and set @target's parent to
+ * @from; after call this function @from owns @target then you must not free it.
+ */
void
gda_sql_select_from_take_new_target (GdaSqlSelectFrom *from, GdaSqlSelectTarget *target)
{
@@ -1206,6 +1622,14 @@
gda_sql_any_part_set_parent (target, from);
}
+/**
+ * gda_sql_select_from_take_new_join
+ * @from: a #GdaSqlSelectFrom structure
+ * @join: a #GdaSqlSelectJoin to take from
+ *
+ * Append @join to the joins in the FROM clausure and set @join's parent to
+ * @from; after call this function @from owns @join then you must not free it.
+ */
void
gda_sql_select_from_take_new_join (GdaSqlSelectFrom *from, GdaSqlSelectJoin *join)
{
@@ -1216,6 +1640,15 @@
/*
* Any expression in a SELECT ... after the ORDER BY
*/
+
+/**
+ * gda_sql_select_order_new
+ * @parent: a #GdaSqlStatementSelect
+ *
+ * Creates a new #GdaSqlSelectOrder structure and sets its parent to @parent.
+ *
+ * Returns: a new #GdaSqlSelectOrder structure
+ */
GdaSqlSelectOrder *
gda_sql_select_order_new (GdaSqlAnyPart *parent)
{
@@ -1226,6 +1659,12 @@
return order;
}
+/**
+ * gda_sql_select_order_free
+ * @order: a #GdaSqlSelectOrder structure to be freed
+ *
+ * Frees a #GdaSqlSelectOrder structure and its members.
+ */
void
gda_sql_select_order_free (GdaSqlSelectOrder *order)
{
@@ -1237,6 +1676,14 @@
g_free (order);
}
+/**
+ * gda_sql_select_order_copy
+ * @order: a #GdaSqlSelectOrder structure to be copied
+ *
+ * Creates a new #GdaSqlSelectOrder structure initated with the values stored in @order.
+ *
+ * Returns: a new #GdaSqlSelectOrder structure.
+ */
GdaSqlSelectOrder *
gda_sql_select_order_copy (GdaSqlSelectOrder *order)
{
@@ -1255,6 +1702,14 @@
return copy;
}
+/**
+ * gda_sql_select_order_serialize
+ * @order: a #GdaSqlSelectOrder structure
+ *
+ * Creates a new string description of the ORDER BY clausure used in a SELECT statement.
+ *
+ * Returns: a new string with the description of the ORDER BY or "null" in case @order is invalid.
+ */
gchar *
gda_sql_select_order_serialize (GdaSqlSelectOrder *order)
{
Modified: trunk/libgda/sql-parser/gda-statement-struct-util.c
==============================================================================
--- trunk/libgda/sql-parser/gda-statement-struct-util.c (original)
+++ trunk/libgda/sql-parser/gda-statement-struct-util.c Tue Apr 15 09:26:32 2008
@@ -83,9 +83,16 @@
total = strlen (str);
- g_assert (str[total-1] == delim);
- g_memmove (str, str+1, total-2);
- total -=2;
+ if (str[total-1] == delim) {
+ /* string is correclty terminated by a double quote */
+ g_memmove (str, str+1, total-2);
+ total -=2;
+ }
+ else {
+ /* string is _not_ correclty terminated by a double quote */
+ g_memmove (str, str+1, total-1);
+ total -=1;
+ }
str[total] = 0;
ptr = (gchar *) str;
@@ -265,6 +272,44 @@
return TRUE;
}
+/**
+ * identifier_needs_quotes
+ */
+gboolean
+_identifier_needs_quotes (const gchar *str)
+{
+ const gchar *ptr;
+
+ g_return_val_if_fail (str, FALSE);
+ for (ptr = str; *ptr; ptr++) {
+ if (*ptr != g_ascii_tolower (*ptr))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * Prepares @str to be compared:
+ * - if surrounded by double quotes, then just remove the quotes
+ * - otherwise convert to lower case
+ *
+ * WARNING: @str must NOT be a composed identifier (<part1>."<part2>" for example)
+ *
+ * Returns: @str
+ */
+gchar *
+_identifier_unquote (gchar *str)
+{
+ if (*str == '"')
+ return _remove_quotes (str);
+ else {
+ gchar *ptr;
+ for (ptr = str; *ptr; ptr++)
+ *ptr = g_ascii_tolower (*ptr);
+ return str;
+ }
+}
+
/*
* Reuses @str and fills in @remain and @last
*
@@ -281,7 +326,7 @@
* if @str has the <part1>.<part2> form, then @last will contain <part2> and @remain will contain <part1>
* if @str has the <part1> form, then @last will contain <part1> and @remain will contain NULL
*
- * Returns FALSE:
+ * Returns FALSE (in any case @str is also freed)
* if @str is NULL:
* if @str is "":
* if @str is malformed:
@@ -305,10 +350,12 @@
}
len = strlen (str) - 1;
- if (((str[len] == '"') && (str[len-1] == '.')) ||
- (str[len] == '.')) {
- g_free (str);
- return FALSE;
+ if (len > 1) {
+ if (((str[len] == '"') && (str[len-1] == '.')) ||
+ (str[len] == '.')) {
+ g_free (str);
+ return FALSE;
+ }
}
if (((str[0] == '"') && (str[1] == '.')) ||
Modified: trunk/libgda/sql-parser/gda-statement-struct-util.h
==============================================================================
--- trunk/libgda/sql-parser/gda-statement-struct-util.h (original)
+++ trunk/libgda/sql-parser/gda-statement-struct-util.h Tue Apr 15 09:26:32 2008
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 Vivien Malerba
+ * Copyright (C) 2007 - 2008 Vivien Malerba
*
* This Library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License as
@@ -28,8 +28,11 @@
gchar *_add_quotes (const gchar *str);
gchar *_json_quote_string (const gchar *str);
+
gboolean _string_is_identifier (const gchar *str);
+gboolean _identifier_needs_quotes (const gchar *str);
gboolean _split_identifier_string (gchar *str, gchar **remain, gchar **last);
+gchar *_identifier_unquote (gchar *str);
/* to be removed, only here for debug */
gchar *gda_sql_value_stringify (const GValue *value);
Modified: trunk/providers/mysql/gda-mysql-blob-op.c
==============================================================================
--- trunk/providers/mysql/gda-mysql-blob-op.c (original)
+++ trunk/providers/mysql/gda-mysql-blob-op.c Tue Apr 15 09:26:32 2008
@@ -165,7 +165,7 @@
bin = (GdaBinary *) blob;
if (bin->data)
g_free (bin->data);
- bin->data = g_new0 (gchar, size);
+ bin->data = g_new0 (guchar, size);
bin->binary_length = 0;
/* fetch blob data using C API into bin->data, and set bin->binary_length */
Modified: trunk/providers/postgres/gda-postgres-meta.c
==============================================================================
--- trunk/providers/postgres/gda-postgres-meta.c (original)
+++ trunk/providers/postgres/gda-postgres-meta.c Tue Apr 15 09:26:32 2008
@@ -129,10 +129,10 @@
"SELECT constraint_catalog, constraint_schema, constraint_name, table_catalog, table_schema, table_name, constraint_type, NULL, CASE WHEN is_deferrable = 'YES' THEN TRUE ELSE FALSE END, CASE WHEN initially_deferred = 'YES' THEN TRUE ELSE FALSE END FROM information_schema.table_constraints WHERE table_catalog = ##cat::string AND table_schema = ##schema::string AND table_name = ##name::string AND constraint_name = ##name2::string",
/* I_STMT_REF_CONSTRAINTS */
- "SELECT current_database(), nt.nspname, t.relname, c.conname, current_database(), nref.nspname, ref.relname, pkc.conname, CASE c.confmatchtype WHEN 'f'::\"char\" THEN 'FULL'::text WHEN 'p'::\"char\" THEN 'PARTIAL'::text WHEN 'u'::\"char\" THEN 'NONE'::text ELSE NULL::text END AS match_option, CASE c.confupdtype WHEN 'c'::\"char\" THEN 'CASCADE'::text WHEN 'n'::\"char\" THEN 'SET NULL'::text WHEN 'd'::\"char\" THEN 'SET DEFAULT'::text WHEN 'r'::\"char\" THEN 'RESTRICT'::text WHEN 'a'::\"char\" THEN 'NO ACTION'::text ELSE NULL::text END AS update_rule, CASE c.confdeltype WHEN 'c'::\"char\" THEN 'CASCADE'::text WHEN 'n'::\"char\" THEN 'SET NULL'::text WHEN 'd'::\"char\" THEN 'SET DEFAULT'::text WHEN 'r'::\"char\" THEN 'RESTRICT'::text WHEN 'a'::\"char\" THEN 'NO ACTION'::text ELSE NULL::text END AS delete_rule FROM pg_constraint c INNER JOIN pg_class t ON (c.conrelid=t.oid) INNER JOIN pg_namespace nt ON (nt.oid=t.relnamespace) INNER JOIN pg_class ref ON (c.confrelid=ref.oid) I
NNER JOIN pg_namespace nref ON (nref.oid=ref.relnamespace) INNER JOIN pg_constraint pkc ON (c.confrelid = pkc.conrelid AND information_schema._pg_keysequal(c.confkey, pkc.conkey)) WHERE c.contype = 'f' AND current_database() = ##cat::string AND nt.nspname = ##schema::string AND t.relname = ##name::string AND c.conname = ##name2::string",
+ "SELECT current_database(), nt.nspname, t.relname, c.conname, current_database(), nref.nspname, ref.relname, pkc.conname, CASE c.confmatchtype WHEN 'f'::\"char\" THEN 'FULL'::text WHEN 'p'::\"char\" THEN 'PARTIAL'::text WHEN 'u'::\"char\" THEN 'NONE'::text ELSE NULL::text END AS match_option, CASE c.confupdtype WHEN 'c'::\"char\" THEN 'CASCADE'::text WHEN 'n'::\"char\" THEN 'SET NULL'::text WHEN 'd'::\"char\" THEN 'SET DEFAULT'::text WHEN 'r'::\"char\" THEN 'RESTRICT'::text WHEN 'a'::\"char\" THEN 'NO ACTION'::text ELSE NULL::text END AS update_rule, CASE c.confdeltype WHEN 'c'::\"char\" THEN 'CASCADE'::text WHEN 'n'::\"char\" THEN 'SET NULL'::text WHEN 'd'::\"char\" THEN 'SET DEFAULT'::text WHEN 'r'::\"char\" THEN 'RESTRICT'::text WHEN 'a'::\"char\" THEN 'NO ACTION'::text ELSE NULL::text END AS delete_rule FROM pg_constraint c INNER JOIN pg_class t ON (c.conrelid=t.oid) INNER JOIN pg_namespace nt ON (nt.oid=t.relnamespace) INNER JOIN pg_class ref ON (c.confrelid=ref.oid) I
NNER JOIN pg_namespace nref ON (nref.oid=ref.relnamespace) INNER JOIN pg_constraint pkc ON (c.confrelid = pkc.conrelid AND information_schema._pg_keysequal(c.confkey, pkc.conkey) AND pkc.contype='p') WHERE c.contype = 'f' AND current_database() = ##cat::string AND nt.nspname = ##schema::string AND t.relname = ##name::string AND c.conname = ##name2::string",
/* I_STMT_REF_CONSTRAINTS_ALL */
- "SELECT current_database(), nt.nspname, t.relname, c.conname, current_database(), nref.nspname, ref.relname, pkc.conname, CASE c.confmatchtype WHEN 'f'::\"char\" THEN 'FULL'::text WHEN 'p'::\"char\" THEN 'PARTIAL'::text WHEN 'u'::\"char\" THEN 'NONE'::text ELSE NULL::text END AS match_option, CASE c.confupdtype WHEN 'c'::\"char\" THEN 'CASCADE'::text WHEN 'n'::\"char\" THEN 'SET NULL'::text WHEN 'd'::\"char\" THEN 'SET DEFAULT'::text WHEN 'r'::\"char\" THEN 'RESTRICT'::text WHEN 'a'::\"char\" THEN 'NO ACTION'::text ELSE NULL::text END AS update_rule, CASE c.confdeltype WHEN 'c'::\"char\" THEN 'CASCADE'::text WHEN 'n'::\"char\" THEN 'SET NULL'::text WHEN 'd'::\"char\" THEN 'SET DEFAULT'::text WHEN 'r'::\"char\" THEN 'RESTRICT'::text WHEN 'a'::\"char\" THEN 'NO ACTION'::text ELSE NULL::text END AS delete_rule FROM pg_constraint c INNER JOIN pg_class t ON (c.conrelid=t.oid) INNER JOIN pg_namespace nt ON (nt.oid=t.relnamespace) INNER JOIN pg_class ref ON (c.confrelid=ref.oid) I
NNER JOIN pg_namespace nref ON (nref.oid=ref.relnamespace) INNER JOIN pg_constraint pkc ON (c.confrelid = pkc.conrelid AND information_schema._pg_keysequal(c.confkey, pkc.conkey)) WHERE c.contype = 'f'",
+ "SELECT current_database(), nt.nspname, t.relname, c.conname, current_database(), nref.nspname, ref.relname, pkc.conname, CASE c.confmatchtype WHEN 'f'::\"char\" THEN 'FULL'::text WHEN 'p'::\"char\" THEN 'PARTIAL'::text WHEN 'u'::\"char\" THEN 'NONE'::text ELSE NULL::text END AS match_option, CASE c.confupdtype WHEN 'c'::\"char\" THEN 'CASCADE'::text WHEN 'n'::\"char\" THEN 'SET NULL'::text WHEN 'd'::\"char\" THEN 'SET DEFAULT'::text WHEN 'r'::\"char\" THEN 'RESTRICT'::text WHEN 'a'::\"char\" THEN 'NO ACTION'::text ELSE NULL::text END AS update_rule, CASE c.confdeltype WHEN 'c'::\"char\" THEN 'CASCADE'::text WHEN 'n'::\"char\" THEN 'SET NULL'::text WHEN 'd'::\"char\" THEN 'SET DEFAULT'::text WHEN 'r'::\"char\" THEN 'RESTRICT'::text WHEN 'a'::\"char\" THEN 'NO ACTION'::text ELSE NULL::text END AS delete_rule FROM pg_constraint c INNER JOIN pg_class t ON (c.conrelid=t.oid) INNER JOIN pg_namespace nt ON (nt.oid=t.relnamespace) INNER JOIN pg_class ref ON (c.confrelid=ref.oid) I
NNER JOIN pg_namespace nref ON (nref.oid=ref.relnamespace) INNER JOIN pg_constraint pkc ON (c.confrelid = pkc.conrelid AND information_schema._pg_keysequal(c.confkey, pkc.conkey) AND pkc.contype='p') WHERE c.contype = 'f'",
/* I_STMT_KEY_COLUMN_USAGE */
"SELECT table_catalog, table_schema, table_name, constraint_name, column_name, ordinal_position FROM information_schema.key_column_usage WHERE table_catalog = ##cat::string AND table_schema = ##schema::string AND table_name = ##name::string AND constraint_name = ##name2::string",
Modified: trunk/providers/skel-implementation/capi/gda-capi-blob-op.c
==============================================================================
--- trunk/providers/skel-implementation/capi/gda-capi-blob-op.c (original)
+++ trunk/providers/skel-implementation/capi/gda-capi-blob-op.c Tue Apr 15 09:26:32 2008
@@ -159,7 +159,7 @@
bin = (GdaBinary *) blob;
if (bin->data)
g_free (bin->data);
- bin->data = g_new0 (gchar, size);
+ bin->data = g_new0 (guchar, size);
bin->binary_length = 0;
/* fetch blob data using C API into bin->data, and set bin->binary_length */
Modified: trunk/tools/command-exec.c
==============================================================================
--- trunk/tools/command-exec.c (original)
+++ trunk/tools/command-exec.c Tue Apr 15 09:26:32 2008
@@ -221,8 +221,6 @@
break;
case T_TEXTUAL:
case T_STRING:
- local_ptr++;
- local_nparsed -= 2;
default: {
gchar hold;
hold = local_ptr[local_nparsed];
Modified: trunk/tools/gda-sql.c
==============================================================================
--- trunk/tools/gda-sql.c (original)
+++ trunk/tools/gda-sql.c Tue Apr 15 09:26:32 2008
@@ -41,13 +41,12 @@
#include <pwd.h>
#endif
-/* options */
-gchar *pass = NULL;
-gchar *user = NULL;
+#ifdef HAVE_READLINE_READLINE_H
+#include <readline/readline.h>
+#endif
-gchar *dsn = NULL;
-gchar *direct = NULL;
-gchar *prov = NULL;
+/* options */
+gboolean ask_pass = FALSE;
gchar *single_command = NULL;
gchar *commandsfile = NULL;
@@ -57,13 +56,8 @@
gchar *outfile = NULL;
-
static GOptionEntry entries[] = {
- { "cnc", 'c', 0, G_OPTION_ARG_STRING, &direct, "Direct connection string", "connection string"},
- { "provider", 'p', 0, G_OPTION_ARG_STRING, &prov, "Provider name", "provider"},
- { "dsn", 's', 0, G_OPTION_ARG_STRING, &dsn, "Data source", "DSN"},
- { "user", 'U', 0, G_OPTION_ARG_STRING, &user, "Username", "username" },
- { "password", 'P', 0, G_OPTION_ARG_STRING, &pass, "Password", "password" },
+ { "no-password-ask", 'p', 0, G_OPTION_ARG_NONE, &ask_pass, "Don't ast for a password when it is empty", NULL },
{ "output-file", 'o', 0, G_OPTION_ARG_STRING, &outfile, "Output file", "output file"},
{ "command", 'C', 0, G_OPTION_ARG_STRING, &single_command, "Run only single command (SQL or internal) and exit", "command" },
@@ -121,15 +115,14 @@
GString *prompt = NULL;
static gchar *read_a_line (MainData *data);
-static char *completion_func (const char *text, int state);
+static char **completion_func (const char *text, int start, int end);
static void compute_prompt (MainData *data, GString *string, gboolean in_command);
static gboolean set_output_file (MainData *data, const gchar *file, GError **error);
static gboolean set_input_file (MainData *data, const gchar *file, GError **error);
static void output_data_model (MainData *data, GdaDataModel *model);
static void output_string (MainData *data, const gchar *str);
-static ConnectionSetting *open_connection (MainData *data, const gchar *cnc_name, const gchar *dsn,
- const gchar *provider, const gchar *direct,
- const gchar *user, const gchar *pass, GError **error);
+static ConnectionSetting *open_connection (MainData *data, const gchar *cnc_name, const gchar *cnc_string,
+ GError **error);
static GdaDataModel *list_all_dsn (MainData *data);
static GdaDataModel *list_all_providers (MainData *data);
@@ -149,7 +142,7 @@
GSList *list;
prompt = g_string_new ("");
- context = g_option_context_new (_("Gda SQL console"));
+ context = g_option_context_new (_("[DSN|connection string]..."));
g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
if (!g_option_context_parse (context, &argc, &argv, &error)) {
g_print ("Can't parse arguments: %s\n", error->message);
@@ -161,14 +154,7 @@
data = g_new0 (MainData, 1);
data->parameters = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
main_data = data;
-
- /* test for command line or env. variable connection string */
- if (!direct) {
- if (argc >= 2)
- direct = argv [1];
- else
- direct = getenv ("GDA_SQL_CNC");
- }
+ ask_pass = !ask_pass;
/* output file */
if (outfile) {
@@ -209,13 +195,6 @@
data->input_stream = stdin;
}
- /* check connection parameters coherence */
- if (direct && dsn) {
- g_fprintf (stderr, _("DSN and connection string are exclusive\n"));
- exit_status = EXIT_FAILURE;
- goto cleanup;
- }
-
/* welcome message */
if (!data->output_stream) {
g_print (_("Welcome to the GDA SQL console, version " PACKAGE_VERSION));
@@ -227,12 +206,43 @@
" or any query terminated by a semicolon\n\n"));
}
- if (direct || dsn) {
+ /* open connections if specified */
+ gint i;
+ for (i = 1; i < argc; i++) {
/* open connection */
ConnectionSetting *cs;
- cs = open_connection (data, NULL, dsn, prov, direct, user, pass, &error);
+ GdaDataSourceInfo *info = NULL;
+ gchar *str;
+
+ info = gda_config_get_dsn (argv[i]);
+ if (info)
+ str = g_strdup (info->name);
+ else
+ str = g_strdup_printf ("c%d", i-1);
+ if (!data->output_stream)
+ g_print (_("Opening connection '%s' for: %s\n"), str, argv[i]);
+ cs = open_connection (data, str, argv[i], &error);
+ g_free (str);
if (!cs) {
- g_print (_("Can't open connection: %s\n"), error && error->message ? error->message : _("No detail"));
+ g_print (_("Can't open connection %d: %s\n"), i,
+ error && error->message ? error->message : _("No detail"));
+ exit_status = EXIT_FAILURE;
+ goto cleanup;
+ }
+ }
+ if (getenv ("GDA_SQL_CNC")) {
+ ConnectionSetting *cs;
+ gchar *str;
+ const gchar *envstr = getenv ("GDA_SQL_CNC");
+ str = g_strdup_printf ("c%d", i-1);
+ if (!data->output_stream)
+ g_print (_("Opening connection '%s' for: %s (GDA_SQL_CNC environment variable)\n"),
+ str, envstr);
+ cs = open_connection (data, str, envstr, &error);
+ g_free (str);
+ if (!cs) {
+ g_print (_("Can't open connection defined by GDA_SQL_CNC: %s\n"),
+ error && error->message ? error->message : _("No detail"));
exit_status = EXIT_FAILURE;
goto cleanup;
}
@@ -828,15 +838,11 @@
* Open a connection
*/
static ConnectionSetting*
-open_connection (MainData *data, const gchar *cnc_name, const gchar *dsn,
- const gchar *provider, const gchar *direct,
- const gchar *user, const gchar *pass,
- GError **error)
+open_connection (MainData *data, const gchar *cnc_name, const gchar *cnc_string, GError **error)
{
GdaConnection *newcnc = NULL;
ConnectionSetting *cs = NULL;
static gint cncindex = 0;
- gchar *auth_string = NULL;
if (cnc_name && ! connection_name_is_valid (cnc_name)) {
g_set_error (error, 0, 0,
@@ -844,40 +850,75 @@
return NULL;
}
- if (user) {
- if (pass)
- auth_string = g_strdup_printf ("USERNAME=%s;PASSWORD=%s", user, pass);
- else
- auth_string = g_strdup_printf ("USERNAME=%s", user);
+ GdaDataSourceInfo *info;
+ gchar *user, *pass, *real_cnc, *real_provider, *real_auth_string = NULL;
+ gda_connection_string_split (cnc_string, &real_cnc, &real_provider, &user, &pass);
+ if (!real_cnc) {
+ g_free (user);
+ g_free (pass);
+ g_free (real_provider);
+ g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_DSN_NOT_FOUND_ERROR,
+ _("Malformed connection string '%s'"), cnc_string);
+ return NULL;
}
- if (dsn) {
- GdaDataSourceInfo *info = NULL;
- info = gda_config_get_dsn (dsn);
- if (!info) {
- if (!direct)
- g_set_error (error, 0, 0,
- _("DSN '%s' is not declared"), dsn);
+
+ if (ask_pass) {
+ if (user && !*user) {
+ gchar buf[80];
+ g_print (_("\tUsername for '%s': "), cnc_name);
+ if (scanf ("%80s", buf) == -1) {
+ g_free (real_cnc);
+ g_free (user);
+ g_free (pass);
+ g_free (real_provider);
+ g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_DSN_NOT_FOUND_ERROR,
+ _("No username for '%s'"), cnc_string);
+ return NULL;
+ }
+ g_free (user);
+ user = g_strdup (buf);
}
- else
- newcnc = gda_connection_open_from_dsn (info->name,
- auth_string ? auth_string : info->auth_string,
- 0, error);
- }
- if (!newcnc && direct) {
- /* test if @direct is not in fact a DSN, in which case use it as a DSN */
- GdaDataSourceInfo *info = NULL;
- info = gda_config_get_dsn (direct);
- if (info) {
- newcnc = gda_connection_open_from_dsn (info->name,
- auth_string ? auth_string : info->auth_string,
- 0, error);
- dsn = direct;
- direct = NULL;
+ if (pass && !*pass) {
+ gchar buf[80];
+ g_print (_("\tPassword for '%s': "), cnc_name);
+ if (scanf ("%80s", buf) == -1) {
+ g_free (real_cnc);
+ g_free (user);
+ g_free (pass);
+ g_free (real_provider);
+ g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_DSN_NOT_FOUND_ERROR,
+ _("No password for '%s'"), cnc_string);
+ return NULL;
+ }
+ g_free (pass);
+ pass = g_strdup (buf);
+ }
+ if (user || pass) {
+ gchar *s1;
+ s1 = gda_rfc1738_encode (user);
+ if (pass) {
+ gchar *s2;
+ s2 = gda_rfc1738_encode (pass);
+ real_auth_string = g_strdup_printf ("USERNAME=%s;PASSWORD=%s", s1, s2);
+ g_free (s2);
+ }
+ else
+ real_auth_string = g_strdup_printf ("USERNAME=%s", s1);
+ g_free (s1);
}
- else
- newcnc = gda_connection_open_from_string (provider, direct, auth_string, 0, error);
}
- g_free (auth_string);
+
+ info = gda_config_get_dsn (real_cnc);
+ if (info && !real_provider)
+ newcnc = gda_connection_open_from_dsn (cnc_string, real_auth_string, 0, error);
+ else
+ newcnc = gda_connection_open_from_string (NULL, cnc_string, real_auth_string, 0, error);
+
+ g_free (real_cnc);
+ g_free (user);
+ g_free (pass);
+ g_free (real_provider);
+ g_free (real_auth_string);
if (newcnc) {
cs = g_new0 (ConnectionSetting, 1);
@@ -896,12 +937,12 @@
GdaMetaStore *store;
gboolean update_store = FALSE;
- if (dsn) {
+ if (info) {
gchar *filename;
#define LIBGDA_USER_CONFIG_DIR G_DIR_SEPARATOR_S ".libgda"
filename = g_strdup_printf ("%s%sgda-sql-%s.db",
g_get_home_dir (), LIBGDA_USER_CONFIG_DIR G_DIR_SEPARATOR_S,
- dsn);
+ info->name);
if (! g_file_test (filename, G_FILE_TEST_EXISTS))
update_store = TRUE;
store = gda_meta_store_new_with_file (filename);
@@ -916,7 +957,7 @@
if (update_store) {
GError *lerror = NULL;
if (!data->output_stream) {
- g_print (_("Getting database schema information, "
+ g_print (_("\tGetting database schema information, "
"this may take some time... "));
fflush (stdout);
}
@@ -1654,7 +1695,7 @@
if (args[3])
pass = args[3];
}
- cs = open_connection (data, args[0], args[1], NULL, args[1], user, pass, error);
+ cs = open_connection (data, args[0], args[1], error);
if (cs) {
GdaInternalCommandResult *res;
@@ -2526,92 +2567,41 @@
return g_strsplit (str, " ", 3);
}
-static char *
-completion_func (const char *text, int state)
+
+
+static char **
+completion_func (const char *text, int start, int end)
{
- static GArray *compl = NULL;
+#ifdef HAVE_READLINE_READLINE_H
+ ConnectionSetting *cs = main_data->current;
+ char **array;
+ gchar **gda_compl;
+ gint i, nb_compl;
- if (state == 0) {
- ConnectionSetting *cs = main_data->current;
- /* clear any previous completion */
- if (compl) {
- /* don't free the contents of @array, it is freed by readline */
- g_array_free (compl, TRUE);
- compl = NULL;
- }
-
- /* compute list of possible completions. It's very simple at the moment */
- if (!(*text)) {
- /* no completion possible */
- }
- else if (cs) {
- gchar *copy;
-
- copy = g_strdup (text);
- g_strchomp (copy);
- if (*copy) {
- const char *start;
- gint nb_compl = 0;
- for (start = copy + (strlen (copy) - 1); start > copy; start--)
- if (g_ascii_isspace (*start)) {
- start ++;
- break;
- }
- GdaDataModel *model;
- GdaMetaStore *store;
- store = gda_connection_get_meta_store (cs->cnc);
- model = gda_meta_store_extract (store, "SELECT table_schema, table_name FROM "
- "_tables", NULL);
- if (model) {
- gint i, nrows;
- gint len = strlen (start);
-
- compl = g_array_new (TRUE, TRUE, sizeof (char *));
- nrows = gda_data_model_get_n_rows (model);
- for (i = 0; i < nrows; i++) {
- const gchar *tname;
- tname = g_value_get_string (gda_data_model_get_value_at (model, 1, i));
- if (!strncmp (tname, start, len)) {
- char *str;
- str = malloc (sizeof (char) * (strlen (tname) + 1));
- strcpy (str, tname);
- g_array_append_val (compl, str);
- nb_compl++;
- }
- }
- g_object_unref (model);
- }
+ if (!cs)
+ return NULL;
+ gda_compl = gda_completion_list_get (cs->cnc, rl_line_buffer, start, end);
+ if (!gda_compl)
+ return NULL;
- model = gda_meta_store_extract (store, "SELECT schema_name FROM "
- "_schemata", NULL);
- if (model) {
- gint i, nrows;
- gint len = strlen (start);
-
- compl = g_array_new (TRUE, TRUE, sizeof (char *));
- nrows = gda_data_model_get_n_rows (model);
- for (i = 0; i < nrows; i++) {
- const gchar *tname;
- tname = g_value_get_string (gda_data_model_get_value_at (model, 0, i));
- if (!strncmp (tname, start, len)) {
- char *str;
- str = malloc (sizeof (char) * (strlen (tname) + 1));
- strcpy (str, tname);
- g_array_append_val (compl, str);
- nb_compl++;
- }
- }
- g_object_unref (model);
- }
- }
- g_free (copy);
- }
+ for (nb_compl = 0; gda_compl[nb_compl]; nb_compl++);
- if (compl)
- return g_array_index (compl, char*, 0);
- else
- return NULL;
- }
- else
- return g_array_index (compl, char*, state) ;
+ array = malloc (sizeof (char*) * (nb_compl + 1));
+ for (i = 0; i < nb_compl; i++) {
+ char *str;
+ gchar *gstr;
+ gint l;
+
+ gstr = gda_compl[i];
+ l = strlen (gstr) + 1;
+ str = malloc (sizeof (char) * l);
+ memcpy (str, gstr, l);
+ array[i] = str;
+ }
+ array[i] = NULL;
+ g_strfreev (gda_compl);
+ return array;
+#else
+ return NULL;
+#endif
}
Modified: trunk/tools/tools-input.c
==============================================================================
--- trunk/tools/tools-input.c (original)
+++ trunk/tools/tools-input.c Tue Apr 15 09:26:32 2008
@@ -118,7 +118,8 @@
set_completion_func (CompletionFunc func)
{
#ifdef HAVE_READLINE_READLINE_H
- rl_completion_entry_function = func;
+ rl_attempted_completion_function = func;
+ rl_basic_word_break_characters = " \t\n\\'` $><=;|&{(";
#endif
}
Modified: trunk/tools/tools-input.h
==============================================================================
--- trunk/tools/tools-input.h (original)
+++ trunk/tools/tools-input.h Tue Apr 15 09:26:32 2008
@@ -25,7 +25,7 @@
#include <stdio.h>
#include <glib.h>
-typedef char *(*CompletionFunc) (const char *, int);
+typedef char **(*CompletionFunc) (const char *, int, int);
gchar *input_from_console (const gchar *prompt);
gchar *input_from_stream (FILE *stream);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]