From 46bf4b727f0fae37b017f194983122c50d3f34e5 Mon Sep 17 00:00:00 2001 From: John Christopher Anderson Date: Mon, 20 Jul 2009 04:11:36 +0000 Subject: Initial checkin of _changes filters. The prime weak-spot for this approach is that it maintains an OS-process per connected filtered _changes consumer. I'm pretty sure we'll be able to work around this without changing the API, but it'll involve a lot of OS-process bookkeeping. Those enhancements should generally improve show & list performance as well. Punting on them for now, first wanted to get _changes filters implemented so people could give feedback. git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@795687 13f79535-47bb-0310-9956-ffa450edef68 --- share/Makefile.am | 1 + share/server/filter.js | 25 ++++++++++++++++ share/server/loop.js | 3 +- share/www/script/test/changes.js | 62 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 share/server/filter.js (limited to 'share') diff --git a/share/Makefile.am b/share/Makefile.am index 99a05426..d1cdb457 100644 --- a/share/Makefile.am +++ b/share/Makefile.am @@ -13,6 +13,7 @@ JS_FILE = server/main.js JS_FILE_COMPONENTS = \ + server/filter.js \ server/render.js \ server/state.js \ server/util.js \ diff --git a/share/server/filter.js b/share/server/filter.js new file mode 100644 index 00000000..23536db0 --- /dev/null +++ b/share/server/filter.js @@ -0,0 +1,25 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +var Filter = { + filter : function(docs, req, userCtx) { + var results = []; + try { + for (var i=0; i < docs.length; i++) { + results.push((funs[0](docs[i], req, userCtx) && true) || false); + }; + respond([true, results]); + } catch (error) { + respond(error); + } + } +}; diff --git a/share/server/loop.js b/share/server/loop.js index d65ff02b..af656121 100644 --- a/share/server/loop.js +++ b/share/server/loop.js @@ -41,7 +41,8 @@ var dispatch = { "rereduce" : Views.rereduce, "validate" : Validate.validate, "show" : Render.show, - "list" : Render.list + "list" : Render.list, + "filter" : Filter.filter }; while (line = eval(readline())) { diff --git a/share/www/script/test/changes.js b/share/www/script/test/changes.js index f2d33c17..f5a3e149 100644 --- a/share/www/script/test/changes.js +++ b/share/www/script/test/changes.js @@ -110,4 +110,66 @@ couchTests.changes = function(debug) { T(str.charAt(str.length - 1) == "\n") T(str.charAt(str.length - 2) == "\n") } + + // test the filtered changes + var ddoc = { + _id : "_design/changes_filter", + "filters" : { + "bop" : "function(doc, req, userCtx) { return (doc.bop);}", + "dynamic" : stringFun(function(doc, req, userCtx) { + var field = req.query.field; + return doc[field]; + }), + "userCtx" : stringFun(function(doc, req, userCtx) { + return doc.user && (doc.user == userCtx.name); + }) + } + } + + db.save(ddoc); + + var req = CouchDB.request("GET", "/test_suite_db/_changes?filter=changes_filter/bop"); + var resp = JSON.parse(req.responseText); + T(resp.results.length == 0); + + db.save({"bop" : "foom"}); + + var req = CouchDB.request("GET", "/test_suite_db/_changes?filter=changes_filter/bop"); + var resp = JSON.parse(req.responseText); + T(resp.results.length == 1); + + req = CouchDB.request("GET", "/test_suite_db/_changes?filter=changes_filter/dynamic&field=woox"); + resp = JSON.parse(req.responseText); + T(resp.results.length == 0); + + req = CouchDB.request("GET", "/test_suite_db/_changes?filter=changes_filter/dynamic&field=bop"); + resp = JSON.parse(req.responseText); + T(resp.results.length == 1); + + // test for userCtx + run_on_modified_server( + [{section: "httpd", + key: "authentication_handler", + value: "{couch_httpd, special_test_authentication_handler}"}, + {section:"httpd", + key: "WWW-Authenticate", + value: "X-Couch-Test-Auth"}], + + function() { + var authOpts = {"headers":{"WWW-Authenticate": "X-Couch-Test-Auth Chris Anderson:mp3"}}; + + T(db.save({"user" : "Noah Slater"}).ok); + var req = CouchDB.request("GET", "/test_suite_db/_changes?filter=changes_filter/userCtx", authOpts); + var resp = JSON.parse(req.responseText); + T(resp.results.length == 0); + + var docResp = db.save({"user" : "Chris Anderson"}); + T(docResp.ok); + req = CouchDB.request("GET", "/test_suite_db/_changes?filter=changes_filter/userCtx", authOpts); + resp = JSON.parse(req.responseText); + T(resp.results.length == 1); + T(resp.results[0].id == docResp.id); + }); + + // todo implement adhoc filters... }; -- cgit v1.2.3