couchbase 1.2.0.beta-x86-mingw32 → 1.2.0-x86-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +1 -1
- data/Makefile +3 -0
- data/README.markdown +15 -4
- data/RELEASE_NOTES.markdown +513 -0
- data/couchbase.gemspec +0 -1
- data/ext/couchbase_ext/arguments.c +161 -244
- data/ext/couchbase_ext/arithmetic.c +29 -37
- data/ext/couchbase_ext/bucket.c +252 -219
- data/ext/couchbase_ext/couchbase_ext.c +540 -417
- data/ext/couchbase_ext/couchbase_ext.h +218 -191
- data/ext/couchbase_ext/delete.c +30 -27
- data/ext/couchbase_ext/extconf.rb +15 -3
- data/ext/couchbase_ext/get.c +45 -37
- data/ext/couchbase_ext/http.c +95 -74
- data/ext/couchbase_ext/multithread_plugin.c +1201 -0
- data/ext/couchbase_ext/observe.c +42 -37
- data/ext/couchbase_ext/result.c +17 -20
- data/ext/couchbase_ext/stats.c +30 -28
- data/ext/couchbase_ext/store.c +46 -39
- data/ext/couchbase_ext/timer.c +11 -11
- data/ext/couchbase_ext/touch.c +30 -27
- data/ext/couchbase_ext/unlock.c +30 -27
- data/ext/couchbase_ext/utils.c +166 -89
- data/ext/couchbase_ext/version.c +29 -26
- data/lib/action_dispatch/middleware/session/couchbase_store.rb +2 -2
- data/lib/active_support/cache/couchbase_store.rb +6 -6
- data/lib/couchbase.rb +1 -0
- data/lib/couchbase/bucket.rb +6 -11
- data/lib/couchbase/cluster.rb +105 -0
- data/lib/couchbase/utils.rb +8 -5
- data/lib/couchbase/version.rb +1 -1
- data/lib/couchbase/view.rb +51 -5
- data/lib/couchbase/view_row.rb +1 -1
- data/lib/ext/multi_json_fix.rb +13 -9
- data/lib/rack/session/couchbase.rb +11 -7
- data/tasks/compile.rake +1 -1
- data/tasks/test.rake +40 -34
- data/tasks/util.rake +1 -1
- data/test/setup.rb +9 -2
- data/test/test_arithmetic.rb +37 -0
- data/test/test_async.rb +22 -18
- data/test/test_unlock.rb +0 -1
- data/test/test_utils.rb +32 -0
- metadata +13 -23
- data/HISTORY.markdown +0 -215
data/ext/couchbase_ext/version.c
CHANGED
@@ -18,31 +18,29 @@
|
|
18
18
|
#include "couchbase_ext.h"
|
19
19
|
|
20
20
|
void
|
21
|
-
|
21
|
+
cb_version_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_server_version_resp_t *resp)
|
22
22
|
{
|
23
|
-
struct
|
24
|
-
struct
|
23
|
+
struct cb_context_st *ctx = (struct cb_context_st *)cookie;
|
24
|
+
struct cb_bucket_st *bucket = ctx->bucket;
|
25
25
|
VALUE node, val, *rv = ctx->rv, exc, res;
|
26
26
|
|
27
27
|
node = resp->v.v0.server_endpoint ? STR_NEW_CSTR(resp->v.v0.server_endpoint) : Qnil;
|
28
28
|
exc = cb_check_error(error, "failed to get version", node);
|
29
29
|
if (exc != Qnil) {
|
30
|
-
rb_ivar_set(exc,
|
31
|
-
|
32
|
-
ctx->exception = cb_gc_protect(bucket, exc);
|
33
|
-
}
|
30
|
+
rb_ivar_set(exc, cb_id_iv_operation, cb_sym_version);
|
31
|
+
ctx->exception = cb_gc_protect(bucket, exc);
|
34
32
|
}
|
35
33
|
|
36
34
|
if (node != Qnil) {
|
37
35
|
val = STR_NEW((const char*)resp->v.v0.vstring, resp->v.v0.nvstring);
|
38
36
|
if (bucket->async) { /* asynchronous */
|
39
37
|
if (ctx->proc != Qnil) {
|
40
|
-
res = rb_class_new_instance(0, NULL,
|
41
|
-
rb_ivar_set(res,
|
42
|
-
rb_ivar_set(res,
|
43
|
-
rb_ivar_set(res,
|
44
|
-
rb_ivar_set(res,
|
45
|
-
cb_proc_call(ctx->proc, 1, res);
|
38
|
+
res = rb_class_new_instance(0, NULL, cb_cResult);
|
39
|
+
rb_ivar_set(res, cb_id_iv_error, exc);
|
40
|
+
rb_ivar_set(res, cb_id_iv_operation, cb_sym_version);
|
41
|
+
rb_ivar_set(res, cb_id_iv_node, node);
|
42
|
+
rb_ivar_set(res, cb_id_iv_value, val);
|
43
|
+
cb_proc_call(bucket, ctx->proc, 1, res);
|
46
44
|
}
|
47
45
|
} else { /* synchronous */
|
48
46
|
if (NIL_P(exc)) {
|
@@ -52,6 +50,9 @@ version_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_
|
|
52
50
|
} else {
|
53
51
|
ctx->nqueries--;
|
54
52
|
cb_gc_unprotect(bucket, ctx->proc);
|
53
|
+
if (bucket->async) {
|
54
|
+
free(ctx);
|
55
|
+
}
|
55
56
|
}
|
56
57
|
|
57
58
|
(void)handle;
|
@@ -87,26 +88,26 @@ version_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_
|
|
87
88
|
VALUE
|
88
89
|
cb_bucket_version(int argc, VALUE *argv, VALUE self)
|
89
90
|
{
|
90
|
-
struct
|
91
|
-
struct
|
91
|
+
struct cb_bucket_st *bucket = DATA_PTR(self);
|
92
|
+
struct cb_context_st *ctx;
|
92
93
|
VALUE rv, exc, args, proc;
|
93
94
|
lcb_error_t err;
|
94
|
-
struct
|
95
|
+
struct cb_params_st params;
|
95
96
|
|
96
97
|
if (bucket->handle == NULL) {
|
97
|
-
rb_raise(
|
98
|
+
rb_raise(cb_eConnectError, "closed connection");
|
98
99
|
}
|
99
100
|
rb_scan_args(argc, argv, "0*&", &args, &proc);
|
100
101
|
if (!bucket->async && proc != Qnil) {
|
101
102
|
rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
|
102
103
|
}
|
103
|
-
memset(¶ms, 0, sizeof(struct
|
104
|
-
params.type =
|
104
|
+
memset(¶ms, 0, sizeof(struct cb_params_st));
|
105
|
+
params.type = cb_cmd_version;
|
105
106
|
params.bucket = bucket;
|
106
107
|
cb_params_build(¶ms, RARRAY_LEN(args), args);
|
107
|
-
ctx =
|
108
|
+
ctx = calloc(1, sizeof(struct cb_context_st));
|
108
109
|
if (ctx == NULL) {
|
109
|
-
rb_raise(
|
110
|
+
rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for context");
|
110
111
|
}
|
111
112
|
rv = rb_hash_new();
|
112
113
|
ctx->rv = &rv;
|
@@ -119,12 +120,12 @@ cb_bucket_version(int argc, VALUE *argv, VALUE self)
|
|
119
120
|
exc = cb_check_error(err, "failed to schedule version request", Qnil);
|
120
121
|
cb_params_destroy(¶ms);
|
121
122
|
if (exc != Qnil) {
|
122
|
-
|
123
|
+
free(ctx);
|
123
124
|
rb_exc_raise(exc);
|
124
125
|
}
|
125
126
|
bucket->nbytes += params.npayload;
|
126
127
|
if (bucket->async) {
|
127
|
-
|
128
|
+
cb_maybe_do_loop(bucket);
|
128
129
|
return Qnil;
|
129
130
|
} else {
|
130
131
|
if (ctx->nqueries > 0) {
|
@@ -132,13 +133,15 @@ cb_bucket_version(int argc, VALUE *argv, VALUE self)
|
|
132
133
|
lcb_wait(bucket->handle);
|
133
134
|
}
|
134
135
|
exc = ctx->exception;
|
135
|
-
|
136
|
+
free(ctx);
|
136
137
|
if (exc != Qnil) {
|
137
138
|
cb_gc_unprotect(bucket, exc);
|
138
139
|
rb_exc_raise(exc);
|
139
140
|
}
|
140
|
-
|
141
|
-
|
141
|
+
exc = bucket->exception;
|
142
|
+
if (exc != Qnil) {
|
143
|
+
bucket->exception = Qnil;
|
144
|
+
rb_exc_raise(exc);
|
142
145
|
}
|
143
146
|
return rv;
|
144
147
|
}
|
@@ -16,7 +16,7 @@ module ActionDispatch
|
|
16
16
|
# Or remove this file and add following line to your `config/application.rb`:
|
17
17
|
#
|
18
18
|
# require 'action_dispatch/middleware/session/couchbase_store'
|
19
|
-
# config.
|
19
|
+
# config.session_store :couchbase_store
|
20
20
|
#
|
21
21
|
# You can also pass additional options:
|
22
22
|
#
|
@@ -25,7 +25,7 @@ module ActionDispatch
|
|
25
25
|
# :expire_after => 5.minutes,
|
26
26
|
# :couchbase => {:bucket => "sessions", :default_format => :marshal}
|
27
27
|
# }
|
28
|
-
# config.
|
28
|
+
# config.session_store :couchbase_store, session_options
|
29
29
|
#
|
30
30
|
# By default sessions will be serialized to JSON, to allow analyse them
|
31
31
|
# using Map/Reduce.
|
@@ -184,7 +184,7 @@ module ActiveSupport
|
|
184
184
|
instrument(:read_multi, names, options) do
|
185
185
|
@data.get(names, options)
|
186
186
|
end
|
187
|
-
rescue Couchbase::Error::Base => e
|
187
|
+
rescue ::Couchbase::Error::Base => e
|
188
188
|
logger.error("#{e.class}: #{e.message}") if logger
|
189
189
|
raise if @raise_errors
|
190
190
|
false
|
@@ -245,7 +245,7 @@ module ActiveSupport
|
|
245
245
|
payload[:amount] = amount if payload
|
246
246
|
@data.incr(name, amount, options)
|
247
247
|
end
|
248
|
-
rescue Couchbase::Error::Base => e
|
248
|
+
rescue ::Couchbase::Error::Base => e
|
249
249
|
logger.error("#{e.class}: #{e.message}") if logger
|
250
250
|
raise if @raise_errors
|
251
251
|
false
|
@@ -277,7 +277,7 @@ module ActiveSupport
|
|
277
277
|
payload[:amount] = amount if payload
|
278
278
|
@data.decr(name, amount, options)
|
279
279
|
end
|
280
|
-
rescue Couchbase::Error::Base => e
|
280
|
+
rescue ::Couchbase::Error::Base => e
|
281
281
|
logger.error("#{e.class}: #{e.message}") if logger
|
282
282
|
raise if @raise_errors
|
283
283
|
false
|
@@ -297,7 +297,7 @@ module ActiveSupport
|
|
297
297
|
# Read an entry from the cache.
|
298
298
|
def read_entry(key, options) # :nodoc:
|
299
299
|
@data.get(key, options)
|
300
|
-
rescue Couchbase::Error::Base => e
|
300
|
+
rescue ::Couchbase::Error::Base => e
|
301
301
|
logger.error("#{e.class}: #{e.message}") if logger
|
302
302
|
raise if @raise_errors
|
303
303
|
nil
|
@@ -314,7 +314,7 @@ module ActiveSupport
|
|
314
314
|
options[:ttl] ||= ttl
|
315
315
|
end
|
316
316
|
@data.send(method, key, value, options)
|
317
|
-
rescue Couchbase::Error::Base => e
|
317
|
+
rescue ::Couchbase::Error::Base => e
|
318
318
|
logger.error("#{e.class}: #{e.message}") if logger
|
319
319
|
raise if @raise_errors
|
320
320
|
false
|
@@ -323,7 +323,7 @@ module ActiveSupport
|
|
323
323
|
# Delete an entry from the cache.
|
324
324
|
def delete_entry(key, options) # :nodoc:
|
325
325
|
@data.delete(key, options)
|
326
|
-
rescue Couchbase::Error::Base => e
|
326
|
+
rescue ::Couchbase::Error::Base => e
|
327
327
|
logger.error("#{e.class}: #{e.message}") if logger
|
328
328
|
raise if @raise_errors
|
329
329
|
false
|
data/lib/couchbase.rb
CHANGED
data/lib/couchbase/bucket.rb
CHANGED
@@ -106,6 +106,9 @@ module Couchbase
|
|
106
106
|
req.on_body do |body|
|
107
107
|
res = MultiJson.load(body.value)
|
108
108
|
res["rows"].each do |obj|
|
109
|
+
if obj['doc']
|
110
|
+
obj['doc']['value'] = obj['doc'].delete('json')
|
111
|
+
end
|
109
112
|
doc = ViewRow.wrap(self, obj)
|
110
113
|
key = doc.id.sub(/^_design\//, '')
|
111
114
|
next if self.environment == :production && key =~ /dev_/
|
@@ -117,17 +120,6 @@ module Couchbase
|
|
117
120
|
async? ? nil : docmap
|
118
121
|
end
|
119
122
|
|
120
|
-
# Fetch all documents from the bucket.
|
121
|
-
#
|
122
|
-
# @since 1.2.0
|
123
|
-
#
|
124
|
-
# @param [Hash] params Params for Couchbase +/_all_docs+ query
|
125
|
-
#
|
126
|
-
# @return [Couchbase::View] View object
|
127
|
-
def all_docs(params = {})
|
128
|
-
View.new(self, "_all_docs", params)
|
129
|
-
end
|
130
|
-
|
131
123
|
# Update or create design doc with supplied views
|
132
124
|
#
|
133
125
|
# @since 1.2.0
|
@@ -238,6 +230,9 @@ module Couchbase
|
|
238
230
|
# end
|
239
231
|
# end
|
240
232
|
def flush
|
233
|
+
if !async? && block_given?
|
234
|
+
raise ArgumentError, "synchronous mode doesn't support callbacks"
|
235
|
+
end
|
241
236
|
req = make_http_request("/pools/default/buckets/#{bucket}/controller/doFlush",
|
242
237
|
:type => :management, :method => :post, :extended => true)
|
243
238
|
res = nil
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# Author:: Couchbase <info@couchbase.com>
|
2
|
+
# Copyright:: 2011, 2012 Couchbase, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# 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,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
module Couchbase
|
19
|
+
|
20
|
+
class Cluster
|
21
|
+
|
22
|
+
# Establish connection to the cluster for administration
|
23
|
+
#
|
24
|
+
# @param [Hash] options The connection parameter
|
25
|
+
# @option options [String] :username The username
|
26
|
+
# @option options [String] :password The password
|
27
|
+
# @option options [String] :pool ("default") The pool name
|
28
|
+
# @option options [String] :hostname ("localhost") The hostname
|
29
|
+
# @option options [String] :port (8091) The port
|
30
|
+
def initialize(options = {})
|
31
|
+
if options[:username].nil? || options[:password].nil?
|
32
|
+
raise ArgumentError, "username and password mandatory to connect to the cluster"
|
33
|
+
end
|
34
|
+
@connection = Bucket.new(options.merge(:type => :cluster))
|
35
|
+
end
|
36
|
+
|
37
|
+
# Create data bucket
|
38
|
+
#
|
39
|
+
# @param [String] name The name of the bucket
|
40
|
+
# @param [Hash] options The bucket parameters
|
41
|
+
# @option options [String] :bucket_type ("couchbase") The type of the
|
42
|
+
# bucket. Possible values are "memcached" and "couchbase".
|
43
|
+
# @option options [Fixnum] :ram_quota (100) The RAM quota in megabytes.
|
44
|
+
# @option options [Fixnum] :replica_number (1) The number of replicas of
|
45
|
+
# each document
|
46
|
+
# @option options [String] :auth_type ("sasl") The authentication type.
|
47
|
+
# Possible values are "sasl" and "none". Note you should specify free
|
48
|
+
# port for "none"
|
49
|
+
# @option options [Fixnum] :proxy_port The port for moxi
|
50
|
+
def create_bucket(name, options = {})
|
51
|
+
defaults = {
|
52
|
+
:type => "couchbase",
|
53
|
+
:ram_quota => 100,
|
54
|
+
:replica_number => 1,
|
55
|
+
:auth_type => "sasl",
|
56
|
+
:sasl_password => "",
|
57
|
+
:proxy_port => nil
|
58
|
+
}
|
59
|
+
options = defaults.merge(options)
|
60
|
+
params = {"name" => name}
|
61
|
+
params["bucketType"] = options[:type]
|
62
|
+
params["ramQuotaMB"] = options[:ram_quota]
|
63
|
+
params["replicaNumber"] = options[:replica_number]
|
64
|
+
params["authType"] = options[:auth_type]
|
65
|
+
params["saslPassword"] = options[:sasl_password]
|
66
|
+
params["proxyPort"] = options[:proxy_port]
|
67
|
+
payload = Utils.encode_params(params.reject!{|k, v| v.nil?})
|
68
|
+
request = @connection.make_http_request("/pools/default/buckets",
|
69
|
+
:content_type => "application/x-www-form-urlencoded",
|
70
|
+
:type => :management,
|
71
|
+
:method => :post,
|
72
|
+
:extended => true,
|
73
|
+
:body => payload)
|
74
|
+
response = nil
|
75
|
+
request.on_body do |r|
|
76
|
+
response = r
|
77
|
+
response.instance_variable_set("@operation", :create_bucket)
|
78
|
+
yield(response) if block_given?
|
79
|
+
end
|
80
|
+
request.continue
|
81
|
+
response
|
82
|
+
end
|
83
|
+
|
84
|
+
# Delete the data bucket
|
85
|
+
#
|
86
|
+
# @param [String] name The name of the bucket
|
87
|
+
# @param [Hash] options
|
88
|
+
def delete_bucket(name, options = {})
|
89
|
+
request = @connection.make_http_request("/pools/default/buckets/#{name}",
|
90
|
+
:type => :management,
|
91
|
+
:method => :delete,
|
92
|
+
:extended => true)
|
93
|
+
response = nil
|
94
|
+
request.on_body do |r|
|
95
|
+
response = r
|
96
|
+
response.instance_variable_set("@operation", :delete_bucket)
|
97
|
+
yield(response) if block_given?
|
98
|
+
end
|
99
|
+
request.continue
|
100
|
+
response
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
data/lib/couchbase/utils.rb
CHANGED
@@ -19,11 +19,8 @@ module Couchbase
|
|
19
19
|
|
20
20
|
class Utils
|
21
21
|
|
22
|
-
def self.
|
23
|
-
|
24
|
-
return uri if params.nil? || params.empty?
|
25
|
-
uri << "?"
|
26
|
-
uri << params.map do |k, v|
|
22
|
+
def self.encode_params(params)
|
23
|
+
params.map do |k, v|
|
27
24
|
next if !v && k.to_s == "group"
|
28
25
|
if %w{key keys startkey endkey start_key end_key}.include?(k.to_s)
|
29
26
|
v = MultiJson.dump(v)
|
@@ -36,6 +33,12 @@ module Couchbase
|
|
36
33
|
end.compact.join("&")
|
37
34
|
end
|
38
35
|
|
36
|
+
def self.build_query(uri, params = nil)
|
37
|
+
uri = uri.dup
|
38
|
+
return uri if params.nil? || params.empty?
|
39
|
+
uri << "?" << encode_params(params)
|
40
|
+
end
|
41
|
+
|
39
42
|
def self.escape(s)
|
40
43
|
s.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/nu) {
|
41
44
|
'%'+$1.unpack('H2'*bytesize($1)).join('%').upcase
|
data/lib/couchbase/version.rb
CHANGED
data/lib/couchbase/view.rb
CHANGED
@@ -15,6 +15,8 @@
|
|
15
15
|
# limitations under the License.
|
16
16
|
#
|
17
17
|
|
18
|
+
require 'base64'
|
19
|
+
|
18
20
|
module Couchbase
|
19
21
|
|
20
22
|
module Error
|
@@ -27,6 +29,28 @@ module Couchbase
|
|
27
29
|
super("#{prefix}#{from}: #{reason}")
|
28
30
|
end
|
29
31
|
end
|
32
|
+
|
33
|
+
class HTTP < Base
|
34
|
+
attr_reader :type, :reason
|
35
|
+
|
36
|
+
def parse_body!
|
37
|
+
if @body
|
38
|
+
hash = MultiJson.load(@body)
|
39
|
+
@type = hash["error"]
|
40
|
+
@reason = hash["reason"]
|
41
|
+
end
|
42
|
+
rescue MultiJson::DecodeError
|
43
|
+
@type = @reason = nil
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_s
|
47
|
+
str = super
|
48
|
+
if @type || @reason
|
49
|
+
str.sub(/ \(/, ": #{[@type, @reason].compact.join(": ")} (")
|
50
|
+
end
|
51
|
+
str
|
52
|
+
end
|
53
|
+
end
|
30
54
|
end
|
31
55
|
|
32
56
|
# This class implements Couchbase View execution
|
@@ -50,7 +74,7 @@ module Couchbase
|
|
50
74
|
def initialize(bucket, endpoint, params = {})
|
51
75
|
@bucket = bucket
|
52
76
|
@endpoint = endpoint
|
53
|
-
@params = params
|
77
|
+
@params = {:connection_timeout => 75_000}.merge(params)
|
54
78
|
@wrapper_class = params.delete(:wrapper_class) || ViewRow
|
55
79
|
unless @wrapper_class.respond_to?(:wrap)
|
56
80
|
raise ArgumentError, "wrapper class should reposond to :wrap, check the options"
|
@@ -142,8 +166,14 @@ module Couchbase
|
|
142
166
|
# the document and store them in {ViewRow#meta} hash.
|
143
167
|
#
|
144
168
|
# @param [Hash] params parameters for Couchbase query.
|
145
|
-
# @option params [true, false] :include_docs (false) Include the
|
146
|
-
# content of the documents in the return.
|
169
|
+
# @option params [true, false] :include_docs (false) Include the
|
170
|
+
# full content of the documents in the return. Note that the document
|
171
|
+
# is fetched from the in memory cache where it may have been changed
|
172
|
+
# or even deleted. See also +:quiet+ parameter below to control error
|
173
|
+
# reporting during fetch.
|
174
|
+
# @option params [true, false] :quiet (true) Do not raise error if
|
175
|
+
# associated document not found in the memory. If the parameter +true+
|
176
|
+
# will use +nil+ value instead.
|
147
177
|
# @option params [true, false] :descending (false) Return the documents
|
148
178
|
# in descending by key order
|
149
179
|
# @option params [String, Fixnum, Hash, Array] :key Return only
|
@@ -175,7 +205,7 @@ module Couchbase
|
|
175
205
|
# response stream.
|
176
206
|
# :stop:: Stop immediately when an error condition occurs. No
|
177
207
|
# further view information will be returned.
|
178
|
-
# @option params [Fixnum] :connection_timeout (
|
208
|
+
# @option params [Fixnum] :connection_timeout (75000) Timeout before the
|
179
209
|
# view request is dropped (milliseconds)
|
180
210
|
# @option params [true, false] :reduce (true) Use the reduction function
|
181
211
|
# @option params [true, false] :group (false) Group the results using
|
@@ -236,6 +266,11 @@ module Couchbase
|
|
236
266
|
body = MultiJson.dump(body) unless body.is_a?(String)
|
237
267
|
options.update(:body => body, :method => params.delete(:method) || :post)
|
238
268
|
end
|
269
|
+
include_docs = params.delete(:include_docs)
|
270
|
+
quiet = true
|
271
|
+
if params.has_key?(:quiet)
|
272
|
+
quiet = params.delete(:quiet)
|
273
|
+
end
|
239
274
|
path = Utils.build_query(@endpoint, params)
|
240
275
|
request = @bucket.make_http_request(path, options)
|
241
276
|
res = []
|
@@ -260,6 +295,17 @@ module Couchbase
|
|
260
295
|
raise Error::View.new(from, reason)
|
261
296
|
end
|
262
297
|
else
|
298
|
+
if include_docs
|
299
|
+
val, flags, cas = @bucket.get(obj['id'], :extended => true, :quiet => quiet)
|
300
|
+
obj['doc'] = {
|
301
|
+
'value' => val,
|
302
|
+
'meta' => {
|
303
|
+
'id' => obj['id'],
|
304
|
+
'flags' => flags,
|
305
|
+
'cas' => cas
|
306
|
+
}
|
307
|
+
}
|
308
|
+
end
|
263
309
|
if block_given?
|
264
310
|
yield @wrapper_class.wrap(@bucket, obj)
|
265
311
|
else
|
@@ -270,7 +316,7 @@ module Couchbase
|
|
270
316
|
# run event loop until the terminating chunk will be found
|
271
317
|
# last_res variable keeps latest known chunk of the result
|
272
318
|
last_res = nil
|
273
|
-
|
319
|
+
while true
|
274
320
|
# feed response received chunks to the parser
|
275
321
|
while r = res.shift
|
276
322
|
if r.error
|