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 ACD9922EF2 for ; Thu, 3 May 2018 14:49:37 -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 pCtlnOK60dBB for ; Thu, 3 May 2018 14:49:37 -0400 (EDT) Received: from smtp29.i.mail.ru (smtp29.i.mail.ru [94.100.177.89]) (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 6A2E722EDB for ; Thu, 3 May 2018 14:49:35 -0400 (EDT) From: Nikita Pettik Subject: [tarantool-patches] [PATCH 3/4] sql: allow SAVEPOINT statement outside transaction Date: Thu, 3 May 2018 21:49:24 +0300 Message-Id: In-Reply-To: References: In-Reply-To: References: 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: tarantool-patches@freelists.org Cc: v.shpilevoy@tarantool.org, Nikita Pettik Before this patch, usage of SAVEPOINT statement outside transaction or inside transaction started in Lua, led to assertion fault. Now, failed assert is substituted with checks to test transaction status. Closes #3313 --- src/box/sql/vdbe.c | 8 +++++- test/sql/gh-3313-savepoints-outside-txn.result | 32 ++++++++++++++++++++++++ test/sql/gh-3313-savepoints-outside-txn.test.lua | 18 +++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 test/sql/gh-3313-savepoints-outside-txn.result create mode 100644 test/sql/gh-3313-savepoints-outside-txn.test.lua diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c index 1192fc399..6ea04901c 100644 --- a/src/box/sql/vdbe.c +++ b/src/box/sql/vdbe.c @@ -2867,7 +2867,13 @@ case OP_Savepoint: { Savepoint *pTmp; struct sql_txn *psql_txn = p->psql_txn; - assert(psql_txn); + if (psql_txn == NULL) { + assert(!box_txn()); + sqlite3VdbeError(p, "cannot process savepoint: " + "there is no active transaction"); + rc = SQLITE_ERROR; + goto abort_due_to_error; + } p1 = pOp->p1; zName = pOp->p4.z; diff --git a/test/sql/gh-3313-savepoints-outside-txn.result b/test/sql/gh-3313-savepoints-outside-txn.result new file mode 100644 index 000000000..702d3e815 --- /dev/null +++ b/test/sql/gh-3313-savepoints-outside-txn.result @@ -0,0 +1,32 @@ +test_run = require('test_run').new() +--- +... +test_run:cmd("setopt delimiter ';'") +--- +- true +... +-- These tests check that SQL savepoints properly work outside +-- transactions as well as inside transactions started in Lua. +-- +-- box.cfg() +box.sql.execute('SAVEPOINT t1;'); +--- +- error: 'cannot process savepoint: there is no active transaction' +... +box.sql.execute('RELEASE SAVEPOINT t1;'); +--- +- error: 'cannot process savepoint: there is no active transaction' +... +box.sql.execute('ROLLBACK TO SAVEPOINT t1;'); +--- +- error: 'cannot process savepoint: there is no active transaction' +... +box.begin() box.sql.execute('SAVEPOINT t1;') box.sql.execute('RELEASE SAVEPOINT t1;') box.commit(); +--- +... +box.begin() box.sql.execute('SAVEPOINT t1;') box.sql.execute('ROLLBACK TO t1;') box.commit(); +--- +... +box.begin() box.sql.execute('SAVEPOINT t1;') box.commit(); +--- +... diff --git a/test/sql/gh-3313-savepoints-outside-txn.test.lua b/test/sql/gh-3313-savepoints-outside-txn.test.lua new file mode 100644 index 000000000..61dd9a86b --- /dev/null +++ b/test/sql/gh-3313-savepoints-outside-txn.test.lua @@ -0,0 +1,18 @@ +test_run = require('test_run').new() +test_run:cmd("setopt delimiter ';'") + +-- These tests check that SQL savepoints properly work outside +-- transactions as well as inside transactions started in Lua. +-- + +-- box.cfg() + +box.sql.execute('SAVEPOINT t1;'); +box.sql.execute('RELEASE SAVEPOINT t1;'); +box.sql.execute('ROLLBACK TO SAVEPOINT t1;'); + +box.begin() box.sql.execute('SAVEPOINT t1;') box.sql.execute('RELEASE SAVEPOINT t1;') box.commit(); + +box.begin() box.sql.execute('SAVEPOINT t1;') box.sql.execute('ROLLBACK TO t1;') box.commit(); + +box.begin() box.sql.execute('SAVEPOINT t1;') box.commit(); -- 2.15.1