aerospike 2.23.0 → 2.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +303 -266
- data/lib/aerospike/client.rb +25 -25
- data/lib/aerospike/command/command.rb +3 -1
- data/lib/aerospike/command/field_type.rb +25 -28
- data/lib/aerospike/exp/exp.rb +1262 -0
- data/lib/aerospike/policy/query_policy.rb +35 -2
- data/lib/aerospike/policy/scan_policy.rb +0 -2
- data/lib/aerospike/query/query_command.rb +1 -1
- data/lib/aerospike/query/query_executor.rb +73 -0
- data/lib/aerospike/query/query_partition_command.rb +266 -0
- data/lib/aerospike/query/statement.rb +7 -0
- data/lib/aerospike/query/stream_command.rb +2 -1
- data/lib/aerospike/utils/buffer.rb +26 -7
- data/lib/aerospike/version.rb +1 -1
- data/lib/aerospike.rb +2 -0
- metadata +6 -3
@@ -0,0 +1,1262 @@
|
|
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 no
|
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
|
+
class Exp
|
19
|
+
|
20
|
+
# Expression type.
|
21
|
+
module Type
|
22
|
+
NIL = 0
|
23
|
+
BOOL = 1
|
24
|
+
INT = 2
|
25
|
+
STRING = 3
|
26
|
+
LIST = 4
|
27
|
+
MAP = 5
|
28
|
+
BLOB = 6
|
29
|
+
FLOAT = 7
|
30
|
+
GEO = 8
|
31
|
+
HLL = 9
|
32
|
+
end # module type
|
33
|
+
|
34
|
+
module WriteFlags
|
35
|
+
# Default. Allow create or update.
|
36
|
+
DEFAULT = 0
|
37
|
+
|
38
|
+
# If bin does not exist, a new bin will be created.
|
39
|
+
# If bin exists, the operation will be denied.
|
40
|
+
# If bin exists, fail with ResultCode#BIN_EXISTS_ERROR
|
41
|
+
# when #POLICY_NO_FAIL is not set.
|
42
|
+
CREATE_ONLY = 1
|
43
|
+
|
44
|
+
# If bin exists, the bin will be overwritten.
|
45
|
+
# If bin does not exist, the operation will be denied.
|
46
|
+
# If bin does not exist, fail with ResultCode#BIN_NOT_FOUND
|
47
|
+
# when #POLICY_NO_FAIL is not set.
|
48
|
+
UPDATE_ONLY = 2
|
49
|
+
|
50
|
+
# If expression results in nil value, then delete the bin. Otherwise, fail with
|
51
|
+
# ResultCode#OP_NOT_APPLICABLE when #POLICY_NO_FAIL is not set.
|
52
|
+
ALLOW_DELETE = 4
|
53
|
+
|
54
|
+
# Do not raise error if operation is denied.
|
55
|
+
POLICY_NO_FAIL = 8
|
56
|
+
|
57
|
+
# Ignore failures caused by the expression resolving to unknown or a non-bin type.
|
58
|
+
EVAL_NO_FAIL = 16
|
59
|
+
end # module WriteFlags
|
60
|
+
|
61
|
+
module ReadFlags
|
62
|
+
# Default.
|
63
|
+
DEFAULT = 0
|
64
|
+
|
65
|
+
# Ignore failures caused by the expression resolving to unknown or a non-bin type.
|
66
|
+
EVAL_NO_FAIL = 16
|
67
|
+
end # module ReadFlags
|
68
|
+
|
69
|
+
# Create record key expression of specified type.
|
70
|
+
#
|
71
|
+
# ==== Examples
|
72
|
+
# # Integer record key >= 100000
|
73
|
+
# Exp.ge(Exp.key(Type::INT), Exp.val(100000))
|
74
|
+
def self.key(type)
|
75
|
+
new CmdInt.new(KEY, type)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Create expression that returns if the primary key is stored in the record meta data
|
79
|
+
# as a boolean expression. This would occur when {@link com.aerospike.client.policy.Policy#sendKey}
|
80
|
+
# is true on record write. This expression usually evaluates quickly because record
|
81
|
+
# meta data is cached in memory.
|
82
|
+
#
|
83
|
+
# ==== Examples
|
84
|
+
# # Key exists in record meta data
|
85
|
+
# Exp.key_exists
|
86
|
+
def self.key_exists
|
87
|
+
new Cmd.new(KEY_EXISTS)
|
88
|
+
end
|
89
|
+
|
90
|
+
#--------------------------------------------------
|
91
|
+
# Record Bin
|
92
|
+
#--------------------------------------------------
|
93
|
+
|
94
|
+
# Create bin expression of specified type.
|
95
|
+
#
|
96
|
+
# ==== Examples
|
97
|
+
# # String bin "a" == "views"
|
98
|
+
# Exp.eq(Exp.bin("a", Type::STRING), Exp.val("views"))
|
99
|
+
def self.bin(name, type)
|
100
|
+
new Bin.new(name, type)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Create 64 bit integer bin expression.
|
104
|
+
#
|
105
|
+
# ==== Examples
|
106
|
+
# # Integer bin "a" == 200
|
107
|
+
# Exp.eq(Exp.int_bin("a"), Exp.val(200))
|
108
|
+
def self.int_bin(name)
|
109
|
+
new Bin.new(name, Type::INT)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Create 64 bit float bin expression.
|
113
|
+
#
|
114
|
+
# ==== Examples
|
115
|
+
# # Float bin "a" >= 1.5
|
116
|
+
# Exp.ge(Exp.float_bin("a"), Exp.val(1.5))
|
117
|
+
def self.float_bin(name)
|
118
|
+
new Bin.new(name, Type::FLOAT)
|
119
|
+
end
|
120
|
+
|
121
|
+
# Create string bin expression.
|
122
|
+
#
|
123
|
+
# ==== Examples
|
124
|
+
# # String bin "a" == "views"
|
125
|
+
# Exp.eq(Exp.string_bin("a"), Exp.val("views"))
|
126
|
+
def self.string_bin(name)
|
127
|
+
new Bin.new(name, Type::STRING)
|
128
|
+
end
|
129
|
+
|
130
|
+
# Create boolean bin expression.
|
131
|
+
#
|
132
|
+
# ==== Examples
|
133
|
+
# # Boolean bin "a" == true
|
134
|
+
# Exp.eq(Exp.bool_bin("a"), Exp.val(true))
|
135
|
+
def self.bool_bin(name)
|
136
|
+
new Bin.new(name, Type::BOOL)
|
137
|
+
end
|
138
|
+
|
139
|
+
# Create bin expression.
|
140
|
+
#
|
141
|
+
# ==== Examples
|
142
|
+
# # Blob bin "a" == [1,2,3]
|
143
|
+
# Exp.eq(Exp.blob_bin("a"), Exp.val(new {1, 2, 3}))
|
144
|
+
def self.blob_bin(name)
|
145
|
+
new Bin.new(name, Type::BLOB)
|
146
|
+
end
|
147
|
+
|
148
|
+
# Create geospatial bin expression.
|
149
|
+
#
|
150
|
+
# ==== Examples
|
151
|
+
# # Geo bin "a" == region
|
152
|
+
# String region = "{ \"type\": \"AeroCircle\", \"coordinates\": [[-122.0, 37.5], 50000.0] }"
|
153
|
+
# Exp.geo_compare(Exp.geo_bin("loc"), Exp.geo(region))
|
154
|
+
def self.geo_bin(name)
|
155
|
+
new Bin.new(name, Type::GEO)
|
156
|
+
end
|
157
|
+
|
158
|
+
# Create list bin expression.
|
159
|
+
#
|
160
|
+
# ==== Examples
|
161
|
+
# # Bin a[2] == 3
|
162
|
+
# Exp.eq(ListExp.get_by_index(ListReturnType::VALUE, Type::INT, Exp.val(2), Exp.list_bin("a")), Exp.val(3))
|
163
|
+
def self.list_bin(name)
|
164
|
+
new Bin.new(name, Type::LIST)
|
165
|
+
end
|
166
|
+
|
167
|
+
# Create map bin expression.
|
168
|
+
#
|
169
|
+
# ==== Examples
|
170
|
+
# # Bin a["key"] == "value"
|
171
|
+
# Exp.eq(
|
172
|
+
# MapExp.get_by_key(MapReturnType::VALUE, Type::STRING, Exp.val("key"), Exp.map_bin("a")),
|
173
|
+
# Exp.val("value"))
|
174
|
+
def self.map_bin(name)
|
175
|
+
new Bin.new(name, Type::MAP)
|
176
|
+
end
|
177
|
+
|
178
|
+
# Create hll bin expression.
|
179
|
+
#
|
180
|
+
# ==== Examples
|
181
|
+
# # HLL bin "a" count > 7
|
182
|
+
# Exp.gt(HLLExp.get_count(Exp.hll_bin("a")), Exp.val(7))
|
183
|
+
def self.hll_bin(name)
|
184
|
+
new Bin.new(name, Type::HLL)
|
185
|
+
end
|
186
|
+
|
187
|
+
# Create expression that returns if bin of specified name exists.
|
188
|
+
#
|
189
|
+
# ==== Examples
|
190
|
+
# # Bin "a" exists in record
|
191
|
+
# Exp.bin_exists("a")
|
192
|
+
def self.bin_exists(name)
|
193
|
+
return Exp.ne(Exp.bin_type(name), Exp.val(0))
|
194
|
+
end
|
195
|
+
|
196
|
+
# Create expression that returns bin's integer particle type::
|
197
|
+
# See {@link com.aerospike.client.command.ParticleType}.
|
198
|
+
#
|
199
|
+
# ==== Examples
|
200
|
+
# # Bin "a" particle type is a list
|
201
|
+
# Exp.eq(Exp.bin_type("a"), Exp.val(ParticleType::LIST))
|
202
|
+
def self.bin_type(name)
|
203
|
+
new CmdStr.new(BIN_TYPE, name)
|
204
|
+
end
|
205
|
+
|
206
|
+
#--------------------------------------------------
|
207
|
+
# Misc
|
208
|
+
#--------------------------------------------------
|
209
|
+
|
210
|
+
# Create expression that returns record set name string. This expression usually
|
211
|
+
# evaluates quickly because record meta data is cached in memory.
|
212
|
+
#
|
213
|
+
# ==== Examples
|
214
|
+
# # Record set name == "myset"
|
215
|
+
# Exp.eq(Exp.set_name, Exp.val("myset"))
|
216
|
+
def self.set_name
|
217
|
+
new Cmd.new(SET_NAME)
|
218
|
+
end
|
219
|
+
|
220
|
+
# Create expression that returns record size on disk. If server storage-engine is
|
221
|
+
# memory, then zero is returned. This expression usually evaluates quickly because
|
222
|
+
# record meta data is cached in memory.
|
223
|
+
#
|
224
|
+
# ==== Examples
|
225
|
+
# # Record device size >= 100 KB
|
226
|
+
# Exp.ge(Exp.device_size, Exp.val(100 * 1024))
|
227
|
+
def self.device_size
|
228
|
+
new Cmd.new(DEVICE_SIZE)
|
229
|
+
end
|
230
|
+
|
231
|
+
# Create expression that returns record size in memory. If server storage-engine is
|
232
|
+
# not memory nor data-in-memory, then zero is returned. This expression usually evaluates
|
233
|
+
# quickly because record meta data is cached in memory.
|
234
|
+
# <p>
|
235
|
+
# Requires server version 5.3.0+
|
236
|
+
#
|
237
|
+
# ==== Examples
|
238
|
+
# # Record memory size >= 100 KB
|
239
|
+
# Exp.ge(Exp.memory_size, Exp.val(100 * 1024))
|
240
|
+
def self.memory_size
|
241
|
+
new Cmd.new(MEMORY_SIZE)
|
242
|
+
end
|
243
|
+
|
244
|
+
# Create expression that returns record last update time expressed as 64 bit integer
|
245
|
+
# nanoseconds since 1970-01-01 epoch. This expression usually evaluates quickly because
|
246
|
+
# record meta data is cached in memory.
|
247
|
+
#
|
248
|
+
# ==== Examples
|
249
|
+
# # Record last update time >= 2020-01-15
|
250
|
+
# Exp.ge(Exp.last_update, Exp.val(new GregorianCalendar(2020, 0, 15)))
|
251
|
+
def self.last_update
|
252
|
+
new Cmd.new(LAST_UPDATE)
|
253
|
+
end
|
254
|
+
|
255
|
+
# Create expression that returns milliseconds since the record was last updated.
|
256
|
+
# This expression usually evaluates quickly because record meta data is cached in memory.
|
257
|
+
#
|
258
|
+
# ==== Examples
|
259
|
+
# # Record last updated more than 2 hours ago
|
260
|
+
# Exp.gt(Exp.since_update, Exp.val(2 * 60 * 60 * 1000))
|
261
|
+
def self.since_update
|
262
|
+
new Cmd.new(SINCE_UPDATE)
|
263
|
+
end
|
264
|
+
|
265
|
+
# Create expression that returns record expiration time expressed as 64 bit integer
|
266
|
+
# nanoseconds since 1970-01-01 epoch. This expression usually evaluates quickly because
|
267
|
+
# record meta data is cached in memory.
|
268
|
+
#
|
269
|
+
# ==== Examples
|
270
|
+
# # Record expires on 2021-01-01
|
271
|
+
# Exp.and(
|
272
|
+
# Exp.ge(Exp.void_time, Exp.val(new GregorianCalendar(2021, 0, 1))),
|
273
|
+
# Exp.lt(Exp.void_time, Exp.val(new GregorianCalendar(2021, 0, 2))))
|
274
|
+
def self.void_time
|
275
|
+
new Cmd.new(VOID_TIME)
|
276
|
+
end
|
277
|
+
|
278
|
+
# Create expression that returns record expiration time (time to live) in integer seconds.
|
279
|
+
# This expression usually evaluates quickly because record meta data is cached in memory.
|
280
|
+
#
|
281
|
+
# ==== Examples
|
282
|
+
# # Record expires in less than 1 hour
|
283
|
+
# Exp.lt(Exp.ttl, Exp.val(60 * 60))
|
284
|
+
def self.ttl
|
285
|
+
new Cmd.new(TTL)
|
286
|
+
end
|
287
|
+
|
288
|
+
# Create expression that returns if record has been deleted and is still in tombstone state.
|
289
|
+
# This expression usually evaluates quickly because record meta data is cached in memory.
|
290
|
+
#
|
291
|
+
# ==== Examples
|
292
|
+
# # Deleted records that are in tombstone state.
|
293
|
+
# Exp.is_tombstone
|
294
|
+
def self.is_tombstone
|
295
|
+
new Cmd.new(IS_TOMBSTONE)
|
296
|
+
end
|
297
|
+
|
298
|
+
# Create expression that returns record digest modulo as integer. This expression usually
|
299
|
+
# evaluates quickly because record meta data is cached in memory.
|
300
|
+
#
|
301
|
+
# ==== Examples
|
302
|
+
# # Records that have digest(key) % 3 == 1
|
303
|
+
# Exp.eq(Exp.digest_modulo(3), Exp.val(1))
|
304
|
+
def self.digest_modulo(mod)
|
305
|
+
new CmdInt.new(DIGEST_MODULO, mod)
|
306
|
+
end
|
307
|
+
|
308
|
+
# Create expression that performs a regex match on a string bin or string value expression.
|
309
|
+
#
|
310
|
+
# ==== Examples
|
311
|
+
# # Select string bin "a" that starts with "prefix" and ends with "suffix".
|
312
|
+
# # Ignore case and do not match newline.
|
313
|
+
# Exp.regex_compare("prefix.*suffix", RegexFlag.ICASE | RegexFlag.NEWLINE, Exp.string_bin("a"))
|
314
|
+
#
|
315
|
+
# @param regex regular expression string
|
316
|
+
# @param flags regular expression bit flags. See {@link com.aerospike.client.query.RegexFlag}
|
317
|
+
# @param bin string bin or string value expression
|
318
|
+
def self.regex_compare(regex, flags, bin)
|
319
|
+
new Regex.new(bin, regex, flags)
|
320
|
+
end
|
321
|
+
|
322
|
+
#--------------------------------------------------
|
323
|
+
# GEO Spatial
|
324
|
+
#--------------------------------------------------
|
325
|
+
|
326
|
+
# Create compare geospatial operation.
|
327
|
+
#
|
328
|
+
# ==== Examples
|
329
|
+
# # Query region within coordinates.
|
330
|
+
# String region =
|
331
|
+
# "{ " +
|
332
|
+
# " \"type\": \"Polygon\", " +
|
333
|
+
# " \"coordinates\": [ " +
|
334
|
+
# " [[-122.500000, 37.000000],[-121.000000, 37.000000], " +
|
335
|
+
# " [-121.000000, 38.080000],[-122.500000, 38.080000], " +
|
336
|
+
# " [-122.500000, 37.000000]] " +
|
337
|
+
# " ] " +
|
338
|
+
# "}"
|
339
|
+
# Exp.geo_compare(Exp.geo_bin("a"), Exp.geo(region))
|
340
|
+
def self.geo_compare(left, right)
|
341
|
+
new CmdExp.new(GEO, left, right)
|
342
|
+
end
|
343
|
+
|
344
|
+
# Create geospatial json string value.
|
345
|
+
def self.geo(val)
|
346
|
+
new Geo.new(val)
|
347
|
+
end
|
348
|
+
|
349
|
+
#--------------------------------------------------
|
350
|
+
# Value
|
351
|
+
#--------------------------------------------------
|
352
|
+
|
353
|
+
# Create boolean value.
|
354
|
+
def self.val(val)
|
355
|
+
new Bool.new(val)
|
356
|
+
end
|
357
|
+
|
358
|
+
# Create 64 bit integer value.
|
359
|
+
def self.val(val)
|
360
|
+
new Int.new(val)
|
361
|
+
end
|
362
|
+
|
363
|
+
# Create 64 bit floating point value.
|
364
|
+
def self.val(val)
|
365
|
+
new Float.new(val)
|
366
|
+
end
|
367
|
+
|
368
|
+
# Create string value.
|
369
|
+
def self.val(val)
|
370
|
+
new Str.new(val)
|
371
|
+
end
|
372
|
+
|
373
|
+
# Create blob byte value.
|
374
|
+
def self.val(val)
|
375
|
+
new Blob.new(val)
|
376
|
+
end
|
377
|
+
|
378
|
+
# Create list value.
|
379
|
+
def self.val(list)
|
380
|
+
new ListVal.new(list)
|
381
|
+
end
|
382
|
+
|
383
|
+
# Create map value.
|
384
|
+
def self.val(map)
|
385
|
+
new MapVal.new(map)
|
386
|
+
end
|
387
|
+
|
388
|
+
# Create nil value.
|
389
|
+
def self.nil
|
390
|
+
new Nil.new
|
391
|
+
end
|
392
|
+
|
393
|
+
#--------------------------------------------------
|
394
|
+
# Boolean Operator
|
395
|
+
#--------------------------------------------------
|
396
|
+
|
397
|
+
# Create "not" operator expression.
|
398
|
+
#
|
399
|
+
# ==== Examples
|
400
|
+
# # ! (a == 0 || a == 10)
|
401
|
+
# Exp.not(
|
402
|
+
# Exp.or(
|
403
|
+
# Exp.eq(Exp.int_bin("a"), Exp.val(0)),
|
404
|
+
# Exp.eq(Exp.int_bin("a"), Exp.val(10))))
|
405
|
+
def self.not(exp)
|
406
|
+
new CmdExp.new(NOT, exp)
|
407
|
+
end
|
408
|
+
|
409
|
+
# Create "and" (&&) operator that applies to a variable number of expressions.
|
410
|
+
#
|
411
|
+
# ==== Examples
|
412
|
+
# # (a > 5 || a == 0) && b < 3
|
413
|
+
# Exp.and(
|
414
|
+
# Exp.or(
|
415
|
+
# Exp.gt(Exp.int_bin("a"), Exp.val(5)),
|
416
|
+
# Exp.eq(Exp.int_bin("a"), Exp.val(0))),
|
417
|
+
# Exp.lt(Exp.int_bin("b"), Exp.val(3)))
|
418
|
+
def self.and(*exps)
|
419
|
+
new CmdExp.new(AND, exps)
|
420
|
+
end
|
421
|
+
|
422
|
+
# Create "or" (||) operator that applies to a variable number of expressions.
|
423
|
+
#
|
424
|
+
# ==== Examples
|
425
|
+
# # a == 0 || b == 0
|
426
|
+
# Exp.or(
|
427
|
+
# Exp.eq(Exp.int_bin("a"), Exp.val(0)),
|
428
|
+
# Exp.eq(Exp.int_bin("b"), Exp.val(0)))
|
429
|
+
def self.or(*exps)
|
430
|
+
new CmdExp.new(OR, exps)
|
431
|
+
end
|
432
|
+
|
433
|
+
# Create expression that returns true if only one of the expressions are true.
|
434
|
+
# Requires server version 5.6.0+.
|
435
|
+
#
|
436
|
+
# ==== Examples
|
437
|
+
# # exclusive(a == 0, b == 0)
|
438
|
+
# Exp.exclusive(
|
439
|
+
# Exp.eq(Exp.int_bin("a"), Exp.val(0)),
|
440
|
+
# Exp.eq(Exp.int_bin("b"), Exp.val(0)))
|
441
|
+
def self.exclusive(*exps)
|
442
|
+
new CmdExp.new(EXCLUSIVE, exps)
|
443
|
+
end
|
444
|
+
|
445
|
+
# Create equal (==) expression.
|
446
|
+
#
|
447
|
+
# ==== Examples
|
448
|
+
# # a == 11
|
449
|
+
# Exp.eq(Exp.int_bin("a"), Exp.val(11))
|
450
|
+
def self.eq(left, right)
|
451
|
+
new CmdExp.new(EQ, left, right)
|
452
|
+
end
|
453
|
+
|
454
|
+
# Create not equal (!=) expression
|
455
|
+
#
|
456
|
+
# ==== Examples
|
457
|
+
# # a != 13
|
458
|
+
# Exp.ne(Exp.int_bin("a"), Exp.val(13))
|
459
|
+
def self.ne(left, right)
|
460
|
+
new CmdExp.new(NE, left, right)
|
461
|
+
end
|
462
|
+
|
463
|
+
# Create greater than (>) operation.
|
464
|
+
#
|
465
|
+
# ==== Examples
|
466
|
+
# # a > 8
|
467
|
+
# Exp.gt(Exp.int_bin("a"), Exp.val(8))
|
468
|
+
def self.gt(left, right)
|
469
|
+
new CmdExp.new(GT, left, right)
|
470
|
+
end
|
471
|
+
|
472
|
+
# Create greater than or equal (>=) operation.
|
473
|
+
#
|
474
|
+
# ==== Examples
|
475
|
+
# # a >= 88
|
476
|
+
# Exp.ge(Exp.int_bin("a"), Exp.val(88))
|
477
|
+
def self.ge(left, right)
|
478
|
+
new CmdExp.new(GE, left, right)
|
479
|
+
end
|
480
|
+
|
481
|
+
# Create less than (<) operation.
|
482
|
+
#
|
483
|
+
# ==== Examples
|
484
|
+
# # a < 1000
|
485
|
+
# Exp.lt(Exp.int_bin("a"), Exp.val(1000))
|
486
|
+
def self.lt(left, right)
|
487
|
+
new CmdExp.new(LT, left, right)
|
488
|
+
end
|
489
|
+
|
490
|
+
# Create less than or equals (<=) operation.
|
491
|
+
#
|
492
|
+
# ==== Examples
|
493
|
+
# # a <= 1
|
494
|
+
# Exp.le(Exp.int_bin("a"), Exp.val(1))
|
495
|
+
def self.le(left, right)
|
496
|
+
new CmdExp.new(LE, left, right)
|
497
|
+
end
|
498
|
+
|
499
|
+
#--------------------------------------------------
|
500
|
+
# Number Operator
|
501
|
+
#--------------------------------------------------
|
502
|
+
|
503
|
+
# Create "add" (+) operator that applies to a variable number of expressions.
|
504
|
+
# Return sum of all arguments. All arguments must resolve to the same type (or float).
|
505
|
+
# Requires server version 5.6.0+.
|
506
|
+
#
|
507
|
+
# ==== Examples
|
508
|
+
# # a + b + c == 10
|
509
|
+
# Exp.eq(
|
510
|
+
# Exp.add(Exp.int_bin("a"), Exp.int_bin("b"), Exp.int_bin("c")),
|
511
|
+
# Exp.val(10))
|
512
|
+
def self.add(*exps)
|
513
|
+
new CmdExp.new(ADD, exps)
|
514
|
+
end
|
515
|
+
|
516
|
+
# Create "subtract" (-) operator that applies to a variable number of expressions.
|
517
|
+
# If only one argument is provided, return the negation of that argument.
|
518
|
+
# Otherwise, return the sum of the 2nd to Nth argument subtracted from the 1st
|
519
|
+
# argument. All arguments must resolve to the same type (or float).
|
520
|
+
# Requires server version 5.6.0+.
|
521
|
+
#
|
522
|
+
# ==== Examples
|
523
|
+
# # a - b - c > 10
|
524
|
+
# Exp.gt(
|
525
|
+
# Exp.sub(Exp.int_bin("a"), Exp.int_bin("b"), Exp.int_bin("c")),
|
526
|
+
# Exp.val(10))
|
527
|
+
def self.sub(*exps)
|
528
|
+
new CmdExp.new(SUB, exps)
|
529
|
+
end
|
530
|
+
|
531
|
+
# Create "multiply" (*) operator that applies to a variable number of expressions.
|
532
|
+
# Return the product of all arguments. If only one argument is supplied, return
|
533
|
+
# that argument. All arguments must resolve to the same type (or float).
|
534
|
+
# Requires server version 5.6.0+.
|
535
|
+
#
|
536
|
+
# ==== Examples
|
537
|
+
# # a * b * c < 100
|
538
|
+
# Exp.lt(
|
539
|
+
# Exp.mul(Exp.int_bin("a"), Exp.int_bin("b"), Exp.int_bin("c")),
|
540
|
+
# Exp.val(100))
|
541
|
+
def self.mul(*exps)
|
542
|
+
new CmdExp.new(MUL, exps)
|
543
|
+
end
|
544
|
+
|
545
|
+
# Create "divide" (/) operator that applies to a variable number of expressions.
|
546
|
+
# If there is only one argument, returns the reciprocal for that argument.
|
547
|
+
# Otherwise, return the first argument divided by the product of the rest.
|
548
|
+
# All arguments must resolve to the same type (or float).
|
549
|
+
# Requires server version 5.6.0+.
|
550
|
+
#
|
551
|
+
# ==== Examples
|
552
|
+
# # a / b / c > 1
|
553
|
+
# Exp.gt(
|
554
|
+
# Exp.div(Exp.int_bin("a"), Exp.int_bin("b"), Exp.int_bin("c")),
|
555
|
+
# Exp.val(1))
|
556
|
+
def self.div(*exps)
|
557
|
+
new CmdExp.new(DIV, exps)
|
558
|
+
end
|
559
|
+
|
560
|
+
# Create "power" operator that raises a "base" to the "exponent" power.
|
561
|
+
# All arguments must resolve to floats.
|
562
|
+
# Requires server version 5.6.0+.
|
563
|
+
#
|
564
|
+
# ==== Examples
|
565
|
+
# # pow(a, 2.0) == 4.0
|
566
|
+
# Exp.eq(
|
567
|
+
# Exp.pow(Exp.float_bin("a"), Exp.val(2.0)),
|
568
|
+
# Exp.val(4.0))
|
569
|
+
def self.pow(base, exponent)
|
570
|
+
new CmdExp.new(POW, base, exponent)
|
571
|
+
end
|
572
|
+
|
573
|
+
# Create "log" operator for logarithm of "num" with base "base".
|
574
|
+
# All arguments must resolve to floats.
|
575
|
+
# Requires server version 5.6.0+.
|
576
|
+
#
|
577
|
+
# ==== Examples
|
578
|
+
# # log(a, 2.0) == 4.0
|
579
|
+
# Exp.eq(
|
580
|
+
# Exp.log(Exp.float_bin("a"), Exp.val(2.0)),
|
581
|
+
# Exp.val(4.0))
|
582
|
+
def self.log(num, base)
|
583
|
+
new CmdExp.new(LOG, num, base)
|
584
|
+
end
|
585
|
+
|
586
|
+
# Create "modulo" (%) operator that determines the remainder of "numerator"
|
587
|
+
# divided by "denominator". All arguments must resolve to integers.
|
588
|
+
# Requires server version 5.6.0+.
|
589
|
+
#
|
590
|
+
# ==== Examples
|
591
|
+
# # a % 10 == 0
|
592
|
+
# Exp.eq(
|
593
|
+
# Exp.mod(Exp.int_bin("a"), Exp.val(10)),
|
594
|
+
# Exp.val(0))
|
595
|
+
def self.mod(numerator, denominator)
|
596
|
+
new CmdExp.new(MOD, numerator, denominator)
|
597
|
+
end
|
598
|
+
|
599
|
+
# Create operator that returns absolute value of a number.
|
600
|
+
# All arguments must resolve to integer or float.
|
601
|
+
# Requires server version 5.6.0+.
|
602
|
+
#
|
603
|
+
# ==== Examples
|
604
|
+
# # abs(a) == 1
|
605
|
+
# Exp.eq(
|
606
|
+
# Exp.abs(Exp.int_bin("a")),
|
607
|
+
# Exp.val(1))
|
608
|
+
def self.abs(value)
|
609
|
+
new CmdExp.new(ABS, value)
|
610
|
+
end
|
611
|
+
|
612
|
+
# Create expression that rounds a floating point number down to the closest integer value.
|
613
|
+
# The return type is float. Requires server version 5.6.0+.
|
614
|
+
#
|
615
|
+
# ==== Examples
|
616
|
+
# # floor(2.95) == 2.0
|
617
|
+
# Exp.eq(
|
618
|
+
# Exp.floor(Exp.val(2.95)),
|
619
|
+
# Exp.val(2.0))
|
620
|
+
def self.floor(num)
|
621
|
+
new CmdExp.new(FLOOR, num)
|
622
|
+
end
|
623
|
+
|
624
|
+
# Create expression that rounds a floating point number up to the closest integer value.
|
625
|
+
# The return type is float. Requires server version 5.6.0+.
|
626
|
+
#
|
627
|
+
# ==== Examples
|
628
|
+
# # ceil(2.15) >= 3.0
|
629
|
+
# Exp.ge(
|
630
|
+
# Exp.ceil(Exp.val(2.15)),
|
631
|
+
# Exp.val(3.0))
|
632
|
+
def self.ceil(num)
|
633
|
+
new CmdExp.new(CEIL, num)
|
634
|
+
end
|
635
|
+
|
636
|
+
# Create expression that converts a float to an integer.
|
637
|
+
# Requires server version 5.6.0+.
|
638
|
+
#
|
639
|
+
# ==== Examples
|
640
|
+
# # int(2.5) == 2
|
641
|
+
# Exp.eq(
|
642
|
+
# Exp.to_int(Exp.val(2.5)),
|
643
|
+
# Exp.val(2))
|
644
|
+
def self.to_int(num)
|
645
|
+
new CmdExp.new(TO_INT, num)
|
646
|
+
end
|
647
|
+
|
648
|
+
# Create expression that converts an integer to a float.
|
649
|
+
# Requires server version 5.6.0+.
|
650
|
+
#
|
651
|
+
# ==== Examples
|
652
|
+
# # float(2) == 2.0
|
653
|
+
# Exp.eq(
|
654
|
+
# Exp.to_float(Exp.val(2))),
|
655
|
+
# Exp.val(2.0))
|
656
|
+
def self.to_float(num)
|
657
|
+
new CmdExp.new(TO_FLOAT, num)
|
658
|
+
end
|
659
|
+
|
660
|
+
# Create integer "and" (&) operator that is applied to two or more integers.
|
661
|
+
# All arguments must resolve to integers.
|
662
|
+
# Requires server version 5.6.0+.
|
663
|
+
#
|
664
|
+
# ==== Examples
|
665
|
+
# # a & 0xff == 0x11
|
666
|
+
# Exp.eq(
|
667
|
+
# Exp.int_and(Exp.int_bin("a"), Exp.val(0xff)),
|
668
|
+
# Exp.val(0x11))
|
669
|
+
def self.int_and(*exps)
|
670
|
+
new CmdExp.new(exps)
|
671
|
+
end
|
672
|
+
|
673
|
+
# Create integer "or" (|) operator that is applied to two or more integers.
|
674
|
+
# All arguments must resolve to integers.
|
675
|
+
# Requires server version 5.6.0+.
|
676
|
+
#
|
677
|
+
# ==== Examples
|
678
|
+
# # a | 0x10 != 0
|
679
|
+
# Exp.ne(
|
680
|
+
# Exp.int_or(Exp.int_bin("a"), Exp.val(0x10)),
|
681
|
+
# Exp.val(0))
|
682
|
+
def self.int_or(*exps)
|
683
|
+
new CmdExp.new(exps)
|
684
|
+
end
|
685
|
+
|
686
|
+
# Create integer "xor" (^) operator that is applied to two or more integers.
|
687
|
+
# All arguments must resolve to integers.
|
688
|
+
# Requires server version 5.6.0+.
|
689
|
+
#
|
690
|
+
# ==== Examples
|
691
|
+
# # a ^ b == 16
|
692
|
+
# Exp.eq(
|
693
|
+
# Exp.int_xor(Exp.int_bin("a"), Exp.int_bin("b")),
|
694
|
+
# Exp.val(16))
|
695
|
+
def self.int_xor(*exps)
|
696
|
+
new CmdExp.new(exps)
|
697
|
+
end
|
698
|
+
|
699
|
+
# Create integer "not" (~) operator.
|
700
|
+
# Requires server version 5.6.0+.
|
701
|
+
#
|
702
|
+
# ==== Examples
|
703
|
+
# # ~a == 7
|
704
|
+
# Exp.eq(
|
705
|
+
# Exp.int_not(Exp.int_bin("a")),
|
706
|
+
# Exp.val(7))
|
707
|
+
def self.int_not(exp)
|
708
|
+
new CmdExp.new(exp)
|
709
|
+
end
|
710
|
+
|
711
|
+
# Create integer "left shift" (<<) operator.
|
712
|
+
# Requires server version 5.6.0+.
|
713
|
+
#
|
714
|
+
# ==== Examples
|
715
|
+
# # a << 8 > 0xff
|
716
|
+
# Exp.gt(
|
717
|
+
# Exp.lshift(Exp.int_bin("a"), Exp.val(8)),
|
718
|
+
# Exp.val(0xff))
|
719
|
+
def self.lshift(value, shift)
|
720
|
+
new CmdExp.new(value, shift)
|
721
|
+
end
|
722
|
+
|
723
|
+
# Create integer "logical right shift" (>>>) operator.
|
724
|
+
# Requires server version 5.6.0+.
|
725
|
+
#
|
726
|
+
# ==== Examples
|
727
|
+
# # a >>> 8 > 0xff
|
728
|
+
# Exp.gt(
|
729
|
+
# Exp.rshift(Exp.int_bin("a"), Exp.val(8)),
|
730
|
+
# Exp.val(0xff))
|
731
|
+
def self.rshift(value, shift)
|
732
|
+
new CmdExp.new(value, shift)
|
733
|
+
end
|
734
|
+
|
735
|
+
# Create integer "arithmetic right shift" (>>) operator.
|
736
|
+
# Requires server version 5.6.0+.
|
737
|
+
#
|
738
|
+
# ==== Examples
|
739
|
+
# # a >> 8 > 0xff
|
740
|
+
# Exp.gt(
|
741
|
+
# Exp.arshift(Exp.int_bin("a"), Exp.val(8)),
|
742
|
+
# Exp.val(0xff))
|
743
|
+
def self.arshift(value, shift)
|
744
|
+
new CmdExp.new(value, shift)
|
745
|
+
end
|
746
|
+
|
747
|
+
# Create expression that returns count of integer bits that are set to 1.
|
748
|
+
# Requires server version 5.6.0+.
|
749
|
+
#
|
750
|
+
# ==== Examples
|
751
|
+
# # count(a) == 4
|
752
|
+
# Exp.eq(
|
753
|
+
# Exp.count(Exp.int_bin("a")),
|
754
|
+
# Exp.val(4))
|
755
|
+
def self.count(exp)
|
756
|
+
new CmdExp.new(exp)
|
757
|
+
end
|
758
|
+
|
759
|
+
# Create expression that scans integer bits from left (most significant bit) to
|
760
|
+
# right (least significant bit), looking for a search bit value. When the
|
761
|
+
# search value is found, the index of that bit (where the most significant bit is
|
762
|
+
# index 0) is returned. If "search" is true, the scan will search for the bit
|
763
|
+
# value 1. If "search" is false it will search for bit value 0.
|
764
|
+
# Requires server version 5.6.0+.
|
765
|
+
#
|
766
|
+
# ==== Examples
|
767
|
+
# # lscan(a, true) == 4
|
768
|
+
# Exp.eq(
|
769
|
+
# Exp.lscan(Exp.int_bin("a"), Exp.val(true)),
|
770
|
+
# Exp.val(4))
|
771
|
+
def self.lscan(value, search)
|
772
|
+
new CmdExp.new(value, search)
|
773
|
+
end
|
774
|
+
|
775
|
+
# Create expression that scans integer bits from right (least significant bit) to
|
776
|
+
# left (most significant bit), looking for a search bit value. When the
|
777
|
+
# search value is found, the index of that bit (where the most significant bit is
|
778
|
+
# index 0) is returned. If "search" is true, the scan will search for the bit
|
779
|
+
# value 1. If "search" is false it will search for bit value 0.
|
780
|
+
# Requires server version 5.6.0+.
|
781
|
+
#
|
782
|
+
# ==== Examples
|
783
|
+
# # rscan(a, true) == 4
|
784
|
+
# Exp.eq(
|
785
|
+
# Exp.rscan(Exp.int_bin("a"), Exp.val(true)),
|
786
|
+
# Exp.val(4))
|
787
|
+
def self.rscan(value, search)
|
788
|
+
new CmdExp.new(value, search)
|
789
|
+
end
|
790
|
+
|
791
|
+
# Create expression that returns the minimum value in a variable number of expressions.
|
792
|
+
# All arguments must be the same type (or float).
|
793
|
+
# Requires server version 5.6.0+.
|
794
|
+
#
|
795
|
+
# ==== Examples
|
796
|
+
# # min(a, b, c) > 0
|
797
|
+
# Exp.gt(
|
798
|
+
# Exp.min(Exp.int_bin("a"), Exp.int_bin("b"), Exp.int_bin("c")),
|
799
|
+
# Exp.val(0))
|
800
|
+
def self.min(*exps)
|
801
|
+
new CmdExp.new(MIN, exps)
|
802
|
+
end
|
803
|
+
|
804
|
+
# Create expression that returns the maximum value in a variable number of expressions.
|
805
|
+
# All arguments must be the same type (or float).
|
806
|
+
# Requires server version 5.6.0+.
|
807
|
+
#
|
808
|
+
# ==== Examples
|
809
|
+
# # max(a, b, c) > 100
|
810
|
+
# Exp.gt(
|
811
|
+
# Exp.max(Exp.int_bin("a"), Exp.int_bin("b"), Exp.int_bin("c")),
|
812
|
+
# Exp.val(100))
|
813
|
+
def self.max(*exps)
|
814
|
+
new CmdExp.new(MAX, exps)
|
815
|
+
end
|
816
|
+
|
817
|
+
#--------------------------------------------------
|
818
|
+
# Variables
|
819
|
+
#--------------------------------------------------
|
820
|
+
|
821
|
+
# Conditionally select an expression from a variable number of expression pairs
|
822
|
+
# followed by default expression action. Requires server version 5.6.0+.
|
823
|
+
#
|
824
|
+
# ==== Examples
|
825
|
+
# Args Format: bool exp1, action exp1, bool exp2, action exp2, ..., action-default
|
826
|
+
#
|
827
|
+
# # Apply operator based on type::
|
828
|
+
# Exp.cond(
|
829
|
+
# Exp.eq(Exp.int_bin("type"), Exp.val(0)), Exp.add(Exp.int_bin("val1"), Exp.int_bin("val2")),
|
830
|
+
# Exp.eq(Exp.int_bin("type"), Exp.val(1)), Exp.sub(Exp.int_bin("val1"), Exp.int_bin("val2")),
|
831
|
+
# Exp.eq(Exp.int_bin("type"), Exp.val(2)), Exp.mul(Exp.int_bin("val1"), Exp.int_bin("val2")),
|
832
|
+
# Exp.val(-1))
|
833
|
+
def self.cond(*exps)
|
834
|
+
new CmdExp.new(COND, exps)
|
835
|
+
end
|
836
|
+
|
837
|
+
# Define variables and expressions in scope.
|
838
|
+
# Requires server version 5.6.0+.
|
839
|
+
#
|
840
|
+
# ==== Examples
|
841
|
+
# Args Format: <def1>, <def2>, ..., <exp>
|
842
|
+
# def: {@link Exp#def(String, Exp)}
|
843
|
+
# exp: Scoped expression
|
844
|
+
#
|
845
|
+
# ==== Examples
|
846
|
+
# # 5 < a < 10
|
847
|
+
# Exp.let(
|
848
|
+
# Exp.def("x", Exp.int_bin("a")),
|
849
|
+
# Exp.and(
|
850
|
+
# Exp.lt(Exp.val(5), Exp.var("x")),
|
851
|
+
# Exp.lt(Exp.var("x"), Exp.val(10))))
|
852
|
+
def self.let(*exps)
|
853
|
+
new Let.new(exps)
|
854
|
+
end
|
855
|
+
|
856
|
+
# Assign variable to a {@link Exp#let(Exp...)} expression that can be accessed later.
|
857
|
+
# Requires server version 5.6.0+.
|
858
|
+
#
|
859
|
+
# ==== Examples
|
860
|
+
# # 5 < a < 10
|
861
|
+
# Exp.let(
|
862
|
+
# Exp.def("x", Exp.int_bin("a")),
|
863
|
+
# Exp.and(
|
864
|
+
# Exp.lt(Exp.val(5), Exp.var("x")),
|
865
|
+
# Exp.lt(Exp.var("x"), Exp.val(10))))
|
866
|
+
def self.def(name, value)
|
867
|
+
new Def.new(name, value)
|
868
|
+
end
|
869
|
+
|
870
|
+
# Retrieve expression value from a variable.
|
871
|
+
# Requires server version 5.6.0+.
|
872
|
+
#
|
873
|
+
# ==== Examples
|
874
|
+
# # 5 < a < 10
|
875
|
+
# Exp.let(
|
876
|
+
# Exp.def("x", Exp.int_bin("a")),
|
877
|
+
# Exp.and(
|
878
|
+
# Exp.lt(Exp.val(5), Exp.var("x")),
|
879
|
+
# Exp.lt(Exp.var("x"), Exp.val(10))))
|
880
|
+
def self.var(name)
|
881
|
+
new CmdStr.new(VAR, name)
|
882
|
+
end
|
883
|
+
|
884
|
+
#--------------------------------------------------
|
885
|
+
# Miscellaneous
|
886
|
+
#--------------------------------------------------
|
887
|
+
|
888
|
+
# Create unknown value. Used to intentionally fail an expression.
|
889
|
+
# The failure can be ignored with {@link com.aerospike.client.exp.exp_write_flags#EVAL_NO_FAIL}
|
890
|
+
# or {@link com.aerospike.client.exp.exp_read_flags#EVAL_NO_FAIL}.
|
891
|
+
# Requires server version 5.6.0+.
|
892
|
+
#
|
893
|
+
# ==== Examples
|
894
|
+
# # double v = balance - 100.0
|
895
|
+
# # return (v > 0.0)? v : unknown
|
896
|
+
# Exp.let(
|
897
|
+
# Exp.def("v", Exp.sub(Exp.float_bin("balance"), Exp.val(100.0))),
|
898
|
+
# Exp.cond(
|
899
|
+
# Exp.ge(Exp.var("v"), Exp.val(0.0)), Exp.var("v"),
|
900
|
+
# Exp.unknown))
|
901
|
+
def self.unknown
|
902
|
+
new Cmd.new(UNKNOWN)
|
903
|
+
end
|
904
|
+
|
905
|
+
# # Merge precompiled expression into a new expression tree.
|
906
|
+
# # Useful for storing common precompiled expressions and then reusing
|
907
|
+
# # these expressions as part of a greater expression.
|
908
|
+
# #
|
909
|
+
# # ==== Examples
|
910
|
+
# # # Merge precompiled expression into new expression.
|
911
|
+
# # Expression e = Exp.build(Exp.eq(Exp.int_bin("a"), Exp.val(200)))
|
912
|
+
# # Expression merged = Exp.build(Exp.and(Exp.expr(e), Exp.eq(Exp.int_bin("b"), Exp.val(100))))
|
913
|
+
# def self.expr(Expression e)
|
914
|
+
# new ExpBytes.new(e)
|
915
|
+
# end
|
916
|
+
|
917
|
+
#--------------------------------------------------
|
918
|
+
# Internal
|
919
|
+
#--------------------------------------------------
|
920
|
+
MODIFY = 0x40
|
921
|
+
|
922
|
+
private
|
923
|
+
|
924
|
+
UNKNOWN = 0
|
925
|
+
EQ = 1
|
926
|
+
NE = 2
|
927
|
+
GT = 3
|
928
|
+
GE = 4
|
929
|
+
LT = 5
|
930
|
+
LE = 6
|
931
|
+
REGEX = 7
|
932
|
+
GEO = 8
|
933
|
+
AND = 16
|
934
|
+
OR = 17
|
935
|
+
NOT = 18
|
936
|
+
EXCLUSIVE = 19
|
937
|
+
ADD = 20
|
938
|
+
SUB = 21
|
939
|
+
MUL = 22
|
940
|
+
DIV = 23
|
941
|
+
POW = 24
|
942
|
+
LOG = 25
|
943
|
+
MOD = 26
|
944
|
+
ABS = 27
|
945
|
+
FLOOR = 28
|
946
|
+
CEIL = 29
|
947
|
+
TO_INT = 30
|
948
|
+
TO_FLOAT = 31
|
949
|
+
INT_AND = 32
|
950
|
+
INT_OR = 33
|
951
|
+
INT_XOR = 34
|
952
|
+
INT_NOT = 35
|
953
|
+
INT_LSHIFT = 36
|
954
|
+
INT_RSHIFT = 37
|
955
|
+
INT_ARSHIFT = 38
|
956
|
+
INT_COUNT = 39
|
957
|
+
INT_LSCAN = 40
|
958
|
+
INT_RSCAN = 41
|
959
|
+
MIN = 50
|
960
|
+
MAX = 51
|
961
|
+
DIGEST_MODULO = 64
|
962
|
+
DEVICE_SIZE = 65
|
963
|
+
LAST_UPDATE = 66
|
964
|
+
SINCE_UPDATE = 67
|
965
|
+
VOID_TIME = 68
|
966
|
+
TTL = 69
|
967
|
+
SET_NAME = 70
|
968
|
+
KEY_EXISTS = 71
|
969
|
+
IS_TOMBSTONE = 72
|
970
|
+
MEMORY_SIZE = 73
|
971
|
+
KEY = 80
|
972
|
+
BIN = 81
|
973
|
+
BIN_TYPE = 82
|
974
|
+
COND = 123
|
975
|
+
VAR = 124
|
976
|
+
LET = 125
|
977
|
+
QUOTED = 126
|
978
|
+
CALL = 127
|
979
|
+
NANOS_PER_MILLIS = 1000000
|
980
|
+
|
981
|
+
def pack(packer)
|
982
|
+
raise "Unreachable"
|
983
|
+
end
|
984
|
+
|
985
|
+
# For internal use only.
|
986
|
+
class Module < Exp
|
987
|
+
attr_reader :bin
|
988
|
+
attr_reader :bytes
|
989
|
+
attr_reader :ret_type
|
990
|
+
attr_reader :module
|
991
|
+
|
992
|
+
def initialize(bin, bytes, ret_type, modul)
|
993
|
+
@bin = bin
|
994
|
+
@bytes = bytes
|
995
|
+
@ret_type = ret_type
|
996
|
+
@module = modul
|
997
|
+
end
|
998
|
+
|
999
|
+
def pack(packer)
|
1000
|
+
packer.pack_array_begin(5)
|
1001
|
+
packer.pack_int(Exp::CALL)
|
1002
|
+
packer.pack_int(ret_type)
|
1003
|
+
packer.pack_int(modul)
|
1004
|
+
packer.pack_byte_array(bytes, 0, bytes.length)
|
1005
|
+
bin.pack(packer)
|
1006
|
+
end
|
1007
|
+
end
|
1008
|
+
|
1009
|
+
class Bin < Exp
|
1010
|
+
attr_reader :name
|
1011
|
+
attr_reader :type
|
1012
|
+
|
1013
|
+
def initialize(name, type)
|
1014
|
+
@name = name
|
1015
|
+
@type = type
|
1016
|
+
end
|
1017
|
+
|
1018
|
+
def pack(packer)
|
1019
|
+
packer.pack_array_begin(3)
|
1020
|
+
packer.pack_int(BIN)
|
1021
|
+
packer.pack_int(type.code)
|
1022
|
+
packer.pack_string(name)
|
1023
|
+
end
|
1024
|
+
end
|
1025
|
+
|
1026
|
+
class Regex < Exp
|
1027
|
+
attr_reader :bin
|
1028
|
+
attr_reader :regex
|
1029
|
+
attr_reader :flags
|
1030
|
+
|
1031
|
+
def initialize(bin, regex, flags)
|
1032
|
+
@bin = bin
|
1033
|
+
@regex = regex
|
1034
|
+
@flags = flags
|
1035
|
+
end
|
1036
|
+
|
1037
|
+
def pack(packer)
|
1038
|
+
packer.pack_array_begin(4)
|
1039
|
+
packer.pack_int(REGEX)
|
1040
|
+
packer.pack_int(flags)
|
1041
|
+
packer.pack_string(regex)
|
1042
|
+
bin.pack(packer)
|
1043
|
+
end
|
1044
|
+
end
|
1045
|
+
|
1046
|
+
class Let < Exp
|
1047
|
+
attr_reader :exps
|
1048
|
+
|
1049
|
+
def initialize(exps)
|
1050
|
+
@exps = exps
|
1051
|
+
end
|
1052
|
+
|
1053
|
+
def pack(packer)
|
1054
|
+
# Let wire format: LET <defname1>, <defexp1>, <defname2>, <defexp2>, ..., <scope exp>
|
1055
|
+
count = (exps.length - 1) * 2 + 2
|
1056
|
+
packer.pack_array_begin(count)
|
1057
|
+
packer.pack_int(LET)
|
1058
|
+
|
1059
|
+
exps.each do |exp|
|
1060
|
+
exp.pack(packer)
|
1061
|
+
end
|
1062
|
+
end
|
1063
|
+
end
|
1064
|
+
|
1065
|
+
class Def < Exp
|
1066
|
+
attr_reader :name
|
1067
|
+
attr_reader :exp
|
1068
|
+
|
1069
|
+
def initialize(name, exp)
|
1070
|
+
@name = name
|
1071
|
+
@exp = exp
|
1072
|
+
end
|
1073
|
+
|
1074
|
+
def pack(packer)
|
1075
|
+
packer.pack_string(name)
|
1076
|
+
exp::pack(packer)
|
1077
|
+
end
|
1078
|
+
end
|
1079
|
+
|
1080
|
+
class CmdExp < Exp
|
1081
|
+
attr_reader :exps
|
1082
|
+
attr_reader :cmd
|
1083
|
+
|
1084
|
+
def initialize(cmd, exps)
|
1085
|
+
@exps = exps
|
1086
|
+
@cmd = cmd
|
1087
|
+
end
|
1088
|
+
|
1089
|
+
def pack(packer)
|
1090
|
+
packer.pack_array_begin(exps.length + 1)
|
1091
|
+
packer.pack_int(cmd)
|
1092
|
+
|
1093
|
+
exps.each do |exp|
|
1094
|
+
exp.pack(packer)
|
1095
|
+
end
|
1096
|
+
end
|
1097
|
+
end
|
1098
|
+
|
1099
|
+
class CmdInt < Exp
|
1100
|
+
attr_reader :cmd
|
1101
|
+
attr_reader :val
|
1102
|
+
|
1103
|
+
def initialize(cmd, val)
|
1104
|
+
@cmd = cmd
|
1105
|
+
@val = val
|
1106
|
+
end
|
1107
|
+
|
1108
|
+
def pack(packer)
|
1109
|
+
packer.pack_array_begin(2)
|
1110
|
+
packer.pack_int(cmd)
|
1111
|
+
packer.pack_int(val)
|
1112
|
+
end
|
1113
|
+
end
|
1114
|
+
|
1115
|
+
class CmdStr < Exp
|
1116
|
+
attr_reader :str
|
1117
|
+
attr_reader :cmd
|
1118
|
+
|
1119
|
+
def initialize(cmd, str)
|
1120
|
+
@str = str
|
1121
|
+
@cmd = cmd
|
1122
|
+
end
|
1123
|
+
|
1124
|
+
def pack(packer)
|
1125
|
+
packer.pack_array_begin(2)
|
1126
|
+
packer.pack_int(cmd)
|
1127
|
+
packer.pack_string(str)
|
1128
|
+
end
|
1129
|
+
end
|
1130
|
+
|
1131
|
+
class Cmd < Exp
|
1132
|
+
attr_reader :cmd
|
1133
|
+
|
1134
|
+
def initialize(cmd)
|
1135
|
+
@cmd = cmd
|
1136
|
+
end
|
1137
|
+
|
1138
|
+
def pack(packer)
|
1139
|
+
packer.pack_array_begin(1)
|
1140
|
+
packer.pack_int(cmd)
|
1141
|
+
end
|
1142
|
+
end
|
1143
|
+
|
1144
|
+
class Bool < Exp
|
1145
|
+
attr_reader :val
|
1146
|
+
|
1147
|
+
def initialize(val)
|
1148
|
+
@val = val
|
1149
|
+
end
|
1150
|
+
|
1151
|
+
def pack(packer)
|
1152
|
+
packer.pack_boolean(val)
|
1153
|
+
end
|
1154
|
+
end
|
1155
|
+
|
1156
|
+
class Int < Exp
|
1157
|
+
attr_reader :val
|
1158
|
+
|
1159
|
+
def initialize(val)
|
1160
|
+
@val = val
|
1161
|
+
end
|
1162
|
+
|
1163
|
+
def pack(packer)
|
1164
|
+
packer.pack_long(val)
|
1165
|
+
end
|
1166
|
+
end
|
1167
|
+
|
1168
|
+
class Float < Exp
|
1169
|
+
attr_reader :val
|
1170
|
+
|
1171
|
+
def initialize(val)
|
1172
|
+
@val = val
|
1173
|
+
end
|
1174
|
+
|
1175
|
+
def pack(packer)
|
1176
|
+
packer.pack_double(val)
|
1177
|
+
end
|
1178
|
+
end
|
1179
|
+
|
1180
|
+
class Str < Exp
|
1181
|
+
attr_reader :val
|
1182
|
+
|
1183
|
+
def initialize(val)
|
1184
|
+
@val = val
|
1185
|
+
end
|
1186
|
+
|
1187
|
+
def pack(packer)
|
1188
|
+
packer.pack_particle_string(val)
|
1189
|
+
end
|
1190
|
+
end
|
1191
|
+
|
1192
|
+
class Geo < Exp
|
1193
|
+
attr_reader :val
|
1194
|
+
|
1195
|
+
def initialize(val)
|
1196
|
+
@val = val
|
1197
|
+
end
|
1198
|
+
|
1199
|
+
def pack(packer)
|
1200
|
+
packer.pack_geo_json(val)
|
1201
|
+
end
|
1202
|
+
end
|
1203
|
+
|
1204
|
+
class Blob < Exp
|
1205
|
+
attr_reader :val
|
1206
|
+
|
1207
|
+
def initialize(val)
|
1208
|
+
@val = val
|
1209
|
+
end
|
1210
|
+
|
1211
|
+
def pack(packer)
|
1212
|
+
packer.pack_particle_bytes(val)
|
1213
|
+
end
|
1214
|
+
end
|
1215
|
+
|
1216
|
+
class ListVal < Exp
|
1217
|
+
attr_reader :list
|
1218
|
+
|
1219
|
+
def initialize(list)
|
1220
|
+
@list = list
|
1221
|
+
end
|
1222
|
+
|
1223
|
+
def pack(packer)
|
1224
|
+
# List values need an extra array and QUOTED in order to distinguish
|
1225
|
+
# between a multiple argument array call and a local list.
|
1226
|
+
packer.pack_array_begin(2)
|
1227
|
+
packer.pack_int(QUOTED)
|
1228
|
+
packer.pack_list(list)
|
1229
|
+
end
|
1230
|
+
end
|
1231
|
+
|
1232
|
+
class MapVal < Exp
|
1233
|
+
attr_reader :map
|
1234
|
+
|
1235
|
+
def initialize(map)
|
1236
|
+
@map = map
|
1237
|
+
end
|
1238
|
+
|
1239
|
+
def pack(packer)
|
1240
|
+
packer.pack_map(map)
|
1241
|
+
end
|
1242
|
+
end
|
1243
|
+
|
1244
|
+
class Nil < Exp
|
1245
|
+
def pack(packer)
|
1246
|
+
packer.pack_nil
|
1247
|
+
end
|
1248
|
+
end
|
1249
|
+
|
1250
|
+
class ExpBytes < Exp
|
1251
|
+
attr_reader :bytes
|
1252
|
+
|
1253
|
+
def initialize(e)
|
1254
|
+
@bytes = e.getBytes
|
1255
|
+
end
|
1256
|
+
|
1257
|
+
def pack(packer)
|
1258
|
+
packer.pack_byte_array(bytes, 0, bytes.length)
|
1259
|
+
end
|
1260
|
+
end
|
1261
|
+
end # class Exp
|
1262
|
+
end # module
|