[libgda] Fixed nasty bug introduced in commit #036420a459b0bb241716cd9a14c3dd1eb2b21f63



commit 7d7742477ad03f19a168c763b988a7807421e9ca
Author: Vivien Malerba <malerba gnome-db org>
Date:   Sat Sep 17 16:26:09 2011 +0200

    Fixed nasty bug introduced in commit #036420a459b0bb241716cd9a14c3dd1eb2b21f63
    
    which "Improved statement rewriting for NULL parameters", and in other
    commits for each provider

 libgda/sqlite/gda-sqlite-provider.c                |   41 ++++++++++++---
 providers/jdbc/gda-jdbc-provider.c                 |   53 +++++++++++++++----
 providers/mysql/gda-mysql-provider.c               |   43 ++++++++++++---
 providers/oracle/gda-oracle-provider.c             |   44 ++++++++++++---
 providers/postgres/gda-postgres-provider.c         |   42 ++++++++++++---
 .../skel-implementation/capi/gda-capi-provider.c   |   38 +++++++++++---
 providers/web/gda-web-provider.c                   |   56 ++++++++++++++------
 7 files changed, 248 insertions(+), 69 deletions(-)
---
diff --git a/libgda/sqlite/gda-sqlite-provider.c b/libgda/sqlite/gda-sqlite-provider.c
index afeab3c..69ccd16 100644
--- a/libgda/sqlite/gda-sqlite-provider.c
+++ b/libgda/sqlite/gda-sqlite-provider.c
@@ -2935,7 +2935,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 */
 				GObject *obj;
+				GdaSqlitePStmt *tps;
+				if (!gda_sqlite_provider_statement_prepare (provider, cnc,
+									    rstmt, error))
+					return NULL;
+				tps = (GdaSqlitePStmt *)
+					gda_connection_get_prepared_statement (cnc, rstmt);
+
+				/* 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);
+
+				/* execute rstmt (it will use @ps) */
 				obj = gda_sqlite_provider_statement_execute (provider, cnc,
 									     rstmt, params,
 									     model_usage,
@@ -2943,15 +2969,14 @@ gda_sqlite_provider_statement_execute (GdaServerProvider *provider, GdaConnectio
 									     last_inserted_row,
 									     task_id, async_cb,
 									     cb_data, error);
+
+				/* 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 (GDA_IS_DATA_SELECT (obj)) {
-					GdaPStmt *pstmt;
-					g_object_get (obj, "prepared-stmt", &pstmt, NULL);
-					if (pstmt) {
-						gda_pstmt_set_gda_statement (pstmt, stmt);
-						g_object_unref (pstmt);
-					}
-				}
+
 				if (new_ps)
 					g_object_unref (ps);
 				pending_blobs_free_list (blobs_list);
diff --git a/providers/jdbc/gda-jdbc-provider.c b/providers/jdbc/gda-jdbc-provider.c
index 164e67f..c1192fb 100644
--- a/providers/jdbc/gda-jdbc-provider.c
+++ b/providers/jdbc/gda-jdbc-provider.c
@@ -1429,9 +1429,49 @@ gda_jdbc_provider_statement_execute (GdaServerProvider *provider, GdaConnection
 			else if (!rstmt)
 				return NULL;
 			else {
-				GObject *obj;
-				g_object_unref (ps);
 				_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 */
+				GObject *obj;
+				GdaJdbcPStmt *tps;
+				if (!gda_jdbc_provider_statement_prepare (provider, cnc,
+									    rstmt, error)) {
+					g_object_unref (ps);
+					return NULL;
+				}
+				tps = (GdaJdbcPStmt *)
+					gda_connection_get_prepared_statement (cnc, rstmt);
+
+				/* 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);
+
+				/* 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);
+
 				obj = gda_jdbc_provider_statement_execute (provider, cnc,
 									   rstmt, params,
 									   model_usage,
@@ -1440,14 +1480,7 @@ gda_jdbc_provider_statement_execute (GdaServerProvider *provider, GdaConnection
 									   task_id, async_cb,
 									   cb_data, error);
 				g_object_unref (rstmt);
-				if (GDA_IS_DATA_SELECT (obj)) {
-					GdaPStmt *pstmt;
-					g_object_get (obj, "prepared-stmt", &pstmt, NULL);
-					if (pstmt) {
-						gda_pstmt_set_gda_statement (pstmt, stmt);
-						g_object_unref (pstmt);
-					}
-				}
+				g_object_unref (ps);
 				return obj;
 			}
 		}
diff --git a/providers/mysql/gda-mysql-provider.c b/providers/mysql/gda-mysql-provider.c
index d581828..8baf0a3 100644
--- a/providers/mysql/gda-mysql-provider.c
+++ b/providers/mysql/gda-mysql-provider.c
@@ -2304,8 +2304,35 @@ gda_mysql_provider_statement_execute (GdaServerProvider               *provider,
 			else if (!rstmt)
 				return NULL;
 			else {
-				GObject *obj;
 				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 */
+				GObject *obj;
+				GdaMysqlPStmt *tps;
+				if (!gda_mysql_provider_statement_prepare (provider, cnc,
+									    rstmt, error))
+					return NULL;
+				tps = (GdaMysqlPStmt *)
+					gda_connection_get_prepared_statement (cnc, rstmt);
+
+				/* 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);
+
+				/* execute rstmt (it will use @ps) */
 				obj = gda_mysql_provider_statement_execute (provider, cnc,
 									    rstmt, params,
 									    model_usage,
@@ -2313,15 +2340,13 @@ gda_mysql_provider_statement_execute (GdaServerProvider               *provider,
 									    last_inserted_row,
 									    task_id, async_cb,
 									    cb_data, error);
+
+				/* 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);
-				if (GDA_IS_DATA_SELECT (obj)) {
-					GdaPStmt *pstmt;
-					g_object_get (obj, "prepared-stmt", &pstmt, NULL);
-					if (pstmt) {
-						gda_pstmt_set_gda_statement (pstmt, stmt);
-						g_object_unref (pstmt);
-					}
-				}
 				return obj;
 			}
 		}
diff --git a/providers/oracle/gda-oracle-provider.c b/providers/oracle/gda-oracle-provider.c
index 1d40105..9d0f485 100644
--- a/providers/oracle/gda-oracle-provider.c
+++ b/providers/oracle/gda-oracle-provider.c
@@ -1931,8 +1931,35 @@ 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 */
 				GObject *obj;
-				g_object_unref (ps);
+				GdaOraclePStmt *tps;
+				if (!gda_oracle_provider_statement_prepare (provider, cnc,
+									    rstmt, error)) {
+					g_object_unref (ps);
+					return NULL;
+				}
+				tps = (GdaOraclePStmt *)
+					gda_connection_get_prepared_statement (cnc, rstmt);
+
+				/* 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);
+
+				/* execute rstmt (it will use @ps) */
 				obj = gda_oracle_provider_statement_execute (provider, cnc,
 									     rstmt, params,
 									     model_usage,
@@ -1940,15 +1967,14 @@ 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);
 				g_object_unref (rstmt);
-				if (GDA_IS_DATA_SELECT (obj)) {
-					GdaPStmt *pstmt;
-					g_object_get (obj, "prepared-stmt", &pstmt, NULL);
-					if (pstmt) {
-						gda_pstmt_set_gda_statement (pstmt, stmt);
-						g_object_unref (pstmt);
-					}
-				}
+				g_object_unref (ps);
 				return obj;
 			}
 		}
diff --git a/providers/postgres/gda-postgres-provider.c b/providers/postgres/gda-postgres-provider.c
index 6adca14..85db58e 100644
--- a/providers/postgres/gda-postgres-provider.c
+++ b/providers/postgres/gda-postgres-provider.c
@@ -2017,13 +2017,39 @@ gda_postgres_provider_statement_execute (GdaServerProvider *provider, GdaConnect
 			else if (!rstmt)
 				return NULL;
 			else {
-				GObject *obj;
 				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);
 
+				/* 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 */
+				GObject *obj;
+				GdaPostgresPStmt *tps;
+				if (!gda_postgres_provider_statement_prepare (provider, cnc,
+									      rstmt, error))
+					return NULL;
+				tps = (GdaPostgresPStmt *)
+					gda_connection_get_prepared_statement (cnc, rstmt);
+
+				/* 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);
+
+				/* execute rstmt (it will use @ps) */
 				obj = gda_postgres_provider_statement_execute (provider, cnc,
 									       rstmt, params,
 									       model_usage,
@@ -2031,15 +2057,13 @@ gda_postgres_provider_statement_execute (GdaServerProvider *provider, GdaConnect
 									       last_inserted_row,
 									       task_id, async_cb,
 									       cb_data, error);
+
+				/* 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);
-				if (GDA_IS_DATA_SELECT (obj)) {
-					GdaPStmt *pstmt;
-					g_object_get (obj, "prepared-stmt", &pstmt, NULL);
-					if (pstmt) {
-						gda_pstmt_set_gda_statement (pstmt, stmt);
-						g_object_unref (pstmt);
-					}
-				}
 				return obj;
 			}
 		}
diff --git a/providers/skel-implementation/capi/gda-capi-provider.c b/providers/skel-implementation/capi/gda-capi-provider.c
index 653f9ea..764d027 100644
--- a/providers/skel-implementation/capi/gda-capi-provider.c
+++ b/providers/skel-implementation/capi/gda-capi-provider.c
@@ -1181,7 +1181,31 @@ 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 */
 				GObject *obj;
+				GdaCapiPStmt *tps;
+				if (!gda_capi_provider_statement_prepare (provider, cnc,
+									    rstmt, error))
+					return NULL;
+				tps = (GdaCapiPStmt *)
+					gda_connection_get_prepared_statement (cnc, rstmt);
+
+				/* 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);
+
+				/* execute rstmt (it will use @ps) */
 				obj = gda_capi_provider_statement_execute (provider, cnc,
 									   rstmt, params,
 									   model_usage,
@@ -1189,15 +1213,13 @@ gda_capi_provider_statement_execute (GdaServerProvider *provider, GdaConnection
 									   last_inserted_row,
 									   task_id, async_cb,
 									   cb_data, error);
+
+				/* revert adaptations */
+				/* TO_ADD: ps->capi_stmt = hps.capi_stmt; */
+
+				gda_connection_add_prepared_statement (cnc, rstmt, (GdaPStmt *) tps);
+				g_object_unref (tps);
 				g_object_unref (rstmt);
-				if (GDA_IS_DATA_SELECT (obj)) {
-					GdaPStmt *pstmt;
-					g_object_get (obj, "prepared-stmt", &pstmt, NULL);
-					if (pstmt) {
-						gda_pstmt_set_gda_statement (pstmt, stmt);
-						g_object_unref (pstmt);
-					}
-				}
 				return obj;
 			}
 		}
diff --git a/providers/web/gda-web-provider.c b/providers/web/gda-web-provider.c
index 4500f01..9061126 100644
--- a/providers/web/gda-web-provider.c
+++ b/providers/web/gda-web-provider.c
@@ -1572,25 +1572,49 @@ gda_web_provider_statement_execute (GdaServerProvider *provider, GdaConnection *
 			else if (!rstmt)
 				return NULL;
 			else {
-				GObject *obj;
-				g_object_unref (ps);
 				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 */
+				GObject *obj;
+				GdaWebPStmt *tps;
+				if (!gda_web_provider_statement_prepare (provider, cnc,
+									 rstmt, error)) {
+					g_object_unref (ps);
+					return NULL;
+				}
+				tps = (GdaWebPStmt *)
+					gda_connection_get_prepared_statement (cnc, rstmt);
+
+				/* 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);
+
+				/* execute rstmt (it will use @ps) */
 				obj = gda_web_provider_statement_execute (provider, cnc,
-									  rstmt, params,
-									  model_usage,
-									  col_types,
-									  last_inserted_row,
-									  task_id, async_cb,
-									  cb_data, error);
+									     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);
 				g_object_unref (rstmt);
-				if (GDA_IS_DATA_SELECT (obj)) {
-					GdaPStmt *pstmt;
-					g_object_get (obj, "prepared-stmt", &pstmt, NULL);
-					if (pstmt) {
-						gda_pstmt_set_gda_statement (pstmt, stmt);
-						g_object_unref (pstmt);
-					}
-				}
+				g_object_unref (ps);
 				return obj;
 			}
 		}



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