Tarantool development patches archive
 help / color / mirror / Atom feed
From: Kirill Shcherbatov <kshcherbatov@tarantool.org>
To: tarantool-patches@freelists.org, korablev@tarantool.org
Cc: Kirill Shcherbatov <kshcherbatov@tarantool.org>
Subject: [tarantool-patches] [PATCH v2 2/3] sql: disallow ck using non-persistent function
Date: Thu, 12 Sep 2019 11:06:42 +0300	[thread overview]
Message-ID: <2c39792c46f84fc38b0a3e2b50fb27fc1d229142.1568275504.git.kshcherbatov@tarantool.org> (raw)
In-Reply-To: <cover.1568275504.git.kshcherbatov@tarantool.org>

Each CK constraint object is a part of the database schema and
is restored during recovery. It is not possible if a CK
constraint uses some user-defined function inside. Thus we should
disallow non-persistent functions participate in ck constraints.

@TarantoolBot document
Title: disallow ck constraint using non-persistent function

Now CK constraints may use only persistent function and
predefined SQL built-in functions. In case of invalid definition
the error would be raised:

function myfunc(x) return x < 10 end
box.schema.func.create("MYFUNC", {exports = {'LUA', 'SQL'},
				  param_list = {'integer'}})
box.execute("CREATE TABLE t6(a  INT CHECK (myfunc(a)) primary key);");
---
- null
- 'Failed to create check constraint ''ck_unnamed_T6_1'': ck constraint
  could not
  use non-persistent function ''MYFUNC'''
---
 src/box/sql/resolve.c    | 10 ++++++++++
 test/sql/checks.result   | 43 ++++++++++++++++++++++++++++++++++++++--
 test/sql/checks.test.lua | 21 +++++++++++++++++++-
 3 files changed, 71 insertions(+), 3 deletions(-)

diff --git a/src/box/sql/resolve.c b/src/box/sql/resolve.c
index 6f625dc18..0d6f146fb 100644
--- a/src/box/sql/resolve.c
+++ b/src/box/sql/resolve.c
@@ -653,6 +653,16 @@ resolveExprStep(Walker * pWalker, Expr * pExpr)
 				pExpr->iTable = func->def->name[0] == 'u' ?
 						8388608 : 125829120;
 			}
+			if ((pNC->ncFlags & NC_IsCheck) != 0 &&
+			    func->def->body == NULL &&
+			    func->def->language != FUNC_LANGUAGE_SQL_BUILTIN) {
+				diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+					 "Check constraint can not invoke "
+					 "non-persistent function");
+				pParse->is_aborted = true;
+				pNC->nErr++;
+				return WRC_Abort;
+			}
 			assert(!func->def->is_deterministic ||
 			       (pNC->ncFlags & NC_IdxExpr) == 0);
 			if (func->def->is_deterministic)
diff --git a/test/sql/checks.result b/test/sql/checks.result
index 3f121226b..7939d46df 100644
--- a/test/sql/checks.result
+++ b/test/sql/checks.result
@@ -830,9 +830,48 @@ test_run:cmd('switch default')
 ---
 - true
 ...
-test_run:cmd('stop server test')
+--
+-- gh-4176: Can't recover if check constraint involves function.
+-- Make sure that non-persistent functions can't participate in
+-- check constraints, since after instance reboot they disappear
+-- and check constraint can't be created.
+--
+function myfunc(x) return x < 10 end
+---
+...
+box.schema.func.create("MYFUNC", {exports = {'LUA', 'SQL'}, param_list = {'integer'}})
+---
+...
+box.execute("CREATE TABLE t6(a  INT CHECK (myfunc(a)) primary key);");
+---
+- null
+- 'Failed to create check constraint ''ck_unnamed_T6_1'': Check constraint can not
+  invoke non-persistent function'
+...
+box.func.MYFUNC:drop()
+---
+...
+box.schema.func.create("MYFUNC", {exports = {'LUA', 'SQL'}, param_list = {'integer'}, body = "function(x) return x < 10 end"})
+---
+...
+box.execute("CREATE TABLE t6(a  INT CHECK (myfunc(a)) primary key);");
+---
+- row_count: 1
+...
+box.space.T6:insert({11})
+---
+- error: 'Check constraint failed ''ck_unnamed_T6_1'': myfunc(a)'
+...
+test_run:cmd("restart server default")
+box.space.T6:insert({11})
+---
+- error: 'Check constraint failed ''ck_unnamed_T6_1'': myfunc(a)'
+...
+box.space.T6:drop()
+---
+...
+box.func.MYFUNC:drop()
 ---
-- true
 ...
 test_run:cmd("clear filter")
 ---
diff --git a/test/sql/checks.test.lua b/test/sql/checks.test.lua
index 9716647d0..051c9ae38 100644
--- a/test/sql/checks.test.lua
+++ b/test/sql/checks.test.lua
@@ -273,6 +273,25 @@ box.execute("DROP TABLE test;")
 
 test_run = require('test_run').new()
 test_run:cmd('switch default')
-test_run:cmd('stop server test')
+
+--
+-- gh-4176: Can't recover if check constraint involves function.
+-- Make sure that non-persistent functions can't participate in
+-- check constraints, since after instance reboot they disappear
+-- and check constraint can't be created.
+--
+function myfunc(x) return x < 10 end
+box.schema.func.create("MYFUNC", {exports = {'LUA', 'SQL'}, param_list = {'integer'}})
+box.execute("CREATE TABLE t6(a  INT CHECK (myfunc(a)) primary key);");
+box.func.MYFUNC:drop()
+
+box.schema.func.create("MYFUNC", {exports = {'LUA', 'SQL'}, param_list = {'integer'}, body = "function(x) return x < 10 end"})
+box.execute("CREATE TABLE t6(a  INT CHECK (myfunc(a)) primary key);");
+box.space.T6:insert({11})
+test_run:cmd("restart server default")
+box.space.T6:insert({11})
+
+box.space.T6:drop()
+box.func.MYFUNC:drop()
 
 test_run:cmd("clear filter")
-- 
2.23.0

  parent reply	other threads:[~2019-09-12  8:06 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-09-12  8:06 [tarantool-patches] [PATCH v2 0/3] sql: fixes for ck constraints involving a function Kirill Shcherbatov
2019-09-12  8:06 ` [tarantool-patches] [PATCH v2 1/3] box: an ability to disable CK constraints Kirill Shcherbatov
2019-09-12 14:00   ` [tarantool-patches] " Nikita Pettik
2019-09-12 14:15     ` Kirill Shcherbatov
2019-09-12  8:06 ` Kirill Shcherbatov [this message]
2019-09-12 11:54   ` [tarantool-patches] Re: [PATCH v2 2/3] sql: disallow ck using non-persistent function Nikita Pettik
2019-09-12  8:06 ` [tarantool-patches] [PATCH v2 3/3] sql: use name instead of function pointer for UDF Kirill Shcherbatov
2019-09-12 12:13   ` [tarantool-patches] " Nikita Pettik

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2c39792c46f84fc38b0a3e2b50fb27fc1d229142.1568275504.git.kshcherbatov@tarantool.org \
    --to=kshcherbatov@tarantool.org \
    --cc=korablev@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --subject='Re: [tarantool-patches] [PATCH v2 2/3] sql: disallow ck using non-persistent function' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox