[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