rethinkdbdash
Version:
A Node.js driver for RethinkDB with promises and a connection pool
1,428 lines (1,281 loc) • 104 kB
JavaScript
var Promise = require('bluebird');
var protodef = require(__dirname+'/protodef.js');
var termTypes = protodef.Term.TermType;
var Error = require(__dirname+'/error.js');
var helper = require(__dirname+'/helper.js');
var ReadableStream = require(__dirname+'/stream.js');
var WritableStream = require(__dirname+'/writable_stream.js');
var TransformStream = require(__dirname+'/transform_stream.js');
function Term(r, value, error) {
var self = this;
var term = function(field) {
if (Term.prototype._fastArity(arguments.length, 1) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
Term.prototype._arity(_args, 1, '(...)', self);
}
return term.bracket(field);
}
helper.changeProto(term, self);
if (value === undefined) {
term._query = [];
}
else {
term._query = value;
}
term._r = r; // Keep a reference to r for global settings
if (error !== undefined) {
term._error = error;
term._frames = [];
}
return term;
}
// run([connection][, options][, callback])
Term.prototype.run = function(connection, options, callback) {
var self = this;
if (self._error != null) {
var error = new Error.ReqlRuntimeError(self._error, self._query, {b: self._frames});
return Promise.reject(error);
}
if (helper.isPlainObject(connection) && (typeof connection._isConnection === 'function') && (connection._isConnection() === true)) {
if (typeof options === 'function') {
callback = options;
options = {};
}
else {
if (!helper.isPlainObject(options)) options = {};
}
if (connection._isOpen() !== true) {
return new Promise(function(resolve, reject) {
reject(new Error.ReqlDriverError('`run` was called with a closed connection', self._query).setOperational());
});
}
var p = new Promise(function(resolve, reject) {
var token = connection._getToken();
var query = [protodef.Query.QueryType.START];
query.push(self._query);
var _options = {};
var sendOptions = false;
if (connection.db != null) {
sendOptions = true;
_options.db = self._r.db(connection.db)._query;
}
if (self._r.arrayLimit != null) {
sendOptions = true;
_options[self._translateArgs['arrayLimit']] = self._r.arrayLimit;
};
var keepGoing = true; // we need it just to avoir calling resolve/reject multiple times
helper.loopKeys(options, function(options, key) {
if (keepGoing === true) {
if ((key === 'readMode') || (key === 'durability') || (key === 'db') ||
(key === 'noreply') || (key === 'arrayLimit') || (key === 'profile') ||
(key === 'minBatchRows') || (key === 'maxBatchRows') || (key === 'maxBatchBytes') ||
(key === 'maxBatchSeconds') || (key === 'firstBatchScaledownFactor')) {
sendOptions = true;
if (key === 'db') {
_options[key] = self._r.db(options[key])._query;
}
else if (self._translateArgs.hasOwnProperty(key)) {
_options[self._translateArgs[key]] = new Term(self._r).expr(options[key])._query;
}
else {
_options[key] = new Term(self._r).expr(options[key])._query;
}
}
else if ((key !== 'timeFormat') && (key !== 'groupFormat') &&
(key !== 'binaryFormat') && (key !== 'cursor') &&
(key !== 'readable') && (key !== 'writable') &&
(key !== 'transform') && (key !== 'stream') &&
(key !== 'highWaterMark')) {
reject(new Error.ReqlDriverError('Unrecognized option `'+key+'` in `run`. Available options are readMode <string>, durability <string>, noreply <bool>, timeFormat <string>, groupFormat: <string>, profile <bool>, binaryFormat <bool>, cursor <bool>, stream <bool>'));
keepGoing = false;
}
}
});
if (keepGoing === false) {
connection.emit('release');
return // The promise was rejected in the loopKeys
}
if (sendOptions === true) {
query.push(_options);
}
connection._send(query, token, resolve, reject, self._query, options);
}).nodeify(callback);
}
else {
var poolMaster = self._r.getPoolMaster(); // if self._r is defined, so is self._r.getPool()
if (!poolMaster) {
throw new Error.ReqlDriverError('`run` was called without a connection and no pool has been created', self._query);
}
else {
if (typeof connection === 'function') {
// run(callback);
callback = connection;
options = {};
}
else if (helper.isPlainObject(connection)) {
// run(options[, callback])
callback = options;
options = connection;
}
else {
options = {};
}
var p = new Promise(function(resolve, reject) {
poolMaster.getConnection().then(function(connection) {
var token = connection._getToken();
var query = [protodef.Query.QueryType.START];
query.push(self._query);
var _options = {};
var sendOptions = false;
if (connection.db != null) {
sendOptions = true;
_options.db = self._r.db(connection.db)._query;
}
if (self._r.arrayLimit != null) {
sendOptions = true;
_options[self._translateArgs['arrayLimit']] = self._r.arrayLimit;
};
var keepGoing = true;
helper.loopKeys(options, function(options, key) {
if (keepGoing === true) {
if ((key === 'readMode') || (key === 'durability') || (key === 'db') ||
(key === 'noreply') || (key === 'arrayLimit') || (key === 'profile') ||
(key === 'minBatchRows') || (key === 'maxBatchRows') || (key === 'maxBatchBytes') ||
(key === 'maxBatchSeconds') || (key === 'firstBatchScaledownFactor')) {
sendOptions = true;
if (key === 'db') {
_options[key] = self._r.db(options[key])._query;
}
else if (self._translateArgs.hasOwnProperty(key)) {
_options[self._translateArgs[key]] = new Term(self._r).expr(options[key])._query
}
else {
_options[key] = new Term(self._r).expr(options[key])._query
}
}
else if ((key !== 'timeFormat') && (key !== 'groupFormat') &&
(key !== 'binaryFormat') && (key !== 'cursor') &&
(key !== 'readable') && (key !== 'writable') &&
(key !== 'transform') && (key !== 'stream') &&
(key !== 'highWaterMark')) {
setTimeout( function() {
reject(new Error.ReqlDriverError('Unrecognized option `'+key+'` in `run`. Available options are readMode <string>, durability <string>, noreply <bool>, timeFormat <string>, groupFormat: <string>, profile <bool>, binaryFormat <string>, cursor <bool>, stream <bool>'));
}, 0);
keepGoing = false;
return false;
}
}
});
if (keepGoing === false) {
connection.emit('release');
return // The promise was rejected in the loopKeys
}
if (sendOptions === true) {
query.push(_options);
}
connection._send(query, token, resolve, reject, self._query, options);
}).error(function(error) {
reject(error);
});
}).nodeify(callback);
}
}
//if (options.noreply) return self; // Do not return a promise if the user ask for no reply.
return p;
}
Term.prototype.toStream = function(connection, options) {
if (helper.isPlainObject(connection) && (typeof connection._isConnection === 'function') && (connection._isConnection() === true)) {
if (helper.isPlainObject(options) === false) {
options = {};
}
if (options.readable === true) {
return this._toReadableStream(connection, options);
}
else if (options.writable === true) {
return this._toWritableStream(connection, options);
}
else if (options.transform === true) {
return this._toTransformStream(connection, options);
}
else {
return this._toReadableStream(connection, options);
}
}
else {
options = connection;
if (helper.isPlainObject(options) === false) {
options = {};
}
if (options.readable === true) {
return this._toReadableStream(options);
}
else if (options.writable === true) {
return this._toWritableStream(options);
}
else if (options.transform === true) {
return this._toTransformStream(options);
}
else {
return this._toReadableStream(options);
}
}
}
Term.prototype._toReadableStream = function(connection, options) {
var stream;
var _options = {};
if (helper.isPlainObject(connection) && (typeof connection._isConnection === 'function') && (connection._isConnection() === true)) {
//toStream make sure that options is an object
helper.loopKeys(options, function(obj, key) {
_options[key] = obj[key];
});
_options.cursor = true;
stream = new ReadableStream(_options);
this.run(connection, _options).then(function(cursor) {
stream._setCursor(cursor);
return null;
}).error(function(error) {
stream.emit('error', error);
});
}
else {
helper.loopKeys(connection, function(obj, key) {
_options[key] = obj[key];
});
_options.cursor = true;
stream = new ReadableStream(_options);
this.run(_options).then(function(cursor) {
stream._setCursor(cursor);
return null;
}).error(function(error) {
stream.emit('error', error);
});
}
return stream;
}
Term.prototype._toWritableStream = function(connection, options) {
if (this._query[0] !== termTypes.TABLE) {
throw new Error.ReqlDriverError('Cannot create a writable stream on something else than a table.');
}
if (helper.isPlainObject(connection) && (typeof connection._isConnection === 'function') && (connection._isConnection() === true)) {
return new WritableStream(this, options, connection);
}
else {
return new WritableStream(this, connection);
}
}
Term.prototype._toTransformStream = function(connection, options) {
if (this._query[0] !== termTypes.TABLE) {
throw new Error.ReqlDriverError('Cannot create a writable stream on something else than a table.');
}
if (helper.isPlainObject(connection) && (typeof connection._isConnection === 'function') && (connection._isConnection() === true)) {
return new TransformStream(this, options, connection);
}
else {
return new TransformStream(this, connection);
}
}
// Manipulating databases
Term.prototype.dbCreate = function(db) {
// Check for arity is done in r.prototype.dbCreate
this._noPrefix(this, 'dbCreate');
var term = new Term(this._r);
term._query.push(termTypes.DB_CREATE);
var args = [new Term(this._r).expr(db)._query]
term._fillArgs(args);
return term;
}
Term.prototype.dbDrop = function(db) {
this._noPrefix(this, 'dbDrop');
var term = new Term(this._r);
term._query.push(termTypes.DB_DROP);
var args = [new Term(this._r).expr(db)._query]
term._fillArgs(args);
return term;
}
Term.prototype.dbList = function() {
this._noPrefix(this, 'dbList');
var term = new Term(this._r);
term._query.push(termTypes.DB_LIST)
return term;
}
// Manipulating Tables
Term.prototype.tableCreate = function(table, options) {
var self = this;
if (self._fastArityRange(arguments.length, 1, 2) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
self._arityRange(_args, 1, 2, 'tableCreate', self);
}
var term = new Term(self._r);
term._query.push(termTypes.TABLE_CREATE)
var args = [];
if (Array.isArray(self._query) && (self._query.length > 0)) {
args.push(self); // Push db
}
args.push(new Term(self._r).expr(table))
term._fillArgs(args);
if (helper.isPlainObject(options)) {
// Check for non valid key
helper.loopKeys(options, function(obj, key) {
if ((key !== 'primaryKey')
&& (key !== 'durability')
&& (key !== 'shards')
&& (key !== 'replicas')
&& (key !== 'primaryReplicaTag')) {
throw new Error.ReqlDriverError('Unrecognized option `'+key+'` in `tableCreate`', self._query, 'Available options are primaryKey <string>, durability <string>, shards <number>, replicas <number/object>, primaryReplicaTag <object>');
}
});
term._query.push(new Term(self._r).expr(translateOptions(options))._query);
}
return term;
}
Term.prototype.tableDrop = function(table) {
if (this._fastArity(arguments.length, 1) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arity(_args, 1, 'tableDrop', this);
}
var term = new Term(this._r);
term._query.push(termTypes.TABLE_DROP)
var args = [];
if (!Array.isArray(this._query) || (this._query.length > 0)) {
args.push(this); // push db
}
args.push(new Term(this._r).expr(table))
term._fillArgs(args);
return term;
}
Term.prototype.tableList = function() {
if (this._fastArity(arguments.length, 0) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arity(_args, 0, 'tableList', this);
}
var term = new Term(this._r);
term._query.push(termTypes.TABLE_LIST);
var args = [];
if (!Array.isArray(this._query) || (this._query.length > 0)) {
args.push(this);
}
term._fillArgs(args);
return term;
}
Term.prototype.indexList = function() {
if (this._fastArity(arguments.length, 0) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arity(_args, 0, 'indexList', this);
}
var term = new Term(this._r);
term._query.push(termTypes.INDEX_LIST);
var args = [this];
term._fillArgs(args);
return term;
}
Term.prototype.indexCreate = function(name, fn, options) {
if (this._fastArityRange(arguments.length, 1, 3) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arityRange(_args, 1, 3, 'indexCreate', this);
}
if ((options == null) && (helper.isPlainObject(fn))) {
options = fn;
fn = undefined;
}
var term = new Term(this._r);
term._query.push(termTypes.INDEX_CREATE);
var args = [this];
args.push(new Term(this._r).expr(name));
if (typeof fn !== 'undefined') args.push(new Term(this._r).expr(fn)._wrap());
term._fillArgs(args);
if (helper.isPlainObject(options)) {
// There is no need to translate here
helper.loopKeys(options, function(obj, key) {
if ((key !== 'multi') && (key !== 'geo')) {
throw new Error.ReqlDriverError('Unrecognized option `'+key+'` in `indexCreate`', self._query, 'Available option is multi <bool> and geo <bool>');
}
});
term._query.push(new Term(this._r).expr(options)._query);
}
return term;
}
Term.prototype.indexDrop = function(name) {
if (this._fastArity(arguments.length, 1) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arity(_args, 1, 'indexDrop', this);
}
var term = new Term(this._r);
term._query.push(termTypes.INDEX_DROP);
var args = [this, new Term(this._r).expr(name)];
term._fillArgs(args);
return term;
}
Term.prototype.indexStatus = function() {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
var term = new Term(this._r);
term._query.push(termTypes.INDEX_STATUS);
var args = [this];
for(var i=0; i<_args.length; i++) {
args.push(new Term(this._r).expr(_args[i]))
}
term._fillArgs(args);
return term;
}
Term.prototype.indexWait = function() {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
var term = new Term(this._r);
term._query.push(termTypes.INDEX_WAIT);
var args = [this];
for(var i=0; i<_args.length; i++) {
args.push(new Term(this._r).expr(_args[i]))
}
term._fillArgs(args);
return term;
}
Term.prototype.indexRename = function(oldName, newName, options) {
var self = this;
if (self._fastArityRange(arguments.length, 2, 3) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
self._arityRange(_args, 2, 3, 'indexRename', self);
}
var term = new Term(this._r);
term._query.push(termTypes.INDEX_RENAME);
var args = [this, new Term(this._r).expr(oldName), new Term(this._r).expr(newName)];
term._fillArgs(args);
if (helper.isPlainObject(options)) {
helper.loopKeys(options, function(obj, key) {
if (key !== 'overwrite') {
throw new Error.ReqlDriverError('Unrecognized option `'+key+'` in `indexRename`', self._query, 'Available options are overwrite <bool>');
}
});
term._query.push(new Term(self._r).expr(translateOptions(options))._query);
}
return term;
}
Term.prototype.changes = function(options) {
var self = this;
if (self._fastArityRange(arguments.length, 0, 1) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
self._arityRange(_args, 0, 1, 'changes', self);
}
var term = new Term(self._r);
term._query.push(termTypes.CHANGES);
var args = [self];
term._fillArgs(args);
if (helper.isPlainObject(options)) {
helper.loopKeys(options, function(obj, key) {
if ((key !== 'squash') && (key !== 'includeStates') && (key !== 'includeTypes')
&& (key !== 'includeInitial') && (key !== 'includeOffsets')) {
throw new Error.ReqlDriverError('Unrecognized option `'+key+'` in `changes`', self._query,
'Available options are squash <bool>, includeInitial <bool>, includeStates <bool>, includeOffsets <bool>, includeTypes <bool>');
}
});
term._query.push(new Term(self._r).expr(translateOptions(options))._query);
}
return term;
}
// Writing data
Term.prototype.insert = function(documents, options) {
var self = this;
if (self._fastArityRange(arguments.length, 1, 2) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
self._arityRange(_args, 1, 2, 'insert', self);
}
var term = new Term(self._r);
term._query.push(termTypes.INSERT);
var args = [self, new Term(self._r).expr(documents)];
term._fillArgs(args);
if (helper.isPlainObject(options)) {
helper.loopKeys(options, function(obj, key) {
if ((key !== 'returnChanges') && (key !== 'durability') && (key !== 'conflict')) {
throw new Error.ReqlDriverError('Unrecognized option `'+key+'` in `insert`', self._query, 'Available options are returnChanges <bool>, durability <string>, conflict <string>');
}
});
term._query.push(new Term(self._r).expr(translateOptions(options))._query);
}
return term;
}
Term.prototype.update = function(newValue, options) {
var self = this;
if (self._fastArityRange(arguments.length, 1, 2) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
self._arityRange(_args, 1, 2, 'update', self);
}
var term = new Term(self._r);
term._query.push(termTypes.UPDATE);
var args = [self, new Term(self._r).expr(newValue)._wrap()];
term._fillArgs(args);
if (helper.isPlainObject(options)) {
helper.loopKeys(options, function(obj, key) {
if ((key !== 'returnChanges') && (key !== 'durability') && (key !== 'nonAtomic')) {
throw new Error.ReqlDriverError('Unrecognized option `'+key+'` in `update`', self._query, 'Available options are returnChanges <bool>, durability <string>, nonAtomic <bool>');
}
});
term._query.push(new Term(self._r).expr(translateOptions(options))._query);
}
return term;
}
Term.prototype.replace = function(newValue, options) {
var self = this;
if (self._fastArityRange(arguments.length, 1, 2) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
self._arityRange(_args, 1, 2, 'replace', self);
}
var term = new Term(self._r);
term._query.push(termTypes.REPLACE);
var args = [self, new Term(self._r).expr(newValue)._wrap()];
term._fillArgs(args);
if (helper.isPlainObject(options)) {
helper.loopKeys(options, function(obj, key) {
if ((key !== 'returnChanges') && (key !== 'durability') && (key !== 'nonAtomic')) {
throw new Error.ReqlDriverError('Unrecognized option `'+key+'` in `replace`', self._query, 'Available options are returnChanges <bool>, durability <string>, nonAtomic <bool>');
}
});
term._query.push(new Term(self._r).expr(translateOptions(options))._query);
}
return term;
}
Term.prototype.delete = function(options) {
var self = this;
if (self._fastArityRange(arguments.length, 1, 2) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
self._arityRange(_args, 0, 1, 'delete', self);
}
var term = new Term(self._r);
term._query.push(termTypes.DELETE);
var args = [self];
term._fillArgs(args);
if (helper.isPlainObject(options)) {
helper.loopKeys(options, function(obj, key) {
if ((key !== 'returnChanges') && (key !== 'durability')) {
throw new Error.ReqlDriverError('Unrecognized option `'+key+'` in `delete`', self._query, 'Available options are returnChanges <bool>, durability <string>');
}
});
term._query.push(new Term(self._r).expr(translateOptions(options))._query);
}
return term;
}
Term.prototype.sync = function() {
if (this._fastArity(arguments.length, 0) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arity(_args, 0, 'sync', this);
}
var term = new Term(this._r);
term._query.push(termTypes.SYNC)
var args = [this._query];
term._fillArgs(args);
return term;
}
// Selecting data
Term.prototype.db = function(db) {
this._noPrefix(this, 'db');
if (this._fastArity(arguments.length, 1) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arity(_args, 1, 'db', this);
}
var term = new Term(this._r);
term._query.push(termTypes.DB)
var args = [new Term(this._r).expr(db)];
term._fillArgs(args);
return term;
}
Term.prototype.table = function(table, options) {
var self = this;
if (self._fastArityRange(arguments.length, 1, 2) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
self._arityRange(_args, 1, 2, 'table', self);
}
var term = new Term(self._r);
term._query.push(termTypes.TABLE)
var args = [];
if (Array.isArray(self._query) && (self._query.length > 0)) {
args.push(self);
}
args.push(new Term(self._r).expr(table))
term._fillArgs(args);
if (helper.isPlainObject(options)) {
helper.loopKeys(options, function(obj, key) {
if (key !== 'readMode') {
throw new Error.ReqlDriverError('Unrecognized option `'+key+'` in `table`', self._query, 'Available option is readMode <string>');
}
});
term._query.push(new Term(self._r).expr(translateOptions(options))._query);
}
return term;
}
Term.prototype.get = function(primaryKey) {
if (this._fastArity(arguments.length, 1) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arity(_args, 1, 'get', this);
}
var term = new Term(this._r);
term._query.push(termTypes.GET);
var args = [this, new Term(this._r).expr(primaryKey)]
term._fillArgs(args);
return term;
}
Term.prototype.getAll = function() {
// We explicitly _args here, so fastArityRange is not useful
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
var term = new Term(this._r);
term._query.push(termTypes.GET_ALL);
var args = [];
args.push(this);
for(var i=0; i<_args.length-1; i++) {
args.push(new Term(this._r).expr(_args[i]))
}
if ((_args.length > 0) && (helper.isPlainObject(_args[_args.length-1])) && (_args[_args.length-1].index !== undefined)) {
term._fillArgs(args);
term._query.push(new Term(this._r).expr(translateOptions(_args[_args.length-1]))._query);
}
else if (_args.length > 0) {
args.push(new Term(this._r).expr(_args[_args.length-1]))
term._fillArgs(args);
} else {
term._fillArgs(args);
}
return term;
}
Term.prototype.between = function(start, end, options) {
var self = this;
if (self._fastArityRange(arguments.length, 2, 3) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
self._arityRange(_args, 2, 3, 'between', self);
}
var term = new Term(self._r);
term._query.push(termTypes.BETWEEN);
var args = [self, new Term(self._r).expr(start), new Term(self._r).expr(end)]
term._fillArgs(args);
if (helper.isPlainObject(options)) {
helper.loopKeys(options, function(obj, key) {
if ((key !== 'index') && (key !== 'leftBound') && (key !== 'rightBound')){
throw new Error.ReqlDriverError('Unrecognized option `'+key+'` in `between`', self._query, 'Available options are index <string>, leftBound <string>, rightBound <string>');
}
});
term._query.push(new Term(self._r).expr(translateOptions(options))._query);
}
return term;
}
Term.prototype.minval = function() {
var term = new Term(this._r);
term._query.push(termTypes.MINVAL);
return term;
}
Term.prototype.maxval = function() {
var term = new Term(this._r);
term._query.push(termTypes.MAXVAL);
return term;
}
Term.prototype.filter = function(filter, options) {
var self = this;
if (self._fastArityRange(arguments.length, 1, 2) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
self._arityRange(_args, 1, 2, 'filter', self);
}
var term = new Term(self._r);
term._query.push(termTypes.FILTER);
var args = [self, new Term(self._r).expr(filter)._wrap()]
term._fillArgs(args);
if (helper.isPlainObject(options)) {
helper.loopKeys(options, function(obj, key) {
if (key !== 'default') {
throw new Error.ReqlDriverError('Unrecognized option `'+key+'` in `filter`', self._query, 'Available option is filter');
}
})
term._query.push(new Term(self._r).expr(translateOptions(options))._query);
}
return term;
}
// Joins
Term.prototype.innerJoin = function(sequence, predicate) {
if (this._fastArity(arguments.length, 2) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arity(_args, 2, 'innerJoin', this);
}
var term = new Term(this._r);
term._query.push(termTypes.INNER_JOIN);
var args = [this._query];
args.push(new Term(this._r).expr(sequence)._query);
args.push(new Term(this._r).expr(predicate)._wrap()._query);
term._fillArgs(args);
return term;
}
Term.prototype.outerJoin = function(sequence, predicate) {
if (this._fastArity(arguments.length, 2) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arity(_args, 2, 'outerJoin', this);
}
var term = new Term(this._r);
term._query.push(termTypes.OUTER_JOIN);
var args = [this];
args.push(new Term(this._r).expr(sequence));
args.push(new Term(this._r).expr(predicate)._wrap());
term._fillArgs(args);
return term;
}
Term.prototype.eqJoin = function(rightKey, sequence, options) {
var self = this;
if (self._fastArityRange(arguments.length, 2, 3) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
self._arityRange(_args, 2, 3, 'eqJoin', self);
}
var term = new Term(self._r);
term._query.push(termTypes.EQ_JOIN);
var args = [self];
args.push(new Term(self._r).expr(rightKey)._wrap());
args.push(new Term(self._r).expr(sequence));
term._fillArgs(args);
if (helper.isPlainObject(options)) {
helper.loopKeys(options, function(obj, key) {
if ((key !== 'index') && (key !== 'ordered')) {
throw new Error.ReqlDriverError('Unrecognized option `'+key+'` in `eqJoin`', self._query, 'Available options are index <string>, ordered <boolean>');
}
})
term._query.push(new Term(self._r).expr(translateOptions(options))._query);
}
return term;
}
Term.prototype.zip = function() {
if (this._fastArity(arguments.length, 0) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arity(_args, 0, 'zip', this);
}
var term = new Term(this._r);
term._query.push(termTypes.ZIP);
var args = [this];
term._fillArgs(args);
return term;
}
// Transformation
Term.prototype.map = function() {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arityRange(_args, 1, Infinity, 'map', this);
var term = new Term(this._r);
term._query.push(termTypes.MAP);
var args = [];
if (!Array.isArray(this._query) || (this._query.length > 0)) {
args.push(this);
}
for(var i=0; i<_args.length-1; i++) {
args.push(new Term(this._r).expr(_args[i]))
}
// Make sure that we don't push undefined if no argument is passed to map,
// in which case the server will handle the case and return an error.
if (_args.length> 0) {
args.push(new Term(this._r).expr(_args[_args.length-1])._wrap())
}
term._fillArgs(args);
return term;
}
Term.prototype.withFields = function() {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arityRange(_args, 1, Infinity, 'withFields', this);
var term = new Term(this._r);
term._query.push(termTypes.WITH_FIELDS);
var args = [this];
for(var i=0; i<_args.length; i++) {
args.push(new Term(this._r).expr(_args[i]))
}
term._fillArgs(args);
return term;
}
Term.prototype.concatMap = function(transformation) {
if (this._fastArity(arguments.length, 1) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arity(_args, 1, 'concatMap', this);
}
var term = new Term(this._r);
term._query.push(termTypes.CONCAT_MAP);
var args = [this];
args.push(new Term(this._r).expr(transformation)._wrap())
term._fillArgs(args);
return term;
}
Term.prototype.orderBy = function() {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arityRange(_args, 1, Infinity, 'orderBy', this);
var term = new Term(this._r);
term._query.push(termTypes.ORDER_BY);
var args = [this];
for(var i=0; i<_args.length-1; i++) {
if ((_args[i] instanceof Term) &&
((_args[i]._query[0] === termTypes.DESC) || (_args[i]._query[0] === termTypes.ASC))) {
args.push(new Term(this._r).expr(_args[i]))
}
else {
args.push(new Term(this._r).expr(_args[i])._wrap())
}
}
// We actually don't need to make the difference here, but...
if ((_args.length > 0) && (helper.isPlainObject(_args[_args.length-1])) && (_args[_args.length-1].index !== undefined)) {
term._fillArgs(args);
term._query.push(new Term(this._r).expr(translateOptions(_args[_args.length-1]))._query);
}
else {
if ((_args[_args.length-1] instanceof Term) &&
((_args[_args.length-1]._query[0] === termTypes.DESC) || (_args[_args.length-1]._query[0] === termTypes.ASC))) {
args.push(new Term(this._r).expr(_args[_args.length-1]))
}
else {
args.push(new Term(this._r).expr(_args[_args.length-1])._wrap())
}
term._fillArgs(args);
}
return term;
}
Term.prototype.desc = function(field) {
this._noPrefix(this, 'desc');
if (this._fastArity(arguments.length, 1) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arity(_args, 1, 'desc', this);
}
var term = new Term(this._r);
term._query.push(termTypes.DESC)
var args = [new Term(this._r).expr(field)._wrap()];
term._fillArgs(args);
return term;
}
Term.prototype.asc = function(field) {
this._noPrefix(this, 'asc');
if (this._fastArity(arguments.length, 1) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arity(_args, 1, 'asc', this);
}
var term = new Term(this._r);
term._query.push(termTypes.ASC)
var args = [new Term(this._r).expr(field)._wrap()];
term._fillArgs(args);
return term;
}
Term.prototype.skip = function(value) {
if (this._fastArity(arguments.length, 1) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arity(_args, 1, 'skip', this);
}
var term = new Term(this._r);
term._query.push(termTypes.SKIP)
var args = [this, new Term(this._r).expr(value)]
term._fillArgs(args);
return term;
}
Term.prototype.limit = function(value) {
if (this._fastArity(arguments.length, 1) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arity(_args, 1, 'limit', this);
}
var term = new Term(this._r);
term._query.push(termTypes.LIMIT)
var args = [this, new Term(this._r).expr(value)]
term._fillArgs(args);
return term;
}
Term.prototype.slice = function(start, end, options) {
if (this._fastArityRange(arguments.length, 1, 2) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arityRange(_args, 1, 3, 'slice', this);
}
var term = new Term(this._r);
term._query.push(termTypes.SLICE);
var args = [];
args.push(this);
args.push(new Term(this._r).expr(start));
if ((end !== undefined) && (options !== undefined)) {
args.push(new Term(this._r).expr(end));
term._fillArgs(args);
term._query.push(new Term(this._r).expr(translateOptions(options))._query);
}
else if ((end !== undefined) && (options === undefined)) {
if (helper.isPlainObject(end) === false) {
args.push(new Term(this._r).expr(end));
term._fillArgs(args);
}
else {
term._fillArgs(args);
term._query.push(new Term(this._r).expr(translateOptions(end))._query);
}
}
else { // end and options are both undefined
term._fillArgs(args);
}
return term;
}
Term.prototype.nth = function(value) {
if (this._fastArity(arguments.length, 1) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arity(_args, 1, 'nth', this);
}
var term = new Term(this._r);
term._query.push(termTypes.NTH)
var args = [this._query, new Term(this._r).expr(value)]
term._fillArgs(args);
return term;
}
Term.prototype.offsetsOf = function(predicate) {
if (this._fastArity(arguments.length, 1) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arity(_args, 1, 'indexesOf', this);
}
var term = new Term(this._r);
term._query.push(termTypes.OFFSETS_OF)
var args = [this, new Term(this._r).expr(predicate)._wrap()];
term._fillArgs(args);
return term;
}
Term.prototype.indexesOf = Term.prototype.offsetsOf;
Term.prototype.isEmpty = function() {
if (this._fastArity(arguments.length, 0) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arity(_args, 0, 'isEmpty', this);
}
var term = new Term(this._r);
term._query.push(termTypes.IS_EMPTY)
var args = [this];
term._fillArgs(args);
return term;
}
Term.prototype.union = function() {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
var term = new Term(this._r);
term._query.push(termTypes.UNION)
var args = [];
if (!Array.isArray(this._query) || (this._query.length > 0)) {
args.push(this);
}
for(var i=0; i<_args.length-1; i++) {
args.push(new Term(this._r).expr(_args[i]))
}
if ((_args.length > 1) && (helper.isPlainObject(_args[_args.length-1])) && (_args[_args.length-1].interleave !== undefined)) {
term._fillArgs(args);
term._query.push(new Term(this._r).expr(translateOptions(_args[_args.length-1]))._query);
}
else if (_args.length > 0) {
args.push(new Term(this._r).expr(_args[_args.length-1]))
term._fillArgs(args);
}
return term;
}
Term.prototype.sample = function(size) {
if (this._fastArity(arguments.length, 1) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arity(_args, 1, 'sample', this);
}
var term = new Term(this._r);
term._query.push(termTypes.SAMPLE)
var args = [this, new Term(this._r).expr(size)];
term._fillArgs(args);
return term;
}
// Aggregations
Term.prototype.reduce = function(func) {
if (this._fastArity(arguments.length, 1) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arity(_args, 1, 'reduce', this);
}
var term = new Term(this._r);
term._query.push(termTypes.REDUCE)
var args = [this, new Term(this._r).expr(func)._wrap()];
term._fillArgs(args);
return term;
}
Term.prototype.count = function(filter) {
if (this._fastArityRange(arguments.length, 0, 1) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arityRange(_args, 0, 1, 'count', this);
}
var term = new Term(this._r);
term._query.push(termTypes.COUNT);
var args = [];
args.push(this);
if (filter !== undefined) {
args.push(new Term(this._r).expr(filter)._wrap())
}
term._fillArgs(args);
return term;
}
Term.prototype.distinct = function(options) {
var self= this;
if (self._fastArityRange(arguments.length, 0, 1) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
self._arityRange(_args, 0, 1, 'distinct', self);
}
var term = new Term(self._r);
term._query.push(termTypes.DISTINCT)
var args = [self];
term._fillArgs(args);
if (helper.isPlainObject(options)) {
var keepGoing = true;
helper.loopKeys(options, function(obj, key) {
if ((keepGoing === true) && (key !== 'index')) {
throw new Error.ReqlDriverError('Unrecognized option `'+key+'` in `distinct`', self._query, 'Available option is index: <string>');
keepGoing = false;
}
});
if (keepGoing === true) {
term._query.push(new Term(self._r).expr(translateOptions(options))._query);
}
}
return term;
}
Term.prototype.group = function() {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
var self = this;
self._arityRange(_args, 1, Infinity, 'group', self);
var term = new Term(self._r);
term._query.push(termTypes.GROUP);
var args = [self];
for(var i=0; i<_args.length-1; i++) {
args.push(new Term(self._r).expr(_args[i])._wrap())
}
if (_args.length > 0) {
if (helper.isPlainObject(_args[_args.length-1])) {
helper.loopKeys(_args[_args.length-1], function(obj, key) {
if ((key !== 'index')
&& (key !== 'multi')) {
throw new Error.ReqlDriverError('Unrecognized option `'+key+'` in `group`', self._query, 'Available options are index: <string>, multi <boolean>');
}
});
term._fillArgs(args);
term._query.push(new Term(self._r).expr(translateOptions(_args[_args.length-1]))._query);
}
else {
args.push(new Term(self._r).expr(_args[_args.length-1])._wrap())
term._fillArgs(args);
}
}
else {
term._fillArgs(args);
}
return term;
}
Term.prototype.split = function(separator, max) {
if (this._fastArityRange(arguments.length, 0, 2) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arityRange(_args, 0, 2, 'split', this);
}
var term = new Term(this._r);
term._query.push(termTypes.SPLIT)
var args = [this];
if (separator !== undefined) {
args.push(new Term(this._r).expr(separator))
if (max !== undefined) {
args.push(new Term(this._r).expr(max))
}
}
term._fillArgs(args);
return term;
}
Term.prototype.ungroup = function() {
if (this._fastArity(arguments.length, 0) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arity(_args, 0, 'ungroup', this);
}
var term = new Term(this._r);
term._query.push(termTypes.UNGROUP)
var args = [this._query];
term._fillArgs(args);
return term;
}
Term.prototype.contains = function() {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arityRange(_args, 1, Infinity, 'contains', this);
var term = new Term(this._r);
term._query.push(termTypes.CONTAINS)
var args = [this._query];
for(var i=0; i<_args.length; i++) {
args.push(new Term(this._r).expr(_args[i])._wrap())
}
term._fillArgs(args);
return term;
}
Term.prototype.sum = function(field) {
if (this._fastArityRange(arguments.length, 0, 1) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arityRange(_args, 0, 1, 'sum', this);
}
var term = new Term(this._r);
term._query.push(termTypes.SUM);
var args = [this];
if (field !== undefined) {
args.push(new Term(this._r).expr(field)._wrap())
}
term._fillArgs(args);
return term;
}
Term.prototype.avg = function(field) {
if (this._fastArityRange(arguments.length, 0, 1) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arityRange(_args, 0, 1, 'avg', this);
}
var term = new Term(this._r);
term._query.push(termTypes.AVG)
var args = [this];
if (field !== undefined) {
args.push(new Term(this._r).expr(field)._wrap())
}
term._fillArgs(args);
return term;
}
Term.prototype.min = function(field) {
if (this._fastArityRange(arguments.length, 0, 1) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arityRange(_args, 0, 1, 'min', this);
}
var term = new Term(this._r);
term._query.push(termTypes.MIN)
var args = [this];
if (field !== undefined) {
if (helper.isPlainObject(field)) {
term._fillArgs(args);
term._query.push(new Term(this._r).expr(translateOptions(field))._query);
}
else {
args.push(new Term(this._r).expr(field)._wrap());
term._fillArgs(args);
}
}
else {
term._fillArgs(args);
}
return term;
}
Term.prototype.max = function(field) {
if (this._fastArityRange(arguments.length, 0, 1) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arityRange(_args, 0, 1, 'max', this);
}
var term = new Term(this._r);
term._query.push(termTypes.MAX)
var args = [this];
if (field !== undefined) {
if (helper.isPlainObject(field)) {
term._fillArgs(args);
term._query.push(new Term(this._r).expr(translateOptions(field))._query);
}
else {
args.push(new Term(this._r).expr(field)._wrap())
term._fillArgs(args);
}
}
else {
term._fillArgs(args);
}
return term;
}
Term.prototype.fold = function(base, func, options) {
if (this._fastArityRange(arguments.length, 2, 3) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arityRange(_args, 2, 3, 'range', this);
}
var term = new Term(this._r);
term._query.push(termTypes.FOLD)
var args = [this, new Term(this._r).expr(base), new Term(this._r).expr(func)._wrap()];
term._fillArgs(args);
if (helper.isPlainObject(options)) {
helper.loopKeys(options, function(obj, key) {
if ((key !== 'emit') && (key !== 'finalEmit')) {
throw new Error.ReqlDriverError('Unrecognized option `'+key+'` in `fold`. Available options are emit <function>, finalEmit <function>');
}
});
term._query.push(new Term(this._r).expr(translateOptions(options))._query);
}
return term;
}
// Document manipulation
Term.prototype.row = function() {
this._noPrefix(this, 'row');
if (this._fastArity(arguments.length, 0) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arity(_args, 0, 'r.row', this);
}
var term = new Term(this._r);
term._query.push(termTypes.IMPLICIT_VAR)
return term;
}
Term.prototype.pluck = function() {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arityRange(_args, 1, Infinity, 'pluck', this);
var term = new Term(this._r);
term._query.push(termTypes.PLUCK)
var args = [this];
for(var i=0; i<_args.length; i++) {
args.push(new Term(this._r).expr(_args[i]))
}
term._fillArgs(args);
return term;
}
Term.prototype.without = function() {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arityRange(_args, 1, Infinity, 'without', this);
var term = new Term(this._r);
term._query.push(termTypes.WITHOUT)
var args = [this];
for(var i=0; i<_args.length; i++) {
args.push(new Term(this._r).expr(_args[i]))
}
term._fillArgs(args);
return term;
}
Term.prototype.merge = function(arg) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arityRange(_args, 1, Infinity, 'merge', this);
var term = new Term(this._r);
term._query.push(termTypes.MERGE)
var args = [this];
for(var i=0; i<_args.length; i++) {
args.push(new Term(this._r).expr(_args[i])._wrap())
}
term._fillArgs(args);
return term;
}
Term.prototype.literal = function(obj) {
this._noPrefix(this, 'literal');
// The test for arity is performed in r.literal
var term = new Term(this._r);
term._query.push(termTypes.LITERAL);
if (arguments.length > 0) {
var args = [new Term(this._r).expr(obj)];
term._fillArgs(args);
}
return term;
}
Term.prototype.append = function(value) {
if (this._fastArity(arguments.length, 1) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arity(_args, 1, 'append', this);
}
var term = new Term(this._r);
term._query.push(termTypes.APPEND)
var args = [this, new Term(this._r).expr(value)];
term._fillArgs(args);
return term;
}
Term.prototype.prepend = function(value) {
if (this._fastArity(arguments.length, 1) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arity(_args, 1, 'prepend', this);
}
var term = new Term(this._r);
term._query.push(termTypes.PREPEND)
var args = [this, new Term(this._r).expr(value)];
term._fillArgs(args);
return term;
}
Term.prototype.difference = function(other) {
if (this._fastArity(arguments.length, 1) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arity(_args, 1, 'difference', this);
}
var term = new Term(this._r);
term._query.push(termTypes.DIFFERENCE)
var args = [this, new Term(this._r).expr(other)];
term._fillArgs(args);
return term;
}
Term.prototype.setInsert = function(other) {
if (this._fastArity(arguments.length, 1) === false) {
var _len = arguments.length;var _args = new Array(_len); for(var _i = 0; _i < _len; _i++) {_args[_i] = arguments[_i];}
this._arity(_args, 1, 'setInsert', this);
}
var term = new Term(this._r);
term._query.push(termTypes.SET_INSERT)
var args = [this, new Term(this._r).expr(other)];
term._fillArgs(args);
return term;
}
Term.prototype.setUnion = function(other) {
if (this._fastArity(arguments.length, 1) === false) {