[libgda] Virtual connections improvements and corrections



commit 3596f0956057efd0018bb69754e48966ecfd4aac
Author: Vivien Malerba <malerba gnome-db org>
Date:   Tue Mar 6 21:00:25 2012 +0100

    Virtual connections improvements and corrections
    
    they shouldn't leak any more, and be more efficient

 libgda/sqlite/gda-sqlite-recordset.c               |   32 +++++-
 .../virtual/gda-vconnection-data-model-private.h   |   57 ++++++++-
 libgda/sqlite/virtual/gda-vconnection-data-model.c |  111 ++++++++++++++++
 libgda/sqlite/virtual/gda-vprovider-data-model.c   |  136 +++++++++++---------
 tests/data-models/check_virtual.c                  |    6 +
 5 files changed, 279 insertions(+), 63 deletions(-)
---
diff --git a/libgda/sqlite/gda-sqlite-recordset.c b/libgda/sqlite/gda-sqlite-recordset.c
index ef073ff..2714685 100644
--- a/libgda/sqlite/gda-sqlite-recordset.c
+++ b/libgda/sqlite/gda-sqlite-recordset.c
@@ -37,6 +37,9 @@
 #include <libgda/gda-util.h>
 #include <libgda/gda-connection-private.h>
 
+#include "virtual/gda-vconnection-data-model.h"
+#include "virtual/gda-vconnection-data-model-private.h"
+
 #define _GDA_PSTMT(x) ((GdaPStmt*)(x))
 
 static void gda_sqlite_recordset_class_init (GdaSqliteRecordsetClass *klass);
@@ -53,6 +56,8 @@ static gboolean gda_sqlite_recordset_fetch_next (GdaDataSelect *model, GdaRow **
 
 static GdaRow *fetch_next_sqlite_row (GdaSqliteRecordset *model, gboolean do_store, GError **error);
 
+static void virt_cnc_set_working_obj (GdaConnection *cnc, GdaSqliteRecordset *model);
+
 struct _GdaSqliteRecordsetPrivate {
 	gboolean      empty_forced;
 	gint          next_row_num;
@@ -105,7 +110,9 @@ gda_sqlite_recordset_dispose (GObject *object)
 		GdaSqlitePStmt *ps;
 		ps = GDA_SQLITE_PSTMT (GDA_DATA_SELECT (object)->prep_stmt);
 		ps->stmt_used = FALSE;
+		virt_cnc_set_working_obj (gda_data_select_get_connection ((GdaDataSelect*) recset), recset);
 		SQLITE3_CALL (sqlite3_reset) (ps->sqlite_stmt);
+		virt_cnc_set_working_obj (gda_data_select_get_connection ((GdaDataSelect*) recset), NULL);
 
 		if (recset->priv->tmp_row)
 			g_object_unref (recset->priv->tmp_row);
@@ -201,7 +208,7 @@ read_rows_to_init_col_types (GdaSqliteRecordset *model)
  */
 GdaDataModel *
 _gda_sqlite_recordset_new (GdaConnection *cnc, GdaSqlitePStmt *ps, GdaSet *exec_params,
-			  GdaDataModelAccessFlags flags, GType *col_types, gboolean force_empty)
+			   GdaDataModelAccessFlags flags, GType *col_types, gboolean force_empty)
 {
 	GdaSqliteRecordset *model;
         SqliteConnectionData *cdata;
@@ -283,6 +290,13 @@ _gda_sqlite_recordset_new (GdaConnection *cnc, GdaSqlitePStmt *ps, GdaSet *exec_
 			      "prepared-stmt", ps, "model-usage", rflags, 
 			      "exec-params", exec_params, 
 			      "auto-reset", force_empty, NULL);
+	gboolean is_virt;
+	is_virt = GDA_IS_VCONNECTION_DATA_MODEL (cnc) ? TRUE : FALSE;
+	if (is_virt) {
+		/* steal the lock */
+		_gda_vconnection_change_working_obj ((GdaVconnectionDataModel*) cnc, (GObject*) model);
+		_gda_vconnection_set_working_obj ((GdaVconnectionDataModel*) cnc, NULL);
+	}
 
         /* fill the data model */
         read_rows_to_init_col_types (model);
@@ -318,6 +332,15 @@ fuzzy_get_gtype (SqliteConnectionData *cdata, GdaSqlitePStmt *ps, gint colnum)
 	return gtype;
 }
 
+static void
+virt_cnc_set_working_obj (GdaConnection *cnc, GdaSqliteRecordset *model)
+{
+	gboolean is_virt;
+	is_virt = GDA_IS_VCONNECTION_DATA_MODEL (cnc) ? TRUE : FALSE;
+	if (is_virt)
+		_gda_vconnection_set_working_obj ((GdaVconnectionDataModel*) cnc, (GObject*) model);
+}
+
 static GdaRow *
 fetch_next_sqlite_row (GdaSqliteRecordset *model, gboolean do_store, GError **error)
 {
@@ -332,9 +355,11 @@ fetch_next_sqlite_row (GdaSqliteRecordset *model, gboolean do_store, GError **er
 		return NULL;
 	ps = GDA_SQLITE_PSTMT (GDA_DATA_SELECT (model)->prep_stmt);
 
+	virt_cnc_set_working_obj (gda_data_select_get_connection ((GdaDataSelect*) model), model);
+
 	if (model->priv->empty_forced)
 		rc = SQLITE_DONE;
-	else
+	else		
 		rc = SQLITE3_CALL (sqlite3_step) (ps->sqlite_stmt);
 	switch (rc) {
 	case  SQLITE_ROW: {
@@ -647,6 +672,9 @@ fetch_next_sqlite_row (GdaSqliteRecordset *model, gboolean do_store, GError **er
 		break;
 	}
 	}
+
+	virt_cnc_set_working_obj (gda_data_select_get_connection ((GdaDataSelect*) model), NULL);
+
 	return prow;
 }
 
diff --git a/libgda/sqlite/virtual/gda-vconnection-data-model-private.h b/libgda/sqlite/virtual/gda-vconnection-data-model-private.h
index d1cde49..6488647 100644
--- a/libgda/sqlite/virtual/gda-vconnection-data-model-private.h
+++ b/libgda/sqlite/virtual/gda-vconnection-data-model-private.h
@@ -33,11 +33,54 @@ typedef enum {
 	PARAMS_NB
 } ParamType;
 
-typedef struct {
+typedef struct GdaVConnectionTableData GdaVConnectionTableData;
+typedef struct VContext VContext;
+typedef struct ExecContext ExecContext;
+typedef struct VirtualFilteredData VirtualFilteredData;
+
+struct VContext{
+	GObject                 *context_object;
+	GArray                  *context_data;
+	GdaVConnectionTableData *vtable;
+};
+
+struct ExecContext {
+	VContext   *current_vcontext;
+	GMutex     *mutex;
+	GHashTable *hash; /* key = a GObject, value = a VContext where @context_object == key */
+};
+
+/*
+ * This structure holds data to be used by a virtual cursor, for a specific filter,
+ * it keeps track of data which has been assigned a rowID
+ */
+struct VirtualFilteredData {
+	/* status */
+	guint8 refcount;
+	gboolean reuseable;
+
+	/* filter */
+	int idxNum;
+	char *idxStr;
+	int argc;
+	GValue **argv;
+
+	/* row numbers offset */
+	guint32 rowid_offset;
+
+	/* data */
+	GdaDataModel *model;
+	GdaDataModelIter *iter; /* not NULL while nrows == -1 */
+	GValueArray  *values;
+	gint          ncols;
+	gint          nrows; /* -1 until known */
+};
+
+struct GdaVConnectionTableData {
 	GdaVconnectionDataModelSpec *spec;
 	GDestroyNotify               spec_free_func;
 
-	GdaDataModel                *real_model; /* data model really being used, a reference is kept on it */
+	GdaDataModel                *real_model; /* data model really being used, a reference is kept */
 	GList                       *columns;
 	gchar                       *table_name;
 	gchar                       *unique_name;
@@ -45,7 +88,12 @@ typedef struct {
 
 	GdaStatement                *modif_stmt[PARAMS_NB];
 	GdaSet                      *modif_params[PARAMS_NB];
-} GdaVConnectionTableData;
+
+	ExecContext                  context; /* not a pointer! */
+};
+
+
+void                     _gda_vconnection_virtual_filtered_data_unref (VirtualFilteredData *data);
 
 void                     gda_vconnection_data_model_table_data_free (GdaVConnectionTableData *td);
 
@@ -53,6 +101,9 @@ GdaVConnectionTableData *gda_vconnection_get_table_data_by_name (GdaVconnectionD
 GdaVConnectionTableData *gda_vconnection_get_table_data_by_model (GdaVconnectionDataModel *cnc, GdaDataModel *model);
 GdaVConnectionTableData *gda_vconnection_get_table_data_by_unique_name (GdaVconnectionDataModel *cnc, const gchar *unique_name);
 
+void                     _gda_vconnection_set_working_obj (GdaVconnectionDataModel *cnc, GObject *obj);
+void                     _gda_vconnection_change_working_obj (GdaVconnectionDataModel *cnc, GObject *obj);
+
 G_END_DECLS
 
 #endif
diff --git a/libgda/sqlite/virtual/gda-vconnection-data-model.c b/libgda/sqlite/virtual/gda-vconnection-data-model.c
index ecb5c60..2dba80c 100644
--- a/libgda/sqlite/virtual/gda-vconnection-data-model.c
+++ b/libgda/sqlite/virtual/gda-vconnection-data-model.c
@@ -31,6 +31,9 @@
 
 struct _GdaVconnectionDataModelPrivate {
 	GSList *table_data_list; /* list of GdaVConnectionTableData structures */
+
+	GMutex       *lock_context;
+	GdaStatement *executed_stmt;
 };
 
 static void gda_vconnection_data_model_class_init (GdaVconnectionDataModelClass *klass);
@@ -136,6 +139,7 @@ gda_vconnection_data_model_init (GdaVconnectionDataModel *cnc, G_GNUC_UNUSED Gda
 {
 	cnc->priv = g_new (GdaVconnectionDataModelPrivate, 1);
 	cnc->priv->table_data_list = NULL;
+	cnc->priv->lock_context = g_mutex_new ();
 
 	g_object_set (G_OBJECT (cnc), "cnc-string", "_IS_VIRTUAL=TRUE", NULL);
 }
@@ -156,6 +160,7 @@ gda_vconnection_data_model_dispose (GObject *object)
 		}
 		gda_connection_close_no_warning ((GdaConnection *) cnc);
 
+		g_mutex_free (cnc->priv->lock_context);
 		g_free (cnc->priv);
 		cnc->priv = NULL;
 	}
@@ -586,5 +591,111 @@ gda_vconnection_data_model_table_data_free (GdaVConnectionTableData *td)
 		if (td->modif_stmt[i])
 			g_object_unref (td->modif_stmt[i]);
 	}
+
+	if (td->context.hash)
+		g_hash_table_destroy (td->context.hash);
 	g_free (td);
 }
+
+static void
+vcontext_object_weak_notify_cb (VContext *context, GObject *old_context_object)
+{
+	g_assert (context);
+	g_mutex_lock (context->vtable->context.mutex);
+	context->context_object = NULL;
+	g_hash_table_remove (context->vtable->context.hash, old_context_object);
+	g_mutex_unlock (context->vtable->context.mutex);
+}
+
+static void
+vcontext_free (VContext *context)
+{
+	if (context->context_object)
+		g_object_weak_unref (context->context_object,
+				     (GWeakNotify) vcontext_object_weak_notify_cb, context);
+	if (context->context_data) {
+		guint i;
+		for (i = 0; i < context->context_data->len; i++) {
+			VirtualFilteredData *data;
+			data = g_array_index (context->context_data, VirtualFilteredData*, i);
+			_gda_vconnection_virtual_filtered_data_unref (data);
+		}
+		g_array_free (context->context_data, TRUE);
+	}
+	g_free (context);
+#ifdef DEBUG_VCONTEXT
+	g_print ("VCFree %p\n", context);
+#endif
+}
+
+void
+_gda_vconnection_set_working_obj (GdaVconnectionDataModel *cnc, GObject *obj)
+{
+	GSList *list;
+	if (obj) {
+		g_mutex_lock (cnc->priv->lock_context);
+		for (list = cnc->priv->table_data_list; list; list = list->next) {
+			GdaVConnectionTableData *td = (GdaVConnectionTableData*) list->data;
+			VContext *vc = NULL;
+			
+			g_assert (!td->context.current_vcontext);
+			td->context.mutex = cnc->priv->lock_context;
+			if (! td->context.hash)
+				td->context.hash = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+									  NULL, (GDestroyNotify) vcontext_free);
+			else
+				vc = g_hash_table_lookup (td->context.hash, obj);
+
+			if (! vc) {
+				vc = g_new0 (VContext, 1);
+				vc->context_object = obj;
+				vc->context_data = g_array_new (FALSE, FALSE,
+								sizeof (VirtualFilteredData*));
+				vc->vtable = td;
+				g_object_weak_ref (obj, (GWeakNotify) vcontext_object_weak_notify_cb, vc);
+				g_hash_table_insert (td->context.hash, obj, vc);
+#ifdef DEBUG_VCONTEXT
+				g_print ("VCNew %p\n", vc);
+#endif
+			}
+			td->context.current_vcontext = vc;
+		}
+	}
+	else {
+		for (list = cnc->priv->table_data_list; list; list = list->next) {
+			GdaVConnectionTableData *td = (GdaVConnectionTableData*) list->data;
+
+			g_assert (td->context.current_vcontext);
+			td->context.current_vcontext = NULL;
+		}
+		g_mutex_unlock (cnc->priv->lock_context);
+	}
+}
+
+void
+_gda_vconnection_change_working_obj (GdaVconnectionDataModel *cnc, GObject *obj)
+{
+	GSList *list;
+
+	for (list = cnc->priv->table_data_list; list; list = list->next) {
+		GdaVConnectionTableData *td = (GdaVConnectionTableData*) list->data;
+		if (!td->context.hash)
+			continue;
+
+		g_assert (td->context.current_vcontext);
+
+		VContext *ovc, *nvc;
+		ovc = td->context.current_vcontext;
+		nvc = g_new0 (VContext, 1);
+		nvc->context_object = obj;
+		nvc->vtable = ovc->vtable;
+		nvc->context_data = ovc->context_data;
+		ovc->context_data = NULL;
+		g_object_weak_ref (obj, (GWeakNotify) vcontext_object_weak_notify_cb, nvc);
+		g_hash_table_insert (td->context.hash, obj, nvc);
+#ifdef DEBUG_VCONTEXT
+		g_print ("VCNew %p\n", nvc);
+#endif
+		g_hash_table_remove (td->context.hash, ovc->context_object);
+	}
+}
diff --git a/libgda/sqlite/virtual/gda-vprovider-data-model.c b/libgda/sqlite/virtual/gda-vprovider-data-model.c
index b2ad2a2..d3c1de3 100644
--- a/libgda/sqlite/virtual/gda-vprovider-data-model.c
+++ b/libgda/sqlite/virtual/gda-vprovider-data-model.c
@@ -185,7 +185,6 @@ gda_vprovider_data_model_new (void)
 
 typedef struct VirtualTable VirtualTable;
 typedef struct VirtualCursor VirtualCursor;
-typedef struct VirtualFilteredData VirtualFilteredData;
 
 struct VirtualTable {
 	sqlite3_vtab                 base;
@@ -194,39 +193,17 @@ struct VirtualTable {
 	gboolean                     locked;
 
 	guint32                      rows_offset;
-	GSList                      *all_data; /* list of #VirtualFilteredData, refs held here */
 };
 
+#define MAX_VDATA_NUMBER 30
+
 struct VirtualCursor {
 	sqlite3_vtab_cursor      base; /* base.pVtab is a pointer to the sqlite3_vtab virtual table */
-	VirtualFilteredData     *data; /* no ref held, ref is held in table->all_data */
+	VirtualFilteredData     *data; /* a ref is held here */
 	gint                     row; /* starts at 0 */
 };
 
-/*
- * This structure holds data to be used by a virtual cursor, for a specific filter
- */
-struct VirtualFilteredData {
-	/* status */
-	guint8 refcount;
-	gboolean reuseable;
-
-	/* filter */
-	int idxNum;
-	char *idxStr;
-	int argc;
-	GValue **argv;
-
-	/* row numbers offset */
-	guint32 rowid_offset;
-
-	/* data */
-	GdaDataModel *model;
-	GdaDataModelIter *iter; /* not NULL while nrows == -1 */
-	GValueArray  *values;
-	gint          ncols;
-	gint          nrows; /* -1 until known */
-};
+
 
 static VirtualFilteredData *
 virtual_filtered_data_new (VirtualTable *vtable, GdaDataModel *model,
@@ -259,6 +236,12 @@ virtual_filtered_data_new (VirtualTable *vtable, GdaDataModel *model,
 	data->rowid_offset = vtable->rows_offset;
 	vtable->rows_offset ++;
 	
+#ifdef DEBUG_VCONTEXT
+	g_print ("New VData %p for table [%s] idxNum=%d, idxStr=[%s], argc=%d\n", data, vtable->td->table_name,
+		 idxNum, idxStr, argc);
+	for (n= 0; n < data->argc; n++)
+		g_print ("    [%s]\n", gda_value_stringify (data->argv [n]));
+#endif
 	return data;
 }
 
@@ -279,6 +262,10 @@ virtual_filtered_data_free (VirtualFilteredData *data)
 	if (data->values)
 		g_value_array_free (data->values);
 	g_free (data);
+
+#ifdef DEBUG_VCONTEXT
+	g_print ("Freed VData %p\n", data);
+#endif
 }
 
 static VirtualFilteredData *
@@ -288,8 +275,8 @@ virtual_filtered_data_ref (VirtualFilteredData *data)
 	return data;
 }
 
-static void
-virtual_filtered_data_unref (VirtualFilteredData *data)
+void
+_gda_vconnection_virtual_filtered_data_unref (VirtualFilteredData *data)
 {
 	data->refcount --;
 	if (data->refcount == 0)
@@ -302,7 +289,7 @@ virtual_cursor_free (VirtualCursor *cursor)
 	if (!cursor)
 		return;
 
-	virtual_filtered_data_unref (cursor->data);
+	_gda_vconnection_virtual_filtered_data_unref (cursor->data);
 	g_free (cursor);
 }
 
@@ -327,7 +314,7 @@ static int virtualRollback (sqlite3_vtab *tab);
 static int virtualRename (sqlite3_vtab *pVtab, const char *zNew);
 
 static sqlite3_module Module = {
-	0,                         /* iVersion */
+	1,                         /* iVersion */
 	virtualCreate,
 	virtualConnect,
 	virtualBestIndex,
@@ -447,12 +434,17 @@ gda_vprovider_data_model_statement_execute (GdaServerProvider *provider, GdaConn
                              "%s", _("Provider does not support asynchronous statement execution"));
                 return NULL;
         }
-        
+
+	_gda_vconnection_set_working_obj ((GdaVconnectionDataModel*) cnc, (GObject*) stmt);
 	retval = GDA_SERVER_PROVIDER_CLASS (parent_class)->statement_execute (provider, cnc, stmt, params,
 									      model_usage, col_types,
 									      last_inserted_row, task_id,
 									      async_cb, cb_data, error);
+
 	if (retval) {
+		if (! GDA_IS_DATA_MODEL (retval))
+			_gda_vconnection_set_working_obj ((GdaVconnectionDataModel*) cnc, NULL);
+
 		gchar *sql;
 		sql = gda_statement_to_sql (stmt, params, NULL);
 		if (sql) {
@@ -497,6 +489,8 @@ gda_vprovider_data_model_statement_execute (GdaServerProvider *provider, GdaConn
 			g_free (sql);
 		}
 	}
+	else
+		_gda_vconnection_set_working_obj ((GdaVconnectionDataModel*) cnc, NULL);
 	return retval;
 }
 
@@ -699,13 +693,7 @@ virtualDisconnect (sqlite3_vtab *pVtab)
 	VirtualTable *vtable = (VirtualTable *) pVtab;
 
 	TRACE (pVtab, NULL);
-
-	if (vtable->all_data) {
-		g_slist_foreach (vtable->all_data, (GFunc) virtual_filtered_data_unref, NULL);
-		g_slist_free (vtable->all_data);
-		vtable->all_data = NULL;
-	}
-	g_free (vtable);
+	g_free (pVtab);
 
 	return SQLITE_OK;
 }
@@ -888,9 +876,12 @@ get_data_value (VirtualTable *vtable, VirtualCursor *cursor, gint row, gint64 ro
 		g_assert (row < 0);
 		row = (gint) (rowid & 0xFFFFFFFF);
 
-		GSList *list;
-		for (list = vtable->all_data; list; list = list->next) {
-			VirtualFilteredData *vd = (VirtualFilteredData*) list->data;
+		g_assert (vtable->td->context.current_vcontext);
+		guint i;
+		GArray *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);
 			if (vd->rowid_offset == (guint32) (rowid >> 32)) {
 				data = vd;
 				break;
@@ -905,6 +896,9 @@ get_data_value (VirtualTable *vtable, VirtualCursor *cursor, gint row, gint64 ro
 		g_set_error (error, 0, 0,
 			     _("Could not find requested value at row %d and col %d"),
 			     row, col);
+#ifdef DEBUG_VCONTEXT
+	g_print ("Read from [%s] [%s] %d x %d x %lld\n", vtable->td->table_name, gda_value_stringify (value), col, row, rowid);
+#endif
 	return value;
 }
 
@@ -1114,15 +1108,18 @@ virtualFilter (sqlite3_vtab_cursor *pVtabCursor, int idxNum, const char *idxStr,
 #endif
 
 	/* find a VirtualFilteredData corresponding to this filter */
-	VirtualFilteredData *data;
-	data = NULL;
-	if (vtable->all_data) {
-		GSList *list;
-		for (list = vtable->all_data; list; list = list->next) {
-			VirtualFilteredData *vd = (VirtualFilteredData*) list->data;
+	VirtualFilteredData *data = NULL;
+	g_assert (vtable->td->context.current_vcontext);
+	GArray *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);
 			if (vd->reuseable &&
 			    (vd->idxNum == idxNum) &&
-			    (argc == argc) &&
+			    (vd->argc == argc) &&
 			    ((!idxStr && !vd->idxStr) || (idxStr && vd->idxStr && !strcmp (idxStr, vd->idxStr)))) {
 				GValue **avalues;
 				gint i;
@@ -1155,18 +1152,36 @@ virtualFilter (sqlite3_vtab_cursor *pVtabCursor, int idxNum, const char *idxStr,
 			}
 		}
 	}
+#ifdef DEBUG_VCONTEXT
+	if (data)
+		g_print ("REUSE VData %p\n", data);
+#endif
 
 	if (!data) {
 		virtual_table_manage_real_data_model (vtable, idxNum, idxStr, argc, argv);
 		if (! vtable->td->real_model)
 			return SQLITE_ERROR;
 		data = virtual_filtered_data_new (vtable, vtable->td->real_model, idxNum, idxStr, argc, argv);
-		vtable->all_data = g_slist_prepend (vtable->all_data, data);
+		g_array_prepend_val (values_array, data);
+#ifdef DEBUG_VCONTEXT
+		g_print ("VData %p prepended to array %p wt %d\n", data, values_array,
+			 values_array->len);
+#endif
+		if (values_array->len > MAX_VDATA_NUMBER) {
+			VirtualFilteredData *ldata;
+			gint index;
+			index = values_array->len - 1;
+			ldata = g_array_index (values_array, VirtualFilteredData*, index);
+			_gda_vconnection_virtual_filtered_data_unref (ldata);
+			g_array_remove_index (values_array, index);
+		}
+	}
+	
+	if (cursor->data != data) {
+		if (cursor->data)
+			_gda_vconnection_virtual_filtered_data_unref (cursor->data);
+		cursor->data = virtual_filtered_data_ref (data);
 	}
-
-	if (cursor->data)
-		virtual_filtered_data_unref (cursor->data);
-	cursor->data = virtual_filtered_data_ref (data);
 
 	/* initialize cursor */
 	cursor->row = -1;
@@ -1509,10 +1524,15 @@ virtualUpdate (sqlite3_vtab *tab, int nData, sqlite3_value **apData, sqlite_int6
 
 	TRACE (tab, NULL);
 
-	GSList *list;
-	for (list = vtable->all_data; list; list = list->next) {
-		VirtualFilteredData *vd = (VirtualFilteredData*) list->data;
-		vd->reuseable = FALSE;
+	g_assert (vtable->td->context.current_vcontext);
+	GArray *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->reuseable = FALSE;
+		}
 	}
 
 	/* determine operation type */
diff --git a/tests/data-models/check_virtual.c b/tests/data-models/check_virtual.c
index c5ad416..354b0bb 100644
--- a/tests/data-models/check_virtual.c
+++ b/tests/data-models/check_virtual.c
@@ -57,6 +57,7 @@ test1 (void)
 	gchar *file;
 	gboolean retval = FALSE;
 
+	g_print ("===== %s() =====\n", __FUNCTION__);
 	provider = gda_vprovider_data_model_new ();
 	cnc = gda_virtual_connection_open (provider, NULL);
 	g_assert (cnc);
@@ -121,6 +122,7 @@ test1 (void)
 	g_object_unref (cnc);
 	g_object_unref (provider);
 
+	g_print ("%s() is %s\n", __FUNCTION__, retval ? "Ok" : "NOT Ok");
 	return retval;
 }
 
@@ -133,6 +135,7 @@ test2 (void)
 	gchar *file;
 	gboolean retval = FALSE;
 
+	g_print ("===== %s () =====\n", __FUNCTION__);
 	provider = gda_vprovider_data_model_new ();
 	cnc = gda_virtual_connection_open (provider, NULL);
 	g_assert (cnc);
@@ -168,6 +171,7 @@ test2 (void)
 	g_object_unref (cnc);
 	g_object_unref (provider);
 
+	g_print ("%s() is %s\n", __FUNCTION__, retval ? "Ok" : "NOT Ok");
 	return retval;
 }
 
@@ -183,6 +187,7 @@ run_sql_select (GdaConnection *cnc, const gchar *sql)
 	stmt = gda_sql_parser_parse_string (parser, sql, NULL, NULL);
 	g_object_unref (parser);
 
+	g_print ("EXECUTING [%s]\n", sql);
         res = gda_connection_statement_execute_select (cnc, stmt, NULL, &error);
         g_object_unref (stmt);
 	if (!res) 
@@ -204,6 +209,7 @@ run_sql_non_select (GdaConnection *cnc, const gchar *sql)
         stmt = gda_sql_parser_parse_string (parser, sql, NULL, NULL);
         g_object_unref (parser);
 
+	g_print ("EXECUTING [%s]\n", sql);
         nrows = gda_connection_statement_execute_non_select (cnc, stmt, NULL, NULL, &error);
         g_object_unref (stmt);
         if (nrows == -1) {



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