[libgda] Fix segfault on virtual connections



commit 892407cb9033396d527bdba594dc4cc982a5d622
Author: Daniel Espinosa Ortiz <esodan gmail com>
Date:   Tue Feb 26 17:07:40 2019 -0600

    Fix segfault on virtual connections

 .../virtual/gda-vconnection-data-model-private.h   |  4 +-
 libgda/sqlite/virtual/gda-vconnection-data-model.c | 23 +++++-----
 libgda/sqlite/virtual/gda-vprovider-data-model.c   | 51 +++++++++-------------
 tests/data-models/check_vcnc.c                     | 36 +++++++++++++--
 4 files changed, 67 insertions(+), 47 deletions(-)
---
diff --git a/libgda/sqlite/virtual/gda-vconnection-data-model-private.h 
b/libgda/sqlite/virtual/gda-vconnection-data-model-private.h
index 6a1e0a0ed..90ddf2977 100644
--- a/libgda/sqlite/virtual/gda-vconnection-data-model-private.h
+++ b/libgda/sqlite/virtual/gda-vconnection-data-model-private.h
@@ -40,7 +40,7 @@ typedef struct VirtualFilteredData VirtualFilteredData;
 
 struct VContext{
        GWeakRef                 context_object;
-       GArray                  *context_data;
+       GPtrArray                  *context_data;
        GdaVConnectionTableData *vtable;
 };
 
@@ -71,7 +71,7 @@ struct VirtualFilteredData {
        /* data */
        GdaDataModel *model;
        GdaDataModelIter *iter; /* not NULL while nrows == -1 */
-       GArray       *values_array;
+       GPtrArray       *values_array;
        gint          ncols;
        gint          nrows; /* -1 until known */
 };
diff --git a/libgda/sqlite/virtual/gda-vconnection-data-model.c 
b/libgda/sqlite/virtual/gda-vconnection-data-model.c
index 5282c04d5..8dd7a7e1c 100644
--- a/libgda/sqlite/virtual/gda-vconnection-data-model.c
+++ b/libgda/sqlite/virtual/gda-vconnection-data-model.c
@@ -157,12 +157,15 @@ gda_vconnection_data_model_dispose (GObject *object)
 
        g_return_if_fail (GDA_IS_VCONNECTION_DATA_MODEL (cnc));
 
-       /* free memory */
-       priv->being_disposed = TRUE;
-       while (priv->table_data_list) {
-               GdaVConnectionTableData *td;
-               td = (GdaVConnectionTableData *) priv->table_data_list->data;
-               get_rid_of_vtable (cnc, td, TRUE, NULL);
+       if (priv->table_data_list != NULL) {
+               /* free memory */
+               priv->being_disposed = TRUE;
+               while (priv->table_data_list) {
+                       GdaVConnectionTableData *td;
+                       td = (GdaVConnectionTableData *) priv->table_data_list->data;
+                       get_rid_of_vtable (cnc, td, TRUE, NULL);
+               }
+               priv->table_data_list = NULL;
        }
        gda_connection_close ((GdaConnection *) cnc, NULL);
 
@@ -302,7 +305,7 @@ gda_vconnection_data_model_add (GdaVconnectionDataModel *cnc, GdaVconnectionData
        if (rc != SQLITE_OK) {
                g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
                             GDA_SERVER_PROVIDER_INTERNAL_ERROR,
-                            "%s", zErrMsg);
+                            _("Internal Error: when trying to add data model spec for virtual connetion: 
%s"), zErrMsg);
                SQLITE3_CALL (sqlite3_free) (zErrMsg);
                _gda_vconnection_data_model_table_data_free (td);
                priv->table_data_list = g_slist_remove (priv->table_data_list, td);
@@ -580,7 +583,7 @@ vcontext_free (VContext *context)
                g_object_unref (obj);
        }
        if (context->context_data) {
-               g_array_free (context->context_data, TRUE);
+               g_ptr_array_free (context->context_data, TRUE);
                context->context_data = NULL;
        }
        g_free (context);
@@ -611,9 +614,7 @@ _gda_vconnection_set_working_obj (GdaVconnectionDataModel *cnc, GObject *obj)
                        if (! vc) {
                                vc = g_new0 (VContext, 1);
                                g_weak_ref_set (&(vc->context_object), obj);
-                               vc->context_data = g_array_new (FALSE, FALSE,
-                                                               sizeof (VirtualFilteredData*));
-                               g_array_set_clear_func (vc->context_data, (GDestroyNotify) 
_gda_vconnection_virtual_filtered_data_unref);
+                               vc->context_data = g_ptr_array_new_full (1, (GDestroyNotify) 
_gda_vconnection_virtual_filtered_data_unref);
                                vc->vtable = td;
                                g_hash_table_insert (td->context.hash, obj, vc);
 #ifdef DEBUG_VCONTEXT
diff --git a/libgda/sqlite/virtual/gda-vprovider-data-model.c 
b/libgda/sqlite/virtual/gda-vprovider-data-model.c
index fc3cd06a2..664d57500 100644
--- a/libgda/sqlite/virtual/gda-vprovider-data-model.c
+++ b/libgda/sqlite/virtual/gda-vprovider-data-model.c
@@ -218,7 +218,7 @@ virtual_filtered_data_new (VirtualTable *vtable, GdaDataModel *model,
        gint n;
        n = gda_data_model_get_n_columns (model);
        n = (n >= 0) ? n : 1;
-       data->values_array = g_array_new (FALSE, FALSE, sizeof (GValue));
+       data->values_array = g_ptr_array_new_full (1, (GDestroyNotify) gda_value_free);
        data->ncols = gda_data_model_get_n_columns (model);
        data->nrows = -1;
        data->rowid_offset = vtable->rows_offset;
@@ -249,13 +249,7 @@ virtual_filtered_data_free (VirtualFilteredData *data)
                g_object_unref (data->iter);
 
        if (data->values_array) {
-               guint i;
-               for (i = 0; i < data->values_array->len; i++) {
-                       GValue *value;
-                       value = & g_array_index (data->values_array, GValue, i);
-                       g_value_reset (value);
-               }
-               g_array_free (data->values_array, TRUE);
+               g_ptr_array_free (data->values_array, TRUE);
        }
        g_free (data);
 
@@ -874,25 +868,22 @@ virtualNext (sqlite3_vtab_cursor *cur)
                                GdaHolder *h = (GdaHolder*) list->data;
                                GError *lerror = NULL;
                                if (! gda_holder_is_valid_e (h, &lerror)) {
-                                       GValue value = {0};
-                                       g_value_init (&value, G_TYPE_ERROR);
-                                       g_value_take_boxed (&value, lerror);
-                                       g_array_append_val (data->values_array, value);
+                                       GValue *value = gda_value_new (G_TYPE_ERROR);
+                                       g_value_take_boxed (value, lerror);
+                                       g_ptr_array_insert (data->values_array, -1, value);
                                }
                                else {
                                        const GValue *cvalue;
                                        cvalue = gda_holder_get_value (h);
                                        if (cvalue && (G_VALUE_TYPE (cvalue) != 0)) {
-                                               GValue copy = {0};
-                                               g_value_init (&copy, G_VALUE_TYPE (cvalue));
-                                               g_value_copy (cvalue, &copy);
-                                               g_array_append_val (data->values_array, copy);
+                                               GValue *copy = gda_value_new (G_VALUE_TYPE (cvalue));
+                                               g_value_copy (cvalue, copy);
+                                               g_ptr_array_insert (data->values_array, -1, copy);
                                        }
                                        else {
-                                               GValue value = {0};
-                                               g_value_init (&value, G_TYPE_ERROR);
-                                               g_value_take_boxed (&value, lerror);
-                                               g_array_append_val (data->values_array, value);
+                                               GValue *value = gda_value_new (G_TYPE_ERROR);
+                                               g_value_take_boxed (value, lerror);
+                                               g_ptr_array_insert (data->values_array, -1, value);
                                        }
                                }
                        }
@@ -944,10 +935,10 @@ get_data_value (VirtualTable *vtable, VirtualCursor *cursor, gint row, gint64 ro
 
                g_assert (vtable->td->context.current_vcontext);
                guint i;
-               GArray *values_array = vtable->td->context.current_vcontext->context_data;
+               GPtrArray *values_array = vtable->td->context.current_vcontext->context_data;
                for (i = 0; i < values_array->len; i++) {
                        VirtualFilteredData *vd;
-                       vd = g_array_index (values_array, VirtualFilteredData*, i);
+                       vd = g_ptr_array_index (values_array, i);
                        if (vd->rowid_offset == (guint32) (rowid >> 32)) {
                                data = vd;
                                break;
@@ -956,7 +947,7 @@ get_data_value (VirtualTable *vtable, VirtualCursor *cursor, gint row, gint64 ro
        }
 
        if (data)
-               value = & g_array_index (data->values_array, GValue, row * data->ncols + col);
+               value = g_ptr_array_index (data->values_array, row * data->ncols + col);
 
        if (!value)
                g_set_error (error, GDA_VPROVIDER_DATA_MODEL_ERROR, GDA_VPROVIDER_DATA_MODEL_GENERAL_ERROR,
@@ -1180,13 +1171,13 @@ virtualFilter (sqlite3_vtab_cursor *pVtabCursor, int idxNum, const char *idxStr,
        /* find a VirtualFilteredData corresponding to this filter */
        VirtualFilteredData *data = NULL;
        g_assert (vtable->td->context.current_vcontext);
-       GArray *values_array = vtable->td->context.current_vcontext->context_data;
+       GPtrArray *values_array = vtable->td->context.current_vcontext->context_data;
 
        if (values_array->len > 0) {
                guint i;
                for (i = 0; i < values_array->len; i++) {
                        VirtualFilteredData *vd;
-                       vd = g_array_index (values_array, VirtualFilteredData*, i);
+                       vd = g_ptr_array_index (values_array, i);
                        if (vd->reuseable &&
                            (vd->idxNum == idxNum) &&
                            (vd->argc == argc) &&
@@ -1232,7 +1223,7 @@ virtualFilter (sqlite3_vtab_cursor *pVtabCursor, int idxNum, const char *idxStr,
                if (! vtable->td->real_model)
                        return SQLITE_ERROR;
                data = virtual_filtered_data_new (vtable, vtable->td->real_model, idxNum, idxStr, argc, argv);
-               g_array_prepend_val (values_array, data);
+               g_ptr_array_insert (values_array, -1, data);
 #ifdef DEBUG_VCONTEXT
                g_print ("VData %p prepended to array %p wt %d\n", data, values_array,
                         values_array->len);
@@ -1241,9 +1232,9 @@ virtualFilter (sqlite3_vtab_cursor *pVtabCursor, int idxNum, const char *idxStr,
                        VirtualFilteredData *ldata;
                        gint index;
                        index = values_array->len - 1;
-                       ldata = g_array_index (values_array, VirtualFilteredData*, index);
+                       ldata = g_ptr_array_index (values_array, index);
                        _gda_vconnection_virtual_filtered_data_unref (ldata);
-                       g_array_remove_index (values_array, index);
+                       g_ptr_array_remove_index (values_array, index);
                }
        }
        
@@ -1598,12 +1589,12 @@ virtualUpdate (sqlite3_vtab *tab, int nData, sqlite3_value **apData, sqlite_int6
        TRACE (tab, NULL);
 
        g_assert (vtable->td->context.current_vcontext);
-       GArray *values_array = vtable->td->context.current_vcontext->context_data;
+       GPtrArray *values_array = vtable->td->context.current_vcontext->context_data;
        if (values_array) {
                guint i;
                for (i = 0; i < values_array->len; i++) {
                        VirtualFilteredData *data;
-                       data = g_array_index (values_array, VirtualFilteredData*, i);
+                       data = g_ptr_array_index (values_array, i);
                        data->reuseable = FALSE;
                }
        }
diff --git a/tests/data-models/check_vcnc.c b/tests/data-models/check_vcnc.c
index bd63fca70..008ab8ee9 100644
--- a/tests/data-models/check_vcnc.c
+++ b/tests/data-models/check_vcnc.c
@@ -91,6 +91,7 @@ test1 (Data *data) {
        provider = gda_vprovider_hub_new ();
        virtual = gda_virtual_connection_open (provider, GDA_CONNECTION_OPTIONS_NONE, NULL);
        g_assert (virtual);
+       g_assert (GDA_IS_VCONNECTION_HUB (virtual));
 
        /* load CSV data models */
        GdaDataModel *country_model, *city_model;
@@ -104,7 +105,8 @@ test1 (Data *data) {
        g_free (file);
        g_object_unref (options);
 
-       g_message ("Add data models to connection: city");
+       g_message ("Adding data models to virtal connection as inputs");
+       g_message ("Add data models to virtual connection: city");
        if (!gda_vconnection_data_model_add_model (GDA_VCONNECTION_DATA_MODEL (virtual),
                                                   city_model, "city", &error)) {
                g_message ("Add city model error: %s", error->message);
@@ -112,7 +114,7 @@ test1 (Data *data) {
                g_main_loop_quit (data->loop);
                return G_SOURCE_REMOVE;
        }
-       g_message ("Add data models to connection: country");
+       g_message ("Add data models to virtual connection: country");
        if (!gda_vconnection_data_model_add_model (GDA_VCONNECTION_DATA_MODEL (virtual),
                                                   country_model, "country", &error)) {
                g_message ("Add country model error: %s", error->message);
@@ -120,9 +122,35 @@ test1 (Data *data) {
                g_main_loop_quit (data->loop);
                return G_SOURCE_REMOVE;
        }
+       // Test data models in virtal connection
+       GdaDataModel *datamodel;
+       datamodel = gda_connection_execute_select_command (virtual, "SELECT * FROM city", &error);
+       if (datamodel == NULL) {
+               g_message ("Select data from city model error: %s", error->message);
+               g_clear_error (&error);
+               g_main_loop_quit (data->loop);
+               return G_SOURCE_REMOVE;
+       }
+       gchar *dump = NULL;
+       dump = gda_data_model_dump_as_string (datamodel);
+       g_message ("Selected data from imported data model city:\n%s", dump);
+       g_free (dump);
+       g_object_unref (datamodel);
+
+       datamodel = gda_connection_execute_select_command (virtual, "SELECT * FROM country", &error);
+       if (datamodel == NULL) {
+               g_message ("Select data from city model error: %s", error->message);
+               g_clear_error (&error);
+               g_main_loop_quit (data->loop);
+               return G_SOURCE_REMOVE;
+       }
+       dump = gda_data_model_dump_as_string (datamodel);
+       g_message ("Selected data from imported data model country:\n%s", dump);
+       g_free (dump);
+       g_object_unref (datamodel);
 
        /* SQLite connection for outputs */
-       g_message ("SQLite connection for outputs");
+       g_message ("Open SQLite connection for outputs");
        out_cnc = open_destination_connection (data, &error);
        if (out_cnc == NULL) {
                g_message ("Error opening destination %s", error->message);
@@ -132,7 +160,7 @@ test1 (Data *data) {
        }
 
        /* adding connections to the virtual connection */
-       g_message ("Add data models to connection");
+       g_message ("Add output connection to virtual connection hub");
        if (!gda_vconnection_hub_add (GDA_VCONNECTION_HUB (virtual), out_cnc, "out", &error)) {
                g_message ("Could not add connection to virtual connection: %s",
                        error->message);


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