couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jch...@apache.org
Subject svn commit: r701847 - in /incubator/couchdb/trunk: share/www/script/couch_tests.js src/couchdb/couch_db.hrl src/couchdb/couch_httpd_db.erl src/couchdb/couch_httpd_view.erl
Date Sun, 05 Oct 2008 18:54:36 GMT
Author: jchris
Date: Sun Oct  5 11:54:36 2008
New Revision: 701847

URL: http://svn.apache.org/viewvc?rev=701847&view=rev
Log:
include_docs option adds a doc member to view rows with the latest _rev of the document (or
the _rev specified in the row value)

Modified:
    incubator/couchdb/trunk/share/www/script/couch_tests.js
    incubator/couchdb/trunk/src/couchdb/couch_db.hrl
    incubator/couchdb/trunk/src/couchdb/couch_httpd_db.erl
    incubator/couchdb/trunk/src/couchdb/couch_httpd_view.erl

Modified: incubator/couchdb/trunk/share/www/script/couch_tests.js
URL: http://svn.apache.org/viewvc/incubator/couchdb/trunk/share/www/script/couch_tests.js?rev=701847&r1=701846&r2=701847&view=diff
==============================================================================
--- incubator/couchdb/trunk/share/www/script/couch_tests.js [utf-8] (original)
+++ incubator/couchdb/trunk/share/www/script/couch_tests.js [utf-8] Sun Oct  5 11:54:36 2008
@@ -1089,6 +1089,102 @@
     T(results.total_rows == 0);
   },
 
+  view_include_docs: function(debug) {
+    var db = new CouchDB("test_suite_db");
+    db.deleteDb();
+    db.createDb();
+    if (debug) debugger;
+
+    var docs = makeDocs(0, 100);
+    T(db.bulkSave(docs).ok);
+
+    var designDoc = {
+      _id:"_design/test",
+      language: "javascript",
+      views: {
+        all_docs: {
+          map: "function(doc) { emit(doc.integer, doc.string) }"
+        },
+        with_prev: {
+          map: "function(doc){if(doc.prev) emit(doc._id,{'_rev':doc.prev}); else emit(doc._id,{'_rev':doc._rev});}"
+        },
+        summate: {
+          map:"function (doc) {emit(doc.integer, doc.integer)};",
+          reduce:"function (keys, values) { return sum(values); };"
+        }
+      }
+    }
+    T(db.save(designDoc).ok);
+
+    var resp = db.view('test/all_docs', {include_docs: true, count: 2});
+    T(resp.rows.length == 2);
+    T(resp.rows[0].id == "0");
+    T(resp.rows[0].doc._id == "0");
+    T(resp.rows[1].id == "1");
+    T(resp.rows[1].doc._id == "1");
+
+    resp = db.view('test/all_docs', {include_docs: true}, [29, 74]);
+    T(resp.rows.length == 2);
+    T(resp.rows[0].doc._id == "29");
+    T(resp.rows[1].doc.integer == 74);
+
+    resp = db.allDocs({count: 2, skip: 1, include_docs: true});
+    T(resp.rows.length == 2);
+    T(resp.rows[0].doc.integer == 1);
+    T(resp.rows[1].doc.integer == 10);
+
+    resp = db.allDocs({include_docs: true}, ['not_a_doc']);
+    T(resp.rows.length == 1);
+    T(!resp.rows[0].doc);
+
+    resp = db.allDocs({include_docs: true}, ["1", "foo"]);
+    T(resp.rows.length == 2);
+    T(resp.rows[0].doc.integer == 1);
+    T(!resp.rows[1].doc);
+
+    resp = db.allDocs({include_docs: true, count: 0});
+    T(resp.rows.length == 0);
+
+    // No reduce support
+    try {
+        resp = db.view('test/summate', {include_docs: true});
+        alert(JSON.stringify(resp));
+        T(0==1);
+    } catch (e) {
+        T(e.error == 'query_parse_error');
+    }
+
+    // Check emitted _rev controls things
+    resp = db.allDocs({include_docs: true}, ["0"]);
+    var before = resp.rows[0].doc;
+    var after = db.open("0");
+    after.integer = 100
+    after.prev = after._rev;
+    db.save(after);
+    after = db.open("0");
+    T(after._rev != after.prev);
+    T(after.integer == 100);
+
+    // should emit the previous revision
+    resp = db.view("test/with_prev", {include_docs: true}, ["0"]);
+    T(resp.rows[0].doc._id == "0");
+    T(resp.rows[0].doc._rev == before._rev);
+    T(!resp.rows[0].doc.prev);
+    T(resp.rows[0].doc.integer == 0);
+
+    var xhr = CouchDB.request("POST", "/test_suite_db/_compact");
+    T(xhr.status == 202)
+    while (db.info().compact_running) {}
+
+    resp = db.view("test/with_prev", {include_docs: true}, ["0", "23"]);
+    T(resp.rows.length == 2);
+    T(resp.rows[0].key == "0");
+    T(resp.rows[0].id == "0");
+    T(!resp.rows[0].doc);
+    T(resp.rows[0].error == "missing");
+    T(resp.rows[1].doc.integer == 23);
+  },
+
   view_multi_key_all_docs: function(debug) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
@@ -1126,7 +1222,9 @@
     rows = db.allDocs({}, [1, "i_dont_exist", "0"]).rows;
     T(rows.length == 3);
     T(rows[0].error == "not_found");
+    T(!rows[0].id);
     T(rows[1].error == "not_found");
+    T(!rows[1].id);
     T(rows[2].id == rows[2].key && rows[2].key == "0");
   },
 

Modified: incubator/couchdb/trunk/src/couchdb/couch_db.hrl
URL: http://svn.apache.org/viewvc/incubator/couchdb/trunk/src/couchdb/couch_db.hrl?rev=701847&r1=701846&r2=701847&view=diff
==============================================================================
--- incubator/couchdb/trunk/src/couchdb/couch_db.hrl (original)
+++ incubator/couchdb/trunk/src/couchdb/couch_db.hrl Sun Oct  5 11:54:36 2008
@@ -124,7 +124,8 @@
     end_docid = {},
     skip = 0,
     group_level = 0,
-    reduce = true
+    reduce = true,
+    include_docs = false
 }).
 
 

Modified: incubator/couchdb/trunk/src/couchdb/couch_httpd_db.erl
URL: http://svn.apache.org/viewvc/incubator/couchdb/trunk/src/couchdb/couch_httpd_db.erl?rev=701847&r1=701846&r2=701847&view=diff
==============================================================================
--- incubator/couchdb/trunk/src/couchdb/couch_httpd_db.erl (original)
+++ incubator/couchdb/trunk/src/couchdb/couch_httpd_db.erl Sun Oct  5 11:54:36 2008
@@ -13,7 +13,7 @@
 -module(couch_httpd_db).
 -include("couch_db.hrl").
 
--export([handle_request/1, db_req/2]).
+-export([handle_request/1, db_req/2, couch_doc_open/4]).
 
 -import(couch_httpd,
     [send_json/2,send_json/3,send_json/4,send_method_not_allowed/2,
@@ -179,8 +179,8 @@
     {ok, Info} = couch_db:get_db_info(Db),
     TotalRowCount = proplists:get_value(doc_count, Info),
 
-    FoldlFun = couch_httpd_view:make_view_fold_fun(Req, QueryArgs, TotalRowCount,
-            fun couch_db:enum_docs_since_reduce_to_count/1),
+    FoldlFun = couch_httpd_view:make_view_fold_fun(Req, QueryArgs, Db,
+        TotalRowCount, fun couch_db:enum_docs_since_reduce_to_count/1),
     StartKey2 = case StartKey of
         nil -> 0;
         <<>> -> 100000000000;
@@ -247,7 +247,7 @@
         count = Count,
         skip = SkipCount,
         direction = Dir
-    } = QueryArgs = couch_httpd_view:parse_view_query(Req, Keys),
+    } = QueryArgs = couch_httpd_view:parse_view_query(Req, Keys),    
     {ok, Info} = couch_db:get_db_info(Db),
     TotalRowCount = proplists:get_value(doc_count, Info),
     StartId = if is_binary(StartKey) -> StartKey;
@@ -257,7 +257,7 @@
     
     case Keys of
     nil ->
-        FoldlFun = couch_httpd_view:make_view_fold_fun(Req, QueryArgs, 
+        FoldlFun = couch_httpd_view:make_view_fold_fun(Req, QueryArgs, Db,
             TotalRowCount, fun couch_db:enum_docs_reduce_to_count/1),
         AdapterFun = fun(#full_doc_info{id=Id}=FullDocInfo, Offset, Acc) ->
             case couch_doc:to_doc_info(FullDocInfo) of
@@ -271,7 +271,7 @@
             AdapterFun, FoldAccInit),
         couch_httpd_view:finish_view_fold(Req, TotalRowCount, {ok, FoldResult});
     _ ->
-        FoldlFun = couch_httpd_view:make_view_fold_fun(Req, QueryArgs, 
+        FoldlFun = couch_httpd_view:make_view_fold_fun(Req, QueryArgs, Db,
             TotalRowCount, fun(Offset) -> Offset end),
         KeyFoldFun = case Dir of
         fwd ->

Modified: incubator/couchdb/trunk/src/couchdb/couch_httpd_view.erl
URL: http://svn.apache.org/viewvc/incubator/couchdb/trunk/src/couchdb/couch_httpd_view.erl?rev=701847&r1=701846&r2=701847&view=diff
==============================================================================
--- incubator/couchdb/trunk/src/couchdb/couch_httpd_view.erl (original)
+++ incubator/couchdb/trunk/src/couchdb/couch_httpd_view.erl Sun Oct  5 11:54:36 2008
@@ -15,7 +15,7 @@
 
 -export([handle_view_req/2,handle_temp_view_req/2]).
 
--export([parse_view_query/1,parse_view_query/2,make_view_fold_fun/4,finish_view_fold/3]).
+-export([parse_view_query/1,parse_view_query/2,make_view_fold_fun/5,finish_view_fold/3]).
 
 -import(couch_httpd,
     [send_json/2,send_json/3,send_json/4,send_method_not_allowed/2,
@@ -26,7 +26,7 @@
             <<"_design/", Id/binary>>, ViewName}) of
     {ok, View} ->    
         QueryArgs = parse_view_query(Req, Keys),
-        output_map_view(Req, View, QueryArgs, Keys);
+        output_map_view(Req, View, Db, QueryArgs, Keys);
     {not_found, Reason} ->
         case couch_view:get_reduce_view({couch_db:name(Db),
                 <<"_design/", Id/binary>>, ViewName}) of
@@ -37,7 +37,7 @@
             case Reduce of
             false ->
                 {reduce, _N, _Lang, MapView} = View,
-                output_map_view(Req, MapView, QueryArgs, Keys);
+                output_map_view(Req, MapView, Db, QueryArgs, Keys);
             _ ->
                 output_reduce_view(Req, View, QueryArgs, Keys)
             end;
@@ -72,7 +72,7 @@
     case proplists:get_value(<<"reduce">>, Props, null) of
     null ->
         {ok, View} = couch_view:get_map_view({temp, couch_db:name(Db), Language, MapSrc}),
-        output_map_view(Req, View, QueryArgs, Keys);
+        output_map_view(Req, View, Db, QueryArgs, Keys);
     RedSrc ->
         {ok, View} = couch_view:get_reduce_view(
                 {temp,  couch_db:name(Db), Language, MapSrc, RedSrc}),
@@ -82,7 +82,7 @@
 handle_temp_view_req(Req, _Db) ->
     send_method_not_allowed(Req, "POST").
 
-output_map_view(Req, View, QueryArgs, nil) ->
+output_map_view(Req, View, Db, QueryArgs, nil) ->
     #view_query_args{
         count = Count,
         direction = Dir,
@@ -92,13 +92,13 @@
     } = QueryArgs,
     {ok, RowCount} = couch_view:get_row_count(View),
     Start = {StartKey, StartDocId},
-    FoldlFun = make_view_fold_fun(Req, QueryArgs, RowCount,
+    FoldlFun = make_view_fold_fun(Req, QueryArgs, Db, RowCount,
             fun couch_view:reduce_to_count/1),
     FoldAccInit = {Count, SkipCount, undefined, []},
     FoldResult = couch_view:fold(View, Start, Dir, FoldlFun, FoldAccInit),
     finish_view_fold(Req, RowCount, FoldResult);
     
-output_map_view(Req, View, QueryArgs, Keys) ->
+output_map_view(Req, View, Db, QueryArgs, Keys) ->
     #view_query_args{
         count = Count,
         direction = Dir,
@@ -114,7 +114,7 @@
                 QueryArgs#view_query_args{
                     start_key = Key,
                     end_key = Key
-                }, RowCount, fun couch_view:reduce_to_count/1),
+                }, Db, RowCount, fun couch_view:reduce_to_count/1),
             couch_view:fold(View, Start, Dir, FoldlFun, FoldAcc)
         end, {ok, FoldAccInit}, Keys),
     finish_view_fold(Req, RowCount, FoldResult).
@@ -305,6 +305,23 @@
             Args#view_query_args{reduce=true};
         {"reduce", "false"} ->
             Args#view_query_args{reduce=false};
+        {"include_docs", Value} ->
+            case IsReduce of
+            true ->
+                Msg = lists:flatten(io_lib:format("Bad URL query key for reduce operation:
~s", [Key])),
+                throw({query_parse_error, Msg});
+            _ ->
+                ok
+            end,
+            case Value of
+            "true" ->
+                Args#view_query_args{include_docs=true};
+            "false" ->
+                Args#view_query_args{include_docs=false};
+            _ ->
+                Msg1 = "Bad URL query value for 'include_docs' expected \"true\" or \"false\".",
+                throw({query_parse_error, Msg1})
+            end;
         _ -> % unknown key
             Msg = lists:flatten(io_lib:format(
                 "Bad URL query key:~s", [Key])),
@@ -331,10 +348,11 @@
     end.
 
 
-make_view_fold_fun(Req, QueryArgs, TotalViewCount, ReduceCountFun) ->
+make_view_fold_fun(Req, QueryArgs, Db, TotalViewCount, ReduceCountFun) ->
     #view_query_args{
         end_key = EndKey,
         end_docid = EndDocId,
+        include_docs = IncludeDocs,
         direction = Dir
     } = QueryArgs,
 
@@ -367,26 +385,48 @@
             {ok, Resp2} = start_json_response(Req, 200),
             JsonBegin = io_lib:format("{\"total_rows\":~w,\"offset\":~w,\"rows\":[\r\n",
                     [TotalViewCount, Offset]),
-            JsonObj = case DocId of
-            error ->
-                {[{key, Key}, {error, Value}]};
-            _ ->
-                {[{id, DocId}, {key, Key}, {value, Value}]}
-            end,            
+            JsonObj = view_row_obj(Db, {{Key, DocId}, Value}, IncludeDocs),
             send_chunk(Resp2, JsonBegin ++ ?JSON_ENCODE(JsonObj)),
             {ok, {AccCount - 1, 0, Resp2, AccRevRows}};
         {_, AccCount, _, Resp} when (AccCount > 0) ->
-            JsonObj = case DocId of
-            error ->
-                {[{key, Key}, {error, Value}]};
-            _ ->
-                {[{id, DocId}, {key, Key}, {value, Value}]}
-            end,
+            JsonObj = view_row_obj(Db, {{Key, DocId}, Value}, IncludeDocs),
             send_chunk(Resp, ",\r\n" ++  ?JSON_ENCODE(JsonObj)),
             {ok, {AccCount - 1, 0, Resp, AccRevRows}}
         end
     end.
 
+view_row_obj(Db, {{Key, DocId}, Value}, IncludeDocs) ->
+    case DocId of
+    error ->
+        {[{key, Key}, {error, Value}]};
+    _ ->
+        case IncludeDocs of
+        true ->
+            Rev = case Value of
+            {Props} ->
+                case is_list(Props) of
+                true ->
+                    proplists:get_value(<<"_rev">>, Props, []);
+                _ ->
+                    []
+                end;
+            _ ->
+                []
+            end,
+            ?LOG_DEBUG("Include Doc: ~p ~p", [DocId, Rev]),
+            case (catch couch_httpd_db:couch_doc_open(Db, DocId, 
+                Rev, [])) of
+            {{not_found, missing}, _} ->
+                {[{id, DocId}, {key, Key}, {value, Value}, {error, missing}]};
+            Doc ->
+                JsonDoc = couch_doc:to_json_obj(Doc, []),
+                {[{id, DocId}, {key, Key}, {value, Value}, {doc, JsonDoc}]}
+            end;
+        _ ->
+            {[{id, DocId}, {key, Key}, {value, Value}]}
+        end
+    end.
+
 finish_view_fold(Req, TotalRows, FoldResult) ->
     case FoldResult of
     {ok, {_, _, undefined, _}} ->



Mime
View raw message