diff options
-rw-r--r-- | share/www/script/futon.browse.js | 9 | ||||
-rw-r--r-- | share/www/script/jquery.couch.js | 7 | ||||
-rw-r--r-- | share/www/script/test/view_errors.js | 37 | ||||
-rw-r--r-- | src/couchdb/couch_httpd_view.erl | 9 |
4 files changed, 55 insertions, 7 deletions
diff --git a/share/www/script/futon.browse.js b/share/www/script/futon.browse.js index 5fd09f94..876866e0 100644 --- a/share/www/script/futon.browse.js +++ b/share/www/script/futon.browse.js @@ -301,7 +301,7 @@ page.storedViewLanguage = page.viewLanguage; if (callback) callback(); } - }); + },{async:false}); } else { page.updateViewEditor(page.storedViewCode.map, page.storedViewCode.reduce || ""); @@ -467,9 +467,6 @@ if (options.limit === undefined) { options.limit = parseInt($("#perpage").val(), 10); } - if (options.group === undefined) { - options.group = true; - } if ($("#documents thead th.key").is(".desc")) { if (typeof options.descending == 'undefined') options.descending = true; var descend = true; @@ -589,6 +586,7 @@ var reduceFun = $("#viewcode_reduce").val() || null; if (reduceFun != null) { $.cookies.set(db.name + ".reduce", reduceFun); + options.group = true; } else { $.cookies.remove(db.name + ".reduce"); } @@ -602,6 +600,9 @@ $("#viewcode").show(); var currentMapCode = $("#viewcode_map").val(); var currentReduceCode = $("#viewcode_reduce").val() || null; + if (currentReduceCode) { + options.group = true; + } if (page.isDirty) { db.query(currentMapCode, currentReduceCode, page.viewLanguage, options); } else { diff --git a/share/www/script/jquery.couch.js b/share/www/script/jquery.couch.js index ace9a8a6..d6aa512e 100644 --- a/share/www/script/jquery.couch.js +++ b/share/www/script/jquery.couch.js @@ -205,9 +205,10 @@ alert("please provide an eachApp function for allApps()"); } }, - openDoc: function(docId, options) { + openDoc: function(docId, options, ajaxOptions) { options = options || {}; - $.ajax({ + ajaxOptions = ajaxOptions || {}; + $.ajax($.extend({ type: "GET", url: this.uri + encodeURIComponent(docId) + encodeOptions(options), dataType: "json", @@ -221,7 +222,7 @@ alert("The document could not be retrieved: " + resp.reason); } } - }); + }, ajaxOptions)); }, saveDoc: function(doc, options) { options = options || {}; diff --git a/share/www/script/test/view_errors.js b/share/www/script/test/view_errors.js index 66fdfa69..aa698f4d 100644 --- a/share/www/script/test/view_errors.js +++ b/share/www/script/test/view_errors.js @@ -49,4 +49,41 @@ couchTests.view_errors = function(debug) { }) }); T(JSON.parse(xhr.responseText).error == "invalid_json"); + + var map = function (doc) {emit(doc.integer, doc.integer);}; + + try { + db.query(map, null, {group: true}); + T(0 == 1); + } catch(e) { + T(e.error == "query_parse_error"); + } + + // reduce=false on map views doesn't work, so group=true will + // never throw for temp reduce views. + + var designDoc = { + _id:"_design/test", + language: "javascript", + views: { + no_reduce: {map:"function(doc) {emit(doc._id, null);}"}, + with_reduce: {map:"function (doc) {emit(doc.integer, doc.integer)};", + reduce:"function (keys, values) { return sum(values); };"}, + } + }; + T(db.save(designDoc).ok); + + try { + db.view("test/no_reduce", {group: true}); + T(0 == 1); + } catch(e) { + T(e.error == "query_parse_error"); + } + + try { + db.view("test/with_reduce", {group: true, reduce: false}); + T(0 == 1); + } catch(e) { + T(e.error == "query_parse_error"); + } }; diff --git a/src/couchdb/couch_httpd_view.erl b/src/couchdb/couch_httpd_view.erl index 4e922d50..f5f0f5f4 100644 --- a/src/couchdb/couch_httpd_view.erl +++ b/src/couchdb/couch_httpd_view.erl @@ -97,6 +97,7 @@ output_map_view(Req, View, Group, Db, QueryArgs, nil) -> start_key = StartKey, start_docid = StartDocId } = QueryArgs, + validate_map_query(QueryArgs), CurrentEtag = view_group_etag(Group), couch_httpd:etag_respond(Req, CurrentEtag, fun() -> {ok, RowCount} = couch_view:get_row_count(View), @@ -114,6 +115,7 @@ output_map_view(Req, View, Group, Db, QueryArgs, Keys) -> skip = SkipCount, start_docid = StartDocId } = QueryArgs, + validate_map_query(QueryArgs), CurrentEtag = view_group_etag(Group, Keys), couch_httpd:etag_respond(Req, CurrentEtag, fun() -> {ok, RowCount} = couch_view:get_row_count(View), @@ -134,6 +136,13 @@ output_map_view(Req, View, Group, Db, QueryArgs, Keys) -> finish_view_fold(Req, RowCount, FoldResult) end). +validate_map_query(QueryArgs) -> + case QueryArgs#view_query_args.group_level of + 0 -> ok; + _ -> + throw({query_parse_error, <<"Query parameter \"group\" and/or \"group_level\" are invalid for map views.">>}) + end. + output_reduce_view(Req, View, Group, QueryArgs, nil) -> #view_query_args{ start_key = StartKey, |