From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp52.i.mail.ru (smtp52.i.mail.ru [94.100.177.112]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 6E5BD46970E for ; Sun, 29 Dec 2019 15:27:50 +0300 (MSK) Received: by smtp52.i.mail.ru with esmtpa (envelope-from ) id 1ilXfi-00081J-3R for tarantool-patches@dev.tarantool.org; Sun, 29 Dec 2019 15:27:50 +0300 From: Chris Sosnin Date: Sun, 29 Dec 2019 15:27:49 +0300 Message-Id: <20191229122749.68537-1-k.sosnin@tarantool.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [Tarantool-patches] [PATCH] sql: fix recursion assertion List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: tarantool-patches@dev.tarantool.org The assertion in the body of region_truncate can fail because select statement does not start transaction and thus the GC is called too early. This leads to the corruption of fiber's region. This patch fixes this problem. Closes #4504 --- src/box/sql/parse.y | 2 + test/sql/gh-4504-recursion-assertion.result | 45 +++++++++++++++++++ test/sql/gh-4504-recursion-assertion.test.lua | 26 +++++++++++ 3 files changed, 73 insertions(+) create mode 100644 test/sql/gh-4504-recursion-assertion.result create mode 100644 test/sql/gh-4504-recursion-assertion.test.lua diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y index 89773eb1c..53ad43f81 100644 --- a/src/box/sql/parse.y +++ b/src/box/sql/parse.y @@ -457,6 +457,8 @@ cmd ::= select(X). { sqlSelect(pParse, X, &dest); else sql_expr_extract_select(pParse, X); + /* Instruct SQL to initate Tarantool's transaction. */ + pParse->initiateTTrans = true; sql_select_delete(pParse->db, X); } diff --git a/test/sql/gh-4504-recursion-assertion.result b/test/sql/gh-4504-recursion-assertion.result new file mode 100644 index 000000000..014df80ef --- /dev/null +++ b/test/sql/gh-4504-recursion-assertion.result @@ -0,0 +1,45 @@ +-- test-run result file version 2 +test_run = require('test_run').new() + | --- + | ... +engine = test_run:get_cfg('engine') + | --- + | ... + +-- +-- Start transaction prior to SELECT query +-- to make sure GC is called only after +-- the whole statement is executed +-- +box.schema.func.create('_C', { \ + language = 'LUA', \ + returns = 'unsigned', \ + body = [[ \ + function (i) \ + local m = box.space._space:select() \ + return 0 \ + end \ + ]], \ + param_list = {'integer'}, \ + exports = {'LUA', 'SQL'}, \ + is_sandboxed = false, \ + is_deterministic = true}) + | --- + | ... + +box.execute([[WITH RECURSIVE x AS (SELECT 0 AS q, 1 UNION ALL \ + SELECT q+1, _c(q) FROM x WHERE q < 1) SELECT * FROM x;]]) + | --- + | - metadata: + | - name: Q + | type: integer + | - name: '1' + | type: integer + | rows: + | - [0, 1] + | - [1, 0] + | ... + +box.schema.func.drop("_C") + | --- + | ... diff --git a/test/sql/gh-4504-recursion-assertion.test.lua b/test/sql/gh-4504-recursion-assertion.test.lua new file mode 100644 index 000000000..0ea5decad --- /dev/null +++ b/test/sql/gh-4504-recursion-assertion.test.lua @@ -0,0 +1,26 @@ +test_run = require('test_run').new() +engine = test_run:get_cfg('engine') + +-- +-- Start transaction prior to SELECT query +-- to make sure GC is called only after +-- the whole statement is executed +-- +box.schema.func.create('_C', { \ + language = 'LUA', \ + returns = 'unsigned', \ + body = [[ \ + function (i) \ + local m = box.space._space:select() \ + return 0 \ + end \ + ]], \ + param_list = {'integer'}, \ + exports = {'LUA', 'SQL'}, \ + is_sandboxed = false, \ + is_deterministic = true}) + +box.execute([[WITH RECURSIVE x AS (SELECT 0 AS q, 1 UNION ALL \ + SELECT q+1, _c(q) FROM x WHERE q < 1) SELECT * FROM x;]]) + +box.schema.func.drop("_C") -- 2.21.0 (Apple Git-122.2)