From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id 6038920E33 for ; Fri, 18 May 2018 09:37:04 -0400 (EDT) Received: from turing.freelists.org ([127.0.0.1]) by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id D6ARR73tjc9I for ; Fri, 18 May 2018 09:37:04 -0400 (EDT) Received: from smtp5.mail.ru (smtp5.mail.ru [94.100.179.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id AEA3720E28 for ; Fri, 18 May 2018 09:37:03 -0400 (EDT) From: Kirill Yukhin Subject: [tarantool-patches] [PATCH] sql: refactor SQL delete to allow Lua spaces Date: Fri, 18 May 2018 16:36:56 +0300 Message-Id: <87358913270ee98c98bc276209289d6b7ac496b6.1526650490.git.kyukhin@tarantool.org> Sender: tarantool-patches-bounce@freelists.org Errors-to: tarantool-patches-bounce@freelists.org Reply-To: tarantool-patches@freelists.org List-help: List-unsubscribe: List-software: Ecartis version 1.0.0 List-Id: tarantool-patches List-subscribe: List-owner: List-post: List-archive: To: v.shpilevoy@tarantool.org Cc: tarantool-patches@freelists.org, Kirill Yukhin 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 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( -- }) +-- 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