<div dir="ltr">As Alexander asked I've added table content checking in tests, fixed the causes of failing tests in Travis & fixed Nikita's remarks. Diff for the newer version is in the end.<br><br><div class="gmail_quote"><div dir="ltr">пт, 13 июл. 2018 г. в 5:15, n.pettik <<a href="mailto:korablev@tarantool.org" target="_blank">korablev@tarantool.org</a>>:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Nitpicking ffter module prefix (i.e. sql:) don’t use upper case for first word<br>
<br></blockquote><div> </div><div>Fixed.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
> Patch is aimed on making our sql closer to ANSI sql.<br>
<br>
Nitpicking: write SQL in upper case - it is an abbreviation.<br>
<br></blockquote><div><br></div><div>Fixed.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
> <br>
> With the patch applied only following commands can be used:<br>
> - "START TRANSACTION" to begin transaction.<br>
> - "COMMIT" to end transaction.<br>
> - "ROLLBACK" to rollback transaction without savepoints.<br>
> - "ROLLBACK TO .." to rollback transaction to savepoint.<br>
> <br>
> Closes #2164<br>
> ---<br>
> <br>
> diff --git a/extra/mkkeywordhash.c b/extra/mkkeywordhash.c<br>
> index 990c419..1ec1538 100644<br>
> --- a/extra/mkkeywordhash.c<br>
> +++ b/extra/mkkeywordhash.c<br>
> @@ -120,7 +120,7 @@ static Keyword aKeywordTable[] = {<br>
> { "ASC", "TK_ASC", ALWAYS, true },<br>
> { "AUTOINCREMENT", "TK_AUTOINCR", AUTOINCR, false },<br>
> { "BEFORE", "TK_BEFORE", TRIGGER, false },<br>
> - { "BEGIN", "TK_BEGIN", ALWAYS, true },<br>
> + { "BEGIN", "TK_BEGIN", TRIGGER, true },<br>
> { "BETWEEN", "TK_BETWEEN", ALWAYS, true },<br>
> { "BY", "TK_BY", ALWAYS, true },<br>
> { "CASCADE", "TK_CASCADE", FKEY, false },<br>
> @@ -210,6 +210,7 @@ static Keyword aKeywordTable[] = {<br>
> { "SAVEPOINT", "TK_SAVEPOINT", ALWAYS, true },<br>
> { "SELECT", "TK_SELECT", ALWAYS, true },<br>
> { "SET", "TK_SET", ALWAYS, true },<br>
> + { "START", "TK_START", ALWAYS, true },<br>
> { "TABLE", "TK_TABLE", ALWAYS, true },<br>
> { "THEN", "TK_THEN", ALWAYS, true },<br>
> { "TO", "TK_TO", ALWAYS, true },<br>
> @@ -274,7 +275,6 @@ static Keyword aKeywordTable[] = {<br>
> { "SIGNAL", "TK_STANDARD", RESERVED, true },<br>
> { "SMALLINT", "TK_ID", RESERVED, true },<br>
> { "SPECIFIC", "TK_STANDARD", RESERVED, true },<br>
> - { "START", "TK_STANDARD", RESERVED, true },<br>
> { "SYSTEM", "TK_STANDARD", RESERVED, true },<br>
> { "SQL", "TK_STANDARD", RESERVED, true },<br>
> { "USER", "TK_STANDARD", RESERVED, true },<br>
> diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c<br>
> index 3183e3d..42ab600 100644<br>
> --- a/src/box/sql/expr.c<br>
> +++ b/src/box/sql/expr.c<br>
> @@ -4835,11 +4835,13 @@ sqlite3ExprIfFalse(Parse * pParse, Expr * pExpr, int dest, int jumpIfNull)<br>
> * Assert()s verify that the computation is correct.<br>
> */<br>
> <br>
> - op = ((pExpr->op + (TK_ISNULL & 1)) ^ 1) - (TK_ISNULL & 1);<br>
> + if (pExpr->op >= TK_NE && pExpr->op <= TK_GE)<br>
> + op = ((pExpr->op + (TK_NE & 1)) ^ 1) - (TK_NE & 1);<br>
> + if (pExpr->op == TK_ISNULL || pExpr->op == TK_NOTNULL)<br>
> + op = ((pExpr->op + (TK_ISNULL & 1)) ^ 1) - (TK_ISNULL & 1);<br>
<br>
Please, leave comment how this code work.<br>
It isn't even close to be obvious, really.<br></blockquote><div><br></div><div>Fixed.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
> <br>
> /*<br>
> * Verify correct alignment of TK_ and OP_ constants.<br>
> - * Tokens TK_ISNULL and TK_NE shoud have the same parity.<br>
> */<br>
> assert(pExpr->op != TK_NE || op == OP_Eq);<br>
> assert(pExpr->op != TK_EQ || op == OP_Ne);<br>
> diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y<br>
> index b2940b7..e956dfc 100644<br>
> --- a/src/box/sql/parse.y<br>
> +++ b/src/box/sql/parse.y<br>
> @@ -147,13 +147,11 @@ cmdx ::= cmd.<br>
> ///////////////////// Begin and end transactions. ////////////////////////////<br>
> //<br>
> <br>
> -cmd ::= BEGIN trans_opt. {sql_transaction_begin(pParse);}<br>
> +cmd ::= START TRANSACTION trans_opt. {sql_transaction_begin(pParse);}<br>
> trans_opt ::= .<br>
> -trans_opt ::= TRANSACTION.<br>
> -trans_opt ::= TRANSACTION nm.<br>
> -cmd ::= COMMIT trans_opt. {sql_transaction_commit(pParse);}<br>
> -cmd ::= END trans_opt. {sql_transaction_commit(pParse);}<br>
> -cmd ::= ROLLBACK trans_opt. {sql_transaction_rollback(pParse);}<br>
> +trans_opt ::= nm.<br>
<br>
What is the point of named transactions, if rollback and commit<br>
don’t use name? I mean, now we ofc can’t use its name, but<br>
what does ANSI say?<br></blockquote><div><br></div><div>Fixed it.</div><div>Ansi only asks for <transaction characteristics> after 'START TRANSACTION'.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
> +cmd ::= COMMIT. {sql_transaction_commit(pParse);}<br>
> +cmd ::= ROLLBACK. {sql_transaction_rollback(pParse);}<br>
> <br>
> savepoint_opt ::= SAVEPOINT.<br>
> savepoint_opt ::= .<br>
> @@ -163,7 +161,7 @@ cmd ::= SAVEPOINT nm(X). {<br>
> cmd ::= RELEASE savepoint_opt nm(X). {<br>
> sqlite3Savepoint(pParse, SAVEPOINT_RELEASE, &X);<br>
> }<br>
> -cmd ::= ROLLBACK trans_opt TO savepoint_opt nm(X). {<br>
> +cmd ::= ROLLBACK TO savepoint_opt nm(X). {<br>
> sqlite3Savepoint(pParse, SAVEPOINT_ROLLBACK, &X);<br>
> }<br>
> <br>
> diff --git a/test/sql-tap/analyze3.test.lua b/test/sql-tap/analyze3.test.lua<br>
> index 26f8793..5079962 100755<br>
> --- a/test/sql-tap/analyze3.test.lua<br>
> +++ b/test/sql-tap/analyze3.test.lua<br>
> @@ -340,7 +340,7 @@ test:do_execsql_test(<br>
> "analyze3-1.3.1",<br>
> [[<br>
> CREATE TABLE t3(id INTEGER PRIMARY KEY, y TEXT, x INTEGER);<br>
> - BEGIN;<br>
> + START TRANSACTION;<br>
> INSERT INTO t3 SELECT id, y, x FROM t1;<br>
> COMMIT;<br>
> CREATE INDEX i3 ON t3(x);<br>
> @@ -465,7 +465,7 @@ test:do_test(<br>
> -- function()<br>
> -- test:execsql([[<br>
> -- PRAGMA case_sensitive_like=off;<br>
> --- BEGIN;<br>
> +-- START TRANSACTION;<br>
<br>
I guess, you can remove it at all. It makes no sense to add dead code.<br>
<br>
> --- a/test/sql-tap/in1.test.lua<br>
> +++ b/test/sql-tap/in1.test.lua<br>
> @@ -26,7 +26,7 @@ test:do_test(<br>
> function()<br>
> test:execsql [[<br>
> CREATE TABLE t1(a PRIMARY KEY, b);<br>
> - BEGIN;<br>
> + START TRANSACTION;<br>
> ]]<br>
> -- for _ in X(0, "X!for", [=[["set i 1","$i<=10","incr i"]]=]) do<br>
> local j = 1<br>
> @@ -1073,7 +1073,7 @@ test:do_execsql_test(<br>
> -- MUST_WORK_TEST<br>
> -- do_test in-13.14 {<br>
> -- execsql {<br>
> --- BEGIN TRANSACTION;<br>
> +-- START TRANSACTION;<br>
<br>
The same is here and in other places.<br>
<br></blockquote><div><br></div><div>Fixed. </div><div><br></div><div><div>diff --git a/extra/lempar.c b/extra/lempar.c</div><div>index 00fd79c..d043e39 100644</div><div>--- a/extra/lempar.c</div><div>+++ b/extra/lempar.c</div><div>@@ -336,8 +336,8 @@ void *ParseAlloc(void *(*mallocProc)(YYMALLOCARGTYPE)){</div><div> if( pParser ){</div><div> #ifdef YYTRACKMAXSTACKDEPTH</div><div> pParser->yyhwm = 0;</div><div>- pParser->is_fallback_failed = false;</div><div> #endif</div><div>+ pParser->is_fallback_failed = false;</div><div> #if YYSTACKDEPTH<=0</div><div> pParser->yytos = NULL;</div><div> pParser->yystack = NULL;</div><div>diff --git a/extra/mkkeywordhash.c b/extra/mkkeywordhash.c</div><div>index 990c419..1ec1538 100644</div><div>--- a/extra/mkkeywordhash.c</div><div>+++ b/extra/mkkeywordhash.c</div><div>@@ -120,7 +120,7 @@ static Keyword aKeywordTable[] = {</div><div> { "ASC", "TK_ASC", ALWAYS, true },</div><div> { "AUTOINCREMENT", "TK_AUTOINCR", AUTOINCR, false },</div><div> { "BEFORE", "TK_BEFORE", TRIGGER, false },</div><div>- { "BEGIN", "TK_BEGIN", ALWAYS, true },</div><div>+ { "BEGIN", "TK_BEGIN", TRIGGER, true },</div><div> { "BETWEEN", "TK_BETWEEN", ALWAYS, true },</div><div> { "BY", "TK_BY", ALWAYS, true },</div><div> { "CASCADE", "TK_CASCADE", FKEY, false },</div><div>@@ -210,6 +210,7 @@ static Keyword aKeywordTable[] = {</div><div> { "SAVEPOINT", "TK_SAVEPOINT", ALWAYS, true },</div><div> { "SELECT", "TK_SELECT", ALWAYS, true },</div><div> { "SET", "TK_SET", ALWAYS, true },</div><div>+ { "START", "TK_START", ALWAYS, true },</div><div> { "TABLE", "TK_TABLE", ALWAYS, true },</div><div> { "THEN", "TK_THEN", ALWAYS, true },</div><div> { "TO", "TK_TO", ALWAYS, true },</div><div>@@ -274,7 +275,6 @@ static Keyword aKeywordTable[] = {</div><div> { "SIGNAL", "TK_STANDARD", RESERVED, true },</div><div> { "SMALLINT", "TK_ID", RESERVED, true },</div><div> { "SPECIFIC", "TK_STANDARD", RESERVED, true },</div><div>- { "START", "TK_STANDARD", RESERVED, true },</div><div> { "SYSTEM", "TK_STANDARD", RESERVED, true },</div><div> { "SQL", "TK_STANDARD", RESERVED, true },</div><div> { "USER", "TK_STANDARD", RESERVED, true },</div><div>diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c</div><div>index b1650cf..b26728d 100644</div><div>--- a/src/box/sql/expr.c</div><div>+++ b/src/box/sql/expr.c</div><div>@@ -4826,23 +4826,32 @@ sqlite3ExprIfFalse(Parse * pParse, Expr * pExpr, int dest, int jumpIfNull)</div><div> <span style="white-space:pre-wrap"> </span> * TK_EQ OP_Ne</div><div> <span style="white-space:pre-wrap"> </span> * TK_GT OP_Le</div><div> <span style="white-space:pre-wrap"> </span> * TK_LE OP_Gt</div><div>-<span style="white-space:pre-wrap"> </span> * TK_GE OP_Lt</div><div> <span style="white-space:pre-wrap"> </span> * TK_LT OP_Ge</div><div>+<span style="white-space:pre-wrap"> </span> * TK_GE OP_Lt</div><div> <span style="white-space:pre-wrap"> </span> * ... ...</div><div> <span style="white-space:pre-wrap"> </span> * TK_ISNULL OP_NotNull</div><div> <span style="white-space:pre-wrap"> </span> * TK_NOTNULL OP_IsNull</div><div> <span style="white-space:pre-wrap"> </span> *</div><div>-<span style="white-space:pre-wrap"> </span> * For other values of pExpr->op, op is undefined and unused.</div><div>-<span style="white-space:pre-wrap"> </span> * The value of TK_ and OP_ constants are arranged such that we</div><div>-<span style="white-space:pre-wrap"> </span> * can compute the mapping above using the following expression.</div><div>+<span style="white-space:pre-wrap"> </span> * For other values of pExpr->op, op is undefined</div><div>+<span style="white-space:pre-wrap"> </span> * and unused. The value of TK_ and OP_ constants</div><div>+<span style="white-space:pre-wrap"> </span> * are arranged such that we can compute the mapping</div><div>+<span style="white-space:pre-wrap"> </span> * above using the following expression. The idea</div><div>+<span style="white-space:pre-wrap"> </span> * is that both for OP_'s and TK_'s the first elements</div><div>+<span style="white-space:pre-wrap"> </span> * in the given mapping ranges of codes and tokens are</div><div>+<span style="white-space:pre-wrap"> </span> * 'Not equal' and 'Is null'. Moreover the 'excluding'</div><div>+<span style="white-space:pre-wrap"> </span> * ones (like 'Greater than' and 'Lower than or Equal')</div><div>+<span style="white-space:pre-wrap"> </span> * are paired and follow one each other, hence have n</div><div>+<span style="white-space:pre-wrap"> </span> * and n + 1 numbers.</div><div> <span style="white-space:pre-wrap"> </span> * Assert()s verify that the computation is correct.</div><div> <span style="white-space:pre-wrap"> </span> */</div><div> </div><div>-<span style="white-space:pre-wrap"> </span>op = ((pExpr->op + (TK_ISNULL & 1)) ^ 1) - (TK_ISNULL & 1);</div><div>+<span style="white-space:pre-wrap"> </span>if (pExpr->op >= TK_NE && pExpr->op <= TK_GE)</div><div>+<span style="white-space:pre-wrap"> </span>op = ((pExpr->op + (TK_NE & 1)) ^ 1) - (TK_NE & 1);</div><div>+<span style="white-space:pre-wrap"> </span>if (pExpr->op == TK_ISNULL || pExpr->op == TK_NOTNULL)</div><div>+<span style="white-space:pre-wrap"> </span>op = ((pExpr->op + (TK_ISNULL & 1)) ^ 1) - (TK_ISNULL & 1);</div><div> </div><div> <span style="white-space:pre-wrap"> </span>/*</div><div> <span style="white-space:pre-wrap"> </span> * Verify correct alignment of TK_ and OP_ constants.</div><div>-<span style="white-space:pre-wrap"> </span> * Tokens TK_ISNULL and TK_NE shoud have the same parity.</div><div> <span style="white-space:pre-wrap"> </span> */</div><div> <span style="white-space:pre-wrap"> </span>assert(pExpr->op != TK_NE || op == OP_Eq);</div><div> <span style="white-space:pre-wrap"> </span>assert(pExpr->op != TK_EQ || op == OP_Ne);</div><div>diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y</div><div>index ac935fd..b4f11e5 100644</div><div>--- a/src/box/sql/parse.y</div><div>+++ b/src/box/sql/parse.y</div><div>@@ -147,13 +147,9 @@ cmdx ::= cmd.</div><div> ///////////////////// Begin and end transactions. ////////////////////////////</div><div> //</div><div> </div><div>-cmd ::= BEGIN trans_opt. {sql_transaction_begin(pParse);}</div><div>-trans_opt ::= .</div><div>-trans_opt ::= TRANSACTION.</div><div>-trans_opt ::= TRANSACTION nm.</div><div>-cmd ::= COMMIT trans_opt. {sql_transaction_commit(pParse);}</div><div>-cmd ::= END trans_opt. {sql_transaction_commit(pParse);}</div><div>-cmd ::= ROLLBACK trans_opt. {sql_transaction_rollback(pParse);}</div><div>+cmd ::= START TRANSACTION. {sql_transaction_begin(pParse);}</div><div>+cmd ::= COMMIT. {sql_transaction_commit(pParse);}</div><div>+cmd ::= ROLLBACK. {sql_transaction_rollback(pParse);}</div><div> </div><div> savepoint_opt ::= SAVEPOINT.</div><div> savepoint_opt ::= .</div><div>@@ -163,7 +159,7 @@ cmd ::= SAVEPOINT nm(X). {</div><div> cmd ::= RELEASE savepoint_opt nm(X). {</div><div> sqlite3Savepoint(pParse, SAVEPOINT_RELEASE, &X);</div><div> }</div><div>-cmd ::= ROLLBACK trans_opt TO savepoint_opt nm(X). {</div><div>+cmd ::= ROLLBACK TO savepoint_opt nm(X). {</div><div> sqlite3Savepoint(pParse, SAVEPOINT_ROLLBACK, &X);</div><div> }</div><div>diff --git a/test/sql-tap/start-transaction.test.lua b/test/sql-tap/start-transaction.test.lua</div><div>new file mode 100755</div><div>index 0000000..eece4cd</div><div>--- /dev/null</div><div>+++ b/test/sql-tap/start-transaction.test.lua</div><div>@@ -0,0 +1,266 @@</div><div>+#!/usr/bin/env tarantool</div><div>+test = require("sqltester")</div><div>+test:plan(21)</div><div>+</div><div>+test:do_catchsql_test(</div><div>+<span style="white-space:pre-wrap"> </span>"start-transaction-1.0",</div><div>+<span style="white-space:pre-wrap"> </span>[[</div><div>+<span style="white-space:pre-wrap"> </span>CREATE TABLE IF NOT EXISTS t(id int PRIMARY KEY);</div><div>+<span style="white-space:pre-wrap"> </span>DELETE FROM t;</div><div>+<span style="white-space:pre-wrap"> </span>BEGIN;</div><div>+<span style="white-space:pre-wrap"> </span>INSERT INTO t VALUES (1);</div><div>+<span style="white-space:pre-wrap"> </span>INSERT INTO t VALUES (2);</div><div>+<span style="white-space:pre-wrap"> </span>COMMIT;</div><div>+<span style="white-space:pre-wrap"> </span>]], {</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.0></div><div>+<span style="white-space:pre-wrap"> </span>1, "near \"BEGIN\": syntax error"</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.0></div><div>+<span style="white-space:pre-wrap"> </span>})</div><div>+</div><div>+test:do_execsql_test(</div><div>+<span style="white-space:pre-wrap"> </span>"start-transaction-1.1",</div><div>+<span style="white-space:pre-wrap"> </span>[[</div><div>+<span style="white-space:pre-wrap"> </span>SELECT * FROM t;</div><div>+<span style="white-space:pre-wrap"> </span>]], {</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.1></div><div>+</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.1></div><div>+<span style="white-space:pre-wrap"> </span>})</div><div>+</div><div>+test:do_catchsql_test(</div><div>+<span style="white-space:pre-wrap"> </span>"start-transaction-1.2",</div><div>+<span style="white-space:pre-wrap"> </span>[[</div><div>+<span style="white-space:pre-wrap"> </span>CREATE TABLE IF NOT EXISTS t(id int primary key);</div><div>+<span style="white-space:pre-wrap"> </span>delete from t;</div><div>+<span style="white-space:pre-wrap"> </span>BEGIN TRANSACTION;</div><div>+<span style="white-space:pre-wrap"> </span>INSERT INTO t VALUES (1);</div><div>+<span style="white-space:pre-wrap"> </span>INSERT INTO t VALUES (2);</div><div>+<span style="white-space:pre-wrap"> </span>COMMIT;</div><div>+<span style="white-space:pre-wrap"> </span>]], {</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.1></div><div>+<span style="white-space:pre-wrap"> </span>1, "near \"BEGIN\": syntax error"</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.1></div><div>+<span style="white-space:pre-wrap"> </span>})</div><div>+</div><div>+test:do_execsql_test(</div><div>+<span style="white-space:pre-wrap"> </span>"start-transaction-1.3",</div><div>+<span style="white-space:pre-wrap"> </span>[[</div><div>+<span style="white-space:pre-wrap"> </span>SELECT * FROM t;</div><div>+<span style="white-space:pre-wrap"> </span>]], {</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.3></div><div>+</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.3></div><div>+<span style="white-space:pre-wrap"> </span>})</div><div>+</div><div>+test:do_catchsql_test(</div><div>+<span style="white-space:pre-wrap"> </span>"start-transaction-1.4",</div><div>+<span style="white-space:pre-wrap"> </span>[[</div><div>+<span style="white-space:pre-wrap"> </span>DELETE FROM t;</div><div>+<span style="white-space:pre-wrap"> </span>START TRANSACTION;</div><div>+<span style="white-space:pre-wrap"> </span>INSERT INTO t VALUES (1);</div><div>+<span style="white-space:pre-wrap"> </span>INSERT INTO t VALUES (2);</div><div>+<span style="white-space:pre-wrap"> </span>COMMIT;</div><div>+<span style="white-space:pre-wrap"> </span>]], {</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.4></div><div>+<span style="white-space:pre-wrap"> </span>0</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.4></div><div>+<span style="white-space:pre-wrap"> </span>})</div><div>+</div><div>+test:do_execsql_test(</div><div>+<span style="white-space:pre-wrap"> </span>"start-transaction-1.5",</div><div>+<span style="white-space:pre-wrap"> </span>[[</div><div>+<span style="white-space:pre-wrap"> </span>SELECT * FROM t;</div><div>+<span style="white-space:pre-wrap"> </span>]], {</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.5></div><div>+<span style="white-space:pre-wrap"> </span>1, 2</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.5></div><div>+<span style="white-space:pre-wrap"> </span>})</div><div>+</div><div>+test:do_catchsql_test(</div><div>+<span style="white-space:pre-wrap"> </span>"start-transaction-1.6",</div><div>+<span style="white-space:pre-wrap"> </span>[[</div><div>+<span style="white-space:pre-wrap"> </span>DELETE FROM t;</div><div>+<span style="white-space:pre-wrap"> </span>START TRANSACTION;</div><div>+<span style="white-space:pre-wrap"> </span>INSERT INTO t VALUES (1);</div><div>+<span style="white-space:pre-wrap"> </span>INSERT INTO t VALUES (2);</div><div>+<span style="white-space:pre-wrap"> </span>COMMIT TRANSACTION;</div><div>+<span style="white-space:pre-wrap"> </span>]], {</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.6></div><div>+<span style="white-space:pre-wrap"> </span>1, "keyword \"TRANSACTION\" is reserved"</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.6></div><div>+<span style="white-space:pre-wrap"> </span>})</div><div>+</div><div>+test:do_execsql_test(</div><div>+<span style="white-space:pre-wrap"> </span>"start-transaction-1.7",</div><div>+<span style="white-space:pre-wrap"> </span>[[</div><div>+<span style="white-space:pre-wrap"> </span>COMMIT;</div><div>+<span style="white-space:pre-wrap"> </span>SELECT * FROM t;</div><div>+<span style="white-space:pre-wrap"> </span>]], {</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.7></div><div>+<span style="white-space:pre-wrap"> </span>1, 2</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.7></div><div>+<span style="white-space:pre-wrap"> </span>})</div><div>+</div><div>+test:do_catchsql_test(</div><div>+<span style="white-space:pre-wrap"> </span>"start-transaction-1.8",</div><div>+<span style="white-space:pre-wrap"> </span>[[</div><div>+<span style="white-space:pre-wrap"> </span>DELETE FROM t;</div><div>+<span style="white-space:pre-wrap"> </span>START TRANSACTION;</div><div>+<span style="white-space:pre-wrap"> </span>INSERT INTO t VALUES (1);</div><div>+<span style="white-space:pre-wrap"> </span>INSERT INTO t VALUES (2);</div><div>+<span style="white-space:pre-wrap"> </span>END;</div><div>+<span style="white-space:pre-wrap"> </span>]], {</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.8></div><div>+<span style="white-space:pre-wrap"> </span>1, "keyword \"END\" is reserved"</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.8></div><div>+<span style="white-space:pre-wrap"> </span>})</div><div>+</div><div>+test:do_execsql_test(</div><div>+<span style="white-space:pre-wrap"> </span>"start-transaction-1.9",</div><div>+<span style="white-space:pre-wrap"> </span>[[</div><div>+<span style="white-space:pre-wrap"> </span>COMMIT;</div><div>+<span style="white-space:pre-wrap"> </span>SELECT * FROM t;</div><div>+<span style="white-space:pre-wrap"> </span>]], {</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.9></div><div>+<span style="white-space:pre-wrap"> </span>1, 2</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.9></div><div>+<span style="white-space:pre-wrap"> </span>})</div><div>+</div><div>+test:do_catchsql_test(</div><div>+<span style="white-space:pre-wrap"> </span>"start-transaction-1.10",</div><div>+<span style="white-space:pre-wrap"> </span>[[</div><div>+<span style="white-space:pre-wrap"> </span>DELETE FROM t;</div><div>+<span style="white-space:pre-wrap"> </span>START TRANSACTION;</div><div>+<span style="white-space:pre-wrap"> </span>INSERT INTO t VALUES (1);</div><div>+<span style="white-space:pre-wrap"> </span>INSERT INTO t VALUES (2);</div><div>+<span style="white-space:pre-wrap"> </span>END TRANSACTION;</div><div>+<span style="white-space:pre-wrap"> </span>]], {</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.10></div><div>+<span style="white-space:pre-wrap"> </span>1, "keyword \"END\" is reserved"</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.10></div><div>+<span style="white-space:pre-wrap"> </span>})</div><div>+</div><div>+test:do_execsql_test(</div><div>+<span style="white-space:pre-wrap"> </span>"start-transaction-1.11",</div><div>+<span style="white-space:pre-wrap"> </span>[[</div><div>+<span style="white-space:pre-wrap"> </span>COMMIT;</div><div>+<span style="white-space:pre-wrap"> </span>SELECT * FROM t;</div><div>+<span style="white-space:pre-wrap"> </span>]], {</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.11></div><div>+<span style="white-space:pre-wrap"> </span>1, 2</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.11></div><div>+<span style="white-space:pre-wrap"> </span>})</div><div>+</div><div>+test:do_catchsql_test(</div><div>+<span style="white-space:pre-wrap"> </span>"start-transaction-1.12",</div><div>+<span style="white-space:pre-wrap"> </span>[[</div><div>+<span style="white-space:pre-wrap"> </span>DELETE FROM t;</div><div>+<span style="white-space:pre-wrap"> </span>START TRANSACTION;</div><div>+<span style="white-space:pre-wrap"> </span>INSERT INTO t VALUES (1);</div><div>+<span style="white-space:pre-wrap"> </span>INSERT INTO t VALUES (2);</div><div>+<span style="white-space:pre-wrap"> </span>ROLLBACK;</div><div>+<span style="white-space:pre-wrap"> </span>]], {</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.12></div><div>+<span style="white-space:pre-wrap"> </span>0</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.12></div><div>+<span style="white-space:pre-wrap"> </span>})</div><div>+</div><div>+test:do_execsql_test(</div><div>+<span style="white-space:pre-wrap"> </span>"start-transaction-1.13",</div><div>+<span style="white-space:pre-wrap"> </span>[[</div><div>+<span style="white-space:pre-wrap"> </span>SELECT * FROM t;</div><div>+<span style="white-space:pre-wrap"> </span>]], {</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.13></div><div>+</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.13></div><div>+<span style="white-space:pre-wrap"> </span>})</div><div>+</div><div>+test:do_catchsql_test(</div><div>+<span style="white-space:pre-wrap"> </span>"start-transaction-1.14",</div><div>+<span style="white-space:pre-wrap"> </span>[[</div><div>+<span style="white-space:pre-wrap"> </span>START TRANSACTION;</div><div>+<span style="white-space:pre-wrap"> </span>INSERT INTO t VALUES (1);</div><div>+<span style="white-space:pre-wrap"> </span>INSERT INTO t VALUES (2);</div><div>+<span style="white-space:pre-wrap"> </span>ROLLBACK TRANSACTION;</div><div>+<span style="white-space:pre-wrap"> </span>COMMIT;</div><div>+<span style="white-space:pre-wrap"> </span>]], {</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.14></div><div>+<span style="white-space:pre-wrap"> </span>1, "keyword \"TRANSACTION\" is reserved"</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.14></div><div>+<span style="white-space:pre-wrap"> </span>})</div><div>+</div><div>+test:do_execsql_test(</div><div>+<span style="white-space:pre-wrap"> </span>"start-transaction-1.15",</div><div>+<span style="white-space:pre-wrap"> </span>[[</div><div>+<span style="white-space:pre-wrap"> </span>COMMIT;</div><div>+<span style="white-space:pre-wrap"> </span>SELECT * FROM t;</div><div>+<span style="white-space:pre-wrap"> </span>]], {</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.15></div><div>+<span style="white-space:pre-wrap"> </span>1, 2</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.15></div><div>+<span style="white-space:pre-wrap"> </span>})</div><div>+</div><div>+test:do_catchsql_test(</div><div>+<span style="white-space:pre-wrap"> </span>"start-transaction-1.16",</div><div>+<span style="white-space:pre-wrap"> </span>[[</div><div>+<span style="white-space:pre-wrap"> </span>DELETE FROM t;</div><div>+<span style="white-space:pre-wrap"> </span>START TRANSACTION;</div><div>+<span style="white-space:pre-wrap"> </span>INSERT INTO t VALUES (1);</div><div>+<span style="white-space:pre-wrap"> </span>SAVEPOINT s1;</div><div>+<span style="white-space:pre-wrap"> </span>INSERT INTO t VALUES (2);</div><div>+<span style="white-space:pre-wrap"> </span>ROLLBACK TO s1;</div><div>+<span style="white-space:pre-wrap"> </span>COMMIT;</div><div>+<span style="white-space:pre-wrap"> </span>]], {</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.16></div><div>+<span style="white-space:pre-wrap"> </span>0</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.16></div><div>+<span style="white-space:pre-wrap"> </span>})</div><div>+</div><div>+test:do_execsql_test(</div><div>+<span style="white-space:pre-wrap"> </span>"start-transaction-1.17",</div><div>+<span style="white-space:pre-wrap"> </span>[[</div><div>+<span style="white-space:pre-wrap"> </span>SELECT * FROM t;</div><div>+<span style="white-space:pre-wrap"> </span>]], {</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.17></div><div>+<span style="white-space:pre-wrap"> </span>1</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.17></div><div>+<span style="white-space:pre-wrap"> </span>})</div><div>+</div><div>+test:do_catchsql_test(</div><div>+<span style="white-space:pre-wrap"> </span>"start-transaction-1.18",</div><div>+<span style="white-space:pre-wrap"> </span>[[</div><div>+<span style="white-space:pre-wrap"> </span>DELETE FROM t;</div><div>+<span style="white-space:pre-wrap"> </span>START TRANSACTION;</div><div>+<span style="white-space:pre-wrap"> </span>INSERT INTO t VALUES (1);</div><div>+<span style="white-space:pre-wrap"> </span>SAVEPOINT s1;</div><div>+<span style="white-space:pre-wrap"> </span>INSERT INTO t VALUES (2);</div><div>+<span style="white-space:pre-wrap"> </span>ROLLBACK TRANSACTION TO s1;</div><div>+<span style="white-space:pre-wrap"> </span>COMMIT;</div><div>+<span style="white-space:pre-wrap"> </span>]], {</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.18></div><div>+<span style="white-space:pre-wrap"> </span>1, "keyword \"TRANSACTION\" is reserved"</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.18></div><div>+<span style="white-space:pre-wrap"> </span>})</div><div>+</div><div>+test:do_execsql_test(</div><div>+<span style="white-space:pre-wrap"> </span>"start-transaction-1.19",</div><div>+<span style="white-space:pre-wrap"> </span>[[</div><div>+<span style="white-space:pre-wrap"> </span>COMMIT;</div><div>+<span style="white-space:pre-wrap"> </span>SELECT * FROM t;</div><div>+<span style="white-space:pre-wrap"> </span>]], {</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.19></div><div>+<span style="white-space:pre-wrap"> </span>1, 2</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.19></div><div>+<span style="white-space:pre-wrap"> </span>})</div><div>+</div><div>+test:do_execsql_test(</div><div>+<span style="white-space:pre-wrap"> </span>"start-transaction-1.20",</div><div>+<span style="white-space:pre-wrap"> </span>[[</div><div>+<span style="white-space:pre-wrap"> </span>drop table t;</div><div>+<span style="white-space:pre-wrap"> </span>]], {</div><div>+<span style="white-space:pre-wrap"> </span>-- <start0transaction-1.20></div><div>+</div><div>+<span style="white-space:pre-wrap"> </span>-- <start-transaction-1.20></div><div>+<span style="white-space:pre-wrap"> </span>})</div><div>+</div><div>+test:finish_test()</div></div></div></div>