[evolution-data-server/openismus-work-master] EBookBackendSqliteDB: New cursor step() API
- From: Tristan Van Berkom <tvb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/openismus-work-master] EBookBackendSqliteDB: New cursor step() API
- Date: Sat, 19 Oct 2013 18:55:01 +0000 (UTC)
commit 2db462e0c66e61927e3f09b0ad5d2881ab4efbd9
Author: Tristan Van Berkom <tristanvb openismus com>
Date: Fri Oct 18 22:40:13 2013 +0200
EBookBackendSqliteDB: New cursor step() API
.../libedata-book/e-book-backend-sqlitedb.c | 422 ++++++++++++--------
.../libedata-book/e-book-backend-sqlitedb.h | 40 ++-
2 files changed, 283 insertions(+), 179 deletions(-)
---
diff --git a/addressbook/libedata-book/e-book-backend-sqlitedb.c
b/addressbook/libedata-book/e-book-backend-sqlitedb.c
index 25cf2ae..6431568 100644
--- a/addressbook/libedata-book/e-book-backend-sqlitedb.c
+++ b/addressbook/libedata-book/e-book-backend-sqlitedb.c
@@ -5272,18 +5272,19 @@ e_book_backend_sqlitedb_get_locale (EBookBackendSqliteDB *ebsdb,
}
/******************************************************************
- * EbSdbCursor apis *
+ * EbSdbCursor apis *
******************************************************************/
-typedef struct {
- gchar **values; /* The cursor position, results will be returned after this position */
- gchar *last_uid; /* The cursor contact UID position, used as a tie breaker */
-} CursorState;
-
-typedef enum {
- STATE_PREVIOUS,
- STATE_CURRENT,
- N_CURSOR_STATES
-} CursorStateType;
+typedef struct _CursorState CursorState;
+
+struct _CursorState {
+ gchar **values; /* The current cursor position, results will be returned after this
position */
+ gchar *last_uid; /* The current cursor contact UID position, used as a tie breaker */
+ EbSdbCursorOrigin position; /* The position is updated with the cursor state and is used to
distinguish
+ * between the beginning and the ending of the cursor's contact list.
+ * While the cursor is in a non-null state, the position will be
+ * EBSDB_CURSOR_ORIGIN_CURRENT.
+ */
+};
struct _EbSdbCursor {
gchar *folderid; /* The folderid for this cursor */
@@ -5299,9 +5300,110 @@ struct _EbSdbCursor {
EBookCursorSortType *sort_types; /* The sort method to use for each field */
gint n_sort_fields; /* The amound of sort fields */
- CursorState state[N_CURSOR_STATES];
+ CursorState state;
};
+static CursorState *cursor_state_copy (EbSdbCursor *cursor,
+ CursorState *state);
+static void cursor_state_free (EbSdbCursor *cursor,
+ CursorState *state);
+static void cursor_state_clear (EbSdbCursor *cursor,
+ CursorState *state,
+ EbSdbCursorOrigin position);
+static void cursor_state_set_from_contact (EBookBackendSqliteDB *ebsdb,
+ EbSdbCursor *cursor,
+ CursorState *state,
+ EContact *contact);
+static void cursor_state_set_from_vcard (EBookBackendSqliteDB *ebsdb,
+ EbSdbCursor *cursor,
+ CursorState *state,
+ const gchar *vcard);
+
+static CursorState *
+cursor_state_copy (EbSdbCursor *cursor,
+ CursorState *state)
+{
+ CursorState *copy;
+ gint i;
+
+ copy = g_slice_new0 (CursorState);
+ copy->values = g_new0 (gchar *, cursor->n_sort_fields);
+
+ for (i = 0; i < cursor->n_sort_fields; i++)
+ copy->values[i] = g_strdup (state->values[i]);
+
+ copy->last_uid = g_strdup (state->last_uid);
+ copy->position = state->position;
+
+ return copy;
+}
+
+static void
+cursor_state_free (EbSdbCursor *cursor,
+ CursorState *state)
+{
+ if (state) {
+ cursor_state_clear (cursor, state, EBSDB_CURSOR_ORIGIN_BEGIN);
+ g_free (state->values);
+ g_slice_free (CursorState, state);
+ }
+}
+
+static void
+cursor_state_clear (EbSdbCursor *cursor,
+ CursorState *state,
+ EbSdbCursorOrigin position)
+{
+ gint i;
+
+ for (i = 0; i < cursor->n_sort_fields; i++) {
+ g_free (state->values[i]);
+ state->values[i] = NULL;
+ }
+
+ g_free (state->last_uid);
+ state->last_uid = NULL;
+ state->position = position;
+}
+
+static void
+cursor_state_set_from_contact (EBookBackendSqliteDB *ebsdb,
+ EbSdbCursor *cursor,
+ CursorState *state,
+ EContact *contact)
+{
+ gint i;
+
+ cursor_state_clear (cursor, state, EBSDB_CURSOR_ORIGIN_BEGIN);
+
+ for (i = 0; i < cursor->n_sort_fields; i++) {
+ const gchar *string = e_contact_get_const (contact, cursor->sort_fields[i]);
+
+ if (string)
+ state->values[i] =
+ e_collator_generate_key (ebsdb->priv->collator,
+ string, NULL);
+ else
+ state->values[i] = g_strdup ("");
+ }
+
+ state->last_uid = e_contact_get (contact, E_CONTACT_UID);
+ state->position = EBSDB_CURSOR_ORIGIN_CURRENT;
+}
+
+static void
+cursor_state_set_from_vcard (EBookBackendSqliteDB *ebsdb,
+ EbSdbCursor *cursor,
+ CursorState *state,
+ const gchar *vcard)
+{
+ EContact *contact;
+
+ contact = e_contact_new_from_vcard (vcard);
+ cursor_state_set_from_contact (ebsdb, cursor, state, contact);
+ g_object_unref (contact);
+}
+
static void
ebsdb_cursor_setup_query (EBookBackendSqliteDB *ebsdb,
EbSdbCursor *cursor,
@@ -5390,7 +5492,6 @@ ebsdb_cursor_new (EBookBackendSqliteDB *ebsdb,
guint n_sort_fields)
{
EbSdbCursor *cursor = g_slice_new0 (EbSdbCursor);
- gint i;
cursor->folderid = g_strdup (folderid);
@@ -5408,59 +5509,25 @@ ebsdb_cursor_new (EBookBackendSqliteDB *ebsdb,
n_sort_fields,
TRUE);
- cursor->n_sort_fields = n_sort_fields;
- cursor->sort_fields = g_memdup (sort_fields, sizeof (EContactField) * n_sort_fields);
- cursor->sort_types = g_memdup (sort_types, sizeof (EBookCursorSortType) * n_sort_fields);
+ /* Sort parameters */
+ cursor->n_sort_fields = n_sort_fields;
+ cursor->sort_fields = g_memdup (sort_fields, sizeof (EContactField) * n_sort_fields);
+ cursor->sort_types = g_memdup (sort_types, sizeof (EBookCursorSortType) * n_sort_fields);
- for (i = 0; i < N_CURSOR_STATES; i++)
- cursor->state[i].values = g_new0 (gchar *, n_sort_fields);
+ /* Cursor state */
+ cursor->state.values = g_new0 (gchar *, n_sort_fields);
+ cursor->state.last_uid = NULL;
+ cursor->state.position = EBSDB_CURSOR_ORIGIN_BEGIN;
return cursor;
}
static void
-ebsdb_cursor_clear_state (EbSdbCursor *cursor,
- CursorStateType state_type)
-{
- gint i;
-
- for (i = 0; i < cursor->n_sort_fields; i++) {
- g_free (cursor->state[state_type].values[i]);
- cursor->state[state_type].values[i] = NULL;
- }
-
- g_free (cursor->state[state_type].last_uid);
- cursor->state[state_type].last_uid = NULL;
-}
-
-static void
-ebsdb_cursor_swap_state (EbSdbCursor *cursor)
-{
- gchar **tmp_values;
- gchar *tmp_last_uid;
-
- /* Swap the current values and the previous values */
- tmp_values = cursor->state[STATE_CURRENT].values;
- cursor->state[STATE_CURRENT].values = cursor->state[STATE_PREVIOUS].values;
- cursor->state[STATE_PREVIOUS].values = tmp_values;
-
- /* Swap the current uid and the previous uid */
- tmp_last_uid = cursor->state[STATE_CURRENT].last_uid;
- cursor->state[STATE_CURRENT].last_uid = cursor->state[STATE_PREVIOUS].last_uid;
- cursor->state[STATE_PREVIOUS].last_uid = tmp_last_uid;
-}
-
-static void
ebsdb_cursor_free (EbSdbCursor *cursor)
{
- gint i;
-
if (cursor) {
-
- for (i = 0; i < N_CURSOR_STATES; i++) {
- ebsdb_cursor_clear_state (cursor, i);
- g_free (cursor->state[i].values);
- }
+ cursor_state_clear (cursor, &(cursor->state), EBSDB_CURSOR_ORIGIN_BEGIN);
+ g_free (cursor->state.values);
g_clear_object (&(cursor->sexp));
g_free (cursor->folderid);
@@ -5476,43 +5543,6 @@ ebsdb_cursor_free (EbSdbCursor *cursor)
}
}
-static void
-ebsdb_cursor_set_state_from_contact (EBookBackendSqliteDB *ebsdb,
- EbSdbCursor *cursor,
- EContact *contact)
-{
- gint i;
-
- /* Push the current state into the previous state and clear the current state */
- ebsdb_cursor_swap_state (cursor);
- ebsdb_cursor_clear_state (cursor, STATE_CURRENT);
-
- for (i = 0; i < cursor->n_sort_fields; i++) {
- const gchar *string = e_contact_get_const (contact, cursor->sort_fields[i]);
-
- if (string)
- cursor->state[STATE_CURRENT].values[i] =
- e_collator_generate_key (ebsdb->priv->collator,
- string, NULL);
- else
- cursor->state[STATE_CURRENT].values[i] = g_strdup ("");
- }
-
- cursor->state[STATE_CURRENT].last_uid = e_contact_get (contact, E_CONTACT_UID);
-}
-
-static void
-ebsdb_cursor_set_state (EBookBackendSqliteDB *ebsdb,
- EbSdbCursor *cursor,
- const gchar *vcard)
-{
- EContact *contact;
-
- contact = e_contact_new_from_vcard (vcard);
- ebsdb_cursor_set_state_from_contact (ebsdb, cursor, contact);
- g_object_unref (contact);
-}
-
#define GREATER_OR_LESS(cursor, index, reverse) \
(reverse ? \
(((EbSdbCursor *)cursor)->sort_types[index] == E_BOOK_CURSOR_SORT_ASCENDING ? '<' : '>') : \
@@ -5521,6 +5551,7 @@ ebsdb_cursor_set_state (EBookBackendSqliteDB *ebsdb,
static gchar *
ebsdb_cursor_constraints (EBookBackendSqliteDB *ebsdb,
EbSdbCursor *cursor,
+ CursorState *state,
gboolean reverse,
gboolean include_current_uid)
{
@@ -5551,12 +5582,12 @@ ebsdb_cursor_constraints (EBookBackendSqliteDB *ebsdb,
string = g_string_new (NULL);
- for (i = 0; i < (cursor->n_sort_fields + 1); i++) {
+ for (i = 0; i <= cursor->n_sort_fields; i++) {
gchar *stmt;
/* Break once we hit a NULL value */
- if ((i < cursor->n_sort_fields && cursor->state[STATE_CURRENT].values[i] == NULL) ||
- (i == cursor->n_sort_fields && cursor->state[STATE_CURRENT].last_uid == NULL))
+ if ((i < cursor->n_sort_fields && state->values[i] == NULL) ||
+ (i == cursor->n_sort_fields && state->last_uid == NULL))
break;
/* Between each qualifier, add an 'OR' */
@@ -5571,8 +5602,7 @@ ebsdb_cursor_constraints (EBookBackendSqliteDB *ebsdb,
field_name = summary_dbname_from_field (ebsdb, cursor->sort_fields[j]);
stmt = sqlite3_mprintf ("summary.%s_localized = %Q",
- field_name,
- cursor->state[STATE_CURRENT].values[j]);
+ field_name, state->values[j]);
g_string_append (string, stmt);
g_string_append (string, " AND ");
@@ -5593,13 +5623,13 @@ ebsdb_cursor_constraints (EBookBackendSqliteDB *ebsdb,
/* Append the UID tie breaker */
stmt = sqlite3_mprintf ("summary.uid %c %Q",
reverse ? '<' : '>',
- cursor->state[STATE_CURRENT].last_uid);
+ state->last_uid);
g_string_append (string, stmt);
sqlite3_free (stmt);
if (include_current_uid) {
stmt = sqlite3_mprintf (" OR summary.uid = %Q",
- cursor->state[STATE_CURRENT].last_uid);
+ state->last_uid);
g_string_append (string, stmt);
g_string_append_c (string, ')');
sqlite3_free (stmt);
@@ -5615,8 +5645,8 @@ ebsdb_cursor_constraints (EBookBackendSqliteDB *ebsdb,
*/
gboolean include_exact_match =
(reverse == FALSE &&
- ((i + 1 < cursor->n_sort_fields && cursor->state[STATE_CURRENT].values[i +
1] == NULL) ||
- (i + 1 == cursor->n_sort_fields && cursor->state[STATE_CURRENT].last_uid ==
NULL)));
+ ((i + 1 < cursor->n_sort_fields && state->values[i + 1] == NULL) ||
+ (i + 1 == cursor->n_sort_fields && state->last_uid == NULL)));
if (include_exact_match)
g_string_append_c (string, '(');
@@ -5627,7 +5657,7 @@ ebsdb_cursor_constraints (EBookBackendSqliteDB *ebsdb,
stmt = sqlite3_mprintf ("summary.%s_localized %c %Q",
field_name,
GREATER_OR_LESS (cursor, i, reverse),
- cursor->state[STATE_CURRENT].values[i]);
+ state->values[i]);
g_string_append (string, stmt);
sqlite3_free (stmt);
@@ -5635,7 +5665,7 @@ ebsdb_cursor_constraints (EBookBackendSqliteDB *ebsdb,
if (include_exact_match) {
stmt = sqlite3_mprintf (" OR summary.%s_localized = %Q",
- field_name, cursor->state[STATE_CURRENT].values[i]);
+ field_name, state->values[i]);
g_string_append (string, stmt);
g_string_append_c (string, ')');
@@ -5700,7 +5730,7 @@ cursor_count_position_locked (EBookBackendSqliteDB *ebsdb,
}
/* Add the cursor constraints (if any) */
- if (cursor->state[STATE_CURRENT].values[0] != NULL) {
+ if (cursor->state.values[0] != NULL) {
gchar *constraints = NULL;
if (!cursor->query)
@@ -5712,7 +5742,9 @@ cursor_count_position_locked (EBookBackendSqliteDB *ebsdb,
* results leading up to the current cursor value, including
* the cursor value
*/
- constraints = ebsdb_cursor_constraints (ebsdb, cursor, TRUE, TRUE);
+ constraints = ebsdb_cursor_constraints (ebsdb, cursor,
+ &(cursor->state),
+ TRUE, TRUE);
g_string_append_c (query, '(');
g_string_append (query, constraints);
@@ -5860,53 +5892,93 @@ collect_results_for_cursor_cb (gpointer ref,
}
/**
- * e_book_backend_sqlitedb_cursor_move_by:
+ * e_book_backend_sqlitedb_cursor_step:
* @ebsdb: An #EBookBackendSqliteDB
* @cursor: The #EbSdbCursor to use
- * @origin: The #EbSdbCursorOrigin for this move
+ * @flags: The #EbSdbCursorStepFlags for this step
+ * @origin: The #EbSdbCursorOrigin from whence to step
* @count: A positive or negative amount of contacts to try and fetch
* @results: (out) (allow-none) (element-type EbSdbSearchData) (transfer full):
- * A return location to store the results, or %NULL to move the cursor without retrieving any results.
+ * A return location to store the results, or %NULL if %EBSDB_CURSOR_STEP_FETCH is not specified in %flags.
* @error: A return location to store any error that might be reported.
*
- * Moves @cursor through the @ebsdb by @count and fetch a maximum of @count contacts.
+ * Steps @cursor through it's sorted query by a maximum of @count contacts
+ * starting from @origin.
*
- * If @count is negative, then the cursor will move backwards.
- *
- * If @cursor is in an empty state, or @origin is %EBSDB_CURSOR_ORIGIN_RESET,
- * then @count contacts will be fetched from the beginning of the cursor's query
- * results, or from the ending of the query results for a negative value of @count.
+ * If @count is negative, then the cursor will move through the list in reverse.
*
* If @cursor reaches the beginning or end of the query results, then the
* returned list might not contain the amount of desired contacts, or might
- * return no results if the cursor currently points to the last contact.
- * This is not considered an error condition.
+ * return no results if the cursor currently points to the last contact.
+ * Reaching the end of the list is not considered an error condition. Attempts
+ * to step beyond the end of the list after having reached the end of the list
+ * will however trigger an %E_BOOK_SDB_ERROR_END_OF_LIST error.
+ *
+ * If %EBSDB_CURSOR_STEP_FETCH is specified in %flags, a pointer to
+ * a %NULL #GSList pointer should be provided for the @results parameter.
*
- * If @results is specified, it should be a pointer to a %NULL #GSList,
- * the result list will be stored to @results and should be freed with g_slist_free()
+ * The result list will be stored to @results and should be freed with g_slist_free()
* and all elements freed with e_book_backend_sqlitedb_search_data_free().
*
- * Returns: The number of contacts which the cursor has moved by if successfull.
- * Otherwise -1 is returned and @error is set.
+ * Returns: The number of contacts traversed if successfull, otherwise -1 is
+ * returned and @error is set.
*
* Since: 3.12
*/
gint
-e_book_backend_sqlitedb_cursor_move_by (EBookBackendSqliteDB *ebsdb,
- EbSdbCursor *cursor,
- EbSdbCursorOrigin origin,
- gint count,
- GSList **results,
- GError **error)
+e_book_backend_sqlitedb_cursor_step (EBookBackendSqliteDB *ebsdb,
+ EbSdbCursor *cursor,
+ EbSdbCursorStepFlags flags,
+ EbSdbCursorOrigin origin,
+ gint count,
+ GSList **results,
+ GError **error)
{
CursorCollectData data = { NULL, NULL, NULL, FALSE, 0 };
+ CursorState *state;
GString *query;
gboolean success;
+ EbSdbCursorOrigin try_position;
+
+ g_return_val_if_fail (E_IS_BOOK_BACKEND_SQLITEDB (ebsdb), -1);
+ g_return_val_if_fail (cursor != NULL, -1);
+ g_return_val_if_fail ((flags & EBSDB_CURSOR_STEP_FETCH) == 0 ||
+ (results != NULL && *results == NULL), -1);
- g_return_val_if_fail (E_IS_BOOK_BACKEND_SQLITEDB (ebsdb), FALSE);
- g_return_val_if_fail (cursor != NULL, FALSE);
- g_return_val_if_fail (count != 0 || origin == EBSDB_CURSOR_ORIGIN_RESET, FALSE);
- g_return_val_if_fail (results == NULL || *results == NULL, FALSE);
+
+ /* Check if this step should result in an end of list error first */
+ try_position = cursor->state.position;
+ if (origin != EBSDB_CURSOR_ORIGIN_CURRENT)
+ try_position = origin;
+
+ /* Report errors for requests to run off the end of the list */
+ if (try_position == EBSDB_CURSOR_ORIGIN_BEGIN && count < 0) {
+ g_set_error (error, E_BOOK_SDB_ERROR,
+ E_BOOK_SDB_ERROR_END_OF_LIST,
+ _("Tried to step a cursor in reverse, "
+ "but cursor is already at the beginning of the contact list"));
+
+ return -1;
+ } else if (try_position == EBSDB_CURSOR_ORIGIN_END && count > 0) {
+ g_set_error (error, E_BOOK_SDB_ERROR,
+ E_BOOK_SDB_ERROR_END_OF_LIST,
+ _("Tried to step a cursor forwards, "
+ "but cursor is already at the end of the contact list"));
+
+ return -1;
+ }
+
+ /* Nothing to do, silently return */
+ if (count == 0 && try_position == EBSDB_CURSOR_ORIGIN_CURRENT)
+ return 0;
+
+ /* If we're not going to modify the position, just use
+ * a copy of the current cursor state.
+ */
+ if ((flags & EBSDB_CURSOR_STEP_MOVE) != 0)
+ state = &(cursor->state);
+ else
+ state = cursor_state_copy (cursor, &(cursor->state));
/* Every query starts with the STATE_CURRENT position, first
* fix up the cursor state according to 'origin'
@@ -5915,22 +5987,28 @@ e_book_backend_sqlitedb_cursor_move_by (EBookBackendSqliteDB *ebsdb,
case EBSDB_CURSOR_ORIGIN_CURRENT:
/* Do nothing, normal operation */
break;
- case EBSDB_CURSOR_ORIGIN_PREVIOUS:
- /* Swap the previous state into the current state first */
- ebsdb_cursor_swap_state (cursor);
- break;
- case EBSDB_CURSOR_ORIGIN_RESET:
- /* Clear the current state before executing the query */
- ebsdb_cursor_clear_state (cursor, STATE_CURRENT);
- ebsdb_cursor_clear_state (cursor, STATE_PREVIOUS);
+
+ case EBSDB_CURSOR_ORIGIN_BEGIN:
+ case EBSDB_CURSOR_ORIGIN_END:
+
+ /* Prepare the state before executing the query */
+ cursor_state_clear (cursor, state, origin);
break;
}
- /* Count can be 0 only for the sake of resetting the current
- * cursor state without fetching any results
+ /* If count is 0 then there is no need to run any
+ * query, however it can be useful if you just want
+ * to move the cursor to the beginning or ending of
+ * the list.
*/
- if (count == 0)
- return TRUE;
+ if (count == 0) {
+
+ /* Free the state copy if need be */
+ if ((flags & EBSDB_CURSOR_STEP_MOVE) == 0)
+ cursor_state_free (cursor, state);
+
+ return 0;
+ }
query = g_string_new (cursor->select_vcards);
@@ -5944,7 +6022,7 @@ e_book_backend_sqlitedb_cursor_move_by (EBookBackendSqliteDB *ebsdb,
}
/* Add the cursor constraints (if any) */
- if (cursor->state[STATE_CURRENT].values[0] != NULL) {
+ if (state->values[0] != NULL) {
gchar *constraints = NULL;
if (!cursor->query)
@@ -5952,7 +6030,11 @@ e_book_backend_sqlitedb_cursor_move_by (EBookBackendSqliteDB *ebsdb,
else
g_string_append (query, " AND ");
- constraints = ebsdb_cursor_constraints (ebsdb, cursor, count < 0, FALSE);
+ constraints = ebsdb_cursor_constraints (ebsdb,
+ cursor,
+ state,
+ count < 0,
+ FALSE);
g_string_append_c (query, '(');
g_string_append (query, constraints);
@@ -5972,7 +6054,7 @@ e_book_backend_sqlitedb_cursor_move_by (EBookBackendSqliteDB *ebsdb,
g_string_append_printf (query, " LIMIT %d", ABS (count));
/* Specify whether we really want results or not */
- data.collect_results = (results != NULL);
+ data.collect_results = (flags & EBSDB_CURSOR_STEP_FETCH) != 0;
/* Execute the query */
LOCK_MUTEX (&ebsdb->priv->lock);
@@ -5987,14 +6069,17 @@ e_book_backend_sqlitedb_cursor_move_by (EBookBackendSqliteDB *ebsdb,
if (success) {
if (data.n_results < ABS (count)) {
- /* We've reached the end, clear the current state, allow
- * a repeat query from the previously recorded position */
- ebsdb_cursor_swap_state (cursor);
- ebsdb_cursor_clear_state (cursor, STATE_CURRENT);
+
+ /* We've reached the end, clear the current state */
+ if (count < 0)
+ cursor_state_clear (cursor, state, EBSDB_CURSOR_ORIGIN_BEGIN);
+ else
+ cursor_state_clear (cursor, state, EBSDB_CURSOR_ORIGIN_END);
} else if (data.last_vcard) {
+
/* Set the cursor state to the last result */
- ebsdb_cursor_set_state (ebsdb, cursor, data.last_vcard);
+ cursor_state_set_from_vcard (ebsdb, cursor, state, data.last_vcard);
} else
/* Should never get here */
g_warn_if_reached ();
@@ -6013,6 +6098,10 @@ e_book_backend_sqlitedb_cursor_move_by (EBookBackendSqliteDB *ebsdb,
(GDestroyNotify)e_book_backend_sqlitedb_search_data_free);
g_free (data.alloc_vcard);
+ /* Free the copy state if we were working with a copy */
+ if ((flags & EBSDB_CURSOR_STEP_MOVE) == 0)
+ cursor_state_free (cursor, state);
+
if (success)
return data.n_results;
@@ -6030,7 +6119,7 @@ e_book_backend_sqlitedb_cursor_move_by (EBookBackendSqliteDB *ebsdb,
* into the alphabet active in @ebsdb's locale.
*
* After setting the target to an alphabetic index, for example the
- * index for letter 'E', then further calls to e_book_backend_sqlitedb_cursor_move_by()
+ * index for letter 'E', then further calls to e_book_backend_sqlitedb_cursor_step()
* will return results starting with the letter 'E' (or results starting
* with the last result in 'D', if moving in a negative direction).
*
@@ -6057,13 +6146,11 @@ e_book_backend_sqlitedb_cursor_set_target_alphabetic_index (EBookBackendSqliteDB
NULL, NULL, NULL);
g_return_if_fail (index < n_labels);
- ebsdb_cursor_clear_state (cursor, STATE_PREVIOUS);
- ebsdb_cursor_clear_state (cursor, STATE_CURRENT);
+ cursor_state_clear (cursor, &(cursor->state), EBSDB_CURSOR_ORIGIN_CURRENT);
if (cursor->n_sort_fields > 0) {
- cursor->state[STATE_PREVIOUS].values[0] =
- e_collator_generate_key_for_index (ebsdb->priv->collator, index);
- cursor->state[STATE_CURRENT].values[0] =
- e_collator_generate_key_for_index (ebsdb->priv->collator, index);
+ cursor->state.values[0] =
+ e_collator_generate_key_for_index (ebsdb->priv->collator,
+ index);
}
}
@@ -6077,7 +6164,7 @@ e_book_backend_sqlitedb_cursor_set_target_alphabetic_index (EBookBackendSqliteDB
* Modifies the current query expression for @cursor. This will not
* modify @cursor's state, but will change the outcome of any further
* calls to e_book_backend_sqlitedb_cursor_calculate() or
- * e_book_backend_sqlitedb_cursor_move_by().
+ * e_book_backend_sqlitedb_cursor_step().
*
* Returns: %TRUE if the expression was valid and accepted by @ebsdb
*
@@ -6141,7 +6228,7 @@ e_book_backend_sqlitedb_cursor_calculate (EBookBackendSqliteDB *ebsdb,
g_return_val_if_fail (cursor != NULL, FALSE);
/* If we're in a clear cursor state, then the position is 0 */
- if (position && cursor->state[STATE_CURRENT].values[0] == NULL) {
+ if (position && cursor->state.values[0] == NULL) {
*position = 0;
/* Mark the local pointer NULL, no need to calculate this anymore */
@@ -6201,8 +6288,9 @@ e_book_backend_sqlitedb_cursor_compare_contact (EBookBackendSqliteDB *ebsdb,
gint i;
gint comparison = 0;
- g_return_val_if_fail (E_IS_BOOK_BACKEND_SQLITEDB (ebsdb), FALSE);
- g_return_val_if_fail (cursor != NULL, FALSE);
+ g_return_val_if_fail (E_IS_BOOK_BACKEND_SQLITEDB (ebsdb), -1);
+ g_return_val_if_fail (E_IS_CONTACT (contact), -1);
+ g_return_val_if_fail (cursor != NULL, -1);
priv = ebsdb->priv;
@@ -6217,7 +6305,7 @@ e_book_backend_sqlitedb_cursor_compare_contact (EBookBackendSqliteDB *ebsdb,
for (i = 0; i < cursor->n_sort_fields && comparison == 0; i++) {
/* Empty state sorts below any contact value, which means the contact sorts above cursor */
- if (cursor->state[STATE_CURRENT].values[i] == NULL) {
+ if (cursor->state.values[i] == NULL) {
comparison = 1;
} else {
const gchar *field_value;
@@ -6233,7 +6321,7 @@ e_book_backend_sqlitedb_cursor_compare_contact (EBookBackendSqliteDB *ebsdb,
/* Check of contact sorts below, equal to, or above the cursor */
collation_key = e_collator_generate_key (priv->collator, field_value, NULL);
- comparison = strcmp (collation_key, cursor->state[STATE_CURRENT].values[i]);
+ comparison = strcmp (collation_key, cursor->state.values[i]);
g_free (collation_key);
}
}
@@ -6245,12 +6333,12 @@ e_book_backend_sqlitedb_cursor_compare_contact (EBookBackendSqliteDB *ebsdb,
uid = (const gchar *)e_contact_get_const (contact, E_CONTACT_UID);
- if (cursor->state[STATE_CURRENT].last_uid == NULL)
+ if (cursor->state.last_uid == NULL)
comparison = 1;
else if (uid == NULL)
comparison = -1;
else
- comparison = strcmp (uid, cursor->state[STATE_CURRENT].last_uid);
+ comparison = strcmp (uid, cursor->state.last_uid);
}
return comparison;
diff --git a/addressbook/libedata-book/e-book-backend-sqlitedb.h
b/addressbook/libedata-book/e-book-backend-sqlitedb.h
index 2ec563c..dd08bc7 100644
--- a/addressbook/libedata-book/e-book-backend-sqlitedb.h
+++ b/addressbook/libedata-book/e-book-backend-sqlitedb.h
@@ -74,6 +74,7 @@ typedef struct _EBookBackendSqliteDBPrivate EBookBackendSqliteDBPrivate;
* @E_BOOK_SDB_ERROR_NOT_SUPPORTED: A query was not supported
* @E_BOOK_SDB_ERROR_INVALID_QUERY: A query was invalid. This can happen if the sexp could not be parsed
* or if a phone number query contained non-phonenumber input.
+ * @E_BOOK_SDB_ERROR_END_OF_LIST: An attempt was made to fetch results past the end of a contact list
*
* Defines the types of possible errors reported by the #EBookBackendSqliteDB
*/
@@ -82,7 +83,8 @@ typedef enum {
E_BOOK_SDB_ERROR_CONTACT_NOT_FOUND,
E_BOOK_SDB_ERROR_OTHER,
E_BOOK_SDB_ERROR_NOT_SUPPORTED,
- E_BOOK_SDB_ERROR_INVALID_QUERY
+ E_BOOK_SDB_ERROR_INVALID_QUERY,
+ E_BOOK_SDB_ERROR_END_OF_LIST
} EBookSDBError;
/**
@@ -127,24 +129,37 @@ typedef struct _EbSdbCursor EbSdbCursor;
/**
* EbSdbCursorOrigin:
* @EBSDB_CURSOR_ORIGIN_CURRENT: The current cursor position
- * @EBSDB_CURSOR_ORIGIN_PREVIOUS: The previously recorded cursor position, this can be used to repeat the
previous query
- * @EBSDB_CURSOR_ORIGIN_RESET: The beginning of the cursor results (or end of the results, if navigating
in reverse).
+ * @EBSDB_CURSOR_ORIGIN_BEGIN: The beginning of the cursor results.
+ * @EBSDB_CURSOR_ORIGIN_END: The ending of the cursor results.
*
- * Defines the behaviour of e_book_backend_sqlitedb_cursor_move_by().
+ * Specifies the start position to in the list of traversed contacts
+ * in calls to e_book_backend_sqlitedb_cursor_step().
*
- * The cursor always saves the previous cursor position as well as
- * the new cursor position after performing a move. This allows
- * cursor queries to be repeated in the case where content may have
- * changed but the same content window should be refreshed in a UI.
+ * When an #EbSdbCuror is created, the current position implied by %EBSDB_CURSOR_ORIGIN_CURRENT
+ * is the same as %EBSDB_CURSOR_ORIGIN_BEGIN.
*
* Since: 3.12
*/
typedef enum {
- EBSDB_CURSOR_ORIGIN_CURRENT,
- EBSDB_CURSOR_ORIGIN_PREVIOUS,
- EBSDB_CURSOR_ORIGIN_RESET
+ EBSDB_CURSOR_ORIGIN_CURRENT = 0,
+ EBSDB_CURSOR_ORIGIN_BEGIN,
+ EBSDB_CURSOR_ORIGIN_END
} EbSdbCursorOrigin;
+/**
+ * EbSdbCursorStepFlags:
+ * @EBSDB_CURSOR_STEP_MOVE: The cursor position should be modified while stepping
+ * @EBSDB_CURSOR_STEP_FETCH: Traversed contacts should be listed and returned while stepping.
+ *
+ * Defines the behaviour of e_book_backend_sqlitedb_cursor_step().
+ *
+ * Since: 3.12
+ */
+typedef enum {
+ EBSDB_CURSOR_STEP_MOVE = (1 << 0),
+ EBSDB_CURSOR_STEP_FETCH = (1 << 1)
+} EbSdbCursorStepFlags;
+
GType e_book_backend_sqlitedb_get_type
(void) G_GNUC_CONST;
GQuark e_book_backend_sqlitedb_error_quark
@@ -334,9 +349,10 @@ EbSdbCursor *e_book_backend_sqlitedb_cursor_new
void e_book_backend_sqlitedb_cursor_free
(EBookBackendSqliteDB *ebsdb,
EbSdbCursor *cursor);
-gint e_book_backend_sqlitedb_cursor_move_by
+gint e_book_backend_sqlitedb_cursor_step
(EBookBackendSqliteDB *ebsdb,
EbSdbCursor *cursor,
+ EbSdbCursorStepFlags flags,
EbSdbCursorOrigin origin,
gint count,
GSList **results,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]