knex/lib/query/builder.js

778 lines
22 KiB
JavaScript
Raw Normal View History

'use strict';
// Builder
// -------
2015-05-09 13:58:18 -04:00
var _ = require('lodash');
var assert = require('assert');
var inherits = require('inherits');
var EventEmitter = require('events').EventEmitter;
2015-05-09 13:58:18 -04:00
var Raw = require('../raw');
var helpers = require('../helpers');
var JoinClause = require('./joinclause');
var assign = require('lodash/object/assign');
// Typically called from `knex.builder`,
// start a new query building chain.
function QueryBuilder(client) {
2015-05-09 13:58:18 -04:00
this.client = client;
this.and = this;
this._single = {};
this._statements = [];
// Internal flags used in the builder.
2015-05-09 13:58:18 -04:00
this._method = 'select';
this._joinFlag = 'inner';
this._boolFlag = 'and';
this._notFlag = false;
this._debug = client.config && client.config.debug;
}
inherits(QueryBuilder, EventEmitter);
2015-04-28 09:14:13 -04:00
assign(QueryBuilder.prototype, {
2015-05-09 13:58:18 -04:00
toString: function toString() {
2015-04-28 09:14:13 -04:00
return this.toQuery();
},
// Convert the current query "toSQL"
2015-05-09 13:58:18 -04:00
toSQL: function toSQL(method) {
2015-04-29 15:13:15 -04:00
return this.client.queryCompiler(this).toSQL(method || this._method);
2015-04-28 09:14:13 -04:00
},
// Create a shallow clone of the current query builder.
// TODO: Test this!!
2015-05-09 13:58:18 -04:00
clone: function clone() {
var cloned = new this.constructor(this.client);
cloned._method = this._method;
cloned._single = _.clone(this._single);
cloned._options = _.clone(this._options);
cloned._statements = this._statements.slice();
2015-04-28 09:14:13 -04:00
return cloned;
},
// Select
// ------
// Adds a column or columns to the list of "columns"
// being selected on the query.
2015-05-09 13:58:18 -04:00
columns: function columns(column) {
2015-04-28 09:14:13 -04:00
if (!column) return this;
this._statements.push({
grouping: 'columns',
value: helpers.normalizeArr.apply(null, arguments)
});
return this;
},
// Allow for a sub-select to be explicitly aliased as a column,
// without needing to compile the query in a where.
2015-05-09 13:58:18 -04:00
as: function as(column) {
2015-04-28 09:14:13 -04:00
this._single.as = column;
return this;
},
// Sets the `tableName` on the query.
// Alias to "from" for select and "into" for insert statements
// e.g. builder.insert({a: value}).into('tableName')
2015-05-09 13:58:18 -04:00
table: function table(tableName) {
2015-04-28 09:14:13 -04:00
this._single.table = tableName;
return this;
},
// Adds a `distinct` clause to the query.
2015-05-09 13:58:18 -04:00
distinct: function distinct() {
2015-04-28 09:14:13 -04:00
this._statements.push({
grouping: 'columns',
value: helpers.normalizeArr.apply(null, arguments),
distinct: true
});
return this;
},
// Adds a join clause to the query, allowing for advanced joins
// with an anonymous function as the second argument.
// function(table, first, operator, second)
2015-05-09 13:58:18 -04:00
join: function join(table, first) {
2015-04-28 09:14:13 -04:00
var join;
var joinType = this._joinType();
if (typeof first === 'function') {
join = new JoinClause(table, joinType);
first.call(join, join);
} else if (joinType === 'raw') {
join = new JoinClause(this.client.raw(table, first), 'raw');
} else {
2015-04-28 09:14:13 -04:00
join = new JoinClause(table, joinType);
if (arguments.length > 1) {
join.on.apply(join, _.toArray(arguments).slice(1));
}
}
this._statements.push(join);
return this;
},
// JOIN blocks:
2015-05-09 13:58:18 -04:00
innerJoin: function innerJoin() {
2015-04-28 09:14:13 -04:00
return this._joinType('inner').join.apply(this, arguments);
},
2015-05-09 13:58:18 -04:00
leftJoin: function leftJoin() {
2015-04-28 09:14:13 -04:00
return this._joinType('left').join.apply(this, arguments);
},
2015-05-09 13:58:18 -04:00
leftOuterJoin: function leftOuterJoin() {
2015-04-28 09:14:13 -04:00
return this._joinType('left outer').join.apply(this, arguments);
},
2015-05-09 13:58:18 -04:00
rightJoin: function rightJoin() {
2015-04-28 09:14:13 -04:00
return this._joinType('right').join.apply(this, arguments);
},
2015-05-09 13:58:18 -04:00
rightOuterJoin: function rightOuterJoin() {
2015-04-28 09:14:13 -04:00
return this._joinType('right outer').join.apply(this, arguments);
},
2015-05-09 13:58:18 -04:00
outerJoin: function outerJoin() {
2015-04-28 09:14:13 -04:00
return this._joinType('outer').join.apply(this, arguments);
},
2015-05-09 13:58:18 -04:00
fullOuterJoin: function fullOuterJoin() {
2015-04-28 09:14:13 -04:00
return this._joinType('full outer').join.apply(this, arguments);
},
2015-05-09 13:58:18 -04:00
crossJoin: function crossJoin() {
2015-04-28 09:14:13 -04:00
return this._joinType('cross').join.apply(this, arguments);
},
2015-05-09 13:58:18 -04:00
joinRaw: function joinRaw() {
2015-04-28 09:14:13 -04:00
return this._joinType('raw').join.apply(this, arguments);
},
// The where function can be used in several ways:
// The most basic is `where(key, value)`, which expands to
// where key = value.
2015-05-09 13:58:18 -04:00
where: function where(column, operator, value) {
2015-04-28 09:14:13 -04:00
// Support "where true || where false"
if (column === false || column === true) {
2015-05-09 13:58:18 -04:00
return this.where(1, '=', column ? 1 : 0);
}
2015-04-28 09:14:13 -04:00
// Check if the column is a function, in which case it's
// a where statement wrapped in parens.
if (typeof column === 'function') {
return this.whereWrapped(column);
2014-09-29 10:05:53 +02:00
}
2015-04-28 09:14:13 -04:00
// Allow a raw statement to be passed along to the query.
if (column instanceof Raw && arguments.length === 1) return this.whereRaw(column);
2015-04-28 09:14:13 -04:00
// Allows `where({id: 2})` syntax.
if (_.isObject(column) && !(column instanceof Raw)) return this._objectWhere(column);
2015-04-28 09:14:13 -04:00
// Enable the where('key', value) syntax, only when there
// are explicitly two arguments passed, so it's not possible to
// do where('key', '!=') and have that turn into where key != null
if (arguments.length === 2) {
2015-05-09 13:58:18 -04:00
value = operator;
2015-04-28 09:14:13 -04:00
operator = '=';
2015-04-28 09:14:13 -04:00
// If the value is null, and it's a two argument query,
// we assume we're going for a `whereNull`.
if (value === null) {
return this.whereNull(column);
}
}
2015-04-28 09:14:13 -04:00
// lower case the operator for comparison purposes
var checkOperator = ('' + operator).toLowerCase().trim();
// If there are 3 arguments, check whether 'in' is one of them.
if (arguments.length === 3) {
if (checkOperator === 'in' || checkOperator === 'not in') {
return this._not(checkOperator === 'not in').whereIn(arguments[0], arguments[2]);
}
if (checkOperator === 'between' || checkOperator === 'not between') {
return this._not(checkOperator === 'not between').whereBetween(arguments[0], arguments[2]);
}
}
2015-04-28 09:14:13 -04:00
// If the value is still null, check whether they're meaning
// where value is null
if (value === null) {
2015-04-28 09:14:13 -04:00
// Check for .where(key, 'is', null) or .where(key, 'is not', 'null');
if (checkOperator === 'is' || checkOperator === 'is not') {
return this._not(checkOperator === 'is not').whereNull(column);
}
}
2015-04-28 09:14:13 -04:00
// Push onto the where statement stack.
this._statements.push({
grouping: 'where',
type: 'whereBasic',
column: column,
operator: operator,
value: value,
not: this._not(),
bool: this._bool()
});
return this;
},
// Adds an `or where` clause to the query.
2015-05-09 13:58:18 -04:00
orWhere: function orWhere() {
2015-04-28 09:14:13 -04:00
return this._bool('or').where.apply(this, arguments);
},
// Adds an `not where` clause to the query.
2015-05-09 13:58:18 -04:00
whereNot: function whereNot() {
2015-04-28 09:14:13 -04:00
return this._not(true).where.apply(this, arguments);
},
// Adds an `or not where` clause to the query.
2015-05-09 13:58:18 -04:00
orWhereNot: function orWhereNot() {
2015-04-28 09:14:13 -04:00
return this._bool('or').whereNot.apply(this, arguments);
},
// Processes an object literal provided in a "where" clause.
2015-05-09 13:58:18 -04:00
_objectWhere: function _objectWhere(obj) {
2015-04-28 09:14:13 -04:00
var boolVal = this._bool();
var notVal = this._not() ? 'Not' : '';
for (var key in obj) {
this[boolVal + 'Where' + notVal](key, obj[key]);
2014-04-16 02:50:19 -04:00
}
2015-04-28 09:14:13 -04:00
return this;
},
// Adds a raw `where` clause to the query.
2015-05-09 13:58:18 -04:00
whereRaw: function whereRaw(sql, bindings) {
var raw = sql instanceof Raw ? sql : this.client.raw(sql, bindings);
2015-04-28 09:14:13 -04:00
this._statements.push({
grouping: 'where',
type: 'whereRaw',
value: raw,
bool: this._bool()
});
return this;
},
2015-05-09 13:58:18 -04:00
orWhereRaw: function orWhereRaw(sql, bindings) {
2015-04-28 09:14:13 -04:00
return this._bool('or').whereRaw(sql, bindings);
},
// Helper for compiling any advanced `where` queries.
2015-05-09 13:58:18 -04:00
whereWrapped: function whereWrapped(callback) {
2015-04-28 09:14:13 -04:00
this._statements.push({
grouping: 'where',
type: 'whereWrapped',
value: callback,
not: this._not(),
bool: this._bool()
});
return this;
},
2014-04-16 02:50:19 -04:00
2015-04-28 09:14:13 -04:00
// Helper for compiling any advanced `having` queries.
2015-05-09 13:58:18 -04:00
havingWrapped: function havingWrapped(callback) {
2015-04-28 09:14:13 -04:00
this._statements.push({
grouping: 'having',
type: 'whereWrapped',
value: callback,
bool: this._bool()
});
return this;
},
// Adds a `where exists` clause to the query.
2015-05-09 13:58:18 -04:00
whereExists: function whereExists(callback) {
2015-04-28 09:14:13 -04:00
this._statements.push({
grouping: 'where',
type: 'whereExists',
value: callback,
not: this._not(),
2015-05-09 13:58:18 -04:00
bool: this._bool() });
2015-04-28 09:14:13 -04:00
return this;
},
// Adds an `or where exists` clause to the query.
2015-05-09 13:58:18 -04:00
orWhereExists: function orWhereExists(callback) {
2015-04-28 09:14:13 -04:00
return this._bool('or').whereExists(callback);
},
// Adds a `where not exists` clause to the query.
2015-05-09 13:58:18 -04:00
whereNotExists: function whereNotExists(callback) {
2015-04-28 09:14:13 -04:00
return this._not(true).whereExists(callback);
},
// Adds a `or where not exists` clause to the query.
2015-05-09 13:58:18 -04:00
orWhereNotExists: function orWhereNotExists(callback) {
2015-04-28 09:14:13 -04:00
return this._bool('or').whereNotExists(callback);
},
// Adds a `where in` clause to the query.
2015-05-09 13:58:18 -04:00
whereIn: function whereIn(column, values) {
2015-04-28 09:14:13 -04:00
if (Array.isArray(values) && _.isEmpty(values)) return this.where(this._not());
this._statements.push({
grouping: 'where',
type: 'whereIn',
column: column,
value: values,
not: this._not(),
bool: this._bool()
});
return this;
},
// Adds a `or where in` clause to the query.
2015-05-09 13:58:18 -04:00
orWhereIn: function orWhereIn(column, values) {
2015-04-28 09:14:13 -04:00
return this._bool('or').whereIn(column, values);
},
// Adds a `where not in` clause to the query.
2015-05-09 13:58:18 -04:00
whereNotIn: function whereNotIn(column, values) {
2015-04-28 09:14:13 -04:00
return this._not(true).whereIn(column, values);
},
// Adds a `or where not in` clause to the query.
2015-05-09 13:58:18 -04:00
orWhereNotIn: function orWhereNotIn(column, values) {
2015-04-28 09:14:13 -04:00
return this._bool('or')._not(true).whereIn(column, values);
},
// Adds a `where null` clause to the query.
2015-05-09 13:58:18 -04:00
whereNull: function whereNull(column) {
2015-04-28 09:14:13 -04:00
this._statements.push({
grouping: 'where',
type: 'whereNull',
column: column,
not: this._not(),
bool: this._bool()
});
return this;
},
// Adds a `or where null` clause to the query.
2015-05-09 13:58:18 -04:00
orWhereNull: function orWhereNull(column) {
2015-04-28 09:14:13 -04:00
return this._bool('or').whereNull(column);
},
// Adds a `where not null` clause to the query.
2015-05-09 13:58:18 -04:00
whereNotNull: function whereNotNull(column) {
2015-04-28 09:14:13 -04:00
return this._not(true).whereNull(column);
},
// Adds a `or where not null` clause to the query.
2015-05-09 13:58:18 -04:00
orWhereNotNull: function orWhereNotNull(column) {
2015-04-28 09:14:13 -04:00
return this._bool('or').whereNotNull(column);
},
// Adds a `where between` clause to the query.
2015-05-09 13:58:18 -04:00
whereBetween: function whereBetween(column, values) {
assert(Array.isArray(values), 'The second argument to whereBetween must be an array.');
assert(values.length === 2, 'You must specify 2 values for the whereBetween clause');
2015-04-28 09:14:13 -04:00
this._statements.push({
grouping: 'where',
type: 'whereBetween',
column: column,
value: values,
not: this._not(),
bool: this._bool()
});
return this;
},
// Adds a `where not between` clause to the query.
2015-05-09 13:58:18 -04:00
whereNotBetween: function whereNotBetween(column, values) {
2015-04-28 09:14:13 -04:00
return this._not(true).whereBetween(column, values);
},
// Adds a `or where between` clause to the query.
2015-05-09 13:58:18 -04:00
orWhereBetween: function orWhereBetween(column, values) {
2015-04-28 09:14:13 -04:00
return this._bool('or').whereBetween(column, values);
},
// Adds a `or where not between` clause to the query.
2015-05-09 13:58:18 -04:00
orWhereNotBetween: function orWhereNotBetween(column, values) {
2015-04-28 09:14:13 -04:00
return this._bool('or').whereNotBetween(column, values);
},
// Adds a `group by` clause to the query.
2015-05-09 13:58:18 -04:00
groupBy: function groupBy(item) {
2015-04-28 09:14:13 -04:00
if (item instanceof Raw) {
return this.groupByRaw.apply(this, arguments);
}
2015-04-28 09:14:13 -04:00
this._statements.push({
grouping: 'group',
type: 'groupByBasic',
value: helpers.normalizeArr.apply(null, arguments)
});
return this;
},
// Adds a raw `group by` clause to the query.
2015-05-09 13:58:18 -04:00
groupByRaw: function groupByRaw(sql, bindings) {
var raw = sql instanceof Raw ? sql : this.client.raw(sql, bindings);
2015-04-28 09:14:13 -04:00
this._statements.push({
grouping: 'group',
type: 'groupByRaw',
value: raw
});
return this;
},
// Adds a `order by` clause to the query.
2015-05-09 13:58:18 -04:00
orderBy: function orderBy(column, direction) {
2015-04-28 09:14:13 -04:00
this._statements.push({
grouping: 'order',
type: 'orderByBasic',
value: column,
direction: direction
});
return this;
},
// Add a raw `order by` clause to the query.
2015-05-09 13:58:18 -04:00
orderByRaw: function orderByRaw(sql, bindings) {
var raw = sql instanceof Raw ? sql : this.client.raw(sql, bindings);
2015-04-28 09:14:13 -04:00
this._statements.push({
grouping: 'order',
type: 'orderByRaw',
value: raw
});
return this;
},
// Add a union statement to the query.
2015-05-09 13:58:18 -04:00
union: function union(callbacks, wrap) {
if (arguments.length === 1 || arguments.length === 2 && _.isBoolean(wrap)) {
2015-04-28 09:14:13 -04:00
if (!Array.isArray(callbacks)) {
callbacks = [callbacks];
}
for (var i = 0, l = callbacks.length; i < l; i++) {
this._statements.push({
grouping: 'union',
clause: 'union',
value: callbacks[i],
wrap: wrap || false
});
}
} else {
callbacks = _.toArray(arguments).slice(0, arguments.length - 1);
wrap = arguments[arguments.length - 1];
if (!_.isBoolean(wrap)) {
callbacks.push(wrap);
wrap = false;
}
this.union(callbacks, wrap);
}
return this;
},
// Adds a union all statement to the query.
2015-05-09 13:58:18 -04:00
unionAll: function unionAll(callback, wrap) {
2015-04-28 09:14:13 -04:00
this._statements.push({
grouping: 'union',
clause: 'union all',
value: callback,
wrap: wrap || false
});
return this;
},
2015-04-28 09:14:13 -04:00
// Adds a `having` clause to the query.
2015-05-09 13:58:18 -04:00
having: function having(column, operator, value) {
2015-04-28 09:14:13 -04:00
if (column instanceof Raw && arguments.length === 1) {
return this._havingRaw(column);
}
2015-05-09 13:58:18 -04:00
2015-04-28 09:14:13 -04:00
// Check if the column is a function, in which case it's
// a having statement wrapped in parens.
if (typeof column === 'function') {
return this.havingWrapped(column);
}
2015-05-09 13:58:18 -04:00
2015-04-28 09:14:13 -04:00
this._statements.push({
grouping: 'having',
type: 'havingBasic',
column: column,
operator: operator,
value: value,
bool: this._bool()
});
return this;
},
// Adds an `or having` clause to the query.
2015-05-09 13:58:18 -04:00
orHaving: function orHaving() {
2015-04-28 09:14:13 -04:00
return this._bool('or').having.apply(this, arguments);
},
2015-05-09 13:58:18 -04:00
havingRaw: function havingRaw(sql, bindings) {
2015-04-28 09:14:13 -04:00
return this._havingRaw(sql, bindings);
},
2015-05-09 13:58:18 -04:00
orHavingRaw: function orHavingRaw(sql, bindings) {
2015-04-28 09:14:13 -04:00
return this._bool('or').havingRaw(sql, bindings);
},
// Adds a raw `having` clause to the query.
2015-05-09 13:58:18 -04:00
_havingRaw: function _havingRaw(sql, bindings) {
var raw = sql instanceof Raw ? sql : this.client.raw(sql, bindings);
2015-04-28 09:14:13 -04:00
this._statements.push({
grouping: 'having',
type: 'havingRaw',
value: raw,
bool: this._bool()
});
return this;
},
// Only allow a single "offset" to be set for the current query.
2015-05-09 13:58:18 -04:00
offset: function offset(value) {
2015-04-28 09:14:13 -04:00
this._single.offset = value;
return this;
},
// Only allow a single "limit" to be set for the current query.
2015-05-09 13:58:18 -04:00
limit: function limit(value) {
var val = parseInt(value, 10);
2015-04-28 09:14:13 -04:00
if (isNaN(val)) {
2015-05-09 13:58:18 -04:00
helpers.warn('A valid integer must be provided to limit');
2015-04-28 09:14:13 -04:00
} else {
2015-05-09 13:58:18 -04:00
this._single.limit = val;
}
2015-04-28 09:14:13 -04:00
return this;
},
// Retrieve the "count" result of the query.
2015-05-09 13:58:18 -04:00
count: function count(column) {
return this._aggregate('count', column || '*');
2015-04-28 09:14:13 -04:00
},
// Retrieve the minimum value of a given column.
2015-05-09 13:58:18 -04:00
min: function min(column) {
2015-04-28 09:14:13 -04:00
return this._aggregate('min', column);
},
// Retrieve the maximum value of a given column.
2015-05-09 13:58:18 -04:00
max: function max(column) {
2015-04-28 09:14:13 -04:00
return this._aggregate('max', column);
},
// Retrieve the sum of the values of a given column.
2015-05-09 13:58:18 -04:00
sum: function sum(column) {
2015-04-28 09:14:13 -04:00
return this._aggregate('sum', column);
},
// Retrieve the average of the values of a given column.
2015-05-09 13:58:18 -04:00
avg: function avg(column) {
2015-04-28 09:14:13 -04:00
return this._aggregate('avg', column);
},
// Increments a column's value by the specified amount.
2015-05-09 13:58:18 -04:00
increment: function increment(column, amount) {
2015-04-28 09:14:13 -04:00
return this._counter(column, amount);
},
// Decrements a column's value by the specified amount.
2015-05-09 13:58:18 -04:00
decrement: function decrement(column, amount) {
2015-04-28 09:14:13 -04:00
return this._counter(column, amount, '-');
},
// Sets the values for a `select` query, informing that only the first
// row should be returned (limit 1).
2015-05-09 13:58:18 -04:00
first: function first() {
var i,
args = new Array(arguments.length);
2015-04-28 09:14:13 -04:00
for (i = 0; i < args.length; i++) {
args[i] = arguments[i];
}
2015-04-28 09:14:13 -04:00
this.select.apply(this, args);
this._method = 'first';
this.limit(1);
return this;
},
// Pluck a column from a query.
2015-05-09 13:58:18 -04:00
pluck: function pluck(column) {
2015-04-28 09:14:13 -04:00
this._method = 'pluck';
this._single.pluck = column;
this._statements.push({
grouping: 'columns',
type: 'pluck',
value: column
});
return this;
},
// Insert & Update
// ------
// Sets the values for an `insert` query.
2015-05-09 13:58:18 -04:00
insert: function insert(values, returning) {
2015-04-28 09:14:13 -04:00
this._method = 'insert';
if (!_.isEmpty(returning)) this.returning(returning);
2015-05-09 13:58:18 -04:00
this._single.insert = values;
2015-04-28 09:14:13 -04:00
return this;
},
// Sets the values for an `update`, allowing for both
// `.update(key, value, [returning])` and `.update(obj, [returning])` syntaxes.
2015-05-09 13:58:18 -04:00
update: function update(values, returning) {
var ret,
obj = this._single.update || {};
2015-04-28 09:14:13 -04:00
this._method = 'update';
if (_.isString(values)) {
obj[values] = returning;
if (arguments.length > 2) {
ret = arguments[2];
}
} else {
2015-05-09 13:58:18 -04:00
var i = -1,
keys = Object.keys(values);
2015-04-28 09:14:13 -04:00
if (this._single.update) {
2015-05-09 13:58:18 -04:00
helpers.warn('Update called multiple times with objects.');
2015-04-28 09:14:13 -04:00
}
while (++i < keys.length) {
2015-05-09 13:58:18 -04:00
obj[keys[i]] = values[keys[i]];
2015-04-28 09:14:13 -04:00
}
ret = arguments[1];
}
2015-04-28 09:14:13 -04:00
if (!_.isEmpty(ret)) this.returning(ret);
this._single.update = obj;
return this;
},
// Sets the returning value for the query.
2015-05-09 13:58:18 -04:00
returning: function returning(_returning) {
this._single.returning = _returning;
2015-04-28 09:14:13 -04:00
return this;
},
// Delete
// ------
// Executes a delete statement on the query;
2015-05-09 13:58:18 -04:00
'delete': function _delete(ret) {
2015-04-28 09:14:13 -04:00
this._method = 'del';
if (!_.isEmpty(ret)) this.returning(ret);
return this;
},
// Truncates a table, ends the query chain.
2015-05-09 13:58:18 -04:00
truncate: function truncate(tableName) {
2015-04-28 09:14:13 -04:00
this._method = 'truncate';
if (tableName) {
2015-05-09 13:58:18 -04:00
this._single.table = tableName;
}
return this;
2015-04-28 09:14:13 -04:00
},
2015-04-28 09:14:13 -04:00
// Retrieves columns for the table specified by `knex(tableName)`
2015-05-09 13:58:18 -04:00
columnInfo: function columnInfo(column) {
2015-04-28 09:14:13 -04:00
this._method = 'columnInfo';
this._single.columnInfo = column;
2014-07-01 08:53:35 -04:00
return this;
2015-04-28 09:14:13 -04:00
},
2014-07-01 08:53:35 -04:00
2015-04-28 09:14:13 -04:00
// Set a lock for update constraint.
2015-05-09 13:58:18 -04:00
forUpdate: function forUpdate() {
2015-04-28 09:14:13 -04:00
this._single.lock = 'forUpdate';
return this;
},
// Set a lock for share constraint.
2015-05-09 13:58:18 -04:00
forShare: function forShare() {
2015-04-28 09:14:13 -04:00
this._single.lock = 'forShare';
return this;
},
// Takes a JS object of methods to call and calls them
2015-05-09 13:58:18 -04:00
fromJS: function fromJS(obj) {
_.each(obj, function (val, key) {
2015-04-28 09:14:13 -04:00
if (typeof this[key] !== 'function') {
2015-05-09 13:58:18 -04:00
helpers.warn('Knex Error: unknown key ' + key);
2015-04-28 09:14:13 -04:00
}
if (Array.isArray(val)) {
2015-05-09 13:58:18 -04:00
this[key].apply(this, val);
2015-04-28 09:14:13 -04:00
} else {
2015-05-09 13:58:18 -04:00
this[key](val);
2015-04-28 09:14:13 -04:00
}
2015-05-09 13:58:18 -04:00
}, this);
return this;
2015-04-28 09:14:13 -04:00
},
// ----------------------------------------------------------------------
// Helper for the incrementing/decrementing queries.
2015-05-09 13:58:18 -04:00
_counter: function _counter(column, amount, symbol) {
2015-04-28 09:14:13 -04:00
var amt = parseInt(amount, 10);
if (isNaN(amt)) amt = 1;
this._method = 'counter';
this._single.counter = {
column: column,
amount: amt,
2015-05-09 13:58:18 -04:00
symbol: symbol || '+'
2015-04-28 09:14:13 -04:00
};
return this;
},
// Helper to get or set the "boolFlag" value.
2015-05-09 13:58:18 -04:00
_bool: function _bool(val) {
2015-04-28 09:14:13 -04:00
if (arguments.length === 1) {
this._boolFlag = val;
return this;
}
var ret = this._boolFlag;
this._boolFlag = 'and';
return ret;
},
// Helper to get or set the "notFlag" value.
2015-05-09 13:58:18 -04:00
_not: function _not(val) {
2015-04-28 09:14:13 -04:00
if (arguments.length === 1) {
this._notFlag = val;
return this;
}
var ret = this._notFlag;
this._notFlag = false;
return ret;
},
// Helper to get or set the "joinFlag" value.
2015-05-09 13:58:18 -04:00
_joinType: function _joinType(val) {
2015-04-28 09:14:13 -04:00
if (arguments.length === 1) {
this._joinFlag = val;
return this;
}
var ret = this._joinFlag || 'inner';
this._joinFlag = 'inner';
return ret;
},
// Helper for compiling any aggregate queries.
2015-05-09 13:58:18 -04:00
_aggregate: function _aggregate(method, column) {
2015-04-28 09:14:13 -04:00
this._statements.push({
grouping: 'columns',
type: 'aggregate',
method: method,
value: column
});
return this;
}
2015-04-28 09:14:13 -04:00
2015-05-09 13:58:18 -04:00
});
2014-07-01 08:53:35 -04:00
Object.defineProperty(QueryBuilder.prototype, 'or', {
2015-05-09 13:58:18 -04:00
get: function get() {
2014-07-01 08:53:35 -04:00
return this._bool('or');
}
});
Object.defineProperty(QueryBuilder.prototype, 'not', {
2015-05-09 13:58:18 -04:00
get: function get() {
2014-07-01 08:53:35 -04:00
return this._not(true);
}
});
2015-05-09 13:58:18 -04:00
QueryBuilder.prototype.select = QueryBuilder.prototype.columns;
QueryBuilder.prototype.column = QueryBuilder.prototype.columns;
QueryBuilder.prototype.andWhereNot = QueryBuilder.prototype.whereNot;
QueryBuilder.prototype.andWhere = QueryBuilder.prototype.where;
QueryBuilder.prototype.andWhereRaw = QueryBuilder.prototype.whereRaw;
QueryBuilder.prototype.andHaving = QueryBuilder.prototype.having;
QueryBuilder.prototype.from = QueryBuilder.prototype.table;
QueryBuilder.prototype.into = QueryBuilder.prototype.table;
QueryBuilder.prototype.del = QueryBuilder.prototype['delete'];
2015-04-28 09:14:13 -04:00
// Attach all of the top level promise methods that should be chainable.
require('../interface')(QueryBuilder);
2015-05-09 13:58:18 -04:00
module.exports = QueryBuilder;