| 'use strict'; |
| |
| var upsert = require('./upsert'); |
| var utils = require('./utils'); |
| var Promise = utils.Promise; |
| |
| module.exports = function (opts) { |
| var sourceDB = opts.db; |
| var viewName = opts.viewName; |
| var mapFun = opts.map; |
| var reduceFun = opts.reduce; |
| var temporary = opts.temporary; |
| |
| // the "undefined" part is for backwards compatibility |
| var viewSignature = mapFun.toString() + (reduceFun && reduceFun.toString()) + |
| 'undefined'; |
| |
| if (!temporary && sourceDB._cachedViews) { |
| var cachedView = sourceDB._cachedViews[viewSignature]; |
| if (cachedView) { |
| return Promise.resolve(cachedView); |
| } |
| } |
| |
| return sourceDB.info().then(function (info) { |
| |
| var depDbName = info.db_name + '-mrview-' + |
| (temporary ? 'temp' : utils.MD5(viewSignature)); |
| |
| // save the view name in the source db so it can be cleaned up if necessary |
| // (e.g. when the _design doc is deleted, remove all associated view data) |
| function diffFunction(doc) { |
| doc.views = doc.views || {}; |
| var fullViewName = viewName; |
| if (fullViewName.indexOf('/') === -1) { |
| fullViewName = viewName + '/' + viewName; |
| } |
| var depDbs = doc.views[fullViewName] = doc.views[fullViewName] || {}; |
| /* istanbul ignore if */ |
| if (depDbs[depDbName]) { |
| return; // no update necessary |
| } |
| depDbs[depDbName] = true; |
| return doc; |
| } |
| return upsert(sourceDB, '_local/mrviews', diffFunction).then(function () { |
| return sourceDB.registerDependentDatabase(depDbName).then(function (res) { |
| var db = res.db; |
| db.auto_compaction = true; |
| var view = { |
| name: depDbName, |
| db: db, |
| sourceDB: sourceDB, |
| adapter: sourceDB.adapter, |
| mapFun: mapFun, |
| reduceFun: reduceFun |
| }; |
| return view.db.get('_local/lastSeq').catch(function (err) { |
| /* istanbul ignore if */ |
| if (err.status !== 404) { |
| throw err; |
| } |
| }).then(function (lastSeqDoc) { |
| view.seq = lastSeqDoc ? lastSeqDoc.seq : 0; |
| if (!temporary) { |
| sourceDB._cachedViews = sourceDB._cachedViews || {}; |
| sourceDB._cachedViews[viewSignature] = view; |
| view.db.on('destroyed', function () { |
| delete sourceDB._cachedViews[viewSignature]; |
| }); |
| } |
| return view; |
| }); |
| }); |
| }); |
| }); |
| }; |