Skip to content

Commit b0c3a30

Browse files
p7novandreyaksenov
andauthored
Update constraints and foreign keys docs (#3583)
Resolves #3043, #3360, #3361, #3429 Co-authored-by: Andrey Aksenov <[email protected]>
1 parent 150c8dd commit b0c3a30

File tree

8 files changed

+453
-150
lines changed

8 files changed

+453
-150
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
local fio = require('fio')
2+
local server = require('luatest.server')
3+
local t = require('luatest')
4+
local g = t.group()
5+
g.before_each(function(cg)
6+
cg.server = server:new {
7+
box_cfg = {},
8+
workdir = fio.cwd() .. '/tmp'
9+
}
10+
cg.server:start()
11+
end)
12+
13+
g.after_each(function(cg)
14+
cg.server:stop()
15+
cg.server:drop()
16+
end)
17+
18+
g.test_constraints = function(cg)
19+
cg.server:exec(function()
20+
21+
-- Define a tuple constraint function --
22+
box.schema.func.create('check_person', {
23+
language = 'LUA',
24+
is_deterministic = true,
25+
body = 'function(t, c) return (t.age >= 0 and #(t.name) > 3) end'
26+
})
27+
28+
-- Create a space with a tuple constraint --
29+
customers = box.schema.space.create('customers', {constraint = 'check_person'})
30+
31+
-- Define a field constraint function --
32+
box.schema.func.create('check_age', {
33+
language = 'LUA',
34+
is_deterministic = true,
35+
body = 'function(f, c) return (f >= 0 and f < 150) end'
36+
})
37+
38+
-- Specify format with a field constraint --
39+
box.space.customers:format({
40+
{name = 'id', type = 'number'},
41+
{name = 'name', type = 'string'},
42+
{name = 'age', type = 'number', constraint = 'check_age'},
43+
})
44+
45+
box.space.customers:create_index('primary', { parts = { 1 } })
46+
47+
box.space.customers:insert{1, "Alice", 30}
48+
49+
-- Tests --
50+
t.assert_equals(customers:count(), 1)
51+
t.assert_equals(customers:get(1), {1, "Alice", 30})
52+
53+
-- Failed contstraint --
54+
t.assert_error_msg_contains("Check constraint 'check_person' failed for tuple",
55+
function() customers:insert{2, "Bob", 230} end)
56+
57+
-- Create one more tuple constraint --
58+
box.schema.func.create('another_constraint',
59+
{language = 'LUA', is_deterministic = true, body = 'function(t, c) return true end'})
60+
61+
-- Set two constraints with optional names --
62+
box.space.customers:alter{
63+
constraint = { check1 = 'check_person', check2 = 'another_constraint'}
64+
}
65+
end)
66+
end
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
local fio = require('fio')
2+
local server = require('luatest.server')
3+
local t = require('luatest')
4+
local g = t.group()
5+
g.before_each(function(cg)
6+
cg.server = server:new {
7+
box_cfg = {},
8+
workdir = fio.cwd() .. '/tmp'
9+
}
10+
cg.server:start()
11+
end)
12+
13+
g.after_each(function(cg)
14+
cg.server:stop()
15+
cg.server:drop()
16+
end)
17+
18+
g.test_foreign_keys = function(cg)
19+
cg.server:exec(function()
20+
21+
-- Parent space --
22+
customers = box.schema.space.create('customers')
23+
customers:format{
24+
{name = 'id', type = 'number'},
25+
{name = 'name', type = 'string'}
26+
}
27+
28+
customers:create_index('primary', { parts = { 1 } })
29+
customers:create_index('name', { parts = { 2 } })
30+
customers:create_index('id_name', { parts = { 1, 2 } })
31+
32+
customers:insert({1, 'Alice'})
33+
34+
-- Create a space with a field foreign key --
35+
box.schema.space.create('orders')
36+
37+
box.space.orders:format({
38+
{name = 'id', type = 'number'},
39+
{name = 'customer_id', foreign_key = {space = 'customers', field = 'id'}},
40+
{name = 'price_total', type = 'number'},
41+
})
42+
43+
orders = box.space.orders
44+
orders:create_index('primary', { parts = { 1 } })
45+
46+
orders:insert({1, 1, 100})
47+
48+
t.assert_equals(orders:count(), 1)
49+
t.assert_equals(orders:get(1), {1, 1, 100})
50+
51+
-- Failed foreign key check --
52+
t.assert_error_msg_contains("Foreign key constraint 'customers' failed for field '2 (customer_id)': foreign tuple was not found",
53+
function() orders:insert{2, 10, 200} end)
54+
55+
end)
56+
end
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
local fio = require('fio')
2+
local server = require('luatest.server')
3+
local t = require('luatest')
4+
local g = t.group()
5+
g.before_each(function(cg)
6+
cg.server = server:new {
7+
box_cfg = {},
8+
workdir = fio.cwd() .. '/tmp'
9+
}
10+
cg.server:start()
11+
end)
12+
13+
g.after_each(function(cg)
14+
cg.server:stop()
15+
cg.server:drop()
16+
end)
17+
18+
g.test_foreign_keys = function(cg)
19+
cg.server:exec(function()
20+
21+
-- Parent space --
22+
customers = box.schema.space.create('customers')
23+
customers:format{
24+
{name = 'id', type = 'number'},
25+
{name = 'name', type = 'string'}
26+
}
27+
28+
customers:create_index('primary', { parts = { 1 } })
29+
customers:create_index('name', { parts = { 2 } })
30+
customers:create_index('id_name', { parts = { 1, 2 } })
31+
32+
customers:insert({1, 'Alice'})
33+
34+
-- Create a space with a tuple foreign key --
35+
box.schema.space.create("orders", {
36+
foreign_key = {
37+
space = 'customers',
38+
field = {customer_id = 'id', customer_name = 'name'}
39+
}
40+
})
41+
42+
box.space.orders:format({
43+
{name = "id", type = "number"},
44+
{name = "customer_id" },
45+
{name = "customer_name"},
46+
{name = "price_total", type = "number"},
47+
})
48+
49+
orders = box.space.orders
50+
orders:create_index('primary', { parts = { 1 } })
51+
52+
orders:insert({1, 1, 'Alice', 100})
53+
54+
t.assert_equals(orders:count(), 1)
55+
t.assert_equals(orders:get(1), {1, 1, 'Alice', 100})
56+
57+
-- Failed foreign key check --
58+
t.assert_error_msg_contains("Foreign key constraint 'customers' failed: foreign tuple was not found",
59+
function() orders:insert{2, 10, 'Bob', 200} end)
60+
61+
-- Set a foreign key with an optional name --
62+
box.space.orders:alter{
63+
foreign_key = {
64+
customer = {
65+
space = 'customers',
66+
field = { customer_id = 'id', customer_name = 'name'}
67+
}
68+
}
69+
}
70+
71+
items = box.schema.space.create('items')
72+
items:format{{name = 'id', type = 'number'}}
73+
items:create_index('primary', { parts = { 1 } })
74+
75+
orders:delete{1}
76+
orders:format({
77+
{name = "id", type = "number"},
78+
{name = "customer_id" },
79+
{name = "customer_name"},
80+
{name = "item_id", type = "number"},
81+
{name = "price_total", type = "number"},
82+
})
83+
84+
-- Set two foreign keys: names are mandatory --
85+
box.space.orders:alter{
86+
foreign_key = {
87+
customer = {
88+
space = 'customers',
89+
field = {customer_id = 'id', customer_name = 'name'}
90+
},
91+
item = {
92+
space = 'items',
93+
field = {item_id = 'id'}
94+
}
95+
}
96+
}
97+
end)
98+
end

0 commit comments

Comments
 (0)