[tarantool-patches] [PATCH v2 2/2] sql: use 'view' opts from space

Nikita Pettik korablev at tarantool.org
Tue Mar 27 02:03:33 MSK 2018


Originally in SQLite, table which represented view had not null pointer
to struct Select. However, after 'view' space option is introduced, it
has become possible to fetch 'view' property directly from struct space.
This patch introduces simple wrapper to get this option.
Moreover, TF_View flag is no more needed, so it is also removed.
---
 src/box/sql/alter.c          |  4 ++--
 src/box/sql/build.c          | 27 +++++++++++++++++++--------
 src/box/sql/delete.c         |  2 +-
 src/box/sql/fkey.c           |  3 ++-
 src/box/sql/insert.c         | 10 ++++++----
 src/box/sql/parse.c          |  4 ++--
 src/box/sql/parse.y          |  5 ++---
 src/box/sql/select.c         |  4 ++--
 src/box/sql/sqliteInt.h      |  5 +++--
 src/box/sql/trigger.c        |  4 ++--
 src/box/sql/update.c         |  2 +-
 src/box/sql/vdbeaux.c        |  2 +-
 src/box/sql/where.c          |  3 ++-
 test/sql/transition.result   |  7 -------
 test/sql/transition.test.lua |  4 ----
 15 files changed, 45 insertions(+), 41 deletions(-)

diff --git a/src/box/sql/alter.c b/src/box/sql/alter.c
index a52ba8d7a..054c0856c 100644
--- a/src/box/sql/alter.c
+++ b/src/box/sql/alter.c
@@ -107,7 +107,7 @@ sqlite3AlterRenameTable(Parse * pParse,	/* Parser context. */
 	}
 
 #ifndef SQLITE_OMIT_VIEW
-	if (pTab->pSelect) {
+	if (space_is_view(pTab)) {
 		sqlite3ErrorMsg(pParse, "view %s may not be altered",
 				pTab->zName);
 		goto exit_rename_table;
@@ -262,7 +262,7 @@ sqlite3AlterBeginAddColumn(Parse * pParse, SrcList * pSrc)
 		goto exit_begin_add_column;
 
 	/* Make sure this is not an attempt to ALTER a view. */
-	if (pTab->pSelect) {
+	if (space_is_view(pTab)) {
 		sqlite3ErrorMsg(pParse, "Cannot add a column to a view");
 		goto exit_begin_add_column;
 	}
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index dd0f45cf6..a9cb76717 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -1160,6 +1160,20 @@ index_collation_name(Index *idx, uint32_t column)
 	return index->def->key_def->parts[column].coll->name;
 }
 
+/**
+ * Return true if space which corresponds to
+ * given table has view option.
+ */
+bool
+space_is_view(Table *table)
+{
+	assert(table != NULL);
+	uint32_t space_id = SQLITE_PAGENO_TO_SPACEID(table->tnum);
+	struct space *space = space_by_id(space_id);
+	assert(space != NULL);
+	return space->def->opts.view;
+}
+
 /*
  * This function returns the collation sequence for database native text
  * encoding identified by the string zName, length nName.
@@ -1839,7 +1853,6 @@ void
 sqlite3EndTable(Parse * pParse,	/* Parse context */
 		Token * pCons,	/* The ',' token after the last column defn. */
 		Token * pEnd,	/* The ')' before options in the CREATE TABLE */
-		u8 tabOpts,	/* Extra table options. Usually 0. */
 		Select * pSelect	/* Select from a "CREATE ... AS SELECT" */
     )
 {
@@ -1864,9 +1877,7 @@ sqlite3EndTable(Parse * pParse,	/* Parse context */
 	if (db->init.busy)
 		p->tnum = db->init.newTnum;
 
-	if (p->pSelect) {
-		tabOpts |= TF_View;
-	} else {
+	if (!p->pSelect) {
 		if ((p->tabFlags & TF_HasPrimaryKey) == 0) {
 			sqlite3ErrorMsg(pParse,
 					"PRIMARY KEY missing on table %s",
@@ -1957,7 +1968,7 @@ sqlite3EndTable(Parse * pParse,	/* Parse context */
 		if (pSelect) {
 			zStmt = createTableStmt(db, p);
 		} else {
-			Token *pEnd2 = tabOpts ? &pParse->sLastToken : pEnd;
+			Token *pEnd2 = p->pSelect ? &pParse->sLastToken : pEnd;
 			n = (int)(pEnd2->z - pParse->sNameToken.z);
 			if (pEnd2->z[0] != ';')
 				n += pEnd2->n;
@@ -2123,7 +2134,7 @@ sqlite3CreateView(Parse * pParse,	/* The parsing context */
 	sEnd.n = 1;
 
 	/* Use sqlite3EndTable() to add the view to the Tarantool.  */
-	sqlite3EndTable(pParse, 0, &sEnd, 0, 0);
+	sqlite3EndTable(pParse, 0, &sEnd, 0);
 
  create_view_fail:
 	sqlite3SelectDelete(db, pSelect);
@@ -2414,12 +2425,12 @@ sqlite3DropTable(Parse * pParse, SrcList * pName, int isView, int noErr)
 	/* Ensure DROP TABLE is not used on a view, and DROP VIEW is not used
 	 * on a table.
 	 */
-	if (isView && pTab->pSelect == 0) {
+	if (isView && !space_is_view(pTab)) {
 		sqlite3ErrorMsg(pParse, "use DROP TABLE to delete table %s",
 				pTab->zName);
 		goto exit_drop_table;
 	}
-	if (!isView && pTab->pSelect) {
+	if (!isView && space_is_view(pTab)) {
 		sqlite3ErrorMsg(pParse, "use DROP VIEW to delete view %s",
 				pTab->zName);
 		goto exit_drop_table;
diff --git a/src/box/sql/delete.c b/src/box/sql/delete.c
index 61845aa27..2e09d926a 100644
--- a/src/box/sql/delete.c
+++ b/src/box/sql/delete.c
@@ -88,7 +88,7 @@ sqlite3IsReadOnly(Parse * pParse, Table * pTab, int viewOk)
 		return 1;
 	}
 #ifndef SQLITE_OMIT_VIEW
-	if (!viewOk && pTab->pSelect) {
+	if (!viewOk && space_is_view(pTab)) {
 		sqlite3ErrorMsg(pParse, "cannot modify %s because it is a view",
 				pTab->zName);
 		return 1;
diff --git a/src/box/sql/fkey.c b/src/box/sql/fkey.c
index 793f2f640..9286f4c5a 100644
--- a/src/box/sql/fkey.c
+++ b/src/box/sql/fkey.c
@@ -769,7 +769,8 @@ sqlite3FkDropTable(Parse * pParse, SrcList * pName, Table * pTab)
 	sqlite3 *db = pParse->db;
 	struct session *user_session = current_session();
 
-	if ((user_session->sql_flags & SQLITE_ForeignKeys) && !pTab->pSelect) {
+	if ((user_session->sql_flags & SQLITE_ForeignKeys) &&
+	    !space_is_view(pTab)) {
 		int iSkip = 0;
 		Vdbe *v = sqlite3GetVdbe(pParse);
 
diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index 28c01092d..42254ddf4 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -381,7 +381,7 @@ sqlite3Insert(Parse * pParse,	/* Parser context */
 	 */
 #ifndef SQLITE_OMIT_TRIGGER
 	pTrigger = sqlite3TriggersExist(pTab, TK_INSERT, 0, &tmask);
-	isView = pTab->pSelect != 0;
+	isView = space_is_view(pTab);
 #else
 #define pTrigger 0
 #define tmask 0
@@ -1074,7 +1074,8 @@ sqlite3GenerateConstraintChecks(Parse * pParse,		/* The parser context */
 	db = pParse->db;
 	v = sqlite3GetVdbe(pParse);
 	assert(v != 0);
-	assert(pTab->pSelect == 0);	/* This table is not a VIEW */
+	/* This table is not a VIEW */
+	assert(!space_is_view(pTab));
 	nCol = pTab->nCol;
 
 	pPk = sqlite3PrimaryKeyIndex(pTab);
@@ -1482,7 +1483,8 @@ sqlite3CompleteInsertion(Parse * pParse,	/* The parser context */
 
 	v = sqlite3GetVdbe(pParse);
 	assert(v != 0);
-	assert(pTab->pSelect == 0);	/* This table is not a VIEW */
+	/* This table is not a VIEW */
+	assert(!space_is_view(pTab));
 	/*
 	 * The for loop which purpose in sqlite was to insert new
 	 * values to all indexes is replaced to inserting new
@@ -1802,7 +1804,7 @@ xferOptimization(Parse * pParse,	/* Parser context */
 	if (pSrc == pDest) {
 		return 0;	/* tab1 and tab2 may not be the same table */
 	}
-	if (pSrc->pSelect) {
+	if (space_is_view(pSrc)) {
 		return 0;	/* tab2 may not be a view */
 	}
 	if (pDest->nCol != pSrc->nCol) {
diff --git a/src/box/sql/parse.c b/src/box/sql/parse.c
index f938a9a3c..17ce309da 100644
--- a/src/box/sql/parse.c
+++ b/src/box/sql/parse.c
@@ -2262,14 +2262,14 @@ static void yy_reduce(
       case 17: /* create_table_args ::= LP columnlist conslist_opt RP */
 #line 185 "parse.y"
 {
-  sqlite3EndTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);
+  sqlite3EndTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0);
 }
 #line 2268 "parse.c"
         break;
       case 18: /* create_table_args ::= AS select */
 #line 188 "parse.y"
 {
-  sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy279);
+  sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy279);
   sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy279);
 }
 #line 2276 "parse.c"
diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y
index 11db58d94..e2acf2423 100644
--- a/src/box/sql/parse.y
+++ b/src/box/sql/parse.y
@@ -183,10 +183,10 @@ ifnotexists(A) ::= .              {A = 0;}
 ifnotexists(A) ::= IF NOT EXISTS. {A = 1;}
 
 create_table_args ::= LP columnlist conslist_opt(X) RP(E). {
-  sqlite3EndTable(pParse,&X,&E,0,0);
+  sqlite3EndTable(pParse,&X,&E,0);
 }
 create_table_args ::= AS select(S). {
-  sqlite3EndTable(pParse,0,0,0,S);
+  sqlite3EndTable(pParse,0,0,S);
   sqlite3SelectDelete(pParse->db, S);
 }
 columnlist ::= columnlist COMMA columnname carglist.
@@ -1357,7 +1357,6 @@ cmd ::= createkw trigger_decl(A) BEGIN trigger_cmd_list(S) END(Z). {
 trigger_decl(A) ::= TRIGGER ifnotexists(NOERR) nm(B)
                     trigger_time(C) trigger_event(D)
                     ON fullname(E) foreach_clause when_clause(G). {
-  pParse->initiateTTrans = false;
   sqlite3BeginTrigger(pParse, &B, C, D.a, D.b, E, G, NOERR);
   A = B; /*A-overwrites-T*/
 }
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index a76286f23..c14bd7462 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -4295,7 +4295,7 @@ isSimpleCount(Select * p, AggInfo * pAggInfo)
 	}
 	pTab = p->pSrc->a[0].pTab;
 	pExpr = p->pEList->a[0].pExpr;
-	assert(pTab && !pTab->pSelect && pExpr);
+	assert(pTab && !space_is_view(pTab) && pExpr);
 	if (pExpr->op != TK_AGG_FUNCTION)
 		return 0;
 	if (NEVER(pAggInfo->nFunc == 0))
@@ -4760,7 +4760,7 @@ selectExpander(Walker * pWalker, Select * p)
 				return WRC_Abort;
 			}
 #if !defined(SQLITE_OMIT_VIEW)
-			if (pTab->pSelect) {
+			if (space_is_view(pTab)) {
 				i16 nCol;
 				if (sqlite3ViewGetColumnNames(pParse, pTab))
 					return WRC_Abort;
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index 0856bc729..effc0ffd5 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -1355,7 +1355,6 @@ struct Table {
 #define TF_Ephemeral       0x02	/* An ephemeral table */
 #define TF_HasPrimaryKey   0x04	/* Table has a primary key */
 #define TF_Autoincrement   0x08	/* Integer primary key is autoincrement */
-#define TF_View   	   0x20	/* A view */
 
 /*
  * Each foreign key constraint is an instance of the following structure.
@@ -2983,7 +2982,9 @@ const char *
 index_collation_name(Index *, uint32_t);
 struct coll *
 sql_default_coll();
-void sqlite3EndTable(Parse *, Token *, Token *, u8, Select *);
+bool
+space_is_view(Table *);
+void sqlite3EndTable(Parse *, Token *, Token *, Select *);
 int sqlite3ParseUri(const char *, const char *, unsigned int *,
 		    sqlite3_vfs **, char **, char **);
 
diff --git a/src/box/sql/trigger.c b/src/box/sql/trigger.c
index 08963cb79..5460d1a54 100644
--- a/src/box/sql/trigger.c
+++ b/src/box/sql/trigger.c
@@ -144,13 +144,13 @@ sqlite3BeginTrigger(Parse * pParse,	/* The parse context of the CREATE TRIGGER s
 	/* INSTEAD of triggers are only for views and views only support INSTEAD
 	 * of triggers.
 	 */
-	if (pTab->pSelect && tr_tm != TK_INSTEAD) {
+	if (space_is_view(pTab) && tr_tm != TK_INSTEAD) {
 		sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S",
 				(tr_tm == TK_BEFORE) ? "BEFORE" : "AFTER",
 				pTableName, 0);
 		goto trigger_cleanup;
 	}
-	if (!pTab->pSelect && tr_tm == TK_INSTEAD) {
+	if (!space_is_view(pTab) && tr_tm == TK_INSTEAD) {
 		sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF"
 				" trigger on table: %S", pTableName, 0);
 		goto trigger_cleanup;
diff --git a/src/box/sql/update.c b/src/box/sql/update.c
index 47500ec9e..bf413252d 100644
--- a/src/box/sql/update.c
+++ b/src/box/sql/update.c
@@ -163,7 +163,7 @@ sqlite3Update(Parse * pParse,		/* The parser context */
 	 */
 #ifndef SQLITE_OMIT_TRIGGER
 	pTrigger = sqlite3TriggersExist(pTab, TK_UPDATE, pChanges, &tmask);
-	isView = pTab->pSelect != 0;
+	isView = space_is_view(pTab);
 	assert(pTrigger || tmask == 0);
 #else
 #define pTrigger 0
diff --git a/src/box/sql/vdbeaux.c b/src/box/sql/vdbeaux.c
index 92bf9943b..773290b28 100644
--- a/src/box/sql/vdbeaux.c
+++ b/src/box/sql/vdbeaux.c
@@ -4717,7 +4717,7 @@ table_column_is_nullable(struct Table *tab, uint32_t column)
 {
 	/* Temporary hack: until Tarantoool's ephemeral spaces are on-boarded,
 	*  views are not handled properly in Tarantool as well. */
-	if (!(tab->tabFlags | TF_Ephemeral || tab->pSelect != NULL)) {
+	if (!(tab->tabFlags | TF_Ephemeral || space_is_view(tab))) {
 		uint32_t space_id = SQLITE_PAGENO_TO_SPACEID(tab->tnum);
 		struct space *space = space_cache_find(space_id);
 
diff --git a/src/box/sql/where.c b/src/box/sql/where.c
index ae1ca6d9f..af87d52bd 100644
--- a/src/box/sql/where.c
+++ b/src/box/sql/where.c
@@ -4511,7 +4511,8 @@ sqlite3WhereBegin(Parse * pParse,	/* The parser context */
 		pTabItem = &pTabList->a[pLevel->iFrom];
 		pTab = pTabItem->pTab;
 		pLoop = pLevel->pWLoop;
-		if ((pTab->tabFlags & TF_Ephemeral) != 0 || pTab->pSelect) {
+		if ((pTab->tabFlags & TF_Ephemeral) != 0 ||
+		    space_is_view(pTab)) {
 			/* Do nothing */
 		} else if ((pLoop->wsFlags & WHERE_IDX_ONLY) == 0 &&
 			   (wctrlFlags & WHERE_OR_SUBCLAUSE) == 0) {
diff --git a/test/sql/transition.result b/test/sql/transition.result
index 500fe85c6..7c4a2c813 100644
--- a/test/sql/transition.result
+++ b/test/sql/transition.result
@@ -112,10 +112,6 @@ box.sql.execute("SELECT COUNT(*) FROM foobar WHERE bar='cacodaemon'")
 ---
 - - [0]
 ...
--- cleanup
-box.space.FOOBAR:drop()
----
-...
 -- multi-index
 -- create space
 box.sql.execute("CREATE TABLE barfoo (bar, foo NUM PRIMARY KEY)")
@@ -188,9 +184,6 @@ box.sql.execute("CREATE TABLE rowid(x)")
 box.sql.execute("CREATE TABLE implicit_indices(a PRIMARY KEY,b,c,d UNIQUE)")
 ---
 ...
-box.space.IMPLICIT_INDICES:drop()
----
-...
 box.sql.execute("DROP TABLE implicit_indices")
 ---
 ...
diff --git a/test/sql/transition.test.lua b/test/sql/transition.test.lua
index 996e634ec..50ee7f569 100644
--- a/test/sql/transition.test.lua
+++ b/test/sql/transition.test.lua
@@ -33,9 +33,6 @@ box.sql.execute("SELECT COUNT(*) FROM foobar WHERE bar='cacodaemon'")
 box.sql.execute("DELETE FROM foobar WHERE bar='cacodaemon'")
 box.sql.execute("SELECT COUNT(*) FROM foobar WHERE bar='cacodaemon'")
 
--- cleanup
-box.space.FOOBAR:drop()
-
 -- multi-index
 
 -- create space
@@ -69,5 +66,4 @@ box.sql.execute("CREATE TABLE rowid(x)")
 
 -- create a table with implicit indices (used to SEGFAULT)
 box.sql.execute("CREATE TABLE implicit_indices(a PRIMARY KEY,b,c,d UNIQUE)")
-box.space.IMPLICIT_INDICES:drop()
 box.sql.execute("DROP TABLE implicit_indices")
-- 
2.15.1





More information about the Tarantool-patches mailing list