libgda r3335 - in trunk: . providers/mysql



Author: vivien
Date: Wed Feb 25 21:24:07 2009
New Revision: 3335
URL: http://svn.gnome.org/viewvc/libgda?rev=3335&view=rev

Log:
2009-02-25  Vivien Malerba <malerba gnome-db org>

	* providers/mysql: more work on the MySQL provider:
	  - some work on the parameters' binding to use the correct type (not
	    always MYSQL_TYPE_STRING
	  - don't pass the bound parameters to the GdaMysqlPStmt as it does not
	    use them
	  - double free problem in GdaMysqlRecordset


Modified:
   trunk/ChangeLog
   trunk/providers/mysql/gda-mysql-provider.c
   trunk/providers/mysql/gda-mysql-pstmt.c
   trunk/providers/mysql/gda-mysql-pstmt.h
   trunk/providers/mysql/gda-mysql-recordset.c

Modified: trunk/providers/mysql/gda-mysql-provider.c
==============================================================================
--- trunk/providers/mysql/gda-mysql-provider.c	(original)
+++ trunk/providers/mysql/gda-mysql-provider.c	Wed Feb 25 21:24:07 2009
@@ -1321,8 +1321,8 @@
 			(GDA_HOLDER(current->data));
 		if (id) {
 			param_ids = g_slist_append (param_ids, g_strdup (id));
-			g_print ("MYSQL preparation: param id=%s\n", id);
-		} else {
+		}
+		else {
 			g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
 				     GDA_SERVER_PROVIDER_PREPARE_STMT_ERROR,
 				     "%s", _("Unnamed statement parameter is not allowed in prepared statement."));
@@ -1417,7 +1417,8 @@
 		_gda_mysql_make_error (cdata->cnc, NULL, mysql_stmt, error);
 		mysql_stmt_close (mysql_stmt);
 		ps = NULL;
-	} else {
+	}
+	else {
 		ps = gda_mysql_pstmt_new (cdata->cnc, cdata->mysql, mysql_stmt);
 		_GDA_PSTMT(ps)->param_ids = NULL;
 		_GDA_PSTMT(ps)->sql = g_strdup (sql);
@@ -1426,6 +1427,14 @@
 	return ps;
 }
 
+static void
+free_bind_param_data (GSList *mem_to_free)
+{
+	if (mem_to_free) {
+		g_slist_foreach (mem_to_free, (GFunc) g_free, NULL);
+		g_slist_free (mem_to_free);
+	}
+}
 
 /*
  * Execute statement request
@@ -1524,15 +1533,15 @@
 	int i;
 	
 	gint nb_params = g_slist_length (_GDA_PSTMT (ps)->param_ids);
-	char **param_values = g_new0 (char *, nb_params + 1);
-        int *param_lengths = g_new0 (int, nb_params + 1);
-        int *param_formats = g_new0 (int, nb_params + 1);
 	/*g_print ("NB=%d, SQL=%s\n", nb_params, _GDA_PSTMT(ps)->sql);*/
 
 	MYSQL_BIND *mysql_bind_param = NULL;
+	GSList *mem_to_free = NULL;
 
-	if (nb_params > 0)
+	if (nb_params > 0) {
 		mysql_bind_param = g_new0 (MYSQL_BIND, nb_params);
+		mem_to_free = g_slist_prepend (mem_to_free, mysql_bind_param);
+	}
 
 	for (i = 0, list = _GDA_PSTMT (ps)->param_ids; list; list = list->next, i++) {
 		const gchar *pname = (gchar *) list->data;
@@ -1556,7 +1565,6 @@
 			}
 		}
 		if (!h) {
-
 			if (!allow_noparam) {
 				gchar *str;
 				str = g_strdup_printf (_("Missing parameter '%s' to execute query"), pname);
@@ -1566,10 +1574,11 @@
 					     GDA_SERVER_PROVIDER_MISSING_PARAM_ERROR, "%s", str);
 				g_free (str);
 				break;
-			} else {
+			}
+			else {
                                 /* bind param to NULL */
-                                //TO_IMPLEMENT;
-				param_values[i] = NULL;
+				mysql_bind_param[i].buffer_type = MYSQL_TYPE_NULL;
+				mysql_bind_param[i].is_null = (my_bool*)1;
                                 empty_rs = TRUE;
                                 continue;
 			}
@@ -1585,10 +1594,11 @@
 					     GDA_SERVER_PROVIDER_MISSING_PARAM_ERROR, "%s", str);
 				g_free (str);
 				break;
-			} else {
+			}
+			else {
                                 /* bind param to NULL */
-				//TO_IMPLEMENT;
-				param_values[i] = NULL;
+				mysql_bind_param[i].buffer_type = MYSQL_TYPE_NULL;
+				mysql_bind_param[i].is_null = (my_bool*)1;
                                 empty_rs = TRUE;
                                 continue;
                         }
@@ -1598,51 +1608,125 @@
 		const GValue *value = gda_holder_get_value (h);
 
 		if (value == NULL || gda_value_is_null (value)) {
-			param_values[i] = NULL;
-		} else if ((G_VALUE_TYPE(value) == G_TYPE_DATE) ||
-			   (G_VALUE_TYPE(value) == GDA_TYPE_TIME) ||
-			   (G_VALUE_TYPE(value) == GDA_TYPE_TIMESTAMP)) {
-			GdaHandlerTime *handler_time = (GdaHandlerTime *) gda_server_provider_get_data_handler_g_type
-				(provider, cnc, G_VALUE_TYPE(value));
-			g_assert (handler_time);
-			param_values[i] = gda_handler_time_get_no_locale_str_from_value (handler_time,
-											 value);
-			//g_print ("--- TIME=%s\n", param_values[i]);
-		} else {
-			GdaDataHandler *data_handler = gda_server_provider_get_data_handler_g_type
-				(provider, cnc, G_VALUE_TYPE(value));
-			if (data_handler == NULL)
-				param_values[i] = NULL;
-			else
-				param_values[i] = gda_data_handler_get_str_from_value (data_handler,
-										       value);
-			//g_print ("--- PV=%s\n", param_values[i]);
-		}
-
-		mysql_bind_param[i].buffer_type = MYSQL_TYPE_STRING;
-		mysql_bind_param[i].buffer = g_strdup (param_values[i]);
-		mysql_bind_param[i].buffer_length = strlen (param_values[i]);
-		mysql_bind_param[i].length = g_malloc0 (sizeof(unsigned long));
-		*(mysql_bind_param[i].length) = mysql_bind_param[i].buffer_length;
+			mysql_bind_param[i].buffer_type = MYSQL_TYPE_NULL;
+			mysql_bind_param[i].is_null = (my_bool*)1;
+		}
+		else if (G_VALUE_TYPE(value) == GDA_TYPE_TIMESTAMP) {
+			const GdaTimestamp *ts;
+
+			ts = gda_value_get_timestamp (value);
+			if (!ts) {
+				mysql_bind_param[i].buffer_type = MYSQL_TYPE_NULL;
+				mysql_bind_param[i].is_null = (my_bool*)1;
+			}
+			else {
+				MYSQL_TIME *mtime;
+				mtime = g_new0 (MYSQL_TIME, 1);
+				mem_to_free = g_slist_prepend (mem_to_free, mtime);
+				mtime->year = ts->year;
+				mtime->month = ts->month;
+				mtime->day = ts->day;
+				mtime->hour = ts->hour;
+				mtime->minute = ts->minute;
+				mtime->second = ts->second;
+				mtime->second_part = ts->fraction;
+
+				mysql_bind_param[i].buffer_type= MYSQL_TYPE_TIMESTAMP;
+				mysql_bind_param[i].buffer= (char *)mtime;
+				mysql_bind_param[i].buffer_length = sizeof (MYSQL_TIME);
+			}
+		}
+		else if (G_VALUE_TYPE(value) == GDA_TYPE_TIME) {
+			const GdaTime *ts;
+
+			ts = gda_value_get_time (value);
+			if (!ts) {
+				mysql_bind_param[i].buffer_type = MYSQL_TYPE_NULL;
+				mysql_bind_param[i].is_null = (my_bool*)1;
+			}
+			else {
+				MYSQL_TIME *mtime;
+				mtime = g_new0 (MYSQL_TIME, 1);
+				mem_to_free = g_slist_prepend (mem_to_free, mtime);
+				mtime->hour = ts->hour;
+				mtime->minute = ts->minute;
+				mtime->second = ts->second;
+				mtime->second_part = ts->fraction;
+
+				mysql_bind_param[i].buffer_type= MYSQL_TYPE_TIME;
+				mysql_bind_param[i].buffer= (char *)mtime;
+				mysql_bind_param[i].buffer_length = sizeof (MYSQL_TIME);
+			}
+		}
+		else if (G_VALUE_TYPE(value) == G_TYPE_DATE) {
+			const GDate *ts;
+
+			ts = (GDate*) g_value_get_boxed (value);
+			if (!ts) {
+				mysql_bind_param[i].buffer_type = MYSQL_TYPE_NULL;
+				mysql_bind_param[i].is_null = (my_bool*)1;
+			}
+			else {
+				MYSQL_TIME *mtime;
+				mtime = g_new0 (MYSQL_TIME, 1);
+				mem_to_free = g_slist_prepend (mem_to_free, mtime);
+				mtime->year = ts->year;
+				mtime->month = ts->month;
+				mtime->day = ts->day;
+
+				mysql_bind_param[i].buffer_type= MYSQL_TYPE_DATE;
+				mysql_bind_param[i].buffer= (char *)mtime;
+				mysql_bind_param[i].buffer_length = sizeof (MYSQL_TIME);
+			}
+		}
+		else if (G_VALUE_TYPE(value) == G_TYPE_STRING) {
+			const gchar *str;
+			str = g_value_get_string (value);
+			if (!str) {
+				mysql_bind_param[i].buffer_type = MYSQL_TYPE_NULL;
+				mysql_bind_param[i].is_null = (my_bool*)1;
+			}
+			else {
+				mysql_bind_param[i].buffer_type= MYSQL_TYPE_STRING;
+				mysql_bind_param[i].buffer= (char *) str;
+				mysql_bind_param[i].buffer_length = strlen (str);
+				mysql_bind_param[i].length = NULL; /* str is 0 terminated */
+			}
+		}
+		else {
+			gchar *str;
+			GdaDataHandler *data_handler =
+				gda_server_provider_get_data_handler_g_type (provider, cnc, 
+									     G_VALUE_TYPE (value));
+			if (data_handler == NULL) {
+				TO_IMPLEMENT;
+				/* there is an error here */
+				str = NULL;
+			}
+			else {
+				str = gda_data_handler_get_str_from_value (data_handler, value);
+				mem_to_free = g_slist_prepend (mem_to_free, str);
+				mysql_bind_param[i].buffer_type = MYSQL_TYPE_STRING;
+				mysql_bind_param[i].buffer = str;
+				mysql_bind_param[i].buffer_length = strlen (str);
+				mysql_bind_param[i].length = NULL; /* str is 0 terminated */
+			}
+		}
 	}
 		
 	if (mysql_bind_param && mysql_stmt_bind_param (ps->mysql_stmt, mysql_bind_param)) {
-		g_warning ("mysql_stmt_bind_param failed: %s\n", mysql_stmt_error (ps->mysql_stmt));
+		//g_warning ("mysql_stmt_bind_param failed: %s\n", mysql_stmt_error (ps->mysql_stmt));
+		event = _gda_mysql_make_error (cnc, cdata->mysql, ps->mysql_stmt, error);
 	}
 
-	ps->mysql_bind_param = mysql_bind_param;
-
 	if (event) {
 		gda_connection_add_event (cnc, event);
-
-		g_strfreev (param_values);
-		g_free (param_lengths);
-		g_free (param_formats);
-
 		g_object_unref (ps);
+		free_bind_param_data (mem_to_free);
 		return NULL;
 	}
 
+
 	/* use cursor when retrieving result */
 	if ((model_usage & GDA_STATEMENT_MODEL_RANDOM_ACCESS) == 0 &&
 	    gda_statement_get_statement_type (stmt) == GDA_SQL_STATEMENT_SELECT) {
@@ -1651,6 +1735,7 @@
 		if (mysql_stmt_attr_set (ps->mysql_stmt, STMT_ATTR_CURSOR_TYPE, (void *) &cursor_type)) {
 			_gda_mysql_make_error (cnc, NULL, ps->mysql_stmt, NULL);
 			g_object_unref (ps);
+			free_bind_param_data (mem_to_free);
 			return NULL;
 		}
 #else
@@ -1676,12 +1761,14 @@
                 stmt_for_empty = gda_select_alter_select_for_empty (stmt, error);
                 if (!stmt_for_empty) {
 			g_object_unref (ps);
+			free_bind_param_data (mem_to_free);
                         return NULL;
 		}
                 sql_for_empty = gda_statement_to_sql (stmt_for_empty, NULL, error);
                 g_object_unref (stmt_for_empty);
                 if (!sql_for_empty) {
 			g_object_unref (ps);
+			free_bind_param_data (mem_to_free);
                         return NULL;
 		}
 
@@ -1690,21 +1777,20 @@
 		if (mysql_stmt_prepare (ps->mysql_stmt, sql_for_empty, strlen (sql_for_empty))) {
 			_gda_mysql_make_error (cdata->cnc, NULL, ps->mysql_stmt, error);
 			g_object_unref (ps);
+			free_bind_param_data (mem_to_free);
 			return NULL;
 		}
 
 		/* Execute the 'sql_for_empty' SQL code */
                 g_free (sql_for_empty);
-
-		//TO_IMPLEMENT;
 	}
 
 	
 	GObject *return_value = NULL;
 	if (mysql_stmt_execute (ps->mysql_stmt)) {
 		event = _gda_mysql_make_error (cnc, NULL, ps->mysql_stmt, error);
-	} else {
-
+	}
+	else {
 		/* execute prepared statement using C API depending on its kind */
 		if (!g_ascii_strncasecmp (_GDA_PSTMT (ps)->sql, "SELECT", 6) ||
 		    !g_ascii_strncasecmp (_GDA_PSTMT (ps)->sql, "SHOW", 4) ||
@@ -1713,7 +1799,8 @@
 			
 			if (mysql_stmt_store_result (ps->mysql_stmt)) {
 				_gda_mysql_make_error (cnc, NULL, ps->mysql_stmt, error);
-			} else {
+			}
+			else {
 				GdaDataModelAccessFlags flags;
 
 				if (model_usage & GDA_STATEMENT_MODEL_RANDOM_ACCESS)
@@ -1724,14 +1811,12 @@
 				return_value = (GObject *) gda_mysql_recordset_new (cnc, ps, params, flags, col_types);
 				gda_connection_internal_statement_executed (cnc, stmt, params, NULL); /* required: help @cnc keep some stats */
 			}
-			
-		} else {
+		}
+		else {
 			my_ulonglong affected_rows = (my_ulonglong)~0;
 
-			// TO_IMPLEMENT;
 			/* 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;
@@ -1745,12 +1830,14 @@
                                         (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 {
+			}
+			else {
 				return_value = (GObject *) gda_data_model_array_new (0);
 			}
 		}
 	}
 	g_object_unref (ps);
+	free_bind_param_data (mem_to_free);
 	return return_value;
 }
 

Modified: trunk/providers/mysql/gda-mysql-pstmt.c
==============================================================================
--- trunk/providers/mysql/gda-mysql-pstmt.c	(original)
+++ trunk/providers/mysql/gda-mysql-pstmt.c	Wed Feb 25 21:24:07 2009
@@ -84,7 +84,6 @@
 	
 	/* initialize specific parts of @pstmt */
 	// TO_IMPLEMENT;
-	pstmt->mysql_bind_param = NULL;
 	pstmt->mysql_bind_result = NULL;
 }
 
@@ -100,13 +99,6 @@
 		mysql_stmt_close (pstmt->mysql_stmt);
 
 	gint i;
-	for (i = 0; i < g_slist_length (((GdaPStmt *) pstmt)->param_ids); ++i) {
-		g_free (pstmt->mysql_bind_param[i].buffer);
-		g_free (pstmt->mysql_bind_param[i].length);
-	}
-	g_free (pstmt->mysql_bind_param);
-	pstmt->mysql_bind_param = NULL;
-
 	for (i = 0; i < ((GdaPStmt *) pstmt)->ncols; ++i) {
 		g_free (pstmt->mysql_bind_result[i].buffer);
 		g_free (pstmt->mysql_bind_result[i].is_null);

Modified: trunk/providers/mysql/gda-mysql-pstmt.h
==============================================================================
--- trunk/providers/mysql/gda-mysql-pstmt.h	(original)
+++ trunk/providers/mysql/gda-mysql-pstmt.h	Wed Feb 25 21:24:07 2009
@@ -46,7 +46,6 @@
 	MYSQL_STMT     *mysql_stmt;
 	gboolean        stmt_used; /* TRUE if a recorset already uses this prepared statement,
                                     * necessary because only one recordset can use mysql_stmt at a time */
-	MYSQL_BIND     *mysql_bind_param;
 	MYSQL_BIND     *mysql_bind_result;
 };
 

Modified: trunk/providers/mysql/gda-mysql-recordset.c
==============================================================================
--- trunk/providers/mysql/gda-mysql-recordset.c	(original)
+++ trunk/providers/mysql/gda-mysql-recordset.c	Wed Feb 25 21:24:07 2009
@@ -84,9 +84,7 @@
 
 	gint            chunk_size;    /* Number of rows to fetch at a time when iterating forward/backward. */
 	gint            chunks_read;   /* Number of times that we've iterated forward/backward. */
-	//
 	GdaRow         *tmp_row;       /* Used in cursor mode to store a reference to the latest #GdaRow. */
-	//
 };
 static GObjectClass *parent_class = NULL;
 
@@ -660,7 +658,6 @@
 					 (timevalue.month != 0) ? timevalue.month : 1,
 					 (timevalue.year != 0) ? timevalue.year : 1970);
 				g_value_take_boxed (value, date);
-				g_date_free (date);
 			} else if (type == GDA_TYPE_TIMESTAMP) {
 				GdaTimestamp timestamp = {
 					.year = timevalue.year,



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