summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGarren Smith <garren.smith@gmail.com>2017-06-30 15:19:15 +0200
committerJan Lehnardt <jan@apache.org>2017-07-16 18:22:16 +0200
commita864bebd0f8671ecfec395b6aef9b535dcf7c5af (patch)
treea5d212a3d85f164d9b3a3023df092b53418505ab
parenta8e3396bf696678e58693e8d3aa578227aa62b1a (diff)
downloadcouchdb-a864bebd0f8671ecfec395b6aef9b535dcf7c5af.tar.gz
Add stable and update support to Mango
This brings mango inline with views by supporting the new options `stable` and `update`. Fixes #621 chore: whitespace feat: add stale option to Mango fix: opts parsing
-rw-r--r--src/mango/src/mango_cursor_view.erl28
-rw-r--r--src/mango/src/mango_opts.erl27
-rw-r--r--src/mango/test/13-stable-update-test.py45
-rw-r--r--src/mango/test/mango.py4
4 files changed, 97 insertions, 7 deletions
diff --git a/src/mango/src/mango_cursor_view.erl b/src/mango/src/mango_cursor_view.erl
index 538877cbc..eb07bf898 100644
--- a/src/mango/src/mango_cursor_view.erl
+++ b/src/mango/src/mango_cursor_view.erl
@@ -138,10 +138,10 @@ composite_prefix([Col | Rest], Ranges) ->
% The query planner
-% First choose the index with the lowest difference between its
+% First choose the index with the lowest difference between its
% Prefix and the FieldRanges. If that is equal, then
-% choose the index with the least number of
-% fields in the index. If we still cannot break the tie,
+% choose the index with the least number of
+% fields in the index. If we still cannot break the tie,
% then choose alphabetically based on ddocId.
% Return the first element's Index and IndexRanges.
%
@@ -156,13 +156,13 @@ choose_best_index(_DbName, IndexRanges) ->
ColsLenA = length(mango_idx:columns(IdxA)),
ColsLenB = length(mango_idx:columns(IdxB)),
case ColsLenA - ColsLenB of
- M when M < 0 ->
+ M when M < 0 ->
true;
M when M == 0 ->
- % We have no other way to choose, so at this point
+ % We have no other way to choose, so at this point
% select the index based on (dbname, ddocid, view_name) triple
IdxA =< IdxB;
- _ ->
+ _ ->
false
end;
_ ->
@@ -270,6 +270,22 @@ apply_opts([{sort, Sort} | Rest], Args) ->
},
apply_opts(Rest, NewArgs)
end;
+apply_opts([{stale, ok} | Rest], Args) ->
+ NewArgs = Args#mrargs{
+ stable = true,
+ update = false
+ },
+ apply_opts(Rest, NewArgs);
+apply_opts([{stable, true} | Rest], Args) ->
+ NewArgs = Args#mrargs{
+ stable = true
+ },
+ apply_opts(Rest, NewArgs);
+apply_opts([{update, false} | Rest], Args) ->
+ NewArgs = Args#mrargs{
+ update = false
+ },
+ apply_opts(Rest, NewArgs);
apply_opts([{_, _} | Rest], Args) ->
% Ignore unknown options
apply_opts(Rest, Args).
diff --git a/src/mango/src/mango_opts.erl b/src/mango/src/mango_opts.erl
index af318d238..fe28d8d94 100644
--- a/src/mango/src/mango_opts.erl
+++ b/src/mango/src/mango_opts.erl
@@ -25,6 +25,7 @@
is_pos_integer/1,
is_non_neg_integer/1,
is_object/1,
+ is_ok_or_false/1,
validate_idx_name/1,
validate_selector/1,
@@ -127,6 +128,24 @@ validate_find({Props}) ->
{optional, true},
{default, false},
{validator, fun mango_opts:is_boolean/1}
+ ]},
+ {<<"stale">>, [
+ {tag, stale},
+ {optional, true},
+ {default, false},
+ {validator, fun mango_opts:is_ok_or_false/1}
+ ]},
+ {<<"update">>, [
+ {tag, update},
+ {optional, true},
+ {default, true},
+ {validator, fun mango_opts:is_boolean/1}
+ ]},
+ {<<"stable">>, [
+ {tag, stable},
+ {optional, true},
+ {default, false},
+ {validator, fun mango_opts:is_boolean/1}
]}
],
validate(Props, Opts).
@@ -197,6 +216,14 @@ is_object({Props}) ->
is_object(Else) ->
?MANGO_ERROR({invalid_object, Else}).
+is_ok_or_false(<<"ok">>) ->
+ {ok, ok};
+is_ok_or_false(<<"false">>) -> % convenience
+ {ok, false};
+is_ok_or_false(false) ->
+ {ok, false};
+is_ok_or_false(Else) ->
+ ?MANGO_ERROR({invalid_ok_or_false_value, Else}).
validate_idx_name(auto_name) ->
{ok, auto_name};
diff --git a/src/mango/test/13-stable-update-test.py b/src/mango/test/13-stable-update-test.py
new file mode 100644
index 000000000..3d78ecc65
--- /dev/null
+++ b/src/mango/test/13-stable-update-test.py
@@ -0,0 +1,45 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+import copy
+import mango
+
+DOCS1 = [
+ {
+ "_id": "54af50626de419f5109c962f",
+ "user_id": 0,
+ "age": 10,
+ "name": "Jimi",
+ "location": "UK",
+ "number": 4
+ },
+ {
+ "_id": "54af50622071121b25402dc3",
+ "user_id": 1,
+ "age": 12,
+ "name": "Eddie",
+ "location": "ZAR",
+ "number": 2
+ },
+]
+
+class SupportStableAndUpdate(mango.DbPerClass):
+ def setUp(self):
+ self.db.recreate()
+ self.db.create_index(["name"])
+ self.db.save_docs(copy.deepcopy(DOCS1))
+
+ def test_update_updates_view_when_specified(self):
+ docs = self.db.find({"name": "Eddie"}, update=False)
+ assert len(docs) == 0
+ docs = self.db.find({"name": "Eddie"}, update=True)
+ assert len(docs) == 1
diff --git a/src/mango/test/mango.py b/src/mango/test/mango.py
index bd34edcec..efcf67f2c 100644
--- a/src/mango/test/mango.py
+++ b/src/mango/test/mango.py
@@ -155,7 +155,7 @@ class Database(object):
def find(self, selector, limit=25, skip=0, sort=None, fields=None,
r=1, conflicts=False, use_index=None, explain=False,
- bookmark=None, return_raw=False):
+ bookmark=None, return_raw=False, update=True):
body = {
"selector": selector,
"use_index": use_index,
@@ -170,6 +170,8 @@ class Database(object):
body["fields"] = fields
if bookmark is not None:
body["bookmark"] = bookmark
+ if update == False:
+ body["update"] = False
body = json.dumps(body)
if explain:
path = self.path("_explain")