[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