1- local json = require (' json' )
21local errors = require (' errors' )
32
43local utils = require (' crud.common.utils' )
54local dev_checks = require (' crud.common.dev_checks' )
65local collations = require (' crud.common.collations' )
76local compare_conditions = require (' crud.compare.conditions' )
87
9- local ParseConditionsError = errors .new_class (' ParseConditionsError' , {capture_stack = false })
108local GenFiltersError = errors .new_class (' GenFiltersError' , {capture_stack = false })
119
1210local filters = {}
@@ -97,31 +95,42 @@ local function parse(space, conditions, opts)
9795 for i , condition in ipairs (conditions ) do
9896 if i ~= opts .scan_condition_num then
9997 -- Index check (including one and multicolumn)
100- local fieldnos
101- local fields_types
98+ local fields
99+ local fields_types = {}
102100 local values_opts
103101
104102 local index = space_indexes [condition .operand ]
105103
106104 if index ~= nil then
107- fieldnos = get_index_fieldnos (index )
105+ fields = get_index_fieldnos (index )
108106 fields_types = get_index_fields_types (index )
109107 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+
116127 values_opts = {
117128 {is_nullable = is_nullable , collation = nil },
118129 }
119- else
120- return nil , ParseConditionsError (' No field or index is found for condition %s' , json .encode (condition ))
121130 end
122131
123132 table.insert (filter_conditions , {
124- fieldnos = fieldnos ,
133+ fields = fields ,
125134 operator = condition .operator ,
126135 values = condition .values ,
127136 types = fields_types ,
@@ -156,12 +165,30 @@ end
156165local PARSE_ARGS_TEMPLATE = ' local tuple = ...'
157166local LIB_FUNC_HEADER_TEMPLATE = ' function M.%s(%s)'
158167
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+
159179local function concat_conditions (conditions , operator )
160180 return ' (' .. table.concat (conditions , (' %s ' ):format (operator )) .. ' )'
161181end
162182
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 )
165192end
166193
167194local function get_eq_func_name (id )
@@ -173,38 +200,39 @@ local function get_cmp_func_name(id)
173200end
174201
175202local 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 = {}
179206
180207 for _ , cond in ipairs (filter_conditions ) do
181208 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
186214 end
187215 end
188216 end
189217
190218 -- gen definitions for all used fields
191219 local fields_def_parts = {}
192220
193- for _ , fieldno in ipairs (fieldnos ) do
221+ for _ , field in ipairs (fields ) do
194222 table.insert (fields_def_parts , string.format (
195223 ' local %s = tuple[%s]' ,
196- get_field_variable_name (fieldno ), fieldno
224+ get_field_variable_name (field ), format_path ( field )
197225 ))
198226 end
199227
200228 return table.concat (fields_def_parts , ' \n ' )
201229end
202230
203- local function format_comp_with_value (fieldno , func_name , value )
231+ local function format_comp_with_value (field , func_name , value )
204232 return string.format (
205233 ' %s(%s, %s)' ,
206234 func_name ,
207- get_field_variable_name (fieldno ),
235+ get_field_variable_name (field ),
208236 format_value (value )
209237 )
210238end
@@ -238,7 +266,7 @@ local function format_eq(cond)
238266 local values_opts = cond .values_opts or {}
239267
240268 for j = 1 , # cond .values do
241- local fieldno = cond .fieldnos [j ]
269+ local field = cond .fields [j ]
242270 local value = cond .values [j ]
243271 local value_type = cond .types [j ]
244272 local value_opts = values_opts [j ] or {}
@@ -254,7 +282,7 @@ local function format_eq(cond)
254282 func_name = ' eq_uuid'
255283 end
256284
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 ))
258286 end
259287
260288 return cond_strings
@@ -265,7 +293,7 @@ local function format_lt(cond)
265293 local values_opts = cond .values_opts or {}
266294
267295 for j = 1 , # cond .values do
268- local fieldno = cond .fieldnos [j ]
296+ local field = cond .fields [j ]
269297 local value = cond .values [j ]
270298 local value_type = cond .types [j ]
271299 local value_opts = values_opts [j ] or {}
@@ -279,9 +307,10 @@ local function format_lt(cond)
279307 elseif value_type == ' uuid' then
280308 func_name = ' lt_uuid'
281309 end
310+
282311 func_name = add_strict_postfix (func_name , value_opts )
283312
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 ))
285314 end
286315
287316 return cond_strings
@@ -366,10 +395,10 @@ local function gen_cmp_array_func_code(operator, func_name, cond, func_args_code
366395 return table.concat (func_code_lines , ' \n ' )
367396end
368397
369- local function function_args_by_fieldnos ( fieldnos )
398+ local function function_args_by_field ( fields )
370399 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 ))
373402 end
374403 return table.concat (arg_names , ' , ' )
375404end
@@ -408,8 +437,8 @@ local function gen_filter_code(filter_conditions)
408437 table.insert (filter_code_parts , ' ' )
409438
410439 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 )
413442
414443 local library_func_name , library_func_code = gen_library_func (i , cond , func_args_code )
415444 table.insert (library_funcs_code_parts , library_func_code )
0 commit comments