From 029ab91dedcace264efa6b878859070ed4f6c673 Mon Sep 17 00:00:00 2001 From: Benoit Chesneau Date: Mon, 1 Feb 2010 13:46:26 +0000 Subject: improve object handling from query member of the rule. Allow to handle key/startkey/endkey like {"a", 1}, [1, 2], [{"a": 1], 2] ... git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@905284 13f79535-47bb-0310-9956-ffa450edef68 --- share/www/script/test/rewrite.js | 104 +++++++++++++++++++++++++++++++----- src/couchdb/couch_httpd_rewrite.erl | 35 +++++++----- 2 files changed, 112 insertions(+), 27 deletions(-) diff --git a/share/www/script/test/rewrite.js b/share/www/script/test/rewrite.js index 48e5edb4..46e7e477 100644 --- a/share/www/script/test/rewrite.js +++ b/share/www/script/test/rewrite.js @@ -67,12 +67,19 @@ couchTests.rewrite = function(debug) { } }, { - "from": "/welcome2/:name", + "from": "/welcome2", + "to": "_show/welcome", + "query": { + "name": "user" + } + }, + { + "from": "/welcome3/:name", "to": "_update/welcome2/:name", "method": "PUT" }, { - "from": "/welcome2/:name", + "from": "/welcome3/:name", "to": "_show/welcome2/:name", "method": "GET" }, @@ -95,8 +102,37 @@ couchTests.rewrite = function(debug) { "startkey": ":start", "endkey": ":end" } + }, + { + "from": "simpleForm/complexView", + "to": "_list/simpleForm/complexView", + "query": { + "key": [1, 2] + } + }, + { + "from": "simpleForm/complexView2", + "to": "_list/simpleForm/complexView", + "query": { + "key": ["test", {}] + } + }, + { + "from": "simpleForm/complexView3", + "to": "_list/simpleForm/complexView", + "query": { + "key": ["test", ["test", "essai"]] + } + }, + { + "from": "simpleForm/complexView4", + "to": "_list/simpleForm/complexView2", + "query": { + "key": {"c": 1} + } } + ], lists: { simpleForm: stringFun(function(head, req) { @@ -112,7 +148,7 @@ couchTests.rewrite = function(debug) { +' LineNo: '+row_number+''); } return '

FirstKey: '+ firstKey + ' LastKey: '+ prevKey+'

'; - }) + }), }, shows: { "welcome": stringFun(function(doc,req) { @@ -152,7 +188,24 @@ couchTests.rewrite = function(debug) { views : { basicView : { map : stringFun(function(doc) { - emit(doc.integer, doc.string); + if (doc.integer) { + emit(doc.integer, doc.string); + } + + }) + }, + complexView: { + map: stringFun(function(doc) { + if (doc.type == "complex") { + emit([doc.a, doc.b], doc.string); + } + }) + }, + complexView2: { + map: stringFun(function(doc) { + if (doc.type == "complex") { + emit(doc.a, doc.string); + } }) } } @@ -162,7 +215,17 @@ couchTests.rewrite = function(debug) { var docs = makeDocs(0, 10); db.bulkSave(docs); - + + var docs2 = [ + {"a": 1, "b": 1, "string": "doc 1", "type": "complex"}, + {"a": 1, "b": 2, "string": "doc 2", "type": "complex"}, + {"a": "test", "b": {}, "string": "doc 3", "type": "complex"}, + {"a": "test", "b": ["test", "essai"], "string": "doc 4", "type": "complex"}, + {"a": {"c": 1}, "b": "", "string": "doc 5", "type": "complex"} + ]; + + db.bulkSave(docs2); + // test simple rewriting req = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/foo"); @@ -190,21 +253,22 @@ couchTests.rewrite = function(debug) { doc = db.open(docid); T(doc.world == "hello"); - xhr = CouchDB.request("PUT", "/test_suite_db/_design/test/_rewrite/welcome2/test"); - T(xhr.status == 201); - T(xhr.responseText == "New World"); - T(/charset=utf-8/.test(xhr.getResponseHeader("Content-Type"))); - - xhr = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/welcome2/test"); - T(xhr.responseText == "Welcome test"); - req = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/welcome?name=user"); T(req.responseText == "Welcome user"); req = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/welcome/user"); T(req.responseText == "Welcome user"); + req = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/welcome2"); + T(req.responseText == "Welcome user"); + + xhr = CouchDB.request("PUT", "/test_suite_db/_design/test/_rewrite/welcome3/test"); + T(xhr.status == 201); + T(xhr.responseText == "New World"); + T(/charset=utf-8/.test(xhr.getResponseHeader("Content-Type"))); + xhr = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/welcome3/test"); + T(xhr.responseText == "Welcome test"); // get with query params @@ -234,8 +298,22 @@ couchTests.rewrite = function(debug) { T(/FirstKey: 3/.test(xhr.responseText)); T(/LastKey: 8/.test(xhr.responseText)); + // get with query params + xhr = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/simpleForm/complexView"); + T(xhr.status == 200, "with query params"); + T(/FirstKey: [1, 2]/.test(xhr.responseText)); + + xhr = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/simpleForm/complexView2"); + T(xhr.status == 200, "with query params"); + T(/Value: doc 3/.test(xhr.responseText)); + xhr = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/simpleForm/complexView3"); + T(xhr.status == 200, "with query params"); + T(/Value: doc 4/.test(xhr.responseText)); + xhr = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/simpleForm/complexView4"); + T(xhr.status == 200, "with query params"); + T(/Value: doc 5/.test(xhr.responseText)); }); } \ No newline at end of file diff --git a/src/couchdb/couch_httpd_rewrite.erl b/src/couchdb/couch_httpd_rewrite.erl index 452873d9..364e6c4d 100644 --- a/src/couchdb/couch_httpd_rewrite.erl +++ b/src/couchdb/couch_httpd_rewrite.erl @@ -229,30 +229,32 @@ try_bind_path([Dispatch|Rest], Method, PathParts, QueryList) -> make_query_list([], _Bindings, Acc) -> Acc; make_query_list([{Key, {Value}}|Rest], Bindings, Acc) -> - Value1 = make_query_list(Value, Bindings, []), + Value1 = to_json({Value}), make_query_list(Rest, Bindings, [{to_atom(Key), Value1}|Acc]); make_query_list([{Key, Value}|Rest], Bindings, Acc) when is_binary(Value) -> - Value1 = replace_var(Value, Bindings), + Value1 = replace_var(Key, Value, Bindings), make_query_list(Rest, Bindings, [{to_atom(Key), Value1}|Acc]); make_query_list([{Key, Value}|Rest], Bindings, Acc) when is_list(Value) -> - - Value1 = replace_vars(Value, Bindings, []), + Value1 = replace_var(Key, Value, Bindings), make_query_list(Rest, Bindings, [{to_atom(Key), Value1}|Acc]); make_query_list([{Key, Value}|Rest], Bindings, Acc) -> make_query_list(Rest, Bindings, [{to_atom(Key), Value}|Acc]). -replace_vars([], _Bindings, Acc) -> - lists:reverse(Acc); -replace_vars([V|R], Bindings, Acc) -> - V1 = replace_var(V, Bindings), - replace_vars(R, Bindings, [V1|Acc]). - -replace_var(Value, Bindings) -> +replace_var(Key, Value, Bindings) -> case Value of <<":", Var/binary>> -> Var1 = list_to_atom(binary_to_list(Var)), proplists:get_value(Var1, Bindings, Value); - _ -> Value + _ when is_binary(Value) -> + Value; + _ -> + case Key of + <<"key">> -> to_json(Value); + <<"startkey">> -> to_json(Value); + <<"endkey">> -> to_json(Value); + _ -> + lists:flatten(?JSON_ENCODE(Value)) + end end. @@ -371,15 +373,17 @@ path_to_list([P|R], Acc) -> path_to_list(R, [P1|Acc]). encode_query(Props) -> - RevPairs = lists:foldl(fun ({K, V}, Acc) -> + Props1 = lists:foldl(fun ({K, V}, Acc) -> V1 = case is_list(V) of true -> V; + false when is_binary(V) -> + V; false -> mochiweb_util:quote_plus(V) end, [{K, V1} | Acc] end, [], Props), - lists:flatten(mochiweb_util:urlencode(RevPairs)). + lists:flatten(mochiweb_util:urlencode(Props1)). to_atom(V) when is_atom(V) -> V; @@ -387,3 +391,6 @@ to_atom(V) when is_binary(V) -> to_atom(?b2l(V)); to_atom(V) -> list_to_atom(V). + +to_json(V) -> + iolist_to_binary(?JSON_ENCODE(V)). -- cgit v1.2.3