Merge lp:~zorba-coders/zorba/couchbase-module-new-options into lp:zorba/couchbase-module
- couchbase-module-new-options
- Merge into couchbase-module
Status: | Merged |
---|---|
Approved by: | Sorin Marian Nasoi |
Approved revision: | 37 |
Merged at revision: | 35 |
Proposed branch: | lp:~zorba-coders/zorba/couchbase-module-new-options |
Merge into: | lp:zorba/couchbase-module |
Diff against target: |
489 lines (+271/-22) 5 files modified
examples/example.xq (+1/-1) src/couchbase.xq (+41/-3) src/couchbase.xq.src/couchbase.cpp (+170/-8) src/couchbase.xq.src/couchbase.h (+49/-4) test/Queries/couchbase_module/view.xq (+10/-6) |
To merge this branch: | bzr merge lp:~zorba-coders/zorba/couchbase-module-new-options |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Sorin Marian Nasoi | Approve | ||
Chris Hillery | Approve | ||
Review via email: mp+143187@code.launchpad.net |
Commit message
*Added new options to the cb:view Function:
-"limit" option, allows the user to limit the numbers of results shown by the view
-"stale" option, allows the user to specify when to update the view: update after the view is returned(default by couchbase), update before the view is returned, and don't update if the view function is called.
*Added a new option to the cb:put-text and cb:put-binary Functions:
-"wait" option, allows the user to wait for confirmation from couchbase that the key/value pair was stored in disk.
Modified test view.xq using the new options so it doesn't fail when ran for the first time.
Description of the change
Zorba Build Bot (zorba-buildbot) wrote : | # |
Validation queue starting for merge proposal.
Log at: http://
Zorba Build Bot (zorba-buildbot) wrote : | # |
Validation queue job couchbase-
All tests succeeded!
Zorba Build Bot (zorba-buildbot) wrote : | # |
Voting does not meet specified criteria. Required: Approve > 1, Disapprove < 1, Needs Fixing < 1, Pending < 1. Got: 1 Needs Fixing, 1 Pending.
Juan Zacarias (juan457) wrote : | # |
It didn't fail because the created views remain on the database. They are not deleted since they shouldn't be cleaned with the module, but the views are database management work. I will add a delete view just like the create view which are management functions.
- 37. By Juan Zacarias
-
Added a delete view function added it to view.xq test
Juan Zacarias (juan457) wrote : | # |
Fixed
Chris Hillery (ceejatec) : | # |
Sorin Marian Nasoi (sorin.marian.nasoi) : | # |
Zorba Build Bot (zorba-buildbot) wrote : | # |
Validation queue starting for merge proposal.
Log at: http://
Zorba Build Bot (zorba-buildbot) wrote : | # |
Validation queue job couchbase-
All tests succeeded!
Preview Diff
1 | === modified file 'examples/example.xq' |
2 | --- examples/example.xq 2013-01-10 07:59:35 +0000 |
3 | +++ examples/example.xq 2013-01-17 22:52:18 +0000 |
4 | @@ -7,7 +7,7 @@ |
5 | "password" : null, |
6 | "bucket" : "default"}); |
7 | variable $view-name := cb:create-view($instance, "zip", "zip", {"key" : "doc.state", "values" : "doc.pop"}); |
8 | -variable $data := cb:view($instance, $view-name); |
9 | +variable $data := cb:view($instance, $view-name, {"stale" : "false"}); |
10 | for $d in jn:members($data("rows")) |
11 | let $state := $d("key") |
12 | group by $state |
13 | |
14 | === modified file 'src/couchbase.xq' |
15 | --- src/couchbase.xq 2013-01-10 08:07:25 +0000 |
16 | +++ src/couchbase.xq 2013-01-17 22:52:18 +0000 |
17 | @@ -232,7 +232,10 @@ |
18 | : @option "operation" type of operation, possible values are |
19 | : "add", "replace", "set", "append" and "prepend". |
20 | : @option "encoding" the encoding that should be used for the |
21 | - : value (default is UTF-8). |
22 | + : value (default is UTF-8). |
23 | + : @option "wait" variable for setting if a wait for persistancy in |
24 | + : the storing key is needed, possible values are "persist" |
25 | + : and "false". |
26 | : |
27 | : @error cb:LCB0002 if any error occurs in the communication with |
28 | : the server. |
29 | @@ -241,6 +244,7 @@ |
30 | : @error cb:CB0006 if the given encoding is not supported. |
31 | : @error cb:CB0007 if any of the options is not supported. |
32 | : @error cb:CB0009 if the given expiration time is not an xs:integer. |
33 | + : @error cb:CB0011 if the stored Variable was not stored |
34 | : |
35 | : @return a empty sequence. |
36 | :) |
37 | @@ -286,6 +290,9 @@ |
38 | : expiration time in seconds. |
39 | : @option "operation" type of operation, possible values are |
40 | : "add", "replace", "set", "append" and "prepend". |
41 | + : @option "wait" variable for setting if a wait for persistancy in |
42 | + : the storing key is needed, possible values are "persist" |
43 | + : and "false". |
44 | : |
45 | : @error cb:LCB0002 if any error occurs in the communication with |
46 | : the server. |
47 | @@ -293,6 +300,7 @@ |
48 | : of values. |
49 | : @error cb:CB0007 if any of the options is not supported. |
50 | : @error cb:CB0009 if the given expiration time is not an xs:integer. |
51 | + : @error cb:CB0011 if the stored Variable was not stored |
52 | : |
53 | : @return a empty sequence. |
54 | :) |
55 | @@ -365,8 +373,18 @@ |
56 | : (e.g. "_design/test/_view/vies"). |
57 | : @param $options JSONiq object with additional options |
58 | : |
59 | - : @option "encoding" string with the name of the encoding of the returned |
60 | - : strings (if not UTF-8). |
61 | + : @option Json object whith options for the querying the view. available options: |
62 | + : "encoding" string with the name of the encoding of the returned |
63 | + : strings (if not UTF-8). |
64 | + : "stale" option's value is a string with the type of stale to be used. |
65 | + : Valid values: |
66 | + : "ok" : the view is not updated |
67 | + : "false" : the view is updated before the function view is executed, |
68 | + : this options needs the key to be on disk before the call of the |
69 | + : view function. |
70 | + : "update_after" : the view is updated after the call of view |
71 | + : "limit" option's value is an integer which sets a number of how many |
72 | + : rows the view will show. |
73 | : |
74 | : @error cb:LCB0002 if any error occurs in the communication with |
75 | : the server. |
76 | @@ -451,3 +469,23 @@ |
77 | $view-names as xs:string*, |
78 | $options as object()*) |
79 | as xs:string* external; |
80 | + |
81 | + |
82 | +(:~ |
83 | + : Delete a document/view. |
84 | + |
85 | + : If the document doesn't exists, function does nothing. All the views hold in the |
86 | + : Document are deleted, this function can't delete single views. |
87 | + : |
88 | + : @param $db connection reference |
89 | + : @param $doc-name name of the document to create. |
90 | + : |
91 | + : @error cb:LCB0002 if any error occurs in the communication with |
92 | + : the server. |
93 | + : |
94 | + : @return empty sequence. |
95 | + :) |
96 | +declare %an:sequential function cb:delete-view( |
97 | + $db as xs:anyURI, |
98 | + $doc as xs:string*) |
99 | +as xs:string* external; |
100 | |
101 | === modified file 'src/couchbase.xq.src/couchbase.cpp' |
102 | --- src/couchbase.xq.src/couchbase.cpp 2013-01-10 07:59:35 +0000 |
103 | +++ src/couchbase.xq.src/couchbase.cpp 2013-01-17 22:52:18 +0000 |
104 | @@ -89,6 +89,10 @@ |
105 | { |
106 | lFunc = new CreateViewFunction(this); |
107 | } |
108 | + else if (localname == "delete-view") |
109 | + { |
110 | + lFunc = new DeleteViewFunction(this); |
111 | + } |
112 | } |
113 | |
114 | return lFunc; |
115 | @@ -190,6 +194,30 @@ |
116 | return NULL; |
117 | } |
118 | |
119 | +String |
120 | + CouchbaseFunction::ViewOptions::getPathOptions() |
121 | +{ |
122 | + String lPathOptions("?"); |
123 | + bool lAmp = false; |
124 | + if (theStaleOption != "") |
125 | + { |
126 | + lPathOptions.append(theStaleOption); |
127 | + lAmp = true; |
128 | + } |
129 | + if (theLimitOption != "") |
130 | + { |
131 | + if(lAmp) |
132 | + lPathOptions.append("&"); |
133 | + lPathOptions.append(theLimitOption); |
134 | + lAmp = true; |
135 | + } |
136 | + |
137 | + if (lPathOptions == "?") |
138 | + lPathOptions = ""; |
139 | + |
140 | + return lPathOptions; |
141 | +} |
142 | + |
143 | void |
144 | CouchbaseFunction::ViewOptions::setOptions(Item& aOptions) |
145 | { |
146 | @@ -216,6 +244,42 @@ |
147 | throwError("CB0006", lMsg.str().c_str()); |
148 | } |
149 | } |
150 | + else if (lStrKey == "stale") |
151 | + { |
152 | + Item lValue = aOptions.getObjectValue(lStrKey); |
153 | + String lString = lValue.getStringValue(); |
154 | + if (lString == "false") |
155 | + { |
156 | + theStaleOption ="stale=false"; |
157 | + } |
158 | + else if (lString == "ok") |
159 | + { |
160 | + theStaleOption ="stale=ok"; |
161 | + } |
162 | + else if (lString == "update_after") |
163 | + { |
164 | + theStaleOption ="stale=update_after"; |
165 | + } |
166 | + else |
167 | + { |
168 | + std::ostringstream lMsg; |
169 | + lMsg << lStrKey << "=" << lString << ": option not supported"; |
170 | + throwError("CB0007", lMsg.str().c_str()); |
171 | + } |
172 | + } |
173 | + else if (lStrKey == "limit") |
174 | + { |
175 | + Item lValue = aOptions.getObjectValue(lStrKey); |
176 | + try |
177 | + { |
178 | + int lLimit = lValue.getIntValue(); |
179 | + theLimitOption = "limit=" + lLimit; |
180 | + } |
181 | + catch (ZorbaException& e) |
182 | + { |
183 | + throwError("CB0009", " limit option must be an integer value"); |
184 | + } |
185 | + } |
186 | else |
187 | { |
188 | std::ostringstream lMsg; |
189 | @@ -371,6 +435,28 @@ |
190 | throwError("CB0006", lMsg.str().c_str()); |
191 | } |
192 | } |
193 | + else if (lStrKey == "wait") |
194 | + { |
195 | + Item lValue = aOptions.getObjectValue(lStrKey); |
196 | + String lStrValue = lValue.getStringValue(); |
197 | + std::transform( |
198 | + lStrValue.begin(), lStrValue.end(), |
199 | + lStrValue.begin(), tolower); |
200 | + if (lStrValue == "persist") |
201 | + { |
202 | + theWaitType = CB_WAIT_PERSIST; |
203 | + } |
204 | + else if (lStrValue == "false") |
205 | + { |
206 | + theWaitType = CB_WAIT_FALSE; |
207 | + } |
208 | + else |
209 | + { |
210 | + std::ostringstream lMsg; |
211 | + lMsg << lStrKey << "=" << lStrValue << " : option not supported"; |
212 | + throwError("CB0007", lMsg.str().c_str()); |
213 | + } |
214 | + } |
215 | else |
216 | { |
217 | std::ostringstream lMsg; |
218 | @@ -731,6 +817,26 @@ |
219 | /******************************************************************************* |
220 | ******************************************************************************/ |
221 | |
222 | +void CouchbaseFunction::observe_callback(lcb_t instance, const void *cookie, lcb_error_t error, const lcb_observe_resp_t *resp) |
223 | +{ |
224 | + if (error != LCB_SUCCESS) |
225 | + { |
226 | + libCouchbaseError (instance, error); |
227 | + } |
228 | + |
229 | + PutOptions* lWait = (PutOptions*) cookie; |
230 | + //verify is coming from the master |
231 | + if (resp->v.v0.from_master > 0) |
232 | + { |
233 | + lcb_observe_t lStatus = resp->v.v0.status;if (lStatus == LCB_OBSERVE_NOT_FOUND) |
234 | + { |
235 | + throwError("CB0011", "Variable stored not found."); |
236 | + } |
237 | + //check for flag of persisntancy |
238 | + lWait->setWaiting(lStatus & LCB_OBSERVE_PERSISTED?false:true); |
239 | + } |
240 | +} |
241 | + |
242 | void CouchbaseFunction::put (lcb_t aInstance, Iterator_t aKeys, Iterator_t aValues, PutOptions aOptions) |
243 | { |
244 | lcb_error_t lError; |
245 | @@ -800,9 +906,23 @@ |
246 | { |
247 | libCouchbaseError (aInstance, lError); |
248 | } |
249 | - |
250 | - |
251 | + //Wait for store |
252 | lcb_wait(aInstance); |
253 | + //Check if wait for disk |
254 | + if (aOptions.getWaitType() != CB_WAIT_FALSE) |
255 | + { |
256 | + lcb_set_observe_callback(aInstance, observe_callback); |
257 | + PutOptions* lOptions = &aOptions; |
258 | + do { |
259 | + lcb_observe_cmd_t lObserve; |
260 | + lObserve.version = 0; |
261 | + lObserve.v.v0.key = lStrKey.c_str(); |
262 | + lObserve.v.v0.nkey = lStrKey.size(); |
263 | + lcb_observe_cmd_t* lCommands[1] = { &lObserve }; |
264 | + lcb_observe(aInstance, lOptions, 1, lCommands); |
265 | + lcb_wait(aInstance); |
266 | + }while(lOptions->isWaiting()); |
267 | + } |
268 | } |
269 | |
270 | if (aValues->next(lValue)) |
271 | @@ -1005,19 +1125,23 @@ |
272 | if (thePaths->next(lPath)) |
273 | { |
274 | ViewOptions* lOptions = &theOptions; |
275 | - |
276 | + String lPathOptions = lOptions->getPathOptions(); |
277 | + String lPathString = lPath.getStringValue(); |
278 | + if (lPathOptions != "") |
279 | + { |
280 | + lPathString.append(lPathOptions); |
281 | + } |
282 | lcb_http_request_t lReq; |
283 | lcb_http_cmd_t lCmd; |
284 | lCmd.version = 0; |
285 | - lCmd.v.v0.path = lPath.getStringValue().c_str(); |
286 | - lCmd.v.v0.npath = lPath.getStringValue().size(); |
287 | + lCmd.v.v0.path = lPathString.c_str(); |
288 | + lCmd.v.v0.npath = lPathString.size(); |
289 | lCmd.v.v0.body = NULL; |
290 | lCmd.v.v0.nbody = 0; |
291 | lCmd.v.v0.method = LCB_HTTP_METHOD_GET; |
292 | lCmd.v.v0.chunked = 1; |
293 | lCmd.v.v0.content_type = "application/json"; |
294 | lcb_error_t err = lcb_make_http_request(theInstance, lOptions, LCB_HTTP_TYPE_VIEW, &lCmd, &lReq); |
295 | - |
296 | if (err != LCB_SUCCESS) |
297 | { |
298 | libCouchbaseError (theInstance, err); |
299 | @@ -1065,8 +1189,46 @@ |
300 | |
301 | /******************************************************************************* |
302 | ******************************************************************************/ |
303 | - |
304 | - |
305 | +zorba::ItemSequence_t |
306 | +DeleteViewFunction::evaluate( |
307 | + const Arguments_t& aArgs, |
308 | + const zorba::StaticContext* aSctx, |
309 | + const zorba::DynamicContext* aDctx) const |
310 | +{ |
311 | + String lInstanceID = getOneStringArgument(aArgs, 0); |
312 | + lcb_t lInstance = getInstance(aDctx, lInstanceID); |
313 | + |
314 | + Iterator_t lDocNames = getIterArgument(aArgs, 1); |
315 | + Item lDoc; |
316 | + lDocNames->open(); |
317 | + while(lDocNames->next(lDoc)) |
318 | + { |
319 | + String lPath = "_design/" + lDoc.getStringValue(); |
320 | + lcb_http_request_t req; |
321 | + lcb_http_cmd_t cmd; |
322 | + cmd.version = 0; |
323 | + cmd.v.v0.path = lPath.c_str(); |
324 | + cmd.v.v0.npath = lPath.size(); |
325 | + cmd.v.v0.body = NULL; |
326 | + cmd.v.v0.nbody = 0; |
327 | + cmd.v.v0.method = LCB_HTTP_METHOD_DELETE; |
328 | + cmd.v.v0.chunked = false; |
329 | + cmd.v.v0.content_type = "application/json"; |
330 | + lcb_error_t err = lcb_make_http_request(lInstance, NULL, |
331 | + LCB_HTTP_TYPE_VIEW, &cmd, &req); |
332 | + |
333 | + if (err != LCB_SUCCESS) |
334 | + libCouchbaseError (lInstance, err); |
335 | + |
336 | + lcb_wait(lInstance); |
337 | + } |
338 | + lDocNames->close(); |
339 | + |
340 | + return ItemSequence_t(new EmptySequence()); |
341 | +} |
342 | + |
343 | +/******************************************************************************* |
344 | + ******************************************************************************/ |
345 | zorba::ItemSequence_t |
346 | CreateViewFunction::evaluate( |
347 | const Arguments_t& aArgs, |
348 | |
349 | === modified file 'src/couchbase.xq.src/couchbase.h' |
350 | --- src/couchbase.xq.src/couchbase.h 2013-01-10 06:51:21 +0000 |
351 | +++ src/couchbase.xq.src/couchbase.h 2013-01-17 22:52:18 +0000 |
352 | @@ -86,16 +86,25 @@ |
353 | |
354 | } lcb_storage_type_t; |
355 | |
356 | + typedef enum |
357 | + { |
358 | + CB_WAIT_FALSE = 0x00, |
359 | + CB_WAIT_PERSIST = 0x01, |
360 | + CB_WAIT_REPLICATE = 0x02 |
361 | + } cb_wait_type_t; |
362 | + |
363 | class ViewOptions |
364 | { |
365 | protected: |
366 | String theEncoding; |
367 | String thePath; |
368 | + String theStaleOption; |
369 | + String theLimitOption; |
370 | |
371 | public: |
372 | std::unique_ptr<std::stringstream>* theStream; |
373 | |
374 | - ViewOptions() : theEncoding("UTF-8"), thePath("") { theStream = NULL; } |
375 | + ViewOptions() : theEncoding("UTF-8"), thePath(""), theStaleOption(""), theLimitOption("") { theStream = NULL; } |
376 | |
377 | ViewOptions(String& aPath) : theEncoding("UTF-8"), thePath(aPath) {} |
378 | |
379 | @@ -106,6 +115,8 @@ |
380 | String getEncoding() { return theEncoding; } |
381 | |
382 | String getPath() { return thePath; } |
383 | + |
384 | + String getPathOptions(); |
385 | }; |
386 | |
387 | class GetOptions |
388 | @@ -137,17 +148,18 @@ |
389 | class PutOptions |
390 | { |
391 | protected: |
392 | - |
393 | lcb_storage_t theOperation; |
394 | lcb_storage_type_t theType; |
395 | unsigned int theExpTime; |
396 | String theEncoding; |
397 | + cb_wait_type_t theWaitType; |
398 | + bool theIsWaiting; |
399 | |
400 | public: |
401 | |
402 | - PutOptions() : theOperation(LCB_ADD), theType(LCB_JSON), theExpTime(0), theEncoding("") { } |
403 | + PutOptions() : theOperation(LCB_ADD), theType(LCB_JSON), theExpTime(0), theEncoding(""), theWaitType(CB_WAIT_FALSE), theIsWaiting(false){ } |
404 | |
405 | - PutOptions(lcb_storage_type_t aType) : theOperation(LCB_SET), theType(aType), theExpTime(0) { } |
406 | + PutOptions(lcb_storage_type_t aType) : theOperation(LCB_SET), theType(aType), theExpTime(0), theWaitType(CB_WAIT_FALSE), theIsWaiting(false) { } |
407 | |
408 | void setOptions(Item& aOptions); |
409 | |
410 | @@ -160,6 +172,12 @@ |
411 | unsigned int getExmpTime() { return theExpTime; } |
412 | |
413 | String getEncoding() { return theEncoding; } |
414 | + |
415 | + cb_wait_type_t getWaitType() { return theWaitType; } |
416 | + |
417 | + bool isWaiting() { return theIsWaiting; } |
418 | + |
419 | + void setWaiting(bool isWaiting) { theIsWaiting = isWaiting; } |
420 | }; |
421 | |
422 | class ViewItemSequence : public ItemSequence |
423 | @@ -299,6 +317,14 @@ |
424 | static void |
425 | put (lcb_t aInstance, Iterator_t aKeys, Iterator_t aValues, PutOptions aOptions); |
426 | |
427 | + |
428 | + static void |
429 | + observe_callback( |
430 | + lcb_t instance, |
431 | + const void *cookie, |
432 | + lcb_error_t error, |
433 | + const lcb_observe_resp_t *resp); |
434 | + |
435 | public: |
436 | |
437 | CouchbaseFunction(const CouchbaseModule* module); |
438 | @@ -560,6 +586,25 @@ |
439 | const zorba::DynamicContext*) const; |
440 | }; |
441 | |
442 | +/******************************************************************************* |
443 | + ******************************************************************************/ |
444 | + |
445 | +class DeleteViewFunction : public CouchbaseFunction |
446 | +{ |
447 | + public: |
448 | + DeleteViewFunction(const CouchbaseModule* aModule) |
449 | + : CouchbaseFunction(aModule) {} |
450 | + |
451 | + virtual ~DeleteViewFunction(){} |
452 | + |
453 | + virtual zorba::String |
454 | + getLocalName() const { return "delete-view"; } |
455 | + |
456 | + virtual zorba::ItemSequence_t |
457 | + evaluate( const Arguments_t&, |
458 | + const zorba::StaticContext*, |
459 | + const zorba::DynamicContext*) const; |
460 | +}; |
461 | } /*namespace couchbase*/ } /*namespace zorba*/ |
462 | |
463 | |
464 | |
465 | === modified file 'test/Queries/couchbase_module/view.xq' |
466 | --- test/Queries/couchbase_module/view.xq 2013-01-10 07:59:35 +0000 |
467 | +++ test/Queries/couchbase_module/view.xq 2013-01-17 22:52:18 +0000 |
468 | @@ -6,12 +6,16 @@ |
469 | "password" : null, |
470 | "bucket" : "default"}); |
471 | |
472 | -cb:put-text($instance, "view", '{ "view" : 1 }'); |
473 | - |
474 | -variable $view-name := cb:create-view($instance, "test-view", "test", {"key":"doc.view"}); |
475 | - |
476 | -variable $data := cb:view($instance, $view-name); |
477 | +cb:remove($instance, "view"); |
478 | +cb:put-text($instance, "view", '{ "view" : 1 }', { "wait" : "persist" }); |
479 | + |
480 | +variable $cb-document := "test-view"; |
481 | +variable $cb-view := "view"; |
482 | +variable $view-name := cb:create-view($instance, $cb-document, $cb-view, {"key":"doc.view"}); |
483 | + |
484 | +variable $data := cb:view($instance, $view-name, {"stale" : "false"}); |
485 | +cb:delete-view($instance, $cb-document); |
486 | for $d in jn:members($data("rows")) |
487 | -where $d("key") >0 |
488 | +where $d("key") > 0 |
489 | return $d |
490 |
I was a bit confused by the choices for parameter values for "stale" and "wait", but it looks like those come directly from Couchbase itself, so OK then.
One change: This failed on the RQ the first time the test was run, but not on later RQ runs. That implies to me that later RQ runs are probably seeing leftover data from the earlier runs. The view.xq test case should clean up after itself by deleting the value that it inserts, at least IMHO. Possibly other test cases have a similar issue; please check.