Skip to content

Commit

Permalink
ddl: support sequences
Browse files Browse the repository at this point in the history
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
  • Loading branch information
DifferentialOrange committed Apr 10, 2024
1 parent 45b08f7 commit dd59559
Show file tree
Hide file tree
Showing 15 changed files with 870 additions and 61 deletions.
2 changes: 2 additions & 0 deletions .luacheckrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
redefined = false
globals = {"box", "_TARANTOOL", "tonumber64", "utf8", "table"}
include_files = {"**/*.lua", "*.rockspec", "*.luacheckrc"}
exclude_files = {".rocks/", "tmp/", ".history/"}
max_line_length = 120
max_comment_line_length = 150
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## Unreleased

### Added

- Added support of sequences in schema and space indexes (#122).

## [1.6.5] - 2023-10-23

### Added
Expand Down
69 changes: 56 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,17 +205,16 @@ format = {
},
...
},
sequences = { -- Not implemented yet
[seqence_name] = {
start
min
max
cycle
cache
step

}
}
sequences = {
[sequence_name] = {
start = start,
min = min,
max = max,
cycle = cycle,
cache = cache,
step = step,
},
},
}
```

Expand Down Expand Up @@ -292,8 +291,52 @@ local schema = {
}},
sharding_key = {'customer_id'},
sharding_func = 'vshard.router.bucket_id_mpcrc32',
}
}
},
tickets = {
engine = 'memtx',
is_local = false,
temporary = false,
format = {
{name = 'ticket_id', is_nullable = false, type = 'unsigned'},
{name = 'customer_id', is_nullable = false, type = 'unsigned'},
{name = 'bucket_id', is_nullable = false, type = 'unsigned'},
{name = 'contents', is_nullable = false, type = 'string'},
},
indexes = {{
name = 'ticket_id',
type = 'TREE',
unique = true,
parts = {
{path = 'ticket_id', is_nullable = false, type = 'unsigned'}
},
sequence = 'ticket_seq',
}, {,
name = 'customer_id',
type = 'TREE',
unique = false,
parts = {
{path = 'customer_id', is_nullable = false, type = 'unsigned'}
}
}, {
name = 'bucket_id',
type = 'TREE',
unique = false,
parts = {
{path = 'bucket_id', is_nullable = false, type = 'unsigned'}
}
}},
sharding_key = {'customer_id'},
sharding_func = 'vshard.router.bucket_id_mpcrc32',
},
},
sequences = {
ticket_seq = {
start = 1,
min = 1,
max = 10000,
cycle = false,
},
},
}
```

Expand Down
89 changes: 82 additions & 7 deletions ddl.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ local ddl_get = require('ddl.get')
local ddl_set = require('ddl.set')
local ddl_check = require('ddl.check')
local ddl_db = require('ddl.db')
local ddl_compare = require('ddl.compare')
local utils = require('ddl.utils')

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

if type(schema.sequences) ~= 'nil' then
return nil, string.format("sequences: not supported")
if type(schema.sequences) ~= 'nil' and type(schema.sequences) ~= 'table' then
return nil, string.format(
"sequences: must be a table or nil, got %s", type(schema.sequences)
)
end

do -- check redundant keys
local k = utils.redundant_key(schema, {'spaces'})
local k = utils.redundant_key(schema, {'spaces', 'sequences'})
if k ~= nil then
return nil, string.format(
"Invalid schema: redundant key %q", k
Expand All @@ -38,12 +41,47 @@ local function check_schema_format(schema)
return true
end

local function _check_schema(schema)
for space_name, space_schema in pairs(schema.spaces) do
local ok, err = ddl_check.check_space(space_name, space_schema)
local function _check_and_dry_run_sequences(sequences)
for sequence_name, sequence_schema in pairs(sequences) do
local ok, err = ddl_check.check_sequence(sequence_name, sequence_schema)
if not ok then
return nil, err
end

if box.sequence[sequence_name] ~= nil then
local current_schema = ddl_get.get_sequence_schema(sequence_name)
local _, err = ddl_compare.assert_equiv_sequence_schema(sequence_schema, current_schema)
if err ~= nil then
return nil, string.format(
"Incompatible schema: sequences[%q] %s", sequence_name, err)
end
else
local ok, err = pcall(
ddl_set.create_sequence,
sequence_name, sequence_schema, {dummy = true}
)

local dummy = box.sequence['_ddl_dummy']
if dummy then
pcall(box.schema.sequence.drop, dummy.id)
end

if not ok then
return nil, tostring(err):gsub('_ddl_dummy', sequence_name)
end
end
end

return true
end

local function _check_and_dry_run_spaces(spaces, sequences)
for space_name, space_schema in pairs(spaces) do
local ok, err = ddl_check.check_space(space_name, space_schema, sequences)
if not ok then
return nil, err
end

if box.space[space_name] ~= nil then
local diff = {}
local current_schema = ddl_get.get_space_schema(space_name)
Expand Down Expand Up @@ -75,6 +113,23 @@ local function _check_schema(schema)
return true
end

local function _check_and_dry_run_schema(schema)
-- Create dry-run sequences before spaces since space indexes use sequences.
local sequences = schema.sequences or {}
local ok, err = _check_and_dry_run_sequences(sequences)
if not ok then
return nil, err
end

local spaces = schema.spaces
local ok, err = _check_and_dry_run_spaces(spaces, sequences)
if not ok then
return nil, err
end

return true
end

local function check_schema(schema)
local ok, err = check_schema_format(schema)
if not ok then
Expand All @@ -89,7 +144,7 @@ local function check_schema(schema)
return nil, "Instance is read-only (check box.cfg.read_only and box.info.status)"
end

return ddl_db.call_dry_run(_check_schema, schema)
return ddl_db.call_dry_run(_check_and_dry_run_schema, schema)
end

local function set_metadata_space(metadata_name, space_format)
Expand Down Expand Up @@ -127,6 +182,12 @@ local function _set_schema(schema)
}
)

for sequence_name, sequence_schema in pairs(schema.sequences or {}) do
if box.sequence[sequence_name] == nil then
ddl_set.create_sequence(sequence_name, sequence_schema)
end
end

for space_name, space_schema in pairs(schema.spaces) do
if box.space[space_name] == nil then
ddl_set.create_space(space_name, space_schema)
Expand All @@ -153,8 +214,22 @@ local function get_schema()
end
end

local sequences = {}
for _, sequence in box.space._sequence:pairs() do
sequences[sequence.name] = ddl_get.get_sequence_schema(sequence.name)
end

local next_k = next(sequences)
local no_sequences = next_k == nil

if no_sequences then
-- For backward compatibility.
sequences = nil
end

return {
spaces = spaces,
sequences = sequences,
}
end

Expand Down
Loading

0 comments on commit dd59559

Please sign in to comment.