[libgda/LIBGDA_4.0] MySQL provider improvements and misc corrections



commit 3ab5ecef485d260810de06a8076d2a4d0fd6043a
Author: Vivien Malerba <malerba gnome-db org>
Date:   Sat Jul 18 14:09:35 2009 +0200

    MySQL provider improvements and misc corrections
    
    * MySQL: implemented BEGIN, COMMIT and ROLLBACK transactions
    * MySQL: added missing pieces to some server operations
    * example program corrections
    * tests corrections

 providers/mysql/gda-mysql-ddl.c         |   11 ++-
 providers/mysql/gda-mysql-provider.c    |  166 +++++++++++++++++++++++++++---
 samples/TableCopy/README                |    4 +-
 samples/TableCopy/table-copy.c          |    4 +-
 tests/providers/TYPES_SCHEMA_SQLite.xml |    2 +-
 tests/providers/prov-test-util.c        |    2 +-
 tests/test-cnc-utils.c                  |    2 +-
 7 files changed, 164 insertions(+), 27 deletions(-)
---
diff --git a/providers/mysql/gda-mysql-ddl.c b/providers/mysql/gda-mysql-ddl.c
index 0291565..4c0647b 100644
--- a/providers/mysql/gda-mysql-ddl.c
+++ b/providers/mysql/gda-mysql-ddl.c
@@ -64,7 +64,7 @@ gda_mysql_render_CREATE_DB (GdaServerProvider *provider, GdaConnection *cnc,
 	sql = string->str;
 	g_string_free (string, FALSE);
 
-	return sql;	
+	return sql;
 }
 
 gchar *
@@ -269,8 +269,13 @@ gda_mysql_render_CREATE_TABLE (GdaServerProvider *provider, GdaConnection *cnc,
 				}
 				g_string_append (string, ") REFERENCES ");
 				value = gda_server_operation_get_value_at (op, "/FKEY_S/%d/FKEY_REF_TABLE", i);
-				if (value && G_VALUE_HOLDS (value, G_TYPE_STRING) && g_value_get_string (value))
-					g_string_append (string, g_value_get_string (value));
+				if (value && G_VALUE_HOLDS (value, G_TYPE_STRING) && g_value_get_string (value)) {
+					gchar *tmp;
+					tmp = gda_sql_identifier_quote (g_value_get_string (value), cnc, NULL,
+									FALSE, FALSE);
+					g_string_append (string, tmp);
+					g_free (tmp);
+				}
 				else {
 					allok = FALSE;
 					g_set_error (error, 0, 0, "%s", _("No referenced table specified in foreign key constraint"));
diff --git a/providers/mysql/gda-mysql-provider.c b/providers/mysql/gda-mysql-provider.c
index f1d89c6..7658392 100644
--- a/providers/mysql/gda-mysql-provider.c
+++ b/providers/mysql/gda-mysql-provider.c
@@ -523,6 +523,18 @@ real_open_connection (const gchar  *host,
 	return mysql;
 }
 
+int
+gda_mysql_real_query_wrap (GdaConnection *cnc, MYSQL *mysql, const char *stmt_str, unsigned long length)
+{
+	GdaConnectionEvent *event;
+	
+	event = gda_connection_event_new (GDA_CONNECTION_EVENT_COMMAND);
+	gda_connection_event_set_description (event, stmt_str);
+	gda_connection_add_event (cnc, event);
+	
+	return mysql_real_query (mysql, stmt_str, length);
+}
+
 static gchar *
 get_mysql_version (MYSQL  *mysql)
 {
@@ -780,10 +792,7 @@ gda_mysql_provider_supports_operation (GdaServerProvider       *provider,
         switch (type) {
         case GDA_SERVER_OPERATION_CREATE_DB:
         case GDA_SERVER_OPERATION_DROP_DB:
-		return FALSE;
-
         case GDA_SERVER_OPERATION_CREATE_TABLE:
-		return TRUE;
         case GDA_SERVER_OPERATION_DROP_TABLE:
         case GDA_SERVER_OPERATION_RENAME_TABLE:
 
@@ -794,6 +803,7 @@ gda_mysql_provider_supports_operation (GdaServerProvider       *provider,
 
         case GDA_SERVER_OPERATION_CREATE_VIEW:
         case GDA_SERVER_OPERATION_DROP_VIEW:
+		return TRUE;
         default:
                 return FALSE;
         }
@@ -886,20 +896,37 @@ gda_mysql_provider_render_operation (GdaServerProvider   *provider,
 	/* actual rendering */
         switch (gda_server_operation_get_op_type (op)) {
         case GDA_SERVER_OPERATION_CREATE_DB:
+		sql = gda_mysql_render_CREATE_DB (provider, cnc, op, error);
+		break;
         case GDA_SERVER_OPERATION_DROP_DB:
-		sql = NULL;
+		sql = gda_mysql_render_DROP_DB (provider, cnc, op, error);
                 break;
         case GDA_SERVER_OPERATION_CREATE_TABLE:
                 sql = gda_mysql_render_CREATE_TABLE (provider, cnc, op, error);
                 break;
         case GDA_SERVER_OPERATION_DROP_TABLE:
+		sql = gda_mysql_render_DROP_TABLE (provider, cnc, op, error);
+		break;
         case GDA_SERVER_OPERATION_RENAME_TABLE:
+		sql = gda_mysql_render_RENAME_TABLE (provider, cnc, op, error);
+		break;
         case GDA_SERVER_OPERATION_ADD_COLUMN:
+		sql = gda_mysql_render_ADD_COLUMN (provider, cnc, op, error);
+		break;
+	case GDA_SERVER_OPERATION_DROP_COLUMN:
+		sql = gda_mysql_render_DROP_COLUMN (provider, cnc, op, error);
+		break;
         case GDA_SERVER_OPERATION_CREATE_INDEX:
+		sql = gda_mysql_render_CREATE_INDEX (provider, cnc, op, error);
+		break;
         case GDA_SERVER_OPERATION_DROP_INDEX:
+		sql = gda_mysql_render_DROP_INDEX (provider, cnc, op, error);
+		break;
         case GDA_SERVER_OPERATION_CREATE_VIEW:
+		sql = gda_mysql_render_CREATE_VIEW (provider, cnc, op, error);
+		break;
         case GDA_SERVER_OPERATION_DROP_VIEW:
-                sql = NULL;
+                sql = gda_mysql_render_DROP_VIEW (provider, cnc, op, error);
                 break;
         default:
                 g_assert_not_reached ();
@@ -933,10 +960,69 @@ gda_mysql_provider_perform_operation (GdaServerProvider               *provider,
 		g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
 	}
         optype = gda_server_operation_get_op_type (op);
-	switch (optype) {
-	case GDA_SERVER_OPERATION_CREATE_DB: 
-	case GDA_SERVER_OPERATION_DROP_DB: 
-        default: 
+	if (!cnc &&
+	    ((optype == GDA_SERVER_OPERATION_CREATE_DB) ||
+	     (optype == GDA_SERVER_OPERATION_DROP_DB))) {
+		const GValue *value;
+		MYSQL *mysql;
+		const gchar *login = NULL;
+		const gchar *password = NULL;
+		const gchar *host = NULL;
+		gint         port = -1;
+		const gchar *socket = NULL;
+		gboolean     usessl = FALSE;
+
+		value = gda_server_operation_get_value_at (op, "/SERVER_CNX_P/HOST");
+		if (value && G_VALUE_HOLDS (value, G_TYPE_STRING) && g_value_get_string (value))
+			host = g_value_get_string (value);
+		
+		value = gda_server_operation_get_value_at (op, "/SERVER_CNX_P/PORT");
+		if (value && G_VALUE_HOLDS (value, G_TYPE_INT) && (g_value_get_int (value) > 0))
+			port = g_value_get_int (value);
+
+		value = gda_server_operation_get_value_at (op, "/SERVER_CNX_P/UNIX_SOCKET");
+		if (value && G_VALUE_HOLDS (value, G_TYPE_STRING) && g_value_get_string (value))
+			socket = g_value_get_string (value);
+
+		value = gda_server_operation_get_value_at (op, "/SERVER_CNX_P/USE_SSL");
+		if (value && G_VALUE_HOLDS (value, G_TYPE_BOOLEAN) && g_value_get_boolean (value))
+			usessl = TRUE;
+
+		value = gda_server_operation_get_value_at (op, "/SERVER_CNX_P/ADM_LOGIN");
+		if (value && G_VALUE_HOLDS (value, G_TYPE_STRING) && g_value_get_string (value))
+			login = g_value_get_string (value);
+
+		value = gda_server_operation_get_value_at (op, "/SERVER_CNX_P/ADM_PASSWORD");
+		if (value && G_VALUE_HOLDS (value, G_TYPE_STRING) && g_value_get_string (value))
+			password = g_value_get_string (value);
+
+		mysql = real_open_connection (host, port, socket,
+                                              "mysql", login, password, usessl, FALSE, error);
+                if (!mysql)
+                        return FALSE;
+		else {
+			gchar *sql;
+			int res;
+			
+			sql = gda_server_provider_render_operation (provider, cnc, op, error);
+			if (!sql)
+				return FALSE;
+
+			res = mysql_query (mysql, sql);
+			g_free (sql);
+			
+			if (res) {
+				g_set_error (error, 0, 0, mysql_error (mysql));
+				mysql_close (mysql);
+				return FALSE;
+			}
+			else {
+				mysql_close (mysql);
+				return TRUE;
+			}
+		}
+	}
+	else {
 		/* use the SQL from the provider to perform the action */
 		return gda_server_provider_perform_operation_default (provider, cnc, op, error);
 	}
@@ -953,6 +1039,8 @@ gda_mysql_provider_begin_transaction (GdaServerProvider        *provider,
 				      GError                  **error)
 {
 	MysqlConnectionData *cdata;
+	gint rc;
+	GdaConnectionEvent *event = NULL;
 
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
 	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
@@ -961,9 +1049,39 @@ gda_mysql_provider_begin_transaction (GdaServerProvider        *provider,
 	if (!cdata) 
 		return FALSE;
 
-	TO_IMPLEMENT;
+	/* set isolation level */
+        switch (level) {
+        case GDA_TRANSACTION_ISOLATION_READ_COMMITTED :
+                rc = gda_mysql_real_query_wrap (cnc, cdata->mysql, "SET TRANSACTION ISOLATION LEVEL READ COMMITTED", 46);
+                break;
+        case GDA_TRANSACTION_ISOLATION_READ_UNCOMMITTED :
+                rc = gda_mysql_real_query_wrap (cnc, cdata->mysql, "SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED", 48);
+                break;
+        case GDA_TRANSACTION_ISOLATION_REPEATABLE_READ :
+                rc = gda_mysql_real_query_wrap (cnc, cdata->mysql, "SET TRANSACTION ISOLATION LEVEL REPEATABLE READ", 47);
+                break;
+        case GDA_TRANSACTION_ISOLATION_SERIALIZABLE :
+                rc = gda_mysql_real_query_wrap (cnc, cdata->mysql, "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE", 44);
+                break;
+        default :
+                rc = 0;
+        }
 
-	return FALSE;
+	if (rc != 0)
+                event = _gda_mysql_make_error (cnc, cdata->mysql, NULL, error);
+        else {
+                /* start the transaction */
+                rc = gda_mysql_real_query_wrap (cnc, cdata->mysql, "BEGIN", 5);
+                if (rc != 0)
+                        event = _gda_mysql_make_error (cnc, cdata->mysql, NULL, error);
+        }
+	
+	if (event)
+		return FALSE;
+	else {
+		gda_connection_internal_transaction_started (cnc, NULL, NULL, level);
+		return TRUE;
+	}
 }
 
 /*
@@ -976,6 +1094,7 @@ gda_mysql_provider_commit_transaction (GdaServerProvider  *provider,
 				       GError            **error)
 {
 	MysqlConnectionData *cdata;
+	gint rc;
 
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
 	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
@@ -984,9 +1103,15 @@ gda_mysql_provider_commit_transaction (GdaServerProvider  *provider,
 	if (!cdata) 
 		return FALSE;
 
-	TO_IMPLEMENT;
-
-	return FALSE;
+	rc = gda_mysql_real_query_wrap (cnc, cdata->mysql, "COMMIT", 6);
+	if (rc != 0) {
+		_gda_mysql_make_error (cnc, cdata->mysql, NULL, error);
+		return FALSE;
+	}
+	else {
+		gda_connection_internal_transaction_committed (cnc, NULL);
+		return TRUE;
+	}
 }
 
 /*
@@ -999,6 +1124,7 @@ gda_mysql_provider_rollback_transaction (GdaServerProvider  *provider,
 					 GError            **error)
 {
 	MysqlConnectionData *cdata;
+	gint rc;
 
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
 	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
@@ -1007,9 +1133,15 @@ gda_mysql_provider_rollback_transaction (GdaServerProvider  *provider,
 	if (!cdata) 
 		return FALSE;
 
-	TO_IMPLEMENT;
-
-	return FALSE;
+	rc = gda_mysql_real_query_wrap (cnc, cdata->mysql, "ROLLBACK", 8);
+	if (rc != 0) {
+		_gda_mysql_make_error (cnc, cdata->mysql, NULL, error);
+		return FALSE;
+	}
+	else {
+		gda_connection_internal_transaction_rolledback (cnc, NULL);
+		return TRUE;
+	}
 }
 
 /*
diff --git a/samples/TableCopy/README b/samples/TableCopy/README
index 3fb1ff0..c2607e2 100644
--- a/samples/TableCopy/README
+++ b/samples/TableCopy/README
@@ -23,7 +23,7 @@ containing all the data to copy, and:
 * in the 1st method, an INSERT query is created with place holders for the values to
   insert, and this query is executed for each row in the source data model (binding the
   parameters each time) - the price of the products is increased by 5% in the process
-* in the 2nd method, a GdaDataModelQuery is created and gda_data_model_import_from_model()
+* in the 2nd method, a GdaDataSelect is created and gda_data_model_import_from_model()
   is called to actually do the data copy
 
 The "table-copy-easier.c" file shows an easier way using virtual connections: the two opened connections are
@@ -41,4 +41,4 @@ and to run:
 > ./table-copy-easier
 
 After executing either of these programs, there should be a "copy.db" file containing
-the copied data.
\ No newline at end of file
+the copied data.
diff --git a/samples/TableCopy/table-copy.c b/samples/TableCopy/table-copy.c
index 92ce627..e80fbd6 100644
--- a/samples/TableCopy/table-copy.c
+++ b/samples/TableCopy/table-copy.c
@@ -58,7 +58,7 @@ get_products_contents (GdaConnection *cnc)
  * method 1 to copy the data model: 
  *
  * - Get the contents of the 'products' table as a 'source' data model, 
- * - create an INSERT GdaQuery with parameters, 
+ * - create an INSERT statement with parameters, 
  * - execute the query as many times as there are rows in the source data model, each time setting the parameters' 
  * - values with the source's contents.
  *
@@ -144,7 +144,7 @@ copy_products_1 (GdaConnection *s_cnc, GdaConnection *d_cnc)
  * method 2 to copy the data model: 
  *
  * - Get the contents of the 'products' table as a 'source' data model, 
- * - create a GdaDataModelQuery data model, 
+ * - create a GdaDataSelect data model, 
  * - directly copy the contents of the source data model into it.
  *
  * The price of the products is unchanged in the process.
diff --git a/tests/providers/TYPES_SCHEMA_SQLite.xml b/tests/providers/TYPES_SCHEMA_SQLite.xml
index 9d6b90f..c463a30 100644
--- a/tests/providers/TYPES_SCHEMA_SQLite.xml
+++ b/tests/providers/TYPES_SCHEMA_SQLite.xml
@@ -7,7 +7,7 @@
   <gda_array_data>
     <gda_array_row>
       <gda_value>blob</gda_value>
-      <gda_value>GdaBinary</gda_value>
+      <gda_value>GdaBlob</gda_value>
       <gda_value>Blob of data, stored exactly as it was input</gda_value>
       <gda_value isnull="t"/>
     </gda_array_row>
diff --git a/tests/providers/prov-test-util.c b/tests/providers/prov-test-util.c
index f067c4c..07929b2 100644
--- a/tests/providers/prov-test-util.c
+++ b/tests/providers/prov-test-util.c
@@ -125,7 +125,7 @@ compare_data_model_with_expected (GdaDataModel *model, const gchar *expected_fil
 gboolean
 prov_test_check_types_schema (GdaConnection *cnc)
 {
-if (!cnc || !gda_connection_is_opened (cnc)) {
+	if (!cnc || !gda_connection_is_opened (cnc)) {
 #ifdef CHECK_EXTRA_INFO
 		g_warning ("Connection is closed!");
 #endif
diff --git a/tests/test-cnc-utils.c b/tests/test-cnc-utils.c
index b7922d5..3f60fbf 100644
--- a/tests/test-cnc-utils.c
+++ b/tests/test-cnc-utils.c
@@ -116,7 +116,7 @@ test_cnc_setup_connection (const gchar *provider, const gchar *dbname, GError **
 		db_quark_list = gda_quark_list_new_from_string (db_params);
 		op = gda_prepare_drop_database (prov_info->id, dbname, NULL);
 		gda_quark_list_foreach (db_quark_list, (GHFunc) db_create_quark_foreach_func, op);
-		gda_perform_create_database (NULL, op, NULL);
+		gda_perform_drop_database (NULL, op, NULL);
 		g_object_unref (op);
 
 		op = gda_prepare_create_database (prov_info->id, dbname, NULL);



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