[libgda/LIBGDA_4.2] Cleaned GdaDataModelIter implementations
- From: Vivien Malerba <vivien src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgda/LIBGDA_4.2] Cleaned GdaDataModelIter implementations
- Date: Wed, 21 Sep 2011 16:05:30 +0000 (UTC)
commit effae56538e0d56b339dbbcae04f16a18ac00080
Author: Vivien Malerba <malerba gnome-db org>
Date: Wed Sep 21 17:45:03 2011 +0200
Cleaned GdaDataModelIter implementations
libgda/gda-data-model-import.c | 43 ++----
libgda/gda-data-model-iter.c | 152 +++++++++++---------
libgda/gda-data-select.c | 130 +++++++----------
libgda/sqlite/gda-sqlite-recordset.c | 37 ++---
providers/firebird/gda-firebird-recordset.c | 73 +++++-----
providers/jdbc/gda-jdbc-recordset.c | 39 +++---
providers/ldap/gdaprov-data-model-ldap.c | 6 +-
providers/mysql/gda-mysql-recordset.c | 96 +++++--------
providers/oracle/gda-oracle-recordset.c | 129 +++--------------
providers/postgres/gda-postgres-recordset.c | 35 +----
.../skel-implementation/capi/gda-capi-recordset.c | 74 +++++-----
11 files changed, 320 insertions(+), 494 deletions(-)
---
diff --git a/libgda/gda-data-model-import.c b/libgda/gda-data-model-import.c
index 9d4008c..a7107cb 100644
--- a/libgda/gda-data-model-import.c
+++ b/libgda/gda-data-model-import.c
@@ -1927,8 +1927,10 @@ gda_data_model_import_iter_next (GdaDataModel *model, GdaDataModelIter *iter)
break;
case FORMAT_CSV:
- if (! imodel->priv->extract.csv.rows_read)
+ if (! imodel->priv->extract.csv.rows_read) {
+ gda_data_model_iter_invalidate_contents (iter);
return FALSE;
+ }
if (gda_data_model_iter_is_valid (iter) &&
(imodel->priv->extract.csv.rows_read->len > 0)) {
@@ -1957,27 +1959,17 @@ gda_data_model_import_iter_next (GdaDataModel *model, GdaDataModelIter *iter)
GSList *plist;
GSList *vlist;
gboolean update_model;
- gboolean allok = TRUE;
-
g_object_get (G_OBJECT (iter), "update-model", &update_model, NULL);
g_object_set (G_OBJECT (iter), "update-model", FALSE, NULL);
for (plist = ((GdaSet *) iter)->holders, vlist = next_values;
plist && vlist;
plist = plist->next, vlist = vlist->next) {
GError *lerror = NULL;
- if (! gda_holder_set_value (GDA_HOLDER (plist->data),
- (GValue *) vlist->data, &lerror)) {
- gchar *tmp;
- tmp = g_strdup_printf (_("Could not set iterator's value: %s"),
- lerror && lerror->message ? lerror->message : _("No detail"));
- add_error (imodel, tmp);
- g_free (tmp);
- allok = FALSE;
- }
+ if (! gda_holder_set_value (GDA_HOLDER (plist->data),
+ (GValue *) vlist->data, &lerror))
+ gda_holder_force_invalid_e (GDA_HOLDER (plist->data), lerror);
}
if (plist || vlist) {
- if (imodel->priv->strict)
- allok = FALSE;
if (plist) {
add_error_too_few_values (imodel);
for (; plist; plist = plist->next) {
@@ -1998,11 +1990,12 @@ gda_data_model_import_iter_next (GdaDataModel *model, GdaDataModelIter *iter)
g_object_set (G_OBJECT (iter), "current-row", imodel->priv->iter_row,
"update-model", update_model, NULL);
- return allok;
+ return TRUE;
}
else {
- g_signal_emit_by_name (iter, "end-of-data");
+ gda_data_model_iter_invalidate_contents (iter);
g_object_set (G_OBJECT (iter), "current-row", -1, NULL);
+ g_signal_emit_by_name (iter, "end-of-data");
return FALSE;
}
}
@@ -2035,7 +2028,6 @@ gda_data_model_import_iter_prev (GdaDataModel *model, GdaDataModelIter *iter)
GSList *plist;
GSList *vlist;
gboolean update_model;
- gboolean allok = TRUE;
g_object_get (G_OBJECT (iter), "update-model", &update_model, NULL);
g_object_set (G_OBJECT (iter), "update-model", FALSE, NULL);
@@ -2043,19 +2035,11 @@ gda_data_model_import_iter_prev (GdaDataModel *model, GdaDataModelIter *iter)
plist && vlist;
plist = plist->next, vlist = vlist->next) {
GError *lerror = NULL;
- if (! gda_holder_set_value (GDA_HOLDER (plist->data),
- (GValue *) vlist->data, &lerror)) {
- gchar *tmp;
- tmp = g_strdup_printf (_("Could not set iterator's value: %s"),
- lerror && lerror->message ? lerror->message : _("No detail"));
- add_error (imodel, tmp);
- g_free (tmp);
- allok = FALSE;
- }
+ if (! gda_holder_set_value (GDA_HOLDER (plist->data),
+ (GValue *) vlist->data, &lerror))
+ gda_holder_force_invalid_e (GDA_HOLDER (plist->data), lerror);
}
if (plist || vlist) {
- if (imodel->priv->strict)
- allok = FALSE;
if (plist) {
add_error_too_few_values (imodel);
for (; plist; plist = plist->next) {
@@ -2075,9 +2059,10 @@ gda_data_model_import_iter_prev (GdaDataModel *model, GdaDataModelIter *iter)
g_assert (imodel->priv->iter_row >= 0);
g_object_set (G_OBJECT (iter), "current-row", imodel->priv->iter_row,
"update-model", update_model, NULL);
- return allok;
+ return TRUE;
}
else {
+ gda_data_model_iter_invalidate_contents (iter);
g_object_set (G_OBJECT (iter), "current-row", -1, NULL);
return FALSE;
}
diff --git a/libgda/gda-data-model-iter.c b/libgda/gda-data-model-iter.c
index e2da293..087a635 100644
--- a/libgda/gda-data-model-iter.c
+++ b/libgda/gda-data-model-iter.c
@@ -577,14 +577,18 @@ gda_data_model_iter_get_property (GObject *object,
*
* Synchronizes the values of the parameters in @iter with the values at the @row row.
*
- * If @row is not a valid row, then the returned value is FALSE, and the "current-row"
- * property is set to -1 (which means that gda_data_model_iter_is_valid() would return FALSE)
+ * If @row is not a valid row, then the returned value is %FALSE, and the "current-row"
+ * property is set to -1 (which means that gda_data_model_iter_is_valid() would return %FALSE),
+ * with the exception that if @row is -1, then the returned value is %TRUE.
*
- * If any other error occurred then the returned value is FALSE, but the "current-row"
- * property is set to the @row row. In this case
- * each #GdaHolder composing @iter for which an error occurred will be invalid (see gda_holder_is_valid()).
+ * This function can return %FALSE if it was not allowed to be moved (as it emits the
+ * "validate-set" signal before being moved).
*
- * Returns: TRUE if no error occurred
+ * When this function returns %TRUE, then @iter has actually been moved to the next row,
+ * but some values may not have been read correctly in the row, in which case the
+ * correcsponding #GdaHolder will be left invalid.
+ *
+ * Returns: %TRUE if no error occurred
*/
gboolean
gda_data_model_iter_move_to_row (GdaDataModelIter *iter, gint row)
@@ -592,8 +596,15 @@ gda_data_model_iter_move_to_row (GdaDataModelIter *iter, gint row)
g_return_val_if_fail (GDA_IS_DATA_MODEL_ITER (iter), FALSE);
g_return_val_if_fail (iter->priv, FALSE);
+ if ((gda_data_model_iter_get_row (iter) >= 0) &&
+ (gda_data_model_iter_get_row (iter) == row))
+ return TRUE; /* nothing to do! */
+
if (row < 0) {
- if (iter->priv->row != -1) {
+ if (gda_data_model_iter_get_row (iter) >= 0) {
+ if (! _gda_set_validate ((GdaSet*) iter, NULL))
+ return FALSE;
+
iter->priv->row = -1;
g_signal_emit (G_OBJECT (iter),
gda_data_model_iter_signals[ROW_CHANGED],
@@ -603,44 +614,18 @@ gda_data_model_iter_move_to_row (GdaDataModelIter *iter, gint row)
}
else {
GdaDataModel *model;
- if ((gda_data_model_iter_get_row (iter) >= 0) &&
- (gda_data_model_iter_get_row (iter) != row) &&
- ! _gda_set_validate ((GdaSet*) iter, NULL)) {
- return FALSE;
- }
-
- gboolean *null_oks = NULL;
- if (GDA_SET (iter)->holders) {
- gint i;
- GSList *list;
-
- null_oks = g_new (gboolean, g_slist_length (GDA_SET (iter)->holders));
- for (i = 0, list = GDA_SET (iter)->holders; list; i++, list = list->next) {
- null_oks[i] = gda_holder_get_not_null ((GdaHolder*) list->data);
- gda_holder_set_not_null ((GdaHolder*) list->data, FALSE);
- }
- }
-
- gboolean move_ok;
model = iter->priv->data_model;
g_return_val_if_fail (iter->priv->data_model, FALSE);
- if (GDA_DATA_MODEL_GET_CLASS (model)->i_iter_at_row)
- move_ok = (GDA_DATA_MODEL_GET_CLASS (model)->i_iter_at_row) (model, iter, row);
- else {
- /* default method */
- move_ok = gda_data_model_iter_move_to_row_default (model, iter, row);
+ if (GDA_DATA_MODEL_GET_CLASS (model)->i_iter_at_row) {
+ if ((gda_data_model_iter_get_row (iter) >= 0) &&
+ ! _gda_set_validate ((GdaSet*) iter, NULL))
+ return FALSE;
+ return (GDA_DATA_MODEL_GET_CLASS (model)->i_iter_at_row) (model, iter,
+ row);
}
-
- if (null_oks) {
- gint i;
- GSList *list;
- for (i = 0, list = GDA_SET (iter)->holders; list; i++, list = list->next)
- gda_holder_set_not_null ((GdaHolder*) list->data, null_oks[i]);
- g_free (null_oks);
- }
-
- return move_ok;
+ else
+ return gda_data_model_iter_move_to_row_default (model, iter, row);
}
}
@@ -658,6 +643,13 @@ set_param_attributes (GdaHolder *holder, GdaValueAttribute flags)
/**
* gda_data_model_iter_move_to_row_default: (skip)
+ * @model: a #GdaDataModel
+ * @iter: a #GdaDataModelIter iterating in @model
+ * @row: the requested row
+ *
+ * Method reserved to #GdaDataModelIter implementations, should not be called directly.
+ *
+ * Returns: %TRUE if @iter was moved correctly.
*/
gboolean
gda_data_model_iter_move_to_row_default (GdaDataModel *model, GdaDataModelIter *iter, gint row)
@@ -668,7 +660,9 @@ gda_data_model_iter_move_to_row_default (GdaDataModel *model, GdaDataModelIter *
GdaDataModel *test;
gboolean update_model;
- g_return_val_if_fail (GDA_IS_DATA_MODEL (model), FALSE);
+ if ((gda_data_model_iter_get_row (iter) >= 0) &&
+ ! _gda_set_validate ((GdaSet*) iter, NULL))
+ return FALSE;
if (! (gda_data_model_get_access_flags (model) & GDA_DATA_MODEL_ACCESS_RANDOM))
return FALSE;
@@ -713,14 +707,17 @@ gda_data_model_iter_move_to_row_default (GdaDataModel *model, GdaDataModelIter *
* (synchronizes the values of the parameters in @iter with the values at the new row).
*
* If the iterator was on the data model's last row, then it can't be moved forward
- * anymore, and the returned value is FALSE; nore also that the "current-row" property
- * is set to -1 (which means that gda_data_model_iter_is_valid() would return FALSE)
+ * anymore, and the returned value is %FALSE; note also that the "current-row" property
+ * is set to -1 (which means that gda_data_model_iter_is_valid() would return %FALSE)
+ *
+ * This function can return %FALSE if it was not allowed to be moved (as it emits the
+ * "validate-set" signal before being moved).
*
- * If any other error occurred then the returned value is FALSE, but the "current-row"
- * property is set to the new current row (one row more than it was before the call). In this case
- * each #GdaHolder composing @iter for which an error occurred will be invalid (see gda_holder_is_valid()).
+ * When this function returns %TRUE, then @iter has actually been moved to the next row,
+ * but some values may not have been read correctly in the row, in which case the
+ * correcsponding #GdaHolder will be left invalid.
*
- * Returns: TRUE if the iterator is now at the next row
+ * Returns: %TRUE if the iterator is now at the next row
*/
gboolean
gda_data_model_iter_move_next (GdaDataModelIter *iter)
@@ -730,13 +727,13 @@ gda_data_model_iter_move_next (GdaDataModelIter *iter)
g_return_val_if_fail (iter->priv, FALSE);
g_return_val_if_fail (iter->priv->data_model, FALSE);
- if ((gda_data_model_iter_get_row (iter) >= 0) &&
- ! _gda_set_validate ((GdaSet*) iter, NULL))
- return FALSE;
-
model = iter->priv->data_model;
- if (GDA_DATA_MODEL_GET_CLASS (model)->i_iter_next)
+ if (GDA_DATA_MODEL_GET_CLASS (model)->i_iter_next) {
+ if ((gda_data_model_iter_get_row (iter) >= 0) &&
+ ! _gda_set_validate ((GdaSet*) iter, NULL))
+ return FALSE;
return (GDA_DATA_MODEL_GET_CLASS (model)->i_iter_next) (model, iter);
+ }
else
/* default method */
return gda_data_model_iter_move_next_default (model, iter);
@@ -744,6 +741,12 @@ gda_data_model_iter_move_next (GdaDataModelIter *iter)
/**
* gda_data_model_iter_move_next_default: (skip)
+ * @model: a #GdaDataModel
+ * @iter: a #GdaDataModelIter iterating in @model
+ *
+ * Method reserved to #GdaDataModelIter implementations, should not be called directly.
+ *
+ * Returns: %TRUE if @iter was moved correctly.
*/
gboolean
gda_data_model_iter_move_next_default (GdaDataModel *model, GdaDataModelIter *iter)
@@ -753,8 +756,11 @@ gda_data_model_iter_move_next_default (GdaDataModel *model, GdaDataModelIter *it
gint row;
GdaDataModel *test;
gboolean update_model;
-
- /* validity tests */
+
+ if ((gda_data_model_iter_get_row (iter) >= 0) &&
+ ! _gda_set_validate ((GdaSet*) iter, NULL))
+ return FALSE;
+
if (! (gda_data_model_get_access_flags (model) & GDA_DATA_MODEL_ACCESS_RANDOM))
return FALSE;
@@ -799,14 +805,17 @@ gda_data_model_iter_move_next_default (GdaDataModel *model, GdaDataModelIter *it
* with the values at the new row).
*
* If the iterator was on the data model's first row, then it can't be moved backwards
- * anymore, and the returned value is FALSE; note also that the "current-row" property
- * is set to -1 (which means that gda_data_model_iter_is_valid() would return FALSE).
+ * anymore, and the returned value is %FALSE; note also that the "current-row" property
+ * is set to -1 (which means that gda_data_model_iter_is_valid() would return %FALSE).
+ *
+ * This function can return %FALSE if it was not allowed to be moved (as it emits the
+ * "validate-set" signal before being moved).
*
- * If any other error occurred then the returned value is FALSE, but the "current-row"
- * property is set to the new current row (one row less than it was before the call). In this case
- * each #GdaHolder composing @iter for which an error occurred will be invalid (see gda_holder_is_valid()).
+ * When this function returns %TRUE, then @iter has actually been moved to the next row,
+ * but some values may not have been read correctly in the row, in which case the
+ * correcsponding #GdaHolder will be left invalid.
*
- * Returns: TRUE if the iterator is now at the previous row
+ * Returns: %TRUE if the iterator is now at the previous row
*/
gboolean
gda_data_model_iter_move_prev (GdaDataModelIter *iter)
@@ -817,13 +826,13 @@ gda_data_model_iter_move_prev (GdaDataModelIter *iter)
g_return_val_if_fail (iter->priv, FALSE);
g_return_val_if_fail (iter->priv->data_model, FALSE);
- if ((gda_data_model_iter_get_row (iter) >= 0) &&
- ! _gda_set_validate ((GdaSet*) iter, NULL))
- return FALSE;
-
model = iter->priv->data_model;
- if (GDA_DATA_MODEL_GET_CLASS (model)->i_iter_prev)
+ if (GDA_DATA_MODEL_GET_CLASS (model)->i_iter_prev) {
+ if ((gda_data_model_iter_get_row (iter) >= 0) &&
+ ! _gda_set_validate ((GdaSet*) iter, NULL))
+ return FALSE;
return (GDA_DATA_MODEL_GET_CLASS (model)->i_iter_prev) (model, iter);
+ }
else
/* default method */
return gda_data_model_iter_move_prev_default (model, iter);
@@ -831,6 +840,12 @@ gda_data_model_iter_move_prev (GdaDataModelIter *iter)
/**
* gda_data_model_iter_move_prev_default: (skip)
+ * @model: a #GdaDataModel
+ * @iter: a #GdaDataModelIter iterating in @model
+ *
+ * Method reserved to #GdaDataModelIter implementations, should not be called directly.
+ *
+ * Returns: %TRUE if @iter was moved correctly.
*/
gboolean
gda_data_model_iter_move_prev_default (GdaDataModel *model, GdaDataModelIter *iter)
@@ -841,7 +856,10 @@ gda_data_model_iter_move_prev_default (GdaDataModel *model, GdaDataModelIter *it
GdaDataModel *test;
gboolean update_model;
- /* validity tests */
+ if ((gda_data_model_iter_get_row (iter) >= 0) &&
+ ! _gda_set_validate ((GdaSet*) iter, NULL))
+ return FALSE;
+
if (! (gda_data_model_get_access_flags (model) & GDA_DATA_MODEL_ACCESS_RANDOM))
return FALSE;
diff --git a/libgda/gda-data-select.c b/libgda/gda-data-select.c
index 01e735f..aa66e49 100644
--- a/libgda/gda-data-select.c
+++ b/libgda/gda-data-select.c
@@ -1923,20 +1923,12 @@ gda_data_select_get_value_at (GdaDataModel *model, gint col, gint row, GError **
prow = dstmt->row;
}
else {
- gint *ptr;
- irow = int_row;
- ptr = g_hash_table_lookup (imodel->priv->sh->index, &irow);
- if (!ptr) {
- prow = NULL;
- if (CLASS (model)->fetch_random &&
- !CLASS (model)->fetch_random (imodel, &prow, int_row, error))
- return NULL;
- }
- else
- prow = g_array_index (imodel->priv->sh->rows, GdaRow *, *ptr);
+ prow = gda_data_select_get_stored_row (imodel, int_row);
+ if (!prow && CLASS (model)->fetch_random)
+ CLASS (model)->fetch_random (imodel, &prow, int_row, error);
}
-
- g_assert (prow);
+ if (!prow)
+ return NULL;
GValue *retval = gda_row_get_value (prow, col);
if (gda_row_value_is_valid_e (prow, retval, error))
@@ -2011,7 +2003,7 @@ gda_data_select_create_iter (GdaDataModel *model)
}
}
-static gboolean update_iter (GdaDataSelect *imodel, GdaRow *prow);
+static void update_iter (GdaDataSelect *imodel, GdaRow *prow);
static gboolean
gda_data_select_iter_next (GdaDataModel *model, GdaDataModelIter *iter)
{
@@ -2027,37 +2019,33 @@ gda_data_select_iter_next (GdaDataModel *model, GdaDataModelIter *iter)
return gda_data_model_iter_move_next_default (model, iter);
g_return_val_if_fail (CLASS (model)->fetch_next, FALSE);
-
g_return_val_if_fail (iter, FALSE);
g_return_val_if_fail (imodel->priv->iter == iter, FALSE);
- if (imodel->priv->sh->iter_row == G_MAXINT)
+ if (imodel->priv->sh->iter_row == G_MAXINT) {
+ gda_data_model_iter_invalidate_contents (iter);
return FALSE;
+ }
else if (imodel->priv->sh->iter_row == G_MININT)
target_iter_row = 0;
else
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)
+ CLASS (model)->fetch_next (imodel, &prow, int_row, NULL);
- gint *ptr;
- irow = int_row;
- ptr = g_hash_table_lookup (imodel->priv->sh->index, &irow);
- if (ptr)
- prow = g_array_index (imodel->priv->sh->rows, GdaRow *, *ptr);
- else if (!CLASS (model)->fetch_next (imodel, &prow, int_row, NULL)) {
- /* an error occurred */
- g_object_set (G_OBJECT (iter), "current-row", target_iter_row, NULL);
- return FALSE;
- }
-
if (prow) {
imodel->priv->sh->iter_row = target_iter_row;
- return update_iter (imodel, prow);
+ update_iter (imodel, prow);
+ return TRUE;
}
else {
- g_signal_emit_by_name (iter, "end-of-data");
- g_object_set (G_OBJECT (iter), "current-row", -1, NULL);
+ gda_data_model_iter_invalidate_contents (iter);
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;
}
}
@@ -2076,8 +2064,10 @@ 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)
+ 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);
@@ -2092,26 +2082,21 @@ gda_data_select_iter_prev (GdaDataModel *model, GdaDataModelIter *iter)
else
target_iter_row = imodel->priv->sh->iter_row - 1;
- gint *ptr;
int_row = external_to_internal_row (imodel, target_iter_row, NULL);
- irow = int_row;
- ptr = g_hash_table_lookup (imodel->priv->sh->index, &irow);
- if (ptr)
- prow = g_array_index (imodel->priv->sh->rows, GdaRow *, *ptr);
- else if (!CLASS (model)->fetch_prev (imodel, &prow, int_row, NULL)) {
- /* an error occurred */
- g_object_set (G_OBJECT (iter), "current-row", target_iter_row, NULL);
- return FALSE;
- }
+ prow = gda_data_select_get_stored_row (model, int_row);
+ if (!prow)
+ CLASS (model)->fetch_prev (imodel, &prow, int_row, NULL);
if (prow) {
imodel->priv->sh->iter_row = target_iter_row;
- return update_iter (imodel, prow);
+ update_iter (imodel, prow);
+ return TRUE;
}
prev_error:
g_object_set (G_OBJECT (iter), "current-row", -1, NULL);
imodel->priv->sh->iter_row = G_MININT;
+ gda_data_model_iter_invalidate_contents (iter);
return FALSE;
}
@@ -2125,39 +2110,34 @@ gda_data_select_iter_at_row (GdaDataModel *model, GdaDataModelIter *iter, gint r
imodel = (GdaDataSelect *) model;
g_return_val_if_fail (imodel->priv, FALSE);
- int_row = external_to_internal_row (imodel, row, NULL);
- if (imodel->priv->sh->usage_flags & GDA_DATA_MODEL_ACCESS_RANDOM)
+ if (imodel->priv->sh->usage_flags & GDA_DATA_MODEL_ACCESS_RANDOM)
return gda_data_model_iter_move_to_row_default (model, iter, row);
g_return_val_if_fail (iter, FALSE);
g_return_val_if_fail (imodel->priv->iter == iter, FALSE);
- irow = int_row;
- ptr = g_hash_table_lookup (imodel->priv->sh->index, &irow);
- if (ptr)
- prow = g_array_index (imodel->priv->sh->rows, GdaRow *, *ptr);
-
- if (CLASS (model)->fetch_at) {
- if (!CLASS (model)->fetch_at (imodel, &prow, int_row, NULL)) {
- /* an error occurred */
- g_object_set (G_OBJECT (iter), "current-row", row, NULL);
- return FALSE;
- }
+ int_row = external_to_internal_row (imodel, row, NULL);
+ prow = gda_data_select_get_stored_row (model, int_row);
- if (prow) {
- imodel->priv->sh->iter_row = row;
- return update_iter (imodel, prow);
- }
- else {
- g_object_set (G_OBJECT (iter), "current-row", -1, NULL);
- imodel->priv->sh->iter_row = G_MININT;
- return FALSE;
- }
+ if (prow) {
+ imodel->priv->sh->iter_row = row;
+ update_iter (imodel, prow);
+ return TRUE;
}
else {
- if (prow) {
- imodel->priv->sh->iter_row = row;
- return update_iter (imodel, prow);
+ if (CLASS (model)->fetch_at) {
+ CLASS (model)->fetch_at (imodel, &prow, int_row, NULL);
+ if (prow) {
+ imodel->priv->sh->iter_row = row;
+ update_iter (imodel, prow);
+ return TRUE;
+ }
+ else {
+ g_object_set (G_OBJECT (iter), "current-row", -1, NULL);
+ imodel->priv->sh->iter_row = G_MININT;
+ gda_data_model_iter_invalidate_contents (iter);
+ return FALSE;
+ }
}
else {
/* implementation of fetch_at() is optional */
@@ -2181,15 +2161,13 @@ gda_data_select_iter_at_row (GdaDataModel *model, GdaDataModelIter *iter, gint r
}
}
-static gboolean
+static void
update_iter (GdaDataSelect *imodel, GdaRow *prow)
{
gint i;
GdaDataModelIter *iter = imodel->priv->iter;
GSList *plist;
gboolean update_model;
- gboolean retval = TRUE;
-
g_object_get (G_OBJECT (iter), "update-model", &update_model, NULL);
if (update_model)
g_object_set (G_OBJECT (iter), "update-model", FALSE, NULL);
@@ -2199,7 +2177,6 @@ update_iter (GdaDataSelect *imodel, GdaRow *prow)
i++, plist = plist->next) {
GValue *value;
GError *lerror = NULL;
- gboolean pok = TRUE;
value = gda_row_get_value (prow, i);
if (!gda_row_value_is_valid_e (prow, value, &lerror)) {
@@ -2213,7 +2190,7 @@ update_iter (GdaDataSelect *imodel, GdaRow *prow)
gda_value_is_null (value)) {
gda_holder_set_not_null ((GdaHolder*) plist->data, FALSE);
if (! gda_holder_set_value ((GdaHolder*) plist->data, value, NULL)) {
- pok = FALSE;
+ gda_holder_force_invalid_e ((GdaHolder*) plist->data, lerror);
g_warning (_("Could not change iter's value for column %d: %s"), i,
lerror && lerror->message ? lerror->message : _("No detail"));
gda_holder_set_not_null ((GdaHolder*) plist->data, TRUE);
@@ -2223,23 +2200,18 @@ update_iter (GdaDataSelect *imodel, GdaRow *prow)
"to be updated"));
}
else {
- pok = FALSE;
+ gda_holder_force_invalid_e ((GdaHolder*) plist->data, lerror);
g_warning (_("Could not change iter's value for column %d: %s"), i,
lerror && lerror->message ? lerror->message : _("No detail"));
}
}
- if (!pok) {
- retval = FALSE;
- gda_holder_force_invalid_e ((GdaHolder*) plist->data, lerror);
- }
}
g_object_set (G_OBJECT (iter), "current-row", imodel->priv->sh->iter_row, NULL);
if (update_model)
g_object_set (G_OBJECT (iter), "update-model", update_model, NULL);
- g_print ("%s(%p) => %d, current-row =>%d advertized_nrows => %d\n", __FUNCTION__, imodel, retval, imodel->priv->sh->iter_row, imodel->advertized_nrows);
- return retval;
+ g_print ("%s(%p), current-row =>%d advertized_nrows => %d\n", __FUNCTION__, imodel, imodel->priv->sh->iter_row, imodel->advertized_nrows);
}
/*
diff --git a/libgda/sqlite/gda-sqlite-recordset.c b/libgda/sqlite/gda-sqlite-recordset.c
index 5663ff8..b54109b 100644
--- a/libgda/sqlite/gda-sqlite-recordset.c
+++ b/libgda/sqlite/gda-sqlite-recordset.c
@@ -639,35 +639,24 @@ gda_sqlite_recordset_fetch_nb_rows (GdaDataSelect *model)
/*
* Create a new filled #GdaRow object for the row at position @rownum.
*
- * Each new #GdaRow created is "given" to the #GdaDataSelect implementation using gda_data_select_take_row ().
+ * Each new #GdaRow created needs to be "given" to the #GdaDataSelect implementation using
+ * gda_data_select_take_row() because backward iterating is not supported.
*/
static gboolean
gda_sqlite_recordset_fetch_random (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
{
GdaSqliteRecordset *imodel;
- if (*prow)
- return TRUE;
-
imodel = GDA_SQLITE_RECORDSET (model);
- for (; imodel->priv->next_row_num <= rownum; ) {
- *prow = fetch_next_sqlite_row (imodel, TRUE, error);
- if (!*prow) {
- /*if (GDA_DATA_SELECT (model)->advertized_nrows >= 0), it's not an error */
- if ((GDA_DATA_SELECT (model)->advertized_nrows >= 0) &&
- (imodel->priv->next_row_num < rownum)) {
- g_set_error (error, 0,
- GDA_DATA_MODEL_ROW_OUT_OF_RANGE_ERROR,
- _("Row %d not found"), rownum);
- }
- return FALSE;
- }
- }
- if (! *prow) {
- *prow = gda_data_select_get_stored_row (model, rownum);
- if (!*prow)
- return FALSE;
+ if (imodel->priv->next_row_num >= rownum) {
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+ GDA_SERVER_PROVIDER_INTERNAL_ERROR,
+ "%s", _("Requested row could not be found"));
+ return TRUE;
}
+ for (*prow = fetch_next_sqlite_row (imodel, TRUE, error);
+ *prow && (imodel->priv->next_row_num < rownum);
+ *prow = fetch_next_sqlite_row (imodel, TRUE, error));
return TRUE;
}
@@ -676,16 +665,16 @@ gda_sqlite_recordset_fetch_random (GdaDataSelect *model, GdaRow **prow, gint row
* Create a new filled #GdaRow object for the next cursor row
*
* Each new #GdaRow created is referenced only by imodel->priv->tmp_row (the #GdaDataSelect implementation
- * never keeps a reference to it). Before a new #GdaRow gets created, the previous one, if set, is discarded.
+ * never keeps a reference to it).
+ * 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)
{
GdaSqliteRecordset *imodel = (GdaSqliteRecordset*) model;
- if (imodel->priv->tmp_row)
+ if (imodel->priv->tmp_row)
g_object_unref (imodel->priv->tmp_row);
-
*prow = fetch_next_sqlite_row (imodel, FALSE, error);
imodel->priv->tmp_row = *prow;
diff --git a/providers/firebird/gda-firebird-recordset.c b/providers/firebird/gda-firebird-recordset.c
index 669ac2d..050bfb1 100644
--- a/providers/firebird/gda-firebird-recordset.c
+++ b/providers/firebird/gda-firebird-recordset.c
@@ -238,17 +238,15 @@ gda_firebird_recordset_fetch_nb_rows (GdaDataSelect *model)
/*
* Create a new filled #GdaRow object for the row at position @rownum, and put it into *prow.
*
- * WARNING: @prow will NOT be NULL, but *prow may or may not be NULL:
- * - If *prow is NULL then a new #GdaRow object has to be created,
- * - and otherwise *prow contains a #GdaRow object which has already been created
- * (through a call to this very function), and in this case it should not be modified
- * but the function may return FALSE if an error occurred.
- *
- * Memory management for that new GdaRow object is left to the implementation, which
- * can use gda_data_select_take_row(). If new row objects are "given" to the GdaDataSelect implemantation
- * using that method, then this method should detect when all the data model rows have been analyzed
- * (when model->nb_stored_rows == model->advertized_nrows) and then possibly discard the API handle
- * as it won't be used anymore to fetch rows.
+ * NOTES:
+ * - @prow will NOT be NULL, but *prow WILL be NULL.
+ * - a new #GdaRow object has to be created.
+ * - memory management for that new GdaRow object is left to the implementation, which
+ * can use gda_data_select_take_row() to "give" the GdaRow to @model (in this case
+ * this method won't be called anymore for the same @rownum), or may decide to
+ * keep a cache of GdaRow object and "recycle" them.
+ * - implementing this method is MANDATORY if the data model supports random access
+ * - this method is only called when data model is used in random access mode
*/
static gboolean
gda_firebird_recordset_fetch_random (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
@@ -285,14 +283,15 @@ gda_firebird_recordset_store_all (GdaDataSelect *model, GError **error)
/*
* Create a new filled #GdaRow object for the next cursor row, and put it into *prow.
*
- * WARNING: @prow will NOT be NULL, but *prow may or may not be NULL:
- * - If *prow is NULL then a new #GdaRow object has to be created,
- * - and otherwise *prow contains a #GdaRow object which has already been created
- * (through a call to this very function), and in this case it should not be modified
- * but the function may return FALSE if an error occurred.
- *
- * Memory management for that new GdaRow object is left to the implementation, which
- * can use gda_data_select_take_row().
+ * NOTES:
+ * - @prow will NOT be NULL, but *prow WILL be NULL.
+ * - a new #GdaRow object has to be created.
+ * - memory management for that new GdaRow object is left to the implementation, which
+ * can use gda_data_select_take_row() to "give" the GdaRow to @model (in this case
+ * this method won't be called anymore for the same @rownum), or may decide to
+ * keep a cache of GdaRow object and "recycle" them.
+ * - implementing this method is MANDATORY
+ * - this method is only called when data model is used in cursor access mode
*/
static gboolean
gda_firebird_recordset_fetch_next (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
@@ -307,14 +306,16 @@ gda_firebird_recordset_fetch_next (GdaDataSelect *model, GdaRow **prow, gint row
/*
* Create a new filled #GdaRow object for the previous cursor row, and put it into *prow.
*
- * WARNING: @prow will NOT be NULL, but *prow may or may not be NULL:
- * - If *prow is NULL then a new #GdaRow object has to be created,
- * - and otherwise *prow contains a #GdaRow object which has already been created
- * (through a call to this very function), and in this case it should not be modified
- * but the function may return FALSE if an error occurred.
- *
- * Memory management for that new GdaRow object is left to the implementation, which
- * can use gda_data_select_take_row().
+ * NOTES:
+ * - @prow will NOT be NULL, but *prow WILL be NULL.
+ * - a new #GdaRow object has to be created.
+ * - memory management for that new GdaRow object is left to the implementation, which
+ * can use gda_data_select_take_row() to "give" the GdaRow to @model (in this case
+ * this method won't be called anymore for the same @rownum), or may decide to
+ * keep a cache of GdaRow object and "recycle" them.
+ * - implementing this method is OPTIONAL (in this case the data model is assumed not to
+ * support moving iterators backward)
+ * - this method is only called when data model is used in cursor access mode
*/
static gboolean
gda_firebird_recordset_fetch_prev (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
@@ -329,14 +330,16 @@ gda_firebird_recordset_fetch_prev (GdaDataSelect *model, GdaRow **prow, gint row
/*
* Create a new filled #GdaRow object for the cursor row at position @rownum, and put it into *prow.
*
- * WARNING: @prow will NOT be NULL, but *prow may or may not be NULL:
- * - If *prow is NULL then a new #GdaRow object has to be created,
- * - and otherwise *prow contains a #GdaRow object which has already been created
- * (through a call to this very function), and in this case it should not be modified
- * but the function may return FALSE if an error occurred.
- *
- * Memory management for that new GdaRow object is left to the implementation, which
- * can use gda_data_select_take_row().
+ * NOTES:
+ * - @prow will NOT be NULL, but *prow WILL be NULL.
+ * - a new #GdaRow object has to be created.
+ * - memory management for that new GdaRow object is left to the implementation, which
+ * can use gda_data_select_take_row() to "give" the GdaRow to @model (in this case
+ * this method won't be called anymore for the same @rownum), or may decide to
+ * keep a cache of GdaRow object and "recycle" them.
+ * - implementing this method is OPTIONAL and usefull only if there is a method quicker
+ * than iterating one step at a time to the correct position.
+ * - this method is only called when data model is used in cursor access mode
*/
static gboolean
gda_firebird_recordset_fetch_at (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
diff --git a/providers/jdbc/gda-jdbc-recordset.c b/providers/jdbc/gda-jdbc-recordset.c
index 1841372..de070ce 100644
--- a/providers/jdbc/gda-jdbc-recordset.c
+++ b/providers/jdbc/gda-jdbc-recordset.c
@@ -410,11 +410,13 @@ fetch_next_jdbc_row (GdaJdbcRecordset *model, JNIEnv *jenv, gboolean do_store, G
prow = gda_row_new (_GDA_PSTMT (ps)->ncols);
jexec_res = jni_wrapper_method_call (jenv, GdaJResultSet__fillNextRow,
- model->priv->rs_value, &error_code, &sql_state, &lerror, (jlong)GPOINTER_TO_INT(prow));
+ model->priv->rs_value, &error_code, &sql_state, &lerror,
+ (jlong)GPOINTER_TO_INT(prow));
if (!jexec_res) {
if (error && lerror)
*error = g_error_copy (lerror);
_gda_jdbc_make_error (model->priv->cnc, error_code, sql_state, lerror);
+ g_object_unref ((GObject*) prow);
return NULL;
}
@@ -422,6 +424,7 @@ fetch_next_jdbc_row (GdaJdbcRecordset *model, JNIEnv *jenv, gboolean do_store, G
gda_value_free (jexec_res);
if (! row_found) {
GDA_DATA_SELECT (model)->advertized_nrows = model->priv->next_row_num;
+ g_object_unref ((GObject*) prow);
return NULL;
}
@@ -465,7 +468,8 @@ gda_jdbc_recordset_fetch_nb_rows (GdaDataSelect *model)
/*
* Create a new filled #GdaRow object for the row at position @rownum.
*
- * Each new #GdaRow created is "given" to the #GdaDataSelect implementation using gda_data_select_take_row ().
+ * Each new #GdaRow created is "given" to the #GdaDataSelect implementation
+ * using gda_data_select_take_row ().
*/
static gboolean
gda_jdbc_recordset_fetch_random (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
@@ -476,23 +480,18 @@ gda_jdbc_recordset_fetch_random (GdaDataSelect *model, GdaRow **prow, gint rownu
jenv = _gda_jdbc_get_jenv (&jni_detach, NULL);
if (!jenv)
- return FALSE;
+ return TRUE;
imodel = GDA_JDBC_RECORDSET (model);
- for (; imodel->priv->next_row_num <= rownum; ) {
- *prow = fetch_next_jdbc_row (imodel, jenv, TRUE, error);
- if (!*prow) {
- /*if (GDA_DATA_SELECT (model)->advertized_nrows >= 0), it's not an error */
- if ((GDA_DATA_SELECT (model)->advertized_nrows >= 0) &&
- (imodel->priv->next_row_num < rownum)) {
- g_set_error (error, 0,
- GDA_DATA_MODEL_ROW_OUT_OF_RANGE_ERROR,
- _("Row %d not found"), rownum);
- }
- _gda_jdbc_release_jenv (jni_detach);
- return FALSE;
- }
- }
+ if (imodel->priv->next_row_num >= rownum) {
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+ GDA_SERVER_PROVIDER_INTERNAL_ERROR,
+ "%s", _("Requested row could not be found"));
+ return TRUE;
+ }
+ for (*prow = fetch_next_jdbc_row (imodel, jenv, TRUE, error);
+ *prow && (imodel->priv->next_row_num < rownum);
+ *prow = fetch_next_jdbc_row (imodel, jenv, TRUE, error));
_gda_jdbc_release_jenv (jni_detach);
return TRUE;
@@ -502,7 +501,8 @@ gda_jdbc_recordset_fetch_random (GdaDataSelect *model, GdaRow **prow, gint rownu
* Create a new filled #GdaRow object for the next cursor row, and put it into *prow.
*
* Each new #GdaRow created is referenced only by imodel->priv->tmp_row (the #GdaDataSelect implementation
- * never keeps a reference to it). Before a new #GdaRow gets created, the previous one, if set, is discarded.
+ * never keeps a reference to it). Before a new #GdaRow gets created, the previous one,
+ * if set, is discarded.
*/
static gboolean
gda_jdbc_recordset_fetch_next (GdaDataSelect *model, GdaRow **prow, G_GNUC_UNUSED gint rownum, GError **error)
@@ -515,9 +515,6 @@ gda_jdbc_recordset_fetch_next (GdaDataSelect *model, GdaRow **prow, G_GNUC_UNUSE
if (!jenv)
return FALSE;
- if (*prow)
- return TRUE;
-
if (imodel->priv->tmp_row)
g_object_unref (imodel->priv->tmp_row);
diff --git a/providers/ldap/gdaprov-data-model-ldap.c b/providers/ldap/gdaprov-data-model-ldap.c
index 4c6f8a3..a4ff290 100644
--- a/providers/ldap/gdaprov-data-model-ldap.c
+++ b/providers/ldap/gdaprov-data-model-ldap.c
@@ -1045,12 +1045,14 @@ gda_data_model_ldap_iter_next (GdaDataModel *model, GdaDataModelIter *iter)
if (! imodel->priv->cnc) {
/* error */
+ gda_data_model_iter_invalidate_contents (iter);
return FALSE;
}
cdata = (LdapConnectionData*) gda_virtual_connection_internal_get_provider_data (GDA_VIRTUAL_CONNECTION (imodel->priv->cnc));
if (!cdata) {
/* error */
+ gda_data_model_iter_invalidate_contents (iter);
return FALSE;
}
@@ -1071,6 +1073,7 @@ gda_data_model_ldap_iter_next (GdaDataModel *model, GdaDataModelIter *iter)
cpart = imodel->priv->current_exec;
if (! cpart->ldap_msg) {
/* error somewhere */
+ gda_data_model_iter_invalidate_contents (iter);
return FALSE;
}
@@ -1101,7 +1104,7 @@ gda_data_model_ldap_iter_next (GdaDataModel *model, GdaDataModelIter *iter)
if (!imodel->priv->current_exec) {
/* execution is over */
- g_signal_emit_by_name (iter, "end-of-data");
+ gda_data_model_iter_invalidate_contents (iter);
g_object_set (G_OBJECT (iter), "current-row", -1, NULL);
if (imodel->priv->truncated) {
GError *e;
@@ -1110,6 +1113,7 @@ gda_data_model_ldap_iter_next (GdaDataModel *model, GdaDataModelIter *iter)
_("Truncated result because LDAP server limit encountered"));
add_exception (imodel, e);
}
+ g_signal_emit_by_name (iter, "end-of-data");
return FALSE;
}
diff --git a/providers/mysql/gda-mysql-recordset.c b/providers/mysql/gda-mysql-recordset.c
index 3ffb940..33a222a 100644
--- a/providers/mysql/gda-mysql-recordset.c
+++ b/providers/mysql/gda-mysql-recordset.c
@@ -1002,17 +1002,7 @@ new_row_from_mysql_stmt (GdaMysqlRecordset *imodel, G_GNUC_UNUSED gint rownum, G
/*
* Create a new filled #GdaRow object for the row at position @rownum, and put it into *row.
*
- * WARNING: @row will NOT be NULL, but *row may or may not be NULL:
- * - If *row is NULL then a new #GdaRow object has to be created,
- * - and otherwise *row contains a #GdaRow object which has already been created
- * (through a call to this very function), and in this case it should not be modified
- * but the function may return FALSE if an error occurred.
- *
- * Memory management for that new GdaRow object is left to the implementation, which
- * can use gda_data_select_take_row(). If new row objects are "given" to the GdaDataSelect implemantation
- * using that method, then this method should detect when all the data model rows have been analyzed
- * (when model->nb_stored_rows == model->advertized_nrows) and then possibly discard the API handle
- * as it won't be used anymore to fetch rows.
+ * Each new GdaRow is given to @model using gda_data_select_take_row().
*/
static gboolean
gda_mysql_recordset_fetch_random (GdaDataSelect *model,
@@ -1024,12 +1014,9 @@ gda_mysql_recordset_fetch_random (GdaDataSelect *model,
imodel = GDA_MYSQL_RECORDSET (model);
- if (*row)
- return TRUE;
-
*row = new_row_from_mysql_stmt (imodel, rownum, error);
if (!*row)
- return FALSE;
+ return TRUE;
gda_data_select_take_row (model, *row, rownum);
@@ -1045,14 +1032,9 @@ gda_mysql_recordset_fetch_random (GdaDataSelect *model,
/*
* Create a new filled #GdaRow object for the next cursor row, and put it into *row.
*
- * WARNING: @row will NOT be NULL, but *row may or may not be NULL:
- * - If *row is NULL then a new #GdaRow object has to be created,
- * - and otherwise *row contains a #GdaRow object which has already been created
- * (through a call to this very function), and in this case it should not be modified
- * but the function may return FALSE if an error occurred.
- *
- * Memory management for that new GdaRow object is left to the implementation, which
- * can use gda_data_select_take_row().
+ * Each new #GdaRow created is referenced only by imodel->priv->tmp_row (the #GdaDataSelect implementation
+ * never keeps a reference to it).
+ * Before a new #GdaRow gets created, the previous one, if set, is discarded.
*/
static gboolean
gda_mysql_recordset_fetch_next (GdaDataSelect *model,
@@ -1062,43 +1044,33 @@ gda_mysql_recordset_fetch_next (GdaDataSelect *model,
{
GdaMysqlRecordset *imodel = (GdaMysqlRecordset*) model;
- // TO_IMPLEMENT;
-
- // gda_data_select_iter_next () increments rownum
-
- if (imodel->priv->tmp_row != NULL) {
+ if (imodel->priv->tmp_row)
g_object_unref (G_OBJECT(imodel->priv->tmp_row));
- imodel->priv->tmp_row = NULL;
- }
-
*row = new_row_from_mysql_stmt (imodel, rownum, error);
-
imodel->priv->tmp_row = *row;
- return *row ? TRUE : FALSE;
+ return TRUE;
}
/*
- * Create a new filled #GdaRow object for the previous cursor row, and put it into *row.
- *
- * WARNING: @row will NOT be NULL, but *row may or may not be NULL:
- * - If *row is NULL then a new #GdaRow object has to be created,
- * - and otherwise *row contains a #GdaRow object which has already been created
- * (through a call to this very function), and in this case it should not be modified
- * but the function may return FALSE if an error occurred.
+ * Create a new filled #GdaRow object for the previous cursor row, and put it into *prow.
*
- * Memory management for that new GdaRow object is left to the implementation, which
- * can use gda_data_select_take_row().
+ * Each new #GdaRow created is referenced only by imodel->priv->tmp_row (the #GdaDataSelect implementation
+ * never keeps a reference to it).
+ * Before a new #GdaRow gets created, the previous one, if set, is discarded.
*/
static gboolean
-gda_mysql_recordset_fetch_prev (G_GNUC_UNUSED GdaDataSelect *model,
- G_GNUC_UNUSED GdaRow **row,
- G_GNUC_UNUSED gint rownum,
- G_GNUC_UNUSED GError **error)
+gda_mysql_recordset_fetch_prev (GdaDataSelect *model,
+ GdaRow **row,
+ gint rownum,
+ GError **error)
{
- /*GdaMysqlRecordset *imodel = (GdaMysqlRecordset*) model;*/
+ GdaMysqlRecordset *imodel = (GdaMysqlRecordset*) model;
- TO_IMPLEMENT;
+ if (imodel->priv->tmp_row)
+ g_object_unref (G_OBJECT(imodel->priv->tmp_row));
+ *row = new_row_from_mysql_stmt (imodel, rownum, error);
+ imodel->priv->tmp_row = *row;
return TRUE;
}
@@ -1106,24 +1078,22 @@ gda_mysql_recordset_fetch_prev (G_GNUC_UNUSED GdaDataSelect *model,
/*
* Create a new filled #GdaRow object for the cursor row at position @rownum, and put it into *row.
*
- * WARNING: @row will NOT be NULL, but *row may or may not be NULL:
- * - If *row is NULL then a new #GdaRow object has to be created,
- * - and otherwise *row contains a #GdaRow object which has already been created
- * (through a call to this very function), and in this case it should not be modified
- * but the function may return FALSE if an error occurred.
- *
- * Memory management for that new GdaRow object is left to the implementation, which
- * can use gda_data_select_take_row().
+ * Each new #GdaRow created is referenced only by imodel->priv->tmp_row (the #GdaDataSelect implementation
+ * never keeps a reference to it).
+ * Before a new #GdaRow gets created, the previous one, if set, is discarded.
*/
static gboolean
-gda_mysql_recordset_fetch_at (G_GNUC_UNUSED GdaDataSelect *model,
- G_GNUC_UNUSED GdaRow **row,
- G_GNUC_UNUSED gint rownum,
- G_GNUC_UNUSED GError **error)
+gda_mysql_recordset_fetch_at (GdaDataSelect *model,
+ GdaRow **row,
+ gint rownum,
+ GError **error)
{
- /*GdaMysqlRecordset *imodel = (GdaMysqlRecordset*) model;*/
-
- TO_IMPLEMENT;
+ GdaMysqlRecordset *imodel = (GdaMysqlRecordset*) model;
+
+ if (imodel->priv->tmp_row)
+ g_object_unref (G_OBJECT(imodel->priv->tmp_row));
+ *row = new_row_from_mysql_stmt (imodel, rownum, error);
+ imodel->priv->tmp_row = *row;
return TRUE;
}
diff --git a/providers/oracle/gda-oracle-recordset.c b/providers/oracle/gda-oracle-recordset.c
index 55b3a92..6cc63ac 100644
--- a/providers/oracle/gda-oracle-recordset.c
+++ b/providers/oracle/gda-oracle-recordset.c
@@ -48,8 +48,6 @@ static void gda_oracle_recordset_dispose (GObject *object);
static gint gda_oracle_recordset_fetch_nb_rows (GdaDataSelect *model);
static gboolean gda_oracle_recordset_fetch_random (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error);
static gboolean gda_oracle_recordset_fetch_next (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error);
-static gboolean gda_oracle_recordset_fetch_prev (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error);
-static gboolean gda_oracle_recordset_fetch_at (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error);
static GdaRow *new_row (GdaDataSelect *imodel, GdaConnection *cnc, GdaOraclePStmt *ps);
@@ -88,8 +86,8 @@ gda_oracle_recordset_class_init (GdaOracleRecordsetClass *klass)
pmodel_class->fetch_random = gda_oracle_recordset_fetch_random;
pmodel_class->fetch_next = gda_oracle_recordset_fetch_next;
- pmodel_class->fetch_prev = gda_oracle_recordset_fetch_prev;
- pmodel_class->fetch_at = gda_oracle_recordset_fetch_at;
+ pmodel_class->fetch_prev = NULL;
+ pmodel_class->fetch_at = NULL;
}
static void
@@ -502,7 +500,7 @@ gda_oracle_recordset_new (GdaConnection *cnc, GdaOraclePStmt *ps, GdaSet *exec_p
}
static GdaRow *
-fetch_next_oracle_row (GdaOracleRecordset *model, gboolean do_store, GError **error)
+fetch_next_oracle_row (GdaOracleRecordset *model, G_GNUC_UNUSED gboolean do_store, GError **error)
{
int result;
GdaRow *prow = NULL;
@@ -583,17 +581,8 @@ gda_oracle_recordset_fetch_nb_rows (GdaDataSelect *model)
/*
* Create a new filled #GdaRow object for the row at position @rownum, and put it into *prow.
*
- * WARNING: @prow will NOT be NULL, but *prow may or may not be NULL:
- * - If *prow is NULL then a new #GdaRow object has to be created,
- * - and otherwise *prow contains a #GdaRow object which has already been created
- * (through a call to this very function), and in this case it should not be modified
- * but the function may return FALSE if an error occurred.
- *
- * Memory management for that new GdaRow object is left to the implementation, which
- * can use gda_data_select_take_row(). If new row objects are "given" to the GdaDataSelect implemantation
- * using that method, then this method should detect when all the data model rows have been analyzed
- * (when model->nb_stored_rows == model->advertized_nrows) and then possibly discard the API handle
- * as it won't be used anymore to fetch rows.
+ * Each new #GdaRow created needs to be "given" to the #GdaDataSelect implementation using
+ * gda_data_select_take_row() because backward iterating is not supported.
*/
static gboolean
gda_oracle_recordset_fetch_random (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
@@ -602,120 +591,38 @@ gda_oracle_recordset_fetch_random (GdaDataSelect *model, GdaRow **prow, gint row
OracleConnectionData *cdata;
GdaConnection *cnc;
- if (*prow)
- return TRUE;
-
imodel = GDA_ORACLE_RECORDSET (model);
cnc = gda_data_select_get_connection (model);
cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
if (!cdata)
- return FALSE;
-
- for (; imodel->priv->next_row_num <= rownum; ) {
- *prow = fetch_next_oracle_row (imodel, TRUE, error);
- if (!*prow) {
- /*if (GDA_DATA_SELECT (model)->advertized_nrows >= 0), it's not an error */
- if ((GDA_DATA_SELECT (model)->advertized_nrows >= 0) &&
- (imodel->priv->next_row_num < rownum)) {
- g_set_error (error, 0,
- GDA_DATA_MODEL_ROW_OUT_OF_RANGE_ERROR,
- _("Row %d not found"), rownum);
- }
- return FALSE;
- }
- }
- return TRUE;
-}
+ return TRUE;
-/*
- * Create and "give" filled #GdaRow object for all the rows in the model
- */
-static gboolean
-gda_oracle_recordset_store_all (GdaDataSelect *model, GError **error)
-{
- GdaOracleRecordset *imodel;
- gint i;
-
- imodel = GDA_ORACLE_RECORDSET (model);
-
- /* default implementation */
- for (i = 0; i < model->advertized_nrows; i++) {
- GdaRow *prow;
- if (! gda_oracle_recordset_fetch_random (model, &prow, i, error))
- return FALSE;
+ if (imodel->priv->next_row_num >= rownum) {
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+ GDA_SERVER_PROVIDER_INTERNAL_ERROR,
+ "%s", _("Requested row could not be found"));
+ return TRUE;
}
+ for (*prow = fetch_next_oracle_row (imodel, TRUE, error);
+ *prow && (imodel->priv->next_row_num < rownum);
+ *prow = fetch_next_oracle_row (imodel, TRUE, error));
+
return TRUE;
}
/*
* Create a new filled #GdaRow object for the next cursor row, and put it into *prow.
*
- * WARNING: @prow will NOT be NULL, but *prow may or may not be NULL:
- * - If *prow is NULL then a new #GdaRow object has to be created,
- * - and otherwise *prow contains a #GdaRow object which has already been created
- * (through a call to this very function), and in this case it should not be modified
- * but the function may return FALSE if an error occurred.
- *
- * Memory management for that new GdaRow object is left to the implementation, which
- * can use gda_data_select_take_row().
+ * Each new #GdaRow created needs to be "given" to the #GdaDataSelect implementation using
+ * gda_data_select_take_row() because backward iterating is not supported.
*/
static gboolean
gda_oracle_recordset_fetch_next (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
{
- if (*prow)
- return TRUE;
-
*prow = fetch_next_oracle_row ((GdaOracleRecordset*) model, TRUE, error);
- return *prow ? TRUE : FALSE;
-}
-
-/*
- * Create a new filled #GdaRow object for the previous cursor row, and put it into *prow.
- *
- * WARNING: @prow will NOT be NULL, but *prow may or may not be NULL:
- * - If *prow is NULL then a new #GdaRow object has to be created,
- * - and otherwise *prow contains a #GdaRow object which has already been created
- * (through a call to this very function), and in this case it should not be modified
- * but the function may return FALSE if an error occurred.
- *
- * Memory management for that new GdaRow object is left to the implementation, which
- * can use gda_data_select_take_row().
- */
-static gboolean
-gda_oracle_recordset_fetch_prev (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
-{
- OracleConnectionData *cdata;
- GdaConnection *cnc;
-
- if (*prow)
- return TRUE;
-
- cnc = gda_data_select_get_connection (model);
- cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
- if (!cdata)
- return FALSE;
-
- g_warning ("Internal implementation error: non scrollable cursor requested to go backward!\n");
- return FALSE;
+ return TRUE;
}
-/*
- * Create a new filled #GdaRow object for the cursor row at position @rownum, and put it into *prow.
- *
- * WARNING: @prow will NOT be NULL, but *prow may or may not be NULL:
- * - If *prow is NULL then a new #GdaRow object has to be created,
- * - and otherwise *prow contains a #GdaRow object which has already been created
- * (through a call to this very function), and in this case it should not be modified
- * but the function may return FALSE if an error occurred.
- *
- * Memory management for that new GdaRow object is left to the implementation, which
- * can use gda_data_select_take_row().
- */
-static gboolean
-gda_oracle_recordset_fetch_at (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
-{
- return gda_oracle_recordset_fetch_random (model, prow, rownum, error);
-}
/* create a new GdaRow from the last read row */
static GdaRow *
diff --git a/providers/postgres/gda-postgres-recordset.c b/providers/postgres/gda-postgres-recordset.c
index 9564519..b5bfce0 100644
--- a/providers/postgres/gda-postgres-recordset.c
+++ b/providers/postgres/gda-postgres-recordset.c
@@ -437,13 +437,10 @@ gda_postgres_recordset_fetch_random (GdaDataSelect *model, GdaRow **prow, gint r
{
GdaPostgresRecordset *imodel = (GdaPostgresRecordset *) model;
- if (*prow)
- return TRUE;
-
if (!imodel->priv->pg_res) {
g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_INTERNAL_ERROR,
"%s", _("Internal error"));
- return FALSE;
+ return TRUE;
}
*prow = new_row_from_pg_res (imodel, rownum, error);
@@ -486,23 +483,19 @@ gda_postgres_recordset_store_all (GdaDataSelect *model, GError **error)
* Create a new filled #GdaRow object for the next cursor row, and put it into *prow.
*
* Each new #GdaRow created is referenced only by imodel->priv->tmp_row (the #GdaDataSelect implementation
- * never keeps a reference to it). Before a new #GdaRow gets created, the previous one, if set, is discarded.
+ * never keeps a reference to it).
*/
static gboolean
gda_postgres_recordset_fetch_next (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
{
GdaPostgresRecordset *imodel = (GdaPostgresRecordset*) model;
- if (*prow)
- return TRUE;
-
if (row_is_in_current_pg_res (imodel, rownum)) {
if (imodel->priv->tmp_row)
set_prow_with_pg_res (imodel, imodel->priv->tmp_row, rownum - imodel->priv->pg_res_inf, error);
else
imodel->priv->tmp_row = new_row_from_pg_res (imodel, rownum - imodel->priv->pg_res_inf, error);
*prow = imodel->priv->tmp_row;
- return TRUE;
}
else {
gboolean fetch_error = FALSE;
@@ -512,34 +505,28 @@ gda_postgres_recordset_fetch_next (GdaDataSelect *model, GdaRow **prow, gint row
else
imodel->priv->tmp_row = new_row_from_pg_res (imodel, rownum - imodel->priv->pg_res_inf, error);
*prow = imodel->priv->tmp_row;
- return TRUE;
}
- else
- return !fetch_error;
}
+ return TRUE;
}
/*
* Create a new filled #GdaRow object for the previous cursor row, and put it into *prow.
*
* Each new #GdaRow created is referenced only by imodel->priv->tmp_row (the #GdaDataSelect implementation
- * never keeps a reference to it). Before a new #GdaRow gets created, the previous one, if set, is discarded.
+ * never keeps a reference to it).
*/
static gboolean
gda_postgres_recordset_fetch_prev (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
{
GdaPostgresRecordset *imodel = (GdaPostgresRecordset*) model;
- if (*prow)
- return TRUE;
-
if (row_is_in_current_pg_res (imodel, rownum)) {
if (imodel->priv->tmp_row)
set_prow_with_pg_res (imodel, imodel->priv->tmp_row, rownum - imodel->priv->pg_res_inf, error);
else
imodel->priv->tmp_row = new_row_from_pg_res (imodel, rownum - imodel->priv->pg_res_inf, error);
*prow = imodel->priv->tmp_row;
- return TRUE;
}
else {
gboolean fetch_error = FALSE;
@@ -549,27 +536,22 @@ gda_postgres_recordset_fetch_prev (GdaDataSelect *model, GdaRow **prow, gint row
else
imodel->priv->tmp_row = new_row_from_pg_res (imodel, rownum - imodel->priv->pg_res_inf, error);
*prow = imodel->priv->tmp_row;
- return TRUE;
}
- else
- return !fetch_error;
}
+ return TRUE;
}
/*
* Create a new filled #GdaRow object for the cursor row at position @rownum, and put it into *prow.
*
* Each new #GdaRow created is referenced only by imodel->priv->tmp_row (the #GdaDataSelect implementation
- * never keeps a reference to it). Before a new #GdaRow gets created, the previous one, if set, is discarded.
+ * never keeps a reference to it).
*/
static gboolean
gda_postgres_recordset_fetch_at (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
{
GdaPostgresRecordset *imodel = (GdaPostgresRecordset*) model;
- if (*prow)
- return TRUE;
-
if (imodel->priv->tmp_row) {
g_object_unref (imodel->priv->tmp_row);
imodel->priv->tmp_row = NULL;
@@ -578,18 +560,15 @@ gda_postgres_recordset_fetch_at (GdaDataSelect *model, GdaRow **prow, gint rownu
if (row_is_in_current_pg_res (imodel, rownum)) {
*prow = new_row_from_pg_res (imodel, rownum - imodel->priv->pg_res_inf, error);
imodel->priv->tmp_row = *prow;
- return TRUE;
}
else {
gboolean fetch_error = FALSE;
if (fetch_row_number_chunk (imodel, rownum, &fetch_error, error)) {
*prow = new_row_from_pg_res (imodel, rownum - imodel->priv->pg_res_inf, error);
imodel->priv->tmp_row = *prow;
- return TRUE;
}
- else
- return !fetch_error;
}
+ return TRUE;
}
diff --git a/providers/skel-implementation/capi/gda-capi-recordset.c b/providers/skel-implementation/capi/gda-capi-recordset.c
index 5785419..3868299 100644
--- a/providers/skel-implementation/capi/gda-capi-recordset.c
+++ b/providers/skel-implementation/capi/gda-capi-recordset.c
@@ -244,17 +244,15 @@ gda_capi_recordset_fetch_nb_rows (GdaDataSelect *model)
/*
* Create a new filled #GdaRow object for the row at position @rownum, and put it into *prow.
*
- * WARNING: @prow will NOT be NULL, but *prow may or may not be NULL:
- * - If *prow is NULL then a new #GdaRow object has to be created,
- * - and otherwise *prow contains a #GdaRow object which has already been created
- * (through a call to this very function), and in this case it should not be modified
- * but the function may return FALSE if an error occurred.
- *
- * Memory management for that new GdaRow object is left to the implementation, which
- * can use gda_data_select_take_row(). If new row objects are "given" to the GdaDataSelect implemantation
- * using that method, then this method should detect when all the data model rows have been analyzed
- * (when model->nb_stored_rows == model->advertized_nrows) and then possibly discard the API handle
- * as it won't be used anymore to fetch rows.
+ * NOTES:
+ * - @prow will NOT be NULL, but *prow WILL be NULL.
+ * - a new #GdaRow object has to be created.
+ * - memory management for that new GdaRow object is left to the implementation, which
+ * can use gda_data_select_take_row() to "give" the GdaRow to @model (in this case
+ * this method won't be called anymore for the same @rownum), or may decide to
+ * keep a cache of GdaRow object and "recycle" them.
+ * - implementing this method is MANDATORY if the data model supports random access
+ * - this method is only called when data model is used in random access mode
*/
static gboolean
gda_capi_recordset_fetch_random (GdaDataSelect *model, G_GNUC_UNUSED GdaRow **prow, G_GNUC_UNUSED gint rownum,
@@ -295,14 +293,15 @@ gda_capi_recordset_store_all (GdaDataSelect *model, GError **error)
/*
* Create a new filled #GdaRow object for the next cursor row, and put it into *prow.
*
- * WARNING: @prow will NOT be NULL, but *prow may or may not be NULL:
- * - If *prow is NULL then a new #GdaRow object has to be created,
- * - and otherwise *prow contains a #GdaRow object which has already been created
- * (through a call to this very function), and in this case it should not be modified
- * but the function may return FALSE if an error occurred.
- *
- * Memory management for that new GdaRow object is left to the implementation, which
- * can use gda_data_select_take_row().
+ * NOTES:
+ * - @prow will NOT be NULL, but *prow WILL be NULL.
+ * - a new #GdaRow object has to be created.
+ * - memory management for that new GdaRow object is left to the implementation, which
+ * can use gda_data_select_take_row() to "give" the GdaRow to @model (in this case
+ * this method won't be called anymore for the same @rownum), or may decide to
+ * keep a cache of GdaRow object and "recycle" them.
+ * - implementing this method is MANDATORY
+ * - this method is only called when data model is used in cursor access mode
*/
static gboolean
gda_capi_recordset_fetch_next (G_GNUC_UNUSED GdaDataSelect *model, G_GNUC_UNUSED GdaRow **prow,
@@ -318,14 +317,16 @@ gda_capi_recordset_fetch_next (G_GNUC_UNUSED GdaDataSelect *model, G_GNUC_UNUSED
/*
* Create a new filled #GdaRow object for the previous cursor row, and put it into *prow.
*
- * WARNING: @prow will NOT be NULL, but *prow may or may not be NULL:
- * - If *prow is NULL then a new #GdaRow object has to be created,
- * - and otherwise *prow contains a #GdaRow object which has already been created
- * (through a call to this very function), and in this case it should not be modified
- * but the function may return FALSE if an error occurred.
- *
- * Memory management for that new GdaRow object is left to the implementation, which
- * can use gda_data_select_take_row().
+ * NOTES:
+ * - @prow will NOT be NULL, but *prow WILL be NULL.
+ * - a new #GdaRow object has to be created.
+ * - memory management for that new GdaRow object is left to the implementation, which
+ * can use gda_data_select_take_row() to "give" the GdaRow to @model (in this case
+ * this method won't be called anymore for the same @rownum), or may decide to
+ * keep a cache of GdaRow object and "recycle" them.
+ * - implementing this method is OPTIONAL (in this case the data model is assumed not to
+ * support moving iterators backward)
+ * - this method is only called when data model is used in cursor access mode
*/
static gboolean
gda_capi_recordset_fetch_prev (G_GNUC_UNUSED GdaDataSelect *model, G_GNUC_UNUSED GdaRow **prow,
@@ -341,14 +342,16 @@ gda_capi_recordset_fetch_prev (G_GNUC_UNUSED GdaDataSelect *model, G_GNUC_UNUSED
/*
* Create a new filled #GdaRow object for the cursor row at position @rownum, and put it into *prow.
*
- * WARNING: @prow will NOT be NULL, but *prow may or may not be NULL:
- * - If *prow is NULL then a new #GdaRow object has to be created,
- * - and otherwise *prow contains a #GdaRow object which has already been created
- * (through a call to this very function), and in this case it should not be modified
- * but the function may return FALSE if an error occurred.
- *
- * Memory management for that new GdaRow object is left to the implementation, which
- * can use gda_data_select_take_row().
+ * NOTES:
+ * - @prow will NOT be NULL, but *prow WILL be NULL.
+ * - a new #GdaRow object has to be created.
+ * - memory management for that new GdaRow object is left to the implementation, which
+ * can use gda_data_select_take_row() to "give" the GdaRow to @model (in this case
+ * this method won't be called anymore for the same @rownum), or may decide to
+ * keep a cache of GdaRow object and "recycle" them.
+ * - implementing this method is OPTIONAL and usefull only if there is a method quicker
+ * than iterating one step at a time to the correct position.
+ * - this method is only called when data model is used in cursor access mode
*/
static gboolean
gda_capi_recordset_fetch_at (G_GNUC_UNUSED GdaDataSelect *model, G_GNUC_UNUSED GdaRow **prow,
@@ -360,4 +363,3 @@ gda_capi_recordset_fetch_at (G_GNUC_UNUSED GdaDataSelect *model, G_GNUC_UNUSED G
return TRUE;
}
-
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]