[tarantool-patches] [PATCH] sql: enable basic SELECTs for Lua created tables

Kirill Yukhin kyukhin at tarantool.org
Tue Jun 26 10:40:04 MSK 2018


Branch: https://github.com/tarantool/tarantool/tree/kyukhin/gh-3369-lua-select
Issue: https://github.com/tarantool/tarantool/issues/3369

Update expander of SELECT statement to search for space if
corresponding table wasn't found in table hash. Create dummy
table if so and fill def field only.

Also fix a leak in VIEW creation.

Part of #3369
---
 src/box/sql.c                    |   8 +--
 src/box/sql/build.c              |   4 +-
 src/box/sql/insert.c             |   9 ++-
 src/box/sql/select.c             |  21 ++++++-
 test/sql-tap/lua-tables.test.lua | 117 +++++++++++++++++++++++++++++++++++++++
 5 files changed, 148 insertions(+), 11 deletions(-)
 create mode 100755 test/sql-tap/lua-tables.test.lua

diff --git a/src/box/sql.c b/src/box/sql.c
index 1135315..6e5c1b3 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -1740,14 +1740,14 @@ space_column_default_expr(uint32_t space_id, uint32_t fieldno)
 }
 
 struct space_def *
-sql_ephemeral_space_def_new(Parse *parser, const char *name)
+sql_ephemeral_space_def_new(struct Parse *parser, const char *name)
 {
 	struct space_def *def = NULL;
-	struct region *region = &fiber()->gc;
 	size_t name_len = name != NULL ? strlen(name) : 0;
 	uint32_t dummy;
-	size_t size = space_def_sizeof(name_len, NULL, 0, &dummy, &dummy, &dummy);
-	def = (struct space_def *)region_alloc(region, size);
+	size_t size = space_def_sizeof(name_len, NULL, 0, &dummy, &dummy,
+				       &dummy);
+	def = (struct space_def *)region_alloc(&parser->region, size);
 	if (def == NULL) {
 		diag_set(OutOfMemory, size, "region_alloc",
 			 "sql_ephemeral_space_def_new");
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 0da7d80..748fb51 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -1970,6 +1970,7 @@ sql_create_view(struct Parse *parse_context, struct Token *begin,
 		struct Select *select, bool if_exists)
 {
 	struct sqlite3 *db = parse_context->db;
+	struct Table *sel_tab = NULL;
 	if (parse_context->nVar > 0) {
 		sqlite3ErrorMsg(parse_context,
 				"parameters are not allowed in views");
@@ -1979,7 +1980,7 @@ sql_create_view(struct Parse *parse_context, struct Token *begin,
 	struct Table *p = parse_context->pNewTable;
 	if (p == NULL || parse_context->nErr != 0)
 		goto create_view_fail;
-	struct Table *sel_tab =	sqlite3ResultSetOfSelect(parse_context, select);
+	sel_tab = sqlite3ResultSetOfSelect(parse_context, select);
 	if (sel_tab == NULL)
 		goto create_view_fail;
 	if (aliases != NULL) {
@@ -2032,6 +2033,7 @@ sql_create_view(struct Parse *parse_context, struct Token *begin,
 	sqlite3EndTable(parse_context, 0, &end, 0);
 
  create_view_fail:
+	sqlite3DbFree(db, sel_tab);
 	sql_expr_list_delete(db, aliases);
 	sql_select_delete(db, select);
 	return;
diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index a43f7b5..6a8cc69 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -51,11 +51,10 @@ sqlite3OpenTable(Parse * pParse,	/* Generate code into this VDBE */
 	Vdbe *v;
 	v = sqlite3GetVdbe(pParse);
 	assert(opcode == OP_OpenWrite || opcode == OP_OpenRead);
-	Index *pPk = sqlite3PrimaryKeyIndex(pTab);
-	assert(pPk != 0);
-	assert(pPk->tnum == pTab->tnum);
-	struct space *space = space_by_id(SQLITE_PAGENO_TO_SPACEID(pPk->tnum));
-	vdbe_emit_open_cursor(pParse, iCur, pPk->tnum, space);
+
+	struct space *space = space_by_id(pTab->def->id);
+	assert(space->index_count > 0);
+	vdbe_emit_open_cursor(pParse, iCur, 0, space);
 	VdbeComment((v, "%s", pTab->def->name));
 }
 
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index 368bcd6..dd847aa 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -36,6 +36,7 @@
 #include "coll.h"
 #include "sqliteInt.h"
 #include "tarantoolInt.h"
+#include "box/box.h"
 #include "box/coll_id_cache.h"
 #include "box/schema.h"
 #include "box/session.h"
@@ -4798,7 +4799,25 @@ selectExpander(Walker * pWalker, Select * p)
 			/* An ordinary table or view name in the FROM clause */
 			assert(pFrom->pTab == 0);
 			pFrom->pTab = pTab =
-			    sqlite3LocateTable(pParse, 0, pFrom->zName);
+			    sqlite3LocateTable(pParse, LOCATE_NOERR, pFrom->zName);
+			if (pTab == NULL) {
+				struct Table *tab = sqlite3DbMallocZero(db,
+									sizeof(Table));
+				tab->nTabRef = 1;
+				const char *t_name = pFrom->zName;
+				int space_id = box_space_id_by_name(t_name,
+								    strlen(t_name));
+				if (space_id == BOX_ID_NIL) {
+					sqlite3ErrorMsg(pParse,
+							"no such table: %s",
+							t_name);
+					pParse->checkSchema = 1;
+					return WRC_Abort;
+				}
+				struct space *space = space_by_id(space_id);
+				tab->def = space->def;
+				pFrom->pTab = pTab = tab;
+			}
 			if (pTab == NULL)
 				return WRC_Abort;
 			if (pTab->nTabRef >= 0xffff) {
diff --git a/test/sql-tap/lua-tables.test.lua b/test/sql-tap/lua-tables.test.lua
new file mode 100755
index 0000000..3096cd7
--- /dev/null
+++ b/test/sql-tap/lua-tables.test.lua
@@ -0,0 +1,117 @@
+#!/usr/bin/env tarantool
+test = require("sqltester")
+test:plan(7)
+
+test:do_test(
+    "lua-tables-repare-1",
+    function()
+        format = {}
+        format[1] = { name = 'id', type = 'scalar'}
+        format[2] = { name = 'f2', type = 'scalar'}
+        s = box.schema.create_space('t', {format = format})
+        i = s:create_index('i', {parts={1, 'scalar'}})
+
+        s:replace{1, 4}
+        s:replace{2, 2}
+        s:replace{3, 3}
+        s:replace{4, 3}
+
+        s1 = box.schema.create_space('t1')
+        s1:create_index('i', {parts={1, 'scalar'}})
+        s1:replace{1, 1}
+    end,
+    {})
+
+test:do_execsql_test(
+    "lua-tables-2",
+    [[SELECT *, count(*)
+        FROM "t" as t1, "t" as t2
+        WHERE t1."id" = t2."f2"
+    ]],
+    {4, 3, 1, 4, 4})
+
+test:do_execsql_test(
+    "lua-tables-3",
+    [[create view v as SELECT * FROM "t";
+      select * from v;
+    ]],
+    {1, 4, 2, 2, 3, 3, 4, 3})
+
+test:do_catchsql_test(
+    "lua-tables-4",
+    [[SELECT * from "t1"]],
+    {1, "no tables specified"}
+)
+
+-- Extract from tkt3527.test.lua
+test:do_test(
+    "lua-tables-prepare-5",
+    function()
+        format = {{name = "CODE", type = "integer"},
+            {name = "NAME", type = "scalar"}}
+        s = box.schema.create_space("ELEMENT", {format = format})
+        s:create_index('pk', {parts = {1, 'scalar'}})
+        s:replace{1, 'Elem1'}
+        s:replace{2, 'Elem2'}
+        s:replace{3, 'Elem3'}
+        s:replace{4, 'Elem4'}
+        s:replace{5, 'Elem5'}
+
+        format  = {{name = "CODEOR", type = "scalar"},
+            {name = "CODE", type = "scalar"}}
+        s = box.schema.create_space("ELEMOR", {format = format})
+        s:create_index('pk', {parts = {1, 'scalar', 2, 'scalar'}})
+        s:replace{3, 4}
+        s:replace{4, 5}
+
+        format = {{name = "CODEAND", type = "scalar"},
+            {name = "CODE", type = "scalar"},
+            {name = "ATTR1", type = "scalar"},
+            {name = "ATTR2", type = "scalar"},
+            {name = "ATTR3", type = "scalar"}}
+        s = box.schema.create_space("ELEMAND", {format = format})
+        s:create_index('pk', {parts = {1, "scalar", 2, "scalar"}})
+        s:replace{1, 3, 'a', 'b', 'c'}
+        s:replace{1, 2, 'x', 'y', 'z'}
+    end,
+    {})
+
+test:do_execsql_test(
+    "lua-tables-6",
+    [[CREATE VIEW ElemView1 AS
+      SELECT
+        CAST(Element.Code AS VARCHAR(50)) AS ElemId,
+       Element.Code AS ElemCode,
+       Element.Name AS ElemName,
+       ElemAnd.Code AS InnerCode,
+       ElemAnd.Attr1 AS Attr1,
+       ElemAnd.Attr2 AS Attr2,
+       ElemAnd.Attr3 AS Attr3,
+       0 AS Level,
+       0 AS IsOrElem
+      FROM Element JOIN ElemAnd ON ElemAnd.CodeAnd=Element.Code
+      WHERE ElemAnd.CodeAnd NOT IN (SELECT CodeOr FROM ElemOr)
+      UNION ALL
+      SELECT
+        CAST(ElemOr.CodeOr AS VARCHAR(50)) AS ElemId,
+        Element.Code AS ElemCode,
+        Element.Name AS ElemName,
+        ElemOr.Code AS InnerCode,
+        NULL AS Attr1,
+        NULL AS Attr2,
+        NULL AS Attr3,
+        0 AS Level,
+        1 AS IsOrElem
+      FROM ElemOr JOIN Element ON Element.Code=ElemOr.CodeOr
+      ORDER BY ElemId, InnerCode;]],
+    {})
+
+test:do_execsql_test(
+    "lua-tables-7",
+    [[SELECT * FROM ElemView1]],
+    {"1",1,"Elem1",2,"x","y","z",0,0,
+     "1",1,"Elem1",3,"a","b","c",0,0,
+     "3",3,"Elem3",4,"","","",0,1,
+     "4",4,"Elem4",5,"","","",0,1})
+
+test:finish_test()
-- 
2.16.2





More information about the Tarantool-patches mailing list