1
- local json = require (' json' )
2
1
local errors = require (' errors' )
3
2
4
3
local utils = require (' crud.common.utils' )
5
4
local dev_checks = require (' crud.common.dev_checks' )
6
5
local collations = require (' crud.common.collations' )
7
6
local compare_conditions = require (' crud.compare.conditions' )
8
7
9
- local ParseConditionsError = errors .new_class (' ParseConditionsError' , {capture_stack = false })
10
8
local GenFiltersError = errors .new_class (' GenFiltersError' , {capture_stack = false })
11
9
12
10
local filters = {}
@@ -97,31 +95,42 @@ local function parse(space, conditions, opts)
97
95
for i , condition in ipairs (conditions ) do
98
96
if i ~= opts .scan_condition_num then
99
97
-- Index check (including one and multicolumn)
100
- local fieldnos
101
- local fields_types
98
+ local fields
99
+ local fields_types = {}
102
100
local values_opts
103
101
104
102
local index = space_indexes [condition .operand ]
105
103
106
104
if index ~= nil then
107
- fieldnos = get_index_fieldnos (index )
105
+ fields = get_index_fieldnos (index )
108
106
fields_types = get_index_fields_types (index )
109
107
values_opts = get_values_opts (index )
110
- elseif fieldnos_by_names [condition .operand ] ~= nil then
111
- local fiendno = fieldnos_by_names [condition .operand ]
112
- fieldnos = {fiendno }
113
- local field_format = space_format [fiendno ]
114
- fields_types = {field_format .type }
115
- local is_nullable = field_format .is_nullable == true
108
+ else
109
+ local fieldno = fieldnos_by_names [condition .operand ]
110
+
111
+ if fieldno ~= nil then
112
+ fields = {fieldno }
113
+ else
114
+ -- We assume this is jsonpath, so it is
115
+ -- not in fieldnos_by_name map.
116
+ fields = {condition .operand }
117
+ end
118
+
119
+ local field_format = space_format [fieldno ]
120
+ local is_nullable
121
+
122
+ if field_format ~= nil then
123
+ fields_types = {field_format .type }
124
+ is_nullable = field_format .is_nullable == true
125
+ end
126
+
116
127
values_opts = {
117
128
{is_nullable = is_nullable , collation = nil },
118
129
}
119
- else
120
- return nil , ParseConditionsError (' No field or index is found for condition %s' , json .encode (condition ))
121
130
end
122
131
123
132
table.insert (filter_conditions , {
124
- fieldnos = fieldnos ,
133
+ fields = fields ,
125
134
operator = condition .operator ,
126
135
values = condition .values ,
127
136
types = fields_types ,
@@ -156,12 +165,30 @@ end
156
165
local PARSE_ARGS_TEMPLATE = ' local tuple = ...'
157
166
local LIB_FUNC_HEADER_TEMPLATE = ' function M.%s(%s)'
158
167
168
+ local function format_path (path )
169
+ local path_type = type (path )
170
+ if path_type == ' number' then
171
+ return tostring (path )
172
+ elseif path_type == ' string' then
173
+ return (' %q' ):format (path )
174
+ end
175
+
176
+ assert (false , (' Unexpected format: %s' ):format (path_type ))
177
+ end
178
+
159
179
local function concat_conditions (conditions , operator )
160
180
return ' (' .. table.concat (conditions , (' %s ' ):format (operator )) .. ' )'
161
181
end
162
182
163
- local function get_field_variable_name (fieldno )
164
- return string.format (' field_%s' , fieldno )
183
+ local function get_field_variable_name (field )
184
+ local field_type = type (field )
185
+ if field_type == ' number' then
186
+ field = tostring (field )
187
+ elseif field_type == ' string' then
188
+ field = string.gsub (field , ' ([().^$%[%]%+%-%*%?%%\' "])' , ' _' )
189
+ end
190
+
191
+ return string.format (' field_%s' , field )
165
192
end
166
193
167
194
local function get_eq_func_name (id )
@@ -173,38 +200,39 @@ local function get_cmp_func_name(id)
173
200
end
174
201
175
202
local function gen_tuple_fields_def_code (filter_conditions )
176
- -- get field numbers
177
- local fieldnos_added = {}
178
- local fieldnos = {}
203
+ -- get field names
204
+ local fields_added = {}
205
+ local fields = {}
179
206
180
207
for _ , cond in ipairs (filter_conditions ) do
181
208
for i = 1 , # cond .values do
182
- local fieldno = cond .fieldnos [i ]
183
- if not fieldnos_added [fieldno ] then
184
- table.insert (fieldnos , fieldno )
185
- fieldnos_added [fieldno ] = true
209
+ local field = cond .fields [i ]
210
+
211
+ if not fields_added [field ] then
212
+ table.insert (fields , field )
213
+ fields_added [field ] = true
186
214
end
187
215
end
188
216
end
189
217
190
218
-- gen definitions for all used fields
191
219
local fields_def_parts = {}
192
220
193
- for _ , fieldno in ipairs (fieldnos ) do
221
+ for _ , field in ipairs (fields ) do
194
222
table.insert (fields_def_parts , string.format (
195
223
' local %s = tuple[%s]' ,
196
- get_field_variable_name (fieldno ), fieldno
224
+ get_field_variable_name (field ), format_path ( field )
197
225
))
198
226
end
199
227
200
228
return table.concat (fields_def_parts , ' \n ' )
201
229
end
202
230
203
- local function format_comp_with_value (fieldno , func_name , value )
231
+ local function format_comp_with_value (field , func_name , value )
204
232
return string.format (
205
233
' %s(%s, %s)' ,
206
234
func_name ,
207
- get_field_variable_name (fieldno ),
235
+ get_field_variable_name (field ),
208
236
format_value (value )
209
237
)
210
238
end
@@ -238,7 +266,7 @@ local function format_eq(cond)
238
266
local values_opts = cond .values_opts or {}
239
267
240
268
for j = 1 , # cond .values do
241
- local fieldno = cond .fieldnos [j ]
269
+ local field = cond .fields [j ]
242
270
local value = cond .values [j ]
243
271
local value_type = cond .types [j ]
244
272
local value_opts = values_opts [j ] or {}
@@ -254,7 +282,7 @@ local function format_eq(cond)
254
282
func_name = ' eq_uuid'
255
283
end
256
284
257
- table.insert (cond_strings , format_comp_with_value (fieldno , func_name , value ))
285
+ table.insert (cond_strings , format_comp_with_value (field , func_name , value ))
258
286
end
259
287
260
288
return cond_strings
@@ -265,7 +293,7 @@ local function format_lt(cond)
265
293
local values_opts = cond .values_opts or {}
266
294
267
295
for j = 1 , # cond .values do
268
- local fieldno = cond .fieldnos [j ]
296
+ local field = cond .fields [j ]
269
297
local value = cond .values [j ]
270
298
local value_type = cond .types [j ]
271
299
local value_opts = values_opts [j ] or {}
@@ -279,9 +307,10 @@ local function format_lt(cond)
279
307
elseif value_type == ' uuid' then
280
308
func_name = ' lt_uuid'
281
309
end
310
+
282
311
func_name = add_strict_postfix (func_name , value_opts )
283
312
284
- table.insert (cond_strings , format_comp_with_value (fieldno , func_name , value ))
313
+ table.insert (cond_strings , format_comp_with_value (field , func_name , value ))
285
314
end
286
315
287
316
return cond_strings
@@ -366,10 +395,10 @@ local function gen_cmp_array_func_code(operator, func_name, cond, func_args_code
366
395
return table.concat (func_code_lines , ' \n ' )
367
396
end
368
397
369
- local function function_args_by_fieldnos ( fieldnos )
398
+ local function function_args_by_field ( fields )
370
399
local arg_names = {}
371
- for _ , fieldno in ipairs (fieldnos ) do
372
- table.insert (arg_names , get_field_variable_name (fieldno ))
400
+ for _ , field in ipairs (fields ) do
401
+ table.insert (arg_names , get_field_variable_name (field ))
373
402
end
374
403
return table.concat (arg_names , ' , ' )
375
404
end
@@ -408,8 +437,8 @@ local function gen_filter_code(filter_conditions)
408
437
table.insert (filter_code_parts , ' ' )
409
438
410
439
for i , cond in ipairs (filter_conditions ) do
411
- local args_fieldnos = { unpack (cond .fieldnos , 1 , # cond .values ) }
412
- local func_args_code = function_args_by_fieldnos ( args_fieldnos )
440
+ local args_fields = { unpack (cond .fields , 1 , # cond .values ) }
441
+ local func_args_code = function_args_by_field ( args_fields )
413
442
414
443
local library_func_name , library_func_code = gen_library_func (i , cond , func_args_code )
415
444
table.insert (library_funcs_code_parts , library_func_code )
@@ -623,6 +652,7 @@ function filters.gen_func(space, conditions, opts)
623
652
scan_condition_num = opts .scan_condition_num ,
624
653
tarantool_iter = opts .tarantool_iter ,
625
654
})
655
+
626
656
if err ~= nil then
627
657
return nil , GenFiltersError :new (" Failed to generate filters for specified conditions: %s" , err )
628
658
end
0 commit comments