[patches] [sql 5/9] sql: completed API for ephemeral tables
Nikita Pettik
korablev at tarantool.org
Tue Jan 23 23:19:16 MSK 2018
- Completed implementing tarantoolSqlite3Ephemeral* API.
Added functions: Last, Next, Previous, Delete, Unpack.
- Added support of ephemeral tables for IN expression.
- Added support of ephemeral tables for sub-select queries.
- Fixed tests, which rely on the name of ephemeral creation opcode.
Part of #2680
Signed-off-by: Nikita Pettik <korablev at tarantool.org>
---
src/box/sql.c | 54 ++++++++++++++++++++++++++++++++++++++++++++--
src/box/sql/btree.c | 16 ++++++++++++--
src/box/sql/expr.c | 2 +-
src/box/sql/select.c | 2 +-
src/box/sql/tarantoolInt.h | 3 +++
src/box/sql/update.c | 2 +-
src/box/sql/vdbe.c | 4 ++--
src/box/sql/vdbeaux.c | 3 ++-
src/box/sql/wherecode.c | 2 +-
test/sql-tap/in3.test.lua | 4 ++--
test/sql-tap/in4.test.lua | 8 +++----
11 files changed, 83 insertions(+), 17 deletions(-)
diff --git a/src/box/sql.c b/src/box/sql.c
index 01eb88419..10ea655c9 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -223,7 +223,9 @@ const void *tarantoolSqlite3PayloadFetch(BtCursor *pCur, u32 *pAmt)
const void *
tarantoolSqlite3TupleColumnFast(BtCursor *pCur, u32 fieldno, u32 *field_size)
{
- assert((pCur->curFlags & BTCF_TaCursor) != 0);
+ assert(pCur->curFlags & BTCF_TaCursor ||
+ pCur->curFlags & BTCF_TEphemCursor);
+
struct ta_cursor *c = pCur->pTaCursor;
assert(c != NULL);
assert(c->tuple_last != NULL);
@@ -250,6 +252,12 @@ int tarantoolSqlite3First(BtCursor *pCur, int *pRes)
nil_key, nil_key + sizeof(nil_key));
}
+int tarantoolSqlite3EphemeralLast(BtCursor *pCur, int *pRes)
+{
+ return cursor_ephemeral_seek(pCur, pRes, ITER_LE,
+ nil_key, nil_key + sizeof(nil_key));
+}
+
int tarantoolSqlite3Last(BtCursor *pCur, int *pRes)
{
return cursor_seek(pCur, pRes, ITER_LE,
@@ -283,6 +291,19 @@ int tarantoolSqlite3Next(BtCursor *pCur, int *pRes)
return cursor_advance(pCur, pRes);
}
+int tarantoolSqlite3EphemeralPrevious(BtCursor *pCur, int *pRes)
+{
+ assert(pCur->curFlags & BTCF_TEphemCursor);
+ 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_ephemeral_advance(pCur, pRes);
+}
+
int tarantoolSqlite3Previous(BtCursor *pCur, int *pRes)
{
assert(pCur->curFlags & BTCF_TaCursor);
@@ -348,7 +369,9 @@ int tarantoolSqlite3MovetoUnpacked(BtCursor *pCur, UnpackedRecord *pIdxKey,
res_success = 0;
break;
}
- rc = cursor_seek(pCur, pRes, iter_type, k, ke);
+ rc = (pCur->curFlags & BTCF_TaCursor) ?
+ cursor_seek(pCur, pRes, iter_type, k, ke) :
+ cursor_ephemeral_seek(pCur, pRes, iter_type, k, ke);
if (*pRes == 0) {
*pRes = res_success;
/*
@@ -471,6 +494,33 @@ int tarantoolSqlite3Insert(BtCursor *pCur, const BtreePayload *pX)
return SQLITE_OK;
}
+int tarantoolSqlite3EphemeralDelete(BtCursor *pCur)
+{
+ assert(pCur->curFlags & BTCF_TEphemCursor);
+ assert(pCur->pTaCursor);
+ struct ta_cursor *c = pCur->pTaCursor;
+ struct space *ephem_space = c->ephem_space;
+ assert(ephem_space);
+
+ char *key;
+ uint32_t key_size;
+ assert(c->iter);
+ assert(c->tuple_last);
+
+ key = tuple_extract_key(c->tuple_last,
+ box_iterator_key_def(c->iter),
+ &key_size);
+ if (key == NULL)
+ return SQLITE_TARANTOOL_ERROR;
+
+ int rc = space_ephemeral_delete(ephem_space, key);
+ if (rc != 0) {
+ diag_log();
+ return SQLITE_TARANTOOL_ERROR;
+ }
+ return SQLITE_OK;
+}
+
int tarantoolSqlite3Delete(BtCursor *pCur, u8 flags)
{
(void)flags;
diff --git a/src/box/sql/btree.c b/src/box/sql/btree.c
index 1a2d1f976..9ed5d3d41 100644
--- a/src/box/sql/btree.c
+++ b/src/box/sql/btree.c
@@ -3592,7 +3592,8 @@ fetchPayload(BtCursor * pCur, /* Cursor pointing to entry to read from */
const void *
sqlite3BtreePayloadFetch(BtCursor * pCur, u32 * pAmt)
{
- if (pCur->curFlags & BTCF_TaCursor) {
+ if (pCur->curFlags & BTCF_TaCursor ||
+ pCur->curFlags & BTCF_TEphemCursor) {
return tarantoolSqlite3PayloadFetch(pCur, pAmt);
}
return fetchPayload(pCur, pAmt);
@@ -3884,6 +3885,10 @@ sqlite3BtreeLast(BtCursor * pCur, int *pRes)
return tarantoolSqlite3Last(pCur, pRes);
}
+ if (pCur->curFlags & BTCF_TEphemCursor) {
+ return tarantoolSqlite3EphemeralLast(pCur, pRes);
+ }
+
/* If the cursor already points to the last entry, this is a no-op. */
if (CURSOR_VALID == pCur->eState && (pCur->curFlags & BTCF_AtLast) != 0) {
#ifdef SQLITE_DEBUG
@@ -3970,7 +3975,8 @@ sqlite3BtreeMovetoUnpacked(BtCursor * pCur, /* The cursor to be moved */
assert(pCur->eState != CURSOR_VALID
|| (pIdxKey == 0) == (pCur->curIntKey != 0));
- if (pCur->curFlags & BTCF_TaCursor) {
+ if (pCur->curFlags & BTCF_TaCursor ||
+ pCur->curFlags & BTCF_TEphemCursor) {
assert(pIdxKey);
/*
* Note: pIdxKey/intKey are mutually-exclusive and all Tarantool
@@ -4464,6 +4470,9 @@ sqlite3BtreePrevious(BtCursor * pCur, int *pRes)
if (pCur->curFlags & BTCF_TaCursor) {
return tarantoolSqlite3Previous(pCur, pRes);
}
+ if (pCur->curFlags & BTCF_TEphemCursor) {
+ return tarantoolSqlite3EphemeralPrevious(pCur, pRes);
+ }
if (pCur->eState != CURSOR_VALID
|| pCur->aiIdx[pCur->iPage] == 0
|| pCur->apPage[pCur->iPage]->leaf == 0) {
@@ -7023,6 +7032,9 @@ sqlite3BtreeDelete(BtCursor * pCur, u8 flags)
return tarantoolSqlite3Delete(pCur, flags);
}
+ if (pCur->curFlags & BTCF_TEphemCursor) {
+ return tarantoolSqlite3EphemeralDelete(pCur);
+ }
assert(pCur->aiIdx[pCur->iPage] < pCur->apPage[pCur->iPage]->nCell);
iCellDepth = pCur->iPage;
diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index 71ace9e5b..4398934f6 100644
--- a/src/box/sql/expr.c
+++ b/src/box/sql/expr.c
@@ -2899,7 +2899,7 @@ sqlite3CodeSubselect(Parse * pParse, /* Parsing context */
*/
pExpr->iTable = pParse->nTab++;
pExpr->is_ephemeral = 1;
- addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral,
+ addr = sqlite3VdbeAddOp2(v, OP_OpenTEphemeral,
pExpr->iTable,
(isRowid ? 0 : nVal));
pKeyInfo =
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index 3c43a217f..18bc766c6 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -2655,7 +2655,7 @@ multiSelect(Parse * pParse, /* Parsing context */
assert(p->pOrderBy == 0);
addr =
sqlite3VdbeAddOp2(v,
- OP_OpenEphemeral,
+ OP_OpenTEphemeral,
unionTab, 0);
assert(p->addrOpenEphm[0] == -1);
p->addrOpenEphm[0] = addr;
diff --git a/src/box/sql/tarantoolInt.h b/src/box/sql/tarantoolInt.h
index 933bf25b8..c4245b6d7 100644
--- a/src/box/sql/tarantoolInt.h
+++ b/src/box/sql/tarantoolInt.h
@@ -88,8 +88,11 @@ int tarantoolSqlite3RenameParentTable(int iTab, const char *zOldParentName,
/* Interface for ephemeral tables. */
int tarantoolSqlite3EphemeralCreate(BtCursor * pCur, uint32_t filed_count);
int tarantoolSqlite3EphemeralInsert(BtCursor * pCur, const BtreePayload * pX);
+int tarantoolSqlite3EphemeralDelete(BtCursor * pCur);
int tarantoolSqlite3EphemeralFirst(BtCursor * pCur, int * pRes);
int tarantoolSqlite3EphemeralNext(BtCursor * pCur, int * pRes);
+int tarantoolSqlite3EphemeralLast(BtCursor * pCur, int * pRes);
+int tarantoolSqlite3EphemeralPrevious(BtCursor * pCur, int * pRes);
int tarantoolSqlite3EphemeralDrop(BtCursor * pCur);
/* Compare against the index key under a cursor -
diff --git a/src/box/sql/update.c b/src/box/sql/update.c
index a1fe097d7..067f2f18f 100644
--- a/src/box/sql/update.c
+++ b/src/box/sql/update.c
@@ -394,7 +394,7 @@ sqlite3Update(Parse * pParse, /* The parser context */
regKey = ++pParse->nMem;
iEph = pParse->nTab++;
sqlite3VdbeAddOp2(v, OP_Null, 0, iPk);
- addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk);
+ addrOpen = sqlite3VdbeAddOp2(v, OP_OpenTEphemeral, iEph, nPk);
sqlite3VdbeSetP4KeyInfo(pParse, pPk);
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0,
WHERE_ONEPASS_DESIRED, iIdxCur);
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 2f22508c3..406819856 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -2576,7 +2576,8 @@ case OP_Column: {
if (pC->nHdrParsed <= p2) {
u32 size;
if (pC->eCurType == CURTYPE_BTREE &&
- pCrsr != NULL && (pCrsr->curFlags & BTCF_TaCursor) != 0 &&
+ pCrsr != NULL && ((pCrsr->curFlags & BTCF_TaCursor) != 0 ||
+ (pCrsr->curFlags & BTCF_TEphemCursor)) &&
(zParse = tarantoolSqlite3TupleColumnFast(pCrsr, p2,
&size)) != NULL) {
/*
@@ -3493,7 +3494,6 @@ case OP_OpenTEphemeral: {
pCx->uc.pCursor);
pCx->isTable = 1;
}
-
rc = tarantoolSqlite3EphemeralCreate(pCx->uc.pCursor, pOp->p2);
if (rc) goto abort_due_to_error;
break;
diff --git a/src/box/sql/vdbeaux.c b/src/box/sql/vdbeaux.c
index 21a3dfe3c..5d0a36215 100644
--- a/src/box/sql/vdbeaux.c
+++ b/src/box/sql/vdbeaux.c
@@ -4429,7 +4429,8 @@ sqlite3VdbeIdxKeyCompare(sqlite3 * db, /* Database connection */
assert(pC->eCurType == CURTYPE_BTREE);
pCur = pC->uc.pCursor;
assert(sqlite3BtreeCursorIsValid(pCur));
- if (pCur->curFlags & BTCF_TaCursor) {
+ if (pCur->curFlags & BTCF_TaCursor ||
+ pCur->curFlags & BTCF_TEphemCursor) {
return tarantoolSqlite3IdxKeyCompare(pCur, pUnpacked, res);
}
nCellKey = sqlite3BtreePayloadSize(pCur);
diff --git a/src/box/sql/wherecode.c b/src/box/sql/wherecode.c
index 9b4e2b2d0..e790bd226 100644
--- a/src/box/sql/wherecode.c
+++ b/src/box/sql/wherecode.c
@@ -1872,7 +1872,7 @@ sqlite3WhereCodeOneLoopStart(WhereInfo * pWInfo, /* Complete information about t
} else {
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
regRowset = pParse->nTab++;
- sqlite3VdbeAddOp2(v, OP_OpenEphemeral,
+ sqlite3VdbeAddOp2(v, OP_OpenTEphemeral,
regRowset, pPk->nKeyCol);
sqlite3VdbeSetP4KeyInfo(pParse, pPk);
}
diff --git a/test/sql-tap/in3.test.lua b/test/sql-tap/in3.test.lua
index 016124e3f..fd120451b 100755
--- a/test/sql-tap/in3.test.lua
+++ b/test/sql-tap/in3.test.lua
@@ -29,7 +29,7 @@ test:plan(27)
local function nEphemeral(sql)
nEph = 0
for _, op in ipairs(test:execsql("EXPLAIN "..sql.."")) do
- if (op == "OpenEphemeral")
+ if (op == "OpenTEphemeral")
then
nEph = nEph + 1
end
@@ -45,7 +45,7 @@ local function exec_neph(sql)
local res = test:execsql('EXPLAIN '..sql)
local cnt = 0
for _, v in ipairs(res) do
- if string.find(v, 'OpenEphemeral') then
+ if string.find(v, 'OpenTEphemeral') then
cnt = cnt + 1
end
end
diff --git a/test/sql-tap/in4.test.lua b/test/sql-tap/in4.test.lua
index c9d0c6c5d..ac39c5fca 100755
--- a/test/sql-tap/in4.test.lua
+++ b/test/sql-tap/in4.test.lua
@@ -450,7 +450,7 @@ test:do_execsql_test(
SELECT * FROM t3 WHERE x IN (10,11);
]], {
-- <in4-3.42>
- "/OpenEphemeral/"
+ "/OpenTEphemeral/"
-- </in4-3.42>
})
@@ -471,7 +471,7 @@ test:do_execsql_test(
SELECT * FROM t3 WHERE x IN (10);
]], {
-- <in4-3.44>
- "~/OpenEphemeral/"
+ "~/OpenTEphemeral/"
-- </in4-3.44>
})
@@ -492,7 +492,7 @@ test:do_execsql_test(
SELECT * FROM t3 WHERE x NOT IN (10,11,99999);
]], {
-- <in4-3.46>
- "/OpenEphemeral/"
+ "/OpenTEphemeral/"
-- </in4-3.46>
})
@@ -513,7 +513,7 @@ test:do_execsql_test(
SELECT * FROM t3 WHERE x NOT IN (10);
]], {
-- <in4-3.48>
- "~/OpenEphemeral/"
+ "~/OpenTEphemeral/"
-- </in4-3.48>
})
--
2.15.1
More information about the Tarantool-patches
mailing list