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 v3 3/3] box: user-friendly interface to manage ck constraints
Date: Tue, 16 Apr 2019 16:51:40 +0300	[thread overview]
Message-ID: <0511eb70cd35f5a3b8fc527e5e08814f3188eb15.1555420166.git.kshcherbatov@tarantool.org> (raw)
In-Reply-To: <cover.1555420166.git.kshcherbatov@tarantool.org>

@TarantoolBot document
Title: check constraint for LUA space

The check constraint is a type of integrity constraint which
specifies a requirement that must be met by tuple before it
is inserted into space. The constraint result must be predictable.

Now it is possible to create ck constraints only for empty space
having format. Constraint expression is a string that defines
relations between top-level tuple fields.
Take into account that all names are converted to an uppercase
before resolve(like SQL does), use \" sign for names of fields
that were created not with SQL.

To create a new CK constraint for a space, use
s = box.schema.create_space('person')
_ = s:create_index('pk', {parts = {1, 'string'}})
s:format({{name='name', type='string'}, {name='age', type='integer'},
{name='experience', type='integer'}})
s:ck_constraint({'physics', '\"age\" > 14 and \"experience\" <
\"age\"'})
s:insert({"James Bond", 36, 36})
---
- error: 'Check constraint failed ''physics'': "age" > 14 and
  "experience" < "age"'
...
s:insert("James Bond", 36, 16) -- success
s:insert({"Bobby", 6, 0})
---
- error: 'Check constraint failed ''physics'': "age" > 14 and
  "experience" < "age"'
...

To list all ck constraints assosiated with space,
s:ck_constraint()

To replace ck constraint, use following syntax:
s:ck_constraint({'physics', '\"experience\" < \"age\"'}, {'physics'})
s:insert({"Bobby", 6, 0}) -- success

To drop ck constraint, use:
s:ck_constraint(nil, {'physics', '\"experience\" < \"age\"'})
---
 src/box/lua/schema.lua   | 19 ++++++++++
 test/sql/checks.result   | 78 ++++++++++++++++++++++++++++++++++++++++
 test/sql/checks.test.lua | 29 +++++++++++++++
 3 files changed, 126 insertions(+)

diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua
index e01f500e6..69aebc01c 100644
--- a/src/box/lua/schema.lua
+++ b/src/box/lua/schema.lua
@@ -1533,6 +1533,25 @@ space_mt.auto_increment = function(space, tuple)
     table.insert(tuple, 1, max + 1)
     return space:insert(tuple)
 end
+-- Manage space ck constraints
+space_mt.ck_constraint = function(space, new, old)
+    check_space_arg(space, 'ck_constraint')
+    if new == nil and old == nil then
+        return box.space._ck_constraint.index['space_id']:select({space.id})
+    end
+    if new == nil then
+        box.space._ck_constraint:delete({old[1], space.id})
+    else
+        local msg = "Usage: space:ck_constraint({name, expr_str} | nil, " ..
+                    "[{name, expr_str} | nil])"
+        if old ~= nil and old[1] ~= new[1] then
+            box.error(box.error.PROC_LUA,
+                      "Error: old and new CK constraint names must " ..
+                      "coincide. " .. msg)
+        end
+        return box.space._ck_constraint:replace({new[1], space.id, new[2]})
+    end
+end
 
 space_mt.pairs = function(space, key, opts)
     check_space_arg(space, 'pairs')
diff --git a/test/sql/checks.result b/test/sql/checks.result
index 0dd5d820f..301140988 100644
--- a/test/sql/checks.result
+++ b/test/sql/checks.result
@@ -395,3 +395,81 @@ s:replace({2, 1, 3})
 s:drop()
 ---
 ...
+-- Test ck constraints user-friendly creation interface
+s1 = box.schema.create_space('test1')
+---
+...
+_ = s1:create_index('pk')
+---
+...
+s1:format({{name='X', type='any'}, {name='Y', type='integer'}})
+---
+...
+s2 = box.schema.create_space('test2')
+---
+...
+_ = s2:create_index('pk')
+---
+...
+s2:format({{name='X', type='any'}, {name='Y', type='integer'}})
+---
+...
+s1:ck_constraint({'physics', 'X < Y'})
+---
+- ['physics', 520, 'X < Y']
+...
+s1:ck_constraint({'greater', 'X > 10'})
+---
+- ['greater', 520, 'X > 10']
+...
+s2:ck_constraint({'physics', 'X > Y'})
+---
+- ['physics', 521, 'X > Y']
+...
+s1:ck_constraint()
+---
+- - ['greater', 520, 'X > 10']
+  - ['physics', 520, 'X < Y']
+...
+s2:ck_constraint()
+---
+- - ['physics', 521, 'X > Y']
+...
+s1:ck_constraint({'greater', 'X > 20'}, {'greater'})
+---
+- ['greater', 520, 'X > 20']
+...
+s2:ck_constraint({'greater', 'X > 20'}, {'greater'})
+---
+- ['greater', 521, 'X > 20']
+...
+s1:ck_constraint()
+---
+- - ['greater', 520, 'X > 20']
+  - ['physics', 520, 'X < Y']
+...
+s2:ck_constraint()
+---
+- - ['greater', 521, 'X > 20']
+  - ['physics', 521, 'X > Y']
+...
+s1:ck_constraint(nil, {'greater'})
+---
+...
+s2:ck_constraint(nil, {'greater'})
+---
+...
+s1:ck_constraint()
+---
+- - ['physics', 520, 'X < Y']
+...
+s2:ck_constraint()
+---
+- - ['physics', 521, 'X > Y']
+...
+s1:drop()
+---
+...
+s2:drop()
+---
+...
diff --git a/test/sql/checks.test.lua b/test/sql/checks.test.lua
index 2652f3b7d..c2c5275e5 100644
--- a/test/sql/checks.test.lua
+++ b/test/sql/checks.test.lua
@@ -134,3 +134,32 @@ s:update({2}, {{'+', 2, 3}})
 s:update({2}, {{'+', 2, 3}, {'+', 3, 3}})
 s:replace({2, 1, 3})
 s:drop()
+
+-- Test ck constraints user-friendly creation interface
+s1 = box.schema.create_space('test1')
+_ = s1:create_index('pk')
+s1:format({{name='X', type='any'}, {name='Y', type='integer'}})
+s2 = box.schema.create_space('test2')
+_ = s2:create_index('pk')
+s2:format({{name='X', type='any'}, {name='Y', type='integer'}})
+s1:ck_constraint({'physics', 'X < Y'})
+s1:ck_constraint({'greater', 'X > 10'})
+s2:ck_constraint({'physics', 'X > Y'})
+s1:ck_constraint()
+s2:ck_constraint()
+s1:ck_constraint({'greater', 'X > 20'}, {'greater'})
+s2:ck_constraint({'greater', 'X > 20'}, {'greater'})
+s1:ck_constraint()
+s2:ck_constraint()
+s1:insert({2, 1})
+s1:insert({21, 20})
+s2:insert({1, 2})
+s2:insert({21, 22})
+s1:ck_constraint(nil, {'greater'})
+s2:ck_constraint(nil, {'greater'})
+s1:ck_constraint()
+s2:ck_constraint()
+s1:insert({2, 1})
+s2:insert({1, 2})
+s1:drop()
+s2:drop()
-- 
2.21.0

  parent reply	other threads:[~2019-04-16 13:51 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-04-16 13:51 [tarantool-patches] [PATCH v3 0/3] box: run checks on insertions in LUA spaces Kirill Shcherbatov
2019-04-16 13:51 ` [tarantool-patches] [PATCH v3 1/3] schema: add new system space for CHECK constraints Kirill Shcherbatov
2019-04-25 20:38   ` [tarantool-patches] " n.pettik
2019-05-07  9:53     ` Kirill Shcherbatov
2019-05-12 13:45       ` n.pettik
2019-05-12 15:52         ` Kirill Shcherbatov
2019-05-12 23:04           ` n.pettik
2019-05-13  7:11             ` Kirill Shcherbatov
2019-05-13 12:29               ` n.pettik
2019-05-13 13:13                 ` Vladislav Shpilevoy
2019-04-16 13:51 ` [tarantool-patches] [PATCH v3 2/3] box: run check constraint tests on space alter Kirill Shcherbatov
2019-04-25 20:38   ` [tarantool-patches] " n.pettik
2019-05-07  9:53     ` Kirill Shcherbatov
2019-05-07 16:39       ` Konstantin Osipov
2019-05-07 17:47         ` [tarantool-patches] " Kirill Shcherbatov
2019-05-07 20:28           ` Konstantin Osipov
2019-05-11 12:15           ` n.pettik
2019-05-12 21:12             ` Konstantin Osipov
2019-05-13  7:09               ` Kirill Shcherbatov
2019-05-13  7:49                 ` Konstantin Osipov
2019-05-14 16:49       ` n.pettik
2019-04-16 13:51 ` Kirill Shcherbatov [this message]
2019-04-25 20:38   ` [tarantool-patches] Re: [PATCH v3 3/3] box: user-friendly interface to manage ck constraints n.pettik
2019-05-07  9:53     ` Kirill Shcherbatov
2019-05-14 15:02 [tarantool-patches] [PATCH v3 0/3] box: run checks on insertions in LUA spaces Kirill Shcherbatov
2019-05-14 15:02 ` [tarantool-patches] [PATCH v3 3/3] box: user-friendly interface to manage ck constraints Kirill Shcherbatov

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=0511eb70cd35f5a3b8fc527e5e08814f3188eb15.1555420166.git.kshcherbatov@tarantool.org \
    --to=kshcherbatov@tarantool.org \
    --cc=korablev@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --subject='Re: [tarantool-patches] [PATCH v3 3/3] box: user-friendly interface to manage ck constraints' \
    /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