aerospike 2.23.0 → 2.25.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,403 @@
1
+ # encoding: utf-8
2
+ # Copyright 2014-2022 Aerospike, Inc.
3
+ #
4
+ # Portions may be licensed to Aerospike, Inc. under one or more contributor
5
+ # license agreements.
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License") you may n
8
+ # use this file except in compliance with the License. You may obtain a copy of
9
+ # the License at http:#www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ # License for the specific language governing permissions and limitations under
15
+ # the License.
16
+
17
+ module Aerospike
18
+
19
+ # List expression generator. See {@link Exp}.
20
+ #
21
+ # The bin expression argument in these methods can be a reference to a bin or the
22
+ # result of another expression. Expressions that modify bin values are only used
23
+ # for temporary expression evaluation and are not permanently applied to the bin.
24
+ #
25
+ # List modify expressions the bin's value. This value will be a list except
26
+ # when the list is nested within a map. In that case, a map is returned for the
27
+ # list modify expression.
28
+ #
29
+ # List expressions support negative indexing. If the index is negative, the
30
+ # resolved index starts backwards from end of list. If an index is out of bounds,
31
+ # a parameter error will be returned. If a range is partially out of bounds, the
32
+ # valid part of the range will be returned. Index/Range examples:
33
+ #
34
+ # Index 0: First item in list.
35
+ # Index 4: Fifth item in list.
36
+ # Index -1: Last item in list.
37
+ # Index -3: Third to last item in list.
38
+ # Index 1 Count 2: Second and third items in list.
39
+ # Index -3 Count 3: Last three items in list.
40
+ # Index -5 Count 4: Range between fifth to last item to second to last item inclusive.
41
+ #
42
+ # Nested expressions are supported by optional CTX context arguments. Example:
43
+ #
44
+ # bin = [[7,9,5],[1,2,3],[6,5,4,1]]
45
+ # Get size of last list.
46
+ # ListExp.size(Exp.listBin("bin"), CTX.listIndex(-1))
47
+ # result = 4
48
+ class Exp::List
49
+
50
+ # Create expression that appends value to end of list.
51
+ def self.append(value, bin, ctx: nil, policy: CDT::ListPolicy::DEFAULT)
52
+ bytes = Exp.pack(ctx, APPEND, value, policy.order, policy.flags)
53
+ self.add_write(bin, bytes, ctx)
54
+ end
55
+
56
+ # Create expression that appends list items to end of list.
57
+ def self.append_items(list, bin, ctx: nil, policy: CDT::ListPolicy::DEFAULT)
58
+ bytes = Exp.pack(ctx, APPEND_ITEMS, list, policy.order, policy.flags)
59
+ self.add_write(bin, bytes, ctx)
60
+ end
61
+
62
+ # Create expression that inserts value to specified index of list.
63
+ def self.insert(index, value, bin, ctx: nil, policy: CDT::ListPolicy::DEFAULT)
64
+ bytes = Exp.pack(ctx, INSERT, index, value, policy.flags)
65
+ self.add_write(bin, bytes, ctx)
66
+ end
67
+
68
+ # Create expression that inserts each input list item starting at specified index of list.
69
+ def self.insert_items(index, list, bin, ctx: nil, policy: CDT::ListPolicy::DEFAULT)
70
+ bytes = Exp.pack(ctx, INSERT_ITEMS, index, list, policy.flags)
71
+ self.add_write(bin, bytes, ctx)
72
+ end
73
+
74
+ # Create expression that increments list[index] by value.
75
+ # Value expression should resolve to a number.
76
+ def self.increment(index, value, bin, ctx: nil, policy: CDT::ListPolicy::DEFAULT)
77
+ bytes = Exp.pack(ctx, INCREMENT, index, value, policy.order, policy.flags)
78
+ self.add_write(bin, bytes, ctx)
79
+ end
80
+
81
+ # Create expression that sets item value at specified index in list.
82
+ def self.set(index, value, bin, ctx: nil, policy: CDT::ListPolicy::DEFAULT)
83
+ bytes = Exp.pack(ctx, SET, index, value, policy.flags)
84
+ self.add_write(bin, bytes, ctx)
85
+ end
86
+
87
+ # Create expression that removes all items in list.
88
+ def self.clear(bin, ctx: nil)
89
+ bytes = Exp.pack(ctx, CLEAR)
90
+ self.add_write(bin, bytes, ctx)
91
+ end
92
+
93
+ # Create expression that sorts list according to sort_flags.
94
+ #
95
+ # @param sort_flags sort flags. See {@link ListSortFlagsend.
96
+ # @param bin bin or list value expression
97
+ # @param ctx optional context path for nested CDT
98
+ def self.sort(sort_flags, bin, ctx: nil)
99
+ bytes = Exp.pack(ctx, SORT, sort_flags)
100
+ self.add_write(bin, bytes, ctx)
101
+ end
102
+
103
+ # Create expression that removes list items identified by value.
104
+ def self.remove_by_value(value, bin, ctx: nil)
105
+ bytes = Exp.pack(ctx, REMOVE_BY_VALUE, CDT::ListReturnType::NONE, value)
106
+ self.add_write(bin, bytes, ctx)
107
+ end
108
+
109
+ # Create expression that removes list items identified by values.
110
+ def self.remove_by_value_list(values, bin, ctx: nil)
111
+ bytes = Exp.pack(ctx, REMOVE_BY_VALUE_LIST, CDT::ListReturnType::NONE, values)
112
+ self.add_write(bin, bytes, ctx)
113
+ end
114
+
115
+ # Create expression that removes list items identified by value range (value_begin inclusive, value_end exclusive).
116
+ # If value_begin is nil, the range is less than value_end. If value_end is nil, the range is
117
+ # greater than equal to value_begin.
118
+ def self.remove_by_value_range(value_begin, value_end, bin, ctx: nil)
119
+ bytes = self.pack_range_operation(REMOVE_BY_VALUE_INTERVAL, CDT::ListReturnType::NONE, value_begin, value_end, ctx)
120
+ self.add_write(bin, bytes, ctx)
121
+ end
122
+
123
+ # Create expression that removes list items nearest to value and greater by relative rank with a count limit if provided.
124
+ #
125
+ # Examples for ordered list [0,4,5,9,11,15]:
126
+ #
127
+ # (value,rank,count) = [removed items]
128
+ # (5,0,2) = [5,9]
129
+ # (5,1,1) = [9]
130
+ # (5,-1,2) = [4,5]
131
+ # (3,0,1) = [4]
132
+ # (3,3,7) = [11,15]
133
+ # (3,-3,2) = []
134
+ def self.remove_by_value_relative_rank_range(value, rank, bin, ctx: nil, count: nil)
135
+ unless count.nil?
136
+ bytes = Exp.pack(ctx, REMOVE_BY_VALUE_REL_RANK_RANGE, CDT::ListReturnType::NONE, value, rank, count)
137
+ else
138
+ bytes = Exp.pack(ctx, REMOVE_BY_VALUE_REL_RANK_RANGE, CDT::ListReturnType::NONE, value, rank)
139
+ end
140
+ self.add_write(bin, bytes, ctx)
141
+ end
142
+
143
+ # Create expression that removes list item identified by index.
144
+ def self.remove_by_index(index, bin, ctx: nil)
145
+ bytes = Exp.pack(ctx, REMOVE_BY_INDEX, CDT::ListReturnType::NONE, index)
146
+ self.add_write(bin, bytes, ctx)
147
+ end
148
+
149
+ # Create expression that removes "count" list items starting at specified index.
150
+ def self.remove_by_index_range(index, bin, ctx: nil, count: nil)
151
+ unless count.nil?
152
+ bytes = Exp.pack(ctx, REMOVE_BY_INDEX_RANGE, CDT::ListReturnType::NONE, index, count)
153
+ else
154
+ bytes = Exp.pack(ctx, REMOVE_BY_INDEX_RANGE, CDT::ListReturnType::NONE, index)
155
+ end
156
+ self.add_write(bin, bytes, ctx)
157
+ end
158
+
159
+ # Create expression that removes list item identified by rank.
160
+ def self.remove_by_rank(rank, bin, ctx: nil)
161
+ bytes = Exp.pack(ctx, REMOVE_BY_RANK, CDT::ListReturnType::NONE, rank)
162
+ self.add_write(bin, bytes, ctx)
163
+ end
164
+
165
+ # Create expression that removes "count" list items starting at specified rank.
166
+ def self.remove_by_rank_range(rank, bin, ctx: nil, count: nil)
167
+ unless count.nil?
168
+ bytes = Exp.pack(ctx, REMOVE_BY_RANK_RANGE, CDT::ListReturnType::NONE, rank, count)
169
+ else
170
+ bytes = Exp.pack(ctx, REMOVE_BY_RANK_RANGE, CDT::ListReturnType::NONE, rank)
171
+ end
172
+ self.add_write(bin, bytes, ctx)
173
+ end
174
+
175
+ # Create expression that returns list size.
176
+ #
177
+ # ==== Examples
178
+ # # List bin "a" size > 7
179
+ # Exp.gt(ListExp.size(Exp.listBin("a")), Exp.val(7))
180
+ # end</pre>
181
+ def self.size(bin, ctx: nil)
182
+ bytes = Exp.pack(ctx, SIZE)
183
+ self.add_read(bin, bytes, Exp::Type::INT)
184
+ end
185
+
186
+ # Create expression that selects list items identified by value and returns selected
187
+ # data specified by return_type.
188
+ #
189
+ # ==== Examples
190
+ # # List bin "a" contains at least one item == "abc"
191
+ # Exp.gt(
192
+ # ListExp.getByValue(CDT::ListReturnType::COUNT, Exp.val("abc"), Exp.listBin("a")),
193
+ # Exp.val(0))
194
+ # end</pre>
195
+ #
196
+ # @param return_type metadata attributes to return. See {@link CDT::ListReturnTypeend
197
+ # @param value search expression
198
+ # @param bin list bin or list value expression
199
+ # @param ctx optional context path for nested CDT
200
+ def self.get_by_value(return_type, value, bin, ctx: nil)
201
+ bytes = Exp.pack(ctx, GET_BY_VALUE, return_type, value)
202
+ self.add_read(bin, bytes, get_value_type(return_type))
203
+ end
204
+
205
+ # Create expression that selects list items identified by value range and returns selected data
206
+ # specified by return_type.
207
+ #
208
+ # ==== Examples
209
+ # # List bin "a" items >= 10 && items < 20
210
+ # ListExp.getByValueRange(CDT::ListReturnType::VALUE, Exp.val(10), Exp.val(20), Exp.listBin("a"))
211
+ # end</pre>
212
+ #
213
+ # @param return_type metadata attributes to return. See {@link CDT::ListReturnTypeend
214
+ # @param value_begin begin expression inclusive. If nil, range is less than value_end.
215
+ # @param value_end end expression exclusive. If nil, range is greater than equal to value_begin.
216
+ # @param bin bin or list value expression
217
+ # @param ctx optional context path for nested CDT
218
+ def self.get_by_value_range(return_type, value_begin, value_end, bin, ctx: nil)
219
+ bytes = self.pack_range_operation(GET_BY_VALUE_INTERVAL, return_type, value_begin, value_end, ctx)
220
+ self.add_read(bin, bytes, get_value_type(return_type))
221
+ end
222
+
223
+ # Create expression that selects list items identified by values and returns selected data
224
+ # specified by return_type.
225
+ def self.get_by_value_list(return_type, values, bin, ctx: nil)
226
+ bytes = Exp.pack(ctx, GET_BY_VALUE_LIST, return_type, values)
227
+ self.add_read(bin, bytes, get_value_type(return_type))
228
+ end
229
+
230
+ # Create expression that selects list items nearest to value and greater by relative rank with a count limit
231
+ # and returns selected data specified by return_type (See {@link CDT::ListReturnTypeend).
232
+ #
233
+ # Examples for ordered list [0,4,5,9,11,15]:
234
+ #
235
+ # (value,rank,count) = [selected items]
236
+ # (5,0,2) = [5,9]
237
+ # (5,1,1) = [9]
238
+ # (5,-1,2) = [4,5]
239
+ # (3,0,1) = [4]
240
+ # (3,3,7) = [11,15]
241
+ # (3,-3,2) = []
242
+ def self.get_by_value_relative_rank_range(return_type, value, rank, bin, ctx: nil, count: nil)
243
+ unless count.nil?
244
+ bytes = Exp.pack(ctx, GET_BY_VALUE_REL_RANK_RANGE, return_type, value, rank, count)
245
+ else
246
+ bytes = Exp.pack(ctx, GET_BY_VALUE_REL_RANK_RANGE, return_type, value, rank)
247
+ end
248
+ self.add_read(bin, bytes, get_value_type(return_type))
249
+ end
250
+
251
+ # Create expression that selects list item identified by index and returns
252
+ # selected data specified by return_type.
253
+ #
254
+ # ==== Examples
255
+ # # a[3] == 5
256
+ # Exp.eq(
257
+ # ListExp.getByIndex(CDT::ListReturnType::VALUE, Exp::Type::INT, Exp.val(3), Exp.listBin("a")),
258
+ # Exp.val(5))
259
+ # end</pre>
260
+ #
261
+ # @param return_type metadata attributes to return. See {@link CDT::ListReturnTypeend
262
+ # @param value_type expected type of value
263
+ # @param index list index expression
264
+ # @param bin list bin or list value expression
265
+ # @param ctx optional context path for nested CDT
266
+ def self.get_by_index(return_type, value_type, index, bin, ctx: nil)
267
+ bytes = Exp.pack(ctx, GET_BY_INDEX, return_type, index)
268
+ self.add_read(bin, bytes, value_type)
269
+ end
270
+
271
+ # Create expression that selects list items starting at specified index to the end of list
272
+ # and returns selected data specified by return_type (See {@link CDT::ListReturnTypeend).
273
+ def self.get_by_index_range(return_type, index, bin, ctx: nil)
274
+ bytes = Exp.pack(ctx, GET_BY_INDEX_RANGE, return_type, index)
275
+ self.add_read(bin, bytes, get_value_type(return_type))
276
+ end
277
+
278
+ # Create expression that selects "count" list items starting at specified index
279
+ # and returns selected data specified by return_type (See {@link CDT::ListReturnTypeend).
280
+ def self.get_by_index_range(return_type, index, bin, ctx: nil, count: nil)
281
+ unless count.nil?
282
+ bytes = Exp.pack(ctx, GET_BY_INDEX_RANGE, return_type, index, count)
283
+ else
284
+ bytes = Exp.pack(ctx, GET_BY_INDEX_RANGE, return_type, index)
285
+ end
286
+ self.add_read(bin, bytes, get_value_type(return_type))
287
+ end
288
+
289
+ # Create expression that selects list item identified by rank and returns selected
290
+ # data specified by return_type.
291
+ #
292
+ # ==== Examples
293
+ # # Player with lowest score.
294
+ # ListExp.getByRank(CDT::ListReturnType::VALUE, Type.STRING, Exp.val(0), Exp.listBin("a"))
295
+ # end</pre>
296
+ #
297
+ # @param return_type metadata attributes to return. See {@link CDT::ListReturnTypeend
298
+ # @param value_type expected type of value
299
+ # @param rank rank expression
300
+ # @param bin list bin or list value expression
301
+ # @param ctx optional context path for nested CDT
302
+ def self.get_by_rank(return_type, value_type, rank, bin, ctx: nil)
303
+ bytes = Exp.pack(ctx, GET_BY_RANK, return_type, rank)
304
+ self.add_read(bin, bytes, value_type)
305
+ end
306
+
307
+ # Create expression that selects list items starting at specified rank to the last ranked item
308
+ # and returns selected data specified by return_type (See {@link CDT::ListReturnTypeend).
309
+ def self.get_by_rank_range(return_type, rank, bin, ctx: nil)
310
+ bytes = Exp.pack(ctx, GET_BY_RANK_RANGE, return_type, rank)
311
+ self.add_read(bin, bytes, get_value_type(return_type))
312
+ end
313
+
314
+ # Create expression that selects "count" list items starting at specified rank and returns
315
+ # selected data specified by return_type (See {@link CDT::ListReturnTypeend).
316
+ def self.get_by_rank_range(return_type, rank, bin, ctx: nil, count: nil)
317
+ unless count.nil?
318
+ bytes = Exp.pack(ctx, GET_BY_RANK_RANGE, return_type, rank, count)
319
+ else
320
+ bytes = Exp.pack(ctx, GET_BY_RANK_RANGE, return_type, rank)
321
+ end
322
+ self.add_read(bin, bytes, get_value_type(return_type))
323
+ end
324
+
325
+ private
326
+
327
+ MODULE = 0
328
+ APPEND = 1
329
+ APPEND_ITEMS = 2
330
+ INSERT = 3
331
+ INSERT_ITEMS = 4
332
+ SET = 9
333
+ CLEAR = 11
334
+ INCREMENT = 12
335
+ SORT = 13
336
+ SIZE = 16
337
+ GET_BY_INDEX = 19
338
+ GET_BY_RANK = 21
339
+ GET_BY_VALUE = 22 # GET_ALL_BY_VALUE on server
340
+ GET_BY_VALUE_LIST = 23
341
+ GET_BY_INDEX_RANGE = 24
342
+ GET_BY_VALUE_INTERVAL = 25
343
+ GET_BY_RANK_RANGE = 26
344
+ GET_BY_VALUE_REL_RANK_RANGE = 27
345
+ REMOVE_BY_INDEX = 32
346
+ REMOVE_BY_RANK = 34
347
+ REMOVE_BY_VALUE = 35
348
+ REMOVE_BY_VALUE_LIST = 36
349
+ REMOVE_BY_INDEX_RANGE = 37
350
+ REMOVE_BY_VALUE_INTERVAL = 38
351
+ REMOVE_BY_RANK_RANGE = 39
352
+ REMOVE_BY_VALUE_REL_RANK_RANGE = 40
353
+
354
+ def self.add_write(bin, bytes, ctx)
355
+ if ctx.to_a.empty?
356
+ ret_type = Exp::Type::LIST
357
+ else
358
+ ret_type = ((ctx[0].id & 0x10) == 0) ? Exp::Type::MAP : Exp::Type::LIST
359
+ end
360
+ Exp::Module.new(bin, bytes, ret_type, MODULE | Exp::MODIFY)
361
+ end
362
+
363
+ def self.add_read(bin, bytes, ret_type)
364
+ Exp::Module.new(bin, bytes, ret_type, MODULE)
365
+ end
366
+
367
+ def self.get_value_type(return_type)
368
+ if (return_type & ~CDT::ListReturnType::INVERTED) == CDT::ListReturnType::VALUE
369
+ Exp::Type::LIST
370
+ else
371
+ Exp::Type::INT
372
+ end
373
+ end
374
+
375
+ def self.pack_range_operation(command, return_type, value_begin, value_end, ctx)
376
+ Packer.use do |packer|
377
+ Exp.pack_ctx(packer, ctx)
378
+ packer.write_array_header(value_end.nil? ? 3 : 4)
379
+ packer.write(command)
380
+ packer.write(return_type)
381
+
382
+ unless value_begin.nil?
383
+ if value_begin.is_a?(Exp)
384
+ value_begin.pack(packer)
385
+ else
386
+ Value.of(value_begin).pack(packer)
387
+ end
388
+ else
389
+ packer.write(nil)
390
+ end
391
+
392
+ unless value_end.nil?
393
+ if value_end.is_a?(Exp)
394
+ value_end.pack(packer)
395
+ else
396
+ Value.of(value_end).pack(packer)
397
+ end
398
+ end
399
+ packer.bytes
400
+ end
401
+ end
402
+ end # class Exp::List
403
+ end # module