File: utils.lua

package info (click to toggle)
tarantool 2.6.0-1.4
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 85,412 kB
  • sloc: ansic: 513,775; cpp: 69,493; sh: 25,650; python: 19,190; perl: 14,973; makefile: 4,178; yacc: 1,329; sql: 1,074; pascal: 620; ruby: 190; awk: 18; lisp: 7
file content (245 lines) | stat: -rw-r--r-- 5,306 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
function space_field_types(space_no)
	local types = {};
	for _, index in pairs(box.space[space_no].index) do
		for _,key_def in pairs(index.parts) do
			types[key_def.fieldno] = key_def.type;
		end
	end
	return types;
end

function iterate(space_no, index_no, f1, f2, iterator, ...)
	local sorted = (box.space[space_no].index[index_no].type == "TREE");
	local pkeys = {};
	local tkeys = {};
	local values = {};
	local types = space_field_types(space_no);
	local function get_field(tuple, field_no)
		local f = tuple[field_no]
		if (types[field_no] == 'unsigned') then
			return string.format('%8d', f);
		else
			return f
		end
	end
	local state, v
	for state, v in box.space[space_no].index[index_no]:pairs({...}, { iterator = iterator }) do
		local pk = get_field(v, 1);
		local tk = '$';
		for f = f1 + 1, f2, 1 do tk = (tk..(get_field(v, f))..'$'); end;
		table.insert(values, tk);
		if pkeys[pk] ~= nil then
			error('Duplicate tuple (primary key): '..pk);
		end
		if box.space[space_no].index[index_no].unique and tkeys[tk] ~= nil then
			error('Duplicate tuple (test key): '..tk);
		end;
		tkeys[pk] = true;
		tkeys[tk] = true;
	end;

	if not sorted then
		table.sort(values);
	end;

	return values
end

function arithmetic(d, count)
	if not d then d = 1 end
	local a = 0;
	local i = 0;

	return function()
		if count and (i >= count) then
			return nil;
		end

		i = i + 1;
		a = a + d;
		return a;
	end
end

function table_shuffle(t)
	local n = #t
	while n >= 2 do
		local k = math.random(n)
		t[k], t[n] = t[n], t[k]
		n = n - 1
	end
end

function table_generate(iter)
	local t = {};
	for k in iter do
		table.insert(t, k);
	end

	return t;
end

-- sort all rows as strings(not for tables);
function sort(tuples)
    local function compare_tables(t1, t2)
        return (tostring(t1) < tostring(t2))
    end
    table.sort(tuples, compare_tables)
    return tuples
end;

-- return string tuple
function tuple_to_string(tuple, yaml)
    ans = '['
    for i = 0, #tuple - 1 do
        if #i == 4 then
            ans = ans..i
        elseif #i == 8 then
            ans = ans..i
        else
            ans = ans..'\''..tostring(i)..'\''
        end
        if not #i == #tuple -1 then
            ans = ans..', '
        end
    end
    ans = ans..']'
    if yaml then
        ans = ' - '..ans
    end
    return ans
end;

function check_space(space, N)
    local errors = {}

    --
    -- Insert
    --
    local keys = {}
    math.randomseed(0)
    for i=1,N do
        local key = math.random(2147483647)
        keys[i] = key
        space:insert({key, 0})
    end

    --
    -- Select
    --
    table_shuffle(keys)
    for i=1,N do
        local key = keys[i]
        local tuple = space:get({key})
        if tuple == nil or tuple[1] ~= key then
            table.insert(errors, {'missing key after insert', key})
        end
    end

    --
    -- Delete some keys
    --
    table_shuffle(keys)
    for i=1,N,3 do
        local key = keys[i]
        space:delete({key})
    end

    --
    -- Upsert
    --
    for k=1,2 do
        -- Insert/update valuaes
        table_shuffle(keys)
        for i=1,N do
            local key = keys[i]
            space:upsert({key, 1}, {{'+', 2, 1}})
        end
        -- Check values
        table_shuffle(keys)
        for i=1,N do
            local key = keys[i]
            local tuple = space:get({key})
            if tuple == nil or tuple[1] ~= key then
                table.insert(errors, {'missing key after upsert', key})
            end
            if tuple[2] ~= k then
                table.insert(errors, {'invalid value after upsert', key,
                             'found', tuple[2], 'expected', k})
            end
        end
    end

    --
    -- Delete
    --
    table_shuffle(keys)
    for i=1,N do
        local key = keys[i]
        space:delete({key})
    end

    for i=1,N do
        local key = keys[i]
        if space:get({key}) ~= nil then
            table.insert(errors, {'found deleted key', key})
        end
    end

    local count = #space:select()
    -- :len() doesn't work on vinyl
    if count ~= 0 then
        table.insert(errors, {'invalid count after delete', count})
    end

    return errors
end

function space_bsize(s)
    local bsize = 0
    for _, t in s:pairs() do
        bsize = bsize + t:bsize()
    end

    return bsize
end

function create_iterator(obj, key, opts)
    local iter, key, state = obj:pairs(key, opts)
    local res = {iter = iter, key = key, state = state}
    res.next = function()
        local st, tp = iter.gen(key, state)
        return tp
    end
    res.iterate_over = function()
        local tp = nil
        local ret = {}
        local i = 0
        tp = res.next()
        while tp do
            ret[i] = tp
            i = i + 1
            tp = res.next()
        end
        return ret
    end
    return res
end

function setmap(tab)
    return setmetatable(tab, { __serialize = 'map' })
end

return {
    space_field_types = space_field_types;
    iterate = iterate;
    arithmetic = arithmetic;
    table_generate = table_generate;
    table_shuffle = table_shuffle;
    sort = sort;
    tuple_to_string = tuple_to_string;
    check_space = check_space;
    space_bsize = space_bsize;
    create_iterator = create_iterator;
    setmap = setmap;
};