@@ -9,12 +9,12 @@ local json = require('json')
9
9
local avro_schema = require (' avro_schema' )
10
10
local utils = require (' graphql.utils' )
11
11
local clock = require (' clock' )
12
- local bit = require (' bit' )
13
- local rex , is_pcre2 = utils .optional_require_rex ()
12
+ local rex = utils .optional_require_rex ()
14
13
local avro_helpers = require (' graphql.avro_helpers' )
15
14
local db_schema_helpers = require (' graphql.db_schema_helpers' )
16
15
local error_codes = require (' graphql.error_codes' )
17
16
local statistics = require (' graphql.statistics' )
17
+ local expressions = require (' graphql.expressions' )
18
18
19
19
local check = utils .check
20
20
local e = error_codes
@@ -763,16 +763,16 @@ local function validate_collections(collections, schemas)
763
763
end
764
764
end
765
765
766
- --- Whether an object match set of PCRE.
767
- ---
768
- --- @tparam table obj an object to check
766
+ --- Whether an object match set of PCREs.
769
767
---
770
768
--- @tparam table pcre map with PCRE as values; names are correspond to field
771
769
--- names of the `obj` to match
772
770
---
771
+ --- @tparam table obj an object to check
772
+ ---
773
773
--- @treturn boolean `res` whether the `obj` object match `pcre` set of
774
774
--- regexps.
775
- local function match_using_re (obj , pcre )
775
+ local function match_using_re (pcre , obj )
776
776
if pcre == nil then return true end
777
777
778
778
assert (rex ~= nil , ' we should not pass over :compile() ' ..
@@ -785,38 +785,34 @@ local function match_using_re(obj, pcre)
785
785
return false
786
786
end
787
787
if type (re ) == ' table' then
788
- local match = match_using_re (obj [field_name ], re )
788
+ local match = match_using_re (re , obj [field_name ])
789
789
if not match then return false end
790
- else
791
- local flags = rex .flags ()
792
- -- emulate behaviour of (?i) on libpcre (libpcre2 supports it)
793
- local cfg = 0
794
- if not is_pcre2 then
795
- local cnt
796
- re , cnt = re :gsub (' ^%(%?i%)' , ' ' )
797
- if cnt > 0 then
798
- cfg = bit .bor (cfg , flags .CASELESS )
799
- end
800
- end
801
- -- enable UTF-8
802
- if is_pcre2 then
803
- cfg = bit .bor (cfg , flags .UTF )
804
- cfg = bit .bor (cfg , flags .UCP )
805
- else
806
- cfg = bit .bor (cfg , flags .UTF8 )
807
- cfg = bit .bor (cfg , flags .UCP )
808
- end
809
- -- XXX: compile re once
810
- local re = rex .new (re , cfg )
811
- if not re :match (obj [field_name ]) then
812
- return false
813
- end
790
+ elseif not utils .regexp (re , obj [field_name ]) then
791
+ return false
814
792
end
815
793
end
816
794
817
795
return true
818
796
end
819
797
798
+ --- Whether an object match an expression.
799
+ ---
800
+ --- @param expr (table or string ) compiled or raw expression
801
+ ---
802
+ --- @tparam table obj an object to check
803
+ ---
804
+ --- @tparam [opt] table variables variables values from the request
805
+ ---
806
+ --- @treturn boolean `res` whether the `obj` object match `expr` expression
807
+ local function match_using_expr (expr , obj , variables )
808
+ if expr == nil then return true end
809
+
810
+ check (expr , ' expression' , ' table' )
811
+ local res = expr :execute (obj , variables )
812
+ check (res , ' expression result' , ' boolean' )
813
+ return res
814
+ end
815
+
820
816
--- Check whether we meet deadline time.
821
817
---
822
818
--- The functions raises an exception in the case.
857
853
--- * `pivot_filter` (table, set of fields to match the objected pointed by
858
854
--- `offset` arqument of the GraphQL query),
859
855
--- * `resolveField` (function) for subrequests, see @{impl.new}.
856
+ --- * XXX: describe other fields.
860
857
---
861
858
--- @return nil
862
859
---
@@ -887,7 +884,9 @@ local function process_tuple(self, state, tuple, opts)
887
884
888
885
local collection_name = opts .collection_name
889
886
local pcre = opts .pcre
887
+ local expr = opts .expr
890
888
local resolveField = opts .resolveField
889
+ local variables = qcontext .variables
891
890
892
891
-- convert tuple -> object
893
892
local obj = opts .unflatten_tuple (self , collection_name , tuple ,
@@ -918,7 +917,7 @@ local function process_tuple(self, state, tuple, opts)
918
917
919
918
-- filter out non-matching objects
920
919
local match = utils .is_subtable (obj , truncated_filter ) and
921
- match_using_re (obj , pcre )
920
+ match_using_re (pcre , obj ) and match_using_expr ( expr , obj , variables )
922
921
if do_filter then
923
922
if not match then return true end
924
923
else
@@ -1058,6 +1057,13 @@ local function prepare_select_internal(self, collection_name, from, filter,
1058
1057
qcontext = qcontext
1059
1058
}
1060
1059
1060
+ -- compile an expression argument if provided and did not compiled yet
1061
+ local expr = args .filter
1062
+ check (expr , ' expression' , ' table' , ' string' , ' nil' )
1063
+ if type (expr ) == ' string' then
1064
+ expr = expressions .new (expr )
1065
+ end
1066
+
1061
1067
-- read only process_tuple options
1062
1068
local select_opts = {
1063
1069
limit = args .limit ,
@@ -1069,6 +1075,7 @@ local function prepare_select_internal(self, collection_name, from, filter,
1069
1075
use_tomap = self .collection_use_tomap [collection_name ] or false ,
1070
1076
default_unflatten_tuple = default_unflatten_tuple ,
1071
1077
pcre = args .pcre ,
1078
+ expr = expr ,
1072
1079
resolveField = extra .resolveField ,
1073
1080
is_hidden = extra .is_hidden ,
1074
1081
}
0 commit comments