[tarantool-patches] [PATCH] sql: refactor SQL delete to allow Lua spaces

Kirill Yukhin kyukhin at tarantool.org
Fri May 18 16:36:56 MSK 2018


Branch: https://github.com/tarantool/tarantool/tree/kyukhin/gh-3235-sql-truncate-on-lua-spaces
Issue: https://github.com/tarantool/tarantool/issues/3235

This is a first step toward fully-featured deletion
of spaces created in Lua by means of SQL language.
This change to handle most simple case:
DELETE * FROM <space_name> and will be improved in
nearest future.

Part of #3235
---
 src/box/sql/analyze.c         |  3 +-
 src/box/sql/build.c           |  3 +-
 src/box/sql/delete.c          | 69 ++++++++++++++++++++++++++-----------------
 src/box/sql/vdbe.c            |  2 +-
 test/sql-tap/delete1.test.lua | 23 ++++++++++++++-
 5 files changed, 69 insertions(+), 31 deletions(-)

diff --git a/src/box/sql/analyze.c b/src/box/sql/analyze.c
index 998dd5b..cc594a7 100644
--- a/src/box/sql/analyze.c
+++ b/src/box/sql/analyze.c
@@ -169,7 +169,8 @@ openStatTable(Parse * pParse,	/* Parsing context */
 			 * The sql_stat[134] table already exists.
 			 * Delete all rows.
 			 */
-			sqlite3VdbeAddOp2(v, OP_Clear, aRoot[i], 0);
+			sqlite3VdbeAddOp2(v, OP_Clear,
+					  SQLITE_PAGENO_TO_SPACEID(aRoot[i]), 0);
 		}
 	}
 
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index df75186..49e59f4 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -2672,7 +2672,8 @@ sqlite3RefillIndex(Parse * pParse, Index * pIndex, int memRootPage)
 	VdbeCoverage(v);
 	sqlite3VdbeJumpHere(v, addr1);
 	if (memRootPage < 0)
-		sqlite3VdbeAddOp2(v, OP_Clear, tnum, 0);
+		sqlite3VdbeAddOp2(v, OP_Clear, SQLITE_PAGENO_TO_SPACEID(tnum),
+				  0);
 	emit_open_cursor(pParse, iIdx, tnum);
 	sqlite3VdbeChangeP5(v,
 			    OPFLAG_BULKCSR | ((memRootPage >= 0) ?
diff --git a/src/box/sql/delete.c b/src/box/sql/delete.c
index f4d248e..dfc91cb 100644
--- a/src/box/sql/delete.c
+++ b/src/box/sql/delete.c
@@ -29,6 +29,7 @@
  * SUCH DAMAGE.
  */
 
+#include "box/box.h"
 #include "box/session.h"
 #include "box/schema.h"
 #include "sqliteInt.h"
@@ -86,35 +87,50 @@ sql_table_delete_from(struct Parse *parse, struct SrcList *tab_list,
 	 * with multiple tables and expect an SrcList* parameter
 	 * instead of just a Table* parameter.
 	 */
-	struct Table *table = sql_list_lookup_table(parse, tab_list);
-	if (table == NULL)
-		goto delete_from_cleanup;
-
-	struct space *space = space_by_id(SQLITE_PAGENO_TO_SPACEID(table->tnum));
-	assert(space != NULL);
+	struct Table *table = NULL;
+	struct space *space;
+	uint32_t space_id;
 	/* Figure out if we have any triggers and if the table
 	 * being deleted from is a view.
 	 */
-	struct Trigger *trigger_list = sqlite3TriggersExist(table, TK_DELETE,
-							    NULL, NULL);
-
-	bool is_view = space->def->opts.is_view;
+	struct Trigger *trigger_list = NULL;
 	/* True if there are triggers or FKs or subqueries in the
 	 * WHERE clause.
 	 */
-	bool is_complex = trigger_list != NULL ||
-			  sqlite3FkRequired(table, NULL);
+	bool is_complex = false;
+	const char *tab_name = tab_list->a->zName;
+	if (sqlite3LocateTable(parse, LOCATE_NOERR, tab_name) == NULL) {
+		space_id = box_space_id_by_name(tab_name,
+						strlen(tab_name));
+		if (space_id == BOX_ID_NIL)
+			goto delete_from_cleanup;
+	} else {
+		table = sql_list_lookup_table(parse, tab_list);
+		if (table == NULL)
+			goto delete_from_cleanup;
+		space_id = SQLITE_PAGENO_TO_SPACEID(table->tnum);
+		trigger_list =sqlite3TriggersExist(table, TK_DELETE,
+						   NULL, NULL);
+		is_complex = trigger_list != NULL ||
+			     sqlite3FkRequired(table, NULL);
+	}
+	space = space_by_id(space_id);
+	assert(space != NULL);
+
+	bool is_view = space->def->opts.is_view;
 
 	/* If table is really a view, make sure it has been
 	 * initialized.
 	 */
-	if (sqlite3ViewGetColumnNames(parse, table))
-		goto delete_from_cleanup;
+	if (is_view) {
+		if (sqlite3ViewGetColumnNames(parse, table))
+			goto delete_from_cleanup;
 
-	if (is_view && trigger_list == NULL) {
-		sqlite3ErrorMsg(parse, "cannot modify %s because it is a view",
-				space->def->name);
-		goto delete_from_cleanup;
+		if (trigger_list == NULL) {
+			sqlite3ErrorMsg(parse, "cannot modify %s because it is a"
+					" view", space->def->name);
+			goto delete_from_cleanup;
+		}
 	}
 
 	/* Assign cursor numbers to the table and all its indices.
@@ -139,14 +155,6 @@ sql_table_delete_from(struct Parse *parse, struct SrcList *tab_list,
 				     tab_cursor);
 	}
 
-	/* Resolve the column names in the WHERE clause. */
-	struct NameContext nc;
-	memset(&nc, 0, sizeof(nc));
-	nc.pParse = parse;
-	nc.pSrcList = tab_list;
-	if (sqlite3ResolveExprNames(&nc, where))
-		goto delete_from_cleanup;
-
 	/* Initialize the counter of the number of rows deleted,
 	 * if we are counting rows.
 	 */
@@ -162,7 +170,7 @@ sql_table_delete_from(struct Parse *parse, struct SrcList *tab_list,
 	if (where == NULL && !is_complex) {
 		assert(!is_view);
 
-		sqlite3VdbeAddOp1(v, OP_Clear, table->tnum);
+		sqlite3VdbeAddOp1(v, OP_Clear, space_id);
 
 		/* Do not start Tarantool's transaction in case of
 		 * truncate optimization. This is workaround until
@@ -171,6 +179,13 @@ sql_table_delete_from(struct Parse *parse, struct SrcList *tab_list,
 		 */
 		parse->initiateTTrans = false;
 	} else {
+		/* Resolve the column names in the WHERE clause. */
+		struct NameContext nc;
+		memset(&nc, 0, sizeof(nc));
+		nc.pParse = parse;
+		nc.pSrcList = tab_list;
+		if (sqlite3ResolveExprNames(&nc, where))
+			goto delete_from_cleanup;
 		uint16_t wcf = WHERE_ONEPASS_DESIRED | WHERE_DUPLICATES_OK |
 			WHERE_SEEK_TABLE;
 		if (nc.ncFlags & NC_VarSelect)
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 455198d..9acb9b6 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -4614,7 +4614,7 @@ case OP_IdxGE:  {       /* jump */
  */
 case OP_Clear: {
 	assert(pOp->p1 > 0);
-	uint32_t space_id = SQLITE_PAGENO_TO_SPACEID(pOp->p1);
+	uint32_t space_id = pOp->p1;
 	struct space *space = space_by_id(space_id);
 	assert(space != NULL);
 	rc = tarantoolSqlite3ClearTable(space);
diff --git a/test/sql-tap/delete1.test.lua b/test/sql-tap/delete1.test.lua
index 61d7756..810ca8a 100755
--- a/test/sql-tap/delete1.test.lua
+++ b/test/sql-tap/delete1.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env tarantool
 test = require("sqltester")
-test:plan(7)
+test:plan(9)
 
 --!./tcltestrunner.lua
 -- ["set","testdir",[["file","dirname",["argv0"]]]]
@@ -131,5 +131,26 @@ test:do_test(
         -- </delete1-5.0>
     })
 
+-- Tests for data dictionary integration.
+s = box.schema.create_space('t')
+i = s:create_index('i', {parts={1, 'unsigned'}})
+test:do_test(
+    "delete1-6.0",
+    function()
+	s:replace({1})
+	s:replace({2})
+	s:replace({3})
+	return s:count()
+    end,
+    3)
+
+test:do_test(
+    "delete1-6.1",
+    function()
+        box.sql.execute([[delete from "t"]])
+	return s:count()
+    end,
+    0)
+
 test:finish_test()
 
-- 
2.16.2





More information about the Tarantool-patches mailing list