@@ -922,8 +922,25 @@ local function process_tuple(state, tuple, opts)
922
922
return true
923
923
end
924
924
925
- --- The function is core of this module and implements logic of fetching and
926
- --- filtering requested objects.
925
+ --- This function is called on first select related to a query. Its purpose is
926
+ --- to initialize qcontext table.
927
+ ---
928
+ --- @tparam table accessor
929
+ --- @tparam table qcontext per-query table which stores query internal state;
930
+ --- all neccessary initialization of this parameter should be performed by this
931
+ --- function
932
+ local function init_qcontext (accessor , qcontext )
933
+ local settings = accessor .settings
934
+ qcontext .statistics = {
935
+ resulting_object_cnt = 0 ,
936
+ fetched_object_cnt = 0
937
+ }
938
+ qcontext .deadline_clock = clock .monotonic64 () +
939
+ settings .timeout_ms * 1000 * 1000
940
+ end
941
+
942
+ --- The function prepares context for tuples selection, postprocessing and
943
+ --- filtering.
927
944
---
928
945
--- @tparam table self the data accessor created by the `new` function
929
946
--- (directly or indirectly using the `accessor_space.new` or the
943
960
--- @tparam table extra table which contains extra information related to
944
961
--- current select and the whole query
945
962
---
946
- --- @treturn table list of matching objects
947
- local function select_internal (self , collection_name , from , filter , args , extra )
963
+ --- @treturn table `res` with `request_opts`, `select_state`, `select_opts` and
964
+ --- `args` fields
965
+ local function prepare_select (self , collection_name , from , filter , args , extra )
948
966
assert (type (self ) == ' table' ,
949
967
' self must be a table, got ' .. type (self ))
950
968
assert (type (collection_name ) == ' string' ,
@@ -976,6 +994,12 @@ local function select_internal(self, collection_name, from, filter, args, extra)
976
994
assert (args .pcre == nil or type (args .pcre ) == ' table' ,
977
995
' args.pcre must be nil or a table, got ' .. type (args .pcre ))
978
996
997
+ -- qcontext initialization
998
+ if extra .qcontext .initialized ~= true then
999
+ init_qcontext (self , extra .qcontext )
1000
+ extra .qcontext .initialized = true
1001
+ end
1002
+
979
1003
local collection = self .collections [collection_name ]
980
1004
assert (collection ~= nil ,
981
1005
(' cannot find the collection "%s"' ):format (
@@ -995,7 +1019,7 @@ local function select_internal(self, collection_name, from, filter, args, extra)
995
1019
index_name , collection_name ))
996
1020
end
997
1021
998
- -- lookup functions for unflattening
1022
+ -- lookup function for unflattening
999
1023
local schema_name = collection .schema_name
1000
1024
assert (type (schema_name ) == ' string' ,
1001
1025
' schema_name must be a string, got ' .. type (schema_name ))
@@ -1028,18 +1052,15 @@ local function select_internal(self, collection_name, from, filter, args, extra)
1028
1052
resolveField = extra .resolveField ,
1029
1053
}
1030
1054
1055
+ local iterator_opts = nil
1056
+
1031
1057
if index == nil then
1032
- -- fullscan
1033
- local primary_index = self .funcs .get_primary_index (collection_name )
1034
- for _ , tuple in primary_index :pairs () do
1035
- assert (pivot == nil ,
1036
- ' offset for top-level objects must use a primary index' )
1037
- local continue = process_tuple (select_state , tuple , select_opts )
1038
- if not continue then break end
1039
- end
1058
+ assert (pivot == nil ,
1059
+ ' offset for top-level objects must use a primary index' )
1060
+ index = self .funcs .get_primary_index (collection_name )
1061
+ index_value = nil
1040
1062
else
1041
- -- select by index
1042
- local iterator_opts = {}
1063
+ iterator_opts = iterator_opts or {}
1043
1064
if pivot ~= nil then
1044
1065
-- handle case when there is pivot item (offset was passed)
1045
1066
if pivot .value_list ~= nil then
@@ -1069,23 +1090,51 @@ local function select_internal(self, collection_name, from, filter, args, extra)
1069
1090
if full_match and args .limit ~= nil then
1070
1091
iterator_opts .limit = args .limit
1071
1092
end
1072
-
1073
- for _ , tuple in index :pairs (index_value , iterator_opts ) do
1074
- local continue = process_tuple (select_state , tuple , select_opts )
1075
- if not continue then break end
1076
- end
1077
1093
end
1078
1094
1079
- local count = select_state .count
1080
- local objs = select_state .objs
1095
+ -- request options can be changed below
1096
+ local request_opts = {
1097
+ index = index ,
1098
+ index_value = index_value ,
1099
+ iterator_opts = iterator_opts ,
1100
+ }
1081
1101
1082
- assert (args .limit == nil or count <= args .limit ,
1083
- (' count[%d] exceeds limit[%s] (before return)' ):format (
1084
- count , args .limit ))
1085
- assert (# objs == count ,
1086
- (' count[%d] is not equal to objs count[%d]' ):format (count , # objs ))
1102
+ return {
1103
+ request_opts = request_opts ,
1104
+ select_state = select_state ,
1105
+ select_opts = select_opts ,
1106
+ args = args ,
1107
+ }
1108
+ end
1087
1109
1088
- return objs
1110
+ --- XXX
1111
+ local function invoke_select (prepared_select )
1112
+ local request_opts = prepared_select .request_opts
1113
+ local select_state = prepared_select .select_state
1114
+ local select_opts = prepared_select .select_opts
1115
+ local args = prepared_select .args
1116
+
1117
+ local index = request_opts .index
1118
+ local index_value = request_opts .index_value
1119
+ local iterator_opts = request_opts .iterator_opts
1120
+
1121
+ for _ , tuple in index :pairs (index_value , iterator_opts ) do
1122
+ local continue = process_tuple (select_state , tuple ,
1123
+ select_opts )
1124
+ if not continue then break end
1125
+ end
1126
+
1127
+ local count = select_state .count
1128
+ local objs = select_state .objs
1129
+
1130
+ assert (args .limit == nil or count <= args .limit ,
1131
+ (' count[%d] exceeds limit[%s] (before return)' ):format (
1132
+ count , args .limit ))
1133
+ assert (# objs == count ,
1134
+ (' count[%d] is not equal to objs count[%d]' ):format (
1135
+ count , # objs ))
1136
+
1137
+ return objs
1089
1138
end
1090
1139
1091
1140
--- Set of asserts to check the `funcs` argument of the @{accessor_general.new}
@@ -1110,22 +1159,6 @@ local function validate_funcs(funcs)
1110
1159
type (funcs .unflatten_tuple ))
1111
1160
end
1112
1161
1113
- --- This function is called on first select related to a query. Its purpose is
1114
- --- to initialize qcontext table.
1115
- --- @tparam table accessor
1116
- --- @tparam table qcontext per-query table which stores query internal state;
1117
- --- all neccessary initialization of this parameter should be performed by this
1118
- -- function
1119
- local function init_qcontext (accessor , qcontext )
1120
- local settings = accessor .settings
1121
- qcontext .statistics = {
1122
- resulting_object_cnt = 0 ,
1123
- fetched_object_cnt = 0
1124
- }
1125
- qcontext .deadline_clock = clock .monotonic64 () +
1126
- settings .timeout_ms * 1000 * 1000
1127
- end
1128
-
1129
1162
--- Get an avro-schema for a primary key by a collection name.
1130
1163
---
1131
1164
--- @tparam table self accessor_general instance
@@ -1273,9 +1306,8 @@ end
1273
1306
--- ...
1274
1307
--- }
1275
1308
---
1276
- --- @treturn table data accessor instance, a table with the two methods
1277
- --- (`select` and `arguments`) as described in the @{tarantool_graphql.new}
1278
- --- function description.
1309
+ --- @treturn table data accessor instance, a table with the methods as
1310
+ --- described in the @{tarantool_graphql.new} function description.
1279
1311
function accessor_general .new (opts , funcs )
1280
1312
assert (type (opts ) == ' table' ,
1281
1313
' opts must be a table, got ' .. type (opts ))
@@ -1352,26 +1384,18 @@ function accessor_general.new(opts, funcs)
1352
1384
__index = {
1353
1385
select = function (self , parent , collection_name , from ,
1354
1386
filter , args , extra )
1355
- assert (type (parent ) == ' table' ,
1356
- ' parent must be a table, got ' .. type (parent ))
1357
- assert (from == nil or type (from ) == ' table' ,
1358
- ' from must be nil or a string, got ' .. type (from ))
1359
- assert (from == nil or type (from .collection_name ) == ' string' ,
1360
- ' from must be nil or from.collection_name ' ..
1361
- ' must be a string, got ' ..
1362
- type ((from or {}).collection_name ))
1363
- assert (from == nil or type (from .connection_name ) == ' string' ,
1364
- ' from must be nil or from.connection_name ' ..
1365
- ' must be a string, got ' ..
1366
- type ((from or {}).connection_name ))
1367
- -- `qcontext` initialization
1368
- if extra .qcontext .initialized ~= true then
1369
- init_qcontext (self , extra .qcontext )
1370
- extra .qcontext .initialized = true
1371
- end
1372
- return select_internal (self , collection_name , from , filter ,
1387
+ local prepared_select = prepare_select (self , collection_name ,
1388
+ from , filter , args , extra )
1389
+ return invoke_select (prepared_select )
1390
+ end ,
1391
+ prepare_select = function (self , parent , collection_name , from ,
1392
+ filter , args , extra )
1393
+ return prepare_select (self , collection_name , from , filter ,
1373
1394
args , extra )
1374
1395
end ,
1396
+ invoke_select = function (self , prepared_select )
1397
+ return invoke_select (prepared_select )
1398
+ end ,
1375
1399
list_args = function (self , collection_name )
1376
1400
local offset_type = get_primary_key_type (self , collection_name )
1377
1401
0 commit comments