[libgda/gtk3] MySQL provider: handle statements where the prepared statement API doe snot work



commit ccd46b3d1922e9e28c018e0fbc555bf95b0feaf9
Author: Vivien Malerba <malerba gnome-db org>
Date:   Fri Oct 29 15:56:37 2010 +0200

    MySQL provider: handle statements where the prepared statement API doe snot work
    
    it seems some statements can't be used with MySQL's prepared statament API,
    and then one gets the "This command is not supported in the prepared statement protocol yet"
    error, see http://bugs.mysql.com/bug.php?id=6415

 providers/mysql/gda-mysql-provider.c |   85 ++++++++++++++++++++++++----------
 providers/mysql/gda-mysql.h          |    1 +
 2 files changed, 62 insertions(+), 24 deletions(-)
---
diff --git a/providers/mysql/gda-mysql-provider.c b/providers/mysql/gda-mysql-provider.c
index 5317461..3a45fce 100644
--- a/providers/mysql/gda-mysql-provider.c
+++ b/providers/mysql/gda-mysql-provider.c
@@ -1817,9 +1817,11 @@ gda_mysql_provider_statement_prepare (GdaServerProvider  *provider,
 static GdaMysqlPStmt *
 prepare_stmt_simple (MysqlConnectionData  *cdata,
 		     const gchar          *sql,
-		     GError              **error)
+		     GError              **error,
+		     gboolean *out_protocol_error)
 {
 	GdaMysqlPStmt *ps = NULL;
+	*out_protocol_error = FALSE;
 	g_return_val_if_fail (sql != NULL, NULL);
 
 	MYSQL_STMT *mysql_stmt = mysql_stmt_init (cdata->mysql);
@@ -1837,6 +1839,8 @@ prepare_stmt_simple (MysqlConnectionData  *cdata,
 	
 	if (mysql_stmt_prepare (mysql_stmt, sql, strlen (sql))) {
 		_gda_mysql_make_error (cdata->cnc, NULL, mysql_stmt, error);
+		if (mysql_stmt_errno (mysql_stmt) == ER_UNSUPPORTED_PS)
+			*out_protocol_error = TRUE;
 		mysql_stmt_close (mysql_stmt);
 		ps = NULL;
 	}
@@ -2096,12 +2100,50 @@ gda_mysql_provider_statement_execute (GdaServerProvider               *provider,
 			 */
 			gchar *sql = gda_mysql_provider_statement_to_sql (provider, cnc, stmt, 
 									  params, 0, NULL, error);
+			gboolean proto_error;
 			if (!sql)
 				return NULL;
-			ps = prepare_stmt_simple (cdata, sql, error);
+			ps = prepare_stmt_simple (cdata, sql, error, &proto_error);
+			if (!ps) {
+				if (proto_error) {
+					/* MySQL's "command is not supported in the prepared
+					 * statement protocol yet" error
+					 * => try to execute the SQL using mysql_real_query() */
+					GdaConnectionEvent *event;
+					if (mysql_real_query (cdata->mysql, sql, strlen (sql))) {
+						event = _gda_mysql_make_error (cnc, cdata->mysql, NULL, error);
+						gda_connection_add_event (cnc, event);
+						g_free (sql);
+						return NULL;
+					}
+
+					g_free (sql);
+					my_ulonglong affected_rows;
+					/* Create a #GdaSet containing "IMPACTED_ROWS" */
+					/* Create GdaConnectionEvent notice with the type of command and impacted rows */
+					affected_rows = mysql_affected_rows (cdata->mysql);
+					if (affected_rows == (my_ulonglong)~0) {
+						TO_IMPLEMENT;
+						return (GObject *) gda_data_model_array_new (0);
+					}
+					else {
+						gchar *str;
+						event = gda_connection_point_available_event (cnc, GDA_CONNECTION_EVENT_NOTICE);
+						str = g_strdup_printf ("%llu", affected_rows);
+						gda_connection_event_set_description (event, str);
+						g_free (str);
+						
+						gda_connection_internal_statement_executed (cnc, stmt, params, event); /* required: help @cnc keep some stats */
+						return (GObject *) gda_set_new_inline
+							(1, "IMPACTED_ROWS", G_TYPE_INT, (int) affected_rows);
+					}
+				}
+				else {
+					g_free (sql);
+					return NULL;
+				}
+			}
 			g_free (sql);
-			if (!ps)
-				return NULL;
 		}
 		else {
 			ps = (GdaMysqlPStmt *) gda_connection_get_prepared_statement (cnc, stmt);
@@ -2477,11 +2519,13 @@ gda_mysql_provider_statement_execute (GdaServerProvider               *provider,
 	}
 	else {
 		/* execute prepared statement using C API depending on its kind */
-		if (!g_ascii_strncasecmp (_GDA_PSTMT (ps)->sql, "SELECT", 6) ||
+		my_ulonglong affected_rows;
+		affected_rows = mysql_stmt_affected_rows (ps->mysql_stmt);
+		if ((affected_rows == (my_ulonglong)~0) ||
+		    !g_ascii_strncasecmp (_GDA_PSTMT (ps)->sql, "SELECT", 6) ||
 		    !g_ascii_strncasecmp (_GDA_PSTMT (ps)->sql, "SHOW", 4) ||
 		    !g_ascii_strncasecmp (_GDA_PSTMT (ps)->sql, "DESCRIBE", 8) ||
 		    !g_ascii_strncasecmp (_GDA_PSTMT (ps)->sql, "EXPLAIN", 7)) {
-			
 			if (mysql_stmt_store_result (ps->mysql_stmt)) {
 				_gda_mysql_make_error (cnc, NULL, ps->mysql_stmt, error);
 			}
@@ -2498,27 +2542,20 @@ gda_mysql_provider_statement_execute (GdaServerProvider               *provider,
 			}
 		}
 		else {
-			my_ulonglong affected_rows = (my_ulonglong)~0;
 
 			/* Create a #GdaSet containing "IMPACTED_ROWS" */
 			/* Create GdaConnectionEvent notice with the type of command and impacted rows */
-			affected_rows = mysql_stmt_affected_rows (ps->mysql_stmt);
-			if (affected_rows >= 0) {
-				GdaConnectionEvent *event;
-                                gchar *str;
-                                event = gda_connection_point_available_event (cnc, GDA_CONNECTION_EVENT_NOTICE);
-                                str = g_strdup_printf ("%llu", affected_rows);
-                                gda_connection_event_set_description (event, str);
-                                g_free (str);
-
-                                return_value = (GObject *) gda_set_new_inline
-                                        (1, "IMPACTED_ROWS", G_TYPE_INT, (int) affected_rows);
-
-				gda_connection_internal_statement_executed (cnc, stmt, params, event); /* required: help @cnc keep some stats */
-			}
-			else {
-				return_value = (GObject *) gda_data_model_array_new (0);
-			}
+			GdaConnectionEvent *event;
+			gchar *str;
+			event = gda_connection_point_available_event (cnc, GDA_CONNECTION_EVENT_NOTICE);
+			str = g_strdup_printf ("%llu", affected_rows);
+			gda_connection_event_set_description (event, str);
+			g_free (str);
+			
+			return_value = (GObject *) gda_set_new_inline
+				(1, "IMPACTED_ROWS", G_TYPE_INT, (int) affected_rows);
+			
+			gda_connection_internal_statement_executed (cnc, stmt, params, event); /* required: help @cnc keep some stats */
 
 			if (last_inserted_row) {
 				my_ulonglong last_row;
diff --git a/providers/mysql/gda-mysql.h b/providers/mysql/gda-mysql.h
index aa3f0b5..ef3ba9b 100644
--- a/providers/mysql/gda-mysql.h
+++ b/providers/mysql/gda-mysql.h
@@ -33,6 +33,7 @@
 #include <winsock.h>
 #endif
 #include <mysql.h>
+#include <mysqld_error.h>
 #include <gda-mysql-reuseable.h>
 
 /*



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