You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ro...@apache.org on 2015/02/03 16:13:18 UTC
[11/50] [abbrv] couchdb-mango git commit: Support escaped period
character in query
Support escaped period character in query
If a document has a field with a period character in it, a query
issued with an optional parameter 'fields' will not return this
field because it'll clash with the selector's syntax.
This patch addresses it by allowing to escape a period character
in the request with a backslash.
BugzID: 38248
Project: http://git-wip-us.apache.org/repos/asf/couchdb-mango/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-mango/commit/2db372bf
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-mango/tree/2db372bf
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-mango/diff/2db372bf
Branch: refs/heads/master
Commit: 2db372bf966c5fd239593de4e1cd1702dd562c30
Parents: 4bee6d1
Author: Eric Avdey <e....@cloudant.com>
Authored: Tue Nov 4 10:46:15 2014 -0400
Committer: Eric Avdey <e....@cloudant.com>
Committed: Tue Nov 4 14:58:49 2014 -0400
----------------------------------------------------------------------
.gitignore | 1 +
src/mango_doc.erl | 44 ++++++++++++++++++++++++-----------------
test/02-basic-find-test.py | 30 ++++++++++++++++++++++++++--
test/user_docs.py | 29 ++++++++++++++++++++++++++-
4 files changed, 83 insertions(+), 21 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/2db372bf/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index 665827a..50d43d8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
ebin/
test/*.pyc
venv/
+.eunit
http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/2db372bf/src/mango_doc.erl
----------------------------------------------------------------------
diff --git a/src/mango_doc.erl b/src/mango_doc.erl
index 97e8574..666ef9b 100644
--- a/src/mango_doc.erl
+++ b/src/mango_doc.erl
@@ -360,12 +360,7 @@ get_field(Props, Field) ->
get_field(Props, Field, Validator) when is_binary(Field) ->
- Path = re:split(Field, <<"\\.">>),
- lists:foreach(fun(P) ->
- if P /= <<>> -> ok; true ->
- ?MANGO_ERROR({invalid_field_name, Field})
- end
- end, Path),
+ {ok, Path} = parse_field(Field),
get_field(Props, Path, Validator);
get_field(Props, [], no_validation) ->
Props;
@@ -403,12 +398,7 @@ get_field(_, [_|_], _) ->
rem_field(Props, Field) when is_binary(Field) ->
- Path = re:split(Field, <<"\\.">>),
- lists:foreach(fun(P) ->
- if P /= <<>> -> ok; true ->
- ?MANGO_ERROR({invalid_field_name, Field})
- end
- end, Path),
+ {ok, Path} = parse_field(Field),
rem_field(Props, Path);
rem_field({Props}, [Name]) ->
case lists:keytake(Name, 1, Props) of
@@ -469,12 +459,7 @@ rem_field(_, [_|_]) ->
set_field(Props, Field, Value) when is_binary(Field) ->
- Path = re:split(Field, <<"\\.">>),
- lists:foreach(fun(P) ->
- if P /= <<>> -> ok; true ->
- ?MANGO_ERROR({invalid_field_name, Field})
- end
- end, Path),
+ {ok, Path} = parse_field(Field),
set_field(Props, Path, Value);
set_field({Props}, [Name], Value) ->
{lists:keystore(Name, 1, Props, {Name, Value})};
@@ -538,3 +523,26 @@ set_elem(1, [_ | Rest], Value) ->
[Value | Rest];
set_elem(I, [Item | Rest], Value) when I > 1 ->
[Item | set_elem(I-1, Rest, Value)].
+
+parse_field(Field) ->
+ Path = lists:map(fun
+ (P) when P =:= <<>> ->
+ ?MANGO_ERROR({invalid_field_name, Field});
+ (P) ->
+ re:replace(P, <<"\\\\">>, <<>>, [global, {return, binary}])
+ end, re:split(Field, <<"(?<!\\\\)\\.">>)),
+ {ok, Path}.
+
+-ifdef(TEST).
+-include_lib("eunit/include/eunit.hrl").
+
+parse_field_test() ->
+ ?assertEqual({ok, [<<"ab">>]}, parse_field(<<"ab">>)),
+ ?assertEqual({ok, [<<"a">>, <<"b">>]}, parse_field(<<"a.b">>)),
+ ?assertEqual({ok, [<<"a.b">>]}, parse_field(<<"a\\.b">>)),
+ ?assertEqual({ok, [<<"a">>, <<"b">>, <<"c">>]}, parse_field(<<"a.b.c">>)),
+ ?assertEqual({ok, [<<"a">>, <<"b.c">>]}, parse_field(<<"a.b\\.c">>)),
+ Exception = {mango_error, ?MODULE, {invalid_field_name, <<"a..b">>}},
+ ?assertThrow(Exception, parse_field(<<"a..b">>)).
+
+-endif.
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/2db372bf/test/02-basic-find-test.py
----------------------------------------------------------------------
diff --git a/test/02-basic-find-test.py b/test/02-basic-find-test.py
index 4287138..f897ddb 100644
--- a/test/02-basic-find-test.py
+++ b/test/02-basic-find-test.py
@@ -1,7 +1,6 @@
-
+# -*- coding: latin-1 -*-
import user_docs
-
def setup():
user_docs.create_db_and_indexes()
@@ -213,6 +212,33 @@ def test_missing_not_indexed():
assert docs[2]["user_id"] == 0
assert docs[3]["user_id"] == 13
+def test_dot_key():
+ db = user_docs.mkdb()
+ fields = ["title", "dot\\.key", "none.dot"]
+ docs = db.find({"type": "complex_key"}, fields = fields)
+ assert len(docs) == 4
+ assert docs[1].has_key("dot.key")
+ assert docs[1]["dot.key"] == "dot's value"
+ assert docs[1].has_key("none")
+ assert docs[1]["none"]["dot"] == "none dot's value"
+
+def test_peso_key():
+ db = user_docs.mkdb()
+ fields = ["title", "$key", "deep.$key"]
+ docs = db.find({"type": "complex_key"}, fields = fields)
+ assert len(docs) == 4
+ assert docs[2].has_key("$key")
+ assert docs[2]["$key"] == "peso"
+ assert docs[2].has_key("deep")
+ assert docs[2]["deep"]["$key"] == "deep peso"
+
+def test_unicode_key():
+ db = user_docs.mkdb()
+ docs = db.find({"type": "complex_key"}, fields = ["title", ""])
+ assert len(docs) == 4
+ # note: == \uf8ff
+ assert docs[3].has_key(u'\uf8ff')
+ assert docs[3][u'\uf8ff'] == "apple"
def test_limit():
db = user_docs.mkdb()
http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/2db372bf/test/user_docs.py
----------------------------------------------------------------------
diff --git a/test/user_docs.py b/test/user_docs.py
index 36f2d2d..d129f59 100644
--- a/test/user_docs.py
+++ b/test/user_docs.py
@@ -1,3 +1,4 @@
+# -*- coding: latin-1 -*-
"""
Generated with http://www.json-generator.com/
@@ -65,7 +66,8 @@ def create_db_and_indexes():
["manager"],
["favorites"],
["favorites.3"],
- ["twitter"]
+ ["twitter"],
+ ["type"]
]
for idx in indexes:
assert db.create_index(idx) is True
@@ -455,5 +457,30 @@ DOCS = [
"Lisp",
"Lisp"
]
+ },
+ {
+ "type": "complex_key",
+ "title": "normal key"
+ },
+ {
+ "type": "complex_key",
+ "title": "key with dot",
+ "dot.key": "dot's value",
+ "none": {
+ "dot": "none dot's value"
+ }
+ },
+ {
+ "type": "complex_key",
+ "title": "key with peso",
+ "$key": "peso",
+ "deep": {
+ "$key": "deep peso"
+ }
+ },
+ {
+ "type": "complex_key",
+ "title": "unicode key",
+ "": "apple"
}
]