You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by to...@apache.org on 2015/09/10 02:34:03 UTC

[01/26] couchdb-mango git commit: Revert "Remove reference to _text indexes"

Repository: couchdb-mango
Updated Branches:
  refs/heads/master 677cd2a59 -> 1de64eabb


Revert "Remove reference to _text indexes"

This reverts commit 955a42c3bbd0502f1623bec29edad59eddd7b2ea.

Conflicts:
	src/mango_error.erl
COUCHDB-2787


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

Branch: refs/heads/master
Commit: fc1e36f354475981a4fce044a160f14251922421
Parents: 677cd2a
Author: Tony Sun <to...@cloudant.com>
Authored: Mon Aug 24 14:17:01 2015 -0700
Committer: Tony Sun <to...@cloudant.com>
Committed: Mon Aug 24 14:17:01 2015 -0700

----------------------------------------------------------------------
 src/mango_cursor.erl      |   3 +-
 src/mango_cursor_text.erl | 307 +++++++++++++++++++++++++++++++++++++++++
 src/mango_error.erl       |  39 ++++++
 src/mango_idx.erl         |  10 +-
 4 files changed, 355 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/fc1e36f3/src/mango_cursor.erl
----------------------------------------------------------------------
diff --git a/src/mango_cursor.erl b/src/mango_cursor.erl
index 0b58c12..545a863 100644
--- a/src/mango_cursor.erl
+++ b/src/mango_cursor.erl
@@ -124,7 +124,8 @@ group_indexes_by_type(Indexes) ->
     % don't suddenly switch indexes for existing client
     % queries.
     CursorModules = [
-        mango_cursor_view
+        mango_cursor_view,
+        mango_cursor_text
     ],
     lists:flatmap(fun(CMod) ->
         case dict:find(CMod, IdxDict) of

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/fc1e36f3/src/mango_cursor_text.erl
----------------------------------------------------------------------
diff --git a/src/mango_cursor_text.erl b/src/mango_cursor_text.erl
new file mode 100644
index 0000000..c774c82
--- /dev/null
+++ b/src/mango_cursor_text.erl
@@ -0,0 +1,307 @@
+% 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.
+
+-module(mango_cursor_text).
+
+-export([
+    create/4,
+    explain/1,
+    execute/3
+]).
+
+
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("dreyfus/include/dreyfus.hrl").
+-include("mango_cursor.hrl").
+-include("mango.hrl").
+
+
+-record(cacc, {
+    selector,
+    dbname,
+    ddocid,
+    idx_name,
+    query_args,
+    bookmark,
+    limit,
+    skip,
+    user_fun,
+    user_acc
+}).
+
+
+create(Db, Indexes, Selector, Opts0) ->
+    Index = case Indexes of
+        [Index0] ->
+            Index0;
+        _ ->
+            ?MANGO_ERROR(multiple_text_indexes)
+    end,
+
+    Opts = unpack_bookmark(Db#db.name, Opts0),
+
+    % Limit the result set size to 50 for Clouseau's
+    % sake. We may want to revisit this.
+    Limit0 = couch_util:get_value(limit, Opts, 50),
+    Limit = if Limit0 < 50 -> Limit0; true -> 50 end,
+    Skip = couch_util:get_value(skip, Opts, 0),
+    Fields = couch_util:get_value(fields, Opts, all_fields),
+
+    {ok, #cursor{
+        db = Db,
+        index = Index,
+        ranges = null,
+        selector = Selector,
+        opts = Opts,
+        limit = Limit,
+        skip = Skip,
+        fields = Fields
+    }}.
+
+
+explain(Cursor) ->
+    #cursor{
+        selector = Selector,
+        opts = Opts
+    } = Cursor,
+    [
+        {'query', mango_selector_text:convert(Selector)},
+        {sort, sort_query(Opts, Selector)}
+    ].
+
+
+execute(Cursor, UserFun, UserAcc) ->
+    #cursor{
+        db = Db,
+        index = Idx,
+        limit = Limit,
+        skip = Skip,
+        selector = Selector,
+        opts = Opts
+    } = Cursor,
+    QueryArgs = #index_query_args{
+        q = mango_selector_text:convert(Selector),
+        sort = sort_query(Opts, Selector),
+        raw_bookmark = true
+    },
+    CAcc = #cacc{
+        selector = Selector,
+        dbname = Db#db.name,
+        ddocid = ddocid(Idx),
+        idx_name = mango_idx:name(Idx),
+        bookmark = get_bookmark(Opts),
+        limit = Limit,
+        skip = Skip,
+        query_args = QueryArgs,
+        user_fun = UserFun,
+        user_acc = UserAcc
+    },
+    try
+        execute(CAcc)
+    catch
+        throw:{stop, FinalCAcc} ->
+            #cacc{
+                bookmark = FinalBM,
+                user_fun = UserFun,
+                user_acc = LastUserAcc
+            } = FinalCAcc,
+            JsonBM = dreyfus_bookmark:pack(FinalBM),
+            Arg = {add_key, bookmark, JsonBM},
+            {_Go, FinalUserAcc} = UserFun(Arg, LastUserAcc),
+            {ok, FinalUserAcc}
+    end.
+
+
+execute(CAcc) ->
+    case search_docs(CAcc) of
+        {ok, Bookmark, []} ->
+            % If we don't have any results from the
+            % query it means the request has paged through
+            % all possible results and the request is over.
+            NewCAcc = CAcc#cacc{bookmark = Bookmark},
+            throw({stop, NewCAcc});
+        {ok, Bookmark, Hits} ->
+            NewCAcc = CAcc#cacc{bookmark = Bookmark},
+            HitDocs = get_json_docs(CAcc#cacc.dbname, Hits),
+            {ok, FinalCAcc} = handle_hits(NewCAcc, HitDocs),
+            execute(FinalCAcc)
+    end.
+
+
+search_docs(CAcc) ->
+    #cacc{
+        dbname = DbName,
+        ddocid = DDocId,
+        idx_name = IdxName
+    } = CAcc,
+    QueryArgs = update_query_args(CAcc),
+    case dreyfus_fabric_search:go(DbName, DDocId, IdxName, QueryArgs) of
+        {ok, Bookmark, _, Hits, _, _} ->
+            {ok, Bookmark, Hits};
+        {error, Reason} ->
+            ?MANGO_ERROR({text_search_error, {error, Reason}})
+    end.
+
+
+handle_hits(CAcc, []) ->
+    {ok, CAcc};
+
+handle_hits(CAcc0, [{Sort, Doc} | Rest]) ->
+    CAcc1 = handle_hit(CAcc0, Sort, Doc),
+    handle_hits(CAcc1, Rest).
+
+
+handle_hit(CAcc0, Sort, Doc) ->
+    #cacc{
+        limit = Limit,
+        skip = Skip
+    } = CAcc0,
+    CAcc1 = update_bookmark(CAcc0, Sort),
+    case mango_selector:match(CAcc1#cacc.selector, Doc) of
+        true when Skip > 0 ->
+            CAcc1#cacc{skip = Skip - 1};
+        true when Limit == 0 ->
+            % We hit this case if the user spcified with a
+            % zero limit. Notice that in this case we need
+            % to return the bookmark from before this match
+            throw({stop, CAcc0});
+        true when Limit == 1 ->
+            NewCAcc = apply_user_fun(CAcc1, Doc),
+            throw({stop, NewCAcc});
+        true when Limit > 1 ->
+            NewCAcc = apply_user_fun(CAcc1, Doc),
+            NewCAcc#cacc{limit = Limit - 1};
+        false ->
+            CAcc1
+    end.
+
+
+apply_user_fun(CAcc, Doc) ->
+    #cacc{
+        user_fun = UserFun,
+        user_acc = UserAcc
+    } = CAcc,
+    case UserFun({row, Doc}, UserAcc) of
+        {ok, NewUserAcc} ->
+            CAcc#cacc{user_acc = NewUserAcc};
+        {stop, NewUserAcc} ->
+            throw({stop, CAcc#cacc{user_acc = NewUserAcc}})
+    end.
+
+
+%% Convert Query to Dreyfus sort specifications
+%% Covert <<"Field">>, <<"desc">> to <<"-Field">>
+%% and append to the dreyfus query
+sort_query(Opts, Selector) ->
+    {sort, {Sort}} = lists:keyfind(sort, 1, Opts),
+    SortList = lists:map(fun(SortField) ->
+        {Dir, RawSortField}  = case SortField of
+            {Field, <<"asc">>} -> {asc, Field};
+            {Field, <<"desc">>} -> {desc, Field};
+            Field when is_binary(Field) -> {asc, Field}
+        end,
+        SField = mango_selector_text:append_sort_type(RawSortField, Selector),
+        case Dir of
+            asc ->
+                SField;
+            desc ->
+                <<"-", SField/binary>>
+        end
+    end, Sort),
+    case SortList of
+        [] -> relevance;
+        _ -> SortList
+    end.
+
+
+get_bookmark(Opts) ->
+    case lists:keyfind(bookmark, 1, Opts) of
+        {_, BM} when is_list(BM), BM /= [] ->
+            BM;
+        _ ->
+            nil
+    end.
+
+
+update_bookmark(CAcc, Sortable) ->
+    BM = CAcc#cacc.bookmark,
+    QueryArgs = CAcc#cacc.query_args,
+    Sort = QueryArgs#index_query_args.sort,
+    NewBM = dreyfus_bookmark:update(Sort, BM, [Sortable]),
+    CAcc#cacc{bookmark = NewBM}.
+
+
+pack_bookmark(Bookmark) ->
+    case dreyfus_bookmark:pack(Bookmark) of
+        null -> nil;
+        Enc -> Enc
+    end.
+
+
+unpack_bookmark(DbName, Opts) ->
+    NewBM = case lists:keyfind(bookmark, 1, Opts) of
+        {_, nil} ->
+            [];
+        {_, Bin} ->
+            try
+                dreyfus_bookmark:unpack(DbName, Bin)
+            catch _:_ ->
+                ?MANGO_ERROR({invalid_bookmark, Bin})
+            end
+    end,
+    lists:keystore(bookmark, 1, Opts, {bookmark, NewBM}).
+
+
+ddocid(Idx) ->
+    case mango_idx:ddoc(Idx) of
+        <<"_design/", Rest/binary>> ->
+            Rest;
+        Else ->
+            Else
+    end.
+
+
+update_query_args(CAcc) ->
+    #cacc{
+        bookmark = Bookmark,
+        query_args = QueryArgs
+    } = CAcc,
+    QueryArgs#index_query_args{
+        bookmark = pack_bookmark(Bookmark),
+        limit = get_limit(CAcc)
+    }.
+
+
+get_limit(CAcc) ->
+    Total = CAcc#cacc.limit + CAcc#cacc.skip,
+    if
+        Total < 25 -> 25;
+        Total > 100 -> 100;
+        true -> Total
+    end.
+
+
+get_json_docs(DbName, Hits) ->
+    Ids = lists:map(fun(#sortable{item = Item}) ->
+        couch_util:get_value(<<"_id">>, Item#hit.fields)
+    end, Hits),
+    {ok, IdDocs} = dreyfus_fabric:get_json_docs(DbName, Ids),
+    lists:map(fun(#sortable{item = Item} = Sort) ->
+        Id = couch_util:get_value(<<"_id">>, Item#hit.fields),
+        case lists:keyfind(Id, 1, IdDocs) of
+            {Id, {doc, Doc}} ->
+                {Sort, Doc};
+            false ->
+                {Sort, not_found}
+        end
+    end, Hits).
+

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/fc1e36f3/src/mango_error.erl
----------------------------------------------------------------------
diff --git a/src/mango_error.erl b/src/mango_error.erl
index 69767cf..cf117ab 100644
--- a/src/mango_error.erl
+++ b/src/mango_error.erl
@@ -46,6 +46,32 @@ info(mango_cursor, {no_usable_index, selector_unsupported}) ->
         <<"There is no index available for this selector.">>
     };
 
+info(mango_cursor_text, {invalid_bookmark, BadBookmark}) ->
+    {
+        400,
+        <<"invalid_bookmark">>,
+        fmt("Invalid boomkark value: ~s", [?JSON_ENCODE(BadBookmark)])
+    };
+info(mango_cursor_text, multiple_text_indexes) ->
+    {
+        400,
+        <<"multiple_text_indexes">>,
+        <<"You must specify an index with the `use_index` parameter.">>
+    };
+info(mango_cursor_text, {text_search_error, {error, {bad_request, Msg}}}) 
+        when is_binary(Msg) ->
+    {
+        400,
+        <<"text_search_error">>,
+        Msg
+    };
+info(mango_cursor_text, {text_search_error, {error, Error}}) ->
+    {
+        400,
+        <<"text_search_error">>,
+        fmt("Error performing text search: ~p", [Error])
+    };
+
 info(mango_fields, {invalid_fields_json, BadFields}) ->
     {
         400,
@@ -122,6 +148,19 @@ info(mango_idx_view, {index_not_found, BadIdx}) ->
         fmt("JSON index ~s not found in this design doc.", [BadIdx])
     };
 
+info(mango_idx_text, {invalid_index_text, BadIdx}) ->
+    {
+        400,
+        <<"invalid_index">>,
+        fmt("Text indexes must be an object, not: ~w", [BadIdx])
+    };
+info(mango_idx_text, {index_not_found, BadIdx}) ->
+    {
+        404,
+        <<"index_not_found">>,
+        fmt("Text index ~s not found in this design doc.", [BadIdx])
+    };
+
 info(mango_opts, {invalid_bulk_docs, Val}) ->
     {
         400,

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/fc1e36f3/src/mango_idx.erl
----------------------------------------------------------------------
diff --git a/src/mango_idx.erl b/src/mango_idx.erl
index f6e688b..71a55a9 100644
--- a/src/mango_idx.erl
+++ b/src/mango_idx.erl
@@ -167,7 +167,7 @@ from_ddoc(Db, {Props}) ->
             ?MANGO_ERROR(invalid_query_ddoc_language)
     end,
 
-    IdxMods = [mango_idx_view],
+    IdxMods = [mango_idx_view, mango_idx_text],
     Idxs = lists:flatmap(fun(Mod) -> Mod:from_ddoc({Props}) end, IdxMods),
     lists:map(fun(Idx) ->
         Idx#idx{
@@ -241,13 +241,17 @@ end_key(#idx{}=Idx, Ranges) ->
 cursor_mod(#idx{type = <<"json">>}) ->
     mango_cursor_view;
 cursor_mod(#idx{def = all_docs, type= <<"special">>}) ->
-    mango_cursor_view.
+    mango_cursor_view;
+cursor_mod(#idx{type = <<"text">>}) ->
+    mango_cursor_text.
 
 
 idx_mod(#idx{type = <<"json">>}) ->
     mango_idx_view;
 idx_mod(#idx{type = <<"special">>}) ->
-    mango_idx_special.
+    mango_idx_special;
+idx_mod(#idx{type = <<"text">>}) ->
+    mango_idx_text.
 
 
 db_to_name(#db{name=Name}) ->


[25/26] couchdb-mango git commit: Reinstate skip tests

Posted by to...@apache.org.
Reinstate skip tests

COUCHDB-2787


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

Branch: refs/heads/master
Commit: 17e4abffaec605d14f836d6b05ec1423da612a31
Parents: f12076f
Author: Tony Sun <to...@cloudant.com>
Authored: Tue Sep 8 11:13:49 2015 -0700
Committer: Tony Sun <to...@cloudant.com>
Committed: Tue Sep 8 11:13:49 2015 -0700

----------------------------------------------------------------------
 test/01-index-crud-test.py             |  8 +++---
 test/04-key-tests.py                   |  2 +-
 test/05-index-selection-test.py        |  4 +--
 test/06-basic-text-test.py             | 38 ++++++++++++++---------------
 test/06-text-default-field-test.py     | 18 +++++++-------
 test/07-text-custom-field-list-test.py |  6 ++---
 test/08-text-limit-test.py             |  6 ++---
 test/09-text-sort-test.py              |  6 ++---
 test/README.md                         |  3 ++-
 test/mango.py                          |  2 +-
 10 files changed, 47 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/17e4abff/test/01-index-crud-test.py
----------------------------------------------------------------------
diff --git a/test/01-index-crud-test.py b/test/01-index-crud-test.py
index 2852a6a..021d66e 100644
--- a/test/01-index-crud-test.py
+++ b/test/01-index-crud-test.py
@@ -16,10 +16,10 @@ import mango
 import unittest
 
 class IndexCrudTests(mango.DbPerClass):
-    # @classmethod
-    # def setUpClass(klass):
-    #     raise unittest.SkipTest('text index service not available')
-    #     super(KeyTests, klass).setUpClass()
+    @classmethod
+    def setUpClass(klass):
+        raise unittest.SkipTest('text index service not available')
+        super(KeyTests, klass).setUpClass()
 
     def test_bad_fields(self):
         bad_fields = [

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/17e4abff/test/04-key-tests.py
----------------------------------------------------------------------
diff --git a/test/04-key-tests.py b/test/04-key-tests.py
index 9b55c7f..5174d0b 100644
--- a/test/04-key-tests.py
+++ b/test/04-key-tests.py
@@ -56,7 +56,7 @@ TEST_DOCS = [
 class KeyTests(mango.DbPerClass):
     @classmethod
     def setUpClass(klass):
-        # raise unittest.SkipTest('text index service not available')
+        raise unittest.SkipTest('text index service not available')
         super(KeyTests, klass).setUpClass()
         klass.db.save_docs(TEST_DOCS, w=3)
         klass.db.create_index(["type"], ddoc="view")

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/17e4abff/test/05-index-selection-test.py
----------------------------------------------------------------------
diff --git a/test/05-index-selection-test.py b/test/05-index-selection-test.py
index 375085f..4ded668 100644
--- a/test/05-index-selection-test.py
+++ b/test/05-index-selection-test.py
@@ -19,7 +19,7 @@ class IndexSelectionTests(mango.UserDocsTests):
     @classmethod
     def setUpClass(klass):
         super(IndexSelectionTests, klass).setUpClass()
-        user_docs.add_text_indexes(klass.db, {})
+        # user_docs.add_text_indexes(klass.db, {})
 
     def test_basic(self):
         resp = self.db.find({"name.last": "A last name"}, explain=True)
@@ -77,7 +77,7 @@ class IndexSelectionTests(mango.UserDocsTests):
 class MultiTextIndexSelectionTests(mango.UserDocsTests):
     @classmethod
     def setUpClass(klass):
-        # raise unittest.SkipTest('text index service is not available')
+        raise unittest.SkipTest('text index service is not available')
         super(MultiTextIndexSelectionTests, klass).setUpClass()
         klass.db.create_text_index(ddoc="foo", analyzer="keyword")
         klass.db.create_text_index(ddoc="bar", analyzer="email")

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/17e4abff/test/06-basic-text-test.py
----------------------------------------------------------------------
diff --git a/test/06-basic-text-test.py b/test/06-basic-text-test.py
index 593e6d7..72a3918 100644
--- a/test/06-basic-text-test.py
+++ b/test/06-basic-text-test.py
@@ -17,24 +17,24 @@ import user_docs
 import num_string_docs
 
 
-# class TextIndexCheckTests(mango.DbPerClass):
+class TextIndexCheckTests(mango.DbPerClass):
 
-#     def test_create_text_index(self):
-#         body = json.dumps({
-#             'index': {
-#                 'fields': 'test'
-#             },
-#             'type': 'text'
-#         })
-#         resp = self.db.sess.post(self.db.path("_index"), data=body)
-#         assert resp.status_code == 503, resp
+    def test_create_text_index(self):
+        body = json.dumps({
+            'index': {
+                'fields': 'test'
+            },
+            'type': 'text'
+        })
+        resp = self.db.sess.post(self.db.path("_index"), data=body)
+        assert resp.status_code == 503, resp
 
 
 class BasicTextTests(mango.UserDocsTextTests):
 
-    # @classmethod
-    # def setUpClass(klass):
-    #     raise unittest.SkipTest('text index service not available')
+    @classmethod
+    def setUpClass(klass):
+        raise unittest.SkipTest('text index service not available')
 
     def test_simple(self):
         docs = self.db.find({"$text": "Stephanie"})
@@ -431,9 +431,9 @@ class BasicTextTests(mango.UserDocsTextTests):
 
 class ElemMatchTests(mango.FriendDocsTextTests):
 
-    # @classmethod
-    # def setUpClass(klass):
-    #     raise unittest.SkipTest('text index service not available')
+    @classmethod
+    def setUpClass(klass):
+        raise unittest.SkipTest('text index service not available')
 
     def test_elem_match_non_object(self):
         q = {"bestfriends":{
@@ -566,9 +566,9 @@ class ElemMatchTests(mango.FriendDocsTextTests):
 # Test numeric strings for $text
 class NumStringTests(mango.NumStringDocsTextTests):
 
-    # @classmethod
-    # def setUpClass(klass):
-    #     raise unittest.SkipTest('text index service not available')
+    @classmethod
+    def setUpClass(klass):
+        raise unittest.SkipTest('text index service not available')
 
     def test_floating_point_val(self):
         float_point_string = num_string_docs.DOCS[2]["number_string"]

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/17e4abff/test/06-text-default-field-test.py
----------------------------------------------------------------------
diff --git a/test/06-text-default-field-test.py b/test/06-text-default-field-test.py
index 599cad6..f4aaf9a 100644
--- a/test/06-text-default-field-test.py
+++ b/test/06-text-default-field-test.py
@@ -18,9 +18,9 @@ class NoDefaultFieldTest(mango.UserDocsTextTests):
 
     DEFAULT_FIELD = False
 
-    # @classmethod
-    # def setUpClass(klass):
-    #     raise unittest.SkipTest('text index service not available')
+    @classmethod
+    def setUpClass(klass):
+        raise unittest.SkipTest('text index service not available')
 
     def test_basic(self):
         docs = self.db.find({"$text": "Ramona"})
@@ -40,9 +40,9 @@ class NoDefaultFieldWithAnalyzer(mango.UserDocsTextTests):
         "analyzer": "keyword"
     }
 
-    # @classmethod
-    # def setUpClass(klass):
-    #     raise unittest.SkipTest('text not supported')
+    @classmethod
+    def setUpClass(klass):
+        raise unittest.SkipTest('text not supported')
 
     def test_basic(self):
         docs = self.db.find({"$text": "Ramona"})
@@ -61,9 +61,9 @@ class DefaultFieldWithCustomAnalyzer(mango.UserDocsTextTests):
         "analyzer": "keyword"
     }
 
-    # @classmethod
-    # def setUpClass(klass):
-    #     raise unittest.SkipTest('text not supported')
+    @classmethod
+    def setUpClass(klass):
+        raise unittest.SkipTest('text not supported')
 
     def test_basic(self):
         docs = self.db.find({"$text": "Ramona"})

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/17e4abff/test/07-text-custom-field-list-test.py
----------------------------------------------------------------------
diff --git a/test/07-text-custom-field-list-test.py b/test/07-text-custom-field-list-test.py
index c59c3a2..8d68a1f 100644
--- a/test/07-text-custom-field-list-test.py
+++ b/test/07-text-custom-field-list-test.py
@@ -16,9 +16,9 @@ import unittest
 
 class CustomFieldsTest(mango.UserDocsTextTests):
 
-    # @classmethod
-    # def setUpClass(klass):
-    #     raise unittest.SkipTest('text index service not available')
+    @classmethod
+    def setUpClass(klass):
+        raise unittest.SkipTest('text index service not available')
 
     FIELDS = [
         {"name": "favorites.[]", "type": "string"},

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/17e4abff/test/08-text-limit-test.py
----------------------------------------------------------------------
diff --git a/test/08-text-limit-test.py b/test/08-text-limit-test.py
index 31083ae..36bf4a9 100644
--- a/test/08-text-limit-test.py
+++ b/test/08-text-limit-test.py
@@ -16,9 +16,9 @@ import unittest
 
 class LimitTests(mango.LimitDocsTextTests):
 
-    # @classmethod
-    # def setUpClass(klass):
-    #     raise unittest.SkipTest('text index service not available')
+    @classmethod
+    def setUpClass(klass):
+        raise unittest.SkipTest('text index service not available')
 
     def test_limit_field(self):
         q = {"$or": [{"user_id" : {"$lt" : 10}}, {"filtered_array.[]": 1}]}

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/17e4abff/test/09-text-sort-test.py
----------------------------------------------------------------------
diff --git a/test/09-text-sort-test.py b/test/09-text-sort-test.py
index c06c680..7bdf54a 100644
--- a/test/09-text-sort-test.py
+++ b/test/09-text-sort-test.py
@@ -15,9 +15,9 @@ import unittest
 
 class SortTests(mango.UserDocsTextTests):
 
-    # @classmethod
-    # def setUpClass(klass):
-    #     raise unittest.SkipTest('text index service is not available')
+    @classmethod
+    def setUpClass(klass):
+        raise unittest.SkipTest('text index service is not available')
 
     def test_number_sort(self):
         q = {"age": {"$gt": 0}}

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/17e4abff/test/README.md
----------------------------------------------------------------------
diff --git a/test/README.md b/test/README.md
index 810fc0a..17abf23 100644
--- a/test/README.md
+++ b/test/README.md
@@ -1,10 +1,11 @@
 Mango Tests
 ===========
 
+CouchDB should be started with ./dev/run -a testuser:testpass.
+
 To run these, do this in the top level directory:
 
     $ virtualenv venv
     $ source venv/bin/activate
     $ pip install nose requests
     $ nosetests
-

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/17e4abff/test/mango.py
----------------------------------------------------------------------
diff --git a/test/mango.py b/test/mango.py
index 3464b14..fa7d52c 100644
--- a/test/mango.py
+++ b/test/mango.py
@@ -33,7 +33,7 @@ class Database(object):
         self.port = port
         self.dbname = dbname
         self.sess = requests.session()
-        self.sess.auth = ('adm', 'pass')
+        self.sess.auth = ('testuser', 'testpass')
         self.sess.headers["Content-Type"] = "application/json"
 
     @property


[11/26] couchdb-mango git commit: Add text index field validator

Posted by to...@apache.org.
Add text index field validator

Our original text field validator let any list through. The new
validator makes text fields definitions more restrictive.

BugzID: 46817


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

Branch: refs/heads/master
Commit: a814fe78b76c2b84ad2f06dbb87ddb0b57fc1de3
Parents: 85f8a2b
Author: Tony Sun <to...@cloudant.com>
Authored: Tue Aug 25 13:40:06 2015 -0700
Committer: Tony Sun <to...@cloudant.com>
Committed: Tue Aug 25 13:40:06 2015 -0700

----------------------------------------------------------------------
 src/mango_error.erl        |  8 ++++++++
 src/mango_idx_text.erl     | 26 +++++++++++++++++++++++---
 test/01-index-crud-test.py | 21 +++++++++++++++++++++
 3 files changed, 52 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/a814fe78/src/mango_error.erl
----------------------------------------------------------------------
diff --git a/src/mango_error.erl b/src/mango_error.erl
index cf117ab..6ad76bb 100644
--- a/src/mango_error.erl
+++ b/src/mango_error.erl
@@ -141,6 +141,14 @@ info(mango_idx_view, {invalid_index_json, BadIdx}) ->
         <<"invalid_index">>,
         fmt("JSON indexes must be an object, not: ~w", [BadIdx])
     };
+info(mango_idx_text, {invalid_index_fields_definition, Def}) ->
+    {
+        400,
+        <<"invalid_index_fields_definition">>,
+        fmt("Text Index field definitions must be of the form
+            {\"name\": \"fieldname\", \"type\":
+                \"boolean,number, or string\"}. Def: ~p", [Def])
+    };
 info(mango_idx_view, {index_not_found, BadIdx}) ->
     {
         404,

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/a814fe78/src/mango_idx_text.erl
----------------------------------------------------------------------
diff --git a/src/mango_idx_text.erl b/src/mango_idx_text.erl
index cce978e..321889a 100644
--- a/src/mango_idx_text.erl
+++ b/src/mango_idx_text.erl
@@ -15,6 +15,7 @@
 
 -export([
     validate/1,
+    validate_fields/1,
     add/2,
     remove/2,
     from_ddoc/1,
@@ -148,12 +149,31 @@ def_to_json([{Key, Value} | Rest]) ->
 
 fields_to_json([]) ->
     [];
-fields_to_json([{[{<<"name">>, Name}, {<<"type">>, Type}]} | Rest]) ->
+fields_to_json([{[{<<"name">>, Name}, {<<"type">>, Type0}]} | Rest]) ->
+    Type = validate_field_type(Type0),
     [{[{Name, Type}]} | fields_to_json(Rest)];
-fields_to_json([{[{<<"type">>, Type}, {<<"name">>, Name}]} | Rest]) ->
+fields_to_json([{[{<<"type">>, Type0}, {<<"name">>, Name}]} | Rest]) ->
+    Type = validate_field_type(Type0),
     [{[{Name, Type}]} | fields_to_json(Rest)].
 
 
+validate_field_type(<<"string">>) ->
+    <<"string">>;
+validate_field_type(<<"number">>) ->
+    <<"number">>;
+validate_field_type(<<"boolean">>) ->
+    <<"boolean">>.
+
+
+validate_fields(Fields) ->
+    try fields_to_json(Fields) of
+        _ ->
+            mango_fields:new(Fields)
+    catch error:function_clause ->
+        ?MANGO_ERROR({invalid_index_fields_definition, Fields})
+    end.
+
+
 opts() ->
     [
         {<<"default_analyzer">>, [
@@ -176,7 +196,7 @@ opts() ->
             {tag, fields},
             {optional, true},
             {default, []},
-            {validator, fun mango_opts:validate_fields/1}
+            {validator, fun ?MODULE:validate_fields/1}
         ]}
     ].
 

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/a814fe78/test/01-index-crud-test.py
----------------------------------------------------------------------
diff --git a/test/01-index-crud-test.py b/test/01-index-crud-test.py
index 31e0b08..bd41516 100644
--- a/test/01-index-crud-test.py
+++ b/test/01-index-crud-test.py
@@ -241,6 +241,27 @@ class IndexCrudTests(mango.DbPerClass):
             return
         raise AssertionError("index not created")
 
+    def test_create_bad_text_idx(self):
+        bad_fields = [
+            True,
+            False,
+            "bing",
+            2.0,
+            ["foo", "bar"],
+            [{"name": "foo2"}],
+            [{"name": "foo3", "type": "garbage"}],
+            [{"type": "number"}],
+            [{"name": "age", "type": "number"} , {"name": "bad"}],
+            [{"name": "age", "type": "number"} , "bla"]
+        ]
+        for fields in bad_fields:
+            try:
+                self.db.create_text_index(fields=fields)
+            except Exception, e:
+                assert e.response.status_code == 400
+            else:
+                raise AssertionError("bad create text index")
+
     def test_limit_skip_index(self):
         fields = ["field1"]
         ret = self.db.create_index(fields, name="idx_01")


[23/26] couchdb-mango git commit: Use short circuit operators

Posted by to...@apache.org.
Use short circuit operators

COUCHDB-2787


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

Branch: refs/heads/master
Commit: 8b6d0dbd3540cf34d9703526ba0b0b6d3226ff8d
Parents: 928d76a
Author: Tony Sun <to...@cloudant.com>
Authored: Thu Sep 3 15:26:59 2015 -0700
Committer: Tony Sun <to...@cloudant.com>
Committed: Thu Sep 3 15:26:59 2015 -0700

----------------------------------------------------------------------
 src/mango_idx_view.erl | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/8b6d0dbd/src/mango_idx_view.erl
----------------------------------------------------------------------
diff --git a/src/mango_idx_view.erl b/src/mango_idx_view.erl
index a313f56..cc5bcb3 100644
--- a/src/mango_idx_view.erl
+++ b/src/mango_idx_view.erl
@@ -112,7 +112,7 @@ is_usable(Idx, Selector) ->
     % a member of the indexable fields of the selector.
     Columns = columns(Idx),
     Fields = indexable_fields(Selector),
-    lists:member(hd(Columns), Fields) and not is_text_search(Selector).
+    lists:member(hd(Columns), Fields) andalso not is_text_search(Selector).
 
 
 is_text_search({[]}) ->
@@ -121,7 +121,7 @@ is_text_search({[{<<"$default">>, _}]}) ->
     true;
 is_text_search({[{_Field, Cond}]}) when is_list(Cond) ->
     lists:foldl(fun(C, Exists) ->
-        Exists or is_text_search(C)
+        Exists orelse is_text_search(C)
     end, false, Cond);
 is_text_search({[{_Field, Cond}]}) when is_tuple(Cond) ->
     is_text_search(Cond);


[20/26] couchdb-mango git commit: Return 503 if dreyfus service does not exist

Posted by to...@apache.org.
Return 503 if dreyfus service does not exist

References to text will throw a 503 if the dreyfus_index module
does not exist.

COUCHDB-2787


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

Branch: refs/heads/master
Commit: 6100a0b68956fdea9a5ab06f3c0cfc275320542b
Parents: 838c632
Author: Tony Sun <to...@cloudant.com>
Authored: Wed Sep 2 18:51:40 2015 -0700
Committer: Tony Sun <to...@cloudant.com>
Committed: Wed Sep 2 23:34:08 2015 -0700

----------------------------------------------------------------------
 src/mango_cursor.erl                   | 10 ++++++----
 src/mango_error.erl                    |  6 ++++++
 src/mango_idx.erl                      | 30 +++++++++++++++++++++++------
 src/mango_util.erl                     | 18 ++++++++++++++++-
 test/01-index-crud-test.py             |  2 +-
 test/04-key-tests.py                   |  2 +-
 test/06-basic-text-test.py             |  8 ++++----
 test/06-text-default-field-test.py     |  2 +-
 test/07-text-custom-field-list-test.py |  2 +-
 test/08-text-limit-test.py             |  2 +-
 10 files changed, 62 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/6100a0b6/src/mango_cursor.erl
----------------------------------------------------------------------
diff --git a/src/mango_cursor.erl b/src/mango_cursor.erl
index 545a863..d73761e 100644
--- a/src/mango_cursor.erl
+++ b/src/mango_cursor.erl
@@ -123,10 +123,12 @@ group_indexes_by_type(Indexes) ->
     % used to service this query. This is so that we
     % don't suddenly switch indexes for existing client
     % queries.
-    CursorModules = [
-        mango_cursor_view,
-        mango_cursor_text
-    ],
+    CursorModules = case mango_util:module_exists(dreyfus_index) of
+        true ->
+            [mango_cursor_view, mango_cursor_text];
+        false ->
+            [mango_cursor_view]
+    end,
     lists:flatmap(fun(CMod) ->
         case dict:find(CMod, IdxDict) of
             {ok, CModIndexes} ->

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/6100a0b6/src/mango_error.erl
----------------------------------------------------------------------
diff --git a/src/mango_error.erl b/src/mango_error.erl
index 6ad76bb..4704261 100644
--- a/src/mango_error.erl
+++ b/src/mango_error.erl
@@ -134,6 +134,12 @@ info(mango_idx, {index_not_implemented, IndexName}) ->
         <<"index_not_implemented">>,
         fmt("~s", [IndexName])
     };
+info(mango_idx, {index_service_unavailable, IndexName}) ->
+    {
+        503,
+        <<"required index service unavailable">>,
+        fmt("~s", [IndexName])
+    };
 
 info(mango_idx_view, {invalid_index_json, BadIdx}) ->
     {

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/6100a0b6/src/mango_idx.erl
----------------------------------------------------------------------
diff --git a/src/mango_idx.erl b/src/mango_idx.erl
index 71a55a9..6f73af1 100644
--- a/src/mango_idx.erl
+++ b/src/mango_idx.erl
@@ -166,8 +166,12 @@ from_ddoc(Db, {Props}) ->
         _ ->
             ?MANGO_ERROR(invalid_query_ddoc_language)
     end,
-
-    IdxMods = [mango_idx_view, mango_idx_text],
+    IdxMods = case mango_util:module_exists(dreyfus_index) of
+        true ->
+            [mango_idx_view, mango_idx_text];
+        false ->
+            [mango_idx_view]
+    end,
     Idxs = lists:flatmap(fun(Mod) -> Mod:from_ddoc({Props}) end, IdxMods),
     lists:map(fun(Idx) ->
         Idx#idx{
@@ -243,7 +247,12 @@ cursor_mod(#idx{type = <<"json">>}) ->
 cursor_mod(#idx{def = all_docs, type= <<"special">>}) ->
     mango_cursor_view;
 cursor_mod(#idx{type = <<"text">>}) ->
-    mango_cursor_text.
+    case mango_util:module_exists(dreyfus_index) of
+        true ->
+            mango_cursor_text;
+        false ->
+            ?MANGO_ERROR({index_service_unavailable, <<"text">>})
+    end.
 
 
 idx_mod(#idx{type = <<"json">>}) ->
@@ -251,7 +260,12 @@ idx_mod(#idx{type = <<"json">>}) ->
 idx_mod(#idx{type = <<"special">>}) ->
     mango_idx_special;
 idx_mod(#idx{type = <<"text">>}) ->
-    mango_idx_text.
+    case mango_util:module_exists(dreyfus_index) of
+        true ->
+            mango_idx_text;
+        false ->
+            ?MANGO_ERROR({index_service_unavailable, <<"text">>})
+    end.
 
 
 db_to_name(#db{name=Name}) ->
@@ -274,8 +288,12 @@ get_idx_def(Opts) ->
 get_idx_type(Opts) ->
     case proplists:get_value(type, Opts) of
         <<"json">> -> <<"json">>;
-        <<"text">> ->
-            ?MANGO_ERROR({index_not_implemented, <<"text">>});
+        <<"text">> -> case mango_util:module_exists(dreyfus_index) of
+            true ->
+                <<"text">>;
+            false ->
+                ?MANGO_ERROR({index_service_unavailable, <<"text">>})
+            end;
         %<<"geo">> -> <<"geo">>;
         undefined -> <<"json">>;
         BadType ->

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/6100a0b6/src/mango_util.erl
----------------------------------------------------------------------
diff --git a/src/mango_util.erl b/src/mango_util.erl
index 94265cd..553535d 100644
--- a/src/mango_util.erl
+++ b/src/mango_util.erl
@@ -42,7 +42,9 @@
 
     parse_field/1,
 
-    cached_re/2
+    cached_re/2,
+
+    module_exists/1
 ]).
 
 
@@ -395,6 +397,20 @@ check_non_empty(Field, Parts) ->
             Parts
     end.
 
+module_exists(Module) ->
+    case is_atom(Module) of
+        true ->
+            try Module:module_info() of
+                _InfoList ->
+                    true
+            catch
+                _:_ ->
+                    false
+            end;
+        false ->
+            false
+    end.
+
 -ifdef(TEST).
 -include_lib("eunit/include/eunit.hrl").
 

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/6100a0b6/test/01-index-crud-test.py
----------------------------------------------------------------------
diff --git a/test/01-index-crud-test.py b/test/01-index-crud-test.py
index 71ea920..021d66e 100644
--- a/test/01-index-crud-test.py
+++ b/test/01-index-crud-test.py
@@ -18,7 +18,7 @@ import unittest
 class IndexCrudTests(mango.DbPerClass):
     @classmethod
     def setUpClass(klass):
-        raise unittest.SkipTest('text index is not supported yet')
+        raise unittest.SkipTest('text index service not available')
         super(KeyTests, klass).setUpClass()
 
     def test_bad_fields(self):

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/6100a0b6/test/04-key-tests.py
----------------------------------------------------------------------
diff --git a/test/04-key-tests.py b/test/04-key-tests.py
index ac0d3ec..5174d0b 100644
--- a/test/04-key-tests.py
+++ b/test/04-key-tests.py
@@ -56,7 +56,7 @@ TEST_DOCS = [
 class KeyTests(mango.DbPerClass):
     @classmethod
     def setUpClass(klass):
-        raise unittest.SkipTest('text index is not supported yet')
+        raise unittest.SkipTest('text index service not available')
         super(KeyTests, klass).setUpClass()
         klass.db.save_docs(TEST_DOCS, w=3)
         klass.db.create_index(["type"], ddoc="view")

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/6100a0b6/test/06-basic-text-test.py
----------------------------------------------------------------------
diff --git a/test/06-basic-text-test.py b/test/06-basic-text-test.py
index b1be671..72a3918 100644
--- a/test/06-basic-text-test.py
+++ b/test/06-basic-text-test.py
@@ -27,14 +27,14 @@ class TextIndexCheckTests(mango.DbPerClass):
             'type': 'text'
         })
         resp = self.db.sess.post(self.db.path("_index"), data=body)
-        assert resp.status_code == 501, resp
+        assert resp.status_code == 503, resp
 
 
 class BasicTextTests(mango.UserDocsTextTests):
 
     @classmethod
     def setUpClass(klass):
-        raise unittest.SkipTest('text index is not supported yet')
+        raise unittest.SkipTest('text index service not available')
 
     def test_simple(self):
         docs = self.db.find({"$text": "Stephanie"})
@@ -433,7 +433,7 @@ class ElemMatchTests(mango.FriendDocsTextTests):
 
     @classmethod
     def setUpClass(klass):
-        raise unittest.SkipTest('text index is not supported yet')
+        raise unittest.SkipTest('text index service not available')
 
     def test_elem_match_non_object(self):
         q = {"bestfriends":{
@@ -568,7 +568,7 @@ class NumStringTests(mango.NumStringDocsTextTests):
 
     @classmethod
     def setUpClass(klass):
-        raise unittest.SkipTest('text index is not supported yet')
+        raise unittest.SkipTest('text index service not available')
 
     def test_floating_point_val(self):
         float_point_string = num_string_docs.DOCS[2]["number_string"]

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/6100a0b6/test/06-text-default-field-test.py
----------------------------------------------------------------------
diff --git a/test/06-text-default-field-test.py b/test/06-text-default-field-test.py
index b0fa911..f4aaf9a 100644
--- a/test/06-text-default-field-test.py
+++ b/test/06-text-default-field-test.py
@@ -20,7 +20,7 @@ class NoDefaultFieldTest(mango.UserDocsTextTests):
 
     @classmethod
     def setUpClass(klass):
-        raise unittest.SkipTest('text not supported')
+        raise unittest.SkipTest('text index service not available')
 
     def test_basic(self):
         docs = self.db.find({"$text": "Ramona"})

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/6100a0b6/test/07-text-custom-field-list-test.py
----------------------------------------------------------------------
diff --git a/test/07-text-custom-field-list-test.py b/test/07-text-custom-field-list-test.py
index c1c96db..8d68a1f 100644
--- a/test/07-text-custom-field-list-test.py
+++ b/test/07-text-custom-field-list-test.py
@@ -18,7 +18,7 @@ class CustomFieldsTest(mango.UserDocsTextTests):
 
     @classmethod
     def setUpClass(klass):
-        raise unittest.SkipTest('text index is not supported yet')
+        raise unittest.SkipTest('text index service not available')
 
     FIELDS = [
         {"name": "favorites.[]", "type": "string"},

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/6100a0b6/test/08-text-limit-test.py
----------------------------------------------------------------------
diff --git a/test/08-text-limit-test.py b/test/08-text-limit-test.py
index 45c0bc4..36bf4a9 100644
--- a/test/08-text-limit-test.py
+++ b/test/08-text-limit-test.py
@@ -18,7 +18,7 @@ class LimitTests(mango.LimitDocsTextTests):
 
     @classmethod
     def setUpClass(klass):
-        raise unittest.SkipTest('text index is not supported yet')
+        raise unittest.SkipTest('text index service not available')
 
     def test_limit_field(self):
         q = {"$or": [{"user_id" : {"$lt" : 10}}, {"filtered_array.[]": 1}]}


[10/26] couchdb-mango git commit: Fix $size operator

Posted by to...@apache.org.
Fix $size operator

The convert function was missing an array reference "[]" in the path.

BugzID: 46731


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

Branch: refs/heads/master
Commit: 85f8a2b607a74b4abf4e78f0fb93b3becff9c0ad
Parents: e80608d
Author: Tony Sun <to...@cloudant.com>
Authored: Tue Aug 25 13:28:32 2015 -0700
Committer: Tony Sun <to...@cloudant.com>
Committed: Tue Aug 25 13:28:32 2015 -0700

----------------------------------------------------------------------
 src/mango_selector_text.erl | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/85f8a2b6/src/mango_selector_text.erl
----------------------------------------------------------------------
diff --git a/src/mango_selector_text.erl b/src/mango_selector_text.erl
index 5eb237f..b7d78e4 100644
--- a/src/mango_selector_text.erl
+++ b/src/mango_selector_text.erl
@@ -71,7 +71,7 @@ convert(Path, {[{<<"$all">>, Args}]}) ->
         _ ->
             % Otherwise the $all operator is equivalent to an $and
             % operator so we treat it as such.
-            convert([<<"[]">>| Path], {[{<<"$and">>, Args}]})
+            convert([<<"[]">> | Path], {[{<<"$and">>, Args}]})
     end;
 
 % The $elemMatch Lucene query is not an exact translation
@@ -151,7 +151,7 @@ convert(Path, {[{<<"$regex">>, _}]}) ->
     field_exists_query(Path, "string");
 
 convert(Path, {[{<<"$size">>, Arg}]}) ->
-    {op_field, {make_field(Path, length), value_str(Arg)}};
+    {op_field, {make_field([<<"[]">> | Path], length), value_str(Arg)}};
 
 % All other operators are internal assertion errors for
 % matching because we either should've removed them during


[26/26] couchdb-mango git commit: Whitespace

Posted by to...@apache.org.
Whitespace


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

Branch: refs/heads/master
Commit: 1de64eabbf9af6a56562acdf3b71fa0c4c98fd0f
Parents: 17e4abf
Author: Tony Sun <to...@cloudant.com>
Authored: Tue Sep 8 11:22:03 2015 -0700
Committer: Tony Sun <to...@cloudant.com>
Committed: Tue Sep 8 11:22:03 2015 -0700

----------------------------------------------------------------------
 src/mango_cursor_text.erl              | 1 -
 src/mango_error.erl                    | 2 +-
 test/01-index-crud-test.py             | 4 ++--
 test/07-text-custom-field-list-test.py | 2 +-
 test/literal_gen.py                    | 2 +-
 5 files changed, 5 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/1de64eab/src/mango_cursor_text.erl
----------------------------------------------------------------------
diff --git a/src/mango_cursor_text.erl b/src/mango_cursor_text.erl
index 971d153..847b04c 100644
--- a/src/mango_cursor_text.erl
+++ b/src/mango_cursor_text.erl
@@ -301,4 +301,3 @@ get_json_docs(DbName, Hits) ->
                 {Sort, not_found}
         end
     end, Hits).
-

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/1de64eab/src/mango_error.erl
----------------------------------------------------------------------
diff --git a/src/mango_error.erl b/src/mango_error.erl
index 9b7ae82..f0a8ee2 100644
--- a/src/mango_error.erl
+++ b/src/mango_error.erl
@@ -58,7 +58,7 @@ info(mango_cursor_text, multiple_text_indexes) ->
         <<"multiple_text_indexes">>,
         <<"You must specify an index with the `use_index` parameter.">>
     };
-info(mango_cursor_text, {text_search_error, {error, {bad_request, Msg}}}) 
+info(mango_cursor_text, {text_search_error, {error, {bad_request, Msg}}})
         when is_binary(Msg) ->
     {
         400,

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/1de64eab/test/01-index-crud-test.py
----------------------------------------------------------------------
diff --git a/test/01-index-crud-test.py b/test/01-index-crud-test.py
index 021d66e..24aa99d 100644
--- a/test/01-index-crud-test.py
+++ b/test/01-index-crud-test.py
@@ -227,7 +227,7 @@ class IndexCrudTests(mango.DbPerClass):
             assert e.response.status_code == 404
         else:
             raise AssertionError("bad index delete")
-    
+
     @unittest.skip
     def test_create_text_idx(self):
         fields = [
@@ -246,7 +246,7 @@ class IndexCrudTests(mango.DbPerClass):
             ]
             return
         raise AssertionError("index not created")
-    
+
     @unittest.skip
     def test_create_bad_text_idx(self):
         bad_fields = [

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/1de64eab/test/07-text-custom-field-list-test.py
----------------------------------------------------------------------
diff --git a/test/07-text-custom-field-list-test.py b/test/07-text-custom-field-list-test.py
index 8d68a1f..f060d79 100644
--- a/test/07-text-custom-field-list-test.py
+++ b/test/07-text-custom-field-list-test.py
@@ -65,7 +65,7 @@ class CustomFieldsTest(mango.UserDocsTextTests):
         docs = self.db.find({"location.state": "New Hampshire"})
         assert len(docs) == 1
         assert docs[0]["user_id"] == 10
-    
+
     # Since our FIELDS list only includes "name\\.first", we should
     # get an error when we try to search for "name.first", since the index
     # for that field does not exist.

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/1de64eab/test/literal_gen.py
----------------------------------------------------------------------
diff --git a/test/literal_gen.py b/test/literal_gen.py
index 7cf60dd..cf46017 100644
--- a/test/literal_gen.py
+++ b/test/literal_gen.py
@@ -14,7 +14,7 @@ import random
 from string import digits, hexdigits
 
 def joiner(*items):
-    return ''.join(item() for item in items)  
+    return ''.join(item() for item in items)
 
 def roll(item, n1, n2=None):
     n2 = n2 or n1


[09/26] couchdb-mango git commit: List text indexes correctly

Posted by to...@apache.org.
List text indexes correctly

Text indexes are created in the form of {"name": "fieldname",
"type":"datatype"}. This differs from view based indexes that
are in the form of {"field":"sortdirection"}. When presenting
the text index fields, we display for each field "fieldname":"datatype".

BugzID:46012


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

Branch: refs/heads/master
Commit: cdc9fe5ca09ca3a05e250f881382be6d4f809c9b
Parents: 5df74ff
Author: Tony Sun <to...@cloudant.com>
Authored: Tue Aug 25 13:15:47 2015 -0700
Committer: Tony Sun <to...@cloudant.com>
Committed: Tue Aug 25 13:24:04 2015 -0700

----------------------------------------------------------------------
 src/mango_idx_text.erl     | 12 ++++++++++--
 test/01-index-crud-test.py | 18 ++++++++++++++++++
 2 files changed, 28 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/cdc9fe5c/src/mango_idx_text.erl
----------------------------------------------------------------------
diff --git a/src/mango_idx_text.erl b/src/mango_idx_text.erl
index 507e0c2..cce978e 100644
--- a/src/mango_idx_text.erl
+++ b/src/mango_idx_text.erl
@@ -139,13 +139,21 @@ def_to_json([]) ->
 def_to_json([{<<"fields">>, <<"all_fields">>} | Rest]) ->
     [{<<"fields">>, []} | def_to_json(Rest)];
 def_to_json([{fields, Fields} | Rest]) ->
-    [{<<"fields">>, mango_sort:to_json(Fields)} | def_to_json(Rest)];
+    [{<<"fields">>, fields_to_json(Fields)} | def_to_json(Rest)];
 def_to_json([{<<"fields">>, Fields} | Rest]) ->
-    [{<<"fields">>, mango_sort:to_json(Fields)} | def_to_json(Rest)];
+    [{<<"fields">>, fields_to_json(Fields)} | def_to_json(Rest)];
 def_to_json([{Key, Value} | Rest]) ->
     [{Key, Value} | def_to_json(Rest)].
 
 
+fields_to_json([]) ->
+    [];
+fields_to_json([{[{<<"name">>, Name}, {<<"type">>, Type}]} | Rest]) ->
+    [{[{Name, Type}]} | fields_to_json(Rest)];
+fields_to_json([{[{<<"type">>, Type}, {<<"name">>, Name}]} | Rest]) ->
+    [{[{Name, Type}]} | fields_to_json(Rest)].
+
+
 opts() ->
     [
         {<<"default_analyzer">>, [

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/cdc9fe5c/test/01-index-crud-test.py
----------------------------------------------------------------------
diff --git a/test/01-index-crud-test.py b/test/01-index-crud-test.py
index 1d73a78..31e0b08 100644
--- a/test/01-index-crud-test.py
+++ b/test/01-index-crud-test.py
@@ -223,6 +223,24 @@ class IndexCrudTests(mango.DbPerClass):
         else:
             raise AssertionError("bad index delete")
 
+    def test_create_text_idx(self):
+        fields = [
+            {"name":"stringidx", "type" : "string"},
+            {"name":"booleanidx", "type": "boolean"}
+        ]
+        ret = self.db.create_text_index(fields=fields, name="text_idx_01")
+        assert ret is True
+        for idx in self.db.list_indexes():
+            if idx["name"] != "text_idx_01":
+                continue
+            print idx["def"]
+            assert idx["def"]["fields"] == [
+                {"stringidx": "string"},
+                {"booleanidx": "boolean"}
+            ]
+            return
+        raise AssertionError("index not created")
+
     def test_limit_skip_index(self):
         fields = ["field1"]
         ret = self.db.create_index(fields, name="idx_01")


[12/26] couchdb-mango git commit: Correctly choose index type

Posted by to...@apache.org.
Correctly choose index type

When users specify "$text" in the selector, json indexes should not be
used satisfy the query. We check the list of fields and look for
"$default". This implies that "$text" was used in the selector and
filter out all json indexes.

BugzId: 46498


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

Branch: refs/heads/master
Commit: f481b566881a7e7effd86bf0449b487789ad93ed
Parents: a814fe7
Author: Tony Sun <to...@cloudant.com>
Authored: Tue Aug 25 13:44:47 2015 -0700
Committer: Tony Sun <to...@cloudant.com>
Committed: Tue Aug 25 13:44:47 2015 -0700

----------------------------------------------------------------------
 src/mango_idx_view.erl          | 20 +++++++++++++++++++-
 test/05-index-selection-test.py |  8 ++++++++
 2 files changed, 27 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/f481b566/src/mango_idx_view.erl
----------------------------------------------------------------------
diff --git a/src/mango_idx_view.erl b/src/mango_idx_view.erl
index ce0b206..a313f56 100644
--- a/src/mango_idx_view.erl
+++ b/src/mango_idx_view.erl
@@ -112,7 +112,25 @@ is_usable(Idx, Selector) ->
     % a member of the indexable fields of the selector.
     Columns = columns(Idx),
     Fields = indexable_fields(Selector),
-    lists:member(hd(Columns), Fields).
+    lists:member(hd(Columns), Fields) and not is_text_search(Selector).
+
+
+is_text_search({[]}) ->
+    false;
+is_text_search({[{<<"$default">>, _}]}) ->
+    true;
+is_text_search({[{_Field, Cond}]}) when is_list(Cond) ->
+    lists:foldl(fun(C, Exists) ->
+        Exists or is_text_search(C)
+    end, false, Cond);
+is_text_search({[{_Field, Cond}]}) when is_tuple(Cond) ->
+    is_text_search(Cond);
+is_text_search({[{_Field, _Cond}]}) ->
+    false;
+%% we reached values, which should always be false
+is_text_search(Val)
+        when is_number(Val); is_boolean(Val); is_binary(Val)->
+    false.
 
 
 start_key([]) ->

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/f481b566/test/05-index-selection-test.py
----------------------------------------------------------------------
diff --git a/test/05-index-selection-test.py b/test/05-index-selection-test.py
index 856e924..5934f91 100644
--- a/test/05-index-selection-test.py
+++ b/test/05-index-selection-test.py
@@ -32,6 +32,14 @@ class IndexSelectionTests(mango.UserDocsTests):
             }, explain=True)
         assert resp["index"]["type"] == "json"
 
+    def test_with_text(self):
+        resp = self.db.find({
+                "$text" : "Stephanie",
+                "name.first": "Stephanie",
+                "name.last": "This doesn't have to match anything."
+            }, explain=True)
+        assert resp["index"]["type"] == "text"
+
     @unittest.skip
     def test_no_view_index(self):
         resp = self.db.find({"name.first": "Ohai!"}, explain=True)


[06/26] couchdb-mango git commit: Fix field_exists_query

Posted by to...@apache.org.
Fix field_exists_query

The mango_selector:field_exists_query/2 was incorrectly returning
the query. This change fixes this issue and consequently fixes operators
that depended on this function such as $regex, $mod, and $type.

BugzId:45970


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

Branch: refs/heads/master
Commit: 5df74ffdc398502a7c097c709fa86d056a99b5ab
Parents: 4f05552
Author: Tony Sun <to...@cloudant.com>
Authored: Tue Aug 25 12:04:49 2015 -0700
Committer: Tony Sun <to...@cloudant.com>
Committed: Tue Aug 25 13:24:03 2015 -0700

----------------------------------------------------------------------
 src/mango_selector_text.erl | 6 +++++-
 test/06-basic-text-test.py  | 9 +++++++++
 2 files changed, 14 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/5df74ffd/src/mango_selector_text.erl
----------------------------------------------------------------------
diff --git a/src/mango_selector_text.erl b/src/mango_selector_text.erl
index 24d4ad1..9402cc2 100644
--- a/src/mango_selector_text.erl
+++ b/src/mango_selector_text.erl
@@ -143,6 +143,10 @@ convert(Path, {[{<<"$type">>, _}]}) ->
 convert(Path, {[{<<"$mod">>, _}]}) ->
     field_exists_query(Path, "number");
 
+% The lucene regular expression engine does not use java's regex engine but
+% instead a custom implementation. The syntax is therefore different, so we do
+% would get different behavior than our view indexes. To be consistent, we will
+% simply return docs for fields that exist and then run our match filter.
 convert(Path, {[{<<"$regex">>, _}]}) ->
     field_exists_query(Path, "string");
 
@@ -260,7 +264,7 @@ field_exists_query(Path) ->
 
 
 field_exists_query(Path, Type) ->
-    {op_fieldname, [path_str(Path), ":", Type]}.
+    {op_fieldname, {[path_str(Path), ":"], Type}}.
 
 
 path_str(Path) ->

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/5df74ffd/test/06-basic-text-test.py
----------------------------------------------------------------------
diff --git a/test/06-basic-text-test.py b/test/06-basic-text-test.py
index 670fad5..28538ad 100644
--- a/test/06-basic-text-test.py
+++ b/test/06-basic-text-test.py
@@ -395,6 +395,15 @@ class BasicTextTests(mango.UserDocsTextTests):
         docs = self.db.find(q)
         assert len(docs) == 1
 
+    def test_regex(self):
+        docs = self.db.find({
+                "age": {"$gt": 40},
+                "location.state": {"$regex": "(?i)new.*"}
+            })
+        assert len(docs) == 2
+        assert docs[0]["user_id"] == 2
+        assert docs[1]["user_id"] == 10
+
     # test lucene syntax in $text
 
 


[07/26] couchdb-mango git commit: Fix compilation error

Posted by to...@apache.org.
Fix compilation error


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

Branch: refs/heads/master
Commit: 4f05552d8c7829fed09b451263a1bb7faf4c941c
Parents: 10fcac2
Author: Tony Sun <to...@cloudant.com>
Authored: Tue Aug 25 11:28:10 2015 -0700
Committer: Tony Sun <to...@cloudant.com>
Committed: Tue Aug 25 13:24:03 2015 -0700

----------------------------------------------------------------------
 src/mango_util.erl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/4f05552d/src/mango_util.erl
----------------------------------------------------------------------
diff --git a/src/mango_util.erl b/src/mango_util.erl
index fd572c7..0e06f66 100644
--- a/src/mango_util.erl
+++ b/src/mango_util.erl
@@ -371,7 +371,7 @@ join(Sep, [Item | Rest]) ->
 is_number_string(Value) when is_binary(Value) ->
     is_number_string(binary_to_list(Value));
 is_number_string(Value) when is_list(Value)->
-    case re:run(Subject, ?NUMSTRING) of
+    case re:run(Value, ?NUMSTRING) of
         nomatch ->
             false;
         _ ->


[18/26] couchdb-mango git commit: Remove mango_cursor_text.erl from path if dreyfus does not exist

Posted by to...@apache.org.
Remove mango_cursor_text.erl from path if dreyfus does not exist

We create a new rebar.config.script for mango to rename
mango_cursor_text.erl so that compilation does not fail. If users
want to enable text search, they will manually have to clone
dreyfus and re-add the file (will be in README).

COUCHDB-2787


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

Branch: refs/heads/master
Commit: 805fee5bec5e1a8970503cbae7c1b7c8097d2ad5
Parents: 8d496c1
Author: Tony Sun <to...@cloudant.com>
Authored: Wed Sep 2 11:08:39 2015 -0700
Committer: Tony Sun <to...@cloudant.com>
Committed: Wed Sep 2 11:08:39 2015 -0700

----------------------------------------------------------------------
 rebar.config.script | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/805fee5b/rebar.config.script
----------------------------------------------------------------------
diff --git a/rebar.config.script b/rebar.config.script
new file mode 100644
index 0000000..02604f9
--- /dev/null
+++ b/rebar.config.script
@@ -0,0 +1,27 @@
+% 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.
+
+DreyfusAppFile  = filename:join(filename:dirname(SCRIPT),
+    "../dreyfus/src/dreyfus.app.src"),
+CursorFile = filename:join(filename:dirname(SCRIPT),
+    "src/mango_cursor_text.erl"),
+RenameFile  = filename:join(filename:dirname(SCRIPT),
+    "src/mango_cursor_text.nocompile"),
+
+case filelib:is_regular(DreyfusAppFile) of
+    true ->
+        ok;
+    false ->
+        file:rename(CursorFile, RenameFile)
+end,
+
+CONFIG.
\ No newline at end of file


[13/26] couchdb-mango git commit: Replace element position with brackets

Posted by to...@apache.org.
Replace element position with brackets

To be consistent with view based indexes, we allow the user
to access array elements via position. We convert that position
to [] for the underlying indexed field. For example, myarray.0.1,
would be converted to myarray.[].[]. This converted field will then
be used for the text search. The results will then be filtered by
the match function.

Bugzid: 46268


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

Branch: refs/heads/master
Commit: 460fcd4723a70ba24aee2b0254ba02602260431a
Parents: f481b56
Author: Tony Sun <to...@cloudant.com>
Authored: Wed Aug 26 01:30:27 2015 -0700
Committer: Tony Sun <to...@cloudant.com>
Committed: Wed Aug 26 01:30:27 2015 -0700

----------------------------------------------------------------------
 src/mango_doc.erl           | 47 +++-------------------------------
 src/mango_fields.erl        |  2 +-
 src/mango_selector_text.erl | 54 +++++++++++++++++++++++++++++++++++-----
 src/mango_util.erl          | 47 ++++++++++++++++++++++++++++++++--
 test/06-basic-text-test.py  | 22 ++++++++++++++++
 test/user_docs.py           |  4 ++-
 6 files changed, 122 insertions(+), 54 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/460fcd47/src/mango_doc.erl
----------------------------------------------------------------------
diff --git a/src/mango_doc.erl b/src/mango_doc.erl
index 479a8ad..c22b155 100644
--- a/src/mango_doc.erl
+++ b/src/mango_doc.erl
@@ -22,7 +22,6 @@
 
     get_field/2,
     get_field/3,
-    parse_field/1,
     rem_field/2,
     set_field/3
 ]).
@@ -373,7 +372,7 @@ get_field(Props, Field) ->
 
 
 get_field(Props, Field, Validator) when is_binary(Field) ->
-    {ok, Path} = parse_field(Field),
+    {ok, Path} = mango_util:parse_field(Field),
     get_field(Props, Path, Validator);
 get_field(Props, [], no_validation) ->
     Props;
@@ -411,7 +410,7 @@ get_field(_, [_|_], _) ->
 
 
 rem_field(Props, Field) when is_binary(Field) ->
-    {ok, Path} = parse_field(Field),
+    {ok, Path} = mango_util:parse_field(Field),
     rem_field(Props, Path);
 rem_field({Props}, [Name]) ->
     case lists:keytake(Name, 1, Props) of
@@ -472,7 +471,7 @@ rem_field(_, [_|_]) ->
 
 
 set_field(Props, Field, Value) when is_binary(Field) ->
-    {ok, Path} = parse_field(Field),
+    {ok, Path} = mango_util:parse_field(Field),
     set_field(Props, Path, Value);
 set_field({Props}, [Name], Value) ->
     {lists:keystore(Name, 1, Props, {Name, Value})};
@@ -536,43 +535,3 @@ 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) ->
-    case binary:match(Field, <<"\\">>, []) of
-        nomatch ->
-            % Fast path, no regex required
-            {ok, check_non_empty(Field, binary:split(Field, <<".">>, [global]))};
-        _ ->
-            parse_field_slow(Field)
-    end.
-
-parse_field_slow(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}.
-
-check_non_empty(Field, Parts) ->
-    case lists:member(<<>>, Parts) of
-        true ->
-            ?MANGO_ERROR({invalid_field_name, Field});
-        false ->
-            Parts
-    end.
-
--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/460fcd47/src/mango_fields.erl
----------------------------------------------------------------------
diff --git a/src/mango_fields.erl b/src/mango_fields.erl
index 8b6a00b..2732560 100644
--- a/src/mango_fields.erl
+++ b/src/mango_fields.erl
@@ -35,7 +35,7 @@ extract(Doc, all_fields) ->
     Doc;
 extract(Doc, Fields) ->
     lists:foldl(fun(F, NewDoc) ->
-        {ok, Path} = mango_doc:parse_field(F),
+        {ok, Path} = mango_util:parse_field(F),
         case mango_doc:get_field(Doc, Path) of
             not_found ->
                 NewDoc;

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/460fcd47/src/mango_selector_text.erl
----------------------------------------------------------------------
diff --git a/src/mango_selector_text.erl b/src/mango_selector_text.erl
index b7d78e4..e61f759 100644
--- a/src/mango_selector_text.erl
+++ b/src/mango_selector_text.erl
@@ -25,6 +25,12 @@
 -include("mango.hrl").
 
 
+%% Regex for <<"\\.">>
+-define(PERIOD, {re_pattern,0,0,<<69,82,67,80,57,0,0,0,0,0,0,0,2,0,0,0,
+0,0,0,0,46,0,0,0,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,93,0,
+5,27,46,84,0,5,0>>}).
+
+
 convert(Object) ->
     TupleTree = convert([], Object),
     iolist_to_binary(to_query(TupleTree)).
@@ -159,12 +165,35 @@ convert(Path, {[{<<"$size">>, Arg}]}) ->
 convert(_Path, {[{<<"$", _/binary>>=Op, _}]}) ->
     ?MANGO_ERROR({invalid_operator, Op});
 
-% We've hit a field name specifier. We need to break the name
-% into path parts and continue our conversion.
-convert(Path, {[{Field, Cond}]}) ->
-    NewPathParts = re:split(Field, <<"\\.">>),
-    NewPath = lists:reverse(NewPathParts) ++ Path,
-    convert(NewPath, Cond);
+% We've hit a field name specifier. Check if the field name is accessing
+% arrays. Convert occurrences of element position references to .[]. Then we
+% need to break the name into path parts and continue our conversion.
+convert(Path, {[{Field0, Cond}]}) ->
+    {ok, PP0} = case Field0 of
+        <<>> ->
+            {ok, []};
+        _ ->
+            mango_util:parse_field(Field0)
+    end,
+    % Later on, we perform a lucene_escape_user call on the
+    % final Path, which calls parse_field again. Calling the function
+    % twice converts <<"a\\.b">> to [<<"a">>,<<"b">>]. This leads to
+    % an incorrect query since we need [<<"a.b">>]. Without breaking
+    % our escaping mechanism, we simply revert this first parse_field
+    % effect and replace instances of "." to "\\.".
+    PP1 = [re:replace(P, ?PERIOD, <<"\\\\.">>,
+        [global,{return,binary}]) || P <- PP0],
+    {PP2, HasInteger} = replace_array_indexes(PP1, [], false),
+    NewPath = PP2 ++ Path,
+    case HasInteger of
+        true ->
+            OldPath = lists:reverse(PP1, Path),
+            OldParts = convert(OldPath, Cond),
+            NewParts = convert(NewPath, Cond),
+            {op_or, [OldParts, NewParts]};
+        false ->
+            convert(NewPath, Cond)
+    end;
 
 %% For $in
 convert(Path, Val) when is_binary(Val); is_number(Val); is_boolean(Val) ->
@@ -362,3 +391,16 @@ get_sort_types(Field, {[{_, Cond}]}, Acc)  when is_tuple(Cond)->
 
 get_sort_types(_Field, _, Acc)  ->
     Acc.
+
+
+replace_array_indexes([], NewPartsAcc, HasIntAcc) ->
+    {NewPartsAcc, HasIntAcc};
+replace_array_indexes([Part | Rest], NewPartsAcc, HasIntAcc) ->
+    {NewPart, HasInt} = try
+        _ = list_to_integer(binary_to_list(Part)),
+        {<<"[]">>, true}
+    catch _:_ ->
+        {Part, false}
+    end,
+    replace_array_indexes(Rest, [NewPart | NewPartsAcc],
+         HasInt or HasIntAcc).

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/460fcd47/src/mango_util.erl
----------------------------------------------------------------------
diff --git a/src/mango_util.erl b/src/mango_util.erl
index 0e06f66..aa11310 100644
--- a/src/mango_util.erl
+++ b/src/mango_util.erl
@@ -38,7 +38,9 @@
 
     has_suffix/2,
 
-    join/2
+    join/2,
+
+    parse_field/1
 ]).
 
 
@@ -343,7 +345,7 @@ lucene_escape_qv(<<C, Rest/binary>>) ->
 
 
 lucene_escape_user(Field) ->
-    {ok, Path} = mango_doc:parse_field(Field),
+    {ok, Path} = parse_field(Field),
     Escaped = [mango_util:lucene_escape_field(P) || P <- Path],
     iolist_to_binary(join(".", Escaped)).
 
@@ -377,3 +379,44 @@ is_number_string(Value) when is_list(Value)->
         _ ->
             true
     end.
+
+
+parse_field(Field) ->
+    case binary:match(Field, <<"\\">>, []) of
+        nomatch ->
+            % Fast path, no regex required
+            {ok, check_non_empty(Field, binary:split(Field, <<".">>, [global]))};
+        _ ->
+            parse_field_slow(Field)
+    end.
+
+parse_field_slow(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}.
+
+check_non_empty(Field, Parts) ->
+    case lists:member(<<>>, Parts) of
+        true ->
+            ?MANGO_ERROR({invalid_field_name, Field});
+        false ->
+            Parts
+    end.
+
+-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.

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/460fcd47/test/06-basic-text-test.py
----------------------------------------------------------------------
diff --git a/test/06-basic-text-test.py b/test/06-basic-text-test.py
index 28538ad..d44e340 100644
--- a/test/06-basic-text-test.py
+++ b/test/06-basic-text-test.py
@@ -59,6 +59,28 @@ class BasicTextTests(mango.UserDocsTextTests):
         assert docs[0]["name"]["first"] == "Stephanie"
         assert docs[0]["favorites"] == faves
 
+    def test_array_ref(self):
+        docs = self.db.find({"favorites.1": "Python"})
+        assert len(docs) == 4
+        for d in docs:
+            assert "Python" in d["favorites"]
+
+        # Nested Level
+        docs = self.db.find({"favorites.0.2": "Python"})
+        print len(docs)
+        assert len(docs) == 1
+        for d in docs:
+            assert "Python" in d["favorites"][0][2]
+
+    def test_number_ref(self):
+        docs = self.db.find({"11111": "number_field"})
+        assert len(docs) == 1
+        assert docs[0]["11111"] == "number_field"
+
+        docs = self.db.find({"22222.33333": "nested_number_field"})
+        assert len(docs) == 1
+        assert docs[0]["22222"]["33333"] == "nested_number_field"
+
     def test_lt(self):
         docs = self.db.find({"age": {"$lt": 22}})
         assert len(docs) == 0

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/460fcd47/test/user_docs.py
----------------------------------------------------------------------
diff --git a/test/user_docs.py b/test/user_docs.py
index baf83f7..e2f1705 100644
--- a/test/user_docs.py
+++ b/test/user_docs.py
@@ -197,7 +197,9 @@ DOCS = [
             "Erlang",
             "C",
             "Erlang"
-        ]
+        ],
+        "11111": "number_field",
+        "22222": {"33333" : "nested_number_field"}
     },
     {
         "_id": "8e1c90c0-ac18-4832-8081-40d14325bde0",


[05/26] couchdb-mango git commit: Handle extra <<>> when elemMatch normalizes selector

Posted by to...@apache.org.
Handle extra <<>> when elemMatch normalizes selector

When $elemMatch is applied to non-objects such as:
{"results":{"$elemMatch": {"$gte": 80, "$lt": 85}}},
our normalizer modifies the selector to include <<>>. This
causes issues for our path_str and match functions. This
fix addresses those issues by removing the <<>> from the selector
and also not adding a period when a Part is <<>>.

BugzId: 44817


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

Branch: refs/heads/master
Commit: 10fcac2be08f22395935bd938d5dccf5e8d71ac9
Parents: ca5ff7b
Author: Tony Sun <to...@cloudant.com>
Authored: Tue Aug 25 11:26:50 2015 -0700
Committer: Tony Sun <to...@cloudant.com>
Committed: Tue Aug 25 13:23:53 2015 -0700

----------------------------------------------------------------------
 src/mango_selector.erl      | 15 +++++++++++++++
 src/mango_selector_text.erl |  8 +++++++-
 test/06-basic-text-test.py  | 18 ++++++++++++++++++
 test/friend_docs.py         |  4 +++-
 4 files changed, 43 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/10fcac2b/src/mango_selector.erl
----------------------------------------------------------------------
diff --git a/src/mango_selector.erl b/src/mango_selector.erl
index c008a4c..21c55ae 100644
--- a/src/mango_selector.erl
+++ b/src/mango_selector.erl
@@ -411,6 +411,21 @@ match({[{<<"$all">>, Args}]}, Values, _Cmp) when is_list(Values) ->
 match({[{<<"$all">>, _Args}]}, _Values, _Cmp) ->
     false;
 
+%% This is for $elemMatch and possibly $in because of our normalizer.
+%% A selector such as {"field_name": {"$elemMatch": {"$gte": 80, "$lt": 85}}}
+%% gets normalized to:
+%% {[{<<"field_name">>,
+%%     {[{<<"$elemMatch">>,
+%%         {[{<<"$and">>, [
+%%             {[{<<>>,{[{<<"$gte">>,80}]}}]},
+%%             {[{<<>>,{[{<<"$lt">>,85}]}}]}
+%%         ]}]}
+%%     }]}
+%% }]}.
+%% So we filter out the <<>>.
+match({[{<<>>, Arg}]}, Values, Cmp) ->
+    match(Arg, Values, Cmp);
+
 % Matches when any element in values matches the
 % sub-selector Arg.
 match({[{<<"$elemMatch">>, Arg}]}, Values, Cmp) when is_list(Values) ->

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/10fcac2b/src/mango_selector_text.erl
----------------------------------------------------------------------
diff --git a/src/mango_selector_text.erl b/src/mango_selector_text.erl
index 74a4012..24d4ad1 100644
--- a/src/mango_selector_text.erl
+++ b/src/mango_selector_text.erl
@@ -274,7 +274,13 @@ path_str([Part], Acc) ->
     % during recursion of convert.
     [Part | Acc];
 path_str([Part | Rest], Acc) ->
-    path_str(Rest, [<<".">>, Part | Acc]).
+    case Part of
+        % do not append a period if Part is blank
+        <<>> ->
+            path_str(Rest, [Acc]);
+        _ ->
+            path_str(Rest, [<<".">>, Part | Acc])
+    end.
 
 
 type_str(Value) when is_number(Value) ->

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/10fcac2b/test/06-basic-text-test.py
----------------------------------------------------------------------
diff --git a/test/06-basic-text-test.py b/test/06-basic-text-test.py
index baf912b..670fad5 100644
--- a/test/06-basic-text-test.py
+++ b/test/06-basic-text-test.py
@@ -404,6 +404,24 @@ class ElemMatchTests(mango.FriendDocsTextTests):
     def setUpClass(klass):
         raise unittest.SkipTest('text index is not supported yet')
 
+    def test_elem_match_non_object(self):
+        q = {"bestfriends":{
+                "$elemMatch":
+                    {"$eq":"Wolverine", "$eq":"Cyclops"}
+            }
+        }
+        docs = self.db.find(q)
+        print len(docs)
+        assert len(docs) == 1
+        assert docs[0]["bestfriends"] == ["Wolverine", "Cyclops"]
+
+        q = {"results": {"$elemMatch": {"$gte": 80, "$lt": 85}}}
+
+        docs = self.db.find(q)
+        print len(docs)
+        assert len(docs) == 1
+        assert docs[0]["results"] == [82, 85, 88]
+
     def test_elem_match(self):
         q = {"friends": {
                 "$elemMatch":

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/10fcac2b/test/friend_docs.py
----------------------------------------------------------------------
diff --git a/test/friend_docs.py b/test/friend_docs.py
index 8bba58d..ec2c082 100644
--- a/test/friend_docs.py
+++ b/test/friend_docs.py
@@ -461,7 +461,8 @@ DOCS =  [
                 },
                 "type": "personal"
             }
-        ]
+        ],
+        "bestfriends" : ["Wolverine", "Cyclops"]
     },
     {
         "_id": "54a431719faa420a5b4fbeb0",
@@ -530,6 +531,7 @@ DOCS =  [
                 "type": "work"
             }
         ]
+        "results": [ 82, 85, 88 ]
     },
     {
         "_id": "54a4317132f2c81561833259",


[02/26] couchdb-mango git commit: Remove text search limit

Posted by to...@apache.org.
Remove text search limit

Rather than use hardcoded values for text search limit,
we fit the value within the configurable Dreyfus max_limit
parameter.

FogBugzID: 44968


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

Branch: refs/heads/master
Commit: 29eddf0115f4a73d920acbdcfb59cf232e98448a
Parents: fc1e36f
Author: Tony Sun <to...@cloudant.com>
Authored: Tue Aug 25 10:12:05 2015 -0700
Committer: Tony Sun <to...@cloudant.com>
Committed: Tue Aug 25 10:12:05 2015 -0700

----------------------------------------------------------------------
 src/mango_cursor_text.erl  | 17 +++++++----------
 test/08-text-limit-test.py |  9 +++++----
 2 files changed, 12 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/29eddf01/src/mango_cursor_text.erl
----------------------------------------------------------------------
diff --git a/src/mango_cursor_text.erl b/src/mango_cursor_text.erl
index c774c82..ec83240 100644
--- a/src/mango_cursor_text.erl
+++ b/src/mango_cursor_text.erl
@@ -49,10 +49,8 @@ create(Db, Indexes, Selector, Opts0) ->
 
     Opts = unpack_bookmark(Db#db.name, Opts0),
 
-    % Limit the result set size to 50 for Clouseau's
-    % sake. We may want to revisit this.
-    Limit0 = couch_util:get_value(limit, Opts, 50),
-    Limit = if Limit0 < 50 -> Limit0; true -> 50 end,
+    DreyfusLimit = get_dreyfus_limit(),
+    Limit = erlang:min(DreyfusLimit, couch_util:get_value(limit, Opts, 50)),
     Skip = couch_util:get_value(skip, Opts, 0),
     Fields = couch_util:get_value(fields, Opts, all_fields),
 
@@ -282,12 +280,11 @@ update_query_args(CAcc) ->
 
 
 get_limit(CAcc) ->
-    Total = CAcc#cacc.limit + CAcc#cacc.skip,
-    if
-        Total < 25 -> 25;
-        Total > 100 -> 100;
-        true -> Total
-    end.
+    erlang:min(get_dreyfus_limit(), CAcc#cacc.limit + CAcc#cacc.skip).
+
+
+get_dreyfus_limit() ->
+    list_to_integer(config:get("dreyfus", "max_limit", "200")).
 
 
 get_json_docs(DbName, Hits) ->

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/29eddf01/test/08-text-limit-test.py
----------------------------------------------------------------------
diff --git a/test/08-text-limit-test.py b/test/08-text-limit-test.py
index 8478773..45c0bc4 100644
--- a/test/08-text-limit-test.py
+++ b/test/08-text-limit-test.py
@@ -48,11 +48,12 @@ class LimitTests(mango.LimitDocsTextTests):
 
     # We reach our cap here of 50
     def test_limit_field5(self):
-        q = {"$or": [{"user_id" : {"$lt" : 100}}, {"filtered_array.[]": 1}]}
-        docs = self.db.find(q, limit=55)
-        assert len(docs) == 50
+        q = {"age": {"$exists": True}}
+        docs = self.db.find(q, limit=250)
+        print len(docs)
+        assert len(docs) == 75
         for d in docs:
-            assert d["user_id"] < 100
+            assert d["age"] < 100
 
     def test_limit_skip_field1(self):
         q = {"$or": [{"user_id" : {"$lt" : 100}}, {"filtered_array.[]": 1}]}


[19/26] couchdb-mango git commit: Modify tests for skip

Posted by to...@apache.org.
Modify tests for skip

COUCHDB-2787


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

Branch: refs/heads/master
Commit: 838c6329015254e0f6ffaf1e99b6718950971559
Parents: 805fee5
Author: Tony Sun <to...@cloudant.com>
Authored: Wed Sep 2 13:30:28 2015 -0700
Committer: Tony Sun <to...@cloudant.com>
Committed: Wed Sep 2 13:30:28 2015 -0700

----------------------------------------------------------------------
 test/01-index-crud-test.py      | 13 ++++++++++---
 test/05-index-selection-test.py |  3 ++-
 test/06-basic-text-test.py      |  5 +++++
 test/09-text-sort-test.py       |  2 +-
 test/friend_docs.py             |  2 +-
 5 files changed, 19 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/838c6329/test/01-index-crud-test.py
----------------------------------------------------------------------
diff --git a/test/01-index-crud-test.py b/test/01-index-crud-test.py
index bd41516..71ea920 100644
--- a/test/01-index-crud-test.py
+++ b/test/01-index-crud-test.py
@@ -13,9 +13,14 @@
 import random
 
 import mango
-
+import unittest
 
 class IndexCrudTests(mango.DbPerClass):
+    @classmethod
+    def setUpClass(klass):
+        raise unittest.SkipTest('text index is not supported yet')
+        super(KeyTests, klass).setUpClass()
+
     def test_bad_fields(self):
         bad_fields = [
             None,
@@ -222,7 +227,8 @@ class IndexCrudTests(mango.DbPerClass):
             assert e.response.status_code == 404
         else:
             raise AssertionError("bad index delete")
-
+    
+    @unittest.skip
     def test_create_text_idx(self):
         fields = [
             {"name":"stringidx", "type" : "string"},
@@ -240,7 +246,8 @@ class IndexCrudTests(mango.DbPerClass):
             ]
             return
         raise AssertionError("index not created")
-
+    
+    @unittest.skip
     def test_create_bad_text_idx(self):
         bad_fields = [
             True,

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/838c6329/test/05-index-selection-test.py
----------------------------------------------------------------------
diff --git a/test/05-index-selection-test.py b/test/05-index-selection-test.py
index 5934f91..4ded668 100644
--- a/test/05-index-selection-test.py
+++ b/test/05-index-selection-test.py
@@ -32,6 +32,7 @@ class IndexSelectionTests(mango.UserDocsTests):
             }, explain=True)
         assert resp["index"]["type"] == "json"
 
+    @unittest.skip
     def test_with_text(self):
         resp = self.db.find({
                 "$text" : "Stephanie",
@@ -76,7 +77,7 @@ class IndexSelectionTests(mango.UserDocsTests):
 class MultiTextIndexSelectionTests(mango.UserDocsTests):
     @classmethod
     def setUpClass(klass):
-        raise unittest.SkipTest('text index is not supported yet')
+        raise unittest.SkipTest('text index service is not available')
         super(MultiTextIndexSelectionTests, klass).setUpClass()
         klass.db.create_text_index(ddoc="foo", analyzer="keyword")
         klass.db.create_text_index(ddoc="bar", analyzer="email")

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/838c6329/test/06-basic-text-test.py
----------------------------------------------------------------------
diff --git a/test/06-basic-text-test.py b/test/06-basic-text-test.py
index d44e340..b1be671 100644
--- a/test/06-basic-text-test.py
+++ b/test/06-basic-text-test.py
@@ -565,6 +565,11 @@ class ElemMatchTests(mango.FriendDocsTextTests):
 
 # Test numeric strings for $text
 class NumStringTests(mango.NumStringDocsTextTests):
+
+    @classmethod
+    def setUpClass(klass):
+        raise unittest.SkipTest('text index is not supported yet')
+
     def test_floating_point_val(self):
         float_point_string = num_string_docs.DOCS[2]["number_string"]
         q = {"$text": float_point_string}

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/838c6329/test/09-text-sort-test.py
----------------------------------------------------------------------
diff --git a/test/09-text-sort-test.py b/test/09-text-sort-test.py
index da58304..7bdf54a 100644
--- a/test/09-text-sort-test.py
+++ b/test/09-text-sort-test.py
@@ -17,7 +17,7 @@ class SortTests(mango.UserDocsTextTests):
 
     @classmethod
     def setUpClass(klass):
-        raise unittest.SkipTest('text index is not supported yet')
+        raise unittest.SkipTest('text index service is not available')
 
     def test_number_sort(self):
         q = {"age": {"$gt": 0}}

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/838c6329/test/friend_docs.py
----------------------------------------------------------------------
diff --git a/test/friend_docs.py b/test/friend_docs.py
index ec2c082..e0cf60e 100644
--- a/test/friend_docs.py
+++ b/test/friend_docs.py
@@ -530,7 +530,7 @@ DOCS =  [
                 },
                 "type": "work"
             }
-        ]
+        ],
         "results": [ 82, 85, 88 ]
     },
     {


[16/26] couchdb-mango git commit: improve regex test

Posted by to...@apache.org.
improve regex test


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

Branch: refs/heads/master
Commit: b2f62f1d0f6872be960246461e82845c6fa09e9a
Parents: 97162fd
Author: Tony Sun <to...@cloudant.com>
Authored: Wed Aug 26 01:53:49 2015 -0700
Committer: Tony Sun <to...@cloudant.com>
Committed: Wed Aug 26 01:53:49 2015 -0700

----------------------------------------------------------------------
 src/mango_util.erl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/b2f62f1d/src/mango_util.erl
----------------------------------------------------------------------
diff --git a/src/mango_util.erl b/src/mango_util.erl
index 2d25bdc..6b150e7 100644
--- a/src/mango_util.erl
+++ b/src/mango_util.erl
@@ -417,6 +417,6 @@ is_number_string_test() ->
     ?assert(is_number_string("-1.0")),
     ?assertNot(is_number_string("hello")),
     ?assertNot(is_number_string("")),
-    ?assertMatch({re_pattern, _, _, _, _}, mochiglobal:get(mango_numstring_re)).
+    ?assertMatch({match, _}, re:run("1.0", mochiglobal:get(mango_numstring_re))).
 
 -endif.


[21/26] couchdb-mango git commit: Use module_loaded instead of module_info

Posted by to...@apache.org.
Use module_loaded instead of module_info

COUCHDB-2787


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

Branch: refs/heads/master
Commit: 874e8d2a74f83e19aedfd0acb1e562f918844c99
Parents: 6100a0b
Author: Tony Sun <to...@cloudant.com>
Authored: Thu Sep 3 13:01:33 2015 -0700
Committer: Tony Sun <to...@cloudant.com>
Committed: Thu Sep 3 13:01:33 2015 -0700

----------------------------------------------------------------------
 src/mango_cursor.erl |  2 +-
 src/mango_idx.erl    |  8 ++++----
 src/mango_util.erl   | 17 +----------------
 3 files changed, 6 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/874e8d2a/src/mango_cursor.erl
----------------------------------------------------------------------
diff --git a/src/mango_cursor.erl b/src/mango_cursor.erl
index d73761e..6cb7fee 100644
--- a/src/mango_cursor.erl
+++ b/src/mango_cursor.erl
@@ -123,7 +123,7 @@ group_indexes_by_type(Indexes) ->
     % used to service this query. This is so that we
     % don't suddenly switch indexes for existing client
     % queries.
-    CursorModules = case mango_util:module_exists(dreyfus_index) of
+    CursorModules = case module_loaded(dreyfus_index) of
         true ->
             [mango_cursor_view, mango_cursor_text];
         false ->

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/874e8d2a/src/mango_idx.erl
----------------------------------------------------------------------
diff --git a/src/mango_idx.erl b/src/mango_idx.erl
index 6f73af1..56b7fc2 100644
--- a/src/mango_idx.erl
+++ b/src/mango_idx.erl
@@ -166,7 +166,7 @@ from_ddoc(Db, {Props}) ->
         _ ->
             ?MANGO_ERROR(invalid_query_ddoc_language)
     end,
-    IdxMods = case mango_util:module_exists(dreyfus_index) of
+    IdxMods = case module_loaded(dreyfus_index) of
         true ->
             [mango_idx_view, mango_idx_text];
         false ->
@@ -247,7 +247,7 @@ cursor_mod(#idx{type = <<"json">>}) ->
 cursor_mod(#idx{def = all_docs, type= <<"special">>}) ->
     mango_cursor_view;
 cursor_mod(#idx{type = <<"text">>}) ->
-    case mango_util:module_exists(dreyfus_index) of
+    case module_loaded(dreyfus_index) of
         true ->
             mango_cursor_text;
         false ->
@@ -260,7 +260,7 @@ idx_mod(#idx{type = <<"json">>}) ->
 idx_mod(#idx{type = <<"special">>}) ->
     mango_idx_special;
 idx_mod(#idx{type = <<"text">>}) ->
-    case mango_util:module_exists(dreyfus_index) of
+    case module_loaded(dreyfus_index) of
         true ->
             mango_idx_text;
         false ->
@@ -288,7 +288,7 @@ get_idx_def(Opts) ->
 get_idx_type(Opts) ->
     case proplists:get_value(type, Opts) of
         <<"json">> -> <<"json">>;
-        <<"text">> -> case mango_util:module_exists(dreyfus_index) of
+        <<"text">> -> case module_loaded(dreyfus_index) of
             true ->
                 <<"text">>;
             false ->

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/874e8d2a/src/mango_util.erl
----------------------------------------------------------------------
diff --git a/src/mango_util.erl b/src/mango_util.erl
index 553535d..c3513dc 100644
--- a/src/mango_util.erl
+++ b/src/mango_util.erl
@@ -42,9 +42,7 @@
 
     parse_field/1,
 
-    cached_re/2,
-
-    module_exists/1
+    cached_re/2
 ]).
 
 
@@ -397,19 +395,6 @@ check_non_empty(Field, Parts) ->
             Parts
     end.
 
-module_exists(Module) ->
-    case is_atom(Module) of
-        true ->
-            try Module:module_info() of
-                _InfoList ->
-                    true
-            catch
-                _:_ ->
-                    false
-            end;
-        false ->
-            false
-    end.
 
 -ifdef(TEST).
 -include_lib("eunit/include/eunit.hrl").


[17/26] couchdb-mango git commit: Request an EJSON body when opening documents

Posted by to...@apache.org.
Request an EJSON body when opening documents


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

Branch: refs/heads/master
Commit: 8d496c1e8c9b790722385d3af53670999fb99b58
Parents: b2f62f1
Author: Tony Sun <to...@cloudant.com>
Authored: Wed Aug 26 09:35:34 2015 -0700
Committer: Tony Sun <to...@cloudant.com>
Committed: Wed Aug 26 09:35:34 2015 -0700

----------------------------------------------------------------------
 src/mango_util.erl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/8d496c1e/src/mango_util.erl
----------------------------------------------------------------------
diff --git a/src/mango_util.erl b/src/mango_util.erl
index 6b150e7..94265cd 100644
--- a/src/mango_util.erl
+++ b/src/mango_util.erl
@@ -80,7 +80,7 @@
 
 
 open_doc(Db, DocId) ->
-    open_doc(Db, DocId, [deleted]).
+    open_doc(Db, DocId, [deleted, ejson_body]).
 
 
 open_doc(Db, DocId, Options) ->


[15/26] couchdb-mango git commit: add tests

Posted by to...@apache.org.
add tests


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

Branch: refs/heads/master
Commit: 97162fd5d9fcddbdc95495565076066ca091c481
Parents: 7032bf5
Author: Tony Sun <to...@cloudant.com>
Authored: Wed Aug 26 01:52:19 2015 -0700
Committer: Tony Sun <to...@cloudant.com>
Committed: Wed Aug 26 01:52:19 2015 -0700

----------------------------------------------------------------------
 src/mango_util.erl | 12 ++++++++++++
 1 file changed, 12 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/97162fd5/src/mango_util.erl
----------------------------------------------------------------------
diff --git a/src/mango_util.erl b/src/mango_util.erl
index 0e71312..2d25bdc 100644
--- a/src/mango_util.erl
+++ b/src/mango_util.erl
@@ -407,4 +407,16 @@ parse_field_test() ->
     Exception = {mango_error, ?MODULE, {invalid_field_name, <<"a..b">>}},
     ?assertThrow(Exception, parse_field(<<"a..b">>)).
 
+is_number_string_test() ->
+    ?assert(is_number_string("0")),
+    ?assert(is_number_string("1")),
+    ?assert(is_number_string("1.0")),
+    ?assert(is_number_string("1.0E10")),
+    ?assert(is_number_string("0d")),
+    ?assert(is_number_string("-1")),
+    ?assert(is_number_string("-1.0")),
+    ?assertNot(is_number_string("hello")),
+    ?assertNot(is_number_string("")),
+    ?assertMatch({re_pattern, _, _, _, _}, mochiglobal:get(mango_numstring_re)).
+
 -endif.


[22/26] couchdb-mango git commit: Use config:get_integer

Posted by to...@apache.org.
Use config:get_integer

COUCHDB-2787


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

Branch: refs/heads/master
Commit: 928d76ac2c2739a25313e281cfeb1ac485070054
Parents: 874e8d2
Author: Tony Sun <to...@cloudant.com>
Authored: Thu Sep 3 15:26:27 2015 -0700
Committer: Tony Sun <to...@cloudant.com>
Committed: Thu Sep 3 15:26:27 2015 -0700

----------------------------------------------------------------------
 src/mango_cursor_text.erl              |  2 +-
 test/01-index-crud-test.py             |  8 +++---
 test/04-key-tests.py                   |  2 +-
 test/05-index-selection-test.py        |  4 +--
 test/06-basic-text-test.py             | 38 ++++++++++++++---------------
 test/06-text-default-field-test.py     | 18 +++++++-------
 test/07-text-custom-field-list-test.py |  6 ++---
 test/08-text-limit-test.py             |  6 ++---
 test/09-text-sort-test.py              |  6 ++---
 test/mango.py                          |  3 +--
 10 files changed, 46 insertions(+), 47 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/928d76ac/src/mango_cursor_text.erl
----------------------------------------------------------------------
diff --git a/src/mango_cursor_text.erl b/src/mango_cursor_text.erl
index ec83240..971d153 100644
--- a/src/mango_cursor_text.erl
+++ b/src/mango_cursor_text.erl
@@ -284,7 +284,7 @@ get_limit(CAcc) ->
 
 
 get_dreyfus_limit() ->
-    list_to_integer(config:get("dreyfus", "max_limit", "200")).
+    config:get_integer("dreyfus", "max_limit", 200).
 
 
 get_json_docs(DbName, Hits) ->

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/928d76ac/test/01-index-crud-test.py
----------------------------------------------------------------------
diff --git a/test/01-index-crud-test.py b/test/01-index-crud-test.py
index 021d66e..2852a6a 100644
--- a/test/01-index-crud-test.py
+++ b/test/01-index-crud-test.py
@@ -16,10 +16,10 @@ import mango
 import unittest
 
 class IndexCrudTests(mango.DbPerClass):
-    @classmethod
-    def setUpClass(klass):
-        raise unittest.SkipTest('text index service not available')
-        super(KeyTests, klass).setUpClass()
+    # @classmethod
+    # def setUpClass(klass):
+    #     raise unittest.SkipTest('text index service not available')
+    #     super(KeyTests, klass).setUpClass()
 
     def test_bad_fields(self):
         bad_fields = [

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/928d76ac/test/04-key-tests.py
----------------------------------------------------------------------
diff --git a/test/04-key-tests.py b/test/04-key-tests.py
index 5174d0b..9b55c7f 100644
--- a/test/04-key-tests.py
+++ b/test/04-key-tests.py
@@ -56,7 +56,7 @@ TEST_DOCS = [
 class KeyTests(mango.DbPerClass):
     @classmethod
     def setUpClass(klass):
-        raise unittest.SkipTest('text index service not available')
+        # raise unittest.SkipTest('text index service not available')
         super(KeyTests, klass).setUpClass()
         klass.db.save_docs(TEST_DOCS, w=3)
         klass.db.create_index(["type"], ddoc="view")

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/928d76ac/test/05-index-selection-test.py
----------------------------------------------------------------------
diff --git a/test/05-index-selection-test.py b/test/05-index-selection-test.py
index 4ded668..375085f 100644
--- a/test/05-index-selection-test.py
+++ b/test/05-index-selection-test.py
@@ -19,7 +19,7 @@ class IndexSelectionTests(mango.UserDocsTests):
     @classmethod
     def setUpClass(klass):
         super(IndexSelectionTests, klass).setUpClass()
-        # user_docs.add_text_indexes(klass.db, {})
+        user_docs.add_text_indexes(klass.db, {})
 
     def test_basic(self):
         resp = self.db.find({"name.last": "A last name"}, explain=True)
@@ -77,7 +77,7 @@ class IndexSelectionTests(mango.UserDocsTests):
 class MultiTextIndexSelectionTests(mango.UserDocsTests):
     @classmethod
     def setUpClass(klass):
-        raise unittest.SkipTest('text index service is not available')
+        # raise unittest.SkipTest('text index service is not available')
         super(MultiTextIndexSelectionTests, klass).setUpClass()
         klass.db.create_text_index(ddoc="foo", analyzer="keyword")
         klass.db.create_text_index(ddoc="bar", analyzer="email")

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/928d76ac/test/06-basic-text-test.py
----------------------------------------------------------------------
diff --git a/test/06-basic-text-test.py b/test/06-basic-text-test.py
index 72a3918..593e6d7 100644
--- a/test/06-basic-text-test.py
+++ b/test/06-basic-text-test.py
@@ -17,24 +17,24 @@ import user_docs
 import num_string_docs
 
 
-class TextIndexCheckTests(mango.DbPerClass):
+# class TextIndexCheckTests(mango.DbPerClass):
 
-    def test_create_text_index(self):
-        body = json.dumps({
-            'index': {
-                'fields': 'test'
-            },
-            'type': 'text'
-        })
-        resp = self.db.sess.post(self.db.path("_index"), data=body)
-        assert resp.status_code == 503, resp
+#     def test_create_text_index(self):
+#         body = json.dumps({
+#             'index': {
+#                 'fields': 'test'
+#             },
+#             'type': 'text'
+#         })
+#         resp = self.db.sess.post(self.db.path("_index"), data=body)
+#         assert resp.status_code == 503, resp
 
 
 class BasicTextTests(mango.UserDocsTextTests):
 
-    @classmethod
-    def setUpClass(klass):
-        raise unittest.SkipTest('text index service not available')
+    # @classmethod
+    # def setUpClass(klass):
+    #     raise unittest.SkipTest('text index service not available')
 
     def test_simple(self):
         docs = self.db.find({"$text": "Stephanie"})
@@ -431,9 +431,9 @@ class BasicTextTests(mango.UserDocsTextTests):
 
 class ElemMatchTests(mango.FriendDocsTextTests):
 
-    @classmethod
-    def setUpClass(klass):
-        raise unittest.SkipTest('text index service not available')
+    # @classmethod
+    # def setUpClass(klass):
+    #     raise unittest.SkipTest('text index service not available')
 
     def test_elem_match_non_object(self):
         q = {"bestfriends":{
@@ -566,9 +566,9 @@ class ElemMatchTests(mango.FriendDocsTextTests):
 # Test numeric strings for $text
 class NumStringTests(mango.NumStringDocsTextTests):
 
-    @classmethod
-    def setUpClass(klass):
-        raise unittest.SkipTest('text index service not available')
+    # @classmethod
+    # def setUpClass(klass):
+    #     raise unittest.SkipTest('text index service not available')
 
     def test_floating_point_val(self):
         float_point_string = num_string_docs.DOCS[2]["number_string"]

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/928d76ac/test/06-text-default-field-test.py
----------------------------------------------------------------------
diff --git a/test/06-text-default-field-test.py b/test/06-text-default-field-test.py
index f4aaf9a..599cad6 100644
--- a/test/06-text-default-field-test.py
+++ b/test/06-text-default-field-test.py
@@ -18,9 +18,9 @@ class NoDefaultFieldTest(mango.UserDocsTextTests):
 
     DEFAULT_FIELD = False
 
-    @classmethod
-    def setUpClass(klass):
-        raise unittest.SkipTest('text index service not available')
+    # @classmethod
+    # def setUpClass(klass):
+    #     raise unittest.SkipTest('text index service not available')
 
     def test_basic(self):
         docs = self.db.find({"$text": "Ramona"})
@@ -40,9 +40,9 @@ class NoDefaultFieldWithAnalyzer(mango.UserDocsTextTests):
         "analyzer": "keyword"
     }
 
-    @classmethod
-    def setUpClass(klass):
-        raise unittest.SkipTest('text not supported')
+    # @classmethod
+    # def setUpClass(klass):
+    #     raise unittest.SkipTest('text not supported')
 
     def test_basic(self):
         docs = self.db.find({"$text": "Ramona"})
@@ -61,9 +61,9 @@ class DefaultFieldWithCustomAnalyzer(mango.UserDocsTextTests):
         "analyzer": "keyword"
     }
 
-    @classmethod
-    def setUpClass(klass):
-        raise unittest.SkipTest('text not supported')
+    # @classmethod
+    # def setUpClass(klass):
+    #     raise unittest.SkipTest('text not supported')
 
     def test_basic(self):
         docs = self.db.find({"$text": "Ramona"})

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/928d76ac/test/07-text-custom-field-list-test.py
----------------------------------------------------------------------
diff --git a/test/07-text-custom-field-list-test.py b/test/07-text-custom-field-list-test.py
index 8d68a1f..c59c3a2 100644
--- a/test/07-text-custom-field-list-test.py
+++ b/test/07-text-custom-field-list-test.py
@@ -16,9 +16,9 @@ import unittest
 
 class CustomFieldsTest(mango.UserDocsTextTests):
 
-    @classmethod
-    def setUpClass(klass):
-        raise unittest.SkipTest('text index service not available')
+    # @classmethod
+    # def setUpClass(klass):
+    #     raise unittest.SkipTest('text index service not available')
 
     FIELDS = [
         {"name": "favorites.[]", "type": "string"},

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/928d76ac/test/08-text-limit-test.py
----------------------------------------------------------------------
diff --git a/test/08-text-limit-test.py b/test/08-text-limit-test.py
index 36bf4a9..31083ae 100644
--- a/test/08-text-limit-test.py
+++ b/test/08-text-limit-test.py
@@ -16,9 +16,9 @@ import unittest
 
 class LimitTests(mango.LimitDocsTextTests):
 
-    @classmethod
-    def setUpClass(klass):
-        raise unittest.SkipTest('text index service not available')
+    # @classmethod
+    # def setUpClass(klass):
+    #     raise unittest.SkipTest('text index service not available')
 
     def test_limit_field(self):
         q = {"$or": [{"user_id" : {"$lt" : 10}}, {"filtered_array.[]": 1}]}

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/928d76ac/test/09-text-sort-test.py
----------------------------------------------------------------------
diff --git a/test/09-text-sort-test.py b/test/09-text-sort-test.py
index 7bdf54a..c06c680 100644
--- a/test/09-text-sort-test.py
+++ b/test/09-text-sort-test.py
@@ -15,9 +15,9 @@ import unittest
 
 class SortTests(mango.UserDocsTextTests):
 
-    @classmethod
-    def setUpClass(klass):
-        raise unittest.SkipTest('text index service is not available')
+    # @classmethod
+    # def setUpClass(klass):
+    #     raise unittest.SkipTest('text index service is not available')
 
     def test_number_sort(self):
         q = {"age": {"$gt": 0}}

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/928d76ac/test/mango.py
----------------------------------------------------------------------
diff --git a/test/mango.py b/test/mango.py
index 6764ed5..3464b14 100644
--- a/test/mango.py
+++ b/test/mango.py
@@ -33,8 +33,7 @@ class Database(object):
         self.port = port
         self.dbname = dbname
         self.sess = requests.session()
-        if auth is not None:
-            self.sess.auth = auth
+        self.sess.auth = ('adm', 'pass')
         self.sess.headers["Content-Type"] = "application/json"
 
     @property


[04/26] couchdb-mango git commit: Add numeric string tests

Posted by to...@apache.org.
Add numeric string tests

BugzId: 45572


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

Branch: refs/heads/master
Commit: ca5ff7bcb33e6242b3fa4bdafc40955d984ca439
Parents: a8def14
Author: Tony Sun <to...@cloudant.com>
Authored: Tue Aug 25 10:51:22 2015 -0700
Committer: Tony Sun <to...@cloudant.com>
Committed: Tue Aug 25 13:23:52 2015 -0700

----------------------------------------------------------------------
 src/mango_selector_text.erl | 13 +++++++++--
 src/mango_util.erl          | 43 +++++++++++++++++++++++++----------
 test/06-basic-text-test.py  | 30 ++++++++++++++++++++++++
 test/literal_gen.py         | 49 ++++++++++++++++++++++++++++++++++++++++
 test/mango.py               |  8 +++++++
 test/num_string_docs.py     | 49 ++++++++++++++++++++++++++++++++++++++++
 6 files changed, 178 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/ca5ff7bc/src/mango_selector_text.erl
----------------------------------------------------------------------
diff --git a/src/mango_selector_text.erl b/src/mango_selector_text.erl
index 47e25ce..74a4012 100644
--- a/src/mango_selector_text.erl
+++ b/src/mango_selector_text.erl
@@ -45,8 +45,8 @@ convert(Path, {[{<<"$default">>, Arg}]}) ->
 % The $text operator specifies a Lucene syntax query
 % so we just pull it in directly.
 convert(Path, {[{<<"$text">>, Query}]}) when is_binary(Query) ->
-    Term = mango_util:append_quotes(value_str(Query)),
-    {op_field, {make_field(Path, Query), Term}};
+    Value = maybe_append_quotes(value_str(Query)),
+    {op_field, {make_field(Path, Query), Value}};
 
 % The MongoDB docs for $all are super confusing and read more
 % like they screwed up the implementation of this operator
@@ -316,6 +316,15 @@ append_sort_type(RawSortField, Selector) ->
     end.
 
 
+maybe_append_quotes(TextValue) ->
+    case mango_util:is_number_string(TextValue) of
+        true ->
+            <<"\"", TextValue/binary, "\"">>;
+        false ->
+            TextValue
+    end.
+
+
 get_sort_type(Field, Selector) ->
     Types = get_sort_types(Field, Selector, []),
     case lists:usort(Types) of

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/ca5ff7bc/src/mango_util.erl
----------------------------------------------------------------------
diff --git a/src/mango_util.erl b/src/mango_util.erl
index b12c6e9..fd572c7 100644
--- a/src/mango_util.erl
+++ b/src/mango_util.erl
@@ -34,7 +34,7 @@
     lucene_escape_field/1,
     lucene_escape_query_value/1,
     lucene_escape_user/1,
-    append_quotes/1,
+    is_number_string/1,
 
     has_suffix/2,
 
@@ -46,7 +46,33 @@
 -include("mango.hrl").
 
 
-%% https://gist.github.com/cad2d2456c518d878d08
+%% Regex for Floating Point, Hex Floating Point, Nan, and Infinity
+%% Digits = "(\\p{N}+)",
+%% HexDigits = "([0-9a-fA-F]+)",
+%% Exp = "[eE][+-]?" ++ Digits,
+%% FpRegexStr = "[\\x00-\\x20]*" ++ "[+-]?(" ++ "NaN|"
+%%     ++ "Infinity|" ++ "((("
+%%     ++ Digits
+%%     ++ "(\\.)?("
+%%     ++ Digits
+%%     ++ "?)("
+%%     ++ Exp
+%%     ++ ")?)|"
+%%     ++ "(\\.("
+%%     ++ Digits
+%%     ++ ")("
+%%     ++ Exp
+%%     ++ ")?)|"
+%%     ++ "(("
+%%     ++ "(0[xX]"
+%%     ++ HexDigits
+%%     ++ "(\\.)?)|"
+%%     ++ "(0[xX]"
+%%     ++ HexDigits
+%%     ++ "?(\\.)"
+%%     ++ HexDigits
+%%     ++ ")"
+%%     ++ ")[pP][+-]?" ++ Digits ++ "))" ++ "[fFdD]?))" ++ "[\\x00-\\x20]*"
 -define(NUMSTRING, {re_pattern,25,0,<<69,82,67,80,71,3,0,0,0,0,0,0,1,0,0,0,25,0,
 0,0,0,0,0,0,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,93,3,19,77,255,255,
 255,255,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,69,77,0,0,0,0,0,
@@ -342,19 +368,12 @@ join(Sep, [Item | Rest]) ->
     [Item, Sep | join(Sep, Rest)].
 
 
-is_number_string(Subject) ->
+is_number_string(Value) when is_binary(Value) ->
+    is_number_string(binary_to_list(Value));
+is_number_string(Value) when is_list(Value)->
     case re:run(Subject, ?NUMSTRING) of
         nomatch ->
             false;
         _ ->
             true
     end.
-
-
-append_quotes(TextValue) ->
-    case is_number_string(binary_to_list(TextValue)) of
-        true ->
-            <<"\"", TextValue/binary, "\"">>;
-        false ->
-            TextValue
-    end.

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/ca5ff7bc/test/06-basic-text-test.py
----------------------------------------------------------------------
diff --git a/test/06-basic-text-test.py b/test/06-basic-text-test.py
index 08739db..baf912b 100644
--- a/test/06-basic-text-test.py
+++ b/test/06-basic-text-test.py
@@ -14,6 +14,7 @@ import json
 import mango
 import unittest
 import user_docs
+import num_string_docs
 
 
 class TextIndexCheckTests(mango.DbPerClass):
@@ -511,3 +512,32 @@ class ElemMatchTests(mango.FriendDocsTextTests):
         assert len(docs) == 3
         for d in docs:
             assert d["user_id"] in (10, 11,12)
+
+
+# Test numeric strings for $text
+class NumStringTests(mango.NumStringDocsTextTests):
+    def test_floating_point_val(self):
+        float_point_string = num_string_docs.DOCS[2]["number_string"]
+        q = {"$text": float_point_string}
+        docs = self.db.find(q)
+        assert len(docs) == 1
+        assert docs[0]["number_string"] == float_point_string
+
+    def test_hex_floating_point_val(self):
+        hex_float_point_string = num_string_docs.DOCS[3]["number_string"]
+        q = {"$text": hex_float_point_string}
+        docs = self.db.find(q)
+        assert len(docs) == 1
+        assert docs[0]["number_string"] == hex_float_point_string
+
+    def test_nan_val(self):
+        q = {"$text": "NaN"}
+        docs = self.db.find(q)
+        assert len(docs) == 1
+        assert docs[0]["number_string"] == "NaN"
+
+    def test_infinity_val(self):
+        q = {"$text": "Infinity"}
+        docs = self.db.find(q)
+        assert len(docs) == 1
+        assert docs[0]["number_string"] == "Infinity"

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/ca5ff7bc/test/literal_gen.py
----------------------------------------------------------------------
diff --git a/test/literal_gen.py b/test/literal_gen.py
new file mode 100644
index 0000000..7cf60dd
--- /dev/null
+++ b/test/literal_gen.py
@@ -0,0 +1,49 @@
+# 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 random
+from string import digits, hexdigits
+
+def joiner(*items):
+    return ''.join(item() for item in items)  
+
+def roll(item, n1, n2=None):
+    n2 = n2 or n1
+    return lambda: ''.join(item() for _ in xrange(random.randint(n1, n2)))
+
+def rand(collection):
+    return lambda: random.choice(collection)
+
+def floating_point_literal():
+    return joiner(roll(rand(' '), 0, 2),
+            roll(rand('+-'), 0, 1),
+            roll(rand(digits), 2, 20),
+            rand('.'),
+            roll(rand(digits), 2, 20),
+            roll(rand('eE'), 1, 1),
+            roll(rand('+-'), 0, 1),
+            roll(rand(digits), 2, 20),
+            roll(rand('fF'), 0, 1),
+            roll(rand(' '), 0, 2))
+
+def hex_floating_point_literal():
+    return joiner(roll(rand(' '), 0, 2),
+            rand('0'),
+            roll(rand('xX'), 1, 1),
+            roll(rand(hexdigits), 1, 6),
+            rand('.'),
+            roll(rand(hexdigits), 1, 7),
+            roll(rand('pP'), 1, 1),
+            roll(rand('+-'), 0, 1),
+            roll(rand(digits), 1, 4),
+            roll(rand('fFdD'), 0, 1),
+            roll(rand(' '), 0, 2))
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/ca5ff7bc/test/mango.py
----------------------------------------------------------------------
diff --git a/test/mango.py b/test/mango.py
index bde9323..6764ed5 100644
--- a/test/mango.py
+++ b/test/mango.py
@@ -20,6 +20,7 @@ import requests
 import friend_docs
 import user_docs
 import limit_docs
+import num_string_docs
 
 
 def random_db_name():
@@ -235,3 +236,10 @@ class LimitDocsTextTests(DbPerClass):
     def setUpClass(klass):
         super(LimitDocsTextTests, klass).setUpClass()
         limit_docs.setup(klass.db, index_type="text")
+
+class NumStringDocsTextTests(DbPerClass):
+
+    @classmethod
+    def setUpClass(klass):
+        super(NumStringDocsTextTests, klass).setUpClass()
+        num_string_docs.setup(klass.db, index_type="text")

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/ca5ff7bc/test/num_string_docs.py
----------------------------------------------------------------------
diff --git a/test/num_string_docs.py b/test/num_string_docs.py
new file mode 100644
index 0000000..f900120
--- /dev/null
+++ b/test/num_string_docs.py
@@ -0,0 +1,49 @@
+# 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 literal_gen
+
+
+def setup(db, index_type="view"):
+    db.recreate()
+    DOCS[2]["number_string"] = literal_gen.floating_point_literal()
+    DOCS[3]["number_string"] = literal_gen.hex_floating_point_literal()
+    db.save_docs(copy.deepcopy(DOCS))
+    if index_type == "view":
+        add_view_indexes(db)
+    elif index_type == "text":
+        add_text_indexes(db)
+
+
+def add_text_indexes(db):
+    db.create_text_index()
+
+
+DOCS =  [
+  {
+    "_id": "55118b87283f8f2901c59663",
+    "number_string": "NaN"
+  },
+  {
+    "_id": "55118b873c98123d69bff407",
+    "number_string": "Infinity"
+  },
+  {
+    "_id": "55118b87b4e99951e6fbe5c4",
+    "number_string": "filler"
+  },
+  {
+    "_id": "55118b87bc21952536ef00da",
+    "number_string": "filler"
+  }
+]
\ No newline at end of file


[03/26] couchdb-mango git commit: Add quotes to numeric strings

Posted by to...@apache.org.
Add quotes to numeric strings

For numeric strings, we surround them with quotes when passed to
$text. This way, Clouseau will use the QueryParser for tokenization
rather than TermQuery. This is currently a workaround until we add
json parser support to Clouseau.

BugzID: 45572


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

Branch: refs/heads/master
Commit: a8def140992cf0d2868c1abce5714ab43e754176
Parents: 29eddf0
Author: Tony Sun <to...@cloudant.com>
Authored: Tue Aug 25 10:26:02 2015 -0700
Committer: Tony Sun <to...@cloudant.com>
Committed: Tue Aug 25 13:23:49 2015 -0700

----------------------------------------------------------------------
 src/mango_selector_text.erl |  3 ++-
 src/mango_util.erl          | 48 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/a8def140/src/mango_selector_text.erl
----------------------------------------------------------------------
diff --git a/src/mango_selector_text.erl b/src/mango_selector_text.erl
index bdd82bf..47e25ce 100644
--- a/src/mango_selector_text.erl
+++ b/src/mango_selector_text.erl
@@ -45,7 +45,8 @@ convert(Path, {[{<<"$default">>, Arg}]}) ->
 % The $text operator specifies a Lucene syntax query
 % so we just pull it in directly.
 convert(Path, {[{<<"$text">>, Query}]}) when is_binary(Query) ->
-    {op_field, {make_field(Path, Query), value_str(Query)}};
+    Term = mango_util:append_quotes(value_str(Query)),
+    {op_field, {make_field(Path, Query), Term}};
 
 % The MongoDB docs for $all are super confusing and read more
 % like they screwed up the implementation of this operator

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/a8def140/src/mango_util.erl
----------------------------------------------------------------------
diff --git a/src/mango_util.erl b/src/mango_util.erl
index 99e15d5..b12c6e9 100644
--- a/src/mango_util.erl
+++ b/src/mango_util.erl
@@ -34,6 +34,7 @@
     lucene_escape_field/1,
     lucene_escape_query_value/1,
     lucene_escape_user/1,
+    append_quotes/1,
 
     has_suffix/2,
 
@@ -45,6 +46,35 @@
 -include("mango.hrl").
 
 
+%% https://gist.github.com/cad2d2456c518d878d08
+-define(NUMSTRING, {re_pattern,25,0,<<69,82,67,80,71,3,0,0,0,0,0,0,1,0,0,0,25,0,
+0,0,0,0,0,0,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,93,3,19,77,255,255,
+255,255,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,69,77,0,0,0,0,0,
+40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,73,94,0,11,0,1,27,78,27,
+97,27,78,83,0,19,27,73,27,110,27,102,27,105,27,110,27,105,27,116,27,121,83,2,
+137,94,2,131,0,2,94,0,145,0,3,94,0,137,0,4,94,0,9,0,5,58,15,2,3,84,0,9,102,94,0,
+7,0,6,27,46,84,0,7,94,0,18,0,7,102,94,0,9,0,8,58,15,2,3,84,0,9,84,0,18,102,94,0,
+84,0,9,77,0,0,0,0,0,0,0,0,32,0,0,0,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,77,
+0,0,0,0,0,40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,73,94,0,9,0,10,
+58,15,2,3,84,0,9,84,0,84,84,0,137,83,0,121,94,0,115,0,11,27,46,94,0,17,0,12,94,
+0,9,0,13,58,15,2,3,84,0,9,84,0,17,102,94,0,84,0,14,77,0,0,0,0,0,0,0,0,32,0,0,0,
+32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,77,0,0,0,0,0,40,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,73,94,0,9,0,15,58,15,2,3,84,0,9,84,0,84,84,0,
+115,83,1,79,94,1,73,0,16,94,0,101,0,17,94,0,93,0,18,27,48,77,0,0,0,0,0,0,0,0,0,
+0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,94,0,39,0,19,77,0,0,0,0,0,0,255,3,
+126,0,0,0,126,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,71,84,0,39,102,94,0,7,0,20,
+27,46,84,0,7,84,0,93,83,0,141,94,0,135,0,21,27,48,77,0,0,0,0,0,0,0,0,0,0,0,1,0,
+0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,94,0,39,0,22,77,0,0,0,0,0,0,255,3,126,
+0,0,0,126,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,71,84,0,39,94,0,7,0,23,27,46,84,
+0,7,94,0,39,0,24,77,0,0,0,0,0,0,255,3,126,0,0,0,126,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,71,84,0,39,84,0,135,84,0,242,77,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,77,0,0,0,0,0,40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,73,94,0,9,0,25,58,15,2,3,84,0,9,84,1,73,84,2,89,77,0,0,0,0,0,0,0,
+0,80,0,0,0,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,73,84,2,131,84,2,167,77,255,
+255,255,255,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,69,84,3,19,
+0>>}).
+
+
 open_doc(Db, DocId) ->
     open_doc(Db, DocId, [deleted]).
 
@@ -310,3 +340,21 @@ join(_Sep, [Item]) ->
     [Item];
 join(Sep, [Item | Rest]) ->
     [Item, Sep | join(Sep, Rest)].
+
+
+is_number_string(Subject) ->
+    case re:run(Subject, ?NUMSTRING) of
+        nomatch ->
+            false;
+        _ ->
+            true
+    end.
+
+
+append_quotes(TextValue) ->
+    case is_number_string(binary_to_list(TextValue)) of
+        true ->
+            <<"\"", TextValue/binary, "\"">>;
+        false ->
+            TextValue
+    end.


[14/26] couchdb-mango git commit: stash compiled regexs in mochiglobal

Posted by to...@apache.org.
stash compiled regexs in mochiglobal


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

Branch: refs/heads/master
Commit: 7032bf582ba9483c41ae3e36ad543788852bac2a
Parents: 460fcd4
Author: Tony Sun <to...@cloudant.com>
Authored: Wed Aug 26 01:50:27 2015 -0700
Committer: Tony Sun <to...@cloudant.com>
Committed: Wed Aug 26 01:50:27 2015 -0700

----------------------------------------------------------------------
 src/mango_selector_text.erl |  7 ++-
 src/mango_util.erl          | 98 ++++++++++++++++++----------------------
 2 files changed, 46 insertions(+), 59 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/7032bf58/src/mango_selector_text.erl
----------------------------------------------------------------------
diff --git a/src/mango_selector_text.erl b/src/mango_selector_text.erl
index e61f759..08aa6ee 100644
--- a/src/mango_selector_text.erl
+++ b/src/mango_selector_text.erl
@@ -26,9 +26,7 @@
 
 
 %% Regex for <<"\\.">>
--define(PERIOD, {re_pattern,0,0,<<69,82,67,80,57,0,0,0,0,0,0,0,2,0,0,0,
-0,0,0,0,46,0,0,0,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,93,0,
-5,27,46,84,0,5,0>>}).
+-define(PERIOD, "\\.").
 
 
 convert(Object) ->
@@ -181,7 +179,8 @@ convert(Path, {[{Field0, Cond}]}) ->
     % an incorrect query since we need [<<"a.b">>]. Without breaking
     % our escaping mechanism, we simply revert this first parse_field
     % effect and replace instances of "." to "\\.".
-    PP1 = [re:replace(P, ?PERIOD, <<"\\\\.">>,
+    MP = mango_util:cached_re(mango_period, ?PERIOD),
+    PP1 = [re:replace(P, MP, <<"\\\\.">>,
         [global,{return,binary}]) || P <- PP0],
     {PP2, HasInteger} = replace_array_indexes(PP1, [], false),
     NewPath = PP2 ++ Path,

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/7032bf58/src/mango_util.erl
----------------------------------------------------------------------
diff --git a/src/mango_util.erl b/src/mango_util.erl
index aa11310..0e71312 100644
--- a/src/mango_util.erl
+++ b/src/mango_util.erl
@@ -40,7 +40,9 @@
 
     join/2,
 
-    parse_field/1
+    parse_field/1,
+
+    cached_re/2
 ]).
 
 
@@ -48,59 +50,33 @@
 -include("mango.hrl").
 
 
-%% Regex for Floating Point, Hex Floating Point, Nan, and Infinity
-%% Digits = "(\\p{N}+)",
-%% HexDigits = "([0-9a-fA-F]+)",
-%% Exp = "[eE][+-]?" ++ Digits,
-%% FpRegexStr = "[\\x00-\\x20]*" ++ "[+-]?(" ++ "NaN|"
-%%     ++ "Infinity|" ++ "((("
-%%     ++ Digits
-%%     ++ "(\\.)?("
-%%     ++ Digits
-%%     ++ "?)("
-%%     ++ Exp
-%%     ++ ")?)|"
-%%     ++ "(\\.("
-%%     ++ Digits
-%%     ++ ")("
-%%     ++ Exp
-%%     ++ ")?)|"
-%%     ++ "(("
-%%     ++ "(0[xX]"
-%%     ++ HexDigits
-%%     ++ "(\\.)?)|"
-%%     ++ "(0[xX]"
-%%     ++ HexDigits
-%%     ++ "?(\\.)"
-%%     ++ HexDigits
-%%     ++ ")"
-%%     ++ ")[pP][+-]?" ++ Digits ++ "))" ++ "[fFdD]?))" ++ "[\\x00-\\x20]*"
--define(NUMSTRING, {re_pattern,25,0,<<69,82,67,80,71,3,0,0,0,0,0,0,1,0,0,0,25,0,
-0,0,0,0,0,0,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,93,3,19,77,255,255,
-255,255,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,69,77,0,0,0,0,0,
-40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,73,94,0,11,0,1,27,78,27,
-97,27,78,83,0,19,27,73,27,110,27,102,27,105,27,110,27,105,27,116,27,121,83,2,
-137,94,2,131,0,2,94,0,145,0,3,94,0,137,0,4,94,0,9,0,5,58,15,2,3,84,0,9,102,94,0,
-7,0,6,27,46,84,0,7,94,0,18,0,7,102,94,0,9,0,8,58,15,2,3,84,0,9,84,0,18,102,94,0,
-84,0,9,77,0,0,0,0,0,0,0,0,32,0,0,0,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,77,
-0,0,0,0,0,40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,73,94,0,9,0,10,
-58,15,2,3,84,0,9,84,0,84,84,0,137,83,0,121,94,0,115,0,11,27,46,94,0,17,0,12,94,
-0,9,0,13,58,15,2,3,84,0,9,84,0,17,102,94,0,84,0,14,77,0,0,0,0,0,0,0,0,32,0,0,0,
-32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,77,0,0,0,0,0,40,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,73,94,0,9,0,15,58,15,2,3,84,0,9,84,0,84,84,0,
-115,83,1,79,94,1,73,0,16,94,0,101,0,17,94,0,93,0,18,27,48,77,0,0,0,0,0,0,0,0,0,
-0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,94,0,39,0,19,77,0,0,0,0,0,0,255,3,
-126,0,0,0,126,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,71,84,0,39,102,94,0,7,0,20,
-27,46,84,0,7,84,0,93,83,0,141,94,0,135,0,21,27,48,77,0,0,0,0,0,0,0,0,0,0,0,1,0,
-0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,94,0,39,0,22,77,0,0,0,0,0,0,255,3,126,
-0,0,0,126,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,71,84,0,39,94,0,7,0,23,27,46,84,
-0,7,94,0,39,0,24,77,0,0,0,0,0,0,255,3,126,0,0,0,126,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,71,84,0,39,84,0,135,84,0,242,77,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,77,0,0,0,0,0,40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,73,94,0,9,0,25,58,15,2,3,84,0,9,84,1,73,84,2,89,77,0,0,0,0,0,0,0,
-0,80,0,0,0,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,73,84,2,131,84,2,167,77,255,
-255,255,255,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,69,84,3,19,
-0>>}).
+-define(DIGITS, "(\\p{N}+)").
+-define(HEXDIGITS, "([0-9a-fA-F]+)").
+-define(EXP, "[eE][+-]?" ++ ?DIGITS).
+-define(NUMSTRING,
+"[\\x00-\\x20]*" ++ "[+-]?(" ++ "NaN|"
+     ++ "Infinity|" ++ "((("
+     ++ ?DIGITS
+     ++ "(\\.)?("
+     ++ ?DIGITS
+     ++ "?)("
+     ++ ?EXP
+     ++ ")?)|"
+     ++ "(\\.("
+     ++ ?DIGITS
+     ++ ")("
+     ++ ?EXP
+     ++ ")?)|"
+     ++ "(("
+     ++ "(0[xX]"
+     ++ ?HEXDIGITS
+     ++ "(\\.)?)|"
+     ++ "(0[xX]"
+     ++ ?HEXDIGITS
+     ++ "?(\\.)"
+     ++ ?HEXDIGITS
+     ++ ")"
+     ++ ")[pP][+-]?" ++ ?DIGITS ++ "))" ++ "[fFdD]?))" ++ "[\\x00-\\x20]*").
 
 
 open_doc(Db, DocId) ->
@@ -373,7 +349,8 @@ join(Sep, [Item | Rest]) ->
 is_number_string(Value) when is_binary(Value) ->
     is_number_string(binary_to_list(Value));
 is_number_string(Value) when is_list(Value)->
-    case re:run(Value, ?NUMSTRING) of
+    MP = cached_re(mango_numstring_re, ?NUMSTRING),
+    case re:run(Value, MP) of
         nomatch ->
             false;
         _ ->
@@ -381,6 +358,17 @@ is_number_string(Value) when is_list(Value)->
     end.
 
 
+cached_re(Name, RE) ->
+    case mochiglobal:get(Name) of
+        undefined ->
+            {ok, MP} = re:compile(RE),
+            ok = mochiglobal:put(Name, MP),
+            MP;
+        MP ->
+            MP
+    end.
+
+
 parse_field(Field) ->
     case binary:match(Field, <<"\\">>, []) of
         nomatch ->


[24/26] couchdb-mango git commit: Remove extraneous error message

Posted by to...@apache.org.
Remove extraneous error message

COUCHDB-2787


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

Branch: refs/heads/master
Commit: f12076f24a4d2cf7ae500dd6c15735ef24f1d5cf
Parents: 8b6d0db
Author: Tony Sun <to...@cloudant.com>
Authored: Thu Sep 3 15:30:19 2015 -0700
Committer: Tony Sun <to...@cloudant.com>
Committed: Thu Sep 3 15:30:19 2015 -0700

----------------------------------------------------------------------
 src/mango_error.erl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/f12076f2/src/mango_error.erl
----------------------------------------------------------------------
diff --git a/src/mango_error.erl b/src/mango_error.erl
index 4704261..9b7ae82 100644
--- a/src/mango_error.erl
+++ b/src/mango_error.erl
@@ -69,7 +69,7 @@ info(mango_cursor_text, {text_search_error, {error, Error}}) ->
     {
         400,
         <<"text_search_error">>,
-        fmt("Error performing text search: ~p", [Error])
+        fmt("~p", [Error])
     };
 
 info(mango_fields, {invalid_fields_json, BadFields}) ->


[08/26] couchdb-mango git commit: Fix $all operator

Posted by to...@apache.org.
Fix $all operator

The $all operator was only returning docs where the field exactly
matched the array. It should return docs where the provided matching
array is a subset of the field's array.
Ex: {"field" :
        { "$all" : ["Bob", "Joe"] }
    }
should match "field" : ["Bob", "Jane", "Joe"]

BugzId:46731


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

Branch: refs/heads/master
Commit: e80608da4f51ce787343a6721a4c44d1f489373c
Parents: cdc9fe5
Author: Tony Sun <to...@cloudant.com>
Authored: Tue Aug 25 13:18:07 2015 -0700
Committer: Tony Sun <to...@cloudant.com>
Committed: Tue Aug 25 13:24:04 2015 -0700

----------------------------------------------------------------------
 src/mango_selector_text.erl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/e80608da/src/mango_selector_text.erl
----------------------------------------------------------------------
diff --git a/src/mango_selector_text.erl b/src/mango_selector_text.erl
index 9402cc2..5eb237f 100644
--- a/src/mango_selector_text.erl
+++ b/src/mango_selector_text.erl
@@ -71,7 +71,7 @@ convert(Path, {[{<<"$all">>, Args}]}) ->
         _ ->
             % Otherwise the $all operator is equivalent to an $and
             % operator so we treat it as such.
-            convert(Path, {[{<<"$eq">> , Args}]})
+            convert([<<"[]">>| Path], {[{<<"$and">>, Args}]})
     end;
 
 % The $elemMatch Lucene query is not an exact translation