@@ -990,6 +990,7 @@ local function select_internal(self, collection_name, from, filter, args, extra)
990
990
-- XXX: save type of args.offset at parsing and check here
991
991
-- check(args.offset, 'args.offset', ...)
992
992
check (args .pcre , ' args.pcre' , ' table' , ' nil' )
993
+ check (extra .exp_tuple_count , ' extra.exp_tuple_count' , ' number' , ' nil' )
993
994
994
995
local collection = self .collections [collection_name ]
995
996
assert (collection ~= nil ,
@@ -1043,6 +1044,18 @@ local function select_internal(self, collection_name, from, filter, args, extra)
1043
1044
resolveField = extra .resolveField ,
1044
1045
}
1045
1046
1047
+ -- assert that connection constraint applied only to objects got from the
1048
+ -- index that underlies the connection
1049
+ if extra .exp_tuple_count ~= nil then
1050
+ local err = ' internal error: connection constraint (expected tuple ' ..
1051
+ ' count) cannot be applied to an index that is not under a ' ..
1052
+ ' connection'
1053
+ assert (from .collection_name ~= nil , err )
1054
+ assert (index ~= nil , err )
1055
+ assert (pivot == nil or (pivot .value_list == nil and
1056
+ pivot .filter ~= nil ), err )
1057
+ end
1058
+
1046
1059
if index == nil then
1047
1060
-- fullscan
1048
1061
local primary_index = self .funcs .get_primary_index (self ,
@@ -1087,21 +1100,38 @@ local function select_internal(self, collection_name, from, filter, args, extra)
1087
1100
iterator_opts .limit = args .limit
1088
1101
end
1089
1102
1103
+ local tuple_count = 0
1104
+
1090
1105
for _ , tuple in index :pairs (index_value , iterator_opts ) do
1106
+ tuple_count = tuple_count + 1
1107
+ -- check full match constraint
1108
+ if extra .exp_tuple_count ~= nil and
1109
+ tuple_count > extra .exp_tuple_count then
1110
+ error ((' FULL MATCH constraint was failed: we got more then ' ..
1111
+ ' %d tuples' ):format (extra .exp_tuple_count ))
1112
+ end
1091
1113
local continue = process_tuple (self , select_state , tuple ,
1092
1114
select_opts )
1093
1115
if not continue then break end
1094
1116
end
1117
+
1118
+ -- check full match constraint
1119
+ if extra .exp_tuple_count ~= nil and
1120
+ tuple_count ~= extra .exp_tuple_count then
1121
+ error ((' FULL MATCH constraint was failed: we expect %d tuples, ' ..
1122
+ ' got %d' ):format (extra .exp_tuple_count , tuple_count ))
1123
+ end
1095
1124
end
1096
1125
1097
1126
local count = select_state .count
1098
1127
local objs = select_state .objs
1099
1128
1100
1129
assert (args .limit == nil or count <= args .limit ,
1101
- (' count[%d] exceeds limit[%s] (before return )' ): format (
1102
- count , args .limit ))
1130
+ (' internal error: selected objects count (%d) exceeds limit (%s )' )
1131
+ : format ( count , args .limit ))
1103
1132
assert (# objs == count ,
1104
- (' count[%d] is not equal to objs count[%d]' ):format (count , # objs ))
1133
+ (' internal error: selected objects count (%d) is not equal size of ' ..
1134
+ ' selected object list (%d)' ):format (count , # objs ))
1105
1135
1106
1136
return objs
1107
1137
end
@@ -1382,6 +1412,25 @@ end
1382
1412
--- @treturn table data accessor instance, a table with the two methods
1383
1413
--- (`select` and `arguments`) as described in the @{impl.new} function
1384
1414
--- description.
1415
+ ---
1416
+ --- Brief explanation of some select function parameters:
1417
+ ---
1418
+ --- * `from` (table or nil) is nil for a top-level collection or a table with
1419
+ --- the following fields:
1420
+ ---
1421
+ --- - collection_name
1422
+ --- - connection_name
1423
+ --- - destination_args_names
1424
+ --- - destination_args_values
1425
+ ---
1426
+ --- * `extra` (table) is a table which contains additional data for the query:
1427
+ ---
1428
+ --- - `qcontext` (table) can be used by an accessor to store any
1429
+ --- query-related data;
1430
+ --- - `resolveField(field_name, object, filter, opts)` (function) for
1431
+ --- performing a subrequest on a fields connected using a 1:1 connection.
1432
+ --- - extra_args
1433
+ --- - exp_tuple_count
1385
1434
function accessor_general .new (opts , funcs )
1386
1435
assert (type (opts ) == ' table' ,
1387
1436
' opts must be a table, got ' .. type (opts ))
0 commit comments