[libgda/LIBGDA_4.2] Corrected bug when executing statement with a NULL variable



commit 7fbd710a274f785cc955327e1211972b1be0c071
Author: Vivien Malerba <malerba gnome-db org>
Date:   Sun Oct 9 16:54:28 2011 +0200

    Corrected bug when executing statement with a NULL variable

 libgda/sqlite/gda-sqlite-provider.c                |   54 +++++++++--------
 providers/jdbc/gda-jdbc-provider.c                 |   59 ++++++++----------
 providers/mysql/gda-mysql-provider.c               |   51 ++++++++-------
 providers/oracle/gda-oracle-provider.c             |   55 +++++++++--------
 providers/postgres/gda-postgres-provider.c         |   49 ++++++++-------
 .../skel-implementation/capi/gda-capi-provider.c   |   47 ++++++++-------
 providers/web/gda-web-provider.c                   |   64 ++++++++++---------
 7 files changed, 197 insertions(+), 182 deletions(-)
---
diff --git a/libgda/sqlite/gda-sqlite-provider.c b/libgda/sqlite/gda-sqlite-provider.c
index 289d115..fd0d2e6 100644
--- a/libgda/sqlite/gda-sqlite-provider.c
+++ b/libgda/sqlite/gda-sqlite-provider.c
@@ -2253,6 +2253,7 @@ real_prepare (GdaServerProvider *provider, GdaConnection *cnc, GdaStatement *stm
 	ps->rowid_hash = hash;
 	ps->nb_rowid_columns = nb_rows_added;
 	g_object_unref (real_stmt);
+	/*g_print ("%s(%s) => GdaSqlitePStmt %p\n", __FUNCTION__, sql, ps);*/
 	return ps;
 
  out_err:
@@ -2796,9 +2797,9 @@ gda_sqlite_provider_statement_execute (GdaServerProvider *provider, GdaConnectio
 			g_object_unref (rstmt);
 			return res;
 		}
-		/*g_print ("BINDING param '%s' to %p\n", pname, h);*/
-		
+
 		const GValue *value = gda_holder_get_value (h);
+		/*g_print ("BINDING param '%s' to GdaHolder %p, valued to [%s]\n", pname, h, gda_value_stringify (value));*/
 		if (!value || gda_value_is_null (value)) {
 			GdaStatement *rstmt;
 			if (! gda_rewrite_statement_for_null_parameters (stmt, params, &rstmt, error))
@@ -2806,33 +2807,33 @@ gda_sqlite_provider_statement_execute (GdaServerProvider *provider, GdaConnectio
 			else if (!rstmt)
 				return NULL;
 			else {
-				/* The strategy here is to execute @rstmt using the prepared
-				 * statement associcted to @stmt, but adapted to @rstmt, so all
-				 * the column names, etc remain the same.
-				 *
-				 * The adaptation consists to replace SQLite specific information
-				 * in the GdaSqlitePStmt object.
-				 *
-				 * The trick is to adapt @ps, then associate @ps with @rstmt, then
-				 * execute @rstmt, and then undo the trick */
+				/* The strategy here is to execute @rstmt using its prepared
+				 * statement, but with common data from @ps. Beware that
+				 * the @param_ids attribute needs to be retained (i.e. it must not
+				 * be the one copied from @ps) */
 				GObject *obj;
 				GdaSqlitePStmt *tps;
+				GdaPStmt *gtps;
+				GSList *prep_param_ids, *copied_param_ids;
 				if (!gda_sqlite_provider_statement_prepare (provider, cnc,
 									    rstmt, error))
 					return NULL;
 				tps = (GdaSqlitePStmt *)
 					gda_connection_get_prepared_statement (cnc, rstmt);
+				gtps = (GdaPStmt *) tps;
+
+				/* keep @param_ids to avoid being cleared by gda_pstmt_copy_contents() */
+				prep_param_ids = gtps->param_ids;
+				gtps->param_ids = NULL;
+				
+				/* actual copy */
+				gda_pstmt_copy_contents ((GdaPStmt *) ps, (GdaPStmt *) tps);
 
-				/* adapt @ps with @tps's SQLite specific information */
-				GdaSqlitePStmt hps;
-				hps.sqlite_stmt = ps->sqlite_stmt; /* save */
-				ps->sqlite_stmt = tps->sqlite_stmt; /* override */
-				hps.stmt_used = ps->stmt_used; /* save */
-				ps->stmt_used = tps->stmt_used; /* override */
-				g_object_ref (tps);
-				gda_connection_add_prepared_statement (cnc, rstmt, (GdaPStmt *) ps);
+				/* restore previous @param_ids */
+				copied_param_ids = gtps->param_ids;
+				gtps->param_ids = prep_param_ids;
 
-				/* execute rstmt (it will use @ps) */
+				/* execute */
 				obj = gda_sqlite_provider_statement_execute (provider, cnc,
 									     rstmt, params,
 									     model_usage,
@@ -2840,12 +2841,15 @@ gda_sqlite_provider_statement_execute (GdaServerProvider *provider, GdaConnectio
 									     last_inserted_row,
 									     task_id, async_cb,
 									     cb_data, error);
+				/* clear original @param_ids and restore copied one */
+				g_slist_foreach (prep_param_ids, (GFunc) g_free, NULL);
+				g_slist_free (prep_param_ids);
+
+				gtps->param_ids = copied_param_ids;
+
+				/*if (GDA_IS_DATA_MODEL (obj))
+				  gda_data_model_dump ((GdaDataModel*) obj, NULL);*/
 
-				/* revert adaptations */
-				ps->sqlite_stmt = hps.sqlite_stmt;
-				ps->stmt_used = hps.stmt_used;
-				gda_connection_add_prepared_statement (cnc, rstmt, (GdaPStmt *) tps);
-				g_object_unref (tps);
 				g_object_unref (rstmt);
 
 				if (new_ps)
diff --git a/providers/jdbc/gda-jdbc-provider.c b/providers/jdbc/gda-jdbc-provider.c
index bea82d9..1e9ea3b 100644
--- a/providers/jdbc/gda-jdbc-provider.c
+++ b/providers/jdbc/gda-jdbc-provider.c
@@ -1429,47 +1429,33 @@ gda_jdbc_provider_statement_execute (GdaServerProvider *provider, GdaConnection
 			else {
 				_gda_jdbc_release_jenv (jni_detach);
 
-				/* The strategy here is to execute @rstmt using the prepared
-				 * statement associcted to @stmt, but adapted to @rstmt, so all
-				 * the column names, etc remain the same.
-				 *
-				 * The adaptation consists to replace Jdbc specific information
-				 * in the GdaJdbcPStmt object.
-				 *
-				 * The trick is to adapt @ps, then associate @ps with @rstmt, then
-				 * execute @rstmt, and then undo the trick */
+				/* The strategy here is to execute @rstmt using its prepared
+				 * statement, but with common data from @ps. Beware that
+				 * the @param_ids attribute needs to be retained (i.e. it must not
+				 * be the one copied from @ps) */
 				GObject *obj;
 				GdaJdbcPStmt *tps;
+				GdaPStmt *gtps;
+				GSList *prep_param_ids, *copied_param_ids;
 				if (!gda_jdbc_provider_statement_prepare (provider, cnc,
-									    rstmt, error)) {
-					g_object_unref (ps);
+									  rstmt, error))
 					return NULL;
-				}
 				tps = (GdaJdbcPStmt *)
 					gda_connection_get_prepared_statement (cnc, rstmt);
+				gtps = (GdaPStmt *) tps;
 
-				/* adapt @ps with @tps's Jdbc specific information */
-				GdaJdbcPStmt hps;
-				hps.pstmt_obj = ps->pstmt_obj; /* save */
-				ps->pstmt_obj = tps->pstmt_obj; /* override */
-				g_object_ref (tps);
-				gda_connection_add_prepared_statement (cnc, rstmt, (GdaPStmt *) ps);
+				/* keep @param_ids to avoid being cleared by gda_pstmt_copy_contents() */
+				prep_param_ids = gtps->param_ids;
+				gtps->param_ids = NULL;
+				
+				/* actual copy */
+				gda_pstmt_copy_contents ((GdaPStmt *) ps, (GdaPStmt *) tps);
 
-				/* execute rstmt (it will use @ps) */
-				obj = gda_jdbc_provider_statement_execute (provider, cnc,
-									     rstmt, params,
-									     model_usage,
-									     col_types,
-									     last_inserted_row,
-									     task_id, async_cb,
-									     cb_data, error);
-
-				/* revert adaptations */
-				ps->pstmt_obj = hps.pstmt_obj;
-				gda_connection_add_prepared_statement (cnc, rstmt, (GdaPStmt *) tps);
-				g_object_unref (tps);
-				g_object_unref (rstmt);
+				/* restore previous @param_ids */
+				copied_param_ids = gtps->param_ids;
+				gtps->param_ids = prep_param_ids;
 
+				/* execute */
 				obj = gda_jdbc_provider_statement_execute (provider, cnc,
 									   rstmt, params,
 									   model_usage,
@@ -1477,6 +1463,15 @@ gda_jdbc_provider_statement_execute (GdaServerProvider *provider, GdaConnection
 									   last_inserted_row,
 									   task_id, async_cb,
 									   cb_data, error);
+				/* clear original @param_ids and restore copied one */
+				g_slist_foreach (prep_param_ids, (GFunc) g_free, NULL);
+				g_slist_free (prep_param_ids);
+
+				gtps->param_ids = copied_param_ids;
+
+				/*if (GDA_IS_DATA_MODEL (obj))
+				  gda_data_model_dump ((GdaDataModel*) obj, NULL);*/
+
 				g_object_unref (rstmt);
 				g_object_unref (ps);
 				return obj;
diff --git a/providers/mysql/gda-mysql-provider.c b/providers/mysql/gda-mysql-provider.c
index ed7e24f..a411907 100644
--- a/providers/mysql/gda-mysql-provider.c
+++ b/providers/mysql/gda-mysql-provider.c
@@ -2310,33 +2310,33 @@ gda_mysql_provider_statement_execute (GdaServerProvider               *provider,
 			else {
 				free_bind_param_data (mem_to_free);
 
-				/* The strategy here is to execute @rstmt using the prepared
-				 * statement associcted to @stmt, but adapted to @rstmt, so all
-				 * the column names, etc remain the same.
-				 *
-				 * The adaptation consists to replace MySQL specific information
-				 * in the GdaMysqlPStmt object.
-				 *
-				 * The trick is to adapt @ps, then associate @ps with @rstmt, then
-				 * execute @rstmt, and then undo the trick */
+				/* The strategy here is to execute @rstmt using its prepared
+				 * statement, but with common data from @ps. Beware that
+				 * the @param_ids attribute needs to be retained (i.e. it must not
+				 * be the one copied from @ps) */
 				GObject *obj;
 				GdaMysqlPStmt *tps;
+				GdaPStmt *gtps;
+				GSList *prep_param_ids, *copied_param_ids;
 				if (!gda_mysql_provider_statement_prepare (provider, cnc,
-									    rstmt, error))
+									   rstmt, error))
 					return NULL;
 				tps = (GdaMysqlPStmt *)
 					gda_connection_get_prepared_statement (cnc, rstmt);
+				gtps = (GdaPStmt *) tps;
 
-				/* adapt @ps with @tps's Mysql specific information */
-				GdaMysqlPStmt hps;
-				hps.mysql_stmt = ps->mysql_stmt; /* save */
-				ps->mysql_stmt = tps->mysql_stmt; /* override */
-				hps.stmt_used = ps->stmt_used; /* save */
-				ps->stmt_used = tps->stmt_used; /* override */
-				g_object_ref (tps);
-				gda_connection_add_prepared_statement (cnc, rstmt, (GdaPStmt *) ps);
+				/* keep @param_ids to avoid being cleared by gda_pstmt_copy_contents() */
+				prep_param_ids = gtps->param_ids;
+				gtps->param_ids = NULL;
+				
+				/* actual copy */
+				gda_pstmt_copy_contents ((GdaPStmt *) ps, (GdaPStmt *) tps);
+
+				/* restore previous @param_ids */
+				copied_param_ids = gtps->param_ids;
+				gtps->param_ids = prep_param_ids;
 
-				/* execute rstmt (it will use @ps) */
+				/* execute */
 				obj = gda_mysql_provider_statement_execute (provider, cnc,
 									    rstmt, params,
 									    model_usage,
@@ -2344,12 +2344,15 @@ gda_mysql_provider_statement_execute (GdaServerProvider               *provider,
 									    last_inserted_row,
 									    task_id, async_cb,
 									    cb_data, error);
+				/* clear original @param_ids and restore copied one */
+				g_slist_foreach (prep_param_ids, (GFunc) g_free, NULL);
+				g_slist_free (prep_param_ids);
+
+				gtps->param_ids = copied_param_ids;
+
+				/*if (GDA_IS_DATA_MODEL (obj))
+				  gda_data_model_dump ((GdaDataModel*) obj, NULL);*/
 
-				/* revert adaptations */
-				ps->mysql_stmt = hps.mysql_stmt;
-				ps->stmt_used = hps.stmt_used;
-				gda_connection_add_prepared_statement (cnc, rstmt, (GdaPStmt *) tps);
-				g_object_unref (tps);
 				g_object_unref (rstmt);
 				return obj;
 			}
diff --git a/providers/oracle/gda-oracle-provider.c b/providers/oracle/gda-oracle-provider.c
index f4f01c1..9ed5e53 100644
--- a/providers/oracle/gda-oracle-provider.c
+++ b/providers/oracle/gda-oracle-provider.c
@@ -1929,35 +1929,33 @@ gda_oracle_provider_statement_execute (GdaServerProvider *provider, GdaConnectio
 			else if (!rstmt)
 				return NULL;
 			else {
-				/* The strategy here is to execute @rstmt using the prepared
-				 * statement associcted to @stmt, but adapted to @rstmt, so all
-				 * the column names, etc remain the same.
-				 *
-				 * The adaptation consists to replace Oracle specific information
-				 * in the GdaOraclePStmt object.
-				 *
-				 * The trick is to adapt @ps, then associate @ps with @rstmt, then
-				 * execute @rstmt, and then undo the trick */
+				/* The strategy here is to execute @rstmt using its prepared
+				 * statement, but with common data from @ps. Beware that
+				 * the @param_ids attribute needs to be retained (i.e. it must not
+				 * be the one copied from @ps) */
 				GObject *obj;
 				GdaOraclePStmt *tps;
+				GdaPStmt *gtps;
+				GSList *prep_param_ids, *copied_param_ids;
 				if (!gda_oracle_provider_statement_prepare (provider, cnc,
-									    rstmt, error)) {
-					g_object_unref (ps);
+									    rstmt, error))
 					return NULL;
-				}
 				tps = (GdaOraclePStmt *)
 					gda_connection_get_prepared_statement (cnc, rstmt);
+				gtps = (GdaPStmt *) tps;
+
+				/* keep @param_ids to avoid being cleared by gda_pstmt_copy_contents() */
+				prep_param_ids = gtps->param_ids;
+				gtps->param_ids = NULL;
+				
+				/* actual copy */
+				gda_pstmt_copy_contents ((GdaPStmt *) ps, (GdaPStmt *) tps);
 
-				/* adapt @ps with @tps's Oracle specific information */
-				GdaOraclePStmt hps;
-				hps.hstmt = ps->hstmt; /* save */
-				ps->hstmt = tps->hstmt; /* override */
-				hps.ora_values = ps->ora_values; /* save */
-				ps->ora_values = tps->ora_values; /* override */
-				g_object_ref (tps);
-				gda_connection_add_prepared_statement (cnc, rstmt, (GdaPStmt *) ps);
+				/* restore previous @param_ids */
+				copied_param_ids = gtps->param_ids;
+				gtps->param_ids = prep_param_ids;
 
-				/* execute rstmt (it will use @ps) */
+				/* execute */
 				obj = gda_oracle_provider_statement_execute (provider, cnc,
 									     rstmt, params,
 									     model_usage,
@@ -1965,12 +1963,15 @@ gda_oracle_provider_statement_execute (GdaServerProvider *provider, GdaConnectio
 									     last_inserted_row,
 									     task_id, async_cb,
 									     cb_data, error);
-				
-				/* revert adaptations */
-				ps->hstmt = hps.hstmt;
-				ps->ora_values = hps.ora_values;
-				gda_connection_add_prepared_statement (cnc, rstmt, (GdaPStmt *) tps);
-				g_object_unref (tps);
+				/* clear original @param_ids and restore copied one */
+				g_slist_foreach (prep_param_ids, (GFunc) g_free, NULL);
+				g_slist_free (prep_param_ids);
+
+				gtps->param_ids = copied_param_ids;
+
+				/*if (GDA_IS_DATA_MODEL (obj))
+				  gda_data_model_dump ((GdaDataModel*) obj, NULL);*/
+
 				g_object_unref (rstmt);
 				g_object_unref (ps);
 				return obj;
diff --git a/providers/postgres/gda-postgres-provider.c b/providers/postgres/gda-postgres-provider.c
index 6533a53..9be726c 100644
--- a/providers/postgres/gda-postgres-provider.c
+++ b/providers/postgres/gda-postgres-provider.c
@@ -2023,33 +2023,33 @@ gda_postgres_provider_statement_execute (GdaServerProvider *provider, GdaConnect
 				if (transaction_started)
 					gda_connection_rollback_transaction (cnc, NULL, NULL);
 
-				/* The strategy here is to execute @rstmt using the prepared
-				 * statement associcted to @stmt, but adapted to @rstmt, so all
-				 * the column names, etc remain the same.
-				 *
-				 * The adaptation consists to replace Postgresql specific information
-				 * in the GdaPostgresPStmt object.
-				 *
-				 * The trick is to adapt @ps, then associate @ps with @rstmt, then
-				 * execute @rstmt, and then undo the trick */
+				/* The strategy here is to execute @rstmt using its prepared
+				 * statement, but with common data from @ps. Beware that
+				 * the @param_ids attribute needs to be retained (i.e. it must not
+				 * be the one copied from @ps) */
 				GObject *obj;
 				GdaPostgresPStmt *tps;
+				GdaPStmt *gtps;
+				GSList *prep_param_ids, *copied_param_ids;
 				if (!gda_postgres_provider_statement_prepare (provider, cnc,
 									      rstmt, error))
 					return NULL;
 				tps = (GdaPostgresPStmt *)
 					gda_connection_get_prepared_statement (cnc, rstmt);
+				gtps = (GdaPStmt *) tps;
 
-				/* adapt @ps with @tps's SQLite specific information */
-				GdaPostgresPStmt hps;
-				hps.pconn = ps->pconn; /* save */
-				ps->pconn = tps->pconn; /* override */
-				hps.prep_name = ps->prep_name; /* save */
-				ps->prep_name = tps->prep_name; /* override */
-				g_object_ref (tps);
-				gda_connection_add_prepared_statement (cnc, rstmt, (GdaPStmt *) ps);
+				/* keep @param_ids to avoid being cleared by gda_pstmt_copy_contents() */
+				prep_param_ids = gtps->param_ids;
+				gtps->param_ids = NULL;
+				
+				/* actual copy */
+				gda_pstmt_copy_contents ((GdaPStmt *) ps, (GdaPStmt *) tps);
 
-				/* execute rstmt (it will use @ps) */
+				/* restore previous @param_ids */
+				copied_param_ids = gtps->param_ids;
+				gtps->param_ids = prep_param_ids;
+
+				/* execute */
 				obj = gda_postgres_provider_statement_execute (provider, cnc,
 									       rstmt, params,
 									       model_usage,
@@ -2057,12 +2057,15 @@ gda_postgres_provider_statement_execute (GdaServerProvider *provider, GdaConnect
 									       last_inserted_row,
 									       task_id, async_cb,
 									       cb_data, error);
+				/* clear original @param_ids and restore copied one */
+				g_slist_foreach (prep_param_ids, (GFunc) g_free, NULL);
+				g_slist_free (prep_param_ids);
+
+				gtps->param_ids = copied_param_ids;
+
+				/*if (GDA_IS_DATA_MODEL (obj))
+				  gda_data_model_dump ((GdaDataModel*) obj, NULL);*/
 
-				/* revert adaptations */
-				ps->pconn = hps.pconn;
-				ps->prep_name = hps.prep_name;
-				gda_connection_add_prepared_statement (cnc, rstmt, (GdaPStmt *) tps);
-				g_object_unref (tps);
 				g_object_unref (rstmt);
 				return obj;
 			}
diff --git a/providers/skel-implementation/capi/gda-capi-provider.c b/providers/skel-implementation/capi/gda-capi-provider.c
index 6d066a5..bcdf58b 100644
--- a/providers/skel-implementation/capi/gda-capi-provider.c
+++ b/providers/skel-implementation/capi/gda-capi-provider.c
@@ -1179,31 +1179,33 @@ gda_capi_provider_statement_execute (GdaServerProvider *provider, GdaConnection
 			else if (!rstmt)
 				return NULL;
 			else {
-				/* The strategy here is to execute @rstmt using the prepared
-				 * statement associcted to @stmt, but adapted to @rstmt, so all
-				 * the column names, etc remain the same.
-				 *
-				 * The adaptation consists to replace Capi specific information
-				 * in the GdaCapiPStmt object.
-				 *
-				 * The trick is to adapt @ps, then associate @ps with @rstmt, then
-				 * execute @rstmt, and then undo the trick */
+				/* The strategy here is to execute @rstmt using its prepared
+				 * statement, but with common data from @ps. Beware that
+				 * the @param_ids attribute needs to be retained (i.e. it must not
+				 * be the one copied from @ps) */
 				GObject *obj;
 				GdaCapiPStmt *tps;
+				GdaPStmt *gtps;
+				GSList *prep_param_ids, *copied_param_ids;
 				if (!gda_capi_provider_statement_prepare (provider, cnc,
-									    rstmt, error))
+									  rstmt, error))
 					return NULL;
 				tps = (GdaCapiPStmt *)
 					gda_connection_get_prepared_statement (cnc, rstmt);
+				gtps = (GdaPStmt *) tps;
 
-				/* adapt @ps with @tps's Capi specific information */
-				GdaCapiPStmt hps;
-				/* TO ADD: hps.capi_stmt = ps->capi_stmt;*/ /* save */
-				/* TO_ADD: ps->capi_stmt = tps->capi_stmt;*/ /* override */
-				g_object_ref (tps);
-				gda_connection_add_prepared_statement (cnc, rstmt, (GdaPStmt *) ps);
+				/* keep @param_ids to avoid being cleared by gda_pstmt_copy_contents() */
+				prep_param_ids = gtps->param_ids;
+				gtps->param_ids = NULL;
+				
+				/* actual copy */
+				gda_pstmt_copy_contents ((GdaPStmt *) ps, (GdaPStmt *) tps);
 
-				/* execute rstmt (it will use @ps) */
+				/* restore previous @param_ids */
+				copied_param_ids = gtps->param_ids;
+				gtps->param_ids = prep_param_ids;
+
+				/* execute */
 				obj = gda_capi_provider_statement_execute (provider, cnc,
 									   rstmt, params,
 									   model_usage,
@@ -1211,12 +1213,15 @@ gda_capi_provider_statement_execute (GdaServerProvider *provider, GdaConnection
 									   last_inserted_row,
 									   task_id, async_cb,
 									   cb_data, error);
+				/* clear original @param_ids and restore copied one */
+				g_slist_foreach (prep_param_ids, (GFunc) g_free, NULL);
+				g_slist_free (prep_param_ids);
+
+				gtps->param_ids = copied_param_ids;
 
-				/* revert adaptations */
-				/* TO_ADD: ps->capi_stmt = hps.capi_stmt; */
+				/*if (GDA_IS_DATA_MODEL (obj))
+				  gda_data_model_dump ((GdaDataModel*) obj, NULL);*/
 
-				gda_connection_add_prepared_statement (cnc, rstmt, (GdaPStmt *) tps);
-				g_object_unref (tps);
 				g_object_unref (rstmt);
 				return obj;
 			}
diff --git a/providers/web/gda-web-provider.c b/providers/web/gda-web-provider.c
index 777bc2c..2201ebe 100644
--- a/providers/web/gda-web-provider.c
+++ b/providers/web/gda-web-provider.c
@@ -1574,45 +1574,49 @@ gda_web_provider_statement_execute (GdaServerProvider *provider, GdaConnection *
 			else {
 				xmlFreeDoc (doc);
 
-				/* The strategy here is to execute @rstmt using the prepared
-				 * statement associcted to @stmt, but adapted to @rstmt, so all
-				 * the column names, etc remain the same.
-				 *
-				 * The adaptation consists to replace Web specific information
-				 * in the GdaWebPStmt object.
-				 *
-				 * The trick is to adapt @ps, then associate @ps with @rstmt, then
-				 * execute @rstmt, and then undo the trick */
+				/* The strategy here is to execute @rstmt using its prepared
+				 * statement, but with common data from @ps. Beware that
+				 * the @param_ids attribute needs to be retained (i.e. it must not
+				 * be the one copied from @ps) */
 				GObject *obj;
 				GdaWebPStmt *tps;
+				GdaPStmt *gtps;
+				GSList *prep_param_ids, *copied_param_ids;
 				if (!gda_web_provider_statement_prepare (provider, cnc,
-									 rstmt, error)) {
-					g_object_unref (ps);
+									 rstmt, error))
 					return NULL;
-				}
 				tps = (GdaWebPStmt *)
 					gda_connection_get_prepared_statement (cnc, rstmt);
+				gtps = (GdaPStmt *) tps;
 
-				/* adapt @ps with @tps's Web specific information */
-				GdaWebPStmt hps;
-				hps.pstmt_hash = ps->pstmt_hash; /* save */
-				ps->pstmt_hash = tps->pstmt_hash; /* override */
-				g_object_ref (tps);
-				gda_connection_add_prepared_statement (cnc, rstmt, (GdaPStmt *) ps);
+				/* keep @param_ids to avoid being cleared by gda_pstmt_copy_contents() */
+				prep_param_ids = gtps->param_ids;
+				gtps->param_ids = NULL;
+				
+				/* actual copy */
+				gda_pstmt_copy_contents ((GdaPStmt *) ps, (GdaPStmt *) tps);
 
-				/* execute rstmt (it will use @ps) */
+				/* restore previous @param_ids */
+				copied_param_ids = gtps->param_ids;
+				gtps->param_ids = prep_param_ids;
+
+				/* execute */
 				obj = gda_web_provider_statement_execute (provider, cnc,
-									     rstmt, params,
-									     model_usage,
-									     col_types,
-									     last_inserted_row,
-									     task_id, async_cb,
-									     cb_data, error);
-
-				/* revert adaptations */
-				ps->pstmt_hash = hps.pstmt_hash;
-				gda_connection_add_prepared_statement (cnc, rstmt, (GdaPStmt *) tps);
-				g_object_unref (tps);
+									  rstmt, params,
+									  model_usage,
+									  col_types,
+									  last_inserted_row,
+									  task_id, async_cb,
+									  cb_data, error);
+				/* clear original @param_ids and restore copied one */
+				g_slist_foreach (prep_param_ids, (GFunc) g_free, NULL);
+				g_slist_free (prep_param_ids);
+
+				gtps->param_ids = copied_param_ids;
+
+				/*if (GDA_IS_DATA_MODEL (obj))
+				  gda_data_model_dump ((GdaDataModel*) obj, NULL);*/
+
 				g_object_unref (rstmt);
 				g_object_unref (ps);
 				return obj;



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