aerospike 2.25.0 → 2.27.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/lib/aerospike/cdt/context.rb +136 -69
- data/lib/aerospike/client.rb +57 -3
- data/lib/aerospike/command/command.rb +251 -4
- data/lib/aerospike/policy/policy.rb +11 -1
- data/lib/aerospike/policy/write_policy.rb +8 -3
- data/lib/aerospike/query/filter.rb +44 -32
- data/lib/aerospike/query/query_partition_command.rb +9 -11
- data/lib/aerospike/query/server_command.rb +60 -0
- data/lib/aerospike/query/statement.rb +31 -18
- data/lib/aerospike/record.rb +15 -1
- data/lib/aerospike/version.rb +1 -1
- data/lib/aerospike.rb +1 -0
- metadata +8 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3fe67950bfa737ce26a8a0e823cd84424219c6ce41720e0202ca93d4dcab2c1d
|
4
|
+
data.tar.gz: 83976d88565599f00136967bd86fe832a88783518c51be2789c1463fa06e795e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e018d80b673081cdbf229aa5c48dd7ebbeb9a127492cc04c651a4e56bab92d7764aba82ffb3e3783f6a6f34755ded66be58c3bf5a9e110be61c0c21e20128932
|
7
|
+
data.tar.gz: 8e02a4d37b620f838dde53b63d4af3fe20146905dd4f3a30c14f97a83453c69f0dccfbaf1f44a777bf4ab53e89583cc7a6e4343204e6749b1d4fb888f0a7200f
|
data/CHANGELOG.md
CHANGED
@@ -2,10 +2,24 @@
|
|
2
2
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
4
4
|
|
5
|
+
## [2.27.0] 2023-05-18
|
6
|
+
- **New Features**
|
7
|
+
- [CLIENT-1176] Support write operations in background query
|
8
|
+
|
9
|
+
|
10
|
+
## [2.26.0] 2022-12-02
|
11
|
+
|
12
|
+
- **New Features**
|
13
|
+
- [CLIENT-1808] Support creating a secondary index on elements within a CDT using `Context`.
|
14
|
+
- [CLIENT-1991] Add base64 encoding methods to `Context`.
|
15
|
+
- [CLIENT-2007] Support using `Context` in query filters.
|
16
|
+
|
5
17
|
## [2.25.0] 2022-11-28
|
6
18
|
|
7
19
|
- **New Features**
|
8
20
|
|
21
|
+
- [CLIENT-1984] Support scan-show and query-show info commands.
|
22
|
+
|
9
23
|
- [CLIENT-1362] Adds support Aerospike Expression filters. Expression filters are now supported on all commands, including `Client#get`, `Client#put`, `Client#delete`, `Client#operate`, `Client#scan`, `Client#query`, `Client#execute_udf`, etc.
|
10
24
|
|
11
25
|
- Adds `Policy#filter_exp` and `Policy#fail_on_filtered_out`
|
@@ -17,16 +17,17 @@
|
|
17
17
|
# License for the specific language governing permissions and limitations under
|
18
18
|
# the License.
|
19
19
|
|
20
|
+
require "base64"
|
21
|
+
|
20
22
|
module Aerospike
|
21
23
|
module CDT
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
25
|
+
##
|
26
|
+
# Nested CDT context. Identifies the location of nested list/map to apply the operation.
|
27
|
+
# for the current level.
|
28
|
+
# An array of CTX identifies location of the list/map on multiple
|
29
|
+
# levels on nesting.
|
28
30
|
class Context
|
29
|
-
|
30
31
|
attr_accessor :id, :value
|
31
32
|
|
32
33
|
def initialize(id, value)
|
@@ -37,64 +38,64 @@ module Aerospike
|
|
37
38
|
##
|
38
39
|
# Create list with given type at index offset, given an order and pad.
|
39
40
|
def self.list_index_create(index, order, pad)
|
40
|
-
|
41
|
-
end
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
41
|
+
Context.new(0x10 | ListOrder.flag(order, pad), index)
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# Lookup list by index offset.
|
46
|
+
# If the index is negative, the resolved index starts backwards from end of list.
|
47
|
+
# If an index is out of bounds, a parameter error will be returned.
|
48
|
+
# Examples:
|
49
|
+
# 0: First item.
|
50
|
+
# 4: Fifth item.
|
51
|
+
# -1: Last item.
|
52
|
+
# -3: Third to last item.
|
53
|
+
def self.list_index(index)
|
54
|
+
Context.new(0x10, index)
|
55
|
+
end
|
56
|
+
|
57
|
+
##
|
58
|
+
# Lookup list by rank.
|
59
|
+
# 0 = smallest value
|
60
|
+
# N = Nth smallest value
|
61
|
+
# -1 = largest value
|
62
|
+
def self.list_rank(rank)
|
63
|
+
Context.new(0x11, rank)
|
64
|
+
end
|
65
|
+
|
66
|
+
##
|
67
|
+
# Lookup list by value.
|
68
|
+
def self.list_value(key)
|
69
|
+
Context.new(0x13, key)
|
70
|
+
end
|
71
|
+
|
72
|
+
##
|
73
|
+
# Lookup map by index offset.
|
74
|
+
# If the index is negative, the resolved index starts backwards from end of list.
|
75
|
+
# If an index is out of bounds, a parameter error will be returned.
|
76
|
+
# Examples:
|
77
|
+
# 0: First item.
|
78
|
+
# 4: Fifth item.
|
79
|
+
# -1: Last item.
|
80
|
+
# -3: Third to last item.
|
81
|
+
def self.map_index(index)
|
82
|
+
Context.new(0x20, index)
|
83
|
+
end
|
84
|
+
|
85
|
+
##
|
86
|
+
# Lookup map by rank.
|
87
|
+
# 0 = smallest value
|
88
|
+
# N = Nth smallest value
|
89
|
+
# -1 = largest value
|
90
|
+
def self.map_rank(rank)
|
91
|
+
Context.new(0x21, rank)
|
92
|
+
end
|
93
|
+
|
94
|
+
##
|
95
|
+
# Lookup map by key.
|
96
|
+
def self.map_key(key)
|
97
|
+
Context.new(0x22, key)
|
98
|
+
end
|
98
99
|
|
99
100
|
##
|
100
101
|
# Create map with given type at map key.
|
@@ -102,12 +103,78 @@ module Aerospike
|
|
102
103
|
Context.new(0x22 | order[:flag], key)
|
103
104
|
end
|
104
105
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
106
|
+
##
|
107
|
+
# Lookup map by value.
|
108
|
+
def self.map_value(key)
|
109
|
+
Context.new(0x23, key)
|
110
|
+
end
|
111
|
+
|
112
|
+
##
|
113
|
+
# Encodes the context via message pack.
|
114
|
+
def self.pack(packer, ctx)
|
115
|
+
unless ctx.to_a.empty?
|
116
|
+
packer.write_array_header(2)
|
117
|
+
ctx.each do |c|
|
118
|
+
packer.write(c.id)
|
119
|
+
Value.of(c.value)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
##
|
125
|
+
# Encodes the context via message pack and return the results.
|
126
|
+
def self.bytes(ctx)
|
127
|
+
unless ctx.to_a.empty?
|
128
|
+
Packer.use do |packer|
|
129
|
+
packer.write_array_header(ctx.length * 2)
|
130
|
+
ctx.each do |c|
|
131
|
+
packer.write(c.id)
|
132
|
+
Value.of(c.value).pack(packer)
|
133
|
+
end
|
134
|
+
return packer.bytes
|
135
|
+
end
|
136
|
+
end
|
137
|
+
nil
|
138
|
+
end
|
139
|
+
|
140
|
+
def ==(other)
|
141
|
+
self.id == other.id && self.value == other.value
|
142
|
+
end
|
110
143
|
|
144
|
+
##
|
145
|
+
# decodes the base64 encoded messagepack byte array
|
146
|
+
# and converts it to an array of Context.
|
147
|
+
def self.from_bytes(buf)
|
148
|
+
list = nil
|
149
|
+
Unpacker.use do |unpacker|
|
150
|
+
list = unpacker.unpack(buf)
|
151
|
+
end
|
152
|
+
|
153
|
+
unless list.length % 2 == 0
|
154
|
+
raise Exceptions::Aerospike.new(Aerospike::ResultCode::PARAMETER_ERROR, "Invalid buffer")
|
155
|
+
end
|
156
|
+
|
157
|
+
list.each_slice(2).map { |id, value| Context.new(id, value) }
|
158
|
+
end
|
159
|
+
|
160
|
+
##
|
161
|
+
# Encodes the context array to messagepack and then encodes
|
162
|
+
# the resulting byte array to base64.
|
163
|
+
def self.base64(ctx)
|
164
|
+
unless ctx.to_a.empty?
|
165
|
+
data = self.bytes(ctx)
|
166
|
+
return Base64.strict_encode64(data).force_encoding("binary")
|
167
|
+
end
|
168
|
+
""
|
169
|
+
end
|
170
|
+
|
171
|
+
##
|
172
|
+
# Decodes the byte array to messagepack and then decodes
|
173
|
+
# the resulting byte array to an array of Context.
|
174
|
+
def self.from_base64(buf)
|
175
|
+
bytes = Base64.strict_decode64(buf)
|
176
|
+
self.from_bytes(bytes)
|
177
|
+
end
|
111
178
|
end
|
112
179
|
end
|
113
180
|
end
|
data/lib/aerospike/client.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2014-
|
1
|
+
# Copyright 2014-2023 Aerospike, Inc.
|
2
2
|
#
|
3
3
|
# Portions may be licensed to Aerospike, Inc. under one or more contributor
|
4
4
|
# license agreements.
|
@@ -225,7 +225,6 @@ module Aerospike
|
|
225
225
|
policy = create_policy(options, Policy, default_info_policy)
|
226
226
|
|
227
227
|
node = @cluster.random_node
|
228
|
-
conn = node.get_connection(policy.timeout)
|
229
228
|
|
230
229
|
if set_name && !set_name.to_s.strip.empty?
|
231
230
|
str_cmd = "truncate:namespace=#{namespace}"
|
@@ -566,7 +565,8 @@ module Aerospike
|
|
566
565
|
# This method is only supported by Aerospike 3 servers.
|
567
566
|
# index_type should be :string, :numeric or :geo2dsphere (requires server version 3.7 or later)
|
568
567
|
# collection_type should be :list, :mapkeys or :mapvalues
|
569
|
-
|
568
|
+
# ctx is an optional list of context. Supported on server v6.1+.
|
569
|
+
def create_index(namespace, set_name, index_name, bin_name, index_type, collection_type = nil, options = nil, ctx: nil)
|
570
570
|
if options.nil? && collection_type.is_a?(Hash)
|
571
571
|
options, collection_type = collection_type, nil
|
572
572
|
end
|
@@ -575,6 +575,7 @@ module Aerospike
|
|
575
575
|
str_cmd = "sindex-create:ns=#{namespace}"
|
576
576
|
str_cmd << ";set=#{set_name}" unless set_name.to_s.strip.empty?
|
577
577
|
str_cmd << ";indexname=#{index_name};numbins=1"
|
578
|
+
str_cmd << ";context=#{CDT::Context.base64(ctx)}" unless ctx.to_a.empty?
|
578
579
|
str_cmd << ";indextype=#{collection_type.to_s.upcase}" if collection_type
|
579
580
|
str_cmd << ";indexdata=#{bin_name},#{index_type.to_s.upcase}"
|
580
581
|
str_cmd << ";priority=normal"
|
@@ -729,6 +730,59 @@ module Aerospike
|
|
729
730
|
query_partitions(Aerospike::PartitionFilter.all, statement, options)
|
730
731
|
end
|
731
732
|
|
733
|
+
#----------------------------------------------------------
|
734
|
+
# Query/Execute (Supported by Aerospike 3+ servers only)
|
735
|
+
#----------------------------------------------------------
|
736
|
+
|
737
|
+
# QueryExecute applies operations on records that match the statement filter.
|
738
|
+
# Records are not returned to the client.
|
739
|
+
# This asynchronous server call will return before the command is complete.
|
740
|
+
# The user can optionally wait for command completion by using the returned
|
741
|
+
# ExecuteTask instance.
|
742
|
+
#
|
743
|
+
# This method is only supported by Aerospike 3+ servers.
|
744
|
+
# If the policy is nil, the default relevant policy will be used.
|
745
|
+
#
|
746
|
+
# @param statement [Aerospike::Statement] The query or batch read statement.
|
747
|
+
# @param operations [Array<Aerospike::Operation>] An optional list of operations.
|
748
|
+
# @param options [Hash] An optional hash of policy options.
|
749
|
+
# @return [Aerospike::ExecuteTask] An ExecuteTask instance that can be used to wait for command completion.
|
750
|
+
#
|
751
|
+
# @raise [Aerospike::Exceptions::Aerospike] if an error occurs during the operation.
|
752
|
+
def query_execute(statement, operations = [], options = nil)
|
753
|
+
policy = create_policy(options, WritePolicy, default_write_policy)
|
754
|
+
|
755
|
+
if statement.nil?
|
756
|
+
raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::INVALID_COMMAND, "Query failed of invalid statement.")
|
757
|
+
end
|
758
|
+
|
759
|
+
statement = statement.clone
|
760
|
+
unless operations.empty?
|
761
|
+
statement.operations = operations
|
762
|
+
end
|
763
|
+
|
764
|
+
task_id = statement.task_id
|
765
|
+
nodes = @cluster.nodes
|
766
|
+
if nodes.empty?
|
767
|
+
raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::SERVER_NOT_AVAILABLE, "Query failed because cluster is empty.")
|
768
|
+
end
|
769
|
+
|
770
|
+
# Use a thread per node
|
771
|
+
nodes.each do |node|
|
772
|
+
Thread.new do
|
773
|
+
Thread.current.abort_on_exception = true
|
774
|
+
begin
|
775
|
+
command = ServerCommand.new(@cluster, node, policy, statement, true, task_id)
|
776
|
+
execute_command(command)
|
777
|
+
rescue => e
|
778
|
+
Aerospike.logger.error(e)
|
779
|
+
raise e
|
780
|
+
end
|
781
|
+
end
|
782
|
+
end
|
783
|
+
ExecuteTask.new(@cluster, statement)
|
784
|
+
end
|
785
|
+
|
732
786
|
#-------------------------------------------------------
|
733
787
|
# User administration
|
734
788
|
#-------------------------------------------------------
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2014-
|
1
|
+
# Copyright 2014-2024 Aerospike, Inc.
|
2
2
|
#
|
3
3
|
# Portions may be licensed to Aerospike, Inc. under one or more contributor
|
4
4
|
# license agreements.
|
@@ -465,6 +465,254 @@ module Aerospike
|
|
465
465
|
end_cmd
|
466
466
|
end
|
467
467
|
|
468
|
+
def set_query(policy, statement, background, node_partitions)
|
469
|
+
function_arg_buffer = nil
|
470
|
+
field_count = 0
|
471
|
+
filter_size = 0
|
472
|
+
|
473
|
+
begin_cmd
|
474
|
+
|
475
|
+
if statement.namespace
|
476
|
+
@data_offset += statement.namespace.bytesize + FIELD_HEADER_SIZE
|
477
|
+
field_count += 1
|
478
|
+
end
|
479
|
+
|
480
|
+
if statement.set_name
|
481
|
+
@data_offset += statement.set_name.bytesize + FIELD_HEADER_SIZE
|
482
|
+
field_count += 1
|
483
|
+
end
|
484
|
+
|
485
|
+
# Estimate recordsPerSecond field size. This field is used in new servers and not used
|
486
|
+
# (but harmless to add) in old servers.
|
487
|
+
if statement.records_per_second > 0
|
488
|
+
@data_offset += 4 + FIELD_HEADER_SIZE
|
489
|
+
field_count += 1
|
490
|
+
end
|
491
|
+
|
492
|
+
# Estimate socket timeout field size. This field is used in new servers and not used
|
493
|
+
# (but harmless to add) in old servers.
|
494
|
+
@data_offset += 4 + FIELD_HEADER_SIZE
|
495
|
+
field_count += 1
|
496
|
+
|
497
|
+
# Estimate task_id field.
|
498
|
+
@data_offset += 8 + FIELD_HEADER_SIZE
|
499
|
+
field_count += 1
|
500
|
+
|
501
|
+
filter = statement.filters[0]
|
502
|
+
bin_names = statement.bin_names
|
503
|
+
packed_ctx = nil
|
504
|
+
|
505
|
+
if filter
|
506
|
+
col_type = filter.collection_type
|
507
|
+
|
508
|
+
# Estimate INDEX_TYPE field.
|
509
|
+
if col_type > 0
|
510
|
+
@data_offset += FIELD_HEADER_SIZE + 1
|
511
|
+
field_count += 1
|
512
|
+
end
|
513
|
+
|
514
|
+
# Estimate INDEX_RANGE field.
|
515
|
+
@data_offset += FIELD_HEADER_SIZE
|
516
|
+
filter_size += 1 # num filters
|
517
|
+
filter_size += filter.estimate_size
|
518
|
+
|
519
|
+
@data_offset += filter_size
|
520
|
+
field_count += 1
|
521
|
+
|
522
|
+
packed_ctx = filter.packed_ctx
|
523
|
+
if packed_ctx
|
524
|
+
@data_offset += FIELD_HEADER_SIZE + packed_ctx.length
|
525
|
+
field_count += 1
|
526
|
+
end
|
527
|
+
end
|
528
|
+
|
529
|
+
statement.set_task_id
|
530
|
+
predexp = policy.predexp || statement.predexp
|
531
|
+
|
532
|
+
if predexp
|
533
|
+
@data_offset += FIELD_HEADER_SIZE
|
534
|
+
pred_size = Aerospike::PredExp.estimate_size(predexp)
|
535
|
+
@data_offset += pred_size
|
536
|
+
field_count += 1
|
537
|
+
end
|
538
|
+
|
539
|
+
unless policy.filter_exp.nil?
|
540
|
+
exp_size = estimate_expression_size(policy.filter_exp)
|
541
|
+
field_count += 1 if exp_size > 0
|
542
|
+
end
|
543
|
+
|
544
|
+
# Estimate aggregation/background function size.
|
545
|
+
if statement.function_name
|
546
|
+
@data_offset += FIELD_HEADER_SIZE + 1 # udf type
|
547
|
+
@data_offset += statement.package_name.bytesize + FIELD_HEADER_SIZE
|
548
|
+
@data_offset += statement.function_name.bytesize + FIELD_HEADER_SIZE
|
549
|
+
|
550
|
+
function_arg_buffer = ""
|
551
|
+
if statement.function_args && statement.function_args.length > 0
|
552
|
+
function_arg_buffer = Value.of(statement.function_args).to_bytes
|
553
|
+
end
|
554
|
+
@data_offset += FIELD_HEADER_SIZE + function_arg_buffer.bytesize
|
555
|
+
field_count += 4
|
556
|
+
end
|
557
|
+
|
558
|
+
max_records = 0
|
559
|
+
parts_full_size = 0
|
560
|
+
parts_partial_digest_size = 0
|
561
|
+
parts_partial_bval_size = 0
|
562
|
+
|
563
|
+
unless node_partitions.nil?
|
564
|
+
parts_full_size = node_partitions.parts_full.length * 2
|
565
|
+
parts_partial_digest_size = node_partitions.parts_partial.length * 20
|
566
|
+
|
567
|
+
unless filter.nil?
|
568
|
+
parts_partial_bval_size = node_partitions.parts_partial.length * 8
|
569
|
+
end
|
570
|
+
max_records = node_partitions.record_max
|
571
|
+
end
|
572
|
+
|
573
|
+
if parts_full_size > 0
|
574
|
+
@data_offset += parts_full_size + FIELD_HEADER_SIZE
|
575
|
+
field_count += 1
|
576
|
+
end
|
577
|
+
|
578
|
+
if parts_partial_digest_size > 0
|
579
|
+
@data_offset += parts_partial_digest_size + FIELD_HEADER_SIZE
|
580
|
+
field_count += 1
|
581
|
+
end
|
582
|
+
|
583
|
+
if parts_partial_bval_size > 0
|
584
|
+
@data_offset += parts_partial_bval_size + FIELD_HEADER_SIZE
|
585
|
+
field_count += 1
|
586
|
+
end
|
587
|
+
|
588
|
+
# Estimate max records field size. This field is used in new servers and not used
|
589
|
+
# (but harmless to add) in old servers.
|
590
|
+
if max_records > 0
|
591
|
+
@data_offset += 8 + FIELD_HEADER_SIZE
|
592
|
+
field_count += 1
|
593
|
+
end
|
594
|
+
|
595
|
+
operations = statement.operations
|
596
|
+
operation_count = 0
|
597
|
+
|
598
|
+
if !operations.empty?
|
599
|
+
|
600
|
+
unless background
|
601
|
+
raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::PARAMETER_ERROR)
|
602
|
+
end
|
603
|
+
|
604
|
+
operations.each do |operation|
|
605
|
+
estimate_operation_size_for_operation(operation)
|
606
|
+
end
|
607
|
+
operation_count = operations.size
|
608
|
+
elsif !bin_names.empty?
|
609
|
+
bin_names.each do |bin_name|
|
610
|
+
estimate_operation_size_for_bin_name(bin_name)
|
611
|
+
end
|
612
|
+
operation_count = bin_names.length
|
613
|
+
# Estimate size for selected bin names (query bin names already handled for old servers).
|
614
|
+
end
|
615
|
+
|
616
|
+
size_buffer
|
617
|
+
|
618
|
+
if background
|
619
|
+
write_header_with_policy(policy, 0, INFO2_WRITE, field_count, operation_count)
|
620
|
+
else
|
621
|
+
read_attr = INFO1_READ
|
622
|
+
read_attr |= INFO1_NOBINDATA unless policy.include_bin_data
|
623
|
+
read_attr |= INFO1_SHORT_QUERY if policy.short_query
|
624
|
+
write_header(policy, read_attr, 0, field_count, operation_count)
|
625
|
+
end
|
626
|
+
|
627
|
+
write_field_string(statement.namespace, FieldType::NAMESPACE) if statement.namespace
|
628
|
+
write_field_string(statement.set_name, FieldType::TABLE) if statement.set_name
|
629
|
+
|
630
|
+
# Write records per second.
|
631
|
+
write_field_int(statement.records_per_second, FieldType::RECORDS_PER_SECOND) if statement.records_per_second > 0
|
632
|
+
|
633
|
+
write_filter_exp(policy.filter_exp, exp_size)
|
634
|
+
|
635
|
+
# Write socket idle timeout.
|
636
|
+
write_field_int(policy.socket_timeout, FieldType::SOCKET_TIMEOUT)
|
637
|
+
|
638
|
+
# Write task_id field
|
639
|
+
write_field_int64(statement.task_id, FieldType::TRAN_ID)
|
640
|
+
|
641
|
+
unless predexp.nil?
|
642
|
+
write_field_header(pred_size, Aerospike::FieldType::PREDEXP)
|
643
|
+
@data_offset = Aerospike::PredExp.write(
|
644
|
+
predexp, @data_buffer, @data_offset
|
645
|
+
)
|
646
|
+
end
|
647
|
+
|
648
|
+
if filter
|
649
|
+
type = filter.collection_type
|
650
|
+
|
651
|
+
if type > 0
|
652
|
+
write_field_header(1, FieldType::INDEX_TYPE)
|
653
|
+
@data_offset += @data_buffer.write_byte(type, @data_offset)
|
654
|
+
end
|
655
|
+
|
656
|
+
write_field_header(filter_size, FieldType::INDEX_RANGE)
|
657
|
+
@data_offset += @data_buffer.write_byte(1, @data_offset)
|
658
|
+
@data_offset = filter.write(@data_buffer, @data_offset)
|
659
|
+
|
660
|
+
if packed_ctx
|
661
|
+
write_field_header(packed_ctx.length, FieldType::INDEX_CONTEXT)
|
662
|
+
@data_offset += @data_buffer.write_binary(packed_ctx, @data_offset)
|
663
|
+
end
|
664
|
+
end
|
665
|
+
|
666
|
+
if statement.function_name
|
667
|
+
write_field_header(1, FieldType::UDF_OP)
|
668
|
+
@data_offset += @data_buffer.write_byte(1, @data_offset)
|
669
|
+
write_field_string(statement.package_name, FieldType::UDF_PACKAGE_NAME)
|
670
|
+
write_field_string(statement.function_name, FieldType::UDF_FUNCTION)
|
671
|
+
write_field_string(function_arg_buffer, FieldType::UDF_ARGLIST)
|
672
|
+
end
|
673
|
+
|
674
|
+
if parts_full_size > 0
|
675
|
+
write_field_header(parts_full_size, FieldType::PID_ARRAY)
|
676
|
+
node_partitions.parts_full.each do |part|
|
677
|
+
@data_offset += @data_buffer.write_uint16_little_endian(part.id, @data_offset)
|
678
|
+
end
|
679
|
+
end
|
680
|
+
|
681
|
+
if parts_partial_digest_size > 0
|
682
|
+
write_field_header(parts_partial_digest_size, FieldType::DIGEST_ARRAY)
|
683
|
+
node_partitions.parts_partial.each do |part|
|
684
|
+
@data_offset += @data_buffer.write_binary(part.digest, @data_offset)
|
685
|
+
end
|
686
|
+
end
|
687
|
+
|
688
|
+
if parts_partial_bval_size > 0
|
689
|
+
write_field_header(parts_partial_bval_size, FieldType::BVAL_ARRAY)
|
690
|
+
@node_partitions.parts_partial.each do |part|
|
691
|
+
@data_offset += @data_buffer.write_uint64_little_endian(part.bval, @data_offset)
|
692
|
+
end
|
693
|
+
end
|
694
|
+
|
695
|
+
if max_records > 0
|
696
|
+
write_field(max_records, FieldType::MAX_RECORDS)
|
697
|
+
end
|
698
|
+
|
699
|
+
if operations.empty?
|
700
|
+
if bin_names.empty?
|
701
|
+
bin_names.each do |bin_name|
|
702
|
+
write_operation_for_bin_name(bin_name, Operation::READ)
|
703
|
+
end
|
704
|
+
end
|
705
|
+
else
|
706
|
+
operations.each do |operation|
|
707
|
+
write_operation_for_operation(operation)
|
708
|
+
end
|
709
|
+
end
|
710
|
+
|
711
|
+
end_cmd
|
712
|
+
|
713
|
+
nil
|
714
|
+
end
|
715
|
+
|
468
716
|
def execute
|
469
717
|
iterations = 0
|
470
718
|
|
@@ -537,7 +785,7 @@ module Aerospike
|
|
537
785
|
parse_result
|
538
786
|
rescue => e
|
539
787
|
case e
|
540
|
-
|
788
|
+
# do not log the following exceptions
|
541
789
|
when Aerospike::Exceptions::ScanTerminated
|
542
790
|
when Aerospike::Exceptions::QueryTerminated
|
543
791
|
else
|
@@ -703,9 +951,8 @@ module Aerospike
|
|
703
951
|
read_attr |= INFO1_CONSISTENCY_ALL if policy.consistency_level == Aerospike::ConsistencyLevel::CONSISTENCY_ALL
|
704
952
|
write_attr |= INFO2_DURABLE_DELETE if policy.durable_delete
|
705
953
|
read_attr |= INFO1_COMPRESS_RESPONSE if policy.use_compression
|
706
|
-
|
707
954
|
# Write all header data except total size which must be written last.
|
708
|
-
@data_buffer.write_byte(MSG_REMAINING_HEADER_SIZE, 8) # Message
|
955
|
+
@data_buffer.write_byte(MSG_REMAINING_HEADER_SIZE, 8) # Message header.length.
|
709
956
|
@data_buffer.write_byte(read_attr, 9)
|
710
957
|
@data_buffer.write_byte(write_attr, 10)
|
711
958
|
@data_buffer.write_byte(info_attr, 11)
|
@@ -22,7 +22,7 @@ module Aerospike
|
|
22
22
|
# Container object for client policy command.
|
23
23
|
class Policy
|
24
24
|
attr_accessor :filter_exp, :priority, :timeout, :max_retries, :sleep_between_retries, :consistency_level,
|
25
|
-
:predexp, :fail_on_filtered_out, :replica, :use_compression
|
25
|
+
:predexp, :fail_on_filtered_out, :replica, :use_compression, :socket_timeout
|
26
26
|
|
27
27
|
alias total_timeout timeout
|
28
28
|
alias total_timeout= timeout=
|
@@ -133,6 +133,16 @@ module Aerospike
|
|
133
133
|
# Duration to sleep between retries if a transaction fails and the
|
134
134
|
# timeout was not exceeded. Enter zero to skip sleep.
|
135
135
|
@sleep_between_retries = opt[:sleep_between_retries] || 0.5
|
136
|
+
|
137
|
+
# Determines network timeout for each attempt.
|
138
|
+
#
|
139
|
+
# If socket_timeout is not zero and socket_timeout is reached before an attempt completes,
|
140
|
+
# the Timeout above is checked. If Timeout is not exceeded, the transaction
|
141
|
+
# is retried. If both socket_timeout and Timeout are non-zero, socket_timeout must be less
|
142
|
+
# than or equal to Timeout, otherwise Timeout will also be used for socket_timeout.
|
143
|
+
#
|
144
|
+
# Default: 30s
|
145
|
+
@socket_timeout = opt[:socket_timeout] || 30000
|
136
146
|
end
|
137
147
|
end # class
|
138
148
|
end # module
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
# Copyright 2014-
|
2
|
+
# Copyright 2014-2023 Aerospike, Inc.
|
3
3
|
#
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
5
|
# you may not use this file except in compliance with the License.
|
@@ -24,8 +24,8 @@ module Aerospike
|
|
24
24
|
class WritePolicy < Policy
|
25
25
|
|
26
26
|
attr_accessor :record_exists_action, :generation_policy,
|
27
|
-
|
28
|
-
|
27
|
+
:generation, :ttl, :send_key, :commit_level,
|
28
|
+
:durable_delete
|
29
29
|
|
30
30
|
alias expiration ttl
|
31
31
|
alias expiration= ttl=
|
@@ -74,6 +74,11 @@ module Aerospike
|
|
74
74
|
# Valid for Aerospike Server Enterprise Edition 3.10+ only.
|
75
75
|
@durable_delete = opt.fetch(:durable_delete, false)
|
76
76
|
|
77
|
+
# Transaction timeout.
|
78
|
+
# This timeout is used to set the socket timeout and is also sent to the
|
79
|
+
# server along with the transaction in the wire protocol.
|
80
|
+
# Default for write policy is 1.
|
81
|
+
@timeout = opt[:timeout] || 1
|
77
82
|
self
|
78
83
|
end
|
79
84
|
|
@@ -15,39 +15,51 @@
|
|
15
15
|
# the License.
|
16
16
|
|
17
17
|
module Aerospike
|
18
|
-
|
19
18
|
class Filter
|
19
|
+
attr_reader :packed_ctx
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
# open up the class to alias the class methods for naming consistency
|
22
|
+
class << self
|
23
|
+
def equal(bin_name, value, ctx: nil)
|
24
|
+
Filter.new(bin_name, value, value, nil, nil, ctx)
|
25
|
+
end
|
24
26
|
|
25
|
-
|
26
|
-
|
27
|
-
|
27
|
+
def contains(bin_name, value, col_type, ctx: nil)
|
28
|
+
Filter.new(bin_name, value, value, nil, col_type, ctx)
|
29
|
+
end
|
28
30
|
|
29
|
-
|
30
|
-
|
31
|
-
|
31
|
+
def range(bin_name, from, to, col_type = nil, ctx: nil)
|
32
|
+
Filter.new(bin_name, from, to, nil, col_type, ctx)
|
33
|
+
end
|
32
34
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
35
|
+
def geo_within_geo_region(bin_name, region, col_type = nil, ctx: nil)
|
36
|
+
region = region.to_json
|
37
|
+
Filter.new(bin_name, region, region, ParticleType::GEOJSON, col_type, ctx)
|
38
|
+
end
|
37
39
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
40
|
+
def geo_within_radius(bin_name, lon, lat, radius_meter, col_type = nil, ctx: nil)
|
41
|
+
region = GeoJSON.new({ type: "AeroCircle", coordinates: [[lon, lat], radius_meter] })
|
42
|
+
geo_within_geo_region(bin_name, region, col_type, ctx: ctx)
|
43
|
+
end
|
42
44
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
45
|
+
def geo_contains_geo_point(bin_name, point, col_type = nil, ctx: nil)
|
46
|
+
point = point.to_json
|
47
|
+
Filter.new(bin_name, point, point, ParticleType::GEOJSON, col_type, ctx)
|
48
|
+
end
|
47
49
|
|
48
|
-
|
49
|
-
|
50
|
-
|
50
|
+
def geo_contains_point(bin_name, lon, lat, col_type = nil, ctx: nil)
|
51
|
+
point = GeoJSON.new({ type: "Point", coordinates: [lon, lat] })
|
52
|
+
geo_contains_geo_point(bin_name, point, col_type, ctx: ctx)
|
53
|
+
end
|
54
|
+
|
55
|
+
# alias the old names for compatibility
|
56
|
+
alias :Equal :equal
|
57
|
+
alias :Contains :contains
|
58
|
+
alias :Range :range
|
59
|
+
alias :geoWithinGeoJSONRegion :geo_within_geo_region
|
60
|
+
alias :geoWithinRadius :geo_within_radius
|
61
|
+
alias :geoContainsGeoJSONPoint :geo_contains_geo_point
|
62
|
+
alias :geoContainsPoint :geo_contains_point
|
51
63
|
end
|
52
64
|
|
53
65
|
def estimate_size
|
@@ -56,21 +68,21 @@ module Aerospike
|
|
56
68
|
|
57
69
|
def write(buf, offset)
|
58
70
|
# Write name.
|
59
|
-
len = buf.write_binary(@name, offset+1)
|
71
|
+
len = buf.write_binary(@name, offset + 1)
|
60
72
|
buf.write_byte(len, offset)
|
61
73
|
offset += len + 1
|
62
74
|
|
63
75
|
# Write particle type.
|
64
76
|
buf.write_byte(@val_type, offset)
|
65
|
-
offset+=1
|
77
|
+
offset += 1
|
66
78
|
|
67
79
|
# Write filter begin.
|
68
|
-
len = @begin.write(buf, offset+4)
|
80
|
+
len = @begin.write(buf, offset + 4)
|
69
81
|
buf.write_int32(len, offset)
|
70
82
|
offset += len + 4
|
71
83
|
|
72
84
|
# Write filter end.
|
73
|
-
len = @end.write(buf, offset+4)
|
85
|
+
len = @end.write(buf, offset + 4)
|
74
86
|
buf.write_int32(len, offset)
|
75
87
|
offset += len + 4
|
76
88
|
|
@@ -98,7 +110,7 @@ module Aerospike
|
|
98
110
|
|
99
111
|
private
|
100
112
|
|
101
|
-
def initialize(bin_name, begin_value, end_value, val_type = nil, col_type = nil)
|
113
|
+
def initialize(bin_name, begin_value, end_value, val_type = nil, col_type = nil, ctx = nil)
|
102
114
|
@name = bin_name
|
103
115
|
@begin = Aerospike::Value.of(begin_value)
|
104
116
|
@end = Aerospike::Value.of(end_value)
|
@@ -107,8 +119,8 @@ module Aerospike
|
|
107
119
|
# but in certain cases caller can override the type.
|
108
120
|
@val_type = val_type || @begin.type
|
109
121
|
@col_type = col_type
|
110
|
-
end
|
111
122
|
|
123
|
+
@packed_ctx = CDT::Context.bytes(ctx)
|
124
|
+
end
|
112
125
|
end # class
|
113
|
-
|
114
126
|
end
|
@@ -82,12 +82,11 @@ module Aerospike
|
|
82
82
|
@data_offset += filter_size
|
83
83
|
field_count += 1
|
84
84
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
# end
|
85
|
+
packed_ctx = filter.packed_ctx
|
86
|
+
if packed_ctx
|
87
|
+
@data_offset += FIELD_HEADER_SIZE + packed_ctx.length
|
88
|
+
field_count += 1
|
89
|
+
end
|
91
90
|
end
|
92
91
|
|
93
92
|
@statement.set_task_id
|
@@ -210,11 +209,10 @@ module Aerospike
|
|
210
209
|
@data_offset += @data_buffer.write_byte(1, @data_offset)
|
211
210
|
@data_offset = filter.write(@data_buffer, @data_offset)
|
212
211
|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
# end
|
212
|
+
if packed_ctx
|
213
|
+
write_field_header(packed_ctx.length, FieldType::INDEX_CONTEXT)
|
214
|
+
@data_offset += @data_buffer.write_binary(packed_ctx, @data_offset)
|
215
|
+
end
|
218
216
|
end
|
219
217
|
|
220
218
|
if @statement.function_name
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# Copyright 2014-2023 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 not
|
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
|
+
|
18
|
+
module Aerospike
|
19
|
+
class ServerCommand < MultiCommand
|
20
|
+
attr_accessor :statement, :task_id, :cluster, :write_policy, :background
|
21
|
+
|
22
|
+
def initialize(cluster, node, policy, statement, background, task_id)
|
23
|
+
super(node)
|
24
|
+
@statement = statement
|
25
|
+
@task_id = task_id
|
26
|
+
@cluster = cluster
|
27
|
+
@policy = policy
|
28
|
+
@background = background
|
29
|
+
end
|
30
|
+
|
31
|
+
def write?
|
32
|
+
true
|
33
|
+
end
|
34
|
+
|
35
|
+
def write_buffer
|
36
|
+
set_query(@policy, @statement, background, nil)
|
37
|
+
end
|
38
|
+
|
39
|
+
def parse_row
|
40
|
+
field_count = @data_buffer.read_int16(18)
|
41
|
+
result_code = @data_buffer.read(5).ord & 0xFF
|
42
|
+
skip_key(field_count)
|
43
|
+
|
44
|
+
if result_code != 0
|
45
|
+
if result_code == Aerospike::ResultCode::KEY_NOT_FOUND_ERROR
|
46
|
+
return false
|
47
|
+
end
|
48
|
+
raise Aerospike::Exceptions::Aerospike.new(result_code)
|
49
|
+
end
|
50
|
+
op_count = @data_buffer.read_int16(20)
|
51
|
+
if op_count <= 0
|
52
|
+
return Record.new(@node, key, bins, generation, expiration)
|
53
|
+
end
|
54
|
+
|
55
|
+
unless valid?
|
56
|
+
raise Aerospike::Exceptions::QueryTerminated
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
# Copyright 2014-
|
2
|
+
# Copyright 2014-2023 Aerospike, Inc.
|
3
3
|
#
|
4
4
|
# Portions may be licensed to Aerospike, Inc. under one or more contributor
|
5
5
|
# license agreements.
|
@@ -16,11 +16,14 @@
|
|
16
16
|
|
17
17
|
module Aerospike
|
18
18
|
|
19
|
+
# The Aerospike::Statement class represents a query or scan statement to be executed on the database.
|
20
|
+
# It provides a set of properties that define the query or scan, including namespace, set name, bin names,
|
21
|
+
# index name, filters, and operations.
|
19
22
|
class Statement
|
20
23
|
|
21
24
|
attr_accessor :namespace, :set_name, :index_name, :bin_names, :task_id
|
22
|
-
attr_accessor :filters, :package_name, :function_name, :function_args
|
23
|
-
attr_accessor :predexp, :return_data
|
25
|
+
attr_accessor :filters, :package_name, :function_name, :function_args, :operations
|
26
|
+
attr_accessor :predexp, :return_data, :records_per_second
|
24
27
|
|
25
28
|
def initialize(namespace, set_name, bin_names=[])
|
26
29
|
# Namespace determines query Namespace
|
@@ -56,6 +59,14 @@ module Aerospike
|
|
56
59
|
@package_name = nil
|
57
60
|
@function_name = nil
|
58
61
|
@function_args = nil
|
62
|
+
@operations = nil
|
63
|
+
|
64
|
+
|
65
|
+
# Limit returned records per second (rps) rate for each server.
|
66
|
+
# Will not apply rps limit if records_per_second is zero.
|
67
|
+
# Currently only applicable to a query without a defined filter (scan).
|
68
|
+
# Default is 0
|
69
|
+
@records_per_second = 0
|
59
70
|
|
60
71
|
# TaskId determines query task id. (Optional)
|
61
72
|
@task_id = rand(RAND_MAX)
|
@@ -64,33 +75,35 @@ module Aerospike
|
|
64
75
|
@return_data = true
|
65
76
|
end
|
66
77
|
|
67
|
-
|
78
|
+
def set_aggregate_function(package_name, function_name, function_args=[], return_data=true)
|
68
79
|
@package_name = package_name
|
69
80
|
@function_name = function_name
|
70
81
|
@function_args = function_args
|
71
82
|
@return_data = return_data
|
72
|
-
|
83
|
+
end
|
73
84
|
|
74
|
-
|
75
|
-
|
76
|
-
|
85
|
+
def is_scan?
|
86
|
+
return (filters.nil? || (filters.empty?))
|
87
|
+
end
|
77
88
|
|
78
|
-
|
79
|
-
|
80
|
-
|
89
|
+
def set_task_id
|
90
|
+
while @task_id == 0
|
91
|
+
@task_id = rand(RAND_MAX)
|
92
|
+
end
|
81
93
|
end
|
82
|
-
end
|
83
94
|
|
84
|
-
|
85
|
-
@task_id = rand(RAND_MAX)
|
86
|
-
while @task_id == 0
|
95
|
+
def reset_task_id
|
87
96
|
@task_id = rand(RAND_MAX)
|
97
|
+
while @task_id == 0
|
98
|
+
@task_id = rand(RAND_MAX)
|
99
|
+
end
|
88
100
|
end
|
89
|
-
end
|
90
101
|
|
91
|
-
private
|
92
102
|
|
93
|
-
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
RAND_MAX = 2**63 - 1
|
94
107
|
|
95
108
|
end # class
|
96
109
|
end
|
data/lib/aerospike/record.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2014-
|
1
|
+
# Copyright 2014-2023 Aerospike, Inc.
|
2
2
|
#
|
3
3
|
# Portions may be licensed to Aerospike, Inc. under one or more contributor
|
4
4
|
# license agreements.
|
@@ -33,6 +33,8 @@ module Aerospike
|
|
33
33
|
@node = node
|
34
34
|
end
|
35
35
|
|
36
|
+
|
37
|
+
|
36
38
|
def to_s
|
37
39
|
"key: `#{key}` bins: `#{bins}` generation: `#{generation}`, ttl: `#{ttl}`"
|
38
40
|
end
|
@@ -41,6 +43,18 @@ module Aerospike
|
|
41
43
|
|
42
44
|
CITRUSLEAF_EPOCH = 1262304000
|
43
45
|
|
46
|
+
# Arguments:
|
47
|
+
# value: the key to retrieve the value for
|
48
|
+
#
|
49
|
+
# Returns:
|
50
|
+
# the value of the specified key, or `nil` if `@bins` is `nil`
|
51
|
+
def get_value(value)
|
52
|
+
unless @bins.nil?
|
53
|
+
return @bins[value]
|
54
|
+
end
|
55
|
+
nil
|
56
|
+
end
|
57
|
+
|
44
58
|
# Converts an absolute expiration time (in seconds from citrusleaf epoch)
|
45
59
|
# to relative time-to-live (TTL) in seconds
|
46
60
|
def expiration_to_ttl(secs_from_epoc)
|
data/lib/aerospike/version.rb
CHANGED
data/lib/aerospike.rb
CHANGED
@@ -169,6 +169,7 @@ require "aerospike/query/scan_executor"
|
|
169
169
|
require "aerospike/query/scan_partition_command"
|
170
170
|
require "aerospike/query/query_executor"
|
171
171
|
require "aerospike/query/query_partition_command"
|
172
|
+
require "aerospike/query/server_command"
|
172
173
|
|
173
174
|
require "aerospike/exp/exp"
|
174
175
|
require "aerospike/exp/exp_map"
|
metadata
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aerospike
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.27.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Khosrow Afroozeh
|
8
8
|
- Jan Hecking
|
9
|
-
|
9
|
+
- Sachin Venkatesha Murthy
|
10
|
+
autorequire:
|
10
11
|
bindir: bin
|
11
12
|
cert_chain: []
|
12
|
-
date:
|
13
|
+
date: 2023-05-18 00:00:00.000000000 Z
|
13
14
|
dependencies:
|
14
15
|
- !ruby/object:Gem::Dependency
|
15
16
|
name: msgpack
|
@@ -44,6 +45,7 @@ description: Official Aerospike Client for ruby. Access your Aerospike cluster w
|
|
44
45
|
email:
|
45
46
|
- khosrow@aerospike.com
|
46
47
|
- jhecking@aerospike.com
|
48
|
+
- smurthy@aerospike.com
|
47
49
|
executables: []
|
48
50
|
extensions: []
|
49
51
|
extra_rdoc_files: []
|
@@ -181,6 +183,7 @@ files:
|
|
181
183
|
- lib/aerospike/query/scan_command.rb
|
182
184
|
- lib/aerospike/query/scan_executor.rb
|
183
185
|
- lib/aerospike/query/scan_partition_command.rb
|
186
|
+
- lib/aerospike/query/server_command.rb
|
184
187
|
- lib/aerospike/query/statement.rb
|
185
188
|
- lib/aerospike/query/stream_command.rb
|
186
189
|
- lib/aerospike/record.rb
|
@@ -227,8 +230,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
227
230
|
- !ruby/object:Gem::Version
|
228
231
|
version: '0'
|
229
232
|
requirements: []
|
230
|
-
rubygems_version: 3.3.
|
231
|
-
signing_key:
|
233
|
+
rubygems_version: 3.3.3
|
234
|
+
signing_key:
|
232
235
|
specification_version: 4
|
233
236
|
summary: An Aerospike driver for Ruby.
|
234
237
|
test_files: []
|