Skip to content

Commit dd59559

Browse files
ddl: support sequences
This patch adds the support of sequences through new schema section, as well as proper support of sequence option for indexes. Before this patch, ddl had half-baked support of sequences: one could provide `sequence` as sequence name in indexes and it would be created. This approach was broken in basic `set_schema(get_schema)` scenario since there wasn't any sequences support in get. Current design is inspired by existing "not implemented yet" tests and documentation examples. Closes #122
1 parent 45b08f7 commit dd59559

15 files changed

+870
-61
lines changed

.luacheckrc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
redefined = false
2+
globals = {"box", "_TARANTOOL", "tonumber64", "utf8", "table"}
23
include_files = {"**/*.lua", "*.rockspec", "*.luacheckrc"}
34
exclude_files = {".rocks/", "tmp/", ".history/"}
45
max_line_length = 120
6+
max_comment_line_length = 150

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
55
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
66

7+
## Unreleased
8+
9+
### Added
10+
11+
- Added support of sequences in schema and space indexes (#122).
12+
713
## [1.6.5] - 2023-10-23
814

915
### Added

README.md

Lines changed: 56 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -205,17 +205,16 @@ format = {
205205
},
206206
...
207207
},
208-
sequences = { -- Not implemented yet
209-
[seqence_name] = {
210-
start
211-
min
212-
max
213-
cycle
214-
cache
215-
step
216-
217-
}
218-
}
208+
sequences = {
209+
[sequence_name] = {
210+
start = start,
211+
min = min,
212+
max = max,
213+
cycle = cycle,
214+
cache = cache,
215+
step = step,
216+
},
217+
},
219218
}
220219
```
221220

@@ -292,8 +291,52 @@ local schema = {
292291
}},
293292
sharding_key = {'customer_id'},
294293
sharding_func = 'vshard.router.bucket_id_mpcrc32',
295-
}
296-
}
294+
},
295+
tickets = {
296+
engine = 'memtx',
297+
is_local = false,
298+
temporary = false,
299+
format = {
300+
{name = 'ticket_id', is_nullable = false, type = 'unsigned'},
301+
{name = 'customer_id', is_nullable = false, type = 'unsigned'},
302+
{name = 'bucket_id', is_nullable = false, type = 'unsigned'},
303+
{name = 'contents', is_nullable = false, type = 'string'},
304+
},
305+
indexes = {{
306+
name = 'ticket_id',
307+
type = 'TREE',
308+
unique = true,
309+
parts = {
310+
{path = 'ticket_id', is_nullable = false, type = 'unsigned'}
311+
},
312+
sequence = 'ticket_seq',
313+
}, {,
314+
name = 'customer_id',
315+
type = 'TREE',
316+
unique = false,
317+
parts = {
318+
{path = 'customer_id', is_nullable = false, type = 'unsigned'}
319+
}
320+
}, {
321+
name = 'bucket_id',
322+
type = 'TREE',
323+
unique = false,
324+
parts = {
325+
{path = 'bucket_id', is_nullable = false, type = 'unsigned'}
326+
}
327+
}},
328+
sharding_key = {'customer_id'},
329+
sharding_func = 'vshard.router.bucket_id_mpcrc32',
330+
},
331+
},
332+
sequences = {
333+
ticket_seq = {
334+
start = 1,
335+
min = 1,
336+
max = 10000,
337+
cycle = false,
338+
},
339+
},
297340
}
298341
```
299342

ddl.lua

Lines changed: 82 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ local ddl_get = require('ddl.get')
22
local ddl_set = require('ddl.set')
33
local ddl_check = require('ddl.check')
44
local ddl_db = require('ddl.db')
5+
local ddl_compare = require('ddl.compare')
56
local utils = require('ddl.utils')
67

78
local function check_schema_format(schema)
@@ -22,12 +23,14 @@ local function check_schema_format(schema)
2223
return nil, string.format("functions: not supported")
2324
end
2425

25-
if type(schema.sequences) ~= 'nil' then
26-
return nil, string.format("sequences: not supported")
26+
if type(schema.sequences) ~= 'nil' and type(schema.sequences) ~= 'table' then
27+
return nil, string.format(
28+
"sequences: must be a table or nil, got %s", type(schema.sequences)
29+
)
2730
end
2831

2932
do -- check redundant keys
30-
local k = utils.redundant_key(schema, {'spaces'})
33+
local k = utils.redundant_key(schema, {'spaces', 'sequences'})
3134
if k ~= nil then
3235
return nil, string.format(
3336
"Invalid schema: redundant key %q", k
@@ -38,12 +41,47 @@ local function check_schema_format(schema)
3841
return true
3942
end
4043

41-
local function _check_schema(schema)
42-
for space_name, space_schema in pairs(schema.spaces) do
43-
local ok, err = ddl_check.check_space(space_name, space_schema)
44+
local function _check_and_dry_run_sequences(sequences)
45+
for sequence_name, sequence_schema in pairs(sequences) do
46+
local ok, err = ddl_check.check_sequence(sequence_name, sequence_schema)
47+
if not ok then
48+
return nil, err
49+
end
50+
51+
if box.sequence[sequence_name] ~= nil then
52+
local current_schema = ddl_get.get_sequence_schema(sequence_name)
53+
local _, err = ddl_compare.assert_equiv_sequence_schema(sequence_schema, current_schema)
54+
if err ~= nil then
55+
return nil, string.format(
56+
"Incompatible schema: sequences[%q] %s", sequence_name, err)
57+
end
58+
else
59+
local ok, err = pcall(
60+
ddl_set.create_sequence,
61+
sequence_name, sequence_schema, {dummy = true}
62+
)
63+
64+
local dummy = box.sequence['_ddl_dummy']
65+
if dummy then
66+
pcall(box.schema.sequence.drop, dummy.id)
67+
end
68+
69+
if not ok then
70+
return nil, tostring(err):gsub('_ddl_dummy', sequence_name)
71+
end
72+
end
73+
end
74+
75+
return true
76+
end
77+
78+
local function _check_and_dry_run_spaces(spaces, sequences)
79+
for space_name, space_schema in pairs(spaces) do
80+
local ok, err = ddl_check.check_space(space_name, space_schema, sequences)
4481
if not ok then
4582
return nil, err
4683
end
84+
4785
if box.space[space_name] ~= nil then
4886
local diff = {}
4987
local current_schema = ddl_get.get_space_schema(space_name)
@@ -75,6 +113,23 @@ local function _check_schema(schema)
75113
return true
76114
end
77115

116+
local function _check_and_dry_run_schema(schema)
117+
-- Create dry-run sequences before spaces since space indexes use sequences.
118+
local sequences = schema.sequences or {}
119+
local ok, err = _check_and_dry_run_sequences(sequences)
120+
if not ok then
121+
return nil, err
122+
end
123+
124+
local spaces = schema.spaces
125+
local ok, err = _check_and_dry_run_spaces(spaces, sequences)
126+
if not ok then
127+
return nil, err
128+
end
129+
130+
return true
131+
end
132+
78133
local function check_schema(schema)
79134
local ok, err = check_schema_format(schema)
80135
if not ok then
@@ -89,7 +144,7 @@ local function check_schema(schema)
89144
return nil, "Instance is read-only (check box.cfg.read_only and box.info.status)"
90145
end
91146

92-
return ddl_db.call_dry_run(_check_schema, schema)
147+
return ddl_db.call_dry_run(_check_and_dry_run_schema, schema)
93148
end
94149

95150
local function set_metadata_space(metadata_name, space_format)
@@ -127,6 +182,12 @@ local function _set_schema(schema)
127182
}
128183
)
129184

185+
for sequence_name, sequence_schema in pairs(schema.sequences or {}) do
186+
if box.sequence[sequence_name] == nil then
187+
ddl_set.create_sequence(sequence_name, sequence_schema)
188+
end
189+
end
190+
130191
for space_name, space_schema in pairs(schema.spaces) do
131192
if box.space[space_name] == nil then
132193
ddl_set.create_space(space_name, space_schema)
@@ -153,8 +214,22 @@ local function get_schema()
153214
end
154215
end
155216

217+
local sequences = {}
218+
for _, sequence in box.space._sequence:pairs() do
219+
sequences[sequence.name] = ddl_get.get_sequence_schema(sequence.name)
220+
end
221+
222+
local next_k = next(sequences)
223+
local no_sequences = next_k == nil
224+
225+
if no_sequences then
226+
-- For backward compatibility.
227+
sequences = nil
228+
end
229+
156230
return {
157231
spaces = spaces,
232+
sequences = sequences,
158233
}
159234
end
160235

0 commit comments

Comments
 (0)