[libgda] gda-sqlite and virtual provider: improved destruction and tests



commit 972d402ed58a6b7ede86103833b18ad18fe40252
Author: Daniel Espinosa <esodan gmail com>
Date:   Wed Oct 3 17:51:02 2018 -0500

    gda-sqlite and virtual provider: improved destruction and tests

 libgda/sqlite/gda-sqlite-provider.c            |   3 +-
 libgda/sqlite/virtual/gda-vconnection-hub.c    |  41 +++++--
 libgda/sqlite/virtual/gda-virtual-connection.c |  17 ++-
 tests/data-models/check_vcnc.c                 | 163 ++++++++++++++++++-------
 4 files changed, 157 insertions(+), 67 deletions(-)
---
diff --git a/libgda/sqlite/gda-sqlite-provider.c b/libgda/sqlite/gda-sqlite-provider.c
index 770b9fe8c..d5c1cb05c 100644
--- a/libgda/sqlite/gda-sqlite-provider.c
+++ b/libgda/sqlite/gda-sqlite-provider.c
@@ -801,7 +801,8 @@ gda_sqlite_provider_dispose (GObject *object)
   GdaSqliteProvider *prov = GDA_SQLITE_PROVIDER (object);
   GdaSqliteProviderPrivate *priv = gda_sqlite_provider_get_instance_private (prov);
   g_weak_ref_clear (priv->connection);
-  g_free (priv->connection);
+  if (priv->connection)
+    g_free (priv->connection);
   priv->connection = NULL;
 }
 
diff --git a/libgda/sqlite/virtual/gda-vconnection-hub.c b/libgda/sqlite/virtual/gda-vconnection-hub.c
index dfe93dc43..615b82ba2 100644
--- a/libgda/sqlite/virtual/gda-vconnection-hub.c
+++ b/libgda/sqlite/virtual/gda-vconnection-hub.c
@@ -3,7 +3,7 @@
  * Copyright (C) 2008 - 2011 Murray Cumming <murrayc murrayc com>
  * Copyright (C) 2009 Bas Driessen <bas driessen xobas com>
  * Copyright (C) 2010 David King <davidk openismus com>
- * Copyright (C) 2017 Daniel Espinosa <esodan gmail com>
+ * Copyright (C) 2017-2018 Daniel Espinosa <esodan gmail com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -42,15 +42,15 @@ static void hub_connection_free (HubConnection *hc);
 static gboolean attach_hub_connection (GdaVconnectionHub *hub, HubConnection *hc, GError **error);
 static void detach_hub_connection (GdaVconnectionHub *hub, HubConnection *hc);
 
-static GdaSqlParser *internal_parser;
-
 struct _GdaVconnectionHubPrivate {
-       GSList *hub_connections; /* list of HubConnection structures */
+       GSList        *hub_connections; /* list of HubConnection structures */
+       GdaSqlParser *internal_parser;
 };
 
 static void gda_vconnection_hub_class_init (GdaVconnectionHubClass *klass);
 static void gda_vconnection_hub_init       (GdaVconnectionHub *cnc, GdaVconnectionHubClass *klass);
 static void gda_vconnection_hub_dispose   (GObject *object);
+static void gda_vconnection_hub_finalize   (GObject *object);
 static GObjectClass  *parent_class = NULL;
 
 static HubConnection *get_hub_cnc_by_ns (GdaVconnectionHub *hub, const gchar *ns);
@@ -67,9 +67,7 @@ gda_vconnection_hub_class_init (GdaVconnectionHubClass *klass)
        parent_class = g_type_class_peek_parent (klass);
 
        object_class->dispose = gda_vconnection_hub_dispose;
-
-       /* static objects */
-       internal_parser = gda_sql_parser_new ();
+       object_class->finalize = gda_vconnection_hub_finalize;
 }
 
 static void
@@ -77,6 +75,7 @@ gda_vconnection_hub_init (GdaVconnectionHub *cnc, G_GNUC_UNUSED GdaVconnectionHu
 {
        cnc->priv = g_new (GdaVconnectionHubPrivate, 1);
        cnc->priv->hub_connections = NULL;
+       cnc->priv->internal_parser = gda_sql_parser_new ();;
 }
 
 static void
@@ -89,16 +88,34 @@ gda_vconnection_hub_dispose (GObject *object)
        /* free memory */
        if (cnc->priv) {
                gda_connection_close ((GdaConnection *) cnc, NULL);
-               g_assert (!cnc->priv->hub_connections);
+               if (cnc->priv->hub_connections) {
+                       g_slist_free_full (cnc->priv->hub_connections, hub_connection_free);
+                       cnc->priv->hub_connections = NULL;
+               }
+               if (cnc->priv->internal_parser)
+                       g_object_unref (cnc->priv->internal_parser);
+       }
+
+       /* chain to parent class */
+       parent_class->dispose (object);
+}
+
+static void
+gda_vconnection_hub_finalize (GObject *object)
+{
+       GdaVconnectionHub *cnc = (GdaVconnectionHub *) object;
+
+       g_return_if_fail (GDA_IS_VCONNECTION_HUB (cnc));
 
+       /* free memory */
+       if (cnc->priv) {
                g_free (cnc->priv);
                cnc->priv = NULL;
        }
 
        /* chain to parent class */
-       parent_class->dispose (object);
+       parent_class->finalize (object);
 }
-
 GType
 gda_vconnection_hub_get_type (void)
 {
@@ -826,7 +843,7 @@ attach_hub_connection (GdaVconnectionHub *hub, HubConnection *hc, GError **error
        if (hc->ns) {
                GdaStatement *stmt;
                tmp = g_strdup_printf ("ATTACH ':memory:' AS %s", hc->ns);
-               stmt = gda_sql_parser_parse_string (internal_parser, tmp, NULL, NULL);
+               stmt = gda_sql_parser_parse_string (hub->priv->internal_parser, tmp, NULL, NULL);
                g_free (tmp);
                g_assert (stmt);
                if (gda_connection_statement_execute_non_select (GDA_CONNECTION (hub), stmt, NULL, NULL, 
error) == -1) {
@@ -991,7 +1008,7 @@ detach_hub_connection (GdaVconnectionHub *hub, HubConnection *hc)
                GdaStatement *stmt;
                gchar *tmp;
                tmp = g_strdup_printf ("DETACH %s", hc->ns);
-               stmt = gda_sql_parser_parse_string (internal_parser, tmp, NULL, NULL);
+               stmt = gda_sql_parser_parse_string (hub->priv->internal_parser, tmp, NULL, NULL);
                g_free (tmp);
                g_assert (stmt);
                gda_connection_statement_execute_non_select (GDA_CONNECTION (hub), stmt, NULL, NULL, NULL);
diff --git a/libgda/sqlite/virtual/gda-virtual-connection.c b/libgda/sqlite/virtual/gda-virtual-connection.c
index e1c4ea270..0221d0a6d 100644
--- a/libgda/sqlite/virtual/gda-virtual-connection.c
+++ b/libgda/sqlite/virtual/gda-virtual-connection.c
@@ -136,20 +136,19 @@ gda_virtual_connection_open (GdaVirtualProvider *virtual_provider, GdaConnection
 {
        g_return_val_if_fail (GDA_IS_VIRTUAL_PROVIDER (virtual_provider), NULL);
 
-       GdaConnection *cnc;
+       GdaConnection *cnc = NULL;
        cnc = _gda_server_provider_create_connection (GDA_SERVER_PROVIDER (virtual_provider), NULL, NULL,
                                                      NULL, options);
-       if (cnc) {
-               g_object_set (G_OBJECT (cnc), "provider", virtual_provider, NULL);
-               if (!gda_connection_open (cnc, error)) {
-                       g_object_unref (cnc);
-                       cnc = NULL;
-               }
-       }
-       else
+       if (!GDA_IS_CONNECTION (cnc)) {
                g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_PROVIDER_ERROR, "%s", 
                             _("Internal error: virtual provider does not implement the create_operation() 
virtual method"));
+               return NULL;
+       }
 
+       if (!gda_connection_open (cnc, error)) {
+               g_object_unref (cnc);
+               cnc = NULL;
+       }
        return cnc;
 }
 
diff --git a/tests/data-models/check_vcnc.c b/tests/data-models/check_vcnc.c
index 0838b9910..627a36088 100644
--- a/tests/data-models/check_vcnc.c
+++ b/tests/data-models/check_vcnc.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2011 - 2014 Vivien Malerba <malerba gnome-db org>
- * Copyright (C) 2017 Daniel Espinosa <esodan gmail com>
+ * Copyright (C) 2017,2018 Daniel Espinosa <esodan gmail com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -21,6 +21,7 @@
 #include <sql-parser/gda-sql-parser.h>
 #include <string.h>
 #include <unistd.h>
+#include <gio/gio.h>
 
 #define NTHREADS 50
 
@@ -34,26 +35,58 @@ static GdaDataModel *run_sql_select (GdaConnection *cnc, const gchar *sql,
 static gboolean run_sql_non_select (GdaConnection *cnc, const gchar *sql, GdaSet *params, GError **error);
 static GdaDataModel *assert_run_sql_select (GdaConnection *cnc, const gchar *sql,
                                            Action action, const gchar *compare_file);
-static void assert_run_sql_non_select (GdaConnection *cnc, const gchar *sql, GdaSet *params);
+static gboolean assert_run_sql_non_select (GdaConnection *cnc, const gchar *sql, GdaSet *params, GError 
**error);
 GdaDataModel *load_from_file (const gchar *filename);
 static void assert_data_model_equal (GdaDataModel *model, GdaDataModel *ref);
 
-static GdaConnection *open_destination_connection (void);
+typedef struct {
+  gint fails;
+  GMainLoop *loop;
+  GFile *fdb;
+} Data;
+
+static GdaConnection *open_destination_connection (Data *data);
 static void check_update_delete (GdaConnection *virtual);
 static void check_simultanous_select_random (GdaConnection *virtual);
 static void check_simultanous_select_forward (GdaConnection *virtual);
 static void check_threads_select_random (GdaConnection *virtual);
 static void check_date (GdaConnection *virtual);
 
+
+static gboolean test1 (Data *data);
+
 int
 main (int argc, char *argv[])
 {
+  GMainLoop *loop;
+  gda_init ();
+  loop = g_main_loop_new (NULL, FALSE);
+  Data *data = g_new0(Data, 1);
+  data->fails = 0;
+  data->loop = loop;
+  g_idle_add ((GSourceFunc) test1, data);
+  g_main_loop_run (loop);
+  if (data->fails != 0)
+    g_print ("FAIL %d\n", data->fails);
+  else
+    g_print ("All Ok\n");
+  g_main_loop_unref (loop);
+  if (G_IS_OBJECT (data->fdb)) {
+    if (g_file_query_exists (data->fdb, NULL)) {
+      g_file_delete (data->fdb, NULL, NULL);
+      g_object_unref (data->fdb);
+    }
+  }
+  g_free (data);
+  return 0;
+}
+
+static gboolean
+test1 (Data *data) {
        GError *error = NULL;   
        GdaConnection *virtual, *out_cnc;
        GdaVirtualProvider *provider;
        gchar *file;
-       
-       gda_init ();
 
        provider = gda_vprovider_hub_new ();
        virtual = gda_virtual_connection_open (provider, GDA_CONNECTION_OPTIONS_NONE, NULL);
@@ -66,16 +99,10 @@ main (int argc, char *argv[])
        file = g_build_filename (CHECK_FILES, "tests", "data-models", "city.csv", NULL);
        city_model = gda_data_model_import_new_file (file, TRUE, options);
        g_free (file);
-       g_print("Imported Data Model for CITIES:\n");
-       g_assert (GDA_IS_DATA_MODEL (city_model));
-       g_print ("%s", gda_data_model_dump_as_string (city_model));
        file = g_build_filename (CHECK_FILES, "tests", "data-models", "country.csv", NULL);
        country_model = gda_data_model_import_new_file (file, TRUE, options);
        g_free (file);
        g_object_unref (options);
-       g_print("Imported Data Model for COUNTRIES:\n");
-       g_assert (GDA_IS_DATA_MODEL (country_model));
-       g_print ("%s", gda_data_model_dump_as_string (country_model));
 
        /* Add data models to connection */
        if (!gda_vconnection_data_model_add_model (GDA_VCONNECTION_DATA_MODEL (virtual), city_model, "city", 
&error)) 
@@ -84,19 +111,23 @@ main (int argc, char *argv[])
                g_error ("Add country model error: %s\n", error && error->message ? error->message : "no 
detail");
 
        /* SQLite connection for outputs */
-        out_cnc = open_destination_connection ();
+    out_cnc = open_destination_connection (data);
+    if (out_cnc == NULL)
+      return FALSE;
 
        /* adding connections to the virtual connection */
         if (!gda_vconnection_hub_add (GDA_VCONNECTION_HUB (virtual), out_cnc, "out", &error)) {
                 g_print ("Could not add connection to virtual connection: %s\n",
                          error && error->message ? error->message : "No detail");
-                exit (1);
+                data->fails += 1;
+                g_main_loop_quit (data->loop);
+                return G_SOURCE_REMOVE;
         }
 
        check_update_delete (virtual);
 
        g_print ("*** Copying data into 'countries' virtual table...\n");
-       assert_run_sql_non_select (virtual, "INSERT INTO out.countries SELECT * FROM country", NULL);
+       assert_run_sql_non_select (virtual, "INSERT INTO out.countries SELECT * FROM country", NULL, NULL);
 
        check_simultanous_select_random (virtual);
        check_simultanous_select_forward (virtual);
@@ -106,50 +137,98 @@ main (int argc, char *argv[])
         if (! gda_connection_close (virtual, &error)) {
                g_print ("gda_connection_close(virtual) error: %s\n",
                          error && error->message ? error->message : "No detail");
-                exit (1);
+                data->fails += 1;
+                g_main_loop_quit (data->loop);
+                return G_SOURCE_REMOVE;
        }
         if (! gda_connection_close (out_cnc, &error)) {
                g_print ("gda_connection_close(out_cnc) error: %s\n",
                          error && error->message ? error->message : "No detail");
-                exit (1);
-       }
+                data->fails += 1;
+                g_main_loop_quit (data->loop);
+                return G_SOURCE_REMOVE;
+  }
+  g_main_loop_quit (data->loop);
+  return G_SOURCE_REMOVE;
+}
 
-       g_print ("All Ok\n");
-        return 0;
+static gchar*
+create_connection_string () {
+  GFile *db;
+  GFile *d;
+  GRand *rand;
+  gint i;
+
+  rand = g_rand_new ();
+  gchar** envp = g_get_environ ();
+  const gchar* build_dir = g_environ_getenv (envp, "GDA_TOP_BUILD_DIR");
+  gchar *sd = g_strdup_printf ("file://%s/tests/data-models", build_dir);
+  g_strfreev (envp);
+  d = g_file_new_for_uri (sd);
+  g_assert (g_file_query_exists (d, NULL));
+  i = g_rand_int (rand);
+  gchar *sdb = g_strdup_printf ("%s/vcnc%d", sd, i);
+  db = g_file_new_for_uri (sdb);
+  while (g_file_query_exists (db, NULL)) {
+    g_object_unref (db);
+    i++;
+    g_free (sdb);
+    sdb = g_strdup_printf ("%s/vcnc%d", sd, i);
+    db = g_file_new_for_uri (sdb);
+  }
+  g_free (sd);
+
+  gchar* path = g_file_get_path (d);
+  gchar *cstr = g_strdup_printf ("DB_DIR=%s;DB_NAME=vcnc%d", path, i);
+  g_free (path);
+  g_print ("Connecting using: %s\n", cstr);
+  g_object_unref (d);
+  g_object_unref (db);
+  return cstr;
 }
 
 GdaConnection *
-open_destination_connection (void)
+open_destination_connection (Data *data)
 {
         /* create connection */
         GdaConnection *cnc;
         GError *error = NULL;
-        cnc = gda_connection_new_from_string ("SQLite", "DB_DIR=.;DB_NAME=vcnc",
+
+        gchar *cstr = create_connection_string ();
+        cnc = gda_connection_new_from_string ("SQLite", cstr,
                                              NULL,
                                              GDA_CONNECTION_OPTIONS_NONE,
                                              &error);
+        g_free (cstr);
         if (!cnc) {
                 g_print ("Could not create connection to local SQLite database: %s\n",
                          error && error->message ? error->message : "No detail");
-                exit (1);
+                data->fails++;
+                g_main_loop_quit (data->loop);
+                return NULL;
         }
-       if (! gda_connection_open (cnc, &error)) {
-                g_print ("gda_connection_open() error: %s\n",
+        if (! gda_connection_open (cnc, &error)) {
+          g_print ("gda_connection_open() error: %s\n",
                          error && error->message ? error->message : "No detail");
-                exit (1);
-       }
+                data->fails++;
+                g_main_loop_quit (data->loop);
+                return NULL;
+        }
 
         /* table "cities" */
-        assert_run_sql_non_select (cnc, "DROP table IF EXISTS cities", NULL);
-        assert_run_sql_non_select (cnc, "CREATE table cities (name string not NULL primary key, countrycode 
string not null, population int)", NULL);
+        if (!assert_run_sql_non_select (cnc, "DROP table IF EXISTS cities", NULL, NULL)) {
+          g_object_unref (cnc);
+          cnc = open_destination_connection (data);
+        }
+        assert_run_sql_non_select (cnc, "CREATE table cities (name string not NULL primary key, countrycode 
string not null, population int)", NULL, NULL);
 
         /* table "countries" */
-        assert_run_sql_non_select (cnc, "DROP table IF EXISTS countries", NULL);
-        assert_run_sql_non_select (cnc, "CREATE table countries (code string not null primary key, name 
string not null)", NULL);
+        assert_run_sql_non_select (cnc, "DROP table IF EXISTS countries", NULL, NULL);
+        assert_run_sql_non_select (cnc, "CREATE table countries (code string not null primary key, name 
string not null)", NULL, NULL);
 
        /* table "misc" */
-        assert_run_sql_non_select (cnc, "DROP table IF EXISTS misc", NULL);
-        assert_run_sql_non_select (cnc, "CREATE table misc (ts timestamp, adate date, atime time)", NULL);
+        assert_run_sql_non_select (cnc, "DROP table IF EXISTS misc", NULL, NULL);
+        assert_run_sql_non_select (cnc, "CREATE table misc (ts timestamp, adate date, atime time)", NULL, 
NULL);
 
         return cnc;
 }
@@ -256,16 +335,10 @@ assert_run_sql_select (GdaConnection *cnc, const gchar *sql, Action action, cons
        return model;
 }
 
-static void
-assert_run_sql_non_select (GdaConnection *cnc, const gchar *sql, GdaSet *params)
+static gboolean
+assert_run_sql_non_select (GdaConnection *cnc, const gchar *sql, GdaSet *params, GError **error)
 {
-       GError *error = NULL;
-       if (! run_sql_non_select (cnc, sql, params, &error)) {
-               g_print ("Error executing [%s]: %s\n",
-                        sql,
-                        error && error->message ? error->message : "No detail");
-               exit (1);
-       }
+       return run_sql_non_select (cnc, sql, params, error);
 }
 
 GdaDataModel *
@@ -482,13 +555,13 @@ check_update_delete (GdaConnection *virtual)
 {
        /* Check DELETE and UPDATE */
        g_print ("*** Copying data into virtual 'cities' table...\n");
-       assert_run_sql_non_select (virtual, "INSERT INTO out.cities SELECT * FROM city WHERE population >= 
500000", NULL);
+       assert_run_sql_non_select (virtual, "INSERT INTO out.cities SELECT * FROM city WHERE population >= 
500000", NULL, NULL);
        g_print ("*** Showing list of cities WHERE population >= 1000000\n");
        assert_run_sql_select (virtual, "SELECT * FROM out.cities WHERE population >= 1000000 "
                               "ORDER BY name", ACTION_COMPARE, "cities1.xml");
 
        g_print ("*** Deleting data where population < 2000000...\n");
-       assert_run_sql_non_select (virtual, "DELETE FROM out.cities WHERE population < 2000000", NULL);
+       assert_run_sql_non_select (virtual, "DELETE FROM out.cities WHERE population < 2000000", NULL, NULL);
 
        g_print ("*** Showing (shorter) list of cities WHERE population >= 1000000\n");
        assert_run_sql_select (virtual, "SELECT * FROM out.cities WHERE population >= 1000000 "
@@ -496,7 +569,7 @@ check_update_delete (GdaConnection *virtual)
 
        g_print ("*** Updating data where population > 3000000...\n");
        assert_run_sql_non_select (virtual, "UPDATE out.cities SET population = 3000000 WHERE "
-                                  "population >= 3000000", NULL);
+                                  "population >= 3000000", NULL, NULL);
        
        g_print ("*** Showing list of cities WHERE population >= 2100000\n");
        assert_run_sql_select (virtual, "SELECT * FROM out.cities WHERE population >= 2100000 "
@@ -605,7 +678,7 @@ check_date (GdaConnection *virtual)
        g_date_free (adate);
 
        assert_run_sql_non_select (virtual, "INSERT INTO out.misc VALUES (##ts::timestamp, "
-                                  "##adate::date, ##atime::time)", set);
+                                  "##adate::date, ##atime::time)", set, NULL);
 
        g_print ("*** Showing contents of 'misc'\n");
        model = assert_run_sql_select (virtual, "SELECT * FROM out.misc",


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