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

[40/50] [abbrv] couchdb-mango git commit: Implement the _explain endpoint

Implement the _explain endpoint

This returns a JSON blob describing a provided query. It accepts the
same exact POST body parameters as _find but instead of returning query
results it returns a description of the query that would be executed.
This is intended for debugging purposes.

BugzId: 33294


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

Branch: refs/heads/master
Commit: 812cf6bd043f4c9f9b93f0f7eebca4a05df3b2ec
Parents: 06bf775
Author: Paul J. Davis <pa...@gmail.com>
Authored: Fri Jan 9 15:43:51 2015 -0600
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Fri Jan 16 13:32:50 2015 -0600

----------------------------------------------------------------------
 src/mango_crud.erl        | 10 +++++++++-
 src/mango_cursor.erl      | 23 +++++++++++++++++++++++
 src/mango_cursor_view.erl | 12 ++++++++++++
 src/mango_httpd.erl       | 12 ++++++++++++
 test/mango.py             | 13 ++++++++++---
 5 files changed, 66 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/812cf6bd/src/mango_crud.erl
----------------------------------------------------------------------
diff --git a/src/mango_crud.erl b/src/mango_crud.erl
index 159d5f7..68c9d6c 100644
--- a/src/mango_crud.erl
+++ b/src/mango_crud.erl
@@ -16,7 +16,8 @@
     insert/3,
     find/5,
     update/4,
-    delete/3
+    delete/3,
+    explain/3
 ]).
 
 -export([
@@ -98,6 +99,13 @@ delete(Db, Selector, Options) ->
     end.
 
 
+explain(Db, Selector, Opts0) ->
+    Opts1 = maybe_add_user_ctx(Db, Opts0),
+    Opts2 = maybe_int_to_str(r, Opts1),
+    {ok, Cursor} = mango_cursor:create(Db, Selector, Opts2),
+    mango_cursor:explain(Cursor).
+
+
 maybe_add_user_ctx(Db, Opts) ->
     case lists:keyfind(user_ctx, 1, Opts) of
         {user_ctx, _} ->

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/812cf6bd/src/mango_cursor.erl
----------------------------------------------------------------------
diff --git a/src/mango_cursor.erl b/src/mango_cursor.erl
index 5bfe383..d4d5523 100644
--- a/src/mango_cursor.erl
+++ b/src/mango_cursor.erl
@@ -15,6 +15,7 @@
 
 -export([
     create/3,
+    explain/1,
     execute/3
 ]).
 
@@ -49,6 +50,28 @@ create(Db, Selector0, Opts) ->
     create_cursor(Db, UsableIndexes, Selector, Opts).
 
 
+explain(#cursor{}=Cursor) ->
+    #cursor{
+        index = Idx,
+        selector = Selector,
+        opts = Opts0,
+        limit = Limit,
+        skip = Skip,
+        fields = Fields
+    } = Cursor,
+    Mod = mango_idx:cursor_mod(Idx),
+    Opts = lists:keydelete(user_ctx, 1, Opts0),
+    {[
+        {dbname, mango_idx:dbname(Idx)},
+        {index, mango_idx:to_json(Idx)},
+        {selector, Selector},
+        {opts, {Opts}},
+        {limit, Limit},
+        {skip, Skip},
+        {fields, Fields}
+    ] ++ Mod:explain(Cursor)}.
+
+
 execute(#cursor{index=Idx}=Cursor, UserFun, UserAcc) ->
     Mod = mango_idx:cursor_mod(Idx),
     Mod:execute(Cursor, UserFun, UserAcc).

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/812cf6bd/src/mango_cursor_view.erl
----------------------------------------------------------------------
diff --git a/src/mango_cursor_view.erl b/src/mango_cursor_view.erl
index 798b713..b32353d 100644
--- a/src/mango_cursor_view.erl
+++ b/src/mango_cursor_view.erl
@@ -14,6 +14,7 @@
 
 -export([
     create/4,
+    explain/1,
     execute/3
 ]).
 
@@ -47,6 +48,17 @@ create(Db, Indexes, Selector, Opts) ->
     }}.
 
 
+explain(Cursor) ->
+    #cursor{
+        index = Idx,
+        ranges = Ranges
+    } = Cursor,
+    [{range, {[
+        {start_key, mango_idx:start_key(Idx, Ranges)},
+        {end_key, mango_idx:end_key(Idx, Ranges)}
+    ]}}].
+
+
 execute(#cursor{db = Db, index = Idx} = Cursor0, UserFun, UserAcc) ->
     Cursor = Cursor0#cursor{
         user_fun = UserFun,

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/812cf6bd/src/mango_httpd.erl
----------------------------------------------------------------------
diff --git a/src/mango_httpd.erl b/src/mango_httpd.erl
index 02e26ad..ed1e9bc 100644
--- a/src/mango_httpd.erl
+++ b/src/mango_httpd.erl
@@ -41,6 +41,8 @@ handle_req(#httpd{} = Req, Db0) ->
 
 handle_req_int(#httpd{path_parts=[_, <<"_index">> | _]} = Req, Db) ->
     handle_index_req(Req, Db);
+handle_req_int(#httpd{path_parts=[_, <<"_explain">> | _]} = Req, Db) ->
+    handle_explain_req(Req, Db);
 handle_req_int(#httpd{path_parts=[_, <<"_find">> | _]} = Req, Db) ->
     handle_find_req(Req, Db);
 handle_req_int(_, _) ->
@@ -119,6 +121,16 @@ handle_index_req(Req, _Db) ->
     chttpd:send_method_not_allowed(Req, "GET,POST,DELETE").
 
 
+handle_explain_req(#httpd{method='POST'}=Req, Db) ->
+    {ok, Opts0} = mango_opts:validate_find(chttpd:json_body_obj(Req)),
+    {value, {selector, Sel}, Opts} = lists:keytake(selector, 1, Opts0),
+    Resp = mango_crud:explain(Db, Sel, Opts),
+    chttpd:send_json(Req, Resp);
+
+handle_explain_req(Req, _Db) ->
+    chttpd:send_method_not_allowed(Req, "POST").
+
+
 handle_find_req(#httpd{method='POST'}=Req, Db) ->
     {ok, Opts0} = mango_opts:validate_find(chttpd:json_body_obj(Req)),
     {value, {selector, Sel}, Opts} = lists:keytake(selector, 1, Opts0),

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/812cf6bd/test/mango.py
----------------------------------------------------------------------
diff --git a/test/mango.py b/test/mango.py
index c28f280..fac4e7e 100644
--- a/test/mango.py
+++ b/test/mango.py
@@ -107,7 +107,7 @@ class Database(object):
         r.raise_for_status()
 
     def find(self, selector, limit=25, skip=0, sort=None, fields=None,
-                r=1, conflicts=False):
+                r=1, conflicts=False, explain=False):
         body = {
             "selector": selector,
             "limit": limit,
@@ -120,9 +120,16 @@ class Database(object):
         if fields is not None:
             body["fields"] = fields
         body = json.dumps(body)
-        r = self.sess.post(self.path("_find"), data=body)
+        if explain:
+            path = self.path("_explain")
+        else:
+            path = self.path("_find")
+        r = self.sess.post(path, data=body)
         r.raise_for_status()
-        return r.json()["docs"]
+        if explain:
+            return r.json()
+        else:
+            return r.json()["docs"]
 
     def find_one(self, *args, **kwargs):
         results = self.find(*args, **kwargs)