[libgda] Make virtual connections work better with cursor only data models



commit 0cf7f1872928156224bd0d30d58bbc8f0c3442bf
Author: Vivien Malerba <malerba gnome-db org>
Date:   Sun Sep 18 18:34:26 2011 +0200

    Make virtual connections work better with cursor only data models

 libgda/gda-data-select.c                         |   23 +++++++++---------
 libgda/sqlite/gda-sqlite-recordset.c             |   27 +++++++++++++++++-----
 libgda/sqlite/virtual/gda-vprovider-data-model.c |   25 ++++++++++++++++++-
 3 files changed, 55 insertions(+), 20 deletions(-)
---
diff --git a/libgda/gda-data-select.c b/libgda/gda-data-select.c
index ec62320..ebe78ce 100644
--- a/libgda/gda-data-select.c
+++ b/libgda/gda-data-select.c
@@ -2033,7 +2033,7 @@ gda_data_select_iter_next (GdaDataModel *model, GdaDataModelIter *iter)
 		target_iter_row = imodel->priv->sh->iter_row + 1;
 
 	int_row = external_to_internal_row (imodel, target_iter_row, NULL);
-	prow = gda_data_select_get_stored_row (model, int_row);
+	prow = gda_data_select_get_stored_row (imodel, int_row);
 	if (!prow)
 		CLASS (model)->fetch_next (imodel, &prow, int_row, NULL);
 
@@ -2044,8 +2044,8 @@ gda_data_select_iter_next (GdaDataModel *model, GdaDataModelIter *iter)
 	}
 	else {
 		gda_data_model_iter_invalidate_contents (iter);
-                imodel->priv->sh->iter_row = G_MAXINT;
-                g_object_set (G_OBJECT (iter), "current-row", -1, NULL);
+		imodel->priv->sh->iter_row = G_MAXINT;
+		g_object_set (G_OBJECT (iter), "current-row", -1, NULL);
 		g_signal_emit_by_name (iter, "end-of-data");
                 return FALSE;
 	}
@@ -2065,17 +2065,11 @@ gda_data_select_iter_prev (GdaDataModel *model, GdaDataModelIter *iter)
 	if (imodel->priv->sh->usage_flags & GDA_DATA_MODEL_ACCESS_RANDOM)
 		return gda_data_model_iter_move_prev_default (model, iter);
 
-	if (! CLASS (model)->fetch_prev) {
-		gda_data_model_iter_invalidate_contents (iter);
-		return FALSE;
-	}
-
         g_return_val_if_fail (iter, FALSE);
         g_return_val_if_fail (imodel->priv->iter == iter, FALSE);
 
         if (imodel->priv->sh->iter_row <= 0)
                 goto prev_error;
-
         else if (imodel->priv->sh->iter_row == G_MAXINT) {
                 g_assert (imodel->advertized_nrows >= 0);
                 target_iter_row = imodel->advertized_nrows - 1;
@@ -2084,9 +2078,14 @@ gda_data_select_iter_prev (GdaDataModel *model, GdaDataModelIter *iter)
                 target_iter_row = imodel->priv->sh->iter_row - 1;
 
 	int_row = external_to_internal_row (imodel, target_iter_row, NULL);
-	prow = gda_data_select_get_stored_row (model, int_row);
-	if (!prow)
+	prow = gda_data_select_get_stored_row (imodel, int_row);
+	if (!prow) {
+		if (! CLASS (model)->fetch_prev) {
+			gda_data_model_iter_invalidate_contents (iter);
+			return FALSE;
+		}
 		CLASS (model)->fetch_prev (imodel, &prow, int_row, NULL);
+	}
 
 	if (prow) {
 		imodel->priv->sh->iter_row = target_iter_row;
@@ -2118,7 +2117,7 @@ gda_data_select_iter_at_row (GdaDataModel *model, GdaDataModelIter *iter, gint r
         g_return_val_if_fail (imodel->priv->iter == iter, FALSE);
 
 	int_row = external_to_internal_row (imodel, row, NULL);
-	prow = gda_data_select_get_stored_row (model, int_row);
+	prow = gda_data_select_get_stored_row (imodel, int_row);
 
 	if (prow) {
 		imodel->priv->sh->iter_row = row;
diff --git a/libgda/sqlite/gda-sqlite-recordset.c b/libgda/sqlite/gda-sqlite-recordset.c
index 050f822..c4c8099 100644
--- a/libgda/sqlite/gda-sqlite-recordset.c
+++ b/libgda/sqlite/gda-sqlite-recordset.c
@@ -160,17 +160,19 @@ read_rows_to_init_col_types (GdaSqliteRecordset *model)
 		if (pmodel->prep_stmt->types[i] == GDA_TYPE_NULL)
 			missing_cols [nb_missing++] = i;
 	}
-	/*
+
+#ifdef GDA_DEBUG_NO
 	if (nb_missing == 0)
-		g_print ("Hey!, all columns are known for prep stmt %p\n", pmodel->prep_stmt);
-	*/
+		g_print ("All columns are known for model %p\n", pmodel);
+#endif
+
 	for (; nb_missing > 0; ) {
 		GdaRow *prow;
 		prow = fetch_next_sqlite_row (model, TRUE, NULL);
 		if (!prow)
 			break;
 #ifdef GDA_DEBUG_NO
-		g_print ("Read row %d for prep stmt %p\n", model->priv->next_row_num - 1, pmodel->prep_stmt);
+		g_print ("Prefetched row %d of model %p\n", model->priv->next_row_num - 1, pmodel);
 #endif
 		for (i = nb_missing - 1; i >= 0; i--) {
 			if (pmodel->prep_stmt->types [missing_cols [i]] != GDA_TYPE_NULL) {
@@ -671,12 +673,25 @@ gda_sqlite_recordset_fetch_random (GdaDataSelect *model, GdaRow **prow, gint row
  * Before a new #GdaRow gets created, the previous one, if set, is discarded.
  */
 static gboolean
-gda_sqlite_recordset_fetch_next (GdaDataSelect *model, GdaRow **prow, G_GNUC_UNUSED gint rownum, GError **error)
+gda_sqlite_recordset_fetch_next (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
 {
 	GdaSqliteRecordset *imodel = (GdaSqliteRecordset*) model;
 
-	if (imodel->priv->tmp_row)
+	if (imodel->priv->tmp_row) {
 		g_object_unref (imodel->priv->tmp_row);
+		imodel->priv->tmp_row = NULL;
+	}
+	if (imodel->priv->next_row_num != rownum) {
+		GError *lerror = NULL;
+		*prow = NULL;
+		g_set_error (&lerror, GDA_DATA_MODEL_ERROR,
+			     GDA_DATA_MODEL_ROW_NOT_FOUND_ERROR,
+			     "%s", _("Can't set iterator on requested row"));
+		gda_data_select_add_exception (GDA_DATA_SELECT (model), lerror);
+		if (error)
+			g_propagate_error (error, g_error_copy (lerror));
+		return TRUE;
+	}
 	*prow = fetch_next_sqlite_row (imodel, FALSE, error);
 	imodel->priv->tmp_row = *prow;
 
diff --git a/libgda/sqlite/virtual/gda-vprovider-data-model.c b/libgda/sqlite/virtual/gda-vprovider-data-model.c
index 80ea89a..871af84 100644
--- a/libgda/sqlite/virtual/gda-vprovider-data-model.c
+++ b/libgda/sqlite/virtual/gda-vprovider-data-model.c
@@ -277,7 +277,7 @@ handle_data_model_exception (sqlite3_vtab *pVtab, GdaDataModel *model)
 		if (pVtab->zErrMsg)
 			SQLITE3_CALL (sqlite3_free) (pVtab->zErrMsg);
 		pVtab->zErrMsg = SQLITE3_CALL (sqlite3_mprintf)
-			(e->message ? e->message : _("No detail"));
+			("%s", e->message ? e->message : _("No detail"));
 		if (fatal_error)
 			return SQLITE_ERROR;
 		else
@@ -910,10 +910,31 @@ virtualFilter (sqlite3_vtab_cursor *pVtabCursor, int idxNum, const char *idxStr,
 	else
 		cursor->iter = gda_data_model_create_iter (vtable->td->real_model);
 
+	if (gda_data_model_iter_is_valid (cursor->iter) &&
+	    (gda_data_model_iter_get_row (cursor->iter) > 0)) {
+		/*g_print ("@%d, rewinding...", gda_data_model_iter_get_row (cursor->iter));*/
+		for (;gda_data_model_iter_move_prev (cursor->iter););
+		/*g_print ("done: @%d\n", gda_data_model_iter_get_row (cursor->iter));*/
+		if (gda_data_model_iter_is_valid (cursor->iter))
+			goto onerror;
+	}
+	if (! gda_data_model_iter_is_valid (cursor->iter)) {
+		gda_data_model_iter_move_next (cursor->iter);
+		if (! gda_data_model_iter_is_valid (cursor->iter))
+			goto onerror;
+	}
 	cursor->model = g_object_ref (vtable->td->real_model);
-	gda_data_model_iter_move_next (cursor->iter);
 
 	return handle_data_model_exception (pVtabCursor->pVtab, cursor->model);
+
+ onerror:
+	g_object_unref (cursor->iter);
+	cursor->iter = NULL;
+	if (pVtabCursor->pVtab->zErrMsg)
+			SQLITE3_CALL (sqlite3_free) (pVtabCursor->pVtab->zErrMsg);
+	pVtabCursor->pVtab->zErrMsg = SQLITE3_CALL (sqlite3_mprintf)
+		("%s", _("Can't obtain an iterator located on the first row"));
+	return SQLITE_ERROR;
 }
 
 #ifdef GDA_DEBUG_VIRTUAL



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