@@ -975,8 +975,8 @@ local function perform_primary_key_operation(self, collection_name, schema_name,
975
975
return new_objects
976
976
end
977
977
978
- --- The function is core of this module and implements logic of fetching and
979
- --- filtering requested objects .
978
+ --- The function prepares context for tuples selection, postprocessing and
979
+ --- filtering.
980
980
---
981
981
--- @tparam table self the data accessor created by the `new` function
982
982
--- (directly or indirectly using the `accessor_space.new` or the
996
996
--- @tparam table extra table which contains extra information related to
997
997
--- current select and the whole query
998
998
---
999
- --- @treturn table list of matching objects
1000
- local function select_internal (self , collection_name , from , filter , args , extra )
999
+ --- @treturn table `res` with `request_opts`, `select_state`, `select_opts` and
1000
+ --- `args` fields
1001
+ local function prepare_select_internal (self , collection_name , from , filter ,
1002
+ args , extra )
1001
1003
check (self , ' self' , ' table' )
1002
1004
check (collection_name , ' collection_name' , ' string' )
1003
1005
check (from , ' from' , ' table' )
@@ -1028,7 +1030,7 @@ local function select_internal(self, collection_name, from, filter, args, extra)
1028
1030
index_name , collection_name ))
1029
1031
end
1030
1032
1031
- -- lookup functions for unflattening
1033
+ -- lookup function for unflattening
1032
1034
local schema_name = collection .schema_name
1033
1035
assert (type (schema_name ) == ' string' ,
1034
1036
' schema_name must be a string, got ' .. type (schema_name ))
@@ -1075,27 +1077,17 @@ local function select_internal(self, collection_name, from, filter, args, extra)
1075
1077
pivot .filter ~= nil ), err )
1076
1078
end
1077
1079
1078
- if index == nil then
1079
- -- fullscan
1080
- local primary_index = self .funcs .get_primary_index (self ,
1081
- collection_name )
1082
-
1083
- -- count full scan select request
1084
- qcontext .statistics .select_requests_cnt =
1085
- qcontext .statistics .select_requests_cnt + 1
1086
- qcontext .statistics .full_scan_select_requests_cnt =
1087
- qcontext .statistics .full_scan_select_requests_cnt + 1
1080
+ local iterator_opts = nil
1081
+ local is_full_scan
1088
1082
1089
- for _ , tuple in primary_index :pairs () do
1090
- assert (pivot == nil ,
1091
- ' offset for top-level objects must use a primary index' )
1092
- local continue = process_tuple (self , select_state , tuple ,
1093
- select_opts )
1094
- if not continue then break end
1095
- end
1083
+ if index == nil then
1084
+ assert (pivot == nil ,
1085
+ ' offset for top-level objects must use a primary index' )
1086
+ index = self .funcs .get_primary_index (self , collection_name )
1087
+ index_value = nil
1088
+ is_full_scan = true
1096
1089
else
1097
- -- select by index
1098
- local iterator_opts = {}
1090
+ iterator_opts = iterator_opts or {}
1099
1091
if pivot ~= nil then
1100
1092
-- handle case when there is pivot item (offset was passed)
1101
1093
if pivot .value_list ~= nil then
@@ -1126,33 +1118,80 @@ local function select_internal(self, collection_name, from, filter, args, extra)
1126
1118
iterator_opts .limit = args .limit
1127
1119
end
1128
1120
1129
- local tuple_count = 0
1121
+ is_full_scan = false
1122
+ end
1123
+
1124
+ -- request options can be changed below
1125
+ local request_opts = {
1126
+ index = index ,
1127
+ index_value = index_value ,
1128
+ iterator_opts = iterator_opts ,
1129
+ is_full_scan = is_full_scan ,
1130
+ }
1130
1131
1132
+ return {
1133
+ request_opts = request_opts ,
1134
+ select_state = select_state ,
1135
+ select_opts = select_opts ,
1136
+ collection_name = collection_name ,
1137
+ from = from ,
1138
+ filter = filter ,
1139
+ args = args ,
1140
+ extra = extra ,
1141
+ }
1142
+ end
1143
+
1144
+ --- XXX
1145
+ local function invoke_select_internal (self , prepared_select )
1146
+ local request_opts = prepared_select .request_opts
1147
+ local select_state = prepared_select .select_state
1148
+ local select_opts = prepared_select .select_opts
1149
+ local args = prepared_select .args
1150
+ local extra = prepared_select .extra
1151
+
1152
+ local index = request_opts .index
1153
+ local index_value = request_opts .index_value
1154
+ local iterator_opts = request_opts .iterator_opts
1155
+ local is_full_scan = request_opts .is_full_scan
1156
+
1157
+ local qcontext = extra .qcontext
1158
+
1159
+ -- count all select request
1160
+ qcontext .statistics .select_requests_cnt =
1161
+ qcontext .statistics .select_requests_cnt + 1
1162
+
1163
+ if is_full_scan then
1164
+ -- count full scan select request
1165
+ qcontext .statistics .full_scan_select_requests_cnt =
1166
+ qcontext .statistics .full_scan_select_requests_cnt + 1
1167
+ else
1131
1168
-- count index select request
1132
- qcontext .statistics .select_requests_cnt =
1133
- qcontext .statistics .select_requests_cnt + 1
1134
1169
qcontext .statistics .index_select_requests_cnt =
1135
1170
qcontext .statistics .index_select_requests_cnt + 1
1171
+ end
1136
1172
1137
- for _ , tuple in index :pairs (index_value , iterator_opts ) do
1138
- tuple_count = tuple_count + 1
1139
- -- check full match constraint
1140
- if extra .exp_tuple_count ~= nil and
1141
- tuple_count > extra .exp_tuple_count then
1142
- error ((' FULL MATCH constraint was failed: we got more then ' ..
1143
- ' %d tuples' ):format (extra .exp_tuple_count ))
1144
- end
1145
- local continue = process_tuple (self , select_state , tuple ,
1146
- select_opts )
1147
- if not continue then break end
1148
- end
1173
+ local tuple_count = 0
1174
+
1175
+ for _ , tuple in index :pairs (index_value , iterator_opts ) do
1176
+ tuple_count = tuple_count + 1
1149
1177
1150
1178
-- check full match constraint
1151
1179
if extra .exp_tuple_count ~= nil and
1152
- tuple_count ~= extra .exp_tuple_count then
1153
- error ((' FULL MATCH constraint was failed: we expect %d tuples, ' ..
1154
- ' got %d ' ):format (extra .exp_tuple_count , tuple_count ))
1180
+ tuple_count > extra .exp_tuple_count then
1181
+ error ((' FULL MATCH constraint was failed: we got more then ' ..
1182
+ ' %d tuples ' ):format (extra .exp_tuple_count ))
1155
1183
end
1184
+
1185
+ local continue = process_tuple (self , select_state , tuple ,
1186
+ select_opts )
1187
+ if not continue then break end
1188
+ end
1189
+
1190
+ -- check full match constraint
1191
+ if extra .exp_tuple_count ~= nil and
1192
+ tuple_count ~= extra .exp_tuple_count then
1193
+ error ((' FULL MATCH constraint was failed: we expect %d tuples, ' ..
1194
+ ' got %d' ):format (extra .exp_tuple_count , tuple_count ))
1156
1195
end
1157
1196
1158
1197
local count = select_state .count
@@ -1344,6 +1383,8 @@ end
1344
1383
--- all neccessary initialization of this parameter should be performed by this
1345
1384
-- function
1346
1385
local function init_qcontext (accessor , qcontext )
1386
+ if qcontext .initialized then return end
1387
+
1347
1388
for k , v in pairs (accessor .query_settings_default ) do
1348
1389
if qcontext .query_settings [k ] == nil then
1349
1390
qcontext .query_settings [k ] = v
@@ -1361,6 +1402,8 @@ local function init_qcontext(accessor, qcontext)
1361
1402
full_scan_select_requests_cnt = 0 ,
1362
1403
index_select_requests_cnt = 0 ,
1363
1404
}
1405
+
1406
+ qcontext .initialized = true
1364
1407
end
1365
1408
1366
1409
--- Create default unflatten/flatten/xflatten functions, that can be called
@@ -1479,9 +1522,8 @@ end
1479
1522
--- `accessor_space` and the `accessor_shard` modules documentation for these
1480
1523
--- functions description.
1481
1524
---
1482
- --- @treturn table data accessor instance, a table with the two methods
1483
- --- (`select` and `arguments`) as described in the @{impl.new} function
1484
- --- description.
1525
+ --- @treturn table data accessor instance, a table with the methods as
1526
+ --- described in the @{impl.new} function description.
1485
1527
---
1486
1528
--- Brief explanation of some select function parameters:
1487
1529
---
@@ -1572,21 +1614,13 @@ function accessor_general.new(opts, funcs)
1572
1614
__index = {
1573
1615
select = function (self , parent , collection_name , from ,
1574
1616
filter , args , extra )
1575
- check (parent , ' parent' , ' table' )
1576
- validate_from_parameter (from )
1577
-
1578
- -- `qcontext` initialization
1579
- if extra .qcontext .initialized ~= true then
1580
- init_qcontext (self , extra .qcontext )
1581
- extra .qcontext .initialized = true
1582
- end
1583
-
1584
1617
local inserted = insert_internal (self , collection_name , from ,
1585
1618
filter , args , extra )
1586
1619
if inserted ~= nil then return inserted end
1587
1620
1588
- local selected = select_internal (self , collection_name , from , filter ,
1589
- args , extra )
1621
+ local prepared_select = self :prepare_select (parent ,
1622
+ collection_name , from , filter , args , extra )
1623
+ local selected = self :invoke_select (prepared_select )
1590
1624
1591
1625
local updated = update_internal (self , collection_name , extra ,
1592
1626
selected )
@@ -1598,6 +1632,17 @@ function accessor_general.new(opts, funcs)
1598
1632
1599
1633
return selected
1600
1634
end ,
1635
+ prepare_select = function (self , parent , collection_name , from ,
1636
+ filter , args , extra )
1637
+ check (parent , ' parent' , ' table' )
1638
+ validate_from_parameter (from )
1639
+
1640
+ init_qcontext (self , extra .qcontext )
1641
+
1642
+ return prepare_select_internal (self , collection_name , from ,
1643
+ filter , args , extra )
1644
+ end ,
1645
+ invoke_select = invoke_select_internal ,
1601
1646
}
1602
1647
})
1603
1648
end
0 commit comments