[libgda] Correclty handle variables set to DEFAULT when executing a statement



commit 93720d40478ef030f3b87d37b5a33cd43ac8139d
Author: Vivien Malerba <malerba gnome-db org>
Date:   Wed Jul 21 17:10:18 2010 +0200

    Correclty handle variables set to DEFAULT when executing a statement
    
    this is necessary when a statement containing variables is executed
    and when some of the variables are set to a default value (which
    is not compatible with the variable type and can not be bound normally).
    In this case the statement is re-written and executed.

 doc/C/libgda-sections.txt                          |    2 +
 doc/C/tmpl/gda-server-provider.sgml                |    2 +
 doc/C/tmpl/provider-support.sgml                   |   12 +
 libgda/gda-server-provider.h                       |   10 +-
 libgda/gda-util.c                                  |  235 +++++++++++++++++++-
 libgda/gda-util.h                                  |    5 +-
 libgda/libgda.symbols                              |    1 +
 libgda/sqlite/gda-sqlite-provider.c                |   50 ++++
 providers/jdbc/gda-jdbc-provider.c                 |   50 ++++
 providers/mysql/gda-mysql-provider.c               |   48 ++++
 providers/oracle/gda-oracle-provider.c             |   48 ++++
 providers/postgres/gda-postgres-provider.c         |   58 +++++
 .../skel-implementation/capi/gda-capi-provider.c   |   54 +++++
 providers/web/gda-web-provider.c                   |   53 +++++
 tests/parser/.gitignore                            |    3 +-
 tests/parser/Makefile.am                           |   10 +-
 tests/parser/check_rewrite_for_default.c           |  121 ++++++++++
 17 files changed, 752 insertions(+), 10 deletions(-)
---
diff --git a/doc/C/libgda-sections.txt b/doc/C/libgda-sections.txt
index a6abc7b..39b5cc0 100644
--- a/doc/C/libgda-sections.txt
+++ b/doc/C/libgda-sections.txt
@@ -1487,6 +1487,8 @@ gda_compute_unique_table_row_condition
 gda_compute_unique_table_row_condition_with_cnc
 <SUBSECTION>
 gda_sql_any_part_check_structure
+<SUBSECTION>
+gda_statement_rewrite_for_default_values
 </SECTION>
 
 <SECTION>
diff --git a/doc/C/tmpl/gda-server-provider.sgml b/doc/C/tmpl/gda-server-provider.sgml
index e7a91fe..5a9895b 100644
--- a/doc/C/tmpl/gda-server-provider.sgml
+++ b/doc/C/tmpl/gda-server-provider.sgml
@@ -70,6 +70,7 @@ Base class for all the DBMS providers
 @xa_funcs: 
 @identifier_quote: 
 @handle_async: 
+ statement_rewrite: 
 
 <!-- ##### ENUM GdaServerProviderError ##### -->
 <para>
@@ -87,6 +88,7 @@ Base class for all the DBMS providers
 @GDA_SERVER_PROVIDER_NON_SUPPORTED_ERROR: 
 @GDA_SERVER_PROVIDER_SERVER_VERSION_ERROR: 
 @GDA_SERVER_PROVIDER_DATA_ERROR: 
+ GDA_SERVER_PROVIDER_DEFAULT_VALUE_HANDLING_ERROR: 
 
 <!-- ##### MACRO GDA_SERVER_PROVIDER_ERROR ##### -->
 <para>
diff --git a/doc/C/tmpl/provider-support.sgml b/doc/C/tmpl/provider-support.sgml
index 1e852ff..4b0f0d3 100644
--- a/doc/C/tmpl/provider-support.sgml
+++ b/doc/C/tmpl/provider-support.sgml
@@ -466,3 +466,15 @@ Methods dedicated to implementing providers
 @Returns: 
 
 
+<!-- ##### FUNCTION gda_statement_rewrite_for_default_values ##### -->
+<para>
+
+</para>
+
+ stmt: 
+ params: 
+ remove: 
+ error: 
+ Returns: 
+
+
diff --git a/libgda/gda-server-provider.h b/libgda/gda-server-provider.h
index de16cfe..81d4a44 100644
--- a/libgda/gda-server-provider.h
+++ b/libgda/gda-server-provider.h
@@ -57,7 +57,8 @@ typedef enum
 	GDA_SERVER_PROVIDER_BUSY_ERROR,
 	GDA_SERVER_PROVIDER_NON_SUPPORTED_ERROR,
 	GDA_SERVER_PROVIDER_SERVER_VERSION_ERROR,
-	GDA_SERVER_PROVIDER_DATA_ERROR
+	GDA_SERVER_PROVIDER_DATA_ERROR,
+	GDA_SERVER_PROVIDER_DEFAULT_VALUE_HANDLING_ERROR
 } GdaServerProviderError;
 
 struct _GdaServerProvider {
@@ -306,12 +307,13 @@ struct _GdaServerProviderClass {
 							 const gchar *id,
 							 gboolean for_meta_store, gboolean force_quotes);
 
-	/* Async. handling@ */
-	gboolean                (*handle_async)          (GdaServerProvider *provider, GdaConnection *cnc, GError **error);
+	/* Async. handling */
+	gboolean                (*handle_async)         (GdaServerProvider *provider, GdaConnection *cnc, GError **error);
 
+	GdaSqlStatement        *(*statement_rewrite)    (GdaServerProvider *provider, GdaConnection *cnc,
+							 GdaStatement *stmt, GdaSet *params, GError **error);
 	/*< private >*/
 	/* Padding for future expansion */
-	void                    (*_gda_reserved3)        (void);
 	void                    (*_gda_reserved4)        (void);
 	void                    (*_gda_reserved5)        (void);
 	void                    (*_gda_reserved6)        (void);
diff --git a/libgda/gda-util.c b/libgda/gda-util.c
index b92ea32..2ecb247 100644
--- a/libgda/gda-util.c
+++ b/libgda/gda-util.c
@@ -1,5 +1,5 @@
 /* GDA common library
- * Copyright (C) 1998 - 2009 The GNOME Foundation.
+ * Copyright (C) 1998 - 2010 The GNOME Foundation.
  *
  * AUTHORS:
  *	Rodrigo Moya <rodrigo gnome-db org>
@@ -38,6 +38,8 @@
 #endif
 #include <libgda/sql-parser/gda-sql-statement.h>
 #include <sql-parser/gda-statement-struct-util.h>
+#include <libgda/gda-set.h>
+#include <libgda/gda-blob-op.h>
 
 #include <libgda/binreloc/gda-binreloc.h>
 
@@ -409,7 +411,7 @@ gda_utility_data_model_dump_data_to_xml (GdaDataModel *model, xmlNodePtr parent,
 							const GdaBinary *bin = &(blob->data);
 							if (blob->op && 
 							    (bin->binary_length != gda_blob_op_get_length (blob->op)))
-								gda_blob_op_read_all (blob->op, blob);
+								gda_blob_op_read_all (blob->op, (GdaBlob*) blob);
 						}
 						str = gda_value_stringify (value);
 					}
@@ -1201,6 +1203,235 @@ gda_compute_select_statement_from_update (GdaStatement *update_stmt, GError **er
 	return sel_stmt;
 }
 
+static gboolean stmt_rewrite_insert_remove (GdaSqlStatementInsert *ins, GdaSet *params, GError **error);
+static gboolean stmt_rewrite_insert_default_keyword (GdaSqlStatementInsert *ins, GdaSet *params, GError **error);
+static gboolean stmt_rewrite_update_default_keyword (GdaSqlStatementUpdate *upd, GdaSet *params, GError **error);
+
+
+/**
+ * gda_statement_rewrite_for_default_values
+ * @stmt: a #GdaStatement object
+ * @params: a #GdaSet containing the variable's values to be bound when executing @stmt
+ * @remove: set to %TRUE if DEFAULT fields are removed, of %FALSE if the "DEFAULT" keyword is used
+ * @error: a place to store errors, or %NULL
+ *
+ * Rewrites @stmt and creates a new #GdaSqlStatement where all the variables which are to a DEFAULT value
+ * (as returned by gda_holder_value_is_default()) are either removed from the statement (if @remove
+ * is %TRUE) or replaced by the "DEFAULT" keyword (if @remove is %FALSE).
+ *
+ * This function is only usefull for database providers' implementations which have to deal with default
+ * values when executing statements, and is only relevant in the case of INSERT or UPDATE statements
+ * (in the latter case an error is returned if @remove is %TRUE).
+ *
+ * For example the <programlisting><![CDATA[INSERT INTO mytable (id, name) VALUES (23, ##name::string)]]></programlisting>
+ * is re-written into <programlisting><![CDATA[INSERT INTO mytable (id, name) VALUES (23, DEFAULT)]]></programlisting>
+ * if @remove is %FALSE and into <programlisting><![CDATA[INSERT INTO mytable (id) VALUES (23)]]></programlisting>
+ * if @remove is %TRUE.
+ *
+ * Returns: a new #GdaSqlStatement, or %NULL if an error occurred
+ *
+ * Since: 4.2
+ */
+GdaSqlStatement *
+gda_statement_rewrite_for_default_values (GdaStatement *stmt, GdaSet *params, gboolean remove, GError **error)
+{
+	GdaSqlStatement *sqlst;
+	GdaSqlStatementType type;
+	gboolean ok = FALSE;
+	g_return_val_if_fail (GDA_IS_STATEMENT (stmt), NULL);
+	g_return_val_if_fail (GDA_IS_SET (params), NULL);
+	type = gda_statement_get_statement_type (stmt);
+
+	g_object_get (stmt, "structure", &sqlst, NULL);
+	if (! gda_sql_statement_check_structure (sqlst, error)) {
+		gda_sql_statement_free (sqlst);
+		return NULL;		
+	}
+
+	switch (type) {
+	case GDA_SQL_STATEMENT_INSERT:
+		if (remove)
+			ok = stmt_rewrite_insert_remove ((GdaSqlStatementInsert*) sqlst->contents,
+							 params, error);
+		else
+			ok = stmt_rewrite_insert_default_keyword ((GdaSqlStatementInsert*) sqlst->contents,
+								  params, error);
+		break;
+	case GDA_SQL_STATEMENT_UPDATE:
+		if (remove)
+			g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+				     GDA_SERVER_PROVIDER_DEFAULT_VALUE_HANDLING_ERROR,
+				     _("Can't rewrite UPDATE statement to handle default values"));
+		else
+			ok = stmt_rewrite_update_default_keyword ((GdaSqlStatementUpdate*) sqlst->contents,
+								  params, error);
+		break;
+	default:
+		g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+			     GDA_SERVER_PROVIDER_DEFAULT_VALUE_HANDLING_ERROR,
+			     "Can't rewrite statement is not INSERT or UPDATE");
+		break;
+	}
+
+	if (ok)
+		return sqlst;
+	else {
+		gda_sql_statement_free (sqlst);
+		return NULL;
+	}
+}
+
+/*
+ * Modifies @ins
+ * Returns: TRUE if rewrite is Ok
+ */
+static gboolean
+stmt_rewrite_insert_remove (GdaSqlStatementInsert *ins, GdaSet *params, GError **error)
+{
+	if (!ins->values_list)
+		/* nothing to do */
+		return TRUE;
+
+	if (ins->values_list->next) {
+		TO_IMPLEMENT;
+		g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+			     GDA_SERVER_PROVIDER_DEFAULT_VALUE_HANDLING_ERROR,
+			     "Not yet implemented");
+		return FALSE;
+	}
+
+	GSList *fields, *values;
+	for (fields = ins->fields_list, values = (GSList*) ins->values_list->data;
+	     fields && values; ){
+		GdaHolder *h;
+		GdaSqlExpr *expr = (GdaSqlExpr*) values->data;
+		if (! expr->param_spec || ! expr->param_spec->is_param) {
+			fields = fields->next;
+			values = values->next;
+			continue;
+		}
+		h = gda_set_get_holder (params, expr->param_spec->name);
+		if (!h) {
+			gchar *str;
+			str = g_strdup_printf (_("Missing parameter '%s' to execute query"),
+					       expr->param_spec->name);
+			g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+				     GDA_SERVER_PROVIDER_MISSING_PARAM_ERROR,
+				     "%s", str);
+			g_free (str);
+			return FALSE;
+		}
+
+		if (gda_holder_value_is_default (h)) {
+			GSList *tmp;
+			
+			gda_sql_field_free ((GdaSqlField*) fields->data);
+			tmp = fields->next;
+			ins->fields_list = g_slist_delete_link (ins->fields_list, fields);
+			fields = tmp;
+			
+			gda_sql_expr_free (expr);
+			tmp = values->next;
+			ins->values_list->data = g_slist_delete_link ((GSList*) ins->values_list->data,
+								      values);
+			values = tmp;
+		}
+		else {
+			fields = fields->next;
+			values = values->next;
+		}
+	}
+
+	if (! ins->values_list->data) {
+		g_slist_free (ins->values_list);
+		ins->values_list = NULL;
+	}
+
+	return TRUE;
+}
+
+/*
+ * Modifies @ins
+ * Returns: TRUE if rewrite is Ok
+ */
+static gboolean
+stmt_rewrite_insert_default_keyword (GdaSqlStatementInsert *ins, GdaSet *params, GError **error)
+{
+	GSList *llist;
+	for (llist = ins->values_list; llist; llist = llist->next) {
+		GSList *values;
+		for (values = (GSList*) llist->data;
+		     values;
+		     values = values->next){
+			GdaHolder *h;
+			GdaSqlExpr *expr = (GdaSqlExpr*) values->data;
+			if (! expr->param_spec || ! expr->param_spec->is_param)
+				continue;
+			h = gda_set_get_holder (params, expr->param_spec->name);
+			if (!h) {
+				gchar *str;
+				str = g_strdup_printf (_("Missing parameter '%s' to execute query"),
+						       expr->param_spec->name);
+				g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+					     GDA_SERVER_PROVIDER_MISSING_PARAM_ERROR,
+					     "%s", str);
+				g_free (str);
+				return FALSE;
+			}
+			
+			if (gda_holder_value_is_default (h)) {
+				GdaSqlExpr *nexpr;
+				nexpr = gda_sql_expr_new (GDA_SQL_ANY_PART (ins));
+				g_value_set_string ((nexpr->value = gda_value_new (G_TYPE_STRING)),
+						    "DEFAULT");
+				gda_sql_expr_free ((GdaSqlExpr*) values->data);
+				values->data = nexpr;
+			}
+		}
+	}
+
+	if (! ins->values_list->data) {
+		g_slist_free (ins->values_list);
+		ins->values_list = NULL;
+	}
+
+	return TRUE;
+}
+
+static gboolean
+stmt_rewrite_update_default_keyword (GdaSqlStatementUpdate *upd, GdaSet *params, GError **error)
+{
+	GSList *values;
+	for (values = upd->expr_list; values; values = values->next) {
+		GdaHolder *h;
+		GdaSqlExpr *expr = (GdaSqlExpr*) values->data;
+		if (! expr->param_spec || ! expr->param_spec->is_param)
+			continue;
+		h = gda_set_get_holder (params, expr->param_spec->name);
+		if (!h) {
+			gchar *str;
+			str = g_strdup_printf (_("Missing parameter '%s' to execute query"),
+					       expr->param_spec->name);
+			g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+				     GDA_SERVER_PROVIDER_MISSING_PARAM_ERROR,
+				     "%s", str);
+			g_free (str);
+			return FALSE;
+		}
+		
+		if (gda_holder_value_is_default (h)) {
+			GdaSqlExpr *nexpr;
+			nexpr = gda_sql_expr_new (GDA_SQL_ANY_PART (upd));
+			g_value_set_string ((nexpr->value = gda_value_new (G_TYPE_STRING)),
+					    "DEFAULT");
+			gda_sql_expr_free ((GdaSqlExpr*) values->data);
+			values->data = nexpr;
+		}
+	}
+
+	return TRUE;
+}
+
 /**
  * gda_identifier_hash
  * @id: an identifier string
diff --git a/libgda/gda-util.h b/libgda/gda-util.h
index fc8a052..cd4fec1 100644
--- a/libgda/gda-util.h
+++ b/libgda/gda-util.h
@@ -1,5 +1,5 @@
 /* GDA common library
- * Copyright (C) 1998 - 2009 The GNOME Foundation.
+ * Copyright (C) 1998 - 2010 The GNOME Foundation.
  *
  * AUTHORS:
  *	Rodrigo Moya <rodrigo gnome-db org>
@@ -61,6 +61,9 @@ gboolean     gda_utility_data_model_dump_data_to_xml (GdaDataModel *model, xmlNo
 const gchar *gda_utility_data_model_find_column_description (GdaDataSelect *model, const gchar *field_name);
 gboolean     gda_utility_holder_load_attributes (GdaHolder *holder, xmlNodePtr node, GSList *sources, GError **error);
 
+GdaSqlStatement *gda_statement_rewrite_for_default_values (GdaStatement *stmt, GdaSet *params,
+							   gboolean remove, GError **error);
+
 /* 
  * translate any text to an alphanumerical text 
  */
diff --git a/libgda/libgda.symbols b/libgda/libgda.symbols
index f48b266..4144617 100644
--- a/libgda/libgda.symbols
+++ b/libgda/libgda.symbols
@@ -764,6 +764,7 @@
 	gda_statement_model_usage_get_type
 	gda_statement_new
 	gda_statement_normalize
+	gda_statement_rewrite_for_default_values
 	gda_statement_serialize
 	gda_statement_sql_flag_get_type
 	gda_statement_to_sql_extended
diff --git a/libgda/sqlite/gda-sqlite-provider.c b/libgda/sqlite/gda-sqlite-provider.c
index 27b7d5d..0ac4642 100644
--- a/libgda/sqlite/gda-sqlite-provider.c
+++ b/libgda/sqlite/gda-sqlite-provider.c
@@ -261,6 +261,8 @@ static GObject             *gda_sqlite_provider_statement_execute (GdaServerProv
 								   GType *col_types, GdaSet **last_inserted_row, 
 								   guint *task_id, GdaServerProviderExecCallback async_cb, 
 								   gpointer cb_data, GError **error);
+static GdaSqlStatement     *gda_sqlite_statement_rewrite          (GdaServerProvider *provider, GdaConnection *cnc,
+								   GdaStatement *stmt, GdaSet *params, GError **error);
 
 /* string escaping */
 static gchar               *gda_sqlite_provider_escape_string (GdaServerProvider *provider, GdaConnection *cnc,
@@ -379,6 +381,7 @@ gda_sqlite_provider_class_init (GdaSqliteProviderClass *klass)
 	provider_class->statement_to_sql = gda_sqlite_provider_statement_to_sql;
 	provider_class->statement_prepare = gda_sqlite_provider_statement_prepare;
 	provider_class->statement_execute = gda_sqlite_provider_statement_execute;
+	provider_class->statement_rewrite = gda_sqlite_statement_rewrite;
 
 	provider_class->escape_string = gda_sqlite_provider_escape_string;
 	provider_class->unescape_string = gda_sqlite_provider_unescape_string;
@@ -2457,6 +2460,37 @@ gda_sqlite_provider_statement_execute (GdaServerProvider *provider, GdaConnectio
 				continue;
 			}
 		}
+		else if (gda_holder_value_is_default (h) && !gda_holder_get_value (h)) {
+			/* create a new GdaStatement to handle all default values and execute it instead */
+			GdaSqlStatement *sqlst;
+			GError *lerror = NULL;
+			sqlst = gda_statement_rewrite_for_default_values (stmt, params, TRUE, &lerror);
+			if (!sqlst) {
+				event = gda_connection_point_available_event (cnc,
+									      GDA_CONNECTION_EVENT_ERROR);
+				gda_connection_event_set_description (event, lerror && lerror->message ? 
+								      lerror->message :
+								      _("Can't rewrite statement handle default values"));
+				g_propagate_error (error, lerror);
+				break;
+			}
+			
+			GdaStatement *rstmt;
+			GObject *res;
+			rstmt = g_object_new (GDA_TYPE_STATEMENT, "structure", sqlst, NULL);
+			gda_sql_statement_free (sqlst);
+			if (new_ps)
+				g_object_unref (ps);
+			pending_blobs_free_list (blobs_list);
+			res = gda_sqlite_provider_statement_execute (provider, cnc,
+								     rstmt, params,
+								     model_usage,
+								     col_types, last_inserted_row,
+								     task_id,
+								     async_cb, cb_data, error);
+			g_object_unref (rstmt);
+			return res;
+		}
 		/*g_print ("BINDING param '%s' to %p\n", pname, h);*/
 		
 		const GValue *value = gda_holder_get_value (h);
@@ -2743,6 +2777,22 @@ gda_sqlite_provider_statement_execute (GdaServerProvider *provider, GdaConnectio
 	}
 }
 
+/*
+ * Rewrites a statement in case some parameters in @params are set to DEFAULT, for INSERT or UPDATE statements
+ *
+ * Removes any default value inserted or updated
+ */
+static GdaSqlStatement *
+gda_sqlite_statement_rewrite (GdaServerProvider *provider, GdaConnection *cnc,
+			      GdaStatement *stmt, GdaSet *params, GError **error)
+{
+	if (cnc) {
+		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+		g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
+	}
+	return gda_statement_rewrite_for_default_values (stmt, params, TRUE, error);
+}
+
 /* 
  * SQLite's extra functions' implementations
  */
diff --git a/providers/jdbc/gda-jdbc-provider.c b/providers/jdbc/gda-jdbc-provider.c
index d00c193..88a4800 100644
--- a/providers/jdbc/gda-jdbc-provider.c
+++ b/providers/jdbc/gda-jdbc-provider.c
@@ -113,6 +113,9 @@ static GObject             *gda_jdbc_provider_statement_execute (GdaServerProvid
 								 GType *col_types, GdaSet **last_inserted_row, 
 								 guint *task_id, GdaServerProviderExecCallback async_cb, 
 								 gpointer cb_data, GError **error);
+static GdaSqlStatement     *gda_jdbc_statement_rewrite          (GdaServerProvider *provider, GdaConnection *cnc,
+								 GdaStatement *stmt, GdaSet *params, GError **error);
+
 
 /* distributed transactions */
 static gboolean gda_jdbc_provider_xa_start    (GdaServerProvider *provider, GdaConnection *cnc, 
@@ -191,6 +194,7 @@ gda_jdbc_provider_class_init (GdaJdbcProviderClass *klass)
 						  * because it only calls gda_statement_to_sql_extended() */
 	provider_class->statement_prepare = gda_jdbc_provider_statement_prepare;
 	provider_class->statement_execute = gda_jdbc_provider_statement_execute;
+	provider_class->statement_rewrite = gda_jdbc_statement_rewrite;
 
 	provider_class->is_busy = NULL;
 	provider_class->cancel = NULL;
@@ -1365,6 +1369,36 @@ gda_jdbc_provider_statement_execute (GdaServerProvider *provider, GdaConnection
                                 continue;
                         }
 		}
+		else if (gda_holder_value_is_default (h) && !gda_holder_get_value (h)) {
+			/* create a new GdaStatement to handle all default values and execute it instead */
+			GdaSqlStatement *sqlst;
+			GError *lerror = NULL;
+			sqlst = gda_statement_rewrite_for_default_values (stmt, params, TRUE, &lerror);
+			if (!sqlst) {
+				event = gda_connection_point_available_event (cnc,
+									      GDA_CONNECTION_EVENT_ERROR);
+				gda_connection_event_set_description (event, lerror && lerror->message ? 
+								      lerror->message :
+								      _("Can't rewrite statement handle default values"));
+				g_propagate_error (error, lerror);
+				break;
+			}
+			
+			GdaStatement *rstmt;
+			GObject *res;
+			rstmt = g_object_new (GDA_TYPE_STATEMENT, "structure", sqlst, NULL);
+			gda_sql_statement_free (sqlst);
+			g_object_unref (ps);
+			_gda_jdbc_release_jenv (jni_detach);
+			res = gda_jdbc_provider_statement_execute (provider, cnc,
+								   rstmt, params,
+								   model_usage,
+								   col_types, last_inserted_row,
+								   task_id,
+								   async_cb, cb_data, error);
+			g_object_unref (rstmt);
+			return res;
+		}
 
 		/* actual binding using the C API, for parameter at position @i */
 		const GValue *value = gda_holder_get_value (h);
@@ -1509,6 +1543,22 @@ gda_jdbc_provider_statement_execute (GdaServerProvider *provider, GdaConnection
 }
 
 /*
+ * Rewrites a statement in case some parameters in @params are set to DEFAULT, for INSERT or UPDATE statements
+ *
+ * Safely removes any default value inserted or updated
+ */
+static GdaSqlStatement *
+gda_jdbc_statement_rewrite (GdaServerProvider *provider, GdaConnection *cnc,
+			    GdaStatement *stmt, GdaSet *params, GError **error)
+{
+	if (cnc) {
+		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+		g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
+	}
+	return gda_statement_rewrite_for_default_values (stmt, params, TRUE, error);
+}
+
+/*
  * starts a distributed transaction: put the XA transaction in the ACTIVE state
  */
 static gboolean
diff --git a/providers/mysql/gda-mysql-provider.c b/providers/mysql/gda-mysql-provider.c
index 9899a42..08f5c6e 100644
--- a/providers/mysql/gda-mysql-provider.c
+++ b/providers/mysql/gda-mysql-provider.c
@@ -177,6 +177,9 @@ static GObject             *gda_mysql_provider_statement_execute (GdaServerProvi
 								  GdaServerProviderExecCallback    async_cb, 
 								  gpointer                         cb_data,
 								  GError                         **error);
+static GdaSqlStatement     *gda_mysql_statement_rewrite          (GdaServerProvider *provider, GdaConnection *cnc,
+								  GdaStatement *stmt, GdaSet *params, GError **error);
+
 
 /* Quoting */
 static gchar               *gda_mysql_identifier_quote    (GdaServerProvider *provider, GdaConnection *cnc,
@@ -282,6 +285,7 @@ gda_mysql_provider_class_init (GdaMysqlProviderClass  *klass)
 	provider_class->statement_to_sql = gda_mysql_provider_statement_to_sql;
 	provider_class->statement_prepare = gda_mysql_provider_statement_prepare;
 	provider_class->statement_execute = gda_mysql_provider_statement_execute;
+	provider_class->statement_rewrite = gda_mysql_statement_rewrite;
 
 	provider_class->is_busy = NULL;
 	provider_class->cancel = NULL;
@@ -2107,6 +2111,35 @@ gda_mysql_provider_statement_execute (GdaServerProvider               *provider,
                                 continue;
                         }
 		}
+		else if (gda_holder_value_is_default (h) && !gda_holder_get_value (h)) {
+			/* create a new GdaStatement to handle all default values and execute it instead */
+			GdaSqlStatement *sqlst;
+			GError *lerror = NULL;
+			sqlst = gda_statement_rewrite_for_default_values (stmt, params, FALSE, &lerror);
+			if (!sqlst) {
+				event = gda_connection_point_available_event (cnc,
+									      GDA_CONNECTION_EVENT_ERROR);
+				gda_connection_event_set_description (event, lerror && lerror->message ? 
+								      lerror->message :
+								      _("Can't rewrite statement handle default values"));
+				g_propagate_error (error, lerror);
+				break;
+			}
+			
+			GdaStatement *rstmt;
+			GObject *res;
+			rstmt = g_object_new (GDA_TYPE_STATEMENT, "structure", sqlst, NULL);
+			gda_sql_statement_free (sqlst);
+			free_bind_param_data (mem_to_free);
+			res = gda_mysql_provider_statement_execute (provider, cnc,
+								    rstmt, params,
+								    model_usage,
+								    col_types, last_inserted_row,
+								    task_id,
+								    async_cb, cb_data, error);
+			g_object_unref (rstmt);
+			return res;
+		}
 
 		/* actual binding using the C API, for parameter at position @i */
 		const GValue *value = gda_holder_get_value (h);
@@ -2414,6 +2447,21 @@ gda_mysql_provider_statement_execute (GdaServerProvider               *provider,
 }
 
 /*
+ * Rewrites a statement in case some parameters in @params are set to DEFAULT, for INSERT or UPDATE statements
+ */
+static GdaSqlStatement *
+gda_mysql_statement_rewrite (GdaServerProvider *provider, GdaConnection *cnc,
+			     GdaStatement *stmt, GdaSet *params, GError **error)
+{
+	if (cnc) {
+		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+		g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
+	}
+	return gda_statement_rewrite_for_default_values (stmt, params, FALSE, error);
+}
+
+
+/*
  * starts a distributed transaction: put the XA transaction in the ACTIVE state
  */
 static gboolean
diff --git a/providers/oracle/gda-oracle-provider.c b/providers/oracle/gda-oracle-provider.c
index ec607b8..653ac12 100644
--- a/providers/oracle/gda-oracle-provider.c
+++ b/providers/oracle/gda-oracle-provider.c
@@ -117,6 +117,8 @@ static GObject             *gda_oracle_provider_statement_execute (GdaServerProv
 								 GType *col_types, GdaSet **last_inserted_row, 
 								 guint *task_id, GdaServerProviderExecCallback async_cb, 
 								 gpointer cb_data, GError **error);
+static GdaSqlStatement     *gda_oracle_statement_rewrite (GdaServerProvider *provider, GdaConnection *cnc,
+							  GdaStatement *stmt, GdaSet *params, GError **error);
 
 /* Quoting */
 static gchar               *gda_oracle_identifier_quote    (GdaServerProvider *provider, GdaConnection *cnc,
@@ -199,6 +201,7 @@ gda_oracle_provider_class_init (GdaOracleProviderClass *klass)
 	provider_class->statement_to_sql = gda_oracle_provider_statement_to_sql;
 	provider_class->statement_prepare = gda_oracle_provider_statement_prepare;
 	provider_class->statement_execute = gda_oracle_provider_statement_execute;
+	provider_class->statement_rewrite = gda_oracle_statement_rewrite;
 
 	provider_class->is_busy = NULL;
 	provider_class->cancel = NULL;
@@ -1834,6 +1837,35 @@ gda_oracle_provider_statement_execute (GdaServerProvider *provider, GdaConnectio
                                 empty_rs = TRUE;
                         }
 		}
+		else if (gda_holder_value_is_default (h) && !gda_holder_get_value (h)) {
+			/* create a new GdaStatement to handle all default values and execute it instead */
+			GdaSqlStatement *sqlst;
+			GError *lerror = NULL;
+			sqlst = gda_statement_rewrite_for_default_values (stmt, params, FALSE, &lerror);
+			if (!sqlst) {
+				event = gda_connection_point_available_event (cnc,
+									      GDA_CONNECTION_EVENT_ERROR);
+				gda_connection_event_set_description (event, lerror && lerror->message ? 
+								      lerror->message :
+								      _("Can't rewrite statement handle default values"));
+				g_propagate_error (error, lerror);
+				break;
+			}
+			
+			GdaStatement *rstmt;
+			GObject *res;
+			rstmt = g_object_new (GDA_TYPE_STATEMENT, "structure", sqlst, NULL);
+			gda_sql_statement_free (sqlst);
+			g_object_unref (ps);
+			res = gda_oracle_provider_statement_execute (provider, cnc,
+								     rstmt, params,
+								     model_usage,
+								     col_types, last_inserted_row,
+								     task_id,
+								     async_cb, cb_data, error);
+			g_object_unref (rstmt);
+			return res;
+		}
 
 		/* actual binding using the C API, for parameter at position @i */
 		if (!ora_value) {
@@ -2057,6 +2089,22 @@ gda_oracle_provider_statement_execute (GdaServerProvider *provider, GdaConnectio
 }
 
 /*
+ * Rewrites a statement in case some parameters in @params are set to DEFAULT, for INSERT or UPDATE statements
+ *
+ * Uses the DEFAULT keyword
+ */
+static GdaSqlStatement *
+gda_oracle_statement_rewrite (GdaServerProvider *provider, GdaConnection *cnc,
+			      GdaStatement *stmt, GdaSet *params, GError **error)
+{
+	if (cnc) {
+		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+		g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
+	}
+	return gda_statement_rewrite_for_default_values (stmt, params, FALSE, error);
+}
+
+/*
  * starts a distributed transaction: put the XA transaction in the ACTIVE state
  */
 static gboolean
diff --git a/providers/postgres/gda-postgres-provider.c b/providers/postgres/gda-postgres-provider.c
index 909aa94..35c1c30 100644
--- a/providers/postgres/gda-postgres-provider.c
+++ b/providers/postgres/gda-postgres-provider.c
@@ -125,6 +125,10 @@ static gchar               *gda_postgresql_identifier_quote    (GdaServerProvide
 								const gchar *id,
 								gboolean meta_store_convention, gboolean force_quotes);
 
+static GdaSqlStatement     *gda_postgresql_statement_rewrite   (GdaServerProvider *provider, GdaConnection *cnc,
+								GdaStatement *stmt, GdaSet *params, GError **error);
+
+
 /* distributed transactions */
 static gboolean gda_postgres_provider_xa_start    (GdaServerProvider *provider, GdaConnection *cnc,
 						   const GdaXaTransactionId *xid, GError **error);
@@ -217,6 +221,8 @@ gda_postgres_provider_class_init (GdaPostgresProviderClass *klass)
 	provider_class->statement_prepare = gda_postgres_provider_statement_prepare;
 	provider_class->statement_execute = gda_postgres_provider_statement_execute;
 
+	provider_class->statement_rewrite = gda_postgresql_statement_rewrite;
+
 	memset (&(provider_class->meta_funcs), 0, sizeof (GdaServerProviderMeta));
 	provider_class->meta_funcs._info = _gda_postgres_meta__info;
 	provider_class->meta_funcs._btypes = _gda_postgres_meta__btypes;
@@ -1988,6 +1994,39 @@ gda_postgres_provider_statement_execute (GdaServerProvider *provider, GdaConnect
 				continue;
 			}
 		}
+		else if (gda_holder_value_is_default (h) && !gda_holder_get_value (h)) {
+			/* create a new GdaStatement to handle all default values and execute it instead */
+			GdaSqlStatement *sqlst;
+			GError *lerror = NULL;
+			sqlst = gda_statement_rewrite_for_default_values (stmt, params, FALSE, &lerror);
+			if (!sqlst) {
+				event = gda_connection_point_available_event (cnc,
+									      GDA_CONNECTION_EVENT_ERROR);
+				gda_connection_event_set_description (event, lerror && lerror->message ? 
+								      lerror->message :
+								      _("Can't rewrite statement handle default values"));
+				g_propagate_error (error, lerror);
+				break;
+			}
+
+			GdaStatement *rstmt;
+			GObject *res;
+			rstmt = g_object_new (GDA_TYPE_STATEMENT, "structure", sqlst, NULL);
+			gda_sql_statement_free (sqlst);
+			params_freev (param_values, param_mem, nb_params);
+			g_free (param_lengths);
+			g_free (param_formats);
+			if (transaction_started)
+				gda_connection_rollback_transaction (cnc, NULL, NULL);
+			res = gda_postgres_provider_statement_execute (provider, cnc,
+								       rstmt, params,
+								       model_usage,
+								       col_types, last_inserted_row,
+								       task_id,
+								       async_cb, cb_data, error);
+			g_object_unref (rstmt);
+			return res;
+		}
 
 		/* actual binding using the C API, for parameter at position @i */
 		const GValue *value = gda_holder_get_value (h);
@@ -2141,6 +2180,25 @@ gda_postgres_provider_statement_execute (GdaServerProvider *provider, GdaConnect
 }
 
 /*
+ * Rewrites a statement in case some parameters in @params are set to DEFAULT, for INSERT or UPDATE statements
+ *
+ * Usually for INSERTS:
+ *  - it removes any DEFAULT value
+ *  - if there is no default value anymore, it uses the "DEFAULT VALUES" syntax
+ */
+static GdaSqlStatement *
+gda_postgresql_statement_rewrite (GdaServerProvider *provider, GdaConnection *cnc,
+				  GdaStatement *stmt, GdaSet *params, GError **error)
+{
+	if (cnc) {
+		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+		g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
+	}
+	return gda_statement_rewrite_for_default_values (stmt, params, FALSE, error);
+}
+
+
+/*
  * starts a distributed transaction: put the XA transaction in the ACTIVE state
  */
 static gboolean
diff --git a/providers/skel-implementation/capi/gda-capi-provider.c b/providers/skel-implementation/capi/gda-capi-provider.c
index 306b507..c5d407d 100644
--- a/providers/skel-implementation/capi/gda-capi-provider.c
+++ b/providers/skel-implementation/capi/gda-capi-provider.c
@@ -111,6 +111,9 @@ static GObject             *gda_capi_provider_statement_execute (GdaServerProvid
 								 GType *col_types, GdaSet **last_inserted_row, 
 								 guint *task_id, GdaServerProviderExecCallback async_cb, 
 								 gpointer cb_data, GError **error);
+static GdaSqlStatement     *gda_capi_statement_rewrite          (GdaServerProvider *provider, GdaConnection *cnc,
+								 GdaStatement *stmt, GdaSet *params, GError **error);
+
 
 /* distributed transactions */
 static gboolean gda_capi_provider_xa_start    (GdaServerProvider *provider, GdaConnection *cnc, 
@@ -191,6 +194,7 @@ gda_capi_provider_class_init (GdaCapiProviderClass *klass)
 						  * not call calls gda_statement_to_sql_extended() */
 	provider_class->statement_prepare = gda_capi_provider_statement_prepare;
 	provider_class->statement_execute = gda_capi_provider_statement_execute;
+	provider_class->statement_rewrite = gda_capi_statement_rewrite;
 
 	provider_class->is_busy = NULL;
 	provider_class->cancel = NULL;
@@ -1125,6 +1129,39 @@ gda_capi_provider_statement_execute (GdaServerProvider *provider, GdaConnection
                                 continue;
                         }
 		}
+		else if (gda_holder_value_is_default (h) && !gda_holder_get_value (h)) {
+			/* create a new GdaStatement to handle all default values and execute it instead
+			 * needs to be adapted to take into account how the database server handles default
+			 * values (some accept the DEFAULT keyword), changing the 3rd argument of the
+			 * gda_statement_rewrite_for_default_values() call
+			 */
+			GdaSqlStatement *sqlst;
+			GError *lerror = NULL;
+			sqlst = gda_statement_rewrite_for_default_values (stmt, params, TRUE, &lerror);
+			if (!sqlst) {
+				event = gda_connection_point_available_event (cnc,
+									      GDA_CONNECTION_EVENT_ERROR);
+				gda_connection_event_set_description (event, lerror && lerror->message ? 
+								      lerror->message :
+								      _("Can't rewrite statement handle default values"));
+				g_propagate_error (error, lerror);
+				break;
+			}
+			
+			GdaStatement *rstmt;
+			GObject *res;
+			rstmt = g_object_new (GDA_TYPE_STATEMENT, "structure", sqlst, NULL);
+			gda_sql_statement_free (sqlst);
+			res = gda_capi_provider_statement_execute (provider, cnc,
+								   rstmt, params,
+								   model_usage,
+								   col_types, last_inserted_row,
+								   task_id,
+								   async_cb, cb_data, error);
+			g_object_unref (rstmt);
+			return res;
+		}
+
 
 		/* actual binding using the C API, for parameter at position @i */
 		const GValue *value = gda_holder_get_value (h);
@@ -1202,6 +1239,23 @@ gda_capi_provider_statement_execute (GdaServerProvider *provider, GdaConnection
 }
 
 /*
+ * Rewrites a statement in case some parameters in @params are set to DEFAULT, for INSERT or UPDATE statements
+ *
+ * Usually it uses the DEFAULT keyword or removes any default value inserted or updated, see
+ * gda_statement_rewrite_for_default_values()
+ */
+static GdaSqlStatement *
+gda_capi_statement_rewrite (GdaServerProvider *provider, GdaConnection *cnc,
+			    GdaStatement *stmt, GdaSet *params, GError **error)
+{
+	if (cnc) {
+		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+		g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
+	}
+	return gda_statement_rewrite_for_default_values (stmt, params, TRUE, error);
+}
+
+/*
  * starts a distributed transaction: put the XA transaction in the ACTIVE state
  */
 static gboolean
diff --git a/providers/web/gda-web-provider.c b/providers/web/gda-web-provider.c
index 161db77..734f5cb 100644
--- a/providers/web/gda-web-provider.c
+++ b/providers/web/gda-web-provider.c
@@ -116,6 +116,8 @@ static GObject             *gda_web_provider_statement_execute (GdaServerProvide
 								GType *col_types, GdaSet **last_inserted_row, 
 								guint *task_id, GdaServerProviderExecCallback async_cb, 
 								gpointer cb_data, GError **error);
+static GdaSqlStatement     *gda_web_statement_rewrite          (GdaServerProvider *provider, GdaConnection *cnc,
+								GdaStatement *stmt, GdaSet *params, GError **error);
 
 /* Quoting */
 static gchar               *gda_web_identifier_quote    (GdaServerProvider *provider, GdaConnection *cnc,
@@ -162,6 +164,7 @@ gda_web_provider_class_init (GdaWebProviderClass *klass)
 						   * because it only calls gda_statement_to_sql_extended() */
 	provider_class->statement_prepare = gda_web_provider_statement_prepare;
 	provider_class->statement_execute = gda_web_provider_statement_execute;
+	provider_class->statement_rewrite = gda_web_statement_rewrite;
 
 	provider_class->is_busy = NULL;
 	provider_class->cancel = NULL;
@@ -1517,6 +1520,40 @@ gda_web_provider_statement_execute (GdaServerProvider *provider, GdaConnection *
                                 continue;
                         }
 		}
+		else if (gda_holder_value_is_default (h) && !gda_holder_get_value (h)) {
+			/* create a new GdaStatement to handle all default values and execute it instead
+			 * needs to be adapted to take into account how the database server handles default
+			 * values (some accept the DEFAULT keyword), changing the 3rd argument of the
+			 * gda_statement_rewrite_for_default_values() call
+			 */
+			GdaSqlStatement *sqlst;
+			GError *lerror = NULL;
+			sqlst = gda_statement_rewrite_for_default_values (stmt, params, TRUE, &lerror);
+			if (!sqlst) {
+				event = gda_connection_point_available_event (cnc,
+									      GDA_CONNECTION_EVENT_ERROR);
+				gda_connection_event_set_description (event, lerror && lerror->message ? 
+								      lerror->message :
+								      _("Can't rewrite statement handle default values"));
+				g_propagate_error (error, lerror);
+				break;
+			}
+			
+			GdaStatement *rstmt;
+			GObject *res;
+			rstmt = g_object_new (GDA_TYPE_STATEMENT, "structure", sqlst, NULL);
+			gda_sql_statement_free (sqlst);
+			g_object_unref (ps);
+			xmlFreeDoc (doc);
+			res = gda_web_provider_statement_execute (provider, cnc,
+								  rstmt, params,
+								  model_usage,
+								  col_types, last_inserted_row,
+								  task_id,
+								  async_cb, cb_data, error);
+			g_object_unref (rstmt);
+			return res;
+		}
 
 		/* actual binding using the C API, for parameter at position @i */
 		const GValue *value = gda_holder_get_value (h);
@@ -1637,6 +1674,22 @@ gda_web_provider_statement_execute (GdaServerProvider *provider, GdaConnection *
 	return retval;
 }
 
+/*
+ * Rewrites a statement in case some parameters in @params are set to DEFAULT, for INSERT or UPDATE statements
+ *
+ * Removes any default value inserted or updated
+ */
+static GdaSqlStatement *
+gda_web_statement_rewrite (GdaServerProvider *provider, GdaConnection *cnc,
+			   GdaStatement *stmt, GdaSet *params, GError **error)
+{
+	if (cnc) {
+		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+		g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
+	}
+	return gda_statement_rewrite_for_default_values (stmt, params, TRUE, error);
+}
+
 static gchar *
 gda_web_identifier_quote (GdaServerProvider *provider, GdaConnection *cnc,
 			  const gchar *id,
diff --git a/tests/parser/.gitignore b/tests/parser/.gitignore
index 5924de6..2da0e39 100644
--- a/tests/parser/.gitignore
+++ b/tests/parser/.gitignore
@@ -2,4 +2,5 @@ check_parser
 check_validation
 check_normalization
 check_dml_comp
-check_script
\ No newline at end of file
+check_script
+check_rewrite_for_default
diff --git a/tests/parser/Makefile.am b/tests/parser/Makefile.am
index d4a7464..ee67543 100644
--- a/tests/parser/Makefile.am
+++ b/tests/parser/Makefile.am
@@ -7,8 +7,8 @@ AM_CPPFLAGS = \
 	-DTOP_BUILD_DIR=\""$(top_builddir)"\" \
 	-DTOP_SRC_DIR=\""$(top_srcdir)"\"
 
-TESTS = check_parser check_validation check_normalization check_dml_comp check_script
-check_PROGRAMS = check_parser check_validation check_normalization check_dml_comp check_script
+TESTS = check_parser check_validation check_normalization check_dml_comp check_script check_rewrite_for_default
+check_PROGRAMS = check_parser check_validation check_normalization check_dml_comp check_script check_rewrite_for_default
 
 check_parser_SOURCES = check_parser.c
 check_parser_LDADD = \
@@ -35,6 +35,12 @@ check_script_LDADD = \
 	$(top_builddir)/libgda/libgda-4.0.la \
 	$(LIBGDA_LIBS)
 
+check_rewrite_for_default_SOURCES = check_rewrite_for_default.c
+check_rewrite_for_default_LDADD = \
+	$(top_builddir)/libgda/libgda-4.0.la \
+	$(LIBGDA_LIBS)
+
+
 EXTRA_DIST = testdata.xml testvalid.xml testscripts.xml \
 	scripts/mysql_employees.sql \
 	scripts/mysql_employees_partitioned.sql
diff --git a/tests/parser/check_rewrite_for_default.c b/tests/parser/check_rewrite_for_default.c
new file mode 100644
index 0000000..dc5cd72
--- /dev/null
+++ b/tests/parser/check_rewrite_for_default.c
@@ -0,0 +1,121 @@
+#include <libgda/libgda.h>
+#include <sql-parser/gda-sql-parser.h>
+#include <string.h>
+
+typedef struct {
+	gchar *sql;
+	gchar *rsql_remove;
+	gchar *rsql_default;
+} ATest;
+
+ATest tests[] = {
+	{"INSERT INTO mytable (name) VALUES (##name::string)",
+	 "INSERT INTO mytable DEFAULT VALUES",
+	 "INSERT INTO mytable (name) VALUES (DEFAULT)"},
+	{"INSERT INTO mytable (id, name) VALUES (23, ##name::string)",
+	 "INSERT INTO mytable (id) VALUES (23)",
+	 "INSERT INTO mytable (id, name) VALUES (23, DEFAULT)"},
+	{"UPDATE mytable set id=23, name=##name::string where 1",
+	 NULL,
+	 "UPDATE mytable SET id=23, name=DEFAULT WHERE 1"},
+	{"INSERT INTO mytable (id, name) VALUES (23, ##name::string), (44, 'joe')",
+	 NULL,
+	 "INSERT INTO mytable (id, name) VALUES (23, DEFAULT), (44, 'joe')"
+	},
+	{"INSERT INTO mytable (id, name) VALUES (23, ##name::string), (##id::int, 'joe')",
+	 NULL,
+	 "INSERT INTO mytable (id, name) VALUES (23, DEFAULT), (##id::int, 'joe')"
+	},
+	{"INSERT INTO mytable (id, name) VALUES (23, ##name::string), (##id::int, ##name::string)",
+	 NULL,
+	 "INSERT INTO mytable (id, name) VALUES (23, DEFAULT), (##id::int, DEFAULT)"
+	}
+};
+
+static gboolean
+do_test (ATest *test, GdaStatement *stmt, GdaSet *params, gboolean remove)
+{
+	gboolean retval = TRUE;
+	GdaSqlStatement *sqlst;
+	GError* error = NULL;
+
+	sqlst = gda_statement_rewrite_for_default_values (stmt, params, remove, &error);
+	if (!sqlst) {
+		gchar *exp;
+		exp = remove ? test->rsql_remove : test->rsql_default;
+		if (exp) {
+			g_print ("Can't rewrite stmt with %s option: %s\n", remove ? "REMOVE" : "DEFAULT keyword",
+				 error && error->message ? error->message : "No detail");
+			g_clear_error (&error);
+			retval = FALSE;
+		}
+	}
+	else {
+		GdaStatement *rstmt;
+		gchar *sql;
+		rstmt = GDA_STATEMENT (g_object_new (GDA_TYPE_STATEMENT, "structure", sqlst, NULL));
+
+		sql = gda_statement_to_sql (rstmt, NULL, &error);
+		if (sql) {
+			gchar *exp;
+			exp = remove ? test->rsql_remove : test->rsql_default;
+			if (g_strcmp0 (sql, exp)) {
+				g_print ("Error:\n  exp: [%s]\n  got: [%s]\n", exp, sql);
+				retval = FALSE;
+			}
+			g_free (sql);
+		}
+		else {
+			g_print ("Rendering error: %s\n", error && error->message ? error->message : "No detail");
+			g_clear_error (&error);
+			retval = FALSE;
+		}
+		
+		g_object_unref (rstmt);
+		gda_sql_statement_free (sqlst);
+	}
+	return retval;
+}
+
+int main()
+{
+	gda_init();
+	GdaSqlParser *parser;
+	GdaStatement *stmt;
+	GdaSet *params;
+	GdaHolder *h;
+	GValue *value;
+	gint i;
+	gint n_errors = 0;
+	
+	parser = gda_sql_parser_new ();
+
+	for (i = 0; i < sizeof (tests) / sizeof (ATest); i++) {
+		ATest *test = &tests[i];
+
+		stmt = gda_sql_parser_parse_string (parser, test->sql, NULL, NULL);
+		g_assert (stmt);
+		g_assert (gda_statement_get_parameters (stmt, &params, NULL));
+
+		h = gda_set_get_holder (params, "name");
+		g_value_set_int ((value = gda_value_new (G_TYPE_INT)), 5);
+		gda_holder_set_default_value (h, value);
+		gda_value_free (value);
+		g_assert (gda_holder_set_value_to_default (h));
+		
+		if (! do_test (test, stmt, params, TRUE))
+			n_errors++;
+		if (! do_test (test, stmt, params, FALSE))
+			n_errors++;
+		g_object_unref (params);
+		g_object_unref (stmt);
+	}
+
+	g_object_unref (parser);
+
+	if (n_errors == 0)
+		g_print ("Ok: %d tests passed\n", i*2);
+	else
+		g_print ("Failed: %d tests total, %d failed\n", i*2, n_errors);
+	return n_errors ? 1 : 0;
+}



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