@@ -22,6 +22,7 @@ local FilterFieldsError = errors.new_class('FilterFieldsError', {capture_stack =
2222local NotInitializedError = errors .new_class (' NotInitialized' )
2323local StorageInfoError = errors .new_class (' StorageInfoError' )
2424local VshardRouterError = errors .new_class (' VshardRouterError' , {capture_stack = false })
25+ local UtilsInternalError = errors .new_class (' UtilsInternalError' , {capture_stack = false })
2526local fiber = require (' fiber' )
2627
2728local utils = {}
@@ -294,25 +295,153 @@ function utils.enrich_field_names_with_cmp_key(field_names, key_parts, space_for
294295 return enriched_field_names
295296end
296297
297- local enabled_tarantool_features = {}
298298
299- local function determine_enabled_features ()
300- local major_minor_patch = _G ._TARANTOOL :split (' -' , 1 )[1 ]
301- local major_minor_patch_parts = major_minor_patch :split (' .' , 2 )
299+ local function get_version_suffix (suffix_candidate )
300+ if type (suffix_candidate ) ~= ' string' then
301+ return nil
302+ end
303+
304+ if suffix_candidate :find (' ^entrypoint$' )
305+ or suffix_candidate :find (' ^alpha%d$' )
306+ or suffix_candidate :find (' ^beta%d$' )
307+ or suffix_candidate :find (' ^rc%d$' ) then
308+ return suffix_candidate
309+ end
310+
311+ return nil
312+ end
313+
314+ utils .get_version_suffix = get_version_suffix
315+
316+
317+ local suffix_with_digit_weight = {
318+ alpha = - 3000 ,
319+ beta = - 2000 ,
320+ rc = - 1000 ,
321+ }
322+
323+ local function get_version_suffix_weight (suffix )
324+ if suffix == nil then
325+ return 0
326+ end
327+
328+ if suffix :find (' ^entrypoint$' ) then
329+ return - math.huge
330+ end
331+
332+ for header , weight in pairs (suffix_with_digit_weight ) do
333+ local pos , _ , digits = suffix :find (' ^' .. header .. ' (%d)$' )
334+ if pos ~= nil then
335+ return weight + tonumber (digits )
336+ end
337+ end
338+
339+ UtilsInternalError :assert (false ,
340+ ' Unexpected suffix %q, parse with "utils.get_version_suffix" first' , suffix )
341+ end
342+
343+ utils .get_version_suffix_weight = get_version_suffix_weight
344+
345+
346+ local function is_version_ge (major , minor ,
347+ patch , suffix ,
348+ major_to_compare , minor_to_compare ,
349+ patch_to_compare , suffix_to_compare )
350+ major = major or 0
351+ minor = minor or 0
352+ patch = patch or 0
353+ local suffix_weight = get_version_suffix_weight (suffix )
354+
355+ major_to_compare = major_to_compare or 0
356+ minor_to_compare = minor_to_compare or 0
357+ patch_to_compare = patch_to_compare or 0
358+ local suffix_weight_to_compare = get_version_suffix_weight (suffix_to_compare )
359+
360+ if major > major_to_compare then return true end
361+ if major < major_to_compare then return false end
302362
363+ if minor > minor_to_compare then return true end
364+ if minor < minor_to_compare then return false end
365+
366+ if patch > patch_to_compare then return true end
367+ if patch < patch_to_compare then return false end
368+
369+ if suffix_weight > suffix_weight_to_compare then return true end
370+ if suffix_weight < suffix_weight_to_compare then return false end
371+
372+ return true
373+ end
374+
375+ utils .is_version_ge = is_version_ge
376+
377+
378+ local function is_version_in_range (major , minor ,
379+ patch , suffix ,
380+ major_left_side , minor_left_side ,
381+ patch_left_side , suffix_left_side ,
382+ major_right_side , minor_right_side ,
383+ patch_right_side , suffix_right_side )
384+ return is_version_ge (major , minor ,
385+ patch , suffix ,
386+ major_left_side , minor_left_side ,
387+ patch_left_side , suffix_left_side )
388+ and is_version_ge (major_right_side , minor_right_side ,
389+ patch_right_side , suffix_right_side ,
390+ major , minor ,
391+ patch , suffix )
392+ end
393+
394+ utils .is_version_in_range = is_version_in_range
395+
396+
397+ local function get_tarantool_version ()
398+ local version_parts = rawget (_G , ' _TARANTOOL' ):split (' -' , 1 )
399+
400+ local major_minor_patch_parts = version_parts [1 ]:split (' .' , 2 )
303401 local major = tonumber (major_minor_patch_parts [1 ])
304402 local minor = tonumber (major_minor_patch_parts [2 ])
305403 local patch = tonumber (major_minor_patch_parts [3 ])
306404
307- -- since Tarantool 2.3
308- enabled_tarantool_features .fieldpaths = major >= 2 and (minor > 3 or minor == 3 and patch >= 1 )
405+ local suffix = get_version_suffix (version_parts [2 ])
406+
407+ return major , minor , patch , suffix
408+ end
409+
410+ utils .get_tarantool_version = get_tarantool_version
411+
412+
413+ local function tarantool_version_at_least (wanted_major , wanted_minor , wanted_patch )
414+ local major , minor , patch , suffix = get_tarantool_version ()
415+
416+ return is_version_ge (major , minor , patch , suffix ,
417+ wanted_major , wanted_minor , wanted_patch , nil )
418+ end
419+
420+ utils .tarantool_version_at_least = tarantool_version_at_least
421+
422+
423+ local enabled_tarantool_features = {}
424+
425+ local function determine_enabled_features ()
426+ local major , minor , patch , suffix = get_tarantool_version ()
427+
428+ -- since Tarantool 2.3.1
429+ enabled_tarantool_features .fieldpaths = is_version_ge (major , minor , patch , suffix ,
430+ 2 , 3 , 1 , nil )
309431
310- -- since Tarantool 2.4
311- enabled_tarantool_features .uuids = major >= 2 and (minor > 4 or minor == 4 and patch >= 1 )
432+ -- since Tarantool 2.4.1
433+ enabled_tarantool_features .uuids = is_version_ge (major , minor , patch , suffix ,
434+ 2 , 4 , 1 , nil )
312435
313436 -- since Tarantool 2.6.3 / 2.7.2 / 2.8.1
314- enabled_tarantool_features .jsonpath_indexes = major >= 3 or (major >= 2 and ((minor >= 6 and patch >= 3 )
315- or (minor >= 7 and patch >= 2 ) or (minor >= 8 and patch >= 1 ) or minor >= 9 ))
437+ enabled_tarantool_features .jsonpath_indexes = is_version_ge (major , minor , patch , suffix ,
438+ 2 , 8 , 1 , nil )
439+ or is_version_in_range (major , minor , patch , suffix ,
440+ 2 , 7 , 2 , nil ,
441+ 2 , 7 , math.huge , nil )
442+ or is_version_in_range (major , minor , patch , suffix ,
443+ 2 , 6 , 3 , nil ,
444+ 2 , 6 , math.huge , nil )
316445
317446 -- The merger module was implemented in 2.2.1, see [1].
318447 -- However it had the critical problem [2], which leads to
@@ -322,26 +451,38 @@ local function determine_enabled_features()
322451 --
323452 -- [1]: https://github.com/tarantool/tarantool/issues/3276
324453 -- [2]: https://github.com/tarantool/tarantool/issues/4954
325- enabled_tarantool_features .builtin_merger =
326- (major == 2 and minor == 3 and patch >= 3 ) or
327- (major == 2 and minor == 4 and patch >= 2 ) or
328- (major == 2 and minor == 5 and patch >= 1 ) or
329- (major >= 2 and minor >= 6 ) or
330- (major >= 3 )
454+ enabled_tarantool_features .builtin_merger = is_version_ge (major , minor , patch , suffix ,
455+ 2 , 6 , 0 , nil )
456+ or is_version_in_range (major , minor , patch , suffix ,
457+ 2 , 5 , 1 , nil ,
458+ 2 , 5 , math.huge , nil )
459+ or is_version_in_range (major , minor , patch , suffix ,
460+ 2 , 4 , 2 , nil ,
461+ 2 , 4 , math.huge , nil )
462+ or is_version_in_range (major , minor , patch , suffix ,
463+ 2 , 3 , 3 , nil ,
464+ 2 , 3 , math.huge , nil )
331465
332466 -- The external merger module leans on a set of relatively
333467 -- new APIs in tarantool. So it works only on tarantool
334468 -- versions, which offer those APIs.
335469 --
336470 -- See README of the module:
337471 -- https://github.com/tarantool/tuple-merger
338- enabled_tarantool_features .external_merger =
339- (major == 1 and minor == 10 and patch >= 8 ) or
340- (major == 2 and minor == 4 and patch >= 3 ) or
341- (major == 2 and minor == 5 and patch >= 2 ) or
342- (major == 2 and minor == 6 and patch >= 1 ) or
343- (major == 2 and minor >= 7 ) or
344- (major >= 3 )
472+ enabled_tarantool_features .external_merger = is_version_ge (major , minor , patch , suffix ,
473+ 2 , 7 , 0 , nil )
474+ or is_version_in_range (major , minor , patch , suffix ,
475+ 2 , 6 , 1 , nil ,
476+ 2 , 6 , math.huge , nil )
477+ or is_version_in_range (major , minor , patch , suffix ,
478+ 2 , 5 , 2 , nil ,
479+ 2 , 5 , math.huge , nil )
480+ or is_version_in_range (major , minor , patch , suffix ,
481+ 2 , 4 , 3 , nil ,
482+ 2 , 4 , math.huge , nil )
483+ or is_version_in_range (major , minor , patch , suffix ,
484+ 1 , 10 , 8 , nil ,
485+ 1 , 10 , math.huge , nil )
345486end
346487
347488function utils .tarantool_supports_fieldpaths ()
@@ -398,7 +539,7 @@ local function add_nullable_fields_recursive(operations, operations_map, space_f
398539end
399540
400541-- Tarantool < 2.1 has no fields `box.error.NO_SUCH_FIELD_NO` and `box.error.NO_SUCH_FIELD_NAME`.
401- if _TARANTOOL >= " 2.1 " then
542+ if tarantool_version_at_least ( 2 , 1 , 0 , nil ) then
402543 function utils .is_field_not_found (err_code )
403544 return err_code == box .error .NO_SUCH_FIELD_NO or err_code == box .error .NO_SUCH_FIELD_NAME
404545 end
0 commit comments