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:55 UTC

[48/50] [abbrv] couchdb-mango git commit: Escape field name with period correctly

Escape field name with period correctly

Change period escaping mechanism during field indexing
and query building. Rather than escaping the whole field name
at the end, we separate the field name by periods and escape
each component.

BugzId:43621


Project: http://git-wip-us.apache.org/repos/asf/couchdb-mango/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-mango/commit/8af882b7
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-mango/tree/8af882b7
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-mango/diff/8af882b7

Branch: refs/heads/master
Commit: 8af882b7f79054e417e5c251cb5f940217a9ee6f
Parents: bdf9cf7
Author: Tony Sun <to...@cloudant.com>
Authored: Wed Jan 21 18:18:01 2015 -0800
Committer: Tony Sun <to...@cloudant.com>
Committed: Wed Jan 21 18:18:01 2015 -0800

----------------------------------------------------------------------
 src/mango_native_proc.erl   | 35 ++++++++++++++++++++++++++++-------
 src/mango_selector_text.erl | 25 ++++++++++++++-----------
 src/mango_util.erl          | 10 +++++++++-
 3 files changed, 51 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/8af882b7/src/mango_native_proc.erl
----------------------------------------------------------------------
diff --git a/src/mango_native_proc.erl b/src/mango_native_proc.erl
index 3e189bd..a55a3ac 100644
--- a/src/mango_native_proc.erl
+++ b/src/mango_native_proc.erl
@@ -168,8 +168,8 @@ get_text_field_values(Values, TAcc) when is_list(Values) ->
     % We bypass make_text_field and directly call make_text_field_name
     % because the length field name is not part of the path.
     LengthFieldName = make_text_field_name(NewTAcc#tacc.path, <<"length">>),
-    EncLFN = mango_util:lucene_escape_field(LengthFieldName),
-    LengthField = [{EncLFN, <<"length">>, length(Values)}],
+    LengthField = [{escape_name_parts(LengthFieldName), <<"length">>,
+        length(Values)}],
     get_text_field_values_arr(Values, NewTAcc, LengthField);
 
 get_text_field_values(Bin, TAcc) when is_binary(Bin) ->
@@ -283,11 +283,20 @@ get_text_field_type(_) ->
 
 make_text_field(TAcc, Type, Value) ->
     FieldName = make_text_field_name(TAcc#tacc.path, Type),
-    Fields = TAcc#tacc.fields,
-    case Fields == all_fields orelse lists:member(FieldName, Fields) of
+    Fields = case TAcc#tacc.fields of
+        Fields0 when is_list(Fields0) ->
+            % for field names such as "name\\.first"
+            PFields = [mango_doc:parse_field(F) || F <- Fields0],
+            [iolist_to_binary(mango_util:join(".", P)) || {ok, P} <- PFields];
+        _ ->
+            all_fields
+    end,
+    % need to convert the fieldname to binary but not escape it in order
+    % to compare with the user field names.
+    BName = iolist_to_binary(FieldName),
+    case Fields == all_fields orelse lists:member(BName, Fields) of
         true ->
-            [{mango_util:lucene_escape_field(FieldName), Type,
-            Value}];
+            [{escape_name_parts(FieldName), Type, Value}];
         false ->
             []
     end.
@@ -297,6 +306,18 @@ make_text_field_name([P | Rest], Type) ->
     make_text_field_name0(Rest, [P, ":", Type]).
 
 make_text_field_name0([], Name) ->
-    iolist_to_binary(Name);
+    Name;
 make_text_field_name0([P | Rest], Name) ->
     make_text_field_name0(Rest, [P, "." | Name]).
+
+
+escape_name_parts(Name) ->
+    EscapedName = lists:map(fun(N) ->
+        case N of
+            "." ->
+                ".";
+            Else ->
+                mango_util:lucene_escape_field(Else)
+        end
+    end, Name),
+    iolist_to_binary(EscapedName).

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/8af882b7/src/mango_selector_text.erl
----------------------------------------------------------------------
diff --git a/src/mango_selector_text.erl b/src/mango_selector_text.erl
index 35a0d4c..9a69853 100644
--- a/src/mango_selector_text.erl
+++ b/src/mango_selector_text.erl
@@ -171,11 +171,12 @@ convert(_Path, {Props} = Sel) when length(Props) > 1 ->
 
 
 to_query({op_and, Args}) when is_list(Args) ->
-    Res = ["(", join(<<" AND ">>, lists:map(fun to_query/1, Args)), ")"],
+    Res = ["(", mango_util:join(<<" AND ">>, lists:map(fun to_query/1, Args)),
+        ")"],
     Res;
 
 to_query({op_or, Args}) when is_list(Args) ->
-    ["(", join(" OR ", lists:map(fun to_query/1, Args)), ")"];
+    ["(", mango_util:join(" OR ", lists:map(fun to_query/1, Args)), ")"];
 
 to_query({op_not, {ExistsQuery, Arg}}) when is_tuple(Arg) ->
     ["(", to_query(ExistsQuery), " AND NOT (", to_query(Arg), "))"];
@@ -191,25 +192,25 @@ to_query({op_insert, Arg}) when is_binary(Arg) ->
 %% This needs to be resolved.
 to_query({op_field, {Name, Value}}) ->
     NameBin = iolist_to_binary(Name),
-    ["(", mango_util:lucene_escape_field(NameBin), ":", Value, ")"];
+    ["(", escape_name_parts(NameBin), ":", Value, ")"];
 
 %% This is for indexable_fields
 to_query({op_null, {Name, Value}}) ->
     NameBin = iolist_to_binary(Name),
-    ["(", mango_util:lucene_escape_field(NameBin), ":", Value, ")"];
+    ["(", escape_name_parts(NameBin), ":", Value, ")"];
 
 to_query({op_fieldname, {Name, Wildcard}}) ->
     NameBin = iolist_to_binary(Name),
-    ["($fieldnames:", mango_util:lucene_escape_field(NameBin), Wildcard, ")"];
+    ["($fieldnames:", escape_name_parts(NameBin), Wildcard, ")"];
 
 to_query({op_default, Value}) ->
     ["($default:", Value, ")"].
 
 
-join(_Sep, [Item]) ->
-    [Item];
-join(Sep, [Item | Rest]) ->
-    [Item, Sep | join(Sep, Rest)].
+escape_name_parts(Name) ->
+    {ok, ParsedNames} = mango_doc:parse_field(Name),
+    EncodedNames = [mango_util:lucene_escape_field(N) || N <- ParsedNames],
+    iolist_to_binary(mango_util:join(".", EncodedNames)).
 
 
 %% We match on fieldname and fieldname.[]
@@ -256,7 +257,9 @@ field_exists_query(Path) ->
     % appened * isntead).
     Parts = [
         {op_fieldname, {[path_str(Path), ":"], "*"}},
-        {op_fieldname, {[path_str(Path), "."], "*"}}
+        % need to extract out the period because mango_doc:parse_field/1
+        % will not accept "name.", also we don't want to escape the .
+        {op_fieldname, {[path_str(Path)], ".*"}}
     ],
     {op_or, Parts}.
 
@@ -304,7 +307,7 @@ value_str(null) ->
 
 
 append_sort_type(RawSortField, Selector) ->
-    EncodeField = mango_util:lucene_escape_field(RawSortField),
+    EncodeField = escape_name_parts(RawSortField),
     String = mango_util:has_suffix(EncodeField, <<"_3astring">>),
     Number = mango_util:has_suffix(EncodeField, <<"_3anumber">>),
     case {String, Number} of

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/8af882b7/src/mango_util.erl
----------------------------------------------------------------------
diff --git a/src/mango_util.erl b/src/mango_util.erl
index f3b60b2..b1d30fb 100644
--- a/src/mango_util.erl
+++ b/src/mango_util.erl
@@ -34,7 +34,9 @@
     lucene_escape_field/1,
     lucene_escape_query_value/1,
 
-    has_suffix/2
+    has_suffix/2,
+
+    join/2
 ]).
 
 
@@ -293,3 +295,9 @@ has_suffix(Bin, Suffix) when is_binary(Bin), is_binary(Suffix) ->
                 false
         end
     end.
+
+
+join(_Sep, [Item]) ->
+    [Item];
+join(Sep, [Item | Rest]) ->
+    [Item, Sep | join(Sep, Rest)].