[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