couchbase 3.0.0.alpha.5 → 3.0.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +12 -3
- data/README.md +4 -2
- data/Rakefile +1 -1
- data/couchbase.gemspec +17 -12
- data/ext/.idea/misc.xml +12 -0
- data/ext/CMakeLists.txt +10 -1
- data/ext/build_config.hxx.in +20 -0
- data/ext/build_version.hxx.in +1 -1
- data/ext/couchbase/bucket.hxx +90 -24
- data/ext/couchbase/cluster.hxx +125 -84
- data/ext/couchbase/cluster_options.hxx +53 -0
- data/ext/couchbase/configuration.hxx +220 -2
- data/ext/couchbase/couchbase.cxx +134 -127
- data/ext/couchbase/io/dns_client.hxx +3 -1
- data/ext/couchbase/io/http_command.hxx +91 -0
- data/ext/couchbase/io/http_session.hxx +58 -19
- data/ext/couchbase/io/http_session_manager.hxx +26 -31
- data/ext/couchbase/io/mcbp_command.hxx +180 -0
- data/ext/couchbase/io/mcbp_message.hxx +5 -0
- data/ext/couchbase/io/mcbp_session.hxx +213 -98
- data/ext/couchbase/io/streams.hxx +165 -0
- data/ext/couchbase/operations.hxx +1 -1
- data/ext/couchbase/operations/analytics_dataset_create.hxx +1 -1
- data/ext/couchbase/operations/bucket_create.hxx +4 -2
- data/ext/couchbase/operations/bucket_drop.hxx +4 -2
- data/ext/couchbase/operations/bucket_flush.hxx +4 -2
- data/ext/couchbase/operations/bucket_get.hxx +4 -2
- data/ext/couchbase/operations/bucket_get_all.hxx +4 -2
- data/ext/couchbase/operations/bucket_update.hxx +4 -2
- data/ext/couchbase/operations/cluster_developer_preview_enable.hxx +4 -2
- data/ext/couchbase/operations/collection_create.hxx +4 -2
- data/ext/couchbase/operations/collection_drop.hxx +4 -2
- data/ext/couchbase/operations/document_analytics.hxx +0 -4
- data/ext/couchbase/operations/document_decrement.hxx +6 -3
- data/ext/couchbase/operations/document_get.hxx +3 -0
- data/ext/couchbase/operations/document_get_and_lock.hxx +3 -0
- data/ext/couchbase/operations/document_get_and_touch.hxx +5 -2
- data/ext/couchbase/operations/document_get_projected.hxx +12 -9
- data/ext/couchbase/operations/document_increment.hxx +6 -3
- data/ext/couchbase/operations/document_insert.hxx +5 -2
- data/ext/couchbase/operations/document_lookup_in.hxx +3 -0
- data/ext/couchbase/operations/document_mutate_in.hxx +6 -3
- data/ext/couchbase/operations/document_remove.hxx +3 -0
- data/ext/couchbase/operations/document_replace.hxx +5 -2
- data/ext/couchbase/operations/document_search.hxx +6 -7
- data/ext/couchbase/operations/document_touch.hxx +5 -2
- data/ext/couchbase/operations/document_unlock.hxx +3 -0
- data/ext/couchbase/operations/document_upsert.hxx +5 -2
- data/ext/couchbase/operations/query_index_build_deferred.hxx +3 -3
- data/ext/couchbase/operations/query_index_create.hxx +3 -3
- data/ext/couchbase/operations/query_index_drop.hxx +3 -3
- data/ext/couchbase/operations/query_index_get_all.hxx +3 -3
- data/ext/couchbase/operations/scope_create.hxx +4 -2
- data/ext/couchbase/operations/scope_drop.hxx +4 -2
- data/ext/couchbase/operations/scope_get_all.hxx +4 -2
- data/ext/couchbase/operations/search_index_analyze_document.hxx +2 -2
- data/ext/couchbase/operations/search_index_control_ingest.hxx +2 -2
- data/ext/couchbase/operations/search_index_control_plan_freeze.hxx +2 -2
- data/ext/couchbase/operations/search_index_control_query.hxx +2 -2
- data/ext/couchbase/operations/search_index_drop.hxx +2 -2
- data/ext/couchbase/operations/search_index_get.hxx +2 -2
- data/ext/couchbase/operations/search_index_get_all.hxx +2 -2
- data/ext/couchbase/operations/search_index_get_documents_count.hxx +2 -2
- data/ext/couchbase/operations/search_index_upsert.hxx +2 -2
- data/ext/couchbase/origin.hxx +148 -0
- data/ext/couchbase/protocol/cmd_cluster_map_change_notification.hxx +1 -6
- data/ext/couchbase/protocol/cmd_decrement.hxx +5 -5
- data/ext/couchbase/protocol/cmd_get_and_touch.hxx +5 -5
- data/ext/couchbase/protocol/cmd_get_cluster_config.hxx +1 -6
- data/ext/couchbase/protocol/cmd_increment.hxx +5 -5
- data/ext/couchbase/protocol/cmd_info.hxx +0 -11
- data/ext/couchbase/protocol/cmd_insert.hxx +5 -5
- data/ext/couchbase/protocol/cmd_mutate_in.hxx +6 -6
- data/ext/couchbase/protocol/cmd_replace.hxx +5 -5
- data/ext/couchbase/protocol/cmd_touch.hxx +1 -1
- data/ext/couchbase/protocol/cmd_upsert.hxx +5 -5
- data/ext/couchbase/timeout_defaults.hxx +7 -0
- data/ext/couchbase/utils/connection_string.hxx +139 -0
- data/ext/extconf.rb +44 -11
- data/ext/test/main.cxx +93 -15
- data/ext/third_party/http_parser/Makefile +160 -0
- data/ext/third_party/json/Makefile +77 -0
- data/lib/couchbase/analytics_options.rb +18 -4
- data/lib/couchbase/binary_collection.rb +2 -2
- data/lib/couchbase/binary_collection_options.rb +2 -2
- data/lib/couchbase/bucket.rb +4 -4
- data/lib/couchbase/cluster.rb +60 -46
- data/lib/couchbase/collection.rb +13 -13
- data/lib/couchbase/collection_options.rb +15 -9
- data/{bin/console → lib/couchbase/datastructures.rb} +4 -7
- data/lib/couchbase/datastructures/couchbase_list.rb +171 -0
- data/lib/couchbase/datastructures/couchbase_map.rb +205 -0
- data/lib/couchbase/datastructures/couchbase_queue.rb +145 -0
- data/lib/couchbase/datastructures/couchbase_set.rb +138 -0
- data/lib/couchbase/errors.rb +66 -63
- data/lib/couchbase/management/user_manager.rb +1 -1
- data/lib/couchbase/mutation_state.rb +1 -0
- data/lib/couchbase/query_options.rb +25 -2
- data/lib/couchbase/scope.rb +0 -7
- data/lib/couchbase/search_options.rb +7 -0
- data/lib/couchbase/version.rb +1 -1
- data/lib/couchbase/view_options.rb +4 -3
- metadata +20 -82
- data/.github/workflows/tests-6.0.3.yml +0 -52
- data/.github/workflows/tests-dev-preview.yml +0 -55
- data/.github/workflows/tests.yml +0 -50
- data/.gitignore +0 -20
- data/.gitmodules +0 -21
- data/.idea/.gitignore +0 -5
- data/.idea/dictionaries/gem_terms.xml +0 -18
- data/.idea/inspectionProfiles/Project_Default.xml +0 -8
- data/.idea/vcs.xml +0 -13
- data/bin/check-cluster +0 -31
- data/bin/fetch-stats +0 -19
- data/bin/init-cluster +0 -82
- data/bin/jenkins/build-extension +0 -35
- data/bin/jenkins/install-dependencies +0 -47
- data/bin/jenkins/test-with-cbdyncluster +0 -58
- data/bin/setup +0 -24
- data/ext/couchbase/configuration_monitor.hxx +0 -93
- data/ext/couchbase/operations/command.hxx +0 -163
- data/rbi/couchbase.rbi +0 -79
data/lib/couchbase/bucket.rb
CHANGED
@@ -26,7 +26,7 @@ module Couchbase
|
|
26
26
|
|
27
27
|
# @param [Couchbase::Backend] backend
|
28
28
|
def initialize(backend, name)
|
29
|
-
backend.open_bucket(name)
|
29
|
+
backend.open_bucket(name, true)
|
30
30
|
@backend = backend
|
31
31
|
@name = name
|
32
32
|
end
|
@@ -60,7 +60,7 @@ module Couchbase
|
|
60
60
|
#
|
61
61
|
# @return [Collection]
|
62
62
|
def default_collection
|
63
|
-
|
63
|
+
Collection.new(@backend, @name, :_default, :_default)
|
64
64
|
end
|
65
65
|
|
66
66
|
# Performs query to view index.
|
@@ -69,7 +69,7 @@ module Couchbase
|
|
69
69
|
# @param [String] view_name name of the view to query
|
70
70
|
# @param [ViewOptions] options
|
71
71
|
#
|
72
|
-
# @return [
|
72
|
+
# @return [ViewResult]
|
73
73
|
def view_query(design_document_name, view_name, options = ViewOptions.new)
|
74
74
|
resp = @backend.document_view(@name, design_document_name, view_name, options.namespace, {
|
75
75
|
timeout: options.timeout,
|
@@ -84,7 +84,7 @@ module Couchbase
|
|
84
84
|
group: options.group,
|
85
85
|
group_level: options.group_level,
|
86
86
|
key: (JSON.generate(options.key) unless options.key.nil?),
|
87
|
-
keys: options.keys
|
87
|
+
keys: (options.keys.map { |key| JSON.generate(key) } if options.keys),
|
88
88
|
order: options.order,
|
89
89
|
reduce: options.reduce,
|
90
90
|
on_error: options.on_error,
|
data/lib/couchbase/cluster.rb
CHANGED
@@ -67,18 +67,18 @@ module Couchbase
|
|
67
67
|
pipeline_cap: options.pipeline_cap,
|
68
68
|
metrics: options.metrics,
|
69
69
|
profile: options.profile,
|
70
|
-
positional_parameters: options.
|
71
|
-
named_parameters: options.
|
72
|
-
raw_parameters: options.
|
73
|
-
scan_consistency: options.
|
74
|
-
mutation_state: options.
|
70
|
+
positional_parameters: options.export_positional_parameters,
|
71
|
+
named_parameters: options.export_named_parameters,
|
72
|
+
raw_parameters: options.raw_parameters,
|
73
|
+
scan_consistency: options.scan_consistency,
|
74
|
+
mutation_state: (options.mutation_state.tokens.map { |t|
|
75
75
|
{
|
76
76
|
bucket_name: t.bucket_name,
|
77
77
|
partition_id: t.partition_id,
|
78
78
|
partition_uuid: t.partition_uuid,
|
79
79
|
sequence_number: t.sequence_number,
|
80
80
|
}
|
81
|
-
},
|
81
|
+
} if options.mutation_state),
|
82
82
|
})
|
83
83
|
|
84
84
|
QueryResult.new do |res|
|
@@ -119,9 +119,9 @@ module Couchbase
|
|
119
119
|
scan_consistency: options.scan_consistency,
|
120
120
|
readonly: options.readonly,
|
121
121
|
priority: options.priority,
|
122
|
-
positional_parameters: options.
|
123
|
-
named_parameters: options.
|
124
|
-
raw_parameters: options.
|
122
|
+
positional_parameters: options.export_positional_parameters,
|
123
|
+
named_parameters: options.export_named_parameters,
|
124
|
+
raw_parameters: options.raw_parameters,
|
125
125
|
})
|
126
126
|
|
127
127
|
AnalyticsResult.new do |res|
|
@@ -165,17 +165,17 @@ module Couchbase
|
|
165
165
|
highlight_style: options.highlight_style,
|
166
166
|
highlight_fields: options.highlight_fields,
|
167
167
|
fields: options.fields,
|
168
|
-
sort: options.sort
|
169
|
-
facets: options.facets
|
170
|
-
scan_consistency: options.
|
171
|
-
mutation_state: options.
|
168
|
+
sort: (options.sort.map { |v| JSON.generate(v) } if options.sort),
|
169
|
+
facets: (options.facets.map { |(k, v)| [k, JSON.generate(v)] } if options.facets),
|
170
|
+
scan_consistency: options.scan_consistency,
|
171
|
+
mutation_state: (options.mutation_state.tokens.map { |t|
|
172
172
|
{
|
173
173
|
bucket_name: t.bucket_name,
|
174
174
|
partition_id: t.partition_id,
|
175
175
|
partition_uuid: t.partition_uuid,
|
176
176
|
sequence_number: t.sequence_number,
|
177
177
|
}
|
178
|
-
},
|
178
|
+
} if options.mutation_state),
|
179
179
|
})
|
180
180
|
|
181
181
|
SearchResult.new do |res|
|
@@ -209,35 +209,52 @@ module Couchbase
|
|
209
209
|
row.explanation = JSON.parse(r[:explanation]) if r[:explanation]
|
210
210
|
end
|
211
211
|
end
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
212
|
+
if resp[:facets]
|
213
|
+
res.facets = resp[:facets].each_with_object({}) do |(k, v), o|
|
214
|
+
facet = case options.facets[k]
|
215
|
+
when SearchFacet::SearchFacetTerm
|
216
|
+
SearchFacetResult::TermFacetResult.new do |f|
|
217
|
+
f.terms =
|
218
|
+
if v[:terms]
|
219
|
+
v[:terms].map do |t|
|
220
|
+
SearchFacetResult::TermFacetResult::TermFacet.new(t[:term], t[:count])
|
221
|
+
end
|
222
|
+
else
|
223
|
+
[]
|
224
|
+
end
|
225
|
+
end
|
226
|
+
when SearchFacet::SearchFacetDateRange
|
227
|
+
SearchFacetResult::DateRangeFacetResult.new do |f|
|
228
|
+
f.date_ranges =
|
229
|
+
if v[:date_ranges]
|
230
|
+
v[:date_ranges].map do |r|
|
231
|
+
SearchFacetResult::DateRangeFacetResult::DateRangeFacet.new(r[:name], r[:count], r[:start_time], r[:end_time])
|
232
|
+
end
|
233
|
+
else
|
234
|
+
[]
|
235
|
+
end
|
236
|
+
end
|
237
|
+
when SearchFacet::SearchFacetNumericRange
|
238
|
+
SearchFacetResult::NumericRangeFacetResult.new do |f|
|
239
|
+
f.numeric_ranges =
|
240
|
+
if v[:numeric_ranges]
|
241
|
+
v[:numeric_ranges].map do |r|
|
242
|
+
SearchFacetResult::NumericRangeFacetResult::NumericRangeFacet.new(r[:name], r[:count], r[:min], r[:max])
|
243
|
+
end
|
244
|
+
else
|
245
|
+
[]
|
246
|
+
end
|
247
|
+
end
|
248
|
+
else
|
249
|
+
next # ignore unknown facet result
|
225
250
|
end
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
next # ignore unknown facet result
|
234
|
-
end
|
235
|
-
facet.name = v[:name]
|
236
|
-
facet.field = v[:field]
|
237
|
-
facet.total = v[:total]
|
238
|
-
facet.missing = v[:missing]
|
239
|
-
facet.other = v[:other]
|
240
|
-
o[k] = facet
|
251
|
+
facet.name = v[:name]
|
252
|
+
facet.field = v[:field]
|
253
|
+
facet.total = v[:total]
|
254
|
+
facet.missing = v[:missing]
|
255
|
+
facet.other = v[:other]
|
256
|
+
o[k] = facet
|
257
|
+
end
|
241
258
|
end
|
242
259
|
end
|
243
260
|
end
|
@@ -302,9 +319,6 @@ module Couchbase
|
|
302
319
|
# @param [String] connection_string connection string used to locate the Couchbase Cluster
|
303
320
|
# @param [ClusterOptions] options custom options when creating the cluster connection
|
304
321
|
def initialize(connection_string, options)
|
305
|
-
conn_info = Backend.parse_connection_string(connection_string)
|
306
|
-
raise ArgumentError, "missing hostname" if conn_info[:nodes].empty?
|
307
|
-
hostname = conn_info[:nodes].first[:address]
|
308
322
|
raise ArgumentError, "options must have authenticator configured" unless options.authenticator
|
309
323
|
username = options.authenticator.username
|
310
324
|
raise ArgumentError, "missing username" unless username
|
@@ -312,7 +326,7 @@ module Couchbase
|
|
312
326
|
raise ArgumentError, "missing password" unless password
|
313
327
|
|
314
328
|
@backend = Backend.new
|
315
|
-
@backend.open(
|
329
|
+
@backend.open(connection_string, username, password, {})
|
316
330
|
end
|
317
331
|
end
|
318
332
|
end
|
data/lib/couchbase/collection.rb
CHANGED
@@ -52,7 +52,7 @@ module Couchbase
|
|
52
52
|
resp = if options.need_projected_get?
|
53
53
|
@backend.document_get_projected(bucket_name, "#{@scope_name}.#{@name}", id,
|
54
54
|
options.timeout,
|
55
|
-
options.
|
55
|
+
options.with_expiry,
|
56
56
|
options.projections,
|
57
57
|
options.preserve_array_indexes)
|
58
58
|
else
|
@@ -63,7 +63,7 @@ module Couchbase
|
|
63
63
|
res.cas = resp[:cas]
|
64
64
|
res.flags = resp[:flags]
|
65
65
|
res.encoded = resp[:content]
|
66
|
-
res.
|
66
|
+
res.expiry = resp[:expiry] if resp.key?(:expiry)
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
@@ -84,15 +84,15 @@ module Couchbase
|
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
87
|
-
# Fetches a full document and resets its expiration time to the
|
87
|
+
# Fetches a full document and resets its expiration time to the duration provided
|
88
88
|
#
|
89
89
|
# @param [String] id the document id which is used to uniquely identify it.
|
90
|
-
# @param [Integer]
|
90
|
+
# @param [Integer] expiry the new expiration time for the document
|
91
91
|
# @param [GetAndTouchOptions] options request customization
|
92
92
|
#
|
93
93
|
# @return [GetResult]
|
94
|
-
def get_and_touch(id,
|
95
|
-
resp = @backend.document_get_and_touch(bucket_name, "#{@scope_name}.#{@name}", id, options.timeout,
|
94
|
+
def get_and_touch(id, expiry, options = GetAndTouchOptions.new)
|
95
|
+
resp = @backend.document_get_and_touch(bucket_name, "#{@scope_name}.#{@name}", id, options.timeout, expiry)
|
96
96
|
GetResult.new do |res|
|
97
97
|
res.transcoder = options.transcoder
|
98
98
|
res.cas = resp[:cas]
|
@@ -159,7 +159,7 @@ module Couchbase
|
|
159
159
|
blob, flags = options.transcoder.encode(content)
|
160
160
|
resp = @backend.document_insert(bucket_name, "#{@scope_name}.#{@name}", id, options.timeout, blob, flags, {
|
161
161
|
durability_level: options.durability_level,
|
162
|
-
|
162
|
+
expiry: options.expiry,
|
163
163
|
})
|
164
164
|
MutationResult.new do |res|
|
165
165
|
res.cas = resp[:cas]
|
@@ -178,7 +178,7 @@ module Couchbase
|
|
178
178
|
blob, flags = options.transcoder.encode(content)
|
179
179
|
resp = @backend.document_upsert(bucket_name, "#{@scope_name}.#{@name}", id, options.timeout, blob, flags, {
|
180
180
|
durability_level: options.durability_level,
|
181
|
-
|
181
|
+
expiry: options.expiry,
|
182
182
|
})
|
183
183
|
MutationResult.new do |res|
|
184
184
|
res.cas = resp[:cas]
|
@@ -197,7 +197,7 @@ module Couchbase
|
|
197
197
|
blob, flags = options.transcoder.encode(content)
|
198
198
|
resp = @backend.document_replace(bucket_name, "#{@scope_name}.#{@name}", id, options.timeout, blob, flags, {
|
199
199
|
durability_level: options.durability_level,
|
200
|
-
|
200
|
+
expiry: options.expiry,
|
201
201
|
cas: options.cas,
|
202
202
|
})
|
203
203
|
MutationResult.new do |res|
|
@@ -209,12 +209,12 @@ module Couchbase
|
|
209
209
|
# Update the expiration of the document with the given id
|
210
210
|
#
|
211
211
|
# @param [String] id the document id which is used to uniquely identify it.
|
212
|
-
# @param [Integer]
|
212
|
+
# @param [Integer] expiry new expiration time for the document
|
213
213
|
# @param [TouchOptions] options request customization
|
214
214
|
#
|
215
215
|
# @return [MutationResult]
|
216
|
-
def touch(id,
|
217
|
-
resp = @backend.document_touch(bucket_name, "#{@scope_name}.#{@name}", id, options.timeout,
|
216
|
+
def touch(id, expiry, options = TouchOptions.new)
|
217
|
+
resp = @backend.document_touch(bucket_name, "#{@scope_name}.#{@name}", id, options.timeout, expiry)
|
218
218
|
MutationResult.new do |res|
|
219
219
|
res.cas = resp[:cas]
|
220
220
|
end
|
@@ -291,7 +291,7 @@ module Couchbase
|
|
291
291
|
store_semantics: options.store_semantics,
|
292
292
|
access_deleted: options.access_deleted,
|
293
293
|
cas: options.cas,
|
294
|
-
|
294
|
+
expiry: options.expiry,
|
295
295
|
}
|
296
296
|
)
|
297
297
|
res = MutateInResult.new do |res|
|
@@ -21,7 +21,7 @@ module Couchbase
|
|
21
21
|
class Collection
|
22
22
|
class GetOptions < CommonOptions
|
23
23
|
# @return [Boolean] if the expiration should also fetched with get
|
24
|
-
attr_accessor :
|
24
|
+
attr_accessor :with_expiry
|
25
25
|
|
26
26
|
# @return [JsonTranscoder] transcoder used for decoding
|
27
27
|
attr_accessor :transcoder
|
@@ -30,7 +30,7 @@ module Couchbase
|
|
30
30
|
def initialize
|
31
31
|
@transcoder = JsonTranscoder.new
|
32
32
|
@preserve_array_indexes = false
|
33
|
-
@
|
33
|
+
@with_expiry = nil
|
34
34
|
@projections = nil
|
35
35
|
yield self if block_given?
|
36
36
|
end
|
@@ -57,7 +57,7 @@ module Couchbase
|
|
57
57
|
# @api private
|
58
58
|
# @return [Boolean]
|
59
59
|
def need_projected_get?
|
60
|
-
@
|
60
|
+
@with_expiry || !@projections.nil?
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
@@ -88,9 +88,10 @@ module Couchbase
|
|
88
88
|
attr_accessor :cas
|
89
89
|
|
90
90
|
# @return [Integer] the expiration if fetched and present
|
91
|
-
attr_accessor :
|
91
|
+
attr_accessor :expiry
|
92
92
|
|
93
93
|
# @return [String] The encoded content when loading the document
|
94
|
+
# @api private
|
94
95
|
attr_accessor :encoded
|
95
96
|
|
96
97
|
# Decodes the content of the document using given (or default transcoder)
|
@@ -108,6 +109,7 @@ module Couchbase
|
|
108
109
|
end
|
109
110
|
|
110
111
|
# @return [Integer] The flags from the operation
|
112
|
+
# @api private
|
111
113
|
attr_accessor :flags
|
112
114
|
|
113
115
|
# @return [JsonTranscoder] The default transcoder which should be used
|
@@ -186,7 +188,7 @@ module Couchbase
|
|
186
188
|
|
187
189
|
class InsertOptions < CommonOptions
|
188
190
|
# @return [Integer] expiration time to associate with the document
|
189
|
-
attr_accessor :
|
191
|
+
attr_accessor :expiry
|
190
192
|
|
191
193
|
# @return [Proc] transcoder used for encoding
|
192
194
|
attr_accessor :transcoder
|
@@ -204,7 +206,7 @@ module Couchbase
|
|
204
206
|
|
205
207
|
class UpsertOptions < CommonOptions
|
206
208
|
# @return [Integer] expiration time to associate with the document
|
207
|
-
attr_accessor :
|
209
|
+
attr_accessor :expiry
|
208
210
|
|
209
211
|
# @return [JsonTranscoder] transcoder used for encoding
|
210
212
|
attr_accessor :transcoder
|
@@ -222,7 +224,7 @@ module Couchbase
|
|
222
224
|
|
223
225
|
class ReplaceOptions < CommonOptions
|
224
226
|
# @return [Integer] expiration time to associate with the document
|
225
|
-
attr_accessor :
|
227
|
+
attr_accessor :expiry
|
226
228
|
|
227
229
|
# @return [JsonTranscoder] transcoder used for encoding
|
228
230
|
attr_accessor :transcoder
|
@@ -301,7 +303,7 @@ module Couchbase
|
|
301
303
|
#
|
302
304
|
# @return [Boolean] true if a value is present at the index, false otherwise
|
303
305
|
def exists?(index)
|
304
|
-
encoded[index]
|
306
|
+
!encoded[index].nil? && encoded[index].exists
|
305
307
|
end
|
306
308
|
|
307
309
|
# @return [Array<SubDocumentField>] holds the encoded subdocument responses
|
@@ -330,7 +332,7 @@ module Couchbase
|
|
330
332
|
|
331
333
|
class MutateInOptions < CommonOptions
|
332
334
|
# @return [Integer] expiration time to associate with the document
|
333
|
-
attr_accessor :
|
335
|
+
attr_accessor :expiry
|
334
336
|
|
335
337
|
# Describes how the outer document store semantics on subdoc should act
|
336
338
|
#
|
@@ -384,18 +386,22 @@ module Couchbase
|
|
384
386
|
yield self if block_given?
|
385
387
|
end
|
386
388
|
|
389
|
+
# @api private
|
387
390
|
def success?
|
388
391
|
first_error_index.nil?
|
389
392
|
end
|
390
393
|
|
394
|
+
# @api private
|
391
395
|
def first_error
|
392
396
|
encoded[first_error_index].error
|
393
397
|
end
|
394
398
|
|
395
399
|
# @return [Array<SubDocumentField>] holds the encoded subdocument responses
|
400
|
+
# @api private
|
396
401
|
attr_accessor :encoded
|
397
402
|
|
398
403
|
# @return [Integer, nil] index of first operation entry that generated an error
|
404
|
+
# @api private
|
399
405
|
attr_accessor :first_error_index
|
400
406
|
|
401
407
|
# @return [JsonTranscoder] The default transcoder which should be used
|
@@ -1,5 +1,3 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
1
|
# Copyright 2020 Couchbase, Inc.
|
4
2
|
#
|
5
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -14,8 +12,7 @@
|
|
14
12
|
# See the License for the specific language governing permissions and
|
15
13
|
# limitations under the License.
|
16
14
|
|
17
|
-
require "
|
18
|
-
require "
|
19
|
-
require "couchbase"
|
20
|
-
|
21
|
-
IRB.start(__FILE__)
|
15
|
+
require "couchbase/datastructures/couchbase_list"
|
16
|
+
require "couchbase/datastructures/couchbase_set"
|
17
|
+
require "couchbase/datastructures/couchbase_queue"
|
18
|
+
require "couchbase/datastructures/couchbase_map"
|
@@ -0,0 +1,171 @@
|
|
1
|
+
# Copyright 2020 Couchbase, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require "couchbase/collection"
|
16
|
+
require "couchbase/errors"
|
17
|
+
|
18
|
+
module Couchbase
|
19
|
+
module Datastructures
|
20
|
+
# A {CouchbaseList} is implements +Enumerable+ interface and backed by {Collection} document (more specifically
|
21
|
+
# a JSON array).
|
22
|
+
#
|
23
|
+
# Note that as such, a {CouchbaseList} is restricted to the types that JSON array can contain.
|
24
|
+
class CouchbaseList
|
25
|
+
include Enumerable
|
26
|
+
|
27
|
+
# Create a new List, backed by the document identified by +id+ in +collection+.
|
28
|
+
#
|
29
|
+
# @param [String] id the id of the document to back the list.
|
30
|
+
# @param [Collection] collection the Couchbase collection through which to interact with the document.
|
31
|
+
# @param [CouchbaseListOptions] options customization of the datastructure
|
32
|
+
def initialize(id, collection, options = CouchbaseListOptions.new)
|
33
|
+
@id = id
|
34
|
+
@collection = collection
|
35
|
+
@options = options
|
36
|
+
@cas = 0
|
37
|
+
end
|
38
|
+
|
39
|
+
# Calls the given block once for each element in the list, passing that element as a parameter.
|
40
|
+
#
|
41
|
+
# @yieldparam [Object] item
|
42
|
+
#
|
43
|
+
# @return [CouchbaseList, Enumerable]
|
44
|
+
def each
|
45
|
+
if block_given?
|
46
|
+
begin
|
47
|
+
result = @collection.get(@id, @options.get_options)
|
48
|
+
current = result.content
|
49
|
+
@cas = result.cas
|
50
|
+
rescue Error::DocumentNotFound
|
51
|
+
current = []
|
52
|
+
@cas = 0
|
53
|
+
end
|
54
|
+
current.each do |entry|
|
55
|
+
yield entry
|
56
|
+
end
|
57
|
+
self
|
58
|
+
else
|
59
|
+
enum_for(:each)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# @return [Integer] returns the number of elements in the list.
|
64
|
+
def length
|
65
|
+
result = @collection.lookup_in(@id, [
|
66
|
+
LookupInSpec.count("")
|
67
|
+
], @options.lookup_in_options)
|
68
|
+
result.content(0)
|
69
|
+
rescue Error::DocumentNotFound
|
70
|
+
0
|
71
|
+
end
|
72
|
+
|
73
|
+
alias_method :size, :length
|
74
|
+
|
75
|
+
# @return [Boolean] returns true if list is empty
|
76
|
+
def empty?
|
77
|
+
size.zero?
|
78
|
+
end
|
79
|
+
|
80
|
+
# Appends the given object(s) on to the end of this error. This expression returns the array itself, so several
|
81
|
+
# appends may be chained together.
|
82
|
+
#
|
83
|
+
# @param [Object...] obj object(s) to append
|
84
|
+
# @return [CouchbaseList]
|
85
|
+
def push(*obj)
|
86
|
+
@collection.mutate_in(@id, [
|
87
|
+
MutateInSpec.array_append("", obj)
|
88
|
+
], @options.mutate_in_options)
|
89
|
+
self
|
90
|
+
end
|
91
|
+
|
92
|
+
alias_method :append, :push
|
93
|
+
|
94
|
+
# Prepends objects to the front of the list, moving other elements upwards
|
95
|
+
#
|
96
|
+
# @param [Object...] obj object(s) to prepend
|
97
|
+
# @return [CouchbaseList]
|
98
|
+
def unshift(*obj)
|
99
|
+
@collection.mutate_in(@id, [
|
100
|
+
MutateInSpec.array_prepend("", obj)
|
101
|
+
], @options.mutate_in_options)
|
102
|
+
self
|
103
|
+
end
|
104
|
+
|
105
|
+
alias_method :prepend, :unshift
|
106
|
+
|
107
|
+
# Inserts the given values before the element with the given +index+.
|
108
|
+
#
|
109
|
+
# @param [Integer] index
|
110
|
+
# @param [Object...] obj object(s) to insert
|
111
|
+
# @return [CouchbaseList]
|
112
|
+
def insert(index, *obj)
|
113
|
+
@collection.mutate_in(@id, [
|
114
|
+
MutateInSpec.array_insert("[#{index.to_i}]", obj)
|
115
|
+
])
|
116
|
+
self
|
117
|
+
end
|
118
|
+
|
119
|
+
# Returns the element at +index+. A negative index counts from the end. Returns +nil+ if the index is out of range.
|
120
|
+
#
|
121
|
+
# @param [Integer] index
|
122
|
+
# @return [Object, nil]
|
123
|
+
def at(index)
|
124
|
+
result = @collection.lookup_in(@id, [
|
125
|
+
LookupInSpec.get("[#{index.to_i}]")
|
126
|
+
], @options.lookup_in_options)
|
127
|
+
result.exists?(0) ? result.content(0) : nil
|
128
|
+
rescue Error::DocumentNotFound
|
129
|
+
nil
|
130
|
+
end
|
131
|
+
|
132
|
+
alias_method :[], :at
|
133
|
+
|
134
|
+
# Deletes the element at the specified +index+, returning that element, or nil
|
135
|
+
#
|
136
|
+
# @param [Integer] index
|
137
|
+
# @return [CouchbaseList]
|
138
|
+
def delete_at(index)
|
139
|
+
@collection.mutate_in(@id, [
|
140
|
+
MutateInSpec.remove("[#{index.to_i}]")
|
141
|
+
])
|
142
|
+
self
|
143
|
+
rescue Error::DocumentNotFound
|
144
|
+
self
|
145
|
+
end
|
146
|
+
|
147
|
+
# Removes all elements from the list
|
148
|
+
def clear
|
149
|
+
@collection.remove(@id, @options.remove_options)
|
150
|
+
nil
|
151
|
+
rescue Error::DocumentNotFound
|
152
|
+
nil
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
class CouchbaseListOptions
|
157
|
+
attr_accessor :get_options
|
158
|
+
attr_accessor :lookup_in_options
|
159
|
+
attr_accessor :mutate_in_options
|
160
|
+
attr_accessor :remove_options
|
161
|
+
|
162
|
+
def initialize
|
163
|
+
@get_options = Collection::GetOptions.new
|
164
|
+
@remove_options = Collection::RemoveOptions.new
|
165
|
+
@lookup_in_options = Collection::LookupInOptions.new
|
166
|
+
@mutate_in_options = Collection::MutateInOptions.new
|
167
|
+
@mutate_in_options.store_semantics = :upsert
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|