Subclass of patio.sql.ComplexExpression where the expression results in a boolean value in SQL.
Extends
Dataset._filterObject({a : 1}) //=> WHERE (a = 1)
Dataset._filterObject({x : {gt : 1}}) //=> WHERE (x > 1)
Dataset._filterObject({x : {gt : 1}, a : 1}) //=> WHERE ((x > 1) AND (a = 1))
Dataset._filterObject({x : {like : "name"}}) //=> WHERE (x LIKE 'name')
Dataset._filterObject({x : {iLike : "name"}}) //=> WHERE (x LIKE 'name')
Dataset._filterObject({x : {between : [1,10]}}) //=> WHERE ((x >= 1) AND (x <= 10))
Dataset._filterObject({x : {notBetween : [1,10]}}) //=> WHERE ((x < 1) OR (x > 10))
Dataset._filterObject({x : {neq : 1}}) //=> WHERE (x != 1)
Arguments
the expression we need to create an expression out of
null] : the key that the hash corresponds to
patio.sql.Expression an expression to use in the filter
function (expr,key,op){
/*jshint loopfunc:true*/
var pairs = [], opts, newKey;
var twoArityOperators = this.TWO_ARITY_OPERATORS;
for (var k in expr) {
var v = expr[k];
if (isHash(v)) { //its a hash too filter it too!
pairs.push(this.__filterObject(v, k, op));
} else if (key && (twoArityOperators[k.toUpperCase()] || k.match(/between/i))) {
//its a two arrity operator (e.g. '=', '>')
newKey = isString(key) ? key.split(",") : [key];
if (newKey.length > 1) {
//this represents a hash where the key represents two columns
//(e.g. {"col1,col2" : 1}) => WHERE (col1 = 1 AND col2 = 1)
pairs = pairs.concat(newKey.map(function (k) {
//filter each column with the expression
return this.__filterObject(expr, k, op);
}, this));
} else {
newKey = [sql.stringToIdentifier(newKey[0])];
if (k.match(/^like$/)) {
//its a like clause {col : {like : "hello"}}
pairs.push(StringExpression.like.apply(StringExpression, (newKey.concat(isArray(v) ? v : [v]))));
} else if (k.match(/^iLike$/)) {
//its a like clause {col : {iLike : "hello"}}
pairs.push(StringExpression.like.apply(StringExpression, (newKey.concat(isArray(v) ? v : [v]).concat({caseInsensitive: true}))));
} else if (k.match(/between/i)) {
//its a like clause {col : {between : [1,10]}}
var between = sql.stringToIdentifier(newKey[0]).between(v);
k === "notBetween" && (between = between.not());
pairs.push(between);
} else {
//otherwise is just a boolean expressio
//it its not a valid operator then we
//BooleanExpression with throw an error
pairs.push(new BooleanExpression(k, newKey[0], v));
}
}
} else {
//we're not a twoarity operator
//so we create a boolean expression out of it
newKey = k.split(",");
if (newKey.length === 1) {
newKey = sql.stringToIdentifier(newKey[0]);
}
opts = [
[newKey, v]
];
pairs.push(BooleanExpression.fromValuePairs(opts));
}
}
//if the total of pairs is one then we just return the first element
//otherwise we join them all with an AND
return pairs.length === 1 ? pairs[0] : BooleanExpression.fromArgs([op || "AND"].concat(pairs));
}
Take pairs of values (e.g. a hash or array of two element arrays) and converts it to a patio.sql.BooleanExpression. The operator and args used depends on the case of the right (2nd) argument:
BooleanExpression.fromValuePairs({a : [1,2,3]}) //=> a IN (1,2,3)
BooleanExpression.fromValuePairs({a : true}); // a IS TRUE;
BooleanExpression.fromValuePairs({a : /^A/i}); // a *~ '^A'
If multiple arguments are given, they are joined with the op given (AND by default, OR possible). If negate is set to true, all subexpressions are inverted before used.
BooleanExpression.fromValuePairs({a : [1,2,3], b : true}) //=> a IN (1,2,3) AND b IS TRUE
BooleanExpression.fromValuePairs({a : [1,2,3], b : true}, "OR") //=> a IN (1,2,3) OR b IS TRUE
BooleanExpression.fromValuePairs({a : [1,2,3], b : true}, "OR", true) //=> a NOT IN (1,2,3) AND b IS NOT TRUE
Arguments
object to convert to a patio.sql.BooleanExpression
"AND"] : Boolean operator to join each subexpression with.
BooleanExpression.fromValuePairs({a : [1,2,3], b : true}, "OR") //=> a IN (1,2,3) OR b IS TRUE
false] : set to try to invert the patio.sql.BooleanExpression.
BooleanExpression.fromValuePairs({a : [1,2,3], b : true}, "OR", true) //=> a NOT IN (1,2,3) AND b IS NOT TRUE
patio.sql.BooleanExpression expression composed of sub expressions built from the hash.
function (a,op,negate){
!Dataset && (Dataset = require("./dataset"));
op = op || "AND", negate = negate || false;
var pairArr = [];
var isArr = isArray(a) && Expression.isConditionSpecifier(a);
if (isHash(a)) {
pairArr.push(this.__filterObject(a, null, op));
} else {
for (var k in a) {
var v = isArr ? a[k][1] : a[k], ret;
k = isArr ? a[k][0] : k;
if (isArray(v) || isInstanceOf(v, Dataset)) {
k = isArray(k) ? k.map(sql.stringToIdentifier) : sql.stringToIdentifier(k);
ret = new BooleanExpression("IN", k, v);
} else if (isInstanceOf(v, NegativeBooleanConstant)) {
ret = new BooleanExpression("ISNOT", k, v.constant);
} else if (isInstanceOf(v, BooleanConstant)) {
ret = new BooleanExpression("IS", k, v.constant);
} else if (isNull(v) || isBoolean(v)) {
ret = new BooleanExpression("IS", k, v);
} else if (isHash(v)) {
ret = BooleanExpression.__filterObject(v, k, op);
} else if (isRegExp(v)) {
ret = StringExpression.like(sql.stringToIdentifier(k), v);
} else {
ret = new BooleanExpression("EQ", sql.stringToIdentifier(k), v);
}
negate && (ret = BooleanExpression.invert(ret));
pairArr.push(ret);
}
}
//if We just have one then return the first otherwise create a new Boolean expression
return pairArr.length === 1 ? pairArr[0] : BooleanExpression.fromArgs([op].concat(pairArr));
}
Invert the expression, if possible. If the expression cannot be inverted, it throws an patio.error.ExpressionError. An inverted expression should match everything that the uninverted expression did not match, and vice-versa, except for possible issues with SQL NULL (i.e. 1 == NULL is NULL and 1 != NULL is also NULL).
Example
BooleanExpression.invert(sql.a) //=> NOT "a"
Arguments
the expression to invert.
patio.sql.BooleanExpression the inverted expression.
function (expression){
if (isInstanceOf(expression, BooleanExpression)) {
var op = expression.op, newArgs;
if (op === "AND" || op === "OR") {
newArgs = [OPERTATOR_INVERSIONS[op]].concat(expression.args.map(function (arg) {
return BooleanExpression.invert(arg);
}));
return BooleanExpression.fromArgs(newArgs);
} else {
newArgs = [OPERTATOR_INVERSIONS[op]].concat(expression.args);
return BooleanExpression.fromArgs(newArgs);
}
} else if (isInstanceOf(expression, StringExpression) || isInstanceOf(expression, NumericExpression)) {
throw new ExpressionError(format("Cannot invert %4j", [expression]));
} else {
return new BooleanExpression("NOT", expression);
}
}