[tarantool-patches] [PATCH 2/4] sql: rework OP_Clear internals
Nikita Pettik
korablev at tarantool.org
Mon Mar 19 21:10:38 MSK 2018
This patch makes OP_Clear use pointer to space instead of space id.
Moreover, in order to avoid excess function calls (such as box_delete() ->
box_process1(), which in its turn makes additional space lookup),
sql_execute_dml() function is introduced. It is an analogue of
process_rw() from BOX internals. Its purpose is to handle transaction
routine and call DML executor. This function will be also used later as
well during insertion and deletion.
Part of #3122
---
src/box/sql.c | 54 +++++++++++++++++++++++++++++++---------------
src/box/sql/opcodes.c | 2 +-
src/box/sql/opcodes.h | 2 +-
src/box/sql/tarantoolInt.h | 2 +-
src/box/sql/vdbe.c | 28 ++++++++++--------------
5 files changed, 51 insertions(+), 37 deletions(-)
diff --git a/src/box/sql.c b/src/box/sql.c
index 256985793..4f8b39810 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -191,6 +191,27 @@ is_tarantool_error(int rc)
rc == SQL_TARANTOOL_INSERT_FAIL);
}
+/**
+ * This function is analogue of process_rw() from box module.
+ * Apart of calling space_execute_dml(), it handles transaction
+ * routine.
+ */
+static int
+sql_execute_dml(struct request *request, struct space *space)
+{
+ struct txn *txn = txn_begin_stmt(space);
+ if (txn == NULL)
+ return -1;
+ struct tuple *unused = NULL;
+ if (space_execute_dml(space, txn, request, &unused) != 0) {
+ txn_rollback_stmt();
+ return -1;
+ }
+ if (txn_commit_stmt(txn, request) != 0)
+ return -1;
+ return 0;
+}
+
int tarantoolSqlite3CloseCursor(BtCursor *pCur)
{
assert(pCur->curFlags & BTCF_TaCursor ||
@@ -659,10 +680,8 @@ int tarantoolSqlite3EphemeralClearTable(BtCursor *pCur)
/*
* Removes all instances from table.
*/
-int tarantoolSqlite3ClearTable(int iTable)
+int tarantoolSqlite3ClearTable(struct space *space)
{
- int space_id = SQLITE_PAGENO_TO_SPACEID(iTable);
-
/*
* There are two cases when we have to delete tuples one by one:
* 1. When we are inside of another transaction, we can not use
@@ -670,30 +689,31 @@ int tarantoolSqlite3ClearTable(int iTable)
* 2. Truncate on system spaces is disallowed. (because of triggers)
* (main usecase is _sql_stat4 table editing)
*/
- if (box_txn() || space_id < BOX_SYSTEM_ID_MAX) {
- int primary_index_id = 0;
- char *key;
+ if (box_txn() || space_is_system(space)) {
uint32_t key_size;
box_tuple_t *tuple;
int rc;
- box_iterator_t *iter;
- iter = box_index_iterator(space_id, primary_index_id, ITER_ALL,
- nil_key, nil_key + sizeof(nil_key));
+ struct request request;
+ memset(&request, 0, sizeof(request));
+ request.type = IPROTO_DELETE;
+ request.space_id = space->def->id;
+ struct index *pk = space_index(space, 0 /* PK */);
+ struct iterator *iter =
+ index_create_iterator(pk, ITER_ALL, nil_key, 0);
if (iter == NULL)
return SQL_TARANTOOL_ITERATOR_FAIL;
- while (box_iterator_next(iter, &tuple) == 0 && tuple != NULL) {
- key = tuple_extract_key(tuple,
- box_iterator_key_def(iter),
+ while (iterator_next(iter, &tuple) == 0 && tuple != NULL) {
+ request.key = tuple_extract_key(tuple, pk->def->key_def,
&key_size);
- rc = box_delete(space_id, primary_index_id, key,
- key + key_size, NULL);
+ request.key_end = request.key + key_size;
+ rc = sql_execute_dml(&request, space);
if (rc != 0) {
- box_iterator_free(iter);
+ iterator_delete(iter);
return SQL_TARANTOOL_DELETE_FAIL;
}
}
- box_iterator_free(iter);
- } else if (box_truncate(space_id) != 0) {
+ iterator_delete(iter);
+ } else if (box_truncate(space->def->id) != 0) {
return SQL_TARANTOOL_DELETE_FAIL;
}
diff --git a/src/box/sql/opcodes.c b/src/box/sql/opcodes.c
index 53603037d..7a40b28a8 100644
--- a/src/box/sql/opcodes.c
+++ b/src/box/sql/opcodes.c
@@ -129,7 +129,7 @@ const char *sqlite3OpcodeName(int i){
/* 115 */ "Real" OpHelp("r[P2]=P4"),
/* 116 */ "IdxInsert" OpHelp("key=r[P2]"),
/* 117 */ "IdxDelete" OpHelp("key=r[P2 at P3]"),
- /* 118 */ "Clear" OpHelp(""),
+ /* 118 */ "Clear" OpHelp("space id = P1"),
/* 119 */ "ResetSorter" OpHelp(""),
/* 120 */ "ParseSchema2" OpHelp("rows=r[P1 at P2]"),
/* 121 */ "ParseSchema3" OpHelp("name=r[P1] sql=r[P1+1]"),
diff --git a/src/box/sql/opcodes.h b/src/box/sql/opcodes.h
index 1fbb6b690..af2ba1963 100644
--- a/src/box/sql/opcodes.h
+++ b/src/box/sql/opcodes.h
@@ -118,7 +118,7 @@
#define OP_Real 115 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
#define OP_IdxInsert 116 /* synopsis: key=r[P2] */
#define OP_IdxDelete 117 /* synopsis: key=r[P2 at P3] */
-#define OP_Clear 118
+#define OP_Clear 118 /* synopsis: space id = P1 */
#define OP_ResetSorter 119
#define OP_ParseSchema2 120 /* synopsis: rows=r[P1 at P2] */
#define OP_ParseSchema3 121 /* synopsis: name=r[P1] sql=r[P1+1] */
diff --git a/src/box/sql/tarantoolInt.h b/src/box/sql/tarantoolInt.h
index 39fdbcd76..c98871cd5 100644
--- a/src/box/sql/tarantoolInt.h
+++ b/src/box/sql/tarantoolInt.h
@@ -77,7 +77,7 @@ int tarantoolSqlite3Count(BtCursor * pCur, i64 * pnEntry);
int tarantoolSqlite3Insert(BtCursor * pCur);
int tarantoolSqlite3Replace(BtCursor * pCur);
int tarantoolSqlite3Delete(BtCursor * pCur, u8 flags);
-int tarantoolSqlite3ClearTable(int iTable);
+int tarantoolSqlite3ClearTable(struct space *space);
/* Rename table pTab with zNewName by inserting new tuple to _space.
* SQL statement, which creates table with new name is saved in pzSqlStmt.
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 49ce51096..7de9b67c1 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -4590,26 +4590,20 @@ case OP_IdxGE: { /* jump */
break;
}
-/* Opcode: Clear P1 P2 P3
+/* Opcode: Clear P1 * * * *
+ * Synopsis: space id = P1
*
- * Delete all contents of the database table or index whose root page
- * in the database file is given by P1. But, unlike Destroy, do not
- * remove the table or index from the database file.
- *
- * The table being clear is in the main database file if P2==0. If
- * P2==1 then the table to be clear is in the auxiliary database file
- * that is used to store tables create using CREATE TEMPORARY TABLE.
- *
- * If the P3 value is non-zero, then the table referred to must be an
- * intkey table (an SQL table, not an index). In this case the row change
- * count is incremented by the number of rows in the table being cleared.
- * If P3 is greater than zero, then the value stored in register P3 is
- * also incremented by the number of rows in the table being cleared.
- *
- * See also: Destroy
+ * Delete all contents of the space, which space id is given
+ * in P1 argument. Notice, that execution of this opcode inside
+ * active transaction would slow down perfomance, since it
+ * becomes impossible to use truncate feature.
*/
case OP_Clear: {
- rc = tarantoolSqlite3ClearTable(pOp->p1);
+ assert(pOp->p1 > 0);
+ uint32_t space_id = SQLITE_PAGENO_TO_SPACEID(pOp->p1);
+ struct space *space = space_by_id(space_id);
+ assert(space != NULL);
+ rc = tarantoolSqlite3ClearTable(space);
if (rc) goto abort_due_to_error;
break;
}
--
2.15.1
More information about the Tarantool-patches
mailing list