[patches] [PATCH v3 1/3] sql: unify SQL cursor interface
Nikita Pettik
korablev at tarantool.org
Tue Feb 13 15:41:27 MSK 2018
This patch merge functions for cursor manipulating of ordinary and
ephemeral spaces in order to avoid code duplication and excess checks of
cursor types.
Signed-off-by: Nikita Pettik <korablev at tarantool.org>
---
src/box/sql.c | 214 +++++++++++----------------------------------
src/box/sql/cursor.c | 13 +--
src/box/sql/tarantoolInt.h | 4 -
src/box/sql/vdbe.c | 16 +---
4 files changed, 53 insertions(+), 194 deletions(-)
diff --git a/src/box/sql.c b/src/box/sql.c
index ef73d543a..682f15753 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -175,13 +175,6 @@ cursor_seek(BtCursor *pCur, int *pRes, enum iterator_type type,
static int
cursor_advance(BtCursor *pCur, int *pRes);
-static int
-cursor_ephemeral_seek(BtCursor *pCur, int *pRes, enum iterator_type type,
- const char *key, const char *key_end);
-
-static int
-cursor_ephemeral_advance(BtCursor *pCur, int *pRes);
-
const char *tarantoolErrorMessage()
{
return box_error_message(box_error_last());
@@ -197,9 +190,11 @@ int tarantoolSqlite3CloseCursor(BtCursor *pCur)
pCur->pTaCursor = NULL;
if (c) {
- if (c->iter) box_iterator_free(c->iter);
- if (c->tuple_last) box_tuple_unref(c->tuple_last);
- free(c);
+ if (c->iter)
+ box_iterator_free(c->iter);
+ if (c->tuple_last)
+ box_tuple_unref(c->tuple_last);
+ free(c);
}
return SQLITE_OK;
}
@@ -240,28 +235,16 @@ tarantoolSqlite3TupleColumnFast(BtCursor *pCur, u32 fieldno, u32 *field_size)
}
/*
- * Set cursor to the first tuple in ephemeral space.
- * It is a simple wrapper around cursor_ephemeral_seek.
+ * Set cursor to the first tuple in given space.
+ * It is a simple wrapper around cursor_seek().
*/
-int tarantoolSqlite3EphemeralFirst(BtCursor *pCur, int *pRes)
-{
- return cursor_ephemeral_seek(pCur, pRes, ITER_GE,
- nil_key, nil_key + sizeof(nil_key));
-}
-
int tarantoolSqlite3First(BtCursor *pCur, int *pRes)
{
return cursor_seek(pCur, pRes, ITER_GE,
nil_key, nil_key + sizeof(nil_key));
}
-/* Set cursor to the first tuple in ephemeral space. */
-int tarantoolSqlite3EphemeralLast(BtCursor *pCur, int *pRes)
-{
- return cursor_ephemeral_seek(pCur, pRes, ITER_LE,
- nil_key, nil_key + sizeof(nil_key));
-}
-
+/* Set cursor to the last tuple in given space. */
int tarantoolSqlite3Last(BtCursor *pCur, int *pRes)
{
return cursor_seek(pCur, pRes, ITER_LE,
@@ -269,13 +252,14 @@ int tarantoolSqlite3Last(BtCursor *pCur, int *pRes)
}
/*
- * Set cursor to the next entry in ephemeral space.
+ * Set cursor to the next entry in given space.
* If state of cursor is invalid (e.g. it is still under construction,
* or already destroyed), it immediately returns.
+ * Second argument is output parameter: success movement of cursor
+ * results in 0 value of pRes, otherwise it is set to 1.
*/
-int tarantoolSqlite3EphemeralNext(BtCursor *pCur, int *pRes)
+int tarantoolSqlite3Next(BtCursor *pCur, int *pRes)
{
- assert(pCur->curFlags & BTCF_TEphemCursor);
if (pCur->eState == CURSOR_INVALID) {
*pRes = 1;
return SQLITE_OK;
@@ -283,20 +267,6 @@ int tarantoolSqlite3EphemeralNext(BtCursor *pCur, int *pRes)
assert(pCur->pTaCursor);
assert(iterator_direction(
((struct ta_cursor *)pCur->pTaCursor)->type) > 0);
- return cursor_ephemeral_advance(pCur, pRes);
-}
-
-int tarantoolSqlite3Next(BtCursor *pCur, int *pRes)
-{
- assert(pCur->curFlags & BTCF_TaCursor);
- if (pCur->eState == CURSOR_INVALID) {
- *pRes = 1;
- return SQLITE_OK;
- }
- assert(pCur->pTaCursor);
- assert(iterator_direction(
- ((struct ta_cursor *)pCur->pTaCursor)->type
- ) > 0);
return cursor_advance(pCur, pRes);
}
@@ -305,9 +275,8 @@ int tarantoolSqlite3Next(BtCursor *pCur, int *pRes)
* If state of cursor is invalid (e.g. it is still under construction,
* or already destroyed), it immediately returns.
*/
-int tarantoolSqlite3EphemeralPrevious(BtCursor *pCur, int *pRes)
+int tarantoolSqlite3Previous(BtCursor *pCur, int *pRes)
{
- assert(pCur->curFlags & BTCF_TEphemCursor);
if (pCur->eState == CURSOR_INVALID) {
*pRes = 1;
return SQLITE_OK;
@@ -315,20 +284,6 @@ int tarantoolSqlite3EphemeralPrevious(BtCursor *pCur, int *pRes)
assert(pCur->pTaCursor);
assert(iterator_direction(
((struct ta_cursor *)pCur->pTaCursor)->type) < 0);
- return cursor_ephemeral_advance(pCur, pRes);
-}
-
-int tarantoolSqlite3Previous(BtCursor *pCur, int *pRes)
-{
- assert(pCur->curFlags & BTCF_TaCursor);
- if (pCur->eState == CURSOR_INVALID) {
- *pRes = 1;
- return SQLITE_OK;
- }
- assert(pCur->pTaCursor);
- assert(iterator_direction(
- ((struct ta_cursor *)pCur->pTaCursor)->type
- ) < 0);
return cursor_advance(pCur, pRes);
}
@@ -383,9 +338,7 @@ int tarantoolSqlite3MovetoUnpacked(BtCursor *pCur, UnpackedRecord *pIdxKey,
res_success = 0;
break;
}
- rc = (pCur->curFlags & BTCF_TaCursor) ?
- cursor_seek(pCur, pRes, iter_type, k, ke) :
- cursor_ephemeral_seek(pCur, pRes, iter_type, k, ke);
+ rc = cursor_seek(pCur, pRes, iter_type, k, ke);
if (*pRes == 0) {
*pRes = res_success;
/*
@@ -495,7 +448,7 @@ int tarantoolSqlite3EphemeralCreate(BtCursor *pCur, uint32_t field_count,
pCur->pTaCursor = c;
int unused;
- return tarantoolSqlite3EphemeralFirst(pCur, &unused);
+ return tarantoolSqlite3First(pCur, &unused);
}
/*
@@ -1012,7 +965,6 @@ rename_fail:
return SQLITE_ERROR;
}
-
/*
* Performs exactly as extract_key + sqlite3VdbeCompareMsgpack,
* only faster.
@@ -1200,32 +1152,28 @@ cursor_create(struct ta_cursor *c, size_t key_size)
* Create new Tarantool iterator and set it to the first entry found by
* given key. If cursor already contains iterator, it will be freed.
*
- * @param pCur Cursor which points to ephemeral space.
+ * @param pCur Cursor which points to space.
* @param pRes Flag which is == 0 if reached end of space, == 1 otherwise.
- * @param type Type of iterator.
+ * @param type Type of Tarantool iterator.
* @param key Start of buffer containing key.
- * @param key_end End of key.
+ * @param key_end End of buffer containing key.
*
* @retval SQLITE_OK on success, SQLITE_TARANTOOL_ERROR otherwise.
*/
static int
-cursor_ephemeral_seek(BtCursor *pCur, int *pRes, enum iterator_type type,
- const char *key, const char *key_end)
+cursor_seek(BtCursor *pCur, int *pRes, enum iterator_type type,
+ const char *key, const char *key_end)
{
- assert(pCur->curFlags & BTCF_TEphemCursor);
- assert(key != NULL && key_end != NULL);
- assert(type >= 0 && type < iterator_type_MAX);
- mp_tuple_assert(key, key_end);
-
struct ta_cursor *c = pCur->pTaCursor;
- assert(c->ephem_space);
-
size_t key_size = 0;
+
+ /* Close existing iterator, if any */
if (c && c->iter) {
box_iterator_free(c->iter);
c->iter = NULL;
}
+ /* Allocate or grow cursor if needed. */
if (type == ITER_EQ || type == ITER_REQ) {
key_size = (size_t)(key_end - key);
}
@@ -1236,16 +1184,33 @@ cursor_ephemeral_seek(BtCursor *pCur, int *pRes, enum iterator_type type,
}
pCur->pTaCursor = c;
+ /* Copy key if necessary. */
+ if (key_size != 0) {
+ memcpy(c->key, key, key_end - key);
+ key_end = c->key + (key_end - key);
+ key = c->key;
+ }
+
+ struct space *space;
+ struct index *index;
+ uint32_t space_id = SQLITE_PAGENO_TO_SPACEID(pCur->pgnoRoot);
+ if (space_id != 0) {
+ space = space_by_id(space_id);
+ uint32_t index_id = SQLITE_PAGENO_TO_INDEXID(pCur->pgnoRoot);
+ index = index_find(space, index_id);
+ } else {
+ space = c->ephem_space;
+ index = *space->index;
+ }
+
uint32_t part_count = mp_decode_array(&key);
- struct space *ephem_space = c->ephem_space;
- struct index *index = *ephem_space->index;
if (key_validate(index->def, type, key, part_count)) {
diag_log();
return SQLITE_TARANTOOL_ERROR;
}
- struct iterator *it = index_create_iterator(*ephem_space->index, type,
- key, part_count);
+ struct iterator *it = index_create_iterator(index, type, key,
+ part_count);
if (it == NULL) {
pCur->eState = CURSOR_INVALID;
return SQLITE_TARANTOOL_ERROR;
@@ -1253,70 +1218,22 @@ cursor_ephemeral_seek(BtCursor *pCur, int *pRes, enum iterator_type type,
c->iter = it;
c->type = type;
pCur->eState = CURSOR_VALID;
-
- return cursor_ephemeral_advance(pCur, pRes);
-}
-
-/* Cursor positioning. */
-static int
-cursor_seek(BtCursor *pCur, int *pRes, enum iterator_type type,
- const char *k, const char *ke)
-{
- assert(pCur->curFlags & BTCF_TaCursor);
-
- struct ta_cursor *c = pCur->pTaCursor;
- uint32_t space_id = SQLITE_PAGENO_TO_SPACEID(pCur->pgnoRoot);
- uint32_t index_id = SQLITE_PAGENO_TO_INDEXID(pCur->pgnoRoot);
- size_t key_size = 0;
-
- /* Close existing iterator, if any */
- if (c && c->iter) {
- box_iterator_free(c->iter);
- c->iter = NULL;
- }
-
- /* Allocate or grow cursor if needed. */
- if (type == ITER_EQ || type == ITER_REQ) {
- key_size = (size_t)(ke - k);
- }
- c = cursor_create(c, key_size);
- if (!c) {
- *pRes = 1;
- return SQLITE_NOMEM;
- }
- pCur->pTaCursor = c;
-
- /* Copy key if necessary. */
- if (key_size != 0) {
- memcpy(c->key, k, ke-k);
- ke = c->key + (ke-k);
- k = c->key;
- }
-
- c->iter = box_index_iterator(space_id, index_id, type, k, ke);
- if (c->iter == NULL) {
- pCur->eState = CURSOR_INVALID;
- return SQLITE_TARANTOOL_ERROR;
- }
- c->type = type;
- pCur->eState = CURSOR_VALID;
return cursor_advance(pCur, pRes);
}
/*
- * Move cursor to the next entry in ephemeral space.
- * New tuple is refed and saved in cursord.
+ * Move cursor to the next entry in space.
+ * New tuple is refed and saved in cursor.
* Tuple from previous call is unrefed.
*
- * @param pCur Cursor which will point to the new ephemeral space.
- * @param pRes Flag which is == 0 if reached end of space, == 1 otherwise.
+ * @param pCur Cursor which contains space and tuple.
+ * @param[out] pRes Flag which is 0 if reached end of space, 1 otherwise.
*
* @retval SQLITE_OK on success, SQLITE_TARANTOOL_ERROR otherwise.
*/
static int
-cursor_ephemeral_advance(BtCursor *pCur, int *pRes)
+cursor_advance(BtCursor *pCur, int *pRes)
{
- assert(pCur->curFlags & BTCF_TEphemCursor);
struct ta_cursor *c = pCur->pTaCursor;
assert(c);
assert(c->iter);
@@ -1338,34 +1255,6 @@ cursor_ephemeral_advance(BtCursor *pCur, int *pRes)
return SQLITE_OK;
}
-static int
-cursor_advance(BtCursor *pCur, int *pRes)
-{
- assert(pCur->curFlags & BTCF_TaCursor);
-
- struct ta_cursor *c;
- struct tuple *tuple;
- int rc;
-
- c = pCur->pTaCursor;
- assert(c);
- assert(c->iter);
-
- rc = box_iterator_next(c->iter, &tuple);
- if (rc)
- return SQLITE_TARANTOOL_ERROR;
- if (c->tuple_last) box_tuple_unref(c->tuple_last);
- if (tuple) {
- box_tuple_ref(tuple);
- *pRes = 0;
- } else {
- pCur->eState = CURSOR_INVALID;
- *pRes = 1;
- }
- c->tuple_last = tuple;
- return SQLITE_OK;
-}
-
/*********************************************************************
* Schema support.
*/
@@ -1399,11 +1288,6 @@ sql_schema_put(InitData *init,
sqlite3InitCallback(init, 3, argv, NULL);
}
-struct space;
-
-struct space *
-space_by_id(uint32_t id);
-
static int
space_foreach_put_cb(struct space *space, void *udata)
{
diff --git a/src/box/sql/cursor.c b/src/box/sql/cursor.c
index 34066ffe4..8e6d5c82b 100644
--- a/src/box/sql/cursor.c
+++ b/src/box/sql/cursor.c
@@ -169,9 +169,6 @@ sqlite3CursorMovetoUnpacked(BtCursor * pCur, /* The cursor to be moved */
assert((pCur->curFlags & BTCF_TaCursor) ||
(pCur->curFlags & BTCF_TEphemCursor));
- if (pCur->curFlags & BTCF_TaCursor) {
- return tarantoolSqlite3MovetoUnpacked(pCur, pIdxKey, pRes);
- }
return tarantoolSqlite3MovetoUnpacked(pCur, pIdxKey, pRes);
}
@@ -184,10 +181,7 @@ sqlite3CursorNext(BtCursor *pCur, int *pRes)
(pCur->curFlags & BTCF_TEphemCursor));
*pRes = 0;
- if (pCur->curFlags & BTCF_TaCursor) {
- return tarantoolSqlite3Next(pCur, pRes);
- }
- return tarantoolSqlite3EphemeralNext(pCur, pRes);
+ return tarantoolSqlite3Next(pCur, pRes);
}
int
@@ -199,10 +193,7 @@ sqlite3CursorPrevious(BtCursor *pCur, int *pRes)
(pCur->curFlags & BTCF_TEphemCursor));
*pRes = 0;
- if (pCur->curFlags & BTCF_TaCursor) {
- return tarantoolSqlite3Previous(pCur, pRes);
- }
- return tarantoolSqlite3EphemeralPrevious(pCur, pRes);
+ return tarantoolSqlite3Previous(pCur, pRes);
}
/*
diff --git a/src/box/sql/tarantoolInt.h b/src/box/sql/tarantoolInt.h
index 134388d61..489d0ec86 100644
--- a/src/box/sql/tarantoolInt.h
+++ b/src/box/sql/tarantoolInt.h
@@ -96,11 +96,7 @@ int tarantoolSqlite3EphemeralCreate(BtCursor * pCur, uint32_t filed_count,
struct coll *aColl);
int tarantoolSqlite3EphemeralInsert(BtCursor * pCur, const CursorPayload * pX);
int tarantoolSqlite3EphemeralDelete(BtCursor * pCur);
-int tarantoolSqlite3EphemeralFirst(BtCursor * pCur, int * pRes);
-int tarantoolSqlite3EphemeralNext(BtCursor * pCur, int * pRes);
-int tarantoolSqlite3EphemeralLast(BtCursor * pCur, int * pRes);
int tarantoolSqlite3EphemeralCount(BtCursor * pCur, i64 * pnEntry);
-int tarantoolSqlite3EphemeralPrevious(BtCursor * pCur, int * pRes);
int tarantoolSqlite3EphemeralDrop(BtCursor * pCur);
int tarantoolSqlite3EphemeralClearTable(BtCursor * pCur);
int tarantoolSqlite3EphemeralGetMaxId(BtCursor * pCur, uint32_t fieldno,
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index c3d726672..ddd849903 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -4195,13 +4195,7 @@ case OP_Last: { /* jump */
pC->seekOp = OP_Last;
#endif
if (pOp->p3==0 || !sqlite3CursorIsValidNN(pCrsr)) {
- if (pCrsr->curFlags & BTCF_TaCursor) {
- rc = tarantoolSqlite3Last(pCrsr, &res);
- } else if (pCrsr->curFlags & BTCF_TEphemCursor) {
- rc = tarantoolSqlite3EphemeralLast(pCrsr, &res);
- } else {
- unreachable();
- }
+ rc = tarantoolSqlite3Last(pCrsr, &res);
pC->nullRow = (u8)res;
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
@@ -4279,13 +4273,7 @@ case OP_Rewind: { /* jump */
assert(pC->eCurType==CURTYPE_TARANTOOL);
pCrsr = pC->uc.pCursor;
assert(pCrsr);
- if (pCrsr->curFlags & BTCF_TaCursor) {
- rc = tarantoolSqlite3First(pCrsr, &res);
- } else if (pCrsr->curFlags & BTCF_TEphemCursor) {
- rc = tarantoolSqlite3EphemeralFirst(pCrsr, &res);
- } else {
- unreachable();
- }
+ rc = tarantoolSqlite3First(pCrsr, &res);
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
}
--
2.15.1
More information about the Tarantool-patches
mailing list