couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dav...@apache.org
Subject svn commit: r1033676 - in /couchdb/trunk: ./ share/www/script/ share/www/script/test/ src/couchdb/
Date Wed, 10 Nov 2010 19:44:05 GMT
Author: davisp
Date: Wed Nov 10 19:44:05 2010
New Revision: 1033676

URL: http://svn.apache.org/viewvc?rev=1033676&view=rev
Log:
Support the keys parameter in GET requests.

You can now request a list of keys in the query string using a query
string like:

    ?keys=["foo", "bar"]

Your query string obviously needs to be properly escaped.


Modified:
    couchdb/trunk/THANKS
    couchdb/trunk/share/www/script/couch.js
    couchdb/trunk/share/www/script/test/list_views.js
    couchdb/trunk/share/www/script/test/view_multi_key_all_docs.js
    couchdb/trunk/share/www/script/test/view_multi_key_design.js
    couchdb/trunk/src/couchdb/couch_httpd.erl
    couchdb/trunk/src/couchdb/couch_httpd_db.erl
    couchdb/trunk/src/couchdb/couch_httpd_show.erl
    couchdb/trunk/src/couchdb/couch_httpd_view.erl

Modified: couchdb/trunk/THANKS
URL: http://svn.apache.org/viewvc/couchdb/trunk/THANKS?rev=1033676&r1=1033675&r2=1033676&view=diff
==============================================================================
--- couchdb/trunk/THANKS (original)
+++ couchdb/trunk/THANKS Wed Nov 10 19:44:05 2010
@@ -71,5 +71,6 @@ suggesting improvements or submitting ch
  * Klaus Trainer <klaus.trainer@web.de>
  * Dale Harvey <dale@arandomurl.com>
  * Juuso Väänänen <juuso@vaananen.org>
+ * Jeff Zellner <jeff.zellner@gmail.com>
 
 For a list of authors see the `AUTHORS` file.

Modified: couchdb/trunk/share/www/script/couch.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/couch.js?rev=1033676&r1=1033675&r2=1033676&view=diff
==============================================================================
--- couchdb/trunk/share/www/script/couch.js [utf-8] (original)
+++ couchdb/trunk/share/www/script/couch.js [utf-8] Wed Nov 10 19:44:05 2010
@@ -272,7 +272,7 @@ function CouchDB(name, httpHeaders) {
       for (var name in options) {
         if (!options.hasOwnProperty(name)) { continue; };
         var value = options[name];
-        if (name == "key" || name == "startkey" || name == "endkey") {
+        if (name == "key" || name == "keys" || name == "startkey" || name == "endkey") {
           value = toJSON(value);
         }
         buf.push(encodeURIComponent(name) + "=" + encodeURIComponent(value));

Modified: couchdb/trunk/share/www/script/test/list_views.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/test/list_views.js?rev=1033676&r1=1033675&r2=1033676&view=diff
==============================================================================
--- couchdb/trunk/share/www/script/test/list_views.js (original)
+++ couchdb/trunk/share/www/script/test/list_views.js Wed Nov 10 19:44:05 2010
@@ -327,6 +327,16 @@ couchTests.list_views = function(debug) 
   T(/FirstKey: 2/.test(xhr.responseText));
   T(/LastKey: 7/.test(xhr.responseText));
 
+  // multi-key fetch with GET
+  var xhr = CouchDB.request("GET", "/test_suite_db/_design/lists/_list/simpleForm/basicView"
+
+    "?keys=[2,4,5,7]");
+
+  T(xhr.status == 200, "multi key");
+  T(!(/Key: 1 /.test(xhr.responseText)));
+  T(/Key: 2/.test(xhr.responseText));
+  T(/FirstKey: 2/.test(xhr.responseText));
+  T(/LastKey: 7/.test(xhr.responseText));
+
   // no multi-key fetch allowed when group=false
   xhr = CouchDB.request("POST", "/test_suite_db/_design/lists/_list/simpleForm/withReduce?group=false",
{
     body: '{"keys":[2,4,5,7]}'

Modified: couchdb/trunk/share/www/script/test/view_multi_key_all_docs.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/test/view_multi_key_all_docs.js?rev=1033676&r1=1033675&r2=1033676&view=diff
==============================================================================
--- couchdb/trunk/share/www/script/test/view_multi_key_all_docs.js (original)
+++ couchdb/trunk/share/www/script/test/view_multi_key_all_docs.js Wed Nov 10 19:44:05 2010
@@ -25,24 +25,52 @@ couchTests.view_multi_key_all_docs = fun
   for(var i=0; i<rows.length; i++)
     T(rows[i].id == keys[i]);
 
+  // keys in GET parameters
+  rows = db.allDocs({keys:keys}, null).rows;
+  T(rows.length == keys.length);
+  for(var i=0; i<rows.length; i++)
+    T(rows[i].id == keys[i]);
+
   rows = db.allDocs({limit: 1}, keys).rows;
   T(rows.length == 1);
   T(rows[0].id == keys[0]);
 
+  // keys in GET parameters
+  rows = db.allDocs({limit: 1, keys: keys}, null).rows;
+  T(rows.length == 1);
+  T(rows[0].id == keys[0]);
+
   rows = db.allDocs({skip: 2}, keys).rows;
   T(rows.length == 3);
   for(var i=0; i<rows.length; i++)
       T(rows[i].id == keys[i+2]);
 
+  // keys in GET parameters
+  rows = db.allDocs({skip: 2, keys: keys}, null).rows;
+  T(rows.length == 3);
+  for(var i=0; i<rows.length; i++)
+      T(rows[i].id == keys[i+2]);
+
   rows = db.allDocs({descending: "true"}, keys).rows;
   T(rows.length == keys.length);
   for(var i=0; i<rows.length; i++)
       T(rows[i].id == keys[keys.length-i-1]);
 
+  // keys in GET parameters
+  rows = db.allDocs({descending: "true", keys: keys}, null).rows;
+  T(rows.length == keys.length);
+  for(var i=0; i<rows.length; i++)
+      T(rows[i].id == keys[keys.length-i-1]);
+
   rows = db.allDocs({descending: "true", skip: 3, limit:1}, keys).rows;
   T(rows.length == 1);
   T(rows[0].id == keys[1]);
 
+  // keys in GET parameters
+  rows = db.allDocs({descending: "true", skip: 3, limit:1, keys: keys}, null).rows;
+  T(rows.length == 1);
+  T(rows[0].id == keys[1]);
+
   // Check we get invalid rows when the key doesn't exist
   rows = db.allDocs({}, [1, "i_dont_exist", "0"]).rows;
   T(rows.length == 3);
@@ -51,4 +79,13 @@ couchTests.view_multi_key_all_docs = fun
   T(rows[1].error == "not_found");
   T(!rows[1].id);
   T(rows[2].id == rows[2].key && rows[2].key == "0");
+
+  // keys in GET parameters
+  rows = db.allDocs({keys: [1, "i_dont_exist", "0"]}, null).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: couchdb/trunk/share/www/script/test/view_multi_key_design.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/test/view_multi_key_design.js?rev=1033676&r1=1033675&r2=1033676&view=diff
==============================================================================
--- couchdb/trunk/share/www/script/test/view_multi_key_design.js (original)
+++ couchdb/trunk/share/www/script/test/view_multi_key_design.js Wed Nov 10 19:44:05 2010
@@ -54,6 +54,13 @@ couchTests.view_multi_key_design = funct
     T(rows[i].key == rows[i].value);
   }
 
+  // with GET keys
+  rows = db.view("test/all_docs",{keys:keys},null).rows;
+  for(var i=0;i<rows.length; i++) {
+    T(keys.indexOf(rows[i].key) != -1);
+    T(rows[i].key == rows[i].value);
+  }
+
   var reduce = db.view("test/summate",{group:true},keys).rows;
   T(reduce.length == keys.length);
   for(var i=0; i<reduce.length; i++) {
@@ -61,8 +68,18 @@ couchTests.view_multi_key_design = funct
     T(reduce[i].key == reduce[i].value);
   }
 
+  // with GET keys
+  reduce = db.view("test/summate",{group:true,keys:keys},null).rows;
+  T(reduce.length == keys.length);
+  for(var i=0; i<reduce.length; i++) {
+    T(keys.indexOf(reduce[i].key) != -1);
+    T(reduce[i].key == reduce[i].value);
+  }
+
   // Test that invalid parameter combinations get rejected
   var badargs = [{startkey:0}, {endkey:0}, {key: 0}, {group_level: 2}];
+  var getbadargs = [{startkey:0, keys:keys}, {endkey:0, keys:keys}, 
+      {key:0, keys:keys}, {group_level: 2, keys:keys}];
   for(var i in badargs)
   {
       try {
@@ -71,6 +88,13 @@ couchTests.view_multi_key_design = funct
       } catch (e) {
           T(e.error == "query_parse_error");
       }
+
+      try {
+          db.view("test/all_docs",getbadargs[i],null);
+          T(0==1);
+      } catch (e) {
+          T(e.error = "query_parse_error");
+      }
   }
 
   try {
@@ -80,10 +104,20 @@ couchTests.view_multi_key_design = funct
       T(e.error == "query_parse_error");
   }
 
+  try {
+      db.view("test/summate",{keys:keys},null);
+      T(0==1);
+  } catch (e) {
+      T(e.error == "query_parse_error");
+  }
+
   // Test that a map & reduce containing func support keys when reduce=false
   resp = db.view("test/summate", {reduce: false}, keys);
   T(resp.rows.length == 5);
 
+  resp = db.view("test/summate", {reduce: false, keys: keys}, null);
+  T(resp.rows.length == 5);
+
   // Check that limiting by startkey_docid and endkey_docid get applied
   // as expected.
   var curr = db.view("test/multi_emit", {startkey_docid: 21, endkey_docid: 23}, [0, 2]).rows;
@@ -96,34 +130,66 @@ couchTests.view_multi_key_design = funct
       T(curr[i].value == exp_val[i]);
   }
 
+  curr = db.view("test/multi_emit", {startkey_docid: 21, endkey_docid: 23, keys: [0, 2]},
null).rows;
+  T(curr.length == 6);
+  for( var i = 0 ; i < 6 ; i++)
+  {
+      T(curr[i].key == exp_key[i]);
+      T(curr[i].value == exp_val[i]);
+  }
+
   // Check limit works
   curr = db.view("test/all_docs", {limit: 1}, keys).rows;
   T(curr.length == 1);
   T(curr[0].key == 10);
 
+  curr = db.view("test/all_docs", {limit: 1, keys: keys}, null).rows;
+  T(curr.length == 1);
+  T(curr[0].key == 10);
+
   // Check offset works
   curr = db.view("test/multi_emit", {skip: 1}, [0]).rows;
   T(curr.length == 99);
   T(curr[0].value == 1);
 
+  curr = db.view("test/multi_emit", {skip: 1, keys: [0]}, null).rows;
+  T(curr.length == 99);
+  T(curr[0].value == 1);
+
   // Check that dir works
   curr = db.view("test/multi_emit", {descending: "true"}, [1]).rows;
   T(curr.length == 100);
   T(curr[0].value == 99);
   T(curr[99].value == 0);
 
+  curr = db.view("test/multi_emit", {descending: "true", keys: [1]}, null).rows;
+  T(curr.length == 100);
+  T(curr[0].value == 99);
+  T(curr[99].value == 0);
+
   // Check a couple combinations
   curr = db.view("test/multi_emit", {descending: "true", skip: 3, limit: 2}, [2]).rows;
   T(curr.length, 2);
   T(curr[0].value == 96);
   T(curr[1].value == 95);
 
+  curr = db.view("test/multi_emit", {descending: "true", skip: 3, limit: 2, keys: [2]}, null).rows;
+  T(curr.length, 2);
+  T(curr[0].value == 96);
+  T(curr[1].value == 95);
+
   curr = db.view("test/multi_emit", {skip: 2, limit: 3, startkey_docid: "13"}, [0]).rows;
   T(curr.length == 3);
   T(curr[0].value == 15);
   T(curr[1].value == 16);
   T(curr[2].value == 17);
 
+  curr = db.view("test/multi_emit", {skip: 2, limit: 3, startkey_docid: "13", keys: [0]},
null).rows;
+  T(curr.length == 3);
+  T(curr[0].value == 15);
+  T(curr[1].value == 16);
+  T(curr[2].value == 17);
+
   curr = db.view("test/multi_emit",
           {skip: 1, limit: 5, startkey_docid: "25", endkey_docid: "27"}, [1]).rows;
   T(curr.length == 2);
@@ -131,8 +197,20 @@ couchTests.view_multi_key_design = funct
   T(curr[1].value == 27);
 
   curr = db.view("test/multi_emit",
+          {skip: 1, limit: 5, startkey_docid: "25", endkey_docid: "27", keys: [1]}, null).rows;
+  T(curr.length == 2);
+  T(curr[0].value == 26);
+  T(curr[1].value == 27);
+
+  curr = db.view("test/multi_emit",
           {skip: 1, limit: 5, startkey_docid: "28", endkey_docid: "26", descending: "true"},
[1]).rows;
   T(curr.length == 2);
   T(curr[0].value == 27);
   T(curr[1].value == 26);
+
+  curr = db.view("test/multi_emit",
+          {skip: 1, limit: 5, startkey_docid: "28", endkey_docid: "26", descending: "true",
keys: [1]}, null).rows;
+  T(curr.length == 2);
+  T(curr[0].value == 27);
+  T(curr[1].value == 26);
 };

Modified: couchdb/trunk/src/couchdb/couch_httpd.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_httpd.erl?rev=1033676&r1=1033675&r2=1033676&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/couch_httpd.erl (original)
+++ couchdb/trunk/src/couchdb/couch_httpd.erl Wed Nov 10 19:44:05 2010
@@ -15,7 +15,8 @@
 
 -export([start_link/0, start_link/1, stop/0, handle_request/5]).
 
--export([header_value/2,header_value/3,qs_value/2,qs_value/3,qs/1,path/1,absolute_uri/2,body_length/1]).
+-export([header_value/2,header_value/3,qs_value/2,qs_value/3,qs/1,qs_json_value/3]).
+-export([path/1,absolute_uri/2,body_length/1]).
 -export([verify_is_server_admin/1,unquote/1,quote/1,recv/2,recv_chunked/4,error_info/1]).
 -export([make_fun_spec_strs/1]).
 -export([make_arity_1_fun/1, make_arity_2_fun/1, make_arity_3_fun/1]).
@@ -384,6 +385,14 @@ qs_value(Req, Key) ->
 qs_value(Req, Key, Default) ->
     couch_util:get_value(Key, qs(Req), Default).
 
+qs_json_value(Req, Key, Default) ->
+    case qs_value(Req, Key, Default) of
+    Default ->
+        Default;
+    Result ->
+        ?JSON_DECODE(Result)
+    end.
+
 qs(#httpd{mochi_req=MochiReq}) ->
     MochiReq:parse_qs().
 

Modified: couchdb/trunk/src/couchdb/couch_httpd_db.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_httpd_db.erl?rev=1033676&r1=1033675&r2=1033676&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/couch_httpd_db.erl (original)
+++ couchdb/trunk/src/couchdb/couch_httpd_db.erl Wed Nov 10 19:44:05 2010
@@ -375,7 +375,8 @@ db_req(#httpd{path_parts=[_,<<"_purge">>
     send_method_not_allowed(Req, "POST");
 
 db_req(#httpd{method='GET',path_parts=[_,<<"_all_docs">>]}=Req, Db) ->
-    all_docs_view(Req, Db, nil);
+    Keys = couch_httpd:qs_json_value(Req, "keys", nil),
+    all_docs_view(Req, Db, Keys);
 
 db_req(#httpd{method='POST',path_parts=[_,<<"_all_docs">>]}=Req, Db) ->
     couch_httpd:validate_ctype(Req, "application/json"),

Modified: couchdb/trunk/src/couchdb/couch_httpd_show.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_httpd_show.erl?rev=1033676&r1=1033675&r2=1033676&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/couch_httpd_show.erl (original)
+++ couchdb/trunk/src/couchdb/couch_httpd_show.erl Wed Nov 10 19:44:05 2010
@@ -153,12 +153,14 @@ send_doc_update_response(Req, Db, DDoc, 
 % view-list request with view and list from same design doc.
 handle_view_list_req(#httpd{method='GET',
         path_parts=[_, _, DesignName, _, ListName, ViewName]}=Req, Db, DDoc) ->
-    handle_view_list(Req, Db, DDoc, ListName, {DesignName, ViewName}, nil);
+    Keys = couch_httpd:qs_json_value(Req, "keys", nil),
+    handle_view_list(Req, Db, DDoc, ListName, {DesignName, ViewName}, Keys);
 
 % view-list request with view and list from different design docs.
 handle_view_list_req(#httpd{method='GET',
         path_parts=[_, _, _, _, ListName, ViewDesignName, ViewName]}=Req, Db, DDoc) ->
-    handle_view_list(Req, Db, DDoc, ListName, {ViewDesignName, ViewName}, nil);
+    Keys = couch_httpd:qs_json_value(Req, "keys", nil),
+    handle_view_list(Req, Db, DDoc, ListName, {ViewDesignName, ViewName}, Keys);
 
 handle_view_list_req(#httpd{method='GET'}=Req, _Db, _DDoc) ->
     send_error(Req, 404, <<"list_error">>, <<"Invalid path.">>);

Modified: couchdb/trunk/src/couchdb/couch_httpd_view.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_httpd_view.erl?rev=1033676&r1=1033675&r2=1033676&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/couch_httpd_view.erl (original)
+++ couchdb/trunk/src/couchdb/couch_httpd_view.erl Wed Nov 10 19:44:05 2010
@@ -57,7 +57,8 @@ design_doc_view(Req, Db, DName, ViewName
 
 handle_view_req(#httpd{method='GET',
         path_parts=[_, _, DName, _, ViewName]}=Req, Db, _DDoc) ->
-    design_doc_view(Req, Db, DName, ViewName, nil);
+    Keys = couch_httpd:qs_json_value(Req, "keys", nil),
+    design_doc_view(Req, Db, DName, ViewName, Keys);
 
 handle_view_req(#httpd{method='POST',
         path_parts=[_, _, DName, _, ViewName]}=Req, Db, _DDoc) ->



Mime
View raw message