libgda r3174 - in trunk: . doc/C po providers/firebird



Author: vivien
Date: Sat Jul  5 15:50:46 2008
New Revision: 3174
URL: http://svn.gnome.org/viewvc/libgda?rev=3174&view=rev

Log:
2008-07-05  Vivien Malerba <malerba gnome-db org>

	* doc/C: doc. updates
	* providers/firebird: added forgotten files
	* po/POTFILES.in: added missing files
	* NEWS: news for version


Added:
   trunk/providers/firebird/firebird_specs_create_table.xml.in
   trunk/providers/firebird/gda-firebird-ddl.c
   trunk/providers/firebird/gda-firebird-ddl.h
   trunk/providers/firebird/gda-firebird-meta.c
   trunk/providers/firebird/gda-firebird-meta.h
   trunk/providers/firebird/gda-firebird-parser.c
   trunk/providers/firebird/gda-firebird-parser.h
   trunk/providers/firebird/gda-firebird-pstmt.c
   trunk/providers/firebird/gda-firebird-pstmt.h
   trunk/providers/firebird/gda-firebird-util.c
   trunk/providers/firebird/gda-firebird-util.h
   trunk/providers/firebird/gda-firebird.h
   trunk/providers/firebird/gen_def.c
   trunk/providers/firebird/parser.y
Modified:
   trunk/ChangeLog
   trunk/NEWS
   trunk/doc/C/i_s_doc.xml
   trunk/doc/C/libgda-4.0-docs.sgml
   trunk/doc/C/limitations.xml
   trunk/po/POTFILES.in

Modified: trunk/NEWS
==============================================================================
--- trunk/NEWS	(original)
+++ trunk/NEWS	Sat Jul  5 15:50:46 2008
@@ -1,3 +1,40 @@
+libgda 3.99.3, 2008-07-05
+
+ This version includes:
+ - lots of bug fixed, memory leaks fixes and general performance improvements 
+   (Murray Cumming, Daniel Espinosa, Cygwin Ports maintainer, Phil Longstaff, 
+   Carlos Savoretti, Johannes Schmid, Yuriy Penkin, Vivien Malerba)
+ - MySQL support starting to work again (Carlos Savoretti)
+ - documentation improvements
+ - added function to compute INSERT, UPDATE and DELETE statements from a SELECT
+   statement, to be able to have writable data models after a SELECT execution
+ - API changes for easier understanding and usage (gda_init() for example)
+ - added the possibility to check the validity of a statement using the database's
+   associated meta data
+ - improvements to the convenience functions when creating or dropping a table (Daniel Espinosa)
+ - new data model comparator object
+ - make the SQL parser(s) correctly handle SQL identifiers enclosed in double quotes
+ - more checks
+ - new function to the xslt extension libgda-xslt (Pawel Cesar)
+ - new SQL code completion feature (incorporated into the gda-sql tool)
+ - gda-sql tool improvements (SQL completion, command line parsing)
+ - reworked the authentication mechanism as some database don't require a username/password
+ - allow the [<username>[:<password>] ]<DSN> format of string when opening a connection using
+   a predefined data source, or [<provider>://][<username>[:<password>] ]<connection string>
+   when opening a connection without a predefined data source
+ - now internally use SQLite 3.5.9
+ - use GIO instead of GnomeVFS if found
+ - preliminary MacOS X support, and better support for cross compilation
+ - better support for thread safe support
+ - new distributed transaction support
+ - added speficications to create a .MSI file as a Windows installer
+ - bug fixes: #524837, #525601, #525877, #526748, #527892, #527002, #534805, #536418,
+   #536971, #537558, #537117
+ - Translations:
+	- es (Jorge Gonzalez)
+	- pt (Duarte Loreto)
+	- oc (Yannig Marchegay)
+
 libgda 3.99.2, 2008-03-24
 
  This version:

Modified: trunk/doc/C/i_s_doc.xml
==============================================================================
--- trunk/doc/C/i_s_doc.xml	(original)
+++ trunk/doc/C/i_s_doc.xml	Sat Jul  5 15:50:46 2008
@@ -1,5 +1,5 @@
 <sect2>
-<!--File generated by the tools/information-schema-doc program from the
+  <!--File generated by the tools/information-schema-doc program from the
 libgda/information-schema.xml file,
 do not modify-->
   <title>Individual table description</title>
@@ -219,7 +219,7 @@
   <sect3 id="is:_key_column_usage">
     <title>_key_column_usage table</title>
     <para>List of primary key constraints and the name of the tables' columns involved</para>
-    <para>The following table describes the columns:<informaltable frame="all"><tgroup cols="5" colsep="1" rowsep="1" align="justify"><thead><row><entry>Column name</entry><entry>Type</entry><entry>Key</entry><entry>Can be NULL</entry><entry>description</entry></row></thead><tbody><row><entry>table_catalog</entry><entry>string</entry><entry>Yes</entry><entry>No</entry><entry></entry></row><row><entry>table_schema</entry><entry>string</entry><entry>Yes</entry><entry>No</entry><entry></entry></row><row><entry>table_name</entry><entry>string</entry><entry>Yes</entry><entry>No</entry><entry></entry></row><row><entry>constraint_name</entry><entry>string</entry><entry>Yes</entry><entry>No</entry><entry></entry></row><row><entry>column_name</entry><entry>string</entry><entry>Yes</entry><entry>No</entry><entry></entry></row><row><entry>ordinal_position</entry><entry>gint</entry><entry>Yes</entry><entry>No</entry><entry></entry></row></tbody></tgroup></informaltable></para>
+    <para>The following table describes the columns:<informaltable frame="all"><tgroup cols="5" colsep="1" rowsep="1" align="justify"><thead><row><entry>Column name</entry><entry>Type</entry><entry>Key</entry><entry>Can be NULL</entry><entry>description</entry></row></thead><tbody><row><entry>table_catalog</entry><entry>string</entry><entry>Yes</entry><entry>No</entry><entry></entry></row><row><entry>table_schema</entry><entry>string</entry><entry>Yes</entry><entry>No</entry><entry></entry></row><row><entry>table_name</entry><entry>string</entry><entry>Yes</entry><entry>No</entry><entry></entry></row><row><entry>constraint_name</entry><entry>string</entry><entry>Yes</entry><entry>No</entry><entry></entry></row><row><entry>column_name</entry><entry>string</entry><entry>Yes</entry><entry>No</entry><entry></entry></row><row><entry>ordinal_position</entry><entry>gint</entry><entry>Yes</entry><entry>No</entry><entry>Ordinal position of the column within the constraint key (count 
 starts at 1)</entry></row></tbody></tgroup></informaltable></para>
     <para>
       <itemizedlist>
         <listitem>

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	Sat Jul  5 15:50:46 2008
@@ -2,7 +2,7 @@
 <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
      "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"; [
 <!ENTITY nbsp            " ">
-<!ENTITY LIBGDA          "<application>libgda</application>">
+<!ENTITY LIBGDA          "<application>Libgda</application>">
 <!ENTITY GNOMEDB         "<application>GNOME-DB</application>">
 <!ENTITY igalia          '<emphasis><ulink url="http://www.igalia.com";>Igalia, S.L.</ulink></emphasis>'>
 <!ENTITY xobas           '<emphasis><ulink url="http://www.xobas.com";>Xobas Software</ulink></emphasis>'>
@@ -318,6 +318,10 @@
 	  <listitem>
             <para>Support for virtual connections, see the <link linkend="virtual_connection">Virtual connections chapter</link></para>
           </listitem>
+	  <listitem>
+            <para>Partially thread-safe, see <link linkend="threads">the threads limitation</link> for
+	      more details</para>
+          </listitem>
 	</itemizedlist>
       </para>
       <para>

Modified: trunk/doc/C/limitations.xml
==============================================================================
--- trunk/doc/C/limitations.xml	(original)
+++ trunk/doc/C/limitations.xml	Sat Jul  5 15:50:46 2008
@@ -1,6 +1,20 @@
 <chapter id="limitations">
   <title>Limitations</title>
 
+  <sect1 id="limitations_global"><title>Global limitations</title>
+    <para>
+      &LIBGDA;'s global limitations are:
+      <sect2 id="threads"><title>Multi threading</title>
+	<para>&LIBGDA; is not thread safe. However it supports working with threads as long as
+	  any object created by the API is used by one single thread (that is there is no
+	  situation when two threads try to acces the same object at the same time).
+	</para>
+	<para>For example it is safe to start a thread and in that thread create a connection
+	  which is only used in that thread.</para>
+      </sect2>
+    </para>
+  </sect1>
+
   <sect1 id="limitations_mysql"><title>For MySQL</title>
     <para>
       The following limitations apply to MySQL databases accessed via Libgda: none.

Modified: trunk/po/POTFILES.in
==============================================================================
--- trunk/po/POTFILES.in	(original)
+++ trunk/po/POTFILES.in	Sat Jul  5 15:50:46 2008
@@ -67,6 +67,7 @@
 providers/mdb/libmain.c
 providers/mdb/mdb_specs_dsn.xml.in
 providers/mysql/gda-mysql-ddl.c
+providers/mysql/gda-mysql-meta.c
 providers/mysql/gda-mysql-provider.c
 providers/mysql/gda-mysql-recordset.c
 providers/mysql/gda-mysql-util.c

Added: trunk/providers/firebird/firebird_specs_create_table.xml.in
==============================================================================
--- (empty file)
+++ trunk/providers/firebird/firebird_specs_create_table.xml.in	Sat Jul  5 15:50:46 2008
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<serv_op>
+  <parameters id="TABLE_DEF_P" _name="Table's description">
+    <parameter id="TABLE_NAME" _name="Name" _descr="Table's name" gdatype="gchararray" nullok="FALSE">
+      <gda_value>table_name</gda_value>
+    </parameter>
+  </parameters>
+
+  <!-- list of fields -->
+  <gda_array id="FIELDS_A" _name="Table's columns">
+    <gda_array_field id="COLUMN_NAME" _name="Field name" gdatype="gchararray" nullok="FALSE"/>
+    <gda_array_field id="COLUMN_TYPE" _name="Data type" gdatype="gchararray" hint="datatype" nullok="FALSE"/>
+    <gda_array_field id="COLUMN_NNUL" _name="Not NULL" gdatype="gboolean"/>
+    <gda_array_field id="COLUMN_UNIQUE" _name="Unique" gdatype="gboolean"/>
+    <gda_array_field id="COLUMN_PKEY" _name="Primary key" gdatype="gboolean"/>
+    <gda_array_field id="COLUMN_DEFAULT" _name="Default" _descr="Default value" gdatype="gchararray"/>
+    <gda_array_field id="COLUMN_CHECK" _name="Check" _descr="Check constraint" gdatype="gchararray"/>
+    <gda_array_data>
+        <gda_array_row>
+            <gda_value>id</gda_value>
+            <gda_value>integer</gda_value>
+            <gda_value>TRUE</gda_value>
+            <gda_value>TRUE</gda_value>
+            <gda_value>TRUE</gda_value>
+            <gda_value></gda_value>
+            <gda_value></gda_value>
+        </gda_array_row>
+    </gda_array_data>
+  </gda_array>
+
+  <!-- other table constraints -->
+  <sequence id="TABLE_CONSTRAINTS_S" _name="Global constraints">
+    <parameter id="CONSTRAINT_STRING" name="Constraint" gdatype="gchararray">
+      <gda_value>CHECK (column &gt; 0)</gda_value>
+    </parameter>
+  </sequence>
+</serv_op>

Added: trunk/providers/firebird/gda-firebird-ddl.c
==============================================================================
--- (empty file)
+++ trunk/providers/firebird/gda-firebird-ddl.c	Sat Jul  5 15:50:46 2008
@@ -0,0 +1,144 @@
+/* GDA Firebird Provider
+ * Copyright (C) 2008 The GNOME Foundation
+ *
+ * AUTHORS:
+ *      Vivien Malerba <malerba gnome-db org>
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <glib/gi18n-lib.h>
+#include <libgda/libgda.h>
+#include "gda-firebird-ddl.h"
+
+gchar *
+gda_firebird_render_CREATE_TABLE (GdaServerProvider *provider, GdaConnection *cnc, 
+				  GdaServerOperation *op, GError **error)
+{
+	GString *string;
+	const GValue *value;
+	gboolean allok = TRUE;
+	gboolean hasfields = FALSE;
+	gint nrows;
+	gint i;
+	gboolean first;
+	GSList *pkfields = NULL; /* list of GValue* composing the pkey */
+	gint nbpkfields = 0;
+	gchar *sql = NULL;
+
+	/* CREATE TABLE */
+	string = g_string_new ("CREATE TABLE ");
+
+	value = gda_server_operation_get_value_at (op, "/TABLE_DEF_P/TABLE_NAME");
+	g_assert (value && G_VALUE_HOLDS (value, G_TYPE_STRING));
+	g_string_append (string, g_value_get_string (value));
+	g_string_append (string, " (");
+		
+	/* FIELDS */
+	if (allok) {
+		GdaServerOperationNode *node;
+
+		node = gda_server_operation_get_node_info (op, "/FIELDS_A");
+		g_assert (node);
+
+		/* finding if there is a composed primary key */
+		nrows = gda_data_model_get_n_rows (node->model);
+		for (i = 0; i < nrows; i++) {
+			value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_PKEY/%d", i);
+			if (value && G_VALUE_HOLDS (value, G_TYPE_BOOLEAN) && g_value_get_boolean (value))
+				pkfields = g_slist_append (pkfields,
+							   (GValue *) gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_NAME/%d", i));
+		}
+		nbpkfields = g_slist_length (pkfields);
+
+		/* manually defined fields */
+		first = TRUE;
+		for (i = 0; i < nrows; i++) {
+			hasfields = TRUE;
+			if (first) 
+				first = FALSE;
+			else
+				g_string_append (string, ", ");
+				
+			value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_NAME/%d", i);
+			g_string_append (string, g_value_get_string (value));
+			g_string_append_c (string, ' ');
+				
+			value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_TYPE/%d", i);
+			g_string_append (string, g_value_get_string (value));
+				
+			value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_DEFAULT/%d", i);
+			if (value && G_VALUE_HOLDS (value, G_TYPE_STRING)) {
+				const gchar *str = g_value_get_string (value);
+				if (str && *str) {
+					g_string_append (string, " DEFAULT ");
+					g_string_append (string, str);
+				}
+			}
+				
+			value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_NNUL/%d", i);
+			if (value && G_VALUE_HOLDS (value, G_TYPE_BOOLEAN) && g_value_get_boolean (value))
+				g_string_append (string, " NOT NULL");
+
+			value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_UNIQUE/%d", i);
+			if (value && G_VALUE_HOLDS (value, G_TYPE_BOOLEAN) && g_value_get_boolean (value))
+				g_string_append (string, " UNIQUE");
+				
+			if (nbpkfields == 1) {
+				value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_PKEY/%d", i);
+				if (value && G_VALUE_HOLDS (value, G_TYPE_BOOLEAN) && g_value_get_boolean (value))
+					g_string_append (string, " PRIMARY KEY");
+			}
+				
+			value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_CHECK/%d", i);
+			if (value && G_VALUE_HOLDS (value, G_TYPE_STRING)) {
+				const gchar *str = g_value_get_string (value);
+				if (str && *str) {
+					g_string_append (string, " CHECK (");
+					g_string_append (string, str);
+					g_string_append_c (string, ')');
+				}
+			}
+		}
+	}
+
+	/* composed primary key */
+	if (nbpkfields > 1) {
+		GSList *list = pkfields;
+
+		g_string_append (string, ", PRIMARY KEY (");
+		while (list) {
+			if (list != pkfields)
+				g_string_append (string, ", ");
+			g_string_append (string, g_value_get_string ((GValue*) list->data));
+			list = list->next;
+		}
+		g_string_append_c (string, ')');
+	}
+
+	g_string_append (string, ")");
+
+	if (!hasfields) {
+		allok = FALSE;
+		g_set_error (error, 0, 0, _("Table to create must have at least one row"));
+	}
+	g_slist_free (pkfields);
+
+	sql = string->str;
+	g_string_free (string, FALSE);
+
+	return sql;
+}

Added: trunk/providers/firebird/gda-firebird-ddl.h
==============================================================================
--- (empty file)
+++ trunk/providers/firebird/gda-firebird-ddl.h	Sat Jul  5 15:50:46 2008
@@ -0,0 +1,34 @@
+/* GDA Firebird provider
+ * Copyright (C) 2008 The GNOME Foundation
+ *
+ * AUTHORS:
+ *      Vivien Malerba <malerba gnome-db org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __GDA_FIREBIRD_DDL_H__
+#define __GDA_FIREBIRD_DDL_H__
+
+#include <libgda/gda-server-provider.h>
+
+G_BEGIN_DECLS
+
+gchar *gda_firebird_render_CREATE_TABLE (GdaServerProvider *provider, GdaConnection *cnc, 
+					 GdaServerOperation *op, GError **error);
+G_END_DECLS
+
+#endif
+

Added: trunk/providers/firebird/gda-firebird-meta.c
==============================================================================
--- (empty file)
+++ trunk/providers/firebird/gda-firebird-meta.c	Sat Jul  5 15:50:46 2008
@@ -0,0 +1,488 @@
+/* GDA firebird provider
+ * Copyright (C) 2008 The GNOME Foundation.
+ *
+ * AUTHORS:
+ *      TO_ADD: your name and email
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include "gda-firebird.h"
+#include "gda-firebird-meta.h"
+#include "gda-firebird-provider.h"
+#include <libgda/gda-meta-store.h>
+#include <libgda/sql-parser/gda-sql-parser.h>
+#include <glib/gi18n-lib.h>
+#include <libgda/gda-server-provider-extra.h>
+#include <libgda/gda-connection-private.h>
+#include <libgda/gda-data-model-array.h>
+#include <libgda/gda-set.h>
+#include <libgda/gda-holder.h>
+
+static gboolean append_a_row (GdaDataModel *to_model, GError **error, gint nb, ...);
+
+/*
+ * predefined statements' IDs
+ */
+typedef enum {
+        I_STMT_1,
+} InternalStatementItem;
+
+
+/*
+ * predefined statements' SQL
+ */
+static gchar *internal_sql[] = {
+	"SQL for I_STMT_1"
+};
+
+/*
+ * global static values, and
+ * predefined statements' GdaStatement, all initialized in _gda_postgres_provider_meta_init()
+ */
+static GdaStatement **internal_stmt;
+static GdaSqlParser *internal_parser = NULL;
+static GdaSet       *i_set;
+
+/* TO_ADD: other static values */
+
+
+/*
+ * Meta initialization
+ */
+void
+_gda_firebird_provider_meta_init (GdaServerProvider *provider)
+{
+	static GStaticMutex init_mutex = G_STATIC_MUTEX_INIT;
+	InternalStatementItem i;
+
+	g_static_mutex_lock (&init_mutex);
+
+        internal_parser = gda_server_provider_internal_get_parser (provider);
+        internal_stmt = g_new0 (GdaStatement *, sizeof (internal_sql) / sizeof (gchar*));
+        for (i = I_STMT_1; i < sizeof (internal_sql) / sizeof (gchar*); i++) {
+                internal_stmt[i] = gda_sql_parser_parse_string (internal_parser, internal_sql[i], NULL, NULL);
+                if (!internal_stmt[i])
+                        g_error ("Could not parse internal statement: %s\n", internal_sql[i]);
+        }
+
+	/* initialize static values here */
+	i_set = gda_set_new_inline (4, "cat", G_TYPE_STRING, "", 
+				    "name", G_TYPE_STRING, "",
+				    "schema", G_TYPE_STRING, "",
+				    "name2", G_TYPE_STRING, "");
+	g_static_mutex_unlock (&init_mutex);
+}
+
+gboolean
+_gda_firebird_meta__info (GdaServerProvider *prov, GdaConnection *cnc, 
+		      GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	GdaDataModel *model;
+	gboolean retval;
+
+	TO_IMPLEMENT;
+	/* fill in @model, with something like:
+	 * model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_1], NULL, 
+	 *                                                  error);
+	 */
+	if (!model)
+		return FALSE;
+	retval = gda_meta_store_modify_with_context (store, context, model, error);
+	g_object_unref (model);
+		
+	return retval;
+}
+
+gboolean
+_gda_firebird_meta__btypes (GdaServerProvider *prov, GdaConnection *cnc, 
+			GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta__udt (GdaServerProvider *prov, GdaConnection *cnc, 
+		     GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta_udt (GdaServerProvider *prov, GdaConnection *cnc, 
+		    GdaMetaStore *store, GdaMetaContext *context, GError **error,
+		    const GValue *udt_catalog, const GValue *udt_schema)
+{
+	GdaDataModel *model;
+	gboolean retval = TRUE;
+
+	/* set internal holder's values from the arguments */
+	gda_holder_set_value (gda_set_get_holder (i_set, "cat"), udt_catalog);
+	gda_holder_set_value (gda_set_get_holder (i_set, "schema"), udt_schema);
+
+	TO_IMPLEMENT;
+	/* fill in @model, with something like:
+	 * model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_UDT], i_set, error);
+	 */
+	if (!model)
+		return FALSE;
+	retval = gda_meta_store_modify_with_context (store, context, model, error);
+	g_object_unref (model);
+
+	return retval;
+}
+
+
+gboolean
+_gda_firebird_meta__udt_cols (GdaServerProvider *prov, GdaConnection *cnc, 
+			  GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;	
+}
+
+gboolean
+_gda_firebird_meta_udt_cols (GdaServerProvider *prov, GdaConnection *cnc, 
+			 GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			 const GValue *udt_catalog, const GValue *udt_schema, const GValue *udt_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;	
+}
+
+gboolean
+_gda_firebird_meta__enums (GdaServerProvider *prov, GdaConnection *cnc, 
+		       GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;	
+}
+
+gboolean
+_gda_firebird_meta_enums (GdaServerProvider *prov, GdaConnection *cnc, 
+		      GdaMetaStore *store, GdaMetaContext *context, GError **error,
+		      const GValue *udt_catalog, const GValue *udt_schema, const GValue *udt_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+
+gboolean
+_gda_firebird_meta__domains (GdaServerProvider *prov, GdaConnection *cnc, 
+			 GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta_domains (GdaServerProvider *prov, GdaConnection *cnc, 
+			GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			const GValue *domain_catalog, const GValue *domain_schema)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta__constraints_dom (GdaServerProvider *prov, GdaConnection *cnc, 
+				 GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta_constraints_dom (GdaServerProvider *prov, GdaConnection *cnc, 
+				GdaMetaStore *store, GdaMetaContext *context, GError **error,
+				const GValue *domain_catalog, const GValue *domain_schema, 
+				const GValue *domain_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta__el_types (GdaServerProvider *prov, GdaConnection *cnc, 
+			  GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta_el_types (GdaServerProvider *prov, GdaConnection *cnc, 
+			 GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			 const GValue *specific_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta__collations (GdaServerProvider *prov, GdaConnection *cnc, 
+			    GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta_collations (GdaServerProvider *prov, GdaConnection *cnc, 
+			   GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			   const GValue *collation_catalog, const GValue *collation_schema, 
+			   const GValue *collation_name_n)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta__character_sets (GdaServerProvider *prov, GdaConnection *cnc, 
+				GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta_character_sets (GdaServerProvider *prov, GdaConnection *cnc, 
+			       GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			       const GValue *chset_catalog, const GValue *chset_schema, 
+			       const GValue *chset_name_n)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta__schemata (GdaServerProvider *prov, GdaConnection *cnc, 
+			  GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta_schemata (GdaServerProvider *prov, GdaConnection *cnc, 
+			 GdaMetaStore *store, GdaMetaContext *context, GError **error, 
+			 const GValue *catalog_name, const GValue *schema_name_n)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta__tables_views (GdaServerProvider *prov, GdaConnection *cnc, 
+			      GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta_tables_views (GdaServerProvider *prov, GdaConnection *cnc, 
+			     GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			     const GValue *table_catalog, const GValue *table_schema, 
+			     const GValue *table_name_n)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta__columns (GdaServerProvider *prov, GdaConnection *cnc, 
+			 GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta_columns (GdaServerProvider *prov, GdaConnection *cnc, 
+			GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			const GValue *table_catalog, const GValue *table_schema, 
+			const GValue *table_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta__view_cols (GdaServerProvider *prov, GdaConnection *cnc, 
+			   GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta_view_cols (GdaServerProvider *prov, GdaConnection *cnc, 
+			  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			  const GValue *view_catalog, const GValue *view_schema, 
+			  const GValue *view_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta__constraints_tab (GdaServerProvider *prov, GdaConnection *cnc, 
+				 GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta_constraints_tab (GdaServerProvider *prov, GdaConnection *cnc, 
+				GdaMetaStore *store, GdaMetaContext *context, GError **error, 
+				const GValue *table_catalog, const GValue *table_schema, 
+				const GValue *table_name, const GValue *constraint_name_n)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta__constraints_ref (GdaServerProvider *prov, GdaConnection *cnc, 
+				 GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta_constraints_ref (GdaServerProvider *prov, GdaConnection *cnc, 
+				GdaMetaStore *store, GdaMetaContext *context, GError **error,
+				const GValue *table_catalog, const GValue *table_schema, const GValue *table_name, 
+				const GValue *constraint_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta__key_columns (GdaServerProvider *prov, GdaConnection *cnc, 
+			     GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta_key_columns (GdaServerProvider *prov, GdaConnection *cnc, 
+			    GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			    const GValue *table_catalog, const GValue *table_schema, 
+			    const GValue *table_name, const GValue *constraint_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta__check_columns (GdaServerProvider *prov, GdaConnection *cnc, 
+			       GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta_check_columns (GdaServerProvider *prov, GdaConnection *cnc, 
+			      GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			      const GValue *table_catalog, const GValue *table_schema, 
+			      const GValue *table_name, const GValue *constraint_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta__triggers (GdaServerProvider *prov, GdaConnection *cnc, 
+			  GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta_triggers (GdaServerProvider *prov, GdaConnection *cnc, 
+			 GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			 const GValue *table_catalog, const GValue *table_schema, 
+			 const GValue *table_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta__routines (GdaServerProvider *prov, GdaConnection *cnc, 
+			  GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta_routines (GdaServerProvider *prov, GdaConnection *cnc, 
+			 GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			 const GValue *routine_catalog, const GValue *routine_schema, 
+			 const GValue *routine_name_n)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta__routine_col (GdaServerProvider *prov, GdaConnection *cnc, 
+			     GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta_routine_col (GdaServerProvider *prov, GdaConnection *cnc, 
+			    GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			    const GValue *rout_catalog, const GValue *rout_schema, 
+			    const GValue *rout_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta__routine_par (GdaServerProvider *prov, GdaConnection *cnc, 
+			     GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}
+
+gboolean
+_gda_firebird_meta_routine_par (GdaServerProvider *prov, GdaConnection *cnc, 
+			    GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			    const GValue *rout_catalog, const GValue *rout_schema, 
+			    const GValue *rout_name)
+{
+	TO_IMPLEMENT;
+	return TRUE;
+}

Added: trunk/providers/firebird/gda-firebird-meta.h
==============================================================================
--- (empty file)
+++ trunk/providers/firebird/gda-firebird-meta.h	Sat Jul  5 15:50:46 2008
@@ -0,0 +1,197 @@
+/* GDA firebird provider
+ * Copyright (C) 2008 The GNOME Foundation.
+ *
+ * AUTHORS:
+ *      TO_ADD: your name and email
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __GDA_FIREBIRD_META_H__
+#define __GDA_FIREBIRD_META_H__
+
+#include <libgda/gda-server-provider.h>
+
+G_BEGIN_DECLS
+
+void     _gda_firebird_provider_meta_init    (GdaServerProvider *provider);
+
+/* _information_schema_catalog_name */
+gboolean _gda_firebird_meta__info            (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+
+/* _builtin_data_types */
+gboolean _gda_firebird_meta__btypes          (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+
+/* _udt */
+gboolean _gda_firebird_meta__udt             (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_firebird_meta_udt              (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *udt_catalog, const GValue *udt_schema);
+
+/* _udt_columns */
+gboolean _gda_firebird_meta__udt_cols        (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_firebird_meta_udt_cols         (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *udt_catalog, const GValue *udt_schema, const GValue *udt_name);
+
+/* _enums */
+gboolean _gda_firebird_meta__enums           (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_firebird_meta_enums            (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *udt_catalog, const GValue *udt_schema, const GValue *udt_name);
+
+/* _domains */
+gboolean _gda_firebird_meta__domains         (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_firebird_meta_domains          (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *domain_catalog, const GValue *domain_schema);
+
+/* _domain_constraints */
+gboolean _gda_firebird_meta__constraints_dom (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_firebird_meta_constraints_dom  (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *domain_catalog, const GValue *domain_schema, 
+					  const GValue *domain_name);
+
+/* _element_types */
+gboolean _gda_firebird_meta__el_types        (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_firebird_meta_el_types         (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *specific_name);
+
+/* _collations */
+gboolean _gda_firebird_meta__collations      (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_firebird_meta_collations       (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *collation_catalog, const GValue *collation_schema, 
+					  const GValue *collation_name_n);
+
+/* _character_sets */
+gboolean _gda_firebird_meta__character_sets  (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_firebird_meta_character_sets   (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *chset_catalog, const GValue *chset_schema, 
+					  const GValue *chset_name_n);
+
+/* _schemata */
+gboolean _gda_firebird_meta__schemata        (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_firebird_meta_schemata         (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error, 
+					  const GValue *catalog_name, const GValue *schema_name_n);
+
+/* _tables or _views */
+gboolean _gda_firebird_meta__tables_views    (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_firebird_meta_tables_views     (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *table_catalog, const GValue *table_schema, 
+					  const GValue *table_name_n);
+
+/* _columns */
+gboolean _gda_firebird_meta__columns         (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_firebird_meta_columns          (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *table_catalog, const GValue *table_schema, 
+					  const GValue *table_name);
+
+/* _view_column_usage */
+gboolean _gda_firebird_meta__view_cols       (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_firebird_meta_view_cols        (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *view_catalog, const GValue *view_schema, 
+					  const GValue *view_name);
+
+/* _table_constraints */
+gboolean _gda_firebird_meta__constraints_tab (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_firebird_meta_constraints_tab  (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error, 
+					  const GValue *table_catalog, const GValue *table_schema, 
+					  const GValue *table_name, const GValue *constraint_name_n);
+
+/* _referential_constraints */
+gboolean _gda_firebird_meta__constraints_ref (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_firebird_meta_constraints_ref  (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *table_catalog, const GValue *table_schema, const GValue *table_name, 
+					  const GValue *constraint_name);
+
+/* _key_column_usage */
+gboolean _gda_firebird_meta__key_columns     (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_firebird_meta_key_columns      (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *table_catalog, const GValue *table_schema, 
+					  const GValue *table_name, const GValue *constraint_name);
+
+/* _check_column_usage */
+gboolean _gda_firebird_meta__check_columns   (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_firebird_meta_check_columns    (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *table_catalog, const GValue *table_schema, 
+					  const GValue *table_name, const GValue *constraint_name);
+
+/* _triggers */
+gboolean _gda_firebird_meta__triggers        (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_firebird_meta_triggers         (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *table_catalog, const GValue *table_schema, 
+					  const GValue *table_name);
+
+/* _routines */
+gboolean _gda_firebird_meta__routines       (GdaServerProvider *prov, GdaConnection *cnc, 
+					 GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_firebird_meta_routines        (GdaServerProvider *prov, GdaConnection *cnc, 
+					 GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					 const GValue *routine_catalog, const GValue *routine_schema, 
+					 const GValue *routine_name_n);
+
+/* _routine_columns */
+gboolean _gda_firebird_meta__routine_col     (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_firebird_meta_routine_col      (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *rout_catalog, const GValue *rout_schema, 
+					  const GValue *rout_name);
+
+/* _parameters */
+gboolean _gda_firebird_meta__routine_par     (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_firebird_meta_routine_par      (GdaServerProvider *prov, GdaConnection *cnc, 
+					  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					  const GValue *rout_catalog, const GValue *rout_schema, 
+					  const GValue *rout_name);
+
+
+G_END_DECLS
+
+#endif
+

Added: trunk/providers/firebird/gda-firebird-parser.c
==============================================================================
--- (empty file)
+++ trunk/providers/firebird/gda-firebird-parser.c	Sat Jul  5 15:50:46 2008
@@ -0,0 +1,84 @@
+/* GDA Firebird provider
+ *
+ * Copyright (C) 2008 The GNOME Foundation
+ *
+ * AUTHORS:
+ *      TO_ADD: your name and email
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "gda-firebird-parser.h"
+#include "firebird_token_types.h"
+#include <string.h>
+
+/* 
+ * Main static functions 
+ */
+static void gda_firebird_parser_class_init (GdaFirebirdParserClass *klass);
+static void gda_firebird_parser_init (GdaFirebirdParser *stmt);
+
+GType
+gda_firebird_parser_get_type (void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY (type == 0)) {
+		static GStaticMutex registering = G_STATIC_MUTEX_INIT;
+		static const GTypeInfo info = {
+			sizeof (GdaFirebirdParserClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) gda_firebird_parser_class_init,
+			NULL,
+			NULL,
+			sizeof (GdaFirebirdParser),
+			0,
+			(GInstanceInitFunc) gda_firebird_parser_init
+		};
+		
+		g_static_mutex_lock (&registering);
+		if (type == 0)
+			type = g_type_register_static (GDA_TYPE_SQL_PARSER, "GdaFirebirdParser", &info, 0);
+		g_static_mutex_unlock (&registering);
+	}
+	return type;
+}
+
+/*
+ * The interface to the LEMON-generated parser
+ */
+void *gda_lemon_firebird_parserAlloc (void*(*)(size_t));
+void gda_lemon_firebird_parserFree (void*, void(*)(void*));
+void gda_lemon_firebird_parserTrace (void*, char *);
+void gda_lemon_firebird_parser (void*, int, GValue *, GdaSqlParserIface *);
+
+static void
+gda_firebird_parser_class_init (GdaFirebirdParserClass * klass)
+{
+	GdaSqlParserClass *pclass = GDA_SQL_PARSER_CLASS (klass);
+
+	pclass->parser_alloc = gda_lemon_firebird_parserAlloc;
+	pclass->parser_free = gda_lemon_firebird_parserFree;
+	pclass->parser_trace = gda_lemon_firebird_parserTrace;
+	pclass->parser_parse = gda_lemon_firebird_parser;
+	pclass->parser_tokens_trans = firebird_parser_tokens;
+}
+
+static void
+gda_firebird_parser_init (GdaFirebirdParser *parser)
+{
+}

Added: trunk/providers/firebird/gda-firebird-parser.h
==============================================================================
--- (empty file)
+++ trunk/providers/firebird/gda-firebird-parser.h	Sat Jul  5 15:50:46 2008
@@ -0,0 +1,59 @@
+/* GDA Firebird provider
+ *
+ * Copyright (C) 2008 The GNOME Foundation
+ *
+ * AUTHORS:
+ *      TO_ADD: your name and email
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __GDA_FIREBIRD_PARSER_H_
+#define __GDA_FIREBIRD_PARSER_H_
+
+#include <sql-parser/gda-sql-parser.h>
+
+G_BEGIN_DECLS
+
+#define GDA_TYPE_FIREBIRD_PARSER            (gda_firebird_parser_get_type())
+#define GDA_FIREBIRD_PARSER(obj)            (G_TYPE_CHECK_INSTANCE_CAST (obj, GDA_TYPE_FIREBIRD_PARSER, GdaFirebirdParser))
+#define GDA_FIREBIRD_PARSER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST (klass, GDA_TYPE_FIREBIRD_PARSER, GdaFirebirdParserClass))
+#define GDA_IS_FIREBIRD_PARSER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE (obj, GDA_TYPE_FIREBIRD_PARSER))
+#define GDA_IS_FIREBIRD_PARSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDA_TYPE_FIREBIRD_PARSER))
+
+typedef struct _GdaFirebirdParser GdaFirebirdParser;
+typedef struct _GdaFirebirdParserClass GdaFirebirdParserClass;
+typedef struct _GdaFirebirdParserPrivate GdaFirebirdParserPrivate;
+
+/* struct for the object's data */
+struct _GdaFirebirdParser
+{
+	GdaSqlParser          object;
+	GdaFirebirdParserPrivate *priv;
+};
+
+/* struct for the object's class */
+struct _GdaFirebirdParserClass
+{
+	GdaSqlParserClass      parent_class;
+};
+
+GType gda_firebird_parser_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif

Added: trunk/providers/firebird/gda-firebird-pstmt.c
==============================================================================
--- (empty file)
+++ trunk/providers/firebird/gda-firebird-pstmt.c	Sat Jul  5 15:50:46 2008
@@ -0,0 +1,96 @@
+/* GDA Firebird provider
+ * Copyright (C) 2008 The GNOME Foundation.
+ *
+ * AUTHORS:
+ *      TO_ADD: your name and email
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include <glib/gi18n-lib.h>
+#include "gda-firebird-pstmt.h"
+
+static void gda_firebird_pstmt_class_init (GdaFirebirdPStmtClass *klass);
+static void gda_firebird_pstmt_init       (GdaFirebirdPStmt *pstmt, GdaFirebirdPStmtClass *klass);
+static void gda_firebird_pstmt_finalize    (GObject *object);
+
+static GObjectClass *parent_class = NULL;
+
+/**
+ * gda_firebird_pstmt_get_type
+ *
+ * Returns: the #GType of GdaFirebirdPStmt.
+ */
+GType
+gda_firebird_pstmt_get_type (void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY (type == 0)) {
+		static GStaticMutex registering = G_STATIC_MUTEX_INIT;
+		static const GTypeInfo info = {
+			sizeof (GdaFirebirdPStmtClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) gda_firebird_pstmt_class_init,
+			NULL,
+			NULL,
+			sizeof (GdaFirebirdPStmt),
+			0,
+			(GInstanceInitFunc) gda_firebird_pstmt_init
+		};
+
+		g_static_mutex_lock (&registering);
+		if (type == 0)
+			type = g_type_register_static (GDA_TYPE_PSTMT, "GdaFirebirdPStmt", &info, 0);
+		g_static_mutex_unlock (&registering);
+	}
+	return type;
+}
+
+static void 
+gda_firebird_pstmt_class_init (GdaFirebirdPStmtClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	parent_class = g_type_class_peek_parent (klass);
+
+	/* virtual functions */
+	object_class->finalize = gda_firebird_pstmt_finalize;
+}
+
+static void
+gda_firebird_pstmt_init (GdaFirebirdPStmt *pstmt, GdaFirebirdPStmtClass *klass)
+{
+	g_return_if_fail (GDA_IS_PSTMT (pstmt));
+	
+	/* initialize specific parts of @pstmt */
+	TO_IMPLEMENT;
+}
+
+static void
+gda_firebird_pstmt_finalize (GObject *object)
+{
+	GdaFirebirdPStmt *pstmt = (GdaFirebirdPStmt *) object;
+
+	g_return_if_fail (GDA_IS_PSTMT (pstmt));
+
+	/* free memory */
+	TO_IMPLEMENT; /* free some specific parts of @pstmt */
+
+	/* chain to parent class */
+	parent_class->finalize (object);
+}

Added: trunk/providers/firebird/gda-firebird-pstmt.h
==============================================================================
--- (empty file)
+++ trunk/providers/firebird/gda-firebird-pstmt.h	Sat Jul  5 15:50:46 2008
@@ -0,0 +1,57 @@
+/* GDA Firebird library
+ * Copyright (C) 2008 The GNOME Foundation.
+ *
+ * AUTHORS:
+ *      TO_ADD: your name and email
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GDA_FIREBIRD_PSTMT_H__
+#define __GDA_FIREBIRD_PSTMT_H__
+
+#include <providers-support/gda-pstmt.h>
+#include "gda-firebird.h"
+
+G_BEGIN_DECLS
+
+#define GDA_TYPE_FIREBIRD_PSTMT            (gda_firebird_pstmt_get_type())
+#define GDA_FIREBIRD_PSTMT(obj)            (G_TYPE_CHECK_INSTANCE_CAST (obj, GDA_TYPE_FIREBIRD_PSTMT, GdaFirebirdPStmt))
+#define GDA_FIREBIRD_PSTMT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST (klass, GDA_TYPE_FIREBIRD_PSTMT, GdaFirebirdPStmtClass))
+#define GDA_IS_FIREBIRD_PSTMT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE(obj, GDA_TYPE_FIREBIRD_PSTMT))
+#define GDA_IS_FIREBIRD_PSTMT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GDA_TYPE_FIREBIRD_PSTMT))
+
+typedef struct _GdaFirebirdPStmt        GdaFirebirdPStmt;
+typedef struct _GdaFirebirdPStmtClass   GdaFirebirdPStmtClass;
+
+struct _GdaFirebirdPStmt {
+	GdaPStmt        object;
+
+	/* TO_ADD: this structure holds any information necessary to reference a prepared statement, usually a connection
+         * handle from the C or C++ API
+         */
+};
+
+struct _GdaFirebirdPStmtClass {
+	GdaPStmtClass  parent_class;
+};
+
+GType         gda_firebird_pstmt_get_type  (void) G_GNUC_CONST;
+/* TO_ADD: helper function to create a GdaFirebirdPStmt such as gda_firebird_pstmt_new() with some specific arguments */
+
+G_END_DECLS
+
+#endif

Added: trunk/providers/firebird/gda-firebird-util.c
==============================================================================
--- (empty file)
+++ trunk/providers/firebird/gda-firebird-util.c	Sat Jul  5 15:50:46 2008
@@ -0,0 +1,48 @@
+/* GDA firebird provider
+ * Copyright (C) 2008 The GNOME Foundation.
+ *
+ * AUTHORS:
+ *         Vivien Malerba <malerba gnome-db org>
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <glib/gi18n-lib.h>
+#include "gda-firebird-util.h"
+
+GdaConnectionEvent *
+_gda_firebird_make_error (GdaConnection *cnc, const gint statement_type)
+{
+	FirebirdConnectionData *cdata;
+	GdaConnectionEvent *error;
+        gchar *description;
+
+        g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+
+	cdata = (FirebirdConnectionData*) gda_connection_internal_get_provider_data (cnc);
+	if (!cdata) 
+		return FALSE;
+
+        error = gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR);
+        gda_connection_event_set_code (error, isc_sqlcode (cdata->status));
+        description = fb_sqlerror_get_description (cdata, statement_type);
+        gda_connection_event_set_source (error, "[GDA Firebird]");
+        gda_connection_event_set_description (error, description);
+        gda_connection_add_event (cnc, error);
+        g_free (description);
+
+        return error;
+}

Added: trunk/providers/firebird/gda-firebird-util.h
==============================================================================
--- (empty file)
+++ trunk/providers/firebird/gda-firebird-util.h	Sat Jul  5 15:50:46 2008
@@ -0,0 +1,36 @@
+/* GDA firebird provider
+ * Copyright (C) 1998 - 2008 The GNOME Foundation.
+ *
+ * AUTHORS:
+ *         Vivien Malerba <malerba gnome-db org>
+ *         Rodrigo Moya <rodrigo gnome-db org>
+ *         Gonzalo Paniagua Javier <gonzalo gnome-db org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __GDA_FIREBIRD_UTIL_H__
+#define __GDA_FIREBIRD_UTIL_H__
+
+#include "gda-firebird.h"
+
+G_BEGIN_DECLS
+
+GdaConnectionEvent *_gda_firebird_make_error (GdaConnection *cnc, const gint statement_type);
+
+G_END_DECLS
+
+#endif
+

Added: trunk/providers/firebird/gda-firebird.h
==============================================================================
--- (empty file)
+++ trunk/providers/firebird/gda-firebird.h	Sat Jul  5 15:50:46 2008
@@ -0,0 +1,48 @@
+c/* GDA firebird provider
+ * Copyright (C) 2008 The GNOME Foundation.
+ *
+ * AUTHORS:
+ *      Vivien Malerba <malerba gnome-db org>
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GDA_FIREBIRD_H__
+#define __GDA_FIREBIRD_H__
+
+/*
+ * Provider name
+ */
+#define FIREBIRD_PROVIDER_NAME "Firebird"
+
+#include <ibase.h>
+
+/*
+ * Provider's specific connection data
+ */
+typedef struct {
+	gchar         *dbname;
+	gchar         *server_version;
+        isc_db_handle  handle;
+        ISC_STATUS     status[20];
+        gchar          dpb_buffer[128];
+        gshort         dpb_length;
+
+	/* transaction */
+	isc_tr_handle *ftr;
+} FirebirdConnectionData;
+
+#endif

Added: trunk/providers/firebird/gen_def.c
==============================================================================
--- (empty file)
+++ trunk/providers/firebird/gen_def.c	Sat Jul  5 15:50:46 2008
@@ -0,0 +1,194 @@
+/* 
+ * Copyright (C) 2007 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
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * This program generates tokens'ID transformation because the GdaSqlParser object uses 2 Lemon generated
+ * parsers at once, but with only one tokenizer (because each Lemon generated parser generates it own IDs for
+ * tokens).
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+#define MAX_SYMBOLS 500
+#define PARSER_HEADER "parser.h"
+#define FALSE 0
+#define TRUE (!FALSE)
+
+typedef struct {
+	char *key;
+	int   parser_value;
+} HashEntry;
+
+HashEntry entries[MAX_SYMBOLS];
+int nb_entries; /* must remain < MAX_SYMBOLS */
+
+typedef enum {
+	TYPE_IMPOSED,
+	TYPE_PARSER
+} SourceType;
+
+static void parse_contents (FILE *stream, SourceType type);
+static HashEntry *find_entry_for_token (char *token);
+int 
+main (int argc,char** argv)
+{
+	int i;
+	FILE *fd_imposed;
+	FILE *fd_parser;
+	HashEntry *illegal_entry;
+	HashEntry *rawstring_entry;
+
+	memset (entries, 0, sizeof (entries));
+	fd_imposed = fopen (IMPOSED_HEADER, "r");
+	if (!fd_imposed) {
+		printf ("Can't open '%s':%s\n", IMPOSED_HEADER, strerror (errno));
+		return 1;
+	}
+	fd_parser = fopen (PARSER_HEADER, "r");
+	if (!fd_parser) {
+		printf ("Can't open '%s':%s\n", PARSER_HEADER, strerror (errno));
+		return 1;
+	}
+
+	nb_entries = 0;
+	parse_contents (fd_imposed, TYPE_IMPOSED);
+	parse_contents (fd_parser, TYPE_PARSER);
+
+	fclose (fd_imposed);
+	fclose (fd_parser);
+
+	/* output notice */
+	printf ("/*\n * This file is generated by the gen_def program (see the gen_def.c file \n"
+		" * for some explanations)\n"
+		" * DO NOT EDIT MANUALLY\n */\n\n\n");
+
+	/* output */
+	for (i = 0; i < nb_entries; i++) {
+		HashEntry *entry = &(entries[i]);
+		printf ("#define L_%s \t\t %d\n", entry->key, i);
+	}
+	illegal_entry = find_entry_for_token ("ILLEGAL");
+	rawstring_entry = find_entry_for_token ("RAWSTRING");
+	printf ("gint firebird_parser_tokens[] = {\n");
+	for (i = 0; i < nb_entries; i++) {
+		HashEntry *entry = &(entries[i]);
+		if (i!= 0)
+			printf (",");
+		if (entry->parser_value >= 0)
+			printf ("%d", entry->parser_value);
+		else
+			printf ("%d", illegal_entry->parser_value);
+	}
+	printf ("};\n");
+
+	return 0;
+}
+
+static HashEntry *
+find_entry_for_token (char *token) 
+{
+	int i;
+
+	for (i = 0; i < nb_entries; i++) {
+		HashEntry *e = &(entries[i]);
+		if (!strcmp (e->key, token))
+			return e;
+	}
+	return NULL;
+}
+
+
+
+static void 
+parse_line (char *line, SourceType type) 
+{
+	char *z, *token;
+	int value;
+	HashEntry *entry;
+	
+	z = line;
+	if (strncmp (z, "#define ", 8)) {
+		printf ("Expected '#define', not found");
+		exit (1);
+	}
+	z += 8;
+	token = z + 2;
+	for (; *z && *z != ' '; z++);
+	*z = 0;
+	z++;
+	for (; *z == ' '; z++);
+	value = atoi (z);
+	/*printf ("%d Token: /%s/, value=%d\n", type, token, value);*/
+
+	entry = find_entry_for_token (token);
+	if (!entry) {
+		nb_entries++;
+		entry = &(entries[nb_entries - 1]);
+		entry->key = malloc (sizeof (char) * (strlen (token) + 1));
+		memcpy (entry->key, token, strlen (token) + 1);
+		entry->parser_value = -1;
+	}
+	if (type == TYPE_PARSER)
+		entry->parser_value = value;
+}
+
+static void
+parse_contents (FILE *stream, SourceType type)
+{
+#define BUFSIZE 500
+	char buffer[BUFSIZE];
+	int read;
+	char *end;
+
+	read = fread (buffer, 1, BUFSIZE, stream);
+	end = buffer + read;
+	while (read > 0) {
+		char *ptr;
+
+		/* read all complete lines in buffer */
+		while (end > buffer) {
+			char *hold = NULL;
+			for (ptr = buffer; (ptr < end) && *ptr && (*ptr != '\n'); ptr++);
+			if (ptr == end)
+				break;
+			if (*ptr)
+				hold = ptr+1;
+			*ptr = 0;
+
+			/* treat the line */
+			parse_line (buffer, type);
+
+			if (hold) {
+				int l = end - hold;
+				end -= hold - buffer;
+				memmove (buffer, hold, l);
+			}
+			else
+				break;
+		}
+
+		read = fread (end, 1, BUFSIZE - (end - buffer), stream);
+		end += read;
+	}
+}
+

Added: trunk/providers/firebird/parser.y
==============================================================================
--- (empty file)
+++ trunk/providers/firebird/parser.y	Sat Jul  5 15:50:46 2008
@@ -0,0 +1,1025 @@
+// All token codes are small integers with #defines that begin with "TK_"
+%token_prefix T_
+
+// The type of the data attached to each token is GValue.  This is also the
+// default type for non-terminals.
+//
+%token_type {GValue *}
+%default_type {GValue *}
+%token_destructor {if ($$) {
+		 gchar *str = gda_sql_value_stringify ($$);
+		 DEBUG ("token destructor /%s/", str);
+		 g_free (str);
+		 g_value_unset ($$); g_free ($$);}}
+
+// The generated parser function takes a 4th argument as follows:
+%extra_argument {GdaSqlParserIface *pdata}
+
+// This code runs whenever there is a syntax error
+//
+%syntax_error {
+	gda_sql_parser_set_syntax_error (pdata->parser);
+}
+%stack_overflow {
+	gda_sql_parser_set_overflow_error (pdata->parser);
+}
+
+// The name of the generated procedure that implements the parser
+// is as follows:
+%name gda_lemon_firebird_parser
+
+// The following text is included near the beginning of the C source
+// code file that implements the parser.
+//
+%include {
+#include <string.h>
+#include <glib.h>
+#include <glib-object.h>
+#include <glib/gi18n-lib.h>
+#include <libgda/sql-parser/gda-sql-parser-private.h>
+#include <libgda/sql-parser/gda-statement-struct-util.h>
+#include <libgda/sql-parser/gda-statement-struct-trans.h>
+#include <libgda/sql-parser/gda-statement-struct-insert.h>
+#include <libgda/sql-parser/gda-statement-struct-update.h>
+#include <libgda/sql-parser/gda-statement-struct-delete.h>
+#include <libgda/sql-parser/gda-statement-struct-select.h>
+#include <libgda/sql-parser/gda-statement-struct-compound.h>
+#include <libgda/sql-parser/gda-statement-struct-parts.h>
+#include <assert.h>
+
+#ifdef GDA_DEBUG_NO
+#define DEBUG(format, ...) g_print ("___" format "\n", __VA_ARGS__)
+#else
+#define DEBUG(format, ...)
+#endif
+
+typedef struct {
+	GValue *fname;
+	GdaSqlExpr *expr;
+} UpdateSet;
+
+typedef struct {
+	gboolean    distinct;
+	GdaSqlExpr *expr;
+} Distinct;
+
+typedef struct {
+	GdaSqlExpr *count;
+	GdaSqlExpr *offset;
+} Limit;
+
+typedef struct {
+	GSList *when_list;
+	GSList *then_list;
+} CaseBody;
+
+static GdaSqlOperatorType
+sql_operation_string_to_operator (const gchar *op)
+{
+	switch (g_ascii_toupper (*op)) {
+	case 'A':
+		return GDA_SQL_OPERATOR_TYPE_AND;
+	case 'O':
+		return GDA_SQL_OPERATOR_TYPE_OR;
+	case 'N':
+		return GDA_SQL_OPERATOR_TYPE_NOT;
+	case '=':
+		return GDA_SQL_OPERATOR_TYPE_EQ;
+	case 'I':
+		if (op[1] == 'S')
+			return GDA_SQL_OPERATOR_TYPE_IS;
+		else if (op[1] == 'N')
+			return GDA_SQL_OPERATOR_TYPE_IN;
+		break;
+	case 'L':
+		return GDA_SQL_OPERATOR_TYPE_LIKE;
+	case 'B':
+		return GDA_SQL_OPERATOR_TYPE_BETWEEN;
+	case '>':
+		if (op[1] == '=')
+			return GDA_SQL_OPERATOR_TYPE_GEQ;
+		else if (op[1] == 0)
+			return GDA_SQL_OPERATOR_TYPE_GT;
+		break;
+	case '<':
+		if (op[1] == '=')
+			return GDA_SQL_OPERATOR_TYPE_LEQ;
+		else if (op[1] == 0)
+			return GDA_SQL_OPERATOR_TYPE_LT;
+		break;
+	case '!':
+		if (op[1] == '=')
+			return GDA_SQL_OPERATOR_TYPE_DIFF;
+		else if (op[1] == '~') {
+			if (op[2] == 0)
+				return GDA_SQL_OPERATOR_TYPE_NOT_REGEXP;
+			else if (op[2] == '*')
+				return GDA_SQL_OPERATOR_TYPE_NOT_REGEXP_CI;
+		}
+		break;
+	case '~':
+		if (op[1] == '*')
+			return GDA_SQL_OPERATOR_TYPE_REGEXP_CI;
+		else if (op[1] == 0)
+			return GDA_SQL_OPERATOR_TYPE_REGEXP;
+		break;
+	case 'S':
+		return GDA_SQL_OPERATOR_TYPE_SIMILAR;
+	case '|':
+		if (op[1] == '|')
+			return GDA_SQL_OPERATOR_TYPE_CONCAT;
+		else
+			return GDA_SQL_OPERATOR_TYPE_BITOR;
+	case '+':
+		return GDA_SQL_OPERATOR_TYPE_PLUS;
+	case '-':
+		return GDA_SQL_OPERATOR_TYPE_MINUS;
+	case '*':
+		return GDA_SQL_OPERATOR_TYPE_STAR;
+	case '/':
+		return GDA_SQL_OPERATOR_TYPE_DIV;
+	case '%':
+		return GDA_SQL_OPERATOR_TYPE_REM;
+	case '&':
+		return GDA_SQL_OPERATOR_TYPE_BITAND;
+	}
+	g_error ("Unhandled operator named '%s'\n", op);
+	return 0;
+}
+
+static GdaSqlOperatorType
+string_to_op_type (GValue *value)
+{
+	GdaSqlOperatorType op;
+	op = sql_operation_string_to_operator (g_value_get_string (value));
+	g_value_reset (value);
+	g_free (value);
+	return op;
+}
+
+static GdaSqlExpr *
+compose_multiple_expr (GdaSqlOperatorType op, GdaSqlExpr *left, GdaSqlExpr *right) {
+	GdaSqlExpr *ret;
+	if (left->cond && (left->cond->operator == op)) {
+		ret = left;
+		ret->cond->operands = g_slist_append (ret->cond->operands, right);
+	}
+	else {
+		GdaSqlOperation *cond;
+		ret = gda_sql_expr_new (NULL);
+		cond = gda_sql_operation_new (GDA_SQL_ANY_PART (ret));
+		ret->cond = cond;
+		cond->operator = op;
+		cond->operands = g_slist_prepend (NULL, right);
+		GDA_SQL_ANY_PART (right)->parent = GDA_SQL_ANY_PART (cond);
+		cond->operands = g_slist_prepend (cond->operands, left);
+		GDA_SQL_ANY_PART (left)->parent = GDA_SQL_ANY_PART (cond);
+	}
+	return ret;
+}
+
+static GdaSqlExpr *
+create_two_expr (GdaSqlOperatorType op, GdaSqlExpr *left, GdaSqlExpr *right) {
+	GdaSqlExpr *ret;
+	GdaSqlOperation *cond;
+	ret = gda_sql_expr_new (NULL);
+	cond = gda_sql_operation_new (GDA_SQL_ANY_PART (ret));
+	ret->cond = cond;
+	cond->operator = op;
+	cond->operands = g_slist_prepend (NULL, right);
+	GDA_SQL_ANY_PART (right)->parent = GDA_SQL_ANY_PART (cond);
+	cond->operands = g_slist_prepend (cond->operands, left);
+	GDA_SQL_ANY_PART (left)->parent = GDA_SQL_ANY_PART (cond);
+	return ret;
+}
+
+static GdaSqlExpr *
+create_uni_expr (GdaSqlOperatorType op, GdaSqlExpr *expr) {
+	GdaSqlExpr *ret;
+	GdaSqlOperation *cond;
+	ret = gda_sql_expr_new (NULL);
+	cond = gda_sql_operation_new (GDA_SQL_ANY_PART (ret));
+	ret->cond = cond;
+	cond->operator = op;
+	cond->operands = g_slist_prepend (NULL, expr);
+	GDA_SQL_ANY_PART (expr)->parent = GDA_SQL_ANY_PART (cond);
+	return ret;
+}
+
+static GdaSqlStatement *
+compose_multiple_compounds (GdaSqlStatementCompoundType ctype, GdaSqlStatement *left, GdaSqlStatement *right) {
+	GdaSqlStatement *ret;
+	GdaSqlStatementCompound *lc = (GdaSqlStatementCompound*) left->contents;
+	if (lc->compound_type == ctype) {
+		GdaSqlStatementCompound *rc = (GdaSqlStatementCompound*) right->contents;
+		if (!rc->stmt_list->next || rc->compound_type == ctype) {
+			GSList *list;
+			for (list = rc->stmt_list; list; list = list->next)
+				GDA_SQL_ANY_PART (((GdaSqlStatement*)list->data)->contents)->parent = GDA_SQL_ANY_PART (lc);
+
+			ret = left;
+			lc->stmt_list = g_slist_concat (lc->stmt_list, rc->stmt_list);
+			rc->stmt_list = NULL;
+			gda_sql_statement_free (right);
+		}
+	}
+	else {
+		ret = gda_sql_statement_new (GDA_SQL_STATEMENT_COMPOUND);
+		gda_sql_statement_compound_set_type (ret, ctype);
+		gda_sql_statement_compound_take_stmt (ret, left);
+		gda_sql_statement_compound_take_stmt (ret, right);
+	}
+	return ret;
+}
+
+}
+
+// The following directive causes tokens ABORT, AFTER, ASC, etc. to
+// fallback to ID if they will not parse as their original value.
+%fallback ID
+  ABORT AFTER ANALYZE ASC ATTACH BEFORE BEGIN CASCADE CAST CONFLICT
+  DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR
+  IGNORE IMMEDIATE INITIALLY INSTEAD LIKE MATCH PLAN
+  QUERY KEY OF OFFSET PRAGMA RAISE REPLACE RESTRICT ROW
+  TEMP TRIGGER VACUUM VIEW VIRTUAL
+  REINDEX RENAME CTIME_KW IF
+  DELIMITER COMMIT ROLLBACK ISOLATION LEVEL SERIALIZABLE READ COMMITTED 
+  UNCOMMITTED REPEATABLE WRITE ONLY SAVEPOINT RELEASE COMMENT FORCE WAIT NOWAIT BATCH.
+
+// Define operator precedence early so that this is the first occurance
+// of the operator tokens in the grammer.  Keeping the operators together
+// causes them to be assigned integer values that are close together,
+// which keeps parser tables smaller.
+%left OR.
+%left AND.
+%right NOT.
+%left IS MATCH LIKE IN ISNULL NOTNULL DIFF EQ.
+%left BETWEEN.
+%left GT LEQ LT GEQ.
+%left REGEXP REGEXP_CI NOT_REGEXP NOT_REGEXP_CI.
+%left SIMILAR.
+%right ESCAPE.
+%left BITAND BITOR LSHIFT RSHIFT.
+%left PLUS MINUS.
+%left STAR SLASH REM.
+%left CONCAT.
+%left COLLATE.
+%right UMINUS UPLUS BITNOT.
+%left LP RP.
+%left JOIN INNER NATURAL LEFT RIGHT FULL CROSS.
+%left UNION EXCEPT.
+%left INTERSECT.
+%left PGCAST.
+
+// force the declaration of the ILLEGAL and SQLCOMMENT tokens
+%nonassoc ILLEGAL.
+%nonassoc SQLCOMMENT.
+
+// Input is a single SQL command
+%type stmt {GdaSqlStatement *}
+%destructor stmt {g_print ("Statement destroyed by parser: %p\n", $$); gda_sql_statement_free ($$);}
+stmt ::= cmd(C) eos. {pdata->parsed_statement = C;}
+stmt ::= compound(C) eos. {
+	GdaSqlStatementCompound *scompound = (GdaSqlStatementCompound *) C->contents;
+	if (scompound->stmt_list->next)
+		/* real compound (multiple statements) */
+		pdata->parsed_statement = C;
+	else {
+		/* false compound (only 1 select) */
+		pdata->parsed_statement = (GdaSqlStatement*) scompound->stmt_list->data;
+		GDA_SQL_ANY_PART (pdata->parsed_statement->contents)->parent = NULL;
+		g_slist_free (scompound->stmt_list);
+		scompound->stmt_list = NULL;
+		gda_sql_statement_free (C);
+	}
+}
+cmd(C) ::= LP cmd(E) RP. {C = E;}
+compound(C) ::= LP compound(E) RP. {C = E;}
+
+eos ::= SEMI.
+eos ::= END_OF_FILE.
+
+%type cmd {GdaSqlStatement *}
+%destructor cmd {gda_sql_statement_free ($$);}
+
+//
+// Transactions
+//
+cmd(C) ::= BEGIN. {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);}
+cmd(C) ::= BEGIN TRANSACTION nm_opt(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+					 gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= BEGIN transtype(Y) TRANSACTION nm_opt(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+						      gda_sql_statement_trans_take_mode (C, Y);
+						      gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= BEGIN transtype(Y) nm_opt(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+					  gda_sql_statement_trans_take_mode (C, Y);
+					  gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= BEGIN transilev(L). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+				gda_sql_statement_trans_set_isol_level (C, L);
+}
+
+cmd(C) ::= BEGIN TRANSACTION transilev(L). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+					    gda_sql_statement_trans_set_isol_level (C, L);
+}
+
+cmd(C) ::= BEGIN TRANSACTION transtype(Y). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+					    gda_sql_statement_trans_take_mode (C, Y);
+}
+
+cmd(C) ::= BEGIN TRANSACTION transtype(Y) opt_comma transilev(L). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+								   gda_sql_statement_trans_take_mode (C, Y);
+								   gda_sql_statement_trans_set_isol_level (C, L);
+}
+
+cmd(C) ::= BEGIN TRANSACTION transilev(L) opt_comma transtype(Y). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+								   gda_sql_statement_trans_take_mode (C, Y);
+								   gda_sql_statement_trans_set_isol_level (C, L);
+}
+
+cmd(C) ::= BEGIN transtype(Y) opt_comma transilev(L). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+						       gda_sql_statement_trans_take_mode (C, Y);
+						       gda_sql_statement_trans_set_isol_level (C, L);
+}
+	
+cmd(C) ::= BEGIN transilev(L) opt_comma transtype(Y). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+						       gda_sql_statement_trans_take_mode (C, Y);
+						       gda_sql_statement_trans_set_isol_level (C, L);
+}
+
+cmd(C) ::= END trans_opt_kw nm_opt(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);
+					gda_sql_statement_trans_take_name (C, R);
+}
+	
+cmd(C) ::= COMMIT nm_opt(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);
+			      gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= COMMIT TRANSACTION nm_opt(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);
+					  gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= COMMIT FORCE STRING. {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);}
+cmd(C) ::= COMMIT FORCE STRING COMMA INTEGER. {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);}
+cmd(C) ::= COMMIT COMMENT STRING. {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);}
+cmd(C) ::= COMMIT COMMENT STRING ora_commit_write. {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);}
+cmd(C) ::= COMMIT ora_commit_write. {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);}
+
+cmd(C) ::= ROLLBACK trans_opt_kw nm_opt(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_ROLLBACK);
+					     gda_sql_statement_trans_take_name (C, R);
+}
+
+ora_commit_write ::= WRITE IMMEDIATE.
+ora_commit_write ::= WRITE BATCH.
+ora_commit_write ::= WRITE WAIT.
+ora_commit_write ::= WRITE NOWAIT.
+ora_commit_write ::= WRITE IMMEDIATE WAIT.
+ora_commit_write ::= WRITE IMMEDIATE NOWAIT.
+ora_commit_write ::= WRITE BATCH WAIT.
+ora_commit_write ::= WRITE BATCH NOWAIT.
+
+trans_opt_kw ::= .
+trans_opt_kw ::= TRANSACTION.
+
+opt_comma ::= .
+opt_comma ::= COMMA.
+
+%type transilev {GdaTransactionIsolation}
+transilev(L) ::= ISOLATION LEVEL SERIALIZABLE. {L = GDA_TRANSACTION_ISOLATION_SERIALIZABLE;}
+transilev(L) ::= ISOLATION LEVEL REPEATABLE READ. {L = GDA_TRANSACTION_ISOLATION_REPEATABLE_READ;}
+transilev(L) ::= ISOLATION LEVEL READ COMMITTED. {L = GDA_TRANSACTION_ISOLATION_READ_COMMITTED;}
+transilev(L) ::= ISOLATION LEVEL READ UNCOMMITTED. {L = GDA_TRANSACTION_ISOLATION_READ_UNCOMMITTED;}
+
+nm_opt(R) ::= . {R = NULL;}
+nm_opt(R) ::= nm(N). {R = N;}
+
+transtype(A) ::= DEFERRED(X).  {A = X;}
+transtype(A) ::= IMMEDIATE(X). {A = X;}
+transtype(A) ::= EXCLUSIVE(X). {A = X;}
+transtype(A) ::= READ WRITE. {A = g_new0 (GValue, 1);
+			      g_value_init (A, G_TYPE_STRING);
+			      g_value_set_string (A, "READ_WRITE");
+}
+transtype(A) ::= READ ONLY. {A = g_new0 (GValue, 1);
+			     g_value_init (A, G_TYPE_STRING);
+			     g_value_set_string (A, "READ_ONLY");
+}
+
+//
+// Savepoints
+//
+cmd(C) ::= SAVEPOINT nm(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_SAVEPOINT);
+				    gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= RELEASE SAVEPOINT nm(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_DELETE_SAVEPOINT);
+				     gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= RELEASE nm(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_DELETE_SAVEPOINT);
+			   gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= ROLLBACK trans_opt_kw TO nm(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_ROLLBACK_SAVEPOINT);
+					    gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= ROLLBACK trans_opt_kw TO SAVEPOINT nm(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_ROLLBACK_SAVEPOINT);
+						      gda_sql_statement_trans_take_name (C, R);
+}
+
+//
+// INSERT
+//
+cmd(C) ::= INSERT opt_on_conflict(O) INTO fullname(X) inscollist_opt(F) VALUES LP exprlist(Y) RP. {
+	C = gda_sql_statement_new (GDA_SQL_STATEMENT_INSERT);
+	gda_sql_statement_insert_take_table_name (C, X);
+	gda_sql_statement_insert_take_fields_list (C, F);
+	gda_sql_statement_insert_take_1_values_list (C, Y);
+	gda_sql_statement_insert_take_on_conflict (C, O);
+}
+
+cmd(C) ::= INSERT opt_on_conflict(O) INTO fullname(X) inscollist_opt(F) VALUES LP exprlist(Y) RP ins_extra_values(E). {
+	C = gda_sql_statement_new (GDA_SQL_STATEMENT_INSERT);
+	gda_sql_statement_insert_take_table_name (C, X);
+	gda_sql_statement_insert_take_fields_list (C, F);
+	gda_sql_statement_insert_take_1_values_list (C, Y);
+	gda_sql_statement_insert_take_extra_values_list (C, E);
+	gda_sql_statement_insert_take_on_conflict (C, O);
+}
+
+cmd(C) ::= INSERT opt_on_conflict(O) INTO fullname(X) inscollist_opt(F) compound(S). {
+        C = gda_sql_statement_new (GDA_SQL_STATEMENT_INSERT);
+        gda_sql_statement_insert_take_table_name (C, X);
+        gda_sql_statement_insert_take_fields_list (C, F);
+        gda_sql_statement_insert_take_select (C, S);
+        gda_sql_statement_insert_take_on_conflict (C, O);
+}
+
+
+opt_on_conflict(O) ::= . {O = NULL;}
+opt_on_conflict(O) ::= OR ID(V). {O = V;}
+
+%type ins_extra_values {GSList*}
+%destructor ins_extra_values {GSList *list;
+		for (list = $$; list; list = list->next) {
+			g_slist_foreach ((GSList*) list->data, (GFunc) gda_sql_field_free, NULL); 
+			g_slist_free ((GSList*) list->data);
+		}
+		g_slist_free ($$);
+}
+ins_extra_values(E) ::= ins_extra_values(A) COMMA LP exprlist(L) RP. {E = g_slist_append (A, L);}
+ins_extra_values(E) ::= COMMA LP exprlist(L) RP. {E = g_slist_append (NULL, L);}
+
+%type inscollist_opt {GSList*}
+%destructor inscollist_opt {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_field_free, NULL); g_slist_free ($$);}}
+inscollist_opt(A) ::= .                       {A = NULL;}
+inscollist_opt(A) ::= LP inscollist(X) RP.    {A = X;}
+
+%type inscollist {GSList*}
+%destructor inscollist {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_field_free, NULL); g_slist_free ($$);}}
+inscollist(A) ::= inscollist(X) COMMA fullname(Y). {GdaSqlField *field;
+						    field = gda_sql_field_new (NULL);
+						    gda_sql_field_take_name (field, Y);
+						    A = g_slist_append (X, field);
+}
+inscollist(A) ::= fullname(Y). {GdaSqlField *field = gda_sql_field_new (NULL);
+				gda_sql_field_take_name (field, Y);
+				A = g_slist_prepend (NULL, field);
+}
+
+// DELETE
+cmd(C) ::= DELETE FROM fullname(T) where_opt(X). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_DELETE); 
+						  gda_sql_statement_delete_take_table_name (C, T);
+						  gda_sql_statement_delete_take_condition (C, X);}
+
+%type where_opt {GdaSqlExpr *}
+%destructor where_opt {gda_sql_expr_free ($$);}
+where_opt(A) ::= .                    {A = NULL;}
+where_opt(A) ::= WHERE expr(X).       {A = X;}
+
+// UPDATE
+cmd(C) ::= UPDATE opt_on_conflict(O) fullname(T) SET setlist(S) where_opt(X). {
+	GSList *list;
+	C = gda_sql_statement_new (GDA_SQL_STATEMENT_UPDATE);
+	gda_sql_statement_update_take_table_name (C, T);
+	gda_sql_statement_update_take_on_conflict (C, O);
+	gda_sql_statement_update_take_condition (C, X);
+	for (list = S; list; list = list->next) {
+		UpdateSet *set = (UpdateSet*) list->data;
+		gda_sql_statement_update_take_set_value (C, set->fname, set->expr);
+		g_free (set);
+	}
+	g_slist_free (S);
+}
+
+%type setlist {GSList*}
+%destructor setlist {GSList *list;
+	for (list = $$; list; list = list->next) {
+		UpdateSet *set = (UpdateSet*) list->data;
+		g_value_reset (set->fname); g_free (set->fname);
+		gda_sql_expr_free (set->expr);
+		g_free (set);
+	}
+	g_slist_free ($$);
+}
+setlist(A) ::= setlist(Z) COMMA fullname(X) EQ expr(Y). {UpdateSet *set;
+							 set = g_new (UpdateSet, 1);
+							 set->fname = X;
+							 set->expr = Y;
+							 A = g_slist_append (Z, set);
+}
+setlist(A) ::= fullname(X) EQ expr(Y). {UpdateSet *set;
+					set = g_new (UpdateSet, 1);
+					set->fname = X;
+					set->expr = Y;
+					A = g_slist_append (NULL, set);
+}
+
+// COMPOUND SELECT
+%type compound {GdaSqlStatement *}
+%destructor compound {gda_sql_statement_free ($$);}
+//compound(C) ::= LP compound(E) RP. {C = E;}
+compound(C) ::= selectcmd(S). {
+	C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMPOUND);
+	gda_sql_statement_compound_take_stmt (C, S);
+}
+compound(C) ::= compound(L) UNION opt_compound_all(A) compound(R). {
+	C = compose_multiple_compounds (A ? GDA_SQL_STATEMENT_COMPOUND_UNION_ALL : GDA_SQL_STATEMENT_COMPOUND_UNION,
+					L, R);
+}
+
+compound(C) ::= compound(L) EXCEPT opt_compound_all(A) compound(R). {
+	C = compose_multiple_compounds (A ? GDA_SQL_STATEMENT_COMPOUND_EXCEPT_ALL : GDA_SQL_STATEMENT_COMPOUND_EXCEPT,
+					L, R);
+} 
+
+compound(C) ::= compound(L) INTERSECT opt_compound_all(A) compound(R). {
+	C = compose_multiple_compounds (A ? GDA_SQL_STATEMENT_COMPOUND_INTERSECT_ALL : GDA_SQL_STATEMENT_COMPOUND_INTERSECT,
+					L, R);
+} 
+
+%type opt_compound_all {gboolean}
+opt_compound_all(A) ::= .    {A = FALSE;}
+opt_compound_all(A) ::= ALL. {A = TRUE;}
+
+
+// SELECT
+%type selectcmd {GdaSqlStatement *}
+%destructor selectcmd {gda_sql_statement_free ($$);}
+selectcmd(C) ::= SELECT distinct(D) selcollist(W) from(F) where_opt(Y)
+	 groupby_opt(P) having_opt(Q) orderby_opt(Z) limit_opt(L). {
+	C = gda_sql_statement_new (GDA_SQL_STATEMENT_SELECT);
+	if (D) {
+		gda_sql_statement_select_take_distinct (C, D->distinct, D->expr);
+		g_free (D);
+	}
+	gda_sql_statement_select_take_expr_list (C, W);
+	gda_sql_statement_select_take_from (C, F);
+	gda_sql_statement_select_take_where_cond (C, Y);
+	gda_sql_statement_select_take_group_by (C, P);
+	gda_sql_statement_select_take_having_cond (C, Q);
+	gda_sql_statement_select_take_order_by (C, Z);
+	gda_sql_statement_select_take_limits (C, L.count, L.offset);
+}
+
+%type limit_opt {Limit}
+%destructor limit_opt {gda_sql_expr_free ($$.count); gda_sql_expr_free ($$.offset);}
+limit_opt(A) ::= .                     {A.count = NULL; A.offset = NULL;}
+limit_opt(A) ::= LIMIT expr(X).        {A.count = X; A.offset = NULL;}
+limit_opt(A) ::= LIMIT expr(X) OFFSET expr(Y). {A.count = X; A.offset = Y;}
+limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y). {A.count = X; A.offset = Y;}
+
+%type orderby_opt {GSList *}
+%destructor orderby_opt {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_select_order_free, NULL); g_slist_free ($$);}}
+orderby_opt(A) ::= .                          {A = 0;}
+orderby_opt(A) ::= ORDER BY sortlist(X).      {A = X;}
+
+%type sortlist {GSList *}
+%destructor sortlist {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_select_order_free, NULL); g_slist_free ($$);}}
+sortlist(A) ::= sortlist(X) COMMA expr(Y) sortorder(Z). {GdaSqlSelectOrder *order;
+							 order = gda_sql_select_order_new (NULL);
+							 order->expr = Y;
+							 order->asc = Z;
+							 A = g_slist_append (X, order);
+}
+sortlist(A) ::= expr(Y) sortorder(Z). {GdaSqlSelectOrder *order;
+				       order = gda_sql_select_order_new (NULL);
+				       order->expr = Y;
+				       order->asc = Z;
+				       A = g_slist_prepend (NULL, order);
+}
+
+%type sortorder {gboolean}
+sortorder(A) ::= ASC.           {A = TRUE;}
+sortorder(A) ::= DESC.          {A = FALSE;}
+sortorder(A) ::= .              {A = TRUE;}
+
+
+%type having_opt {GdaSqlExpr *}
+%destructor having_opt {gda_sql_expr_free ($$);}
+having_opt(A) ::= .                     {A = NULL;}
+having_opt(A) ::= HAVING expr(X).       {A = X;}
+
+%type groupby_opt {GSList*}
+%destructor groupby_opt {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_expr_free, NULL); g_slist_free ($$);}}
+groupby_opt(A) ::= .                      {A = 0;}
+groupby_opt(A) ::= GROUP BY nexprlist(X). {A = X;}
+
+%type from {GdaSqlSelectFrom *}
+%destructor from {gda_sql_select_from_free ($$);}
+from(F) ::= .                   {F = NULL;}
+from(F) ::= FROM seltablist(X). {F = X;}
+
+%type seltablist {GdaSqlSelectFrom *}
+%destructor seltablist {gda_sql_select_from_free ($$);}
+%type stl_prefix {GdaSqlSelectFrom *}
+%destructor stl_prefix {gda_sql_select_from_free ($$);}
+
+seltablist(L) ::= stl_prefix(P) seltarget(T) on_cond(C) using_opt(U). {
+	GSList *last;
+	if (P)
+		L = P;
+	else 
+		L = gda_sql_select_from_new (NULL);
+	gda_sql_select_from_take_new_target (L, T);
+	last = g_slist_last (L->joins);
+	if (last) {
+		GdaSqlSelectJoin *join = (GdaSqlSelectJoin *) (last->data);
+		join->expr = C;
+		join->position = g_slist_length (L->targets) - 1;
+		join->using = U;
+	}
+}
+
+%type using_opt {GSList*}
+%destructor using_opt {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_field_free, NULL); g_slist_free ($$);}}
+using_opt(U) ::= USING LP inscollist(L) RP. {U = L;}
+using_opt(U) ::= .                          {U = NULL;}
+
+stl_prefix(P) ::= . {P = NULL;}
+stl_prefix(P) ::= seltablist(L) jointype(J). {GdaSqlSelectJoin *join;
+					      P = L;
+					      join = gda_sql_select_join_new (GDA_SQL_ANY_PART (P));
+					      join->type = J;
+					      gda_sql_select_from_take_new_join (P, join);
+}
+					      
+
+%type on_cond {GdaSqlExpr *}
+%destructor on_cond {gda_sql_expr_free ($$);}
+on_cond(N) ::= ON expr(E).  {N = E;}
+on_cond(N) ::= .            {N = NULL;}
+
+%type jointype {GdaSqlSelectJoinType}
+jointype(J) ::= COMMA. {J = GDA_SQL_SELECT_JOIN_CROSS;}
+jointype(J) ::= JOIN. {J = GDA_SQL_SELECT_JOIN_INNER;}
+jointype(J) ::= CROSS JOIN. {J = GDA_SQL_SELECT_JOIN_CROSS;}
+jointype(J) ::= INNER JOIN. {J = GDA_SQL_SELECT_JOIN_INNER;}
+jointype(J) ::= NATURAL JOIN. {J = GDA_SQL_SELECT_JOIN_NATURAL;}
+jointype(J) ::= LEFT JOIN. {J = GDA_SQL_SELECT_JOIN_LEFT;}
+jointype(J) ::= LEFT OUTER JOIN. {J = GDA_SQL_SELECT_JOIN_LEFT;}
+jointype(J) ::= RIGHT JOIN. {J = GDA_SQL_SELECT_JOIN_RIGHT;}
+jointype(J) ::= RIGHT OUTER JOIN. {J = GDA_SQL_SELECT_JOIN_RIGHT;}
+jointype(J) ::= FULL JOIN. {J = GDA_SQL_SELECT_JOIN_FULL;}
+jointype(J) ::= FULL OUTER JOIN. {J = GDA_SQL_SELECT_JOIN_FULL;}
+
+
+%type seltarget {GdaSqlSelectTarget *}
+%destructor seltarget {gda_sql_select_target_free ($$);}
+seltarget(T) ::= fullname(F) as(A). {T = gda_sql_select_target_new (NULL);
+				     gda_sql_select_target_take_alias (T, A);
+				     gda_sql_select_target_take_table_name (T, F);
+}
+seltarget(T) ::= fullname(F) ID(A). {T = gda_sql_select_target_new (NULL);
+                                     gda_sql_select_target_take_alias (T, A);
+                                     gda_sql_select_target_take_table_name (T, F);
+}
+seltarget(T) ::= LP compound(S) RP as(A). {T = gda_sql_select_target_new (NULL);
+					     gda_sql_select_target_take_alias (T, A);
+					     gda_sql_select_target_take_select (T, S);
+}
+
+%type selcollist {GSList *}
+%destructor selcollist {g_slist_foreach ($$, (GFunc) gda_sql_select_field_free, NULL); g_slist_free ($$);}
+
+%type sclp {GSList *}
+%destructor sclp {g_slist_foreach ($$, (GFunc) gda_sql_select_field_free, NULL); g_slist_free ($$);}
+sclp(A) ::= selcollist(X) COMMA.             {A = X;}
+sclp(A) ::= .                                {A = NULL;}
+
+selcollist(L) ::= sclp(E) expr(X) as(A). {GdaSqlSelectField *field;
+					  field = gda_sql_select_field_new (NULL);
+					  gda_sql_select_field_take_expr (field, X);
+					  gda_sql_select_field_take_alias (field, A); 
+					  L = g_slist_append (E, field);}
+selcollist(L) ::= sclp(E) starname(X). {GdaSqlSelectField *field;
+					field = gda_sql_select_field_new (NULL);
+					gda_sql_select_field_take_star_value (field, X);
+					L = g_slist_append (E, field);}
+
+starname(S) ::= STAR(X). {S = X;}
+starname(A) ::= nm(S) DOT STAR(X). {gchar *str;
+				  str = g_strdup_printf ("%s.%s", g_value_get_string (S), g_value_get_string (X));
+				  A = g_new0 (GValue, 1);
+				  g_value_init (A, G_TYPE_STRING);
+				  g_value_take_string (A, str);
+				  g_value_reset (S); g_free (S);
+				  g_value_reset (X); g_free (X);
+}
+
+starname(A) ::= nm(C) DOT nm(S) DOT STAR(X). {gchar *str;
+				  str = g_strdup_printf ("%s.%s.%s", g_value_get_string (C), 
+							 g_value_get_string (S), g_value_get_string (X));
+				  A = g_new0 (GValue, 1);
+				  g_value_init (A, G_TYPE_STRING);
+				  g_value_take_string (A, str);
+				  g_value_reset (C); g_free (C);
+				  g_value_reset (S); g_free (S);
+				  g_value_reset (X); g_free (X);
+}
+
+as(A) ::= AS fullname(F). {A = F;}
+as(A) ::= AS value(F). {A = F;}
+as(A) ::= . {A = NULL;}
+
+%type distinct {Distinct *}
+%destructor distinct {if ($$) {if ($$->expr) gda_sql_expr_free ($$->expr); g_free ($$);}}
+distinct(E) ::= . {E = NULL;}
+distinct(E) ::= ALL. {E = NULL;}
+distinct(E) ::= DISTINCT. {E = g_new0 (Distinct, 1); E->distinct = TRUE;}
+distinct(E) ::= DISTINCT ON expr(X). [OR] {E = g_new0 (Distinct, 1); E->distinct = TRUE; E->expr = X;}
+
+// Non empty list of expressions
+%type nexprlist {GSList *}
+%destructor nexprlist {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_expr_free, NULL); g_slist_free ($$);}}
+nexprlist(L) ::= nexprlist(E) COMMA expr(X). {L = g_slist_append (E, X);}
+nexprlist(L) ::= expr(E). {L = g_slist_append (NULL, E);}
+
+// List of expressions
+%type exprlist {GSList *}
+%destructor exprlist {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_expr_free, NULL); g_slist_free ($$);}}
+exprlist(L) ::= . {L = NULL;}
+exprlist(L) ::= exprlist(E) COMMA expr(X). {L = g_slist_append (E, X);}
+exprlist(L) ::= expr(E). {L = g_slist_append (NULL, E);}
+
+// A single expression
+%type expr {GdaSqlExpr *}
+%destructor expr {gda_sql_expr_free ($$);}
+expr(E) ::= pvalue(V). {E = V;}
+expr(E) ::= value(V). {E = gda_sql_expr_new (NULL); E->value = V;}
+expr(E) ::= LP expr(X) RP. {E = X;}
+expr(E) ::= fullname(V). {E = gda_sql_expr_new (NULL); E->value = V;}
+expr(E) ::= fullname(V) LP exprlist(A) RP. {GdaSqlFunction *func;
+					    E = gda_sql_expr_new (NULL); 
+					    func = gda_sql_function_new (GDA_SQL_ANY_PART (E)); 
+					    gda_sql_function_take_name (func, V);
+					    gda_sql_function_take_args_list (func, A);
+					    E->func = func;}
+expr(E) ::= fullname(V) LP compound(S) RP. {GdaSqlFunction *func;
+					     GdaSqlExpr *expr;
+					     E = gda_sql_expr_new (NULL); 
+					     func = gda_sql_function_new (GDA_SQL_ANY_PART (E)); 
+					     gda_sql_function_take_name (func, V);
+					     expr = gda_sql_expr_new (GDA_SQL_ANY_PART (func)); 
+					     gda_sql_expr_take_select (expr, S);
+					     gda_sql_function_take_args_list (func, g_slist_prepend (NULL, expr));
+					     E->func = func;}
+expr(E) ::= fullname(V) LP starname(A) RP. {GdaSqlFunction *func;
+					    GdaSqlExpr *expr;
+					    E = gda_sql_expr_new (NULL); 
+					    func = gda_sql_function_new (GDA_SQL_ANY_PART (E));
+					    gda_sql_function_take_name (func, V);
+					    expr = gda_sql_expr_new (GDA_SQL_ANY_PART (func)); 
+					    expr->value = A;
+					    gda_sql_function_take_args_list (func, g_slist_prepend (NULL, expr));
+					    E->func = func;}
+expr(E) ::= CAST LP expr(A) AS fullname(T) RP. {E = A;
+						A->cast_as = g_value_dup_string (T);
+						g_value_reset (T);
+						g_free (T);}
+expr(E) ::= expr(A) PGCAST fullname(T). {E = A;
+					 A->cast_as = g_value_dup_string (T);
+					 g_value_reset (T);
+					 g_free (T);}
+
+expr(C) ::= expr(L) PLUS|MINUS(O) expr(R). {C = compose_multiple_expr (string_to_op_type (O), L, R);}
+expr(C) ::= expr(L) STAR expr(R). {C = compose_multiple_expr (GDA_SQL_OPERATOR_TYPE_STAR, L, R);}
+expr(C) ::= expr(L) SLASH|REM(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
+expr(C) ::= expr(L) BITAND|BITOR(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
+
+expr(C) ::= MINUS expr(X). [UMINUS] {C = create_uni_expr (GDA_SQL_OPERATOR_TYPE_MINUS, X);}
+expr(C) ::= PLUS expr(X). [UPLUS] {C = create_uni_expr (GDA_SQL_OPERATOR_TYPE_PLUS, X);}
+
+expr(C) ::= expr(L) AND expr(R). {C = compose_multiple_expr (GDA_SQL_OPERATOR_TYPE_AND, L, R);}
+expr(C) ::= expr(L) OR expr(R). {C = compose_multiple_expr (GDA_SQL_OPERATOR_TYPE_OR, L, R);}
+expr(C) ::= expr(L) CONCAT expr(R). {C = compose_multiple_expr (GDA_SQL_OPERATOR_TYPE_CONCAT, L, R);}
+
+expr(C) ::= expr(L) GT|LEQ|GEQ|LT(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
+expr(C) ::= expr(L) DIFF|EQ(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
+expr(C) ::= expr(L) LIKE expr(R). {C = create_two_expr (GDA_SQL_OPERATOR_TYPE_LIKE, L, R);}
+expr(C) ::= expr(L) REGEXP|REGEXP_CI|NOT_REGEXP|NOT_REGEXP_CI|SIMILAR(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
+expr(C) ::= expr(L) BETWEEN expr(R) AND expr(E). {GdaSqlOperation *cond;
+						  C = gda_sql_expr_new (NULL);
+						  cond = gda_sql_operation_new (GDA_SQL_ANY_PART (C));
+						  C->cond = cond;
+						  cond->operator = GDA_SQL_OPERATOR_TYPE_BETWEEN;
+						  cond->operands = g_slist_append (NULL, L);
+						  GDA_SQL_ANY_PART (L)->parent = GDA_SQL_ANY_PART (cond);
+						  cond->operands = g_slist_append (cond->operands, R);
+						  GDA_SQL_ANY_PART (R)->parent = GDA_SQL_ANY_PART (cond);
+						  cond->operands = g_slist_append (cond->operands, E);
+						  GDA_SQL_ANY_PART (E)->parent = GDA_SQL_ANY_PART (cond);
+}
+
+expr(C) ::= expr(L) NOT BETWEEN expr(R) AND expr(E). {GdaSqlOperation *cond;
+						      GdaSqlExpr *expr;
+						      expr = gda_sql_expr_new (NULL);
+						      cond = gda_sql_operation_new (GDA_SQL_ANY_PART (expr));
+						      expr->cond = cond;
+						      cond->operator = GDA_SQL_OPERATOR_TYPE_BETWEEN;
+						      cond->operands = g_slist_append (NULL, L);
+						      GDA_SQL_ANY_PART (L)->parent = GDA_SQL_ANY_PART (cond);
+						      cond->operands = g_slist_append (cond->operands, R);
+						      GDA_SQL_ANY_PART (R)->parent = GDA_SQL_ANY_PART (cond);
+						      cond->operands = g_slist_append (cond->operands, E);
+						      GDA_SQL_ANY_PART (E)->parent = GDA_SQL_ANY_PART (cond);
+
+						      C = gda_sql_expr_new (NULL);
+						      cond = gda_sql_operation_new (GDA_SQL_ANY_PART (C));
+						      C->cond = cond;
+						      cond->operator = GDA_SQL_OPERATOR_TYPE_NOT;
+						      cond->operands = g_slist_prepend (NULL, expr);
+						      GDA_SQL_ANY_PART (expr)->parent = GDA_SQL_ANY_PART (cond);
+}
+
+expr(C) ::= NOT expr(R). {C = create_uni_expr (GDA_SQL_OPERATOR_TYPE_NOT, R);}
+expr(C) ::= BITNOT expr(R). {C = create_uni_expr (GDA_SQL_OPERATOR_TYPE_BITNOT, R);}
+expr(C) ::= expr(R) uni_op(O) . {C = create_uni_expr (O, R);}
+
+expr(C) ::= expr(L) IS expr(R). {C = create_two_expr (GDA_SQL_OPERATOR_TYPE_IS, L, R);}
+expr(E) ::= LP compound(S) RP. {E = gda_sql_expr_new (NULL); gda_sql_expr_take_select (E, S);}
+expr(E) ::= expr(R) IN LP exprlist(L) RP. {GdaSqlOperation *cond;
+					   GSList *list;
+					   E = gda_sql_expr_new (NULL);
+					   cond = gda_sql_operation_new (GDA_SQL_ANY_PART (E));
+					   E->cond = cond;
+					   cond->operator = GDA_SQL_OPERATOR_TYPE_IN;
+					   cond->operands = g_slist_prepend (L, R);
+					   for (list = cond->operands; list; list = list->next)
+						   GDA_SQL_ANY_PART (list->data)->parent = GDA_SQL_ANY_PART (cond);
+}
+expr(E) ::= expr(R) IN LP compound(S) RP. {GdaSqlOperation *cond;
+					    GdaSqlExpr *expr;
+					    E = gda_sql_expr_new (NULL);
+					    cond = gda_sql_operation_new (GDA_SQL_ANY_PART (E));
+					    E->cond = cond;
+					    cond->operator = GDA_SQL_OPERATOR_TYPE_IN;
+					    
+					    expr = gda_sql_expr_new (GDA_SQL_ANY_PART (cond));
+					    gda_sql_expr_take_select (expr, S);
+					    cond->operands = g_slist_prepend (NULL, expr);
+					    cond->operands = g_slist_prepend (cond->operands, R);
+					    GDA_SQL_ANY_PART (R)->parent = GDA_SQL_ANY_PART (cond);
+}
+expr(E) ::= expr(R) NOT IN LP exprlist(L) RP. {GdaSqlOperation *cond;
+					       GdaSqlExpr *expr;
+					       GSList *list;
+					       expr = gda_sql_expr_new (NULL);
+					       cond = gda_sql_operation_new (GDA_SQL_ANY_PART (expr));
+					       expr->cond = cond;
+					       cond->operator = GDA_SQL_OPERATOR_TYPE_IN;
+					       cond->operands = g_slist_prepend (L, R);
+					       for (list = cond->operands; list; list = list->next)
+						       GDA_SQL_ANY_PART (list->data)->parent = GDA_SQL_ANY_PART (cond);
+					       
+					       E = gda_sql_expr_new (NULL);
+					       cond = gda_sql_operation_new (GDA_SQL_ANY_PART (E));
+					       E->cond = cond;
+					       cond->operator = GDA_SQL_OPERATOR_TYPE_NOT;
+					       cond->operands = g_slist_prepend (NULL, expr);
+					       GDA_SQL_ANY_PART (expr)->parent = GDA_SQL_ANY_PART (cond);
+}
+expr(E) ::= expr(R) NOT IN LP compound(S) RP. {GdaSqlOperation *cond;
+						GdaSqlExpr *expr1, *expr2;
+						expr1 = gda_sql_expr_new (NULL);
+						cond = gda_sql_operation_new (GDA_SQL_ANY_PART (expr1));
+						expr1->cond = cond;
+						cond->operator = GDA_SQL_OPERATOR_TYPE_IN;
+						
+						expr2 = gda_sql_expr_new (NULL);
+						gda_sql_expr_take_select (expr2, S);
+						cond->operands = g_slist_prepend (NULL, expr2);
+						GDA_SQL_ANY_PART (expr2)->parent = GDA_SQL_ANY_PART (cond);
+						cond->operands = g_slist_prepend (cond->operands, R);
+						GDA_SQL_ANY_PART (R)->parent = GDA_SQL_ANY_PART (cond);
+						
+						E = gda_sql_expr_new (NULL);
+						cond = gda_sql_operation_new (GDA_SQL_ANY_PART (E));
+						E->cond = cond;
+						cond->operator = GDA_SQL_OPERATOR_TYPE_NOT;
+						cond->operands = g_slist_prepend (NULL, expr1);
+						GDA_SQL_ANY_PART (expr1)->parent = GDA_SQL_ANY_PART (cond);
+}
+expr(A) ::= CASE case_operand(X) case_exprlist(Y) case_else(Z) END. {
+	GdaSqlCase *sc;
+	GSList *list;
+	A = gda_sql_expr_new (NULL);
+	sc = gda_sql_case_new (GDA_SQL_ANY_PART (A));
+	sc->base_expr = X;
+	sc->else_expr = Z;
+	sc->when_expr_list = Y.when_list;
+	sc->then_expr_list = Y.then_list;
+	A->case_s = sc;
+	for (list = sc->when_expr_list; list; list = list->next)
+		GDA_SQL_ANY_PART (list->data)->parent = GDA_SQL_ANY_PART (sc);
+	for (list = sc->then_expr_list; list; list = list->next)
+		GDA_SQL_ANY_PART (list->data)->parent = GDA_SQL_ANY_PART (sc);
+}
+	
+%type case_operand {GdaSqlExpr*}
+%destructor case_operand {gda_sql_expr_free ($$);}
+case_operand(A) ::= expr(X).            {A = X;}
+case_operand(A) ::= .                   {A = NULL;}
+
+%type case_exprlist {CaseBody}
+%destructor case_exprlist {g_slist_foreach ($$.when_list, (GFunc) gda_sql_expr_free, NULL); g_slist_free ($$.when_list);
+	g_slist_foreach ($$.then_list, (GFunc) gda_sql_expr_free, NULL); g_slist_free ($$.then_list);}
+
+case_exprlist(A) ::= case_exprlist(X) WHEN expr(Y) THEN expr(Z). {
+	A.when_list = g_slist_append (X.when_list, Y);
+	A.then_list = g_slist_append (X.then_list, Z);
+}
+case_exprlist(A) ::= WHEN expr(Y) THEN expr(Z). {
+	A.when_list = g_slist_prepend (NULL, Y);
+	A.then_list = g_slist_prepend (NULL, Z);
+}
+
+%type case_else {GdaSqlExpr*}
+%destructor case_else {gda_sql_expr_free ($$);}
+case_else(A) ::= ELSE expr(X).       {A = X;}
+case_else(A) ::= .                   {A = NULL;}
+
+%type uni_op {GdaSqlOperatorType}
+uni_op(O) ::= ISNULL. {O = GDA_SQL_OPERATOR_TYPE_ISNULL;}
+uni_op(O) ::= IS NOTNULL. {O = GDA_SQL_OPERATOR_TYPE_ISNOTNULL;}
+
+
+// Values: for all constants (G_TYPE_STRING GValue)
+value(V) ::= NULL. {V = NULL;}
+value(V) ::= STRING(S). {V = S;}
+value(V) ::= TEXTUAL(T). {V = T;}
+value(V) ::= INTEGER(I). {V = I;}
+value(V) ::= FLOAT(F). {V = F;}
+
+// pvalue: values which are parameters (GdaSqlExpr)
+%type pvalue {GdaSqlExpr *}
+%destructor pvalue {gda_sql_expr_free ($$);}
+	pvalue(E) ::= UNSPECVAL LSBRACKET paramspec(P) RSBRACKET. {E = gda_sql_expr_new (NULL); E->param_spec = P;}
+pvalue(E) ::= value(V) LSBRACKET paramspec(P) RSBRACKET. {E = gda_sql_expr_new (NULL); E->value = V; E->param_spec = P;}
+pvalue(E) ::= SIMPLEPARAM(S). {E = gda_sql_expr_new (NULL); E->param_spec = gda_sql_param_spec_new (S);}
+
+// paramspec: parameter's specifications
+%type paramspec {GdaSqlParamSpec *}
+%destructor paramspec {gda_sql_param_spec_free ($$);}
+paramspec(P) ::= . {P = NULL;}
+paramspec(P) ::= paramspec(E) PNAME(N). {if (!E) P = gda_sql_param_spec_new (NULL); else P = E; 
+					 gda_sql_param_spec_take_name (P, N);}
+paramspec(P) ::= paramspec(E) PDESCR(N). {if (!E) P = gda_sql_param_spec_new (NULL); else P = E; 
+					 gda_sql_param_spec_take_descr (P, N);}
+paramspec(P) ::= paramspec(E) PTYPE(N). {if (!E) P = gda_sql_param_spec_new (NULL); else P = E; 
+					 gda_sql_param_spec_take_type (P, N);}
+paramspec(P) ::= paramspec(E) PNULLOK(N). {if (!E) P = gda_sql_param_spec_new (NULL); else P = E; 
+					   gda_sql_param_spec_take_nullok (P, N);}
+
+// The name of a column or table can be any of the following:
+//
+nm(A) ::= JOIN(X).       {A = X;}
+nm(A) ::= ID(X).       {A = X;}
+nm(A) ::= TEXTUAL(X). {A = X;}
+
+// Fully qualified name
+fullname(A) ::= nm(S) DOT nm(X). {gchar *str;
+				  str = g_strdup_printf ("%s.%s", g_value_get_string (S), g_value_get_string (X));
+				  A = g_new0 (GValue, 1);
+				  g_value_init (A, G_TYPE_STRING);
+				  g_value_take_string (A, str);
+				  g_value_reset (S); g_free (S);
+				  g_value_reset (X); g_free (X);
+}
+
+fullname(A) ::= nm(C) DOT nm(S) DOT nm(X). {gchar *str;
+				  str = g_strdup_printf ("%s.%s.%s", g_value_get_string (C), 
+							 g_value_get_string (S), g_value_get_string (X));
+				  A = g_new0 (GValue, 1);
+				  g_value_init (A, G_TYPE_STRING);
+				  g_value_take_string (A, str);
+				  g_value_reset (C); g_free (C);
+				  g_value_reset (S); g_free (S);
+				  g_value_reset (X); g_free (X);
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]