diff --git a/History.md b/History.md index 4ca1e267..9c748b20 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,8 @@ +#v0.2.15 + +* Updated patio migrate to use an exit code of `1` if the migration fails. [#92](https://github.com/C2FO/patio/issues/92) +* Fixed the use of hashes in `andGrouped*` methods. + # v0.2.14 * Converted uses of `.then` to `.chain` diff --git a/bin/patio b/bin/patio index 11873605..0993b86b 100755 --- a/bin/patio +++ b/bin/patio @@ -34,6 +34,7 @@ program.command("migrate") ["directory", "uri"].forEach(function (arg) { if (comb.isUndefined(program[arg])) { self.missingArgument(arg); + process.exit(1); } }); @@ -61,6 +62,7 @@ program.command("migrate") var disconnectError = function (err) { patio.logError(err); patio.disconnect(); + process.exit(1); }; var start = new Date(); diff --git a/docs-md/coverage.html b/docs-md/coverage.html index 827b7d68..5cbdc95d 100644 --- a/docs-md/coverage.html +++ b/docs-md/coverage.html @@ -256,10 +256,10 @@
* Checks all deferred connection requests.
*/
__checkQueries: function () {
var fc = this.freeCount, def, defQueue = this.__deferredQueue;
while (fc-- >= 0 && defQueue.count) {
var fc = this.freeCount, def, defQueue = this.__deferredQueue;
while (fc-- >= 0 && defQueue.count) {
def = defQueue.dequeue();
var conn = this.getObject();
if (conn) {
* @return {comb.Promise} A promise to called back with a connection.
*/
getConnection: function () {
var ret = new Promise();
if (this.count > this.__maxObjects) {
var ret = new Promise();
if (this.count > this.__maxObjects) {
this.__deferredQueue.enqueue(ret);
} else {
//todo override getObject to make async so creating a connetion can execute setup sql
var conn = this.getObject();
if (!conn) {
var conn = this.getObject();
if (!conn) {
//we need to deffer it
this.__deferredQueue.enqueue(ret);
} else {
ret.callback(conn);
ret.callback(conn);
}
}
if (this.count > this.__maxObjects && !conn) {
if (this.count > this.__maxObjects && !conn) {
ret.errback(new Error("Unexpected ConnectionPool error"));
}
return ret.promise();
return ret.promise();
},
/**
*
*/
returnObject: function (obj) {
var self = this;
this.validate(obj).chain(function (valid) {
var index;
if (self.count <= self.__maxObjects && valid && (index = self.__inUseObjects.indexOf(obj)) > -1) {
self.__inUseObjects.splice(index, 1);
self.__freeObjects.enqueue(obj);
self.__checkQueries();
var self = this;
this.validate(obj).chain(function (valid) {
var index;
if (self.count <= self.__maxObjects && valid && (index = self.__inUseObjects.indexOf(obj)) > -1) {
self.__inUseObjects.splice(index, 1);
self.__freeObjects.enqueue(obj);
self.__checkQueries();
} else {
self.removeObject(obj);
}
* @return {*} an adapter specific connection.
*/
returnConnection: function (connection) {
this.returnObject(connection);
this.returnObject(connection);
},
createObject: function () {
* @return {comb.Promise} called back with a valid or invalid state.
*/
validate: function (conn) {
if (!this.__validateConnectionCB) {
if (!this.__validateConnectionCB) {
var ret = new Promise();
ret.callback(true);
return ret;
} else {
return this.__validateConnectionCB();
return this.__validateConnectionCB();
}
},
};
var isBlank = function (obj) {
var ret = false;
if (isUndefinedOrNull(obj)) {
ret = true;
} else if (isString(obj) || isArray(obj)) {
ret = obj.length === 0;
var ret = false;
if (isUndefinedOrNull(obj)) {
ret = true;
} else if (isString(obj) || isArray(obj)) {
ret = obj.length === 0;
} else if (isBoolean(obj) && !obj) {
ret = true;
} else if (isObject(obj) && isEmpty(obj)) {
ret = true;
}
return ret;
return ret;
};
var byteaParser = function (val) {
},
query: function (query) {
var ret = new Promise();
try {
this.connection.setMaxListeners(0);
var fields = [];
var q = this.connection.query(query, function (err, results) {
q.handleRowDescription = orig;
if (err) {
var ret = new Promise();
try {
this.connection.setMaxListeners(0);
var fields = [];
var q = this.connection.query(query, function (err, results) {
q.handleRowDescription = orig;
if (err) {
return ret.errback(err);
} else {
return ret.callback(results.rows, fields);
return ret.callback(results.rows, fields);
}
});
var orig = q.handleRowDescription;
q.handleRowDescription = function (msg) {
fields = msg.fields;
return orig.apply(q, arguments);
var orig = q.handleRowDescription;
q.handleRowDescription = function (msg) {
fields = msg.fields;
return orig.apply(q, arguments);
};
} catch (e) {
patio.logError(e);
}
return ret.promise();
return ret.promise();
}
}
});
function colCallback(o) {
return o;
return o;
}
DS = define(Dataset, {
instance: {
complexExpressionSql: function (op, args) {
var ret = "";
if (op === "^") {
var ret = "";
if (op === "^") {
var j = this._static.XOR_OP, c = false;
args.forEach(function (a) {
if (c) {
c = true;
}, true);
} else {
return this._super(arguments);
return this._super(arguments);
}
return ret;
},
},
_literalString: function (v) {
return "'" + v.replace(/\\/g, "\\\\").replace(/'/g, "''") + "'";
return "'" + v.replace(/\\/g, "\\\\").replace(/'/g, "''") + "'";
},
_deleteFromSql: function () {
},
_selectLockSql: function () {
if (this.__opts.lock === "share") {
if (this.__opts.lock === "share") {
return this._static.FOR_SHARE;
} else {
return this._super(arguments);
return this._super(arguments);
}
},
_selectWithSql: function () {
var optsWith = this.__opts["with"];
if (!isEmpty(optsWith) && optsWith.some(function (w) {
var optsWith = this.__opts["with"];
if (!isEmpty(optsWith) && optsWith.some(function (w) {
return w.recursive;
})) {
return this._static.SQL_WITH_RECURSIVE;
} else {
return this._super(arguments);
return this._super(arguments);
}
},
},
_quotedIdentifier: function (c) {
return format('"%s"', c);
return format('"%s"', c);
},
__fullTextStringJoin: function (cols) {
},
fetchRows: function (sql) {
var oi = this.outputIdentifier.bind(this), self = this;
return asyncArray(this.execute(sql).chain(function (rows, fields) {
var cols = [];
if (rows && rows.length) {
self.__columns = [];
var col, colOutputIdentifier, i = -1, l;
if (fields && fields.length) {
var oi = this.outputIdentifier.bind(this), self = this;
return asyncArray(this.execute(sql).chain(function (rows, fields) {
var cols = [];
if (rows && rows.length) {
self.__columns = [];
var col, colOutputIdentifier, i = -1, l;
if (fields && fields.length) {
l = fields.length;
while (++i < l) {
colOutputIdentifier = self.__columns[i] = oi(col = fields[i].name);
cols[i] = [colOutputIdentifier, colCallback, col];
}
} else {
fields = Object.keys(rows[0]);
l = fields.length;
while (++i < l) {
colOutputIdentifier = self.__columns[i] = oi(col = fields[i]);
cols[i] = [colOutputIdentifier, colCallback, col];
fields = Object.keys(rows[0]);
l = fields.length;
while (++i < l) {
colOutputIdentifier = self.__columns[i] = oi(col = fields[i]);
cols[i] = [colOutputIdentifier, colCallback, col];
}
}
}
return self.__processRows(rows, cols);
return self.__processRows(rows, cols);
}));
},
__processRows: function (rows, cols) {
//dp this so the callbacks are called in appropriate order also.
var ret = [], i = -1, l = rows.length, j = -1, k = cols.length, row, h, col;
while (++i < l) {
row = rows[i];
h = {};
j = -1;
while (++j < k) {
col = cols[j];
h[col[0]] = col[1](row[col[2]]);
var ret = [], i = -1, l = rows.length, j = -1, k = cols.length, row, h, col;
while (++i < l) {
row = rows[i];
h = {};
j = -1;
while (++j < k) {
col = cols[j];
h[col[0]] = col[1](row[col[2]]);
}
ret[i] = h;
ret[i] = h;
}
return ret;
return ret;
},
},
supportsDistinctOn: function () {
return true;
return true;
},
supportsModifyingJoins: function () {
return true;
return true;
},
supportsTimestampTimezones: function () {
return true;
return true;
}
}
},
validate: function (conn) {
return new Promise().callback(true).promise();
return new Promise().callback(true).promise();
},
execute: function (sql, opts, conn) {
var self = this;
return when(conn || this._getConnection()).chain(function (conn) {
return self.__execute(conn, sql, opts);
var self = this;
return when(conn || this._getConnection()).chain(function (conn) {
return self.__execute(conn, sql, opts);
});
},
__execute: function (conn, sql, opts, cb) {
var self = this;
return this.__logAndExecute(sql, function () {
return conn.query(sql);
var self = this;
return this.__logAndExecute(sql, function () {
return conn.query(sql);
})
.both(function () {
return self._returnConnection(conn);
return self._returnConnection(conn);
});
},
schemaParseTable: function (tableName, opts) {
var m = this.outputIdentifierFunc,
var m = this.outputIdentifierFunc,
m2 = this.inputIdentifierFunc;
var ds = this.metadataDataset
var ds = this.metadataDataset
.select(
"pg_attribute__attname___name",
sql["format_type"]("pg_type__oid", "pg_attribute__atttypmod").as(literal('"dbType"')),
.filter({"pg_attribute__attnum": {gt: 0}})
.filter({"pg_class__relname": m2(tableName)})
.order("pg_attribute__attnum");
ds = this.__filterSchema(ds, opts);
var currentSchema = null, self = this;
return ds.map(function (row) {
var sch = row.nspname;
delete row.nspname;
if (currentSchema) {
if (sch !== currentSchema) {
ds = this.__filterSchema(ds, opts);
var currentSchema = null, self = this;
return ds.map(function (row) {
var sch = row.nspname;
delete row.nspname;
if (currentSchema) {
if (sch !== currentSchema) {
var error = new Error("columns from two tables were returned please specify a schema");
self.logError(error);
}
} else {
currentSchema = sch;
currentSchema = sch;
}
if (isBlank(row["default"])) {
row["default"] = null;
if (isBlank(row["default"])) {
row["default"] = null;
}
row.type = self.schemaColumnType(row.dbType);
var fieldName = m(row.name);
delete row.name;
return [fieldName, row];
row.type = self.schemaColumnType(row.dbType);
var fieldName = m(row.name);
delete row.name;
return [fieldName, row];
});
//If opts includes a :schema option, or a default schema is used, restrict the dataset to
// that schema. Otherwise, just exclude the default PostgreSQL schemas except for public.
__filterSchema: function (ds, opts) {
opts = opts || {};
var schema = opts.schema, ret = ds;
if (schema) {
opts = opts || {};
var schema = opts.schema, ret = ds;
if (schema) {
ds = ds.filter({"pg_namespace__nspname": schema});
} else {
ds = ds.exclude({"pg_namespace__nspname": this.EXCLUDE_SCHEMAS});
ds = ds.exclude({"pg_namespace__nspname": this.EXCLUDE_SCHEMAS});
}
return ds;
return ds;
},
__notifySql: function (channel, payload) {
},
dataset: function () {
return new DS(this);
return new DS(this);
},
serialPrimaryKeyOptions: function () {
},
query: function (query) {
var ret = new Promise();
try {
this.connection.setMaxListeners(0);
this.connection.query(query, hitch(ret, ret.resolve));
var ret = new Promise();
try {
this.connection.setMaxListeners(0);
this.connection.query(query, hitch(ret, ret.resolve));
} catch (e) {
patio.logError(e);
}
return ret.promise();
return ret.promise();
}
}
});
},
fetchRows: function (sql) {
var self = this;
return asyncArray(this.execute(sql).chain(function (r, fields) {
var cols = [], i = -1, l = fields.length, col, fieldName, type, length, colIdentifier, selfCols = [];
self.__columns = selfCols;
while (++i < l) {
col = fields[i];
fieldName = col.name;
type = col.type;
length = col.fieldLength;
colIdentifier = self.outputIdentifier(fieldName);
selfCols[i] = colIdentifier;
cols[i] = [colIdentifier, DB.convertMysqlType(type === 1 && length !== 1 ? 2 : type), fieldName];
var self = this;
return asyncArray(this.execute(sql).chain(function (r, fields) {
var cols = [], i = -1, l = fields.length, col, fieldName, type, length, colIdentifier, selfCols = [];
self.__columns = selfCols;
while (++i < l) {
col = fields[i];
fieldName = col.name;
type = col.type;
length = col.fieldLength;
colIdentifier = self.outputIdentifier(fieldName);
selfCols[i] = colIdentifier;
cols[i] = [colIdentifier, DB.convertMysqlType(type === 1 && length !== 1 ? 2 : type), fieldName];
}
return self.__processRows(r, cols);
return self.__processRows(r, cols);
}));
},
__processRows: function (rows, cols) {
//dp this so the callbacks are called in appropriate order also.
var ret = [], i = -1, l = rows.length, j = -1, k = cols.length, row, h, col;
while (++i < l) {
row = rows[i];
h = {};
j = -1;
while (++j < k) {
col = cols[j];
h[col[0]] = col[1](row[col[2]]);
var ret = [], i = -1, l = rows.length, j = -1, k = cols.length, row, h, col;
while (++i < l) {
row = rows[i];
h = {};
j = -1;
while (++j < k) {
col = cols[j];
h[col[0]] = col[1](row[col[2]]);
}
ret[i] = h;
ret[i] = h;
}
return ret;
return ret;
},
//Don't allow graphing a dataset that splits multiple statements
//Set the :type option to select if it hasn't been set.
execute: function (sql, opts) {
opts = opts || {};
return this._super([sql, merge({type: "select"}, opts)]);
opts = opts || {};
return this._super([sql, merge({type: "select"}, opts)]);
},
//Set the :type option to :select if it hasn't been set.
},
validate: function (conn) {
return new Promise().callback(true).promise();
return new Promise().callback(true).promise();
},
execute: function (sql, opts, conn) {
var self = this;
return when(conn || this._getConnection()).chain(function (conn) {
return self.__execute(conn, sql, opts);
var self = this;
return when(conn || this._getConnection()).chain(function (conn) {
return self.__execute(conn, sql, opts);
});
},
__execute: function (conn, sql, opts, cb) {
var self = this;
return this.__logAndExecute(sql, function () {
return conn.query(sql);
var self = this;
return this.__logAndExecute(sql, function () {
return conn.query(sql);
})
.both(function () {
return self._returnConnection(conn);
return self._returnConnection(conn);
});
},
//Use the MySQL specific DESCRIBE syntax to get a table description.
schemaParseTable: function (tableName, opts) {
var m = this.outputIdentifierFunc, im = this.inputIdentifierFunc, self = this;
return this.metadataDataset.withSql("DESCRIBE ?", sql.identifier(im(tableName))).map(function (row) {
var ret = {};
var e = row[m("Extra")];
var allowNull = row[m("Null")];
var key = row[m("Key")];
ret.autoIncrement = e.match(/auto_increment/i) !== null;
ret.allowNull = allowNull.match(/Yes/i) !== null;
ret.primaryKey = key.match(/PRI/i) !== null;
var defaultValue = row[m("Default")];
ret["default"] = Buffer.isBuffer(defaultValue) ? defaultValue.toString() : defaultValue;
if (isEmpty(row["default"])) {
row["default"] = null;
var m = this.outputIdentifierFunc, im = this.inputIdentifierFunc, self = this;
return this.metadataDataset.withSql("DESCRIBE ?", sql.identifier(im(tableName))).map(function (row) {
var ret = {};
var e = row[m("Extra")];
var allowNull = row[m("Null")];
var key = row[m("Key")];
ret.autoIncrement = e.match(/auto_increment/i) !== null;
ret.allowNull = allowNull.match(/Yes/i) !== null;
ret.primaryKey = key.match(/PRI/i) !== null;
var defaultValue = row[m("Default")];
ret["default"] = Buffer.isBuffer(defaultValue) ? defaultValue.toString() : defaultValue;
if (isEmpty(row["default"])) {
row["default"] = null;
}
ret.dbType = row[m("Type")];
if (Buffer.isBuffer(ret.dbType)) {
ret.dbType = row[m("Type")];
if (Buffer.isBuffer(ret.dbType)) {
//handle case for field type being returned at 252 (i.e. BLOB)
ret.dbType = ret.dbType.toString();
ret.dbType = ret.dbType.toString();
}
ret.type = self.schemaColumnType(ret.dbType.toString("utf8"));
var fieldName = m(row[m("Field")]);
return [fieldName, ret];
ret.type = self.schemaColumnType(ret.dbType.toString("utf8"));
var fieldName = m(row[m("Field")]);
return [fieldName, ret];
});
},
//Convert tinyint(1) type to boolean if convert_tinyint_to_bool is true
schemaColumnType: function (dbType) {
return this._static.convertTinyintToBool && dbType === 'tinyint(1)' ? "boolean" : this._super(arguments);
return this._static.convertTinyintToBool && dbType === 'tinyint(1)' ? "boolean" : this._super(arguments);
},
},
dataset: function () {
return new DS(this);
return new DS(this);
}
}
},
},
convertMysqlType: function (type) {
var convert = this.convertTinyintToBool, convertDateTime = this.__convertInvalidDateTime, types = this.FIELD_TYPES;
if (!patio) {
var convert = this.convertTinyintToBool, convertDateTime = this.__convertInvalidDateTime, types = this.FIELD_TYPES;
if (!patio) {
patio = require("../index");
}
return function (o) {
var ret = o;
if (o !== null) {
switch (type) {
return function (o) {
var ret = o;
if (o !== null) {
switch (type) {
case types.FIELD_TYPE_TIMESTAMP:
case types.FIELD_TYPE_DATETIME:
ret = convertDate(o, "stringToDateTime", convertDateTime);
case types.FIELD_TYPE_MEDIUM_BLOB:
case types.FIELD_TYPE_LONG_BLOB:
case types.FIELD_TYPE_BLOB:
ret = new Buffer(o);
break;
ret = new Buffer(o);
break;
}
}
return ret;
return ret;
};
},
getters: {
convertTinyintToBool: function () {
return this.__convertTinyintToBool;
return this.__convertTinyintToBool;
},
convertInvalidDateTime: function () {
* @property {Boolean} hasSelectSource true if this dataset already has a select sources.
*/
constructor:function (db, opts) {
this._super(arguments);
this.db = db;
this.__opts = {};
this.__rowCb = null;
if (db) {
this.__quoteIdentifiers = db.quoteIdentifiers;
this.__identifierInputMethod = db.identifierInputMethod;
this.__identifierOutputMethod = db.identifierOutputMethod;
this._super(arguments);
this.db = db;
this.__opts = {};
this.__rowCb = null;
if (db) {
this.__quoteIdentifiers = db.quoteIdentifiers;
this.__identifierInputMethod = db.identifierInputMethod;
this.__identifierOutputMethod = db.identifierOutputMethod;
}
},
* @return [patio.Dataset] a cloned dataset with the merged options
**/
mergeOptions:function (opts) {
opts = isUndefined(opts) ? {} : opts;
var ds = new this._static(this.db, {});
ds.rowCb = this.rowCb;
this._static.FEATURES.forEach(function (f) {
ds[f] = this[f];
opts = isUndefined(opts) ? {} : opts;
var ds = new this._static(this.db, {});
ds.rowCb = this.rowCb;
this._static.FEATURES.forEach(function (f) {
ds[f] = this[f];
}, this);
var dsOpts = ds.__opts = merge({}, this.__opts, opts);
ds.identifierInputMethod = this.identifierInputMethod;
ds.identifierOutputMethod = this.identifierOutputMethod;
var columnChangeOpts = this._static.COLUMN_CHANGE_OPTS;
if (Object.keys(opts).some(function (o) {
return columnChangeOpts.indexOf(o) !== -1;
var dsOpts = ds.__opts = merge({}, this.__opts, opts);
ds.identifierInputMethod = this.identifierInputMethod;
ds.identifierOutputMethod = this.identifierOutputMethod;
var columnChangeOpts = this._static.COLUMN_CHANGE_OPTS;
if (Object.keys(opts).some(function (o) {
return columnChangeOpts.indexOf(o) !== -1;
})) {
dsOpts.columns = null;
dsOpts.columns = null;
}
return ds;
return ds;
},
* @return {patio.sql.Identifier|patio.sql.QualifiedIdentifier|patio.sql.AliasedExpression} an identifier generated based on the name string.
*/
stringToIdentifier:function (name) {
if (isString(name)) {
var parts = this._splitString(name);
var schema = parts[0], table = parts[1], alias = parts[2];
return (schema && table && alias
if (isString(name)) {
var parts = this._splitString(name);
var schema = parts[0], table = parts[1], alias = parts[2];
return (schema && table && alias
? new AliasedExpression(new QualifiedIdentifier(schema, table), alias)
: (schema && table
? new QualifiedIdentifier(schema, table)
: (table && alias
? new AliasedExpression(new Identifier(table), alias) : new Identifier(table))));
} else {
return name;
return name;
}
},
* </ul>
*/
_splitString:function (s) {
var ret, m;
if ((m = s.match(this._static.COLUMN_REF_RE1)) !== null) {
ret = m.slice(1);
var ret, m;
if ((m = s.match(this._static.COLUMN_REF_RE1)) !== null) {
ret = m.slice(1);
}
else if ((m = s.match(this._static.COLUMN_REF_RE2)) !== null) {
else if ((m = s.match(this._static.COLUMN_REF_RE2)) !== null) {
ret = [null, m[1], m[2]];
}
else if ((m = s.match(this._static.COLUMN_REF_RE3)) !== null) {
ret = [m[1], m[2], null];
else if ((m = s.match(this._static.COLUMN_REF_RE3)) !== null) {
ret = [m[1], m[2], null];
}
else {
ret = [null, s, null];
ret = [null, s, null];
}
return ret;
return ret;
},
/**
getters:{
rowCb:function () {
return this.__rowCb;
return this.__rowCb;
},
identifierInputMethod:function () {
return this.__identifierInputMethod;
return this.__identifierInputMethod;
},
identifierOutputMethod:function () {
return this.__identifierOutputMethod;
return this.__identifierOutputMethod;
},
firstSourceAlias:function () {
var source = this.__opts.from;
if (isUndefinedOrNull(source) || !source.length) {
var source = this.__opts.from;
if (isUndefinedOrNull(source) || !source.length) {
throw new DatasetError("No source specified for the query");
}
source = source[0];
if (isInstanceOf(source, AliasedExpression)) {
source = source[0];
if (isInstanceOf(source, AliasedExpression)) {
return source.alias;
} else if (isString(source)) {
} else if (isString(source)) {
var parts = this._splitString(source);
var alias = parts[2];
return alias ? alias : source;
} else {
return source;
return source;
}
},
/**@lends patio.Dataset.prototype*/
identifierInputMethod:function (meth) {
this.__identifierInputMethod = meth;
this.__identifierInputMethod = meth;
},
identifierOutputMethod:function (meth) {
this.__identifierOutputMethod = meth;
this.__identifierOutputMethod = meth;
},
rowCb:function (cb) {
if (isFunction(cb) || isNull(cb)) {
this.__rowCb = cb;
if (isFunction(cb) || isNull(cb)) {
this.__rowCb = cb;
} else {
throw new DatasetError("rowCb mus be a function");
}
* @borrows patio.Dataset#leftJoin as leftJoin
* */
constructor: function (options, fromDb) {
if (this.synced) {
this.__emitter = new EventEmitter();
this._super(arguments);
this.patio = patio || require("./index");
fromDb = isBoolean(fromDb) ? fromDb : false;
this.__changed = {};
this.__values = {};
if (fromDb) {
if (this.synced) {
this.__emitter = new EventEmitter();
this._super(arguments);
this.patio = patio || require("./index");
fromDb = isBoolean(fromDb) ? fromDb : false;
this.__changed = {};
this.__values = {};
if (fromDb) {
this._hook("pre", "load");
this.__isNew = false;
this.__setFromDb(options, true);
this._static.emit("load", this);
}
} else {
this.__isNew = true;
this.__set(options);
this.__isNew = true;
this.__set(options);
}
} else {
throw new ModelError("Model " + this.tableName + " has not been synced");
},
__set: function (values, ignore) {
values = values || {};
this.__ignore = ignore === true;
Object.keys(values).forEach(function (attribute) {
values = values || {};
this.__ignore = ignore === true;
Object.keys(values).forEach(function (attribute) {
var value = values[attribute];
//check if the column is a constrained value and is allowed to be set
!ignore && this._checkIfColumnIsConstrained(attribute);
this[attribute] = value;
}, this);
this.__ignore = false;
this.__ignore = false;
},
__setFromDb: function (values, ignore) {
},
synced: function () {
return this._static.synced;
return this._static.synced;
}
}
* Proxy the quoteSchemaTable method to the dataset
* */
__quoteSchemaTable: function (table) {
return this.__schemaUtiltyDataset.quoteSchemaTable(table);
return this.__schemaUtiltyDataset.quoteSchemaTable(table);
},
/**
* @field
* */
__schemaUtiltyDataset: function () {
this.__schemaUtiltyDs = this.__schemaUtiltyDs || this.dataset;
return this.__schemaUtiltyDs;
this.__schemaUtiltyDs = this.__schemaUtiltyDs || this.dataset;
return this.__schemaUtiltyDs;
}
}
isString = comb.isString,
define = comb.define,
isRegExp = comb.isRegExp,
Dataset, patio;
Dataset, patio, sql, Expression, AliasedExpression, CaseExpression, Cast,
ColumnAll, BooleanExpression;
var virtualRow = function (name) {
var WILDCARD = new LiteralString('*');
var QUESTION_MARK = new LiteralString('?');
var COMMA_SEPARATOR = new LiteralString(', ');
var DOUBLE_UNDERSCORE = '__';
var parts = name.split(DOUBLE_UNDERSCORE);
var table = parts[0], column = parts[1];
var ident = column ? QualifiedIdentifier.fromArgs([table, column]) : Identifier.fromArgs([name]);
var prox = methodMissing(ident, function (m) {
var DOUBLE_UNDERSCORE = '__';
var parts = name.split(DOUBLE_UNDERSCORE);
var table = parts[0], column = parts[1];
var ident = column ? QualifiedIdentifier.fromArgs([table, column]) : Identifier.fromArgs([name]);
var prox = methodMissing(ident, function (m) {
return function () {
var args = argsToArray(arguments);
return SQLFunction.fromArgs([m, name].concat(args));
}
};
}, column ? QualifiedIdentifier : Identifier);
var ret = createFunctionWrapper(prox, function (m) {
var args = argsToArray(arguments);
if (args.length) {
return SQLFunction.fromArgs([name].concat(args));
var ret = createFunctionWrapper(prox, function (m) {
var args = argsToArray(arguments);
if (args.length) {
return SQLFunction.fromArgs([name].concat(args));
} else {
return prox;
}
}, function () {
return SQLFunction.fromArgs(arguments);
});
ret.__proto__ = ident;
return ret;
ret["__proto__"] = ident;
return ret;
};
var DATE_METHODS = ["getDate", "getDay", "getFullYear", "getHours", "getMilliseconds", "getMinutes", "getMonth", "getSeconds",
var addDateMethod = function (op) {
return function () {
return this.date[op].apply(this.date, arguments);
}
};
};
/**
*/
var DateTime = function (y, m, d, h, min, s, ms) {
var args = argsToArray(arguments);
if(args.length === 0){
if (args.length === 0) {
this.date = new Date();
}else if (isDate(y)) {
} else if (isDate(y)) {
this.date = y;
} else {
var date = new Date(1970, 0, 1, 0, 0, 0);
* @name sql
* @memberOf patio
*/
var sql = {
sql = {
/**@lends patio.sql*/
/**
*
* @return {patio.sql.Identifier|patio.sql.QualifiedIdentifier|patio.sql.AliasedExpression} an identifier generated based on the name string.
*/
identifier:function (s) {
return sql.stringToIdentifier(s);
identifier: function (s) {
return sql.stringToIdentifier(s);
},
/**
* @see patio.sql.identifier
*/
stringToIdentifier:function (name) {
!Dataset && (Dataset = require("./dataset"));
return new Dataset().stringToIdentifier(name);
stringToIdentifier: function (name) {
!Dataset && (Dataset = require("./dataset"));
return new Dataset().stringToIdentifier(name);
},
/**
* @return {patio.sql.LiteralString|patio.sql.PlaceHolderLiteralString} an expression that can be used as an argument
* for {@link patio.Dataset} query methods.
*/
literal:function (s) {
var args = argsToArray(arguments);
return args.length > 1 ? PlaceHolderLiteralString.fromArgs(args) : new LiteralString(s);
literal: function (s) {
var args = argsToArray(arguments);
return args.length > 1 ? PlaceHolderLiteralString.fromArgs(args) : new LiteralString(s);
},
/**
* sql["case"]({a:sql.b}, sql.c, sql.d); //=> (CASE t.d WHEN t.a THEN t.b ELSE t.c END)
*
*/
"case":function (hash, /*args**/opts) {
"case": function (hash, /*args**/opts) {
var args = argsToArray(arguments, 1);
return CaseExpression.fromArgs([hashToArray(hash)].concat(args));
},
* patio.sql.sqlStringJoin([sql.a, 'b']) # SQL: a || 'b'
* patio.sql.sqlStringJoin(['a', sql.b], ' '); //=> 'a' || ' ' || b
*/
sqlStringJoin:function (arr, joiner) {
sqlStringJoin: function (arr, joiner) {
joiner = joiner || null;
var args;
arr = arr.map(function (a) {
return isInstanceOf(a, Expression, LiteralString, Boolean) || isNull(a) ? a : sql.stringToIdentifier(a)
return isInstanceOf(a, Expression, LiteralString, Boolean) || isNull(a) ? a : sql.stringToIdentifier(a);
});
if (joiner) {
var newJoiner = [];
return StringExpression.fromArgs(["||"].concat(args));
},
Year:Year,
TimeStamp:TimeStamp,
Time:Time,
DateTime:DateTime,
Float:Float,
Decimal:Decimal
Year: Year,
TimeStamp: TimeStamp,
Time: Time,
DateTime: DateTime,
Float: Float,
Decimal: Decimal
};
sql.__defineGetter__("patio", function () {
sql["__defineGetter__"]("patio", function () {
!patio && (patio = require("./index"));
return patio;
});
exports.sql = methodMissing(sql, function (name) {
return virtualRow(name);
return virtualRow(name);
});
var OPERTATOR_INVERSIONS = {
AND:"OR",
OR:"AND",
GT:"lte",
GTE:"lt",
LT:"gte",
LTE:"gt",
EQ:"neq",
NEQ:"eq",
LIKE:'NOT LIKE',
"NOT LIKE":"LIKE",
'!~*':'~*',
'~*':'!~*',
"~":'!~',
"IN":'NOTIN',
"NOTIN":"IN",
"IS":'IS NOT',
"ISNOT":"IS",
NOT:"NOOP",
NOOP:"NOT",
ILIKE:'NOT ILIKE',
NOTILIKE:"ILIKE"
AND: "OR",
OR: "AND",
GT: "lte",
GTE: "lt",
LT: "gte",
LTE: "gt",
EQ: "neq",
NEQ: "eq",
LIKE: 'NOT LIKE',
"NOT LIKE": "LIKE",
'!~*': '~*',
'~*': '!~*',
"~": '!~',
"IN": 'NOTIN',
"NOTIN": "IN",
"IS": 'IS NOT',
"ISNOT": "IS",
NOT: "NOOP",
NOOP: "NOT",
ILIKE: 'NOT ILIKE',
NOTILIKE: "ILIKE"
};
// Standard mathematical operators used in +NumericMethods+
var MATHEMATICAL_OPERATORS = {PLUS:"+", MINUS:"-", DIVIDE:"/", MULTIPLY:"*"};
var MATHEMATICAL_OPERATORS = {PLUS: "+", MINUS: "-", DIVIDE: "/", MULTIPLY: "*"};
// Bitwise mathematical operators used in +NumericMethods+
var BITWISE_OPERATORS = {bitWiseAnd:"&", bitWiseOr:"|", exclusiveOr:"^", leftShift:"<<", rightShift:">>"};
var BITWISE_OPERATORS = {bitWiseAnd: "&", bitWiseOr: "|", exclusiveOr: "^", leftShift: "<<", rightShift: ">>"};
var INEQUALITY_OPERATORS = {GT:">", GTE:">=", LT:"<", LTE:"<="};
var INEQUALITY_OPERATORS = {GT: ">", GTE: ">=", LT: "<", LTE: "<="};
//Hash of ruby operator symbols to SQL operators, used in +BooleanMethods+
var BOOLEAN_OPERATORS = {AND:"AND", OR:"OR"};
var BOOLEAN_OPERATORS = {AND: "AND", OR: "OR"};
//Operators that use IN/NOT IN for inclusion/exclusion
var IN_OPERATORS = {IN:"IN", NOTIN:'NOT IN'};
var IN_OPERATORS = {IN: "IN", NOTIN: 'NOT IN'};
//Operators that use IS, used for special casing to override literal true/false values
var IS_OPERATORS = {IS:"IS", ISNOT:'IS NOT'};
var IS_OPERATORS = {IS: "IS", ISNOT: 'IS NOT'};
//Operator symbols that take exactly two arguments
var TWO_ARITY_OPERATORS = merge({
EQ:'=',
NEQ:'!=', LIKE:"LIKE",
"NOT LIKE":'NOT LIKE',
ILIKE:"ILIKE",
"NOT ILIKE":'NOT ILIKE',
"~":"~",
'!~':"!~",
'~*':"~*",
'!~*':"!~*"}, INEQUALITY_OPERATORS, BITWISE_OPERATORS, IS_OPERATORS, IN_OPERATORS);
EQ: '=',
NEQ: '!=',
LIKE: "LIKE",
"NOT LIKE": 'NOT LIKE',
ILIKE: "ILIKE",
"NOT ILIKE": 'NOT ILIKE',
"~": "~",
'!~': "!~",
'~*': "~*",
'!~*': "!~*"
}, INEQUALITY_OPERATORS, BITWISE_OPERATORS, IS_OPERATORS, IN_OPERATORS);
//Operator symbols that take one or more arguments
var N_ARITY_OPERATORS = merge({"||":"||"}, BOOLEAN_OPERATORS, MATHEMATICAL_OPERATORS);
var N_ARITY_OPERATORS = merge({"||": "||"}, BOOLEAN_OPERATORS, MATHEMATICAL_OPERATORS);
//Operator symbols that take only a single argument
var ONE_ARITY_OPERATORS = {"NOT":"NOT", "NOOP":"NOOP"};
var ONE_ARITY_OPERATORS = {"NOT": "NOT", "NOOP": "NOOP"};
/**
* @class Mixin to provide alias methods to an expression.
* @memberOf patio.sql
*/
var AliasMethods = define(null, {
instance:{
instance: {
/**@lends patio.sql.AliasMethods.prototype*/
/**
*
* @return {patio.sql.AliasedExpression} the aliased expression.
*/
as:function (alias) {
return new AliasedExpression(this, alias);
as: function (alias) {
return new AliasedExpression(this, alias);
}
}
else {
return new BooleanExpression(op, this, expression);
}
}
};
};
/**
* @memberOf patio.sql
*/
var BitWiseMethods = define(null, {
instance:{
instance: {
/**@lends patio.sql.BitWiseMethods.prototype*/
/**
* @example
* sql.a.sqlNumber.bitWiseAnd("b"); //=> "a" & "b"
*/
bitWiseAnd:bitWiseMethod("bitWiseAnd"),
bitWiseAnd: bitWiseMethod("bitWiseAnd"),
/**
* Bitwise or
* @example
* sql.a.sqlNumber.bitWiseOr("b") //=> "a" | "b"
*/
bitWiseOr:bitWiseMethod("bitWiseOr"),
bitWiseOr: bitWiseMethod("bitWiseOr"),
/**
* Exclusive Or
*
* sql.a.sqlNumber.exclusiveOr("b") //=> "a" ^ "b"
*/
exclusiveOr:bitWiseMethod("exclusiveOr"),
exclusiveOr: bitWiseMethod("exclusiveOr"),
/**
* Bitwise shift left
*
* sql.a.sqlNumber.leftShift("b") // "a" << "b"
*/
leftShift:bitWiseMethod("leftShift"),
leftShift: bitWiseMethod("leftShift"),
/**
* Bitwise shift right
*
* sql.a.sqlNumber.rightShift("b") //=> "a" >> "b"
*/
rightShift:bitWiseMethod("rightShift")
rightShift: bitWiseMethod("rightShift")
}
}).as(sql, "BitWiseMethods");
else {
return new BooleanExpression(op, this, expression);
}
}
};
};
/**
* @memberOf patio.sql
*/
var BooleanMethods = define(null, {
instance:{
instance: {
/**@lends patio.sql.BooleanMethods.prototype*/
/**
*
* @return {patio.sql.BooleanExpression} a ANDed boolean expression.
*/
and:booleanMethod("and"),
and: booleanMethod("and"),
/**
* @function
*
* @return {patio.sql.BooleanExpression} a ORed boolean expression
*/
or:booleanMethod("or"),
or: booleanMethod("or"),
/**
* Logical NOT
*
* @return {patio.sql.BooleanExpression} a inverted boolean expression.
*/
not:function () {
not: function () {
return BooleanExpression.invert(this);
}
* @memberOf patio.sql
*/
var CastMethods = define(null, {
instance:{
instance: {
/**@lends patio.sql.CastMethods.prototype*/
/**
* Cast the reciever to the given SQL type.
*
* @return {patio.sql.Cast} the casted expression
*/
cast:function (type) {
cast: function (type) {
return new Cast(this, type);
},
*
* @return {patio.sql.NumericExpression} a casted numberic expression
*/
castNumeric:function (type) {
castNumeric: function (type) {
return this.cast(type || "integer").sqlNumber;
},
*
* @return {patio.sql.StringExpression} the casted string expression
*/
castString:function (type) {
castString: function (type) {
return this.cast(type || String).sqlString;
}
}
* </pre>
*/
var ComplexExpressionMethods = define(null, {
instance:{
instance: {
/**@ignore*/
getters:{
getters: {
/**
* @ignore
*/
sqlBoolean:function () {
sqlBoolean: function () {
return new BooleanExpression("noop", this);
},
/**
* @ignore
*/
sqlFunction:function () {
sqlFunction: function () {
return new SQLFunction(this);
},
/**
* @ignore
*/
sqlNumber:function () {
sqlNumber: function () {
return new NumericExpression("noop", this);
},
/**
* @ignore
*/
sqlString:function () {
sqlString: function () {
return new StringExpression("noop", this);
}
}
var inequalityMethod = function (op) {
return function (expression) {
if (isInstanceOf(expression, BooleanExpression)
|| isBoolean(expression)
|| isNull(expression)
|| (isHash(expression))
|| isArray(expression)) {
if (isInstanceOf(expression, BooleanExpression) ||
isBoolean(expression) ||
isNull(expression) ||
(isHash(expression)) ||
isArray(expression)) {
throw new ExpressionError("Cannot apply " + op + " to a boolean expression");
} else {
return new BooleanExpression(op, this, expression);
}
}
};
};
/**
* @memberOf patio.sql
*/
var InequalityMethods = define(null, {
instance:{
instance: {
/**@lends patio.sql.InequalityMethods.prototype*/
/**
*
* @return {patio.sql.BooleanExpression}
*/
gt:inequalityMethod("gt"),
gt: inequalityMethod("gt"),
/**
* @function Creates a gte {@link patio.sql.BooleanExpression} compared to this expression.
*
*
* @return {patio.sql.BooleanExpression}
*/
gte:inequalityMethod("gte"),
gte: inequalityMethod("gte"),
/**
* @function Creates a lt {@link patio.sql.BooleanExpression} compared to this expression.
*
*
* @return {patio.sql.BooleanExpression}
*/
lt:inequalityMethod("lt"),
lt: inequalityMethod("lt"),
/**
* @function Creates a lte {@link patio.sql.BooleanExpression} compared to this expression.
*
*
* @return {patio.sql.BooleanExpression}
*/
lte:inequalityMethod("lte"),
lte: inequalityMethod("lte"),
/**
* @function Creates a eq {@link patio.sql.BooleanExpression} compared to this expression.
*
*
* @return {patio.sql.BooleanExpression}
*/
eq:inequalityMethod("eq"),
eq: inequalityMethod("eq"),
neq:inequalityMethod("neq"),
neq: inequalityMethod("neq"),
/**
* @private
*
* @return {patio.sql.BooleanExpression} a boolean expression containing the between expression.
*/
between:function (items) {
return new BooleanExpression("AND", new BooleanExpression("gte", this, items[0]), new BooleanExpression("lte", this, items[1]))
between: function (items) {
return new BooleanExpression("AND", new BooleanExpression("gte", this, items[0]), new BooleanExpression("lte", this, items[1]));
}
}
}).as(sql, "InequalityMethods");
* @memberOf patio.sql
*/
var NoBooleanInputMethods = define(null, {
instance:{
constructor:function (op) {
instance: {
constructor: function (op) {
var args = argsToArray(arguments, 1);
args.forEach(function (expression) {
if ((isInstanceOf(expression, BooleanExpression))
|| isBoolean(expression)
|| isNull(expression)
|| (isObject(expression) && !isInstanceOf(expression, Expression, Dataset, LiteralString))
|| isArray(expression)) {
if ((isInstanceOf(expression, BooleanExpression)) ||
isBoolean(expression) ||
isNull(expression) ||
(isObject(expression) && !isInstanceOf(expression, Expression, Dataset, LiteralString)) ||
isArray(expression)) {
throw new ExpressionError("Cannot apply " + op + " to a boolean expression");
}
});
} else {
return new NumericExpression(op, this, expression);
}
}
};
};
* @memberOf patio.sql
*/
var NumericMethods = define(null, {
instance:{
instance: {
/**@lends patio.sql.NumericMethods.prototype*/
*
* @return {patio.sql.NumericExpression}
*/
plus:numericMethod("plus"),
plus: numericMethod("plus"),
/**
* @function Subtracts the provided expression from this expression and returns a {@link patio.sql.NumericExpression}.
*
* @return {patio.sql.NumericExpression}
*/
minus:numericMethod("minus"),
minus: numericMethod("minus"),
/**
* @function Divides this expression by the provided expression and returns a {@link patio.sql.NumericExpression}.
*
* @return {patio.sql.NumericExpression}
*/
divide:numericMethod("divide"),
divide: numericMethod("divide"),
/**
* @function Divides this expression by the provided expression and returns a {@link patio.sql.NumericExpression}.
*
* @return {patio.sql.NumericExpression}
*/
multiply:numericMethod("multiply")
multiply: numericMethod("multiply")
}
}).as(sql, "NumericMethods");
* @memberOf patio.sql
*/
var OrderedMethods = define(null, {
instance:{
instance: {
/**@lends patio.sql.OrderedMethods.prototype*/
/**
* before other values), or "last" to use NULLS LAST (so NULL values are ordered after other values).
* @return {patio.sql.OrderedExpression}
*/
asc:function (options) {
asc: function (options) {
return new OrderedExpression(this, false, options);
},
* before other values), or "last" to use NULLS LAST (so NULL values are ordered after other values).
* @return {patio.sql.OrderedExpression}
*/
desc:function (options) {
desc: function (options) {
return new OrderedExpression(this, true, options);
}
}
* @memberOf patio.sql
*/
var QualifyingMethods = define(null, {
instance:{
instance: {
/**@lends patio.sql.QualifyingMethods.prototype*/
/**
*
* @return {patio.sql.QualifiedIdentifier}
*/
qualify:function (qualifier) {
return new QualifiedIdentifier(qualifier, this);
qualify: function (qualifier) {
return new QualifiedIdentifier(qualifier, this);
},
/**
*
* @return {patio.sql.ColumnAll}
*/
all:function () {
all: function () {
return new ColumnAll(this);
}
* @memberOf patio.sql
*/
var StringMethods = define(null, {
instance:{
instance: {
/**@lends patio.sql.StringMethods.prototype*/
/**
*
* @return {patio.sql.BooleanExpression}
*/
ilike:function (expression) {
ilike: function (expression) {
expression = argsToArray(arguments);
return StringExpression.like.apply(StringExpression, [this].concat(expression).concat([
{caseInsensitive:true}
{caseInsensitive: true}
]));
},
*
* @param expression
*/
like:function (expression) {
like: function (expression) {
expression = argsToArray(arguments);
return StringExpression.like.apply(StringExpression, [this].concat(expression));
}
* @memberOf patio.sql
*/
var StringConcatenationMethods = define(null, {
instance:{
instance: {
/**@lends patio.sql.StringConcatenationMethods.prototype*/
/**
*
* @param expression expression to concatenate this expression with.
*/
concat:function (expression) {
concat: function (expression) {
return new StringExpression("||", this, expression);
}
}
* @memberOf patio.sql
*/
var SubscriptMethods = define(null, {
instance:{
instance: {
/**
* Return a {@link patio.sql.Subscript} with the given arguments, representing an
*
* @param subscript
*/
sqlSubscript:function (subscript) {
sqlSubscript: function (subscript) {
var args = argsToArray(arguments);
return new SubScript(this, flatten(args));
}
* @name Expression
* @memberOf patio.sql
*/
var Expression = define(null, {
Expression = define(null, {
instance:{
instance: {
/**@lends patio.sql.Expression.prototype*/
/**
* @param {patio.Dataset} ds the dataset that will be used to SQL-ify this expression.
* @return {String} a string literal version of this expression.
*/
sqlLiteral:function (ds) {
sqlLiteral: function (ds) {
return this.toString(ds);
}
},
static:{
static: {
/**@lends patio.sql.Expression*/
/**
*
* @return {patio.sql.Expression} an expression.
*/
fromArgs:function (args) {
var ret;
try {
ret = new this();
fromArgs: function (args) {
var ret, Self = this;
try {
ret = new Self();
} catch (ignore) {
}
this.apply(ret, args);
return ret;
this.apply(ret, args);
return ret;
},
/**
* @param {*} obj object to test if it is a condition specifier
* @return {Boolean} true if the object is a Hash or is an array of two element arrays.
*/
isConditionSpecifier:function (obj) {
return isHash(obj) || (isArray(obj) && obj.length && obj.every(function (i) {
return isArray(i) && i.length === 2;
isConditionSpecifier: function (obj) {
return isHash(obj) || (isArray(obj) && obj.length && obj.every(function (i) {
return isArray(i) && i.length === 2;
}));
}
}
var GenericExpression = define([Expression, AliasMethods, BooleanMethods, CastMethods, ComplexExpressionMethods, InequalityMethods, NumericMethods, OrderedMethods, StringMethods, SubscriptMethods]).as(sql, "GenericExpression");
var AliasedExpression = define(Expression, {
instance:{
AliasedExpression = define(Expression, {
instance: {
/**@lends patio.sql.AliasedExpression.prototype*/
/**
* @property alias the alias of the expression
*
*/
constructor:function (expression, alias) {
this.expression = expression;
this.alias = alias;
constructor: function (expression, alias) {
this.expression = expression;
this.alias = alias;
},
/**
*
* @return String the SQL alias fragment.
*/
toString:function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.aliasedExpressionSql(this);
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.aliasedExpressionSql(this);
}
}
}
).as(sql, "AliasedExpression");
var CaseExpression = define(GenericExpression, {
instance:{
CaseExpression = define(GenericExpression, {
instance: {
/**@lends patio.sql.CaseExpression.prototype*/
/**
* @property expression the expression of the {@link patio.sql.CaseExpression}.
* @property {Boolean} noExpression true if this {@link patio.sql.CaseExpression}'s expression is undefined.
*/
constructor:function (conditions, def, expression) {
constructor: function (conditions, def, expression) {
if (Expression.isConditionSpecifier(conditions)) {
this.conditions = toArray(conditions);
this.def = def;
*
* @return String the SQL case expression fragment.
*/
toString:function (ds) {
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.caseExpressionSql(this);
},
/**@ignore*/
getters:{
getters: {
/**@ignore*/
hasExpression:function () {
hasExpression: function () {
return !this.noExpression;
}
}
}).as(sql, "CaseExpression");
var Cast = define(GenericExpression, {
instance:{
Cast = define(GenericExpression, {
instance: {
/**@lends patio.sql.Cast*/
/**
* @property expr the expression to CAST.
* @property type the type to CAST the expression to.
*/
constructor:function (expr, type) {
constructor: function (expr, type) {
this.expr = expr;
this.type = type;
},
*
* @return String the SQL cast expression fragment.
*/
toString:function (ds) {
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.castSql(this.expr, this.type);
}).as(sql, "Cast");
var ColumnAll = define(Expression, {
instance:{
ColumnAll = define(Expression, {
instance: {
/**@lends patio.sql.ColumnAll.prototype*/
/**
*
* @property table the table this all column expression represents.
*/
constructor:function (table) {
constructor: function (table) {
this.table = table;
},
*
* @return String the SQL columnAll expression fragment.
*/
toString:function (ds) {
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.columnAllSql(this);
}).as(sql, "ColumnAll");
var ComplexExpression = define([Expression, AliasMethods, CastMethods, OrderedMethods, SubscriptMethods], {
instance:{
instance: {
/**@lends patio.sql.ComplexExpression.prototype*/
/**
* other than the second arg for an IN/NOT IN operator.</li>
* </p>
*/
constructor:function (op) {
if (op) {
var args = argsToArray(arguments,1 );
constructor: function (op) {
if (op) {
var args = argsToArray(arguments, 1);
//make a copy of the args
var origArgs = args.slice(0);
args.forEach(function (a, i) {
if (Expression.isConditionSpecifier(a)) {
var origArgs = args.slice(0);
args.forEach(function (a, i) {
if (Expression.isConditionSpecifier(a)) {
args[i] = BooleanExpression.fromValuePairs(a);
}
});
op = op.toUpperCase();
op = op.toUpperCase();
if (N_ARITY_OPERATORS.hasOwnProperty(op)) {
if (args.length < 1) {
throw new ExpressionError("The " + op + " operator requires at least 1 argument")
if (N_ARITY_OPERATORS.hasOwnProperty(op)) {
if (args.length < 1) {
throw new ExpressionError("The " + op + " operator requires at least 1 argument");
}
var oldArgs = args.slice(0);
args = [];
oldArgs.forEach(function (a) {
a instanceof ComplexExpression && a.op == op ? args = args.concat(a.args) : args.push(a);
var oldArgs = args.slice(0);
args = [];
oldArgs.forEach(function (a) {
a instanceof ComplexExpression && a.op === op ? args = args.concat(a.args) : args.push(a);
});
} else if (TWO_ARITY_OPERATORS.hasOwnProperty(op)) {
if (args.length != 2) {
} else if (TWO_ARITY_OPERATORS.hasOwnProperty(op)) {
if (args.length !== 2) {
throw new ExpressionError("The " + op + " operator requires precisely 2 arguments");
}
//With IN/NOT IN, even if the second argument is an array of two element arrays,
//don't convert it into a boolean expression, since it's definitely being used
//as a value list.
if (IN_OPERATORS[op]) {
args[1] = origArgs[1]
if (IN_OPERATORS[op]) {
args[1] = origArgs[1];
}
} else if (ONE_ARITY_OPERATORS.hasOwnProperty(op)) {
if (args.length != 1) {
if (args.length !== 1) {
throw new ExpressionError("The " + op + " operator requires only one argument");
}
} else {
throw new ExpressionError("Invalid operator " + op);
}
this.op = op;
this.args = args;
this.op = op;
this.args = args;
}
},
*
* @return String the SQL version of the {@link patio.sql.ComplexExpression}.
*/
toString:function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.complexExpressionSql(this.op, this.args);
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.complexExpressionSql(this.op, this.args);
}
},
static:{
static: {
/**@lends patio.sql.ComplexExpression*/
/**
* NOTILIKE:"ILIKE"
* }
*/
OPERATOR_INVERSIONS:OPERTATOR_INVERSIONS,
OPERATOR_INVERSIONS: OPERTATOR_INVERSIONS,
/**
* Default mathematical operators.
* @type Object
* @default {PLUS:"+", MINUS:"-", DIVIDE:"/", MULTIPLY:"*"}
*/
MATHEMATICAL_OPERATORS:MATHEMATICAL_OPERATORS,
MATHEMATICAL_OPERATORS: MATHEMATICAL_OPERATORS,
/**
* Default bitwise operators.
* @type Object
* @default {bitWiseAnd:"&", bitWiseOr:"|", exclusiveOr:"^", leftShift:"<<", rightShift:">>"}
*/
BITWISE_OPERATORS:BITWISE_OPERATORS,
BITWISE_OPERATORS: BITWISE_OPERATORS,
/**
* Default inequality operators.
*
* @type Object
* @default {GT:">",GTE:">=",LT:"<",LTE:"<="}
*/
INEQUALITY_OPERATORS:INEQUALITY_OPERATORS,
INEQUALITY_OPERATORS: INEQUALITY_OPERATORS,
/**
* Default boolean operators.
* @type Object
* @default {AND:"AND",OR:"OR"}
*/
BOOLEAN_OPERATORS:BOOLEAN_OPERATORS,
BOOLEAN_OPERATORS: BOOLEAN_OPERATORS,
/**
* Default IN operators.
* @type Object
* @default {IN:"IN",NOTIN:'NOT IN'}
*/
IN_OPERATORS:IN_OPERATORS,
IN_OPERATORS: IN_OPERATORS,
/**
* Default IS operators.
*
* @type Object
* @default {IS:"IS", ISNOT:'IS NOT'}
*/
IS_OPERATORS:IS_OPERATORS,
IS_OPERATORS: IS_OPERATORS,
/**
* Default two arity operators.
*
* NOTIN:'NOT IN'
* }
*/
TWO_ARITY_OPERATORS:TWO_ARITY_OPERATORS,
TWO_ARITY_OPERATORS: TWO_ARITY_OPERATORS,
/**
* Default N(multi) arity operators.
* DIVIDE:"/", MULTIPLY:"*"
* }
*/
N_ARITY_OPERATORS:N_ARITY_OPERATORS,
N_ARITY_OPERATORS: N_ARITY_OPERATORS,
/**
* Default ONE operators.
* "NOOP":"NOOP"
* }
*/
ONE_ARITY_OPERATORS:ONE_ARITY_OPERATORS
ONE_ARITY_OPERATORS: ONE_ARITY_OPERATORS
}
}).as(sql, "ComplexExpression");
* @name BooleanExpression
* @memberOf patio.sql
*/
var BooleanExpression = define([ComplexExpression, BooleanMethods], {
static:{
BooleanExpression = define([ComplexExpression, BooleanMethods], {
static: {
/**@lends patio.sql.BooleanExpression*/
/**
*
* @return {patio.sql.BooleanExpression} the inverted expression.
*/
invert:function (expression) {
if (isInstanceOf(expression, BooleanExpression)) {
var op = expression.op, newArgs;
if (op == "AND" || op == "OR") {
invert: 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);
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]));
* </pre>
* @return {patio.sql.BooleanExpression} expression composed of sub expressions built from the hash.
*/
fromValuePairs: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));
fromValuePairs: 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)) {
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(function (i) {
return isString(i) ? sql.stringToIdentifier(i) : i
return isString(i) ? sql.stringToIdentifier(i) : i;
}) : isString(k) ? sql.stringToIdentifier(k) : k;
ret = new BooleanExpression("IN", k, v);
} else if (isInstanceOf(v, NegativeBooleanConstant)) {
} else if (isInstanceOf(v, NegativeBooleanConstant)) {
ret = new BooleanExpression("ISNOT", k, v.constant);
} else if (isInstanceOf(v, BooleanConstant)) {
} 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);
} else if (isRegExp(v)) {
ret = StringExpression.like(sql.stringToIdentifier(k), v);
} 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);
ret = new BooleanExpression("EQ", sql.stringToIdentifier(k), v);
}
negate && (ret = BooleanExpression.invert(ret));
pairArr.push(ret);
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));
return pairArr.length == 1 ? pairArr[0] : BooleanExpression.fromArgs([op].concat(pairArr));
},
/**
*
* @return {patio.sql.Expression} an expression to use in the filter
*/
__filterObject:function (expr, key) {
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));
} else if (key && (twoArityOperators[k.toUpperCase()] || k.match(/between/i))) {
__filterObject: function (expr, key, op) {
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) {
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);
return this.__filterObject(expr, k, op);
}, this));
} else {
newKey = [sql.stringToIdentifier(newKey[0])];
if (k.match(/^like$/)) {
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$/)) {
} 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)) {
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());
//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));
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]);
newKey = k.split(",");
if (newKey.length == 1) {
newKey = sql.stringToIdentifier(newKey[0]);
}
opts = [
opts = [
[newKey, v]
];
pairs.push(BooleanExpression.fromValuePairs(opts));
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(["AND"].concat(pairs));
return pairs.length == 1 ? pairs[0] : BooleanExpression.fromArgs([op || "AND"].concat(pairs));
}
}
}).as(sql, "BooleanExpression");
var Constant = define(GenericExpression, {
instance:{
instance: {
/**@lends patio.sql.Constant.prototype*/
/**
* Represents constants or psuedo-constants (e.g.'CURRENT_DATE) in SQL.
* @augments patio.sql.GenericExpression
* @property {String} constant <b>READ ONLY</b> the contant.
*/
constructor:function (constant) {
constructor: function (constant) {
this.__constant = constant;
},
*
* @return String the SQL version of the {@link patio.sql.Constant}.
*/
toString:function (ds) {
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.constantSql(this.__constant);
},
getters:{
constant:function () {
getters: {
constant: function () {
return this.__constant;
}
}
* @memberOf patio.sql
*/
var BooleanConstant = define(Constant, {
instance:{
instance: {
/**@lends patio.sql.BooleanConstant.prototype*/
/**
*
* @return String the SQL version of the {@link patio.sql.BooleanConstant}.
*/
toString:function (ds) {
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.booleanConstantSql(this.__constant);
* @memberOf patio.sql
*/
var NegativeBooleanConstant = define(BooleanConstant, {
instance:{
instance: {
/**@lends patio.sql.NegativeBooleanConstant.prototype*/
/**
*
* @return String the SQL version of the {@link patio.sql.NegativeBooleanConstant}.
*/
toString:function (ds) {
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.negativeBooleanConstantSql(this.__constant);
* Constant for CURRENT DATE
* @type patio.sql.Constant
*/
CURRENT_DATE:new Constant("CURRENT_DATE"),
CURRENT_DATE: new Constant("CURRENT_DATE"),
/**
* Constant for CURRENT TIME
* @type patio.sql.Constant
*/
CURRENT_TIME:new Constant("CURRENT_TIME"),
CURRENT_TIME: new Constant("CURRENT_TIME"),
/**
* Constant for CURRENT TIMESTAMP
* @type patio.sql.Constant
*/
CURRENT_TIMESTAMP:new Constant("CURRENT_TIMESTAMP"),
CURRENT_TIMESTAMP: new Constant("CURRENT_TIMESTAMP"),
/**
* Constant for TRUE
* @type patio.sql.BooleanConstant
*/
SQLTRUE:new BooleanConstant(1),
SQLTRUE: new BooleanConstant(1),
/**
* Constant for TRUE
* @type patio.sql.BooleanConstant
*/
TRUE:new BooleanConstant(1),
TRUE: new BooleanConstant(1),
/**
* Constant for FALSE.
* @type patio.sql.BooleanConstant
*/
SQLFALSE:new BooleanConstant(0),
SQLFALSE: new BooleanConstant(0),
/**
* Constant for FALSE
* @type patio.sql.BooleanConstant
*/
FALSE:new BooleanConstant(0),
FALSE: new BooleanConstant(0),
/**
* Constant for NULL
* @type patio.sql.BooleanConstant
*/
NULL:new BooleanConstant(null),
NULL: new BooleanConstant(null),
/**
* Constant for NOT NULL
* @type patio.sql.NegativeBooleanConstant
*/
NOTNULL:new NegativeBooleanConstant(null)
NOTNULL: new NegativeBooleanConstant(null)
};
var Constants = sql.Constants
var Identifier = define([GenericExpression, QualifyingMethods], {
instance:{
instance: {
/**@lends patio.sql.Identifier.prototype*/
/**
*
* @property {String} value <b>READ ONLY</b> the column or table this identifier represents.
*/
constructor:function (value) {
this.__value = value;
constructor: function (value) {
this.__value = value;
},
/**
*
* @return String the SQL version of the {@link patio.sql.Identifier}.
*/
toString:function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.quoteIdentifier(this);
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.quoteIdentifier(this);
},
/**@ignore*/
getters:{
value:function () {
return this.__value;
getters: {
value: function () {
return this.__value;
}
}
}
}).as(sql, "Identifier");
var JoinClause = define(Expression, {
instance:{
instance: {
/**@lends patio.sql.JoinClause.prototype*/
/**
* @property table <b>READ ONLY</b> the table to join with
* @property joinType <b>READ ONLY</b> the alias to use for this join clause
* */
constructor:function (joinType, table, tableAlias) {
this.__joinType = joinType;
this.__table = table;
this.__tableAlias = tableAlias || null;
constructor: function (joinType, table, tableAlias) {
this.__joinType = joinType;
this.__table = table;
this.__tableAlias = tableAlias || null;
},
/**
*
* @return String the SQL version of the {@link patio.sql.JoinClause}.
*/
toString:function (ds) {
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.joinClauseSql(this);
},
/**@ignore*/
getters:{
joinType:function () {
return this.__joinType;
getters: {
joinType: function () {
return this.__joinType;
},
table:function () {
return this.__table;
table: function () {
return this.__table;
},
tableAlias:function () {
return this.__tableAlias;
tableAlias: function () {
return this.__tableAlias;
}
}
}
var JoinOnClause = define(JoinClause, {
instance:{
instance: {
/**@lends patio.sql.JoinOnClause.prototype*/
/**
* Represents an SQL JOIN clause with ON conditions. Created by {@link patio.Dataset} join methods.
* @param on the expression to filter with. See {@link patio.Dataset#filter}
* @property on <b>READ ONLY</b> the filter to use with joining the datasets.
*/
constructor:function (on, joinType, table, tableAlias) {
this.__on = on;
this._super(arguments, [joinType, table, tableAlias]);
constructor: function (on, joinType, table, tableAlias) {
this.__on = on;
this._super(arguments, [joinType, table, tableAlias]);
},
/**
*
* @return String the SQL version of the {@link patio.sql.JoinOnClause}.
*/
toString:function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.joinOnClauseSql(this);
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.joinOnClauseSql(this);
},
/**@ignore*/
getters:{
on:function () {
return this.__on;
getters: {
on: function () {
return this.__on;
}
}
}
var JoinUsingClause = define(JoinClause, {
instance:{
instance: {
/**@lends patio.sql.JoinUsingClause.prototype*/
/**
* @param using the column/s to use when joining.
* @property using <b>READ ONLY</b> the column/s to use when joining.
*/
constructor:function (using, joinType, table, tableAlias) {
constructor: function (using, joinType, table, tableAlias) {
this.__using = using.map(function (u) {
return isString(u) ? new Identifier(u) : u;
});
*
* @return String the SQL version of the {@link patio.sql.JoinUsingClause}.
*/
toString:function (ds) {
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.joinUsingClauseSql(this);
},
/**@ignore*/
getters:{
using:function () {
getters: {
using: function () {
return this.__using;
}
}
var PlaceHolderLiteralString = define(GenericExpression, {
instance:{
instance: {
/**@lends patio.sql.PlaceHolderLiteralString.prototype*/
/**
* replaced in the string.
* @property {String} parens <b>READ ONLY</b> set to true to wrap the string in parens.
*/
constructor:function (str, args, parens) {
parens = parens || false;
var v;
this.__str = str;
this.__args = isArray(args) && args.length == 1 && isHash((v = args[0])) ? v : args;
this.__parens = parens;
constructor: function (str, args, parens) {
parens = parens || false;
var v;
this.__str = str;
this.__args = isArray(args) && args.length == 1 && isHash((v = args[0])) ? v : args;
this.__parens = parens;
},
/**
*
* @return String the SQL version of the {@link patio.sql.PlaceHolderLiteralString}.
*/
toString:function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.placeholderLiteralStringSql(this);
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.placeholderLiteralStringSql(this);
},
/**@ignore*/
getters:{
str:function () {
return this.__str;
getters: {
str: function () {
return this.__str;
},
args:function () {
return this.__args;
args: function () {
return this.__args;
},
parens:function () {
return this.__parens;
parens: function () {
return this.__parens;
}
}
var SQLFunction = define(GenericExpression, {
instance:{
instance: {
/**@lends patio.sql.SQLFunction.prototype*/
/**
* @property {Array} args <b>READ ONLY</b> args arguments will be literalized through
* {@link patio.Dataset#literal} and placed into the SQL function call.
* */
constructor:function (f) {
var args = argsToArray(arguments).slice(1);
this.__f = isInstanceOf(f, Identifier) ? f.value : f, this.__args = args.map(function (a) {
return isString(a) ? sql.stringToIdentifier(a) : a;
constructor: function (f) {
var args = argsToArray(arguments).slice(1);
this.__f = isInstanceOf(f, Identifier) ? f.value : f, this.__args = args.map(function (a) {
return isString(a) ? sql.stringToIdentifier(a) : a;
});
},
*
* @return String the SQL version of the {@link patio.sql.SQLFunction}.
*/
toString:function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.functionSql(this);
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.functionSql(this);
},
/**@ignore*/
getters:{
f:function () {
return this.__f;
getters: {
f: function () {
return this.__f;
},
args:function () {
return this.__args;
args: function () {
return this.__args;
}
}
}
var OrderedExpression = define(Expression, {
instance:{
instance: {
/**@lends patio.sql.OrderedExpression.prototype*/
/**
* @property {String} [nulls=null] if value is "first" the null values will be first, if "last" then null values
* will be last
*/
constructor:function (expression, descending, opts) {
constructor: function (expression, descending, opts) {
descending = isBoolean(descending) ? descending : true;
opts = opts || {};
this.__expression = expression;
/**
* @return {patio.sql.OrderedExpression} a copy that is ordered ASC
*/
asc:function () {
return new OrderedExpression(this.__expression, false, {nulls:this.__nulls});
asc: function () {
return new OrderedExpression(this.__expression, false, {nulls: this.__nulls});
},
/**
* @return {patio.sql.OrderedExpression} Return a copy that is ordered DESC
*/
desc:function () {
return new OrderedExpression(this.__expression, true, {nulls:this.__nulls});
desc: function () {
return new OrderedExpression(this.__expression, true, {nulls: this.__nulls});
},
/**
* * @return {patio.sql.OrderedExpression} an inverted expression, changing ASC to DESC and NULLS FIRST to NULLS LAST.
* */
invert:function () {
return new OrderedExpression(this.__expression, !this.__descending, {nulls:this._static.INVERT_NULLS[this.__nulls] || this.__nulls});
invert: function () {
return new OrderedExpression(this.__expression, !this.__descending, {nulls: this._static.INVERT_NULLS[this.__nulls] || this.__nulls});
},
/**
*
* @return String the SQL version of the {@link patio.sql.OrderedExpression}.
*/
toString:function (ds) {
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.orderedExpressionSql(this);
},
/**@ignore*/
getters:{
expression:function () {
getters: {
expression: function () {
return this.__expression;
},
descending:function () {
descending: function () {
return this.__descending;
},
nulls:function () {
nulls: function () {
return this.__nulls;
}
}
},
static:{
static: {
/**@lends patio.sql.OrderedExpression*/
/**
* Hash that contains the inversions for "first" and "last".
* @type Object
* @default {first:"last", last:"first"}
*/
INVERT_NULLS:{first:"last", last:"first"}
INVERT_NULLS: {first: "last", last: "first"}
}
}).as(sql, "OrderedExpression");
var QualifiedIdentifier = define([GenericExpression, QualifyingMethods], {
instance:{
instance: {
/**@lends patio.sql.QualifiedIdentifier.prototype*/
/**
* @property table <b>READ ONLY</b> the table or schema to qualify the column or table to.
* @property column <b>READ ONLY</b> he column or table to qualify.
*/
constructor:function (table, column) {
this.__table = table;
this.__column = column;
constructor: function (table, column) {
this.__table = table;
this.__column = column;
},
/**
*
* @return String the SQL version of the {@link patio.sql.QualifiedIdentifier}.
*/
toString:function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.qualifiedIdentifierSql(this);
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.qualifiedIdentifierSql(this);
},
/**@ignore*/
getters:{
table:function () {
return this.__table;
getters: {
table: function () {
return this.__table;
},
column:function () {
return this.__column;
column: function () {
return this.__column;
}
}
}
var likeElement = function (re) {
var ret;
if (isRegExp(re)) {
ret = [("" + re).replace(/^\/|\/$|\/[i|m|g]*$/g, ""), true, re.ignoreCase]
var ret;
if (isRegExp(re)) {
ret = [("" + re).replace(/^\/|\/$|\/[i|m|g]*$/g, ""), true, re.ignoreCase]
} else {
ret = [re, false, false];
ret = [re, false, false];
}
return ret;
return ret;
};
/**
* @class Subclass of {@link patio.sql.ComplexExpression} where the expression results
* @memberOf patio.sql
*/
var StringExpression = define([ComplexExpression, StringMethods, StringConcatenationMethods, InequalityMethods, NoBooleanInputMethods], {
static:{
static: {
/**@lends patio.sql.StringExpression*/
/**
* StringExpression.like(sql.a, 'a%', {caseInsensitive : true}) //=> "a" ILIKE 'a%'
* StringExpression.like(sql.a, 'a%', /^a/i) //=> "a" LIKE 'a%' OR "a" ~* '^a'
*/
like:function (l) {
var args = argsToArray(arguments, 1);
var params = likeElement(l);
var likeMap = this.likeMap;
var lh = params[0], lre = params[1], lci = params[2];
var last = args[args.length - 1];
lci = (isHash(last) ? args.pop() : {})["caseInsensitive"] ? true : lci;
args = args.map(function (ce) {
var r, rre, rci;
var ceArr = likeElement(ce);
r = ceArr[0], rre = ceArr[1], rci = ceArr[2];
return new BooleanExpression(likeMap["" + (lre || rre) + (lci || rci)], l, r)
like: function (l) {
var args = argsToArray(arguments, 1);
var params = likeElement(l);
var likeMap = this.likeMap;
var lh = params[0], lre = params[1], lci = params[2];
var last = args[args.length - 1];
lci = (isHash(last) ? args.pop() : {})["caseInsensitive"] ? true : lci;
args = args.map(function (ce) {
var r, rre, rci;
var ceArr = likeElement(ce);
r = ceArr[0], rre = ceArr[1], rci = ceArr[2];
return new BooleanExpression(likeMap["" + (lre || rre) + (lci || rci)], l, r)
}, this);
return args.length == 1 ? args[0] : BooleanExpression.fromArgs(["OR"].concat(args));
return args.length == 1 ? args[0] : BooleanExpression.fromArgs(["OR"].concat(args));
},
/**
* LIKE expression.
* @type Object
*/
likeMap:{"truetrue":'~*', "truefalse":"~", "falsetrue":"ILIKE", "falsefalse":"LIKE"}
likeMap: {"truetrue": '~*', "truefalse": "~", "falsetrue": "ILIKE", "falsefalse": "LIKE"}
}
}).as(sql, "StringExpression");
var SubScript = define(GenericExpression, {
instance:{
instance: {
/**@lends patio.sql.SubScript.prototype*/
/**
* @param arrCol the SQL array column
* @param sub The array of subscripts to use (should be an array of numbers)
*/
constructor:function (arrCol, sub) {
constructor: function (arrCol, sub) {
//The SQL array column
this.__arrCol = arrCol;
//The array of subscripts to use (should be an array of numbers)
* Create a new {@link patio.sql.Subscript} appending the given subscript(s)
* the the current array of subscripts.
*/
addSub:function (sub) {
addSub: function (sub) {
return new SubScript(this.__arrCol, this.__sub.concat(sub));
},
*
* @return String the SQL version of the {@link patio.sql.SubScript}.
*/
toString:function (ds) {
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.subscriptSql(this);
},
/**@ignore*/
getters:{
f:function () {
getters: {
f: function () {
return this.__arrCol;
},
sub:function () {
sub: function () {
return this.__sub;
}
}
var addStringMethod = function (op) {
return function () {
return this.__str[op].apply(this.__str, arguments);
return this.__str[op].apply(this.__str, arguments);
}
};
var LiteralString = define([OrderedMethods, ComplexExpressionMethods, BooleanMethods, NumericMethods, StringMethods, InequalityMethods, AliasMethods], {
instance:{
instance: {
/**@lends patio.sql.LiteralString*/
/**
*
* @param {String} str the literal string.
*/
constructor:function (str) {
this.__str = str;
constructor: function (str) {
this.__str = str;
}
}
}).as(sql, "LiteralString");
if (!isFunction(this.schemaParseTable)) {
throw new Error("Schema parsing is not implemented on this database");
}
var ret = new Promise();
opts = opts || {};
var schemaParts = this.__schemaAndTable(table);
var sch = schemaParts[0], tableName = schemaParts[1];
if (opts.reload) {
delete this.schemas[quotedName];
}
if (this.schemas[quotedName]) {
ret = this.schemas[quotedName];
} else {
var self = this;
ret = this.schemas[quotedName] = this.schemaParseTable(tableName, opts).chain(function (cols) {
if (!cols || cols.length === 0) {
throw new Error("Error parsing schema, " + table + " no columns returns, table probably doesnt exist")
} else {
var schema = {};
cols.forEach(function (c) {
var name = c[0];
c = c[1];
c.jsDefault = self.__columnSchemaToJsDefault(c["default"], c.type);
schema[name] = c;
});
return schema;
}
});
}
return ret.promise();
var self = this;
return this.schemaParseTable(tableName, opts).chain(function (cols) {
if (!cols || cols.length === 0) {
throw new Error("Error parsing schema, " + table + " no columns returns, table probably doesnt exist")
} else {
var schema = {};
cols.forEach(function (c) {
var name = c[0];
c = c[1];
c.jsDefault = self.__columnSchemaToJsDefault(c["default"], c.type);
schema[name] = c;
});
return schema;
}
});
},
/**
*/
removeCachedSchema: function (table) {
if (this.schemas && !isEmpty(this.schemas)) {
delete this.schemas[this.__quoteSchemaTable(table)];
delete this.schemas[this.__quoteSchemaTable(table)];
}
},
},
_getConnection: function () {
return this.pool.getConnection();
return this.pool.getConnection();
},
_returnConnection: function (conn) {
if (!this.alreadyInTransaction(conn)) {
this.pool.returnConnection(conn);
if (!this.alreadyInTransaction(conn)) {
this.pool.returnConnection(conn);
}
},
//Convert the given default, which should be a database specific string, into
//a javascript object.
__columnSchemaToJsDefault: function (def, type) {
if (isNull(def) || isUndefined(def)) {
return null;
if (isNull(def) || isUndefined(def)) {
return null;
}
var origDefault = def, m, datePattern, dateTimePattern, timeStampPattern, timePattern;
if (this.type === "postgres" && (m = def.match(this.POSTGRES_DEFAULT_RE)) !== null) {
var origDefault = def, m, datePattern, dateTimePattern, timeStampPattern, timePattern;
if (this.type === "postgres" && (m = def.match(this.POSTGRES_DEFAULT_RE)) !== null) {
def = m[1] || m[2];
dateTimePattern = this.POSTGRES_DATE_TIME_PATTERN;
timePattern = this.POSTGRES_TIME_PATTERN;
}
if (this.type === "mssql" && (m = def.match(this.MSSQL_DEFAULT_RE)) !== null) {
if (this.type === "mssql" && (m = def.match(this.MSSQL_DEFAULT_RE)) !== null) {
def = m[1] || m[2];
}
if (["string", "blob", "date", "datetime", "year", "timestamp", "time", "enum"].indexOf(type) !== -1) {
if (["string", "blob", "date", "datetime", "year", "timestamp", "time", "enum"].indexOf(type) !== -1) {
if (this.type === "mysql") {
if (["date", "datetime", "time", "timestamp"].indexOf(type) !== -1 && def.match(this.MYSQL_TIMESTAMP_RE)) {
return null;
}
def = m[1].replace("''", "'");
}
var ret = null;
try {
switch (type) {
var ret = null;
try {
switch (type) {
case "boolean":
if (def.match(/[f0]/i)) {
ret = false;
ret = def;
break;
case "integer":
ret = parseInt(def, 10);
if (isNaN(ret)) {
ret = null;
ret = parseInt(def, 10);
if (isNaN(ret)) {
ret = null;
}
break;
break;
case "float":
case "decimal":
ret = parseFloat(def, 10);
}
} catch (e) {
}
return ret;
return ret;
},
/**
* @private
*/
schemaColumnType: function (dbType) {
var ret = dbType, m;
if (dbType.match(/^interval$/i)) {
var ret = dbType, m;
if (dbType.match(/^interval$/i)) {
ret = "interval";
} else if (dbType.match(/^(character( varying)?|n?(var)?char)/i)) {
ret = "string";
} else if (dbType.match(/^int(eger)?|(big|small|tiny)int/i)) {
ret = "integer";
} else if (dbType.match(/^date$/i)) {
ret = "date";
} else if (dbType.match(/^year/i)) {
} else if (dbType.match(/^(character( varying)?|n?(var)?char)/i)) {
ret = "string";
} else if (dbType.match(/^int(eger)?|(big|small|tiny)int/i)) {
ret = "integer";
} else if (dbType.match(/^date$/i)) {
ret = "date";
} else if (dbType.match(/^year/i)) {
ret = "year";
} else if (dbType.match(/^((small)?datetime|timestamp( with(out)? time zone)?)$/i)) {
} else if (dbType.match(/^((small)?datetime|timestamp( with(out)? time zone)?)$/i)) {
ret = "datetime";
} else if (dbType.match(/^time( with(out)? timezone)?$/i)) {
} else if (dbType.match(/^time( with(out)? timezone)?$/i)) {
ret = "time";
} else if (dbType.match(/^(bit|boolean)$/i)) {
} else if (dbType.match(/^(bit|boolean)$/i)) {
ret = "boolean";
} else if (dbType.match(/^(real|float|double( precision)?)$/i)) {
} else if (dbType.match(/^(real|float|double( precision)?)$/i)) {
ret = "float";
} else if ((m = dbType.match(/^(?:(?:(?:num(?:ber|eric)?|decimal|double)(?:\(\d+,\s*(\d+)\))?)|(?:small)?money)/i))) {
ret = m[1] && m[1] === '0' ? "integer" : "decimal";
} else if (dbType.match(/n?text/i)) {
ret = "text";
} else if (dbType.match(/bytea|[bc]lob|image|(var)?binary/i)) {
ret = "blob";
} else if (dbType.match(/^enum/i)) {
ret = "enum";
} else if ((m = dbType.match(/^(?:(?:(?:num(?:ber|eric)?|decimal|double)(?:\(\d+,\s*(\d+)\))?)|(?:small)?money)/i))) {
ret = m[1] && m[1] === '0' ? "integer" : "decimal";
} else if (dbType.match(/n?text/i)) {
ret = "text";
} else if (dbType.match(/bytea|[bc]lob|image|(var)?binary/i)) {
ret = "blob";
} else if (dbType.match(/^enum/i)) {
ret = "enum";
} else if (dbType.match(/^set/i)) {
ret = "set";
}
return ret;
return ret;
},
/**
* @return {Boolean} true if this dabase is currently in a transaction.
*/
alreadyInTransaction: function (conn, opts) {
opts = opts || {};
return this.__transactions.indexOf(conn) !== -1 && (!this.supportsSavepoints || !opts.savepoint);
opts = opts || {};
return this.__transactions.indexOf(conn) !== -1 && (!this.supportsSavepoints || !opts.savepoint);
},
/**@ignore*/
* @type Function
*/
outputIdentifierFunc: function () {
var ds = this.dataset;
return function (ident) {
return ds.outputIdentifier(ident);
var ds = this.dataset;
return function (ident) {
return ds.outputIdentifier(ident);
};
},
* @type Function
*/
inputIdentifierFunc: function () {
var ds = this.dataset;
return function (ident) {
return ds.inputIdentifier(ident);
var ds = this.dataset;
return function (ident) {
return ds.inputIdentifier(ident);
};
},
* @type patio.Dataset
*/
metadataDataset: function () {
if (this.__metadataDataset) {
return this.__metadataDataset;
if (this.__metadataDataset) {
return this.__metadataDataset;
}
var ds = this.dataset;
ds.identifierInputMethod = this.identifierInputMethod;
constructor:function () {
//We initialize these here because otherwise
//the will be blank because of recursive dependencies.
!patio && (patio = require("../index"));
!Dataset && (Dataset = patio.Dataset);
this._super(arguments);
!patio && (patio = require("../index"));
!Dataset && (Dataset = patio.Dataset);
this._super(arguments);
},
/**
*
*/
qualifiedColumnName:function (column, table) {
if (isString(column)) {
var parts = this._splitString(column);
var columnTable = parts[0], alias = parts[2], tableAlias;
column = parts[1];
if (!columnTable) {
if (isInstanceOf(table, Identifier)) {
table = table.value;
if (isString(column)) {
var parts = this._splitString(column);
var columnTable = parts[0], alias = parts[2], tableAlias;
column = parts[1];
if (!columnTable) {
if (isInstanceOf(table, Identifier)) {
table = table.value;
}
if (isInstanceOf(table, AliasedExpression)) {
if (isInstanceOf(table, AliasedExpression)) {
tableAlias = table.alias;
} else if (isInstanceOf(table, QualifiedIdentifier)) {
} else if (isInstanceOf(table, QualifiedIdentifier)) {
tableAlias = table;
} else {
parts = this._splitString(table);
var schema = parts[0], tableAlias = parts[2];
table = parts[1];
if (schema) {
parts = this._splitString(table);
var schema = parts[0], tableAlias = parts[2];
table = parts[1];
if (schema) {
tableAlias = new Identifier(tableAlias) || new QualifiedIdentifier(schema, table);
}
}
columnTable = tableAlias || table;
columnTable = tableAlias || table;
}
return new QualifiedIdentifier(columnTable, column);
return new QualifiedIdentifier(columnTable, column);
} else if (isInstanceOf(column, Identifier)) {
return column.qualify(table);
} else {
* @return {String} a literal representation of the value.
*/
literal:function (v) {
if (isInstanceOf(v, LiteralString)) {
if (isInstanceOf(v, LiteralString)) {
return "" + v;
} else if (isString(v)) {
return this._literalString(v);
} else if (isNumber(v)) {
return this._literalNumber(v);
} else if (isString(v)) {
return this._literalString(v);
} else if (isNumber(v)) {
return this._literalNumber(v);
}
else if (isInstanceOf(v, Expression)) {
return this._literalExpression(v);
else if (isInstanceOf(v, Expression)) {
return this._literalExpression(v);
}
else if (isInstanceOf(v, Dataset)) {
else if (isInstanceOf(v, Dataset)) {
return this._literalDataset(v);
}
else if (isArray(v)) {
return this._literalArray(v);
} else if (isInstanceOf(v, sql.Year)) {
else if (isArray(v)) {
return this._literalArray(v);
} else if (isInstanceOf(v, sql.Year)) {
return this._literalYear(v);
} else if (isInstanceOf(v, sql.TimeStamp, sql.DateTime)) {
} else if (isInstanceOf(v, sql.TimeStamp, sql.DateTime)) {
return this._literalTimestamp(v);
} else if (isDate(v)) {
} else if (isDate(v)) {
return this._literalDate(v);
} else if (isInstanceOf(v, sql.Time)) {
} else if (isInstanceOf(v, sql.Time)) {
return this._literalTime(v);
} else if (Buffer.isBuffer(v)) {
} else if (Buffer.isBuffer(v)) {
return this._literalBuffer(v);
} else if (isNull(v)) {
} else if (isNull(v)) {
return this._literalNull();
}
else if (isBoolean(v)) {
return this._literalBoolean(v);
else if (isBoolean(v)) {
return this._literalBoolean(v);
}
else if (isHash(v)) {
return this._literalObject(v);
//Prepares an SQL statement by calling all clause methods for the given statement type.
_clauseSql:function (type) {
var sql = [("" + type).toUpperCase()];
try {
this._static[sql + "_CLAUSE_METHODS"].forEach(function (m) {
if (m.match("With")) {
this[m](sql);
var sql = [("" + type).toUpperCase()];
try {
this._static[sql + "_CLAUSE_METHODS"].forEach(function (m) {
if (m.match("With")) {
this[m](sql);
} else {
var sqlRet = this[m]();
if (sqlRet) {
sql.push(sqlRet);
var sqlRet = this[m]();
if (sqlRet) {
sql.push(sqlRet);
}
}
}, this);
} catch (e) {
throw e;
}
return sql.join("");
return sql.join("");
},
//SQL fragment for Array
_arraySql:function (a) {
return !a.length ? '(NULL)' : "(" + this.__expressionList(a) + ")";
return !a.length ? '(NULL)' : "(" + this.__expressionList(a) + ")";
},
//This method quotes the given name with the SQL standard double quote.
* SQL fragment for AliasedExpression
*/
aliasedExpressionSql:function (ae) {
return this.__asSql(this.literal(ae.expression), ae.alias);
return this.__asSql(this.literal(ae.expression), ae.alias);
},
/**
* SQL fragment for complex expressions
**/
complexExpressionSql:function (op, args) {
var newOp;
var isOperators = this._static.IS_OPERATORS, isLiterals = this._static.IS_LITERALS;
if ((newOp = isOperators[op]) != null) {
var r = args[1], v = isNull(r) ? isLiterals.NULL : isLiterals[r];
if (r == null || this.supportsIsTrue) {
if (isUndefined(v)) {
var newOp;
var isOperators = this._static.IS_OPERATORS, isLiterals = this._static.IS_LITERALS;
if ((newOp = isOperators[op]) != null) {
var r = args[1], v = isNull(r) ? isLiterals.NULL : isLiterals[r];
if (r == null || this.supportsIsTrue) {
if (isUndefined(v)) {
throw new QueryError(string.format("Invalid argument('%s') used for IS operator", r));
}
l = args[0];
return string.format("(%s %s %s)", isString(l) ? l : this.literal(l), newOp, v);
l = args[0];
return string.format("(%s %s %s)", isString(l) ? l : this.literal(l), newOp, v);
} else if (op == "IS") {
return this.complexExpressionSql("EQ", args);
} else {
null)]);
}
} else if (["IN", "NOTIN"].indexOf(op) != -1) {
} else if (["IN", "NOTIN"].indexOf(op) != -1) {
var cols = args[0], vals = args[1], colArray = isArray(cols), valArray = false, emptyValArray = false;
if (isArray(vals)) {
ComplexExpression.IN_OPERATORS[op], this.literal(vals));
}
}
} else if ((newOp = this._static.TWO_ARITY_OPERATORS[op]) != null) {
var l = args[0];
return format("(%s %s %s)", isString(l) ? l : this.literal(l), newOp,
} else if ((newOp = this._static.TWO_ARITY_OPERATORS[op]) != null) {
var l = args[0];
return format("(%s %s %s)", isString(l) ? l : this.literal(l), newOp,
this.literal(args[1]));
} else if ((newOp = this._static.N_ARITY_OPERATORS[op]) != null) {
return string.format("(%s)", args.map(this.literal, this).join(" " + newOp + " "));
} else if ((newOp = this._static.N_ARITY_OPERATORS[op]) != null) {
return string.format("(%s)", args.map(this.literal, this).join(" " + newOp + " "));
} else if (op == "NOT") {
return string.format("NOT %s", this.literal(args[0]));
} else if (op == "NOOP") {
* SQL fragment specifying an SQL function call
* */
functionSql:function (f) {
var args = f.args
return string.format("%s%s", f.f, args.length == 0 ? '()' : this.literal(args));
var args = f.args
return string.format("%s%s", f.f, args.length == 0 ? '()' : this.literal(args));
},
/**
* SQL fragment specifying a JOIN clause without ON or USING.
* */
joinClauseSql:function (jc) {
var table = jc.table
var tableAlias = jc.tableAlias
if (table === tableAlias) {
var table = jc.table
var tableAlias = jc.tableAlias
if (table === tableAlias) {
tableAlias = null;
}
var tref = this.__tableRef(table);
return string.format(" %s %s", this._joinTypeSql(jc.joinType),
var tref = this.__tableRef(table);
return string.format(" %s %s", this._joinTypeSql(jc.joinType),
tableAlias ? this.__asSql(tref, tableAlias) : tref);
},
* SQL fragment specifying a JOIN clause with ON.
**/
joinOnClauseSql:function (jc) {
return string.format("%s ON %s", this.joinClauseSql(jc), this.literal(this._filterExpr(jc.on)));
return string.format("%s ON %s", this.joinClauseSql(jc), this.literal(this._filterExpr(jc.on)));
},
/**
* SQL fragment for a literal string with placeholders
* */
placeholderLiteralStringSql:function (pls) {
var args = pls.args;
var s;
if (isHash(args)) {
var args = pls.args;
var s;
if (isHash(args)) {
for (var i in args) {
args[i] = this.literal(args[i]);
}
s = string.format(pls.str, args);
} else {
s = pls.str.replace(this._static.QUESTION_MARK, "%s");
args = toArray(args).map(this.literal, this);
s = string.format(s, args);
s = pls.str.replace(this._static.QUESTION_MARK, "%s");
args = toArray(args).map(this.literal, this);
s = string.format(s, args);
}
if (pls.parens) {
if (pls.parens) {
s = string.format("(%s)", s);
}
return s;
return s;
},
* a table and a column (or schema and table).
*/
qualifiedIdentifierSql:function (qcr) {
return [qcr.table, qcr.column].map(
return [qcr.table, qcr.column].map(
function (x) {
return [QualifiedIdentifier, Identifier, String].some(function (c) {
return x instanceof c
return [QualifiedIdentifier, Identifier, String].some(function (c) {
return x instanceof c
}) ? this.literal(x) : this.quoteIdentifier(x)
}, this).join('.');
},
* quote the name with {@link patio.dataset._Sql#_quotedIdentifier}.
*/
quoteIdentifier:function (name) {
if (isInstanceOf(name, LiteralString)) {
return name;
if (isInstanceOf(name, LiteralString)) {
return name;
} else {
if (isInstanceOf(name, Identifier)) {
name = name.value;
if (isInstanceOf(name, Identifier)) {
name = name.value;
}
name = this.inputIdentifier(name);
if (this.quoteIdentifiers) {
name = this._quotedIdentifier(name)
name = this.inputIdentifier(name);
if (this.quoteIdentifiers) {
name = this._quotedIdentifier(name)
}
}
return name;
return name;
},
/**
* identifierOutputMethod.
*/
inputIdentifier:function (v) {
var i = this.__identifierInputMethod;
v = v.toString(this);
return !isUndefinedOrNull(i) ?
var i = this.__identifierInputMethod;
v = v.toString(this);
return !isUndefinedOrNull(i) ?
isFunction(v[i]) ?
v[i]() :
isFunction(comb[i]) ?
* identifierOutputMethod.
*/
outputIdentifier:function (v) {
(v == '' && (v = 'untitled'));
var i = this.__identifierOutputMethod;
return !isUndefinedOrNull(i) ?
(v == '' && (v = 'untitled'));
var i = this.__identifierOutputMethod;
return !isUndefinedOrNull(i) ?
isFunction(v[i]) ?
v[i]() :
isFunction(comb[i]) ?
* quoted (if quoting identifiers)
*/
quoteSchemaTable:function (table) {
var parts = this.schemaAndTable(table);
var schema = parts[0];
table = parts[1];
return string.format("%s%s", schema ? this.quoteIdentifier(schema) + "." : "", this.quoteIdentifier(table));
var parts = this.schemaAndTable(table);
var schema = parts[0];
table = parts[1];
return string.format("%s%s", schema ? this.quoteIdentifier(schema) + "." : "", this.quoteIdentifier(table));
},
* Split the schema information from the table
*/
schemaAndTable:function (tableName) {
var sch = this.db ? this.db.defaultSchema || null : null;
if (isString(tableName)) {
var parts = this._splitString(tableName);
var s = parts[0], table = parts[1];
return [s || sch, table];
} else if (isInstanceOf(tableName, QualifiedIdentifier)) {
var sch = this.db ? this.db.defaultSchema || null : null;
if (isString(tableName)) {
var parts = this._splitString(tableName);
var s = parts[0], table = parts[1];
return [s || sch, table];
} else if (isInstanceOf(tableName, QualifiedIdentifier)) {
return [tableName.table, tableName.column]
} else if (isInstanceOf(tableName, Identifier)) {
return [null, tableName.value];
} else if (isInstanceOf(tableName, Identifier)) {
return [null, tableName.value];
} else {
throw new QueryError("table should be a QualifiedIdentifier, Identifier, or String");
}
* SQL fragment for specifying an alias. expression should already be literalized.
*/
__asSql:function (expression, alias) {
return string.format("%s AS %s", expression, this.quoteIdentifier(alias));
return string.format("%s AS %s", expression, this.quoteIdentifier(alias));
},
/**
* column names. If the array is empty, a wildcard (*) is returned.
*/
__columnList:function (columns) {
return (!columns || columns.length == 0) ? this._static.WILDCARD : this.__expressionList(columns);
return (!columns || columns.length == 0) ? this._static.WILDCARD : this.__expressionList(columns);
},
/**
* expressions.
*/
__expressionList:function (columns) {
return columns.map(this.literal, this).join(this._static.COMMA_SEPARATOR);
return columns.map(this.literal, this).join(this._static.COMMA_SEPARATOR);
},
//Format the timestamp based on the default_timestamp_format, with a couple
* and converts to uppercase/
*/
_joinTypeSql:function (joinType) {
return (joinType || "").replace(/([a-z]+)|([A-Z][a-z]+)/g,
return (joinType || "").replace(/([a-z]+)|([A-Z][a-z]+)/g,
function (m) {
return m.toUpperCase() + " ";
return m.toUpperCase() + " ";
}
).trimRight() + " JOIN";
},
* @return SQL fragment for Array. Treats as an expression if an array of all two pairs, or as a SQL array otherwise.
*/
_literalArray:function (v) {
return Expression.isConditionSpecifier(v) ? this._literalExpression(BooleanExpression.fromValuePairs(v)) : this._arraySql(v);
return Expression.isConditionSpecifier(v) ? this._literalExpression(BooleanExpression.fromValuePairs(v)) : this._arraySql(v);
},
/**
* @return SQL fragment for a number.
*/
_literalNumber:function (num) {
var ret = "" + num;
if (isNaN(num) || num == Infinity) {
var ret = "" + num;
if (isNaN(num) || num == Infinity) {
ret = string.format("'%s'", ret);
}
return ret;
return ret;
},
/**
* @return SQL fragment for a boolean.
*/
_literalBoolean:function (b) {
return b ? this._static.BOOL_TRUE : this._static.BOOL_FALSE;
return b ? this._static.BOOL_TRUE : this._static.BOOL_FALSE;
},
/**
* @return SQL fragment for SQL::Expression, result depends on the specific type of expression.
* */
_literalExpression:function (v) {
return v.toString(this);
return v.toString(this);
},
/**
* @return SQL fragment for String. Doubles \ and ' by default.
* */
_literalString:function (v) {
var parts = this._splitString(v);
var table = parts[0], column = parts[1], alias = parts[2];
if (!alias) {
return column && table ? this._literalExpression(QualifiedIdentifier.fromArgs([table, column])) : "'"
var parts = this._splitString(v);
var table = parts[0], column = parts[1], alias = parts[2];
if (!alias) {
return column && table ? this._literalExpression(QualifiedIdentifier.fromArgs([table, column])) : "'"
+ v.replace(/\\/g, "\\\\").replace(/'/g, "''") + "'"
} else {
return this.literal(new AliasedExpression(column
/*SQL STATEMENT CREATION METHODS*/
_selectQualifySql:function () {
var o = this.__opts;
var table = this.__opts.alwaysQualify;
if (table && !o.sql) {
var o = this.__opts;
var table = this.__opts.alwaysQualify;
if (table && !o.sql) {
array.intersect(Object.keys(o), this._static.QUALIFY_KEYS).forEach(function (k) {
o[k] = this._qualifiedExpression(o[k], table);
}, this);
* @return the columns selected
* */
_selectColumnsSql:function () {
return " " + this.__columnList(this.__opts.select);
return " " + this.__columnList(this.__opts.select);
},
/**@return the DISTINCT clause.*/
_selectDistinctSql:function () {
var distinct = this.__opts.distinct, ret = [];
if (distinct) {
var distinct = this.__opts.distinct, ret = [];
if (distinct) {
ret.push(" DISTINCT");
if (distinct.length) {
ret.push(format(" ON (%s)", this.__expressionList(distinct)));
}
}
return ret.join("");
return ret.join("");
},
/**
* work on all databases.
**/
_selectCompoundsSql:function () {
var opts = this.__opts, compounds = opts.compounds, ret = [];
if (compounds) {
var opts = this.__opts, compounds = opts.compounds, ret = [];
if (compounds) {
compounds.forEach(function (c) {
var type = c[0], dataset = c[1], all = c[2];
ret.push(string.format(" %s%s %s", type.toUpperCase(), all ? " ALL" : "", this._subselectSql(dataset)));
}, this);
}
return ret.join("");
return ret.join("");
},
/**
* @return the sql to add the list of tables to select FROM
**/
_selectFromSql:function () {
var from = this.__opts.from;
return from ? string.format(" %s%s", this._static.FROM, this._sourceList(from)) : "";
var from = this.__opts.from;
return from ? string.format(" %s%s", this._static.FROM, this._sourceList(from)) : "";
},
/**
* @return the GROUP BY clause
**/
_selectGroupSql:function () {
var group = this.__opts.group;
return group ? string.format(" GROUP BY %s", this.__expressionList(group)) : "";
var group = this.__opts.group;
return group ? string.format(" GROUP BY %s", this.__expressionList(group)) : "";
},
*@return the sql to add the filter criteria in the HAVING clause
**/
_selectHavingSql:function () {
var having = this.__opts.having;
return having ? string.format(" HAVING %s", this.literal(having)) : "";
var having = this.__opts.having;
return having ? string.format(" HAVING %s", this.literal(having)) : "";
},
/**
* @return the JOIN clause.
**/
_selectJoinSql:function () {
var join = this.__opts.join, ret = [];
if (join) {
join.forEach(function (j) {
ret.push(this.literal(j));
var join = this.__opts.join, ret = [];
if (join) {
join.forEach(function (j) {
ret.push(this.literal(j));
}, this);
}
return ret.join("");
return ret.join("");
},
/**
* @return the LIMIT and OFFSET clauses.
* */
_selectLimitSql:function () {
var ret = [], limit = this.__opts.limit, offset = this.__opts.offset;
!isUndefined(limit) && !isNull(limit) && (ret.push(format(" LIMIT %s", this.literal(limit))));
!isUndefined(offset) && !isNull(offset) && (ret.push(format(" OFFSET %s", this.literal(offset))));
return ret.join("");
var ret = [], limit = this.__opts.limit, offset = this.__opts.offset;
!isUndefined(limit) && !isNull(limit) && (ret.push(format(" LIMIT %s", this.literal(limit))));
!isUndefined(offset) && !isNull(offset) && (ret.push(format(" OFFSET %s", this.literal(offset))));
return ret.join("");
},
/**
* @return SQL for different locking modes.
**/
_selectLockSql:function () {
var lock = this.__opts.lock, ret = [];
if (lock) {
var lock = this.__opts.lock, ret = [];
if (lock) {
if (lock == "update") {
ret.push(this._static.FOR_UPDATE);
} else {
ret.push(" ", lock);
}
}
return ret.join("");
return ret.join("");
},
/**
* @return the SQL ORDER BY clause fragment.
*/
_selectOrderSql:function () {
var order = this.__opts.order;
return order ? string.format(" ORDER BY %s", this.__expressionList(order)) : "";
var order = this.__opts.order;
return order ? string.format(" ORDER BY %s", this.__expressionList(order)) : "";
},
/**
* @return the SQL WHERE clause fragment.
*/
_selectWhereSql:function () {
var where = this.__opts.where;
return where ? string.format(" WHERE %s", this.literal(where)) : "";
var where = this.__opts.where;
return where ? string.format(" WHERE %s", this.literal(where)) : "";
},
/**
* @param sql
*/
_selectWithSql:function (sql) {
var wit = this.__opts["with"];
if (wit && wit.length) {
var wit = this.__opts["with"];
if (wit && wit.length) {
//sql.length = 0;
var base = sql.join("");
sql.length = 0;
* Converts an array of source names into into a comma separated list.
**/
_sourceList:function (source) {
if (!Array.isArray(source)) {
if (!Array.isArray(source)) {
source = [source];
}
if (!source || !source.length) {
if (!source || !source.length) {
throw new QueryError("No source specified for the query");
}
return " " + source.map(
return " " + source.map(
function (s) {
return this.__tableRef(s);
return this.__tableRef(s);
}, this).join(this._static.COMMA_SEPARATOR);
},
* we literalize nonstrings.
**/
_staticSql:function (sql) {
return isString(sql) ? sql : this.literal(sql);
return isString(sql) ? sql : this.literal(sql);
},
* @returns SQL fragment specifying a table name.
**/
__tableRef:function (t) {
return isString(t) ? this._quotedIdentifier(t) : this.literal(t);
return isString(t) ? this._quotedIdentifier(t) : this.literal(t);
},
getters:{
//Same as selectS, not aliased directly to make subclassing simpler.
sql:function () {
return this.selectSql;
return this.selectSql;
},
selectSql:function () {
if (this.__opts.sql) return this._staticSql(this.__opts.sql);
else return this._clauseSql("select");
if (this.__opts.sql) return this._staticSql(this.__opts.sql);
else return this._clauseSql("select");
},
deleteSql:function () {
* @type String
*/
identifierInputMethod:function () {
return this.__identifierInputMethod;
return this.__identifierInputMethod;
},
/**
* @type String
*/
identifierOutputMethod:function () {
return this.__identifierOutputMethod;
return this.__identifierOutputMethod;
},
/**
* @default true
*/
quoteIdentifiers:function () {
return this.__quoteIdentifiers;
return this.__quoteIdentifiers;
}
},
/**@ignore*/
constructor: function () {
if (!Dataset) {
if (!Dataset) {
Dataset = require("../index").Dataset;
}
this._super(arguments);
this._super(arguments);
},
* @return {comb.Promise} a promise that is resolved when the action has completed.
*/
forEach: function (block, cb) {
var rowCb, ret;
if (this.__opts.graph) {
var rowCb, ret;
if (this.__opts.graph) {
ret = this.graphEach(block);
} else {
ret = this.fetchRows(this.selectSql);
if ((rowCb = this.rowCb)) {
ret = this.fetchRows(this.selectSql);
if ((rowCb = this.rowCb)) {
ret = ret.map(function (r) {
return rowCb(r);
});
}
if (block) {
if (block) {
ret = ret.forEach(block);
}
}
return ret.classic(cb);
return ret.classic(cb);
},
/**
* @return {comb.Promise} a promise resolved with the array of mapped values.
*/
map: function (column, cb) {
var ret = this.forEach();
column && (ret = ret[isFunction(column) ? "map" : "pluck"](column))
return ret.classic(cb).promise();
var ret = this.forEach();
column && (ret = ret[isFunction(column) ? "map" : "pluck"](column))
return ret.classic(cb).promise();
},
/**
* readOnly server unless a specific server is set.
*/
execute: function (sql, opts) {
return this.db.execute(sql, merge({server: this.__opts.server || "readOnly"}, opts || {}));
return this.db.execute(sql, merge({server: this.__opts.server || "readOnly"}, opts || {}));
},
/**
*
*/
constructor: function () {
if (comb.isUndefinedOrNull(this.__associations)) {
this.__associations = {};
if (comb.isUndefinedOrNull(this.__associations)) {
this.__associations = {};
}
this._super(arguments);
this._super(arguments);
},
reload: function () {
var ret = null;
try {
if (!action.action(value)) {
ret = format(actionOpts.message, errOpts);
ret = format(actionOpts.message, errOpts);
}
} catch (e) {
ret = format(actionOpts.message, errOpts);
ret = format(actionOpts.message, errOpts);
}
return ret;
}
var Dataset;
function conditionedJoin(type) {
var args = argsToArray(arguments, 1);
return this.joinTable.apply(this, [type].concat(args));
var args = argsToArray(arguments, 1);
return this.joinTable.apply(this, [type].concat(args));
}
function unConditionJoin(type, table) {
* @ignore
*/
constructor: function () {
!Dataset && (Dataset = require("../index").Dataset);
this._super(arguments);
this._static.CONDITIONED_JOIN_TYPES.forEach(function (type) {
if (!this[type + "Join"]) {
this[type + "Join"] = hitch(this, conditionedJoin, type);
!Dataset && (Dataset = require("../index").Dataset);
this._super(arguments);
this._static.CONDITIONED_JOIN_TYPES.forEach(function (type) {
if (!this[type + "Join"]) {
this[type + "Join"] = hitch(this, conditionedJoin, type);
}
}, this);
this._static.UNCONDITIONED_JOIN_TYPES.forEach(function (type) {
if (!this[type + "Join"]) {
this[type + "Join"] = hitch(this, unConditionJoin, type);
this._static.UNCONDITIONED_JOIN_TYPES.forEach(function (type) {
if (!this[type + "Join"]) {
this[type + "Join"] = hitch(this, unConditionJoin, type);
}
}, this);
var clause = (tOpts.having ? "having" : "where"), clauseObj = tOpts[clause];
if (clauseObj) {
var args = argsToArray(arguments);
args = args.length == 1 ? args[0] : args;
args = args.length === 1 ? args[0] : args;
var opts = {};
opts[clause] = new BooleanExpression("OR", clauseObj, this._filterExpr(args));
return this.mergeOptions(opts);
* @return {patio.Dataset} a cloned dataset with the condition 'or group' added to the WHERE/HAVING clause.
*/
andGroupedOr: function (filterExp) {
return this._addGroupedCondition("AND", "OR", filterExp);
return this._addGroupedCondition("AND", "OR", filterExp);
},
/**
return this.or.apply(this, arguments);
} else {
var args = argsToArray(arguments);
args = args.length == 1 ? args[0] : args;
args = args.length === 1 ? args[0] : args;
var opts = {};
opts[clause] = this._filterExpr(args, null, "AND");
return this.mergeOptions(opts);
* @return {patio.Dataset} a cloned dataset with the excluded conditions applied to the HAVING/WHERE clause.
*/
exclude: function () {
var cond = argsToArray(arguments), tOpts = this.__opts;
var clause = (tOpts["having"] ? "having" : "where"), clauseObj = tOpts[clause];
cond = cond.length > 1 ? cond : cond[0];
cond = this._filterExpr.call(this, cond);
cond = BooleanExpression.invert(cond);
if (clauseObj) {
cond = new BooleanExpression("AND", clauseObj, cond)
var cond = argsToArray(arguments), tOpts = this.__opts;
var clause = (tOpts["having"] ? "having" : "where"), clauseObj = tOpts[clause];
cond = cond.length > 1 ? cond : cond[0];
cond = this._filterExpr.call(this, cond);
cond = BooleanExpression.invert(cond);
if (clauseObj) {
cond = new BooleanExpression("AND", clauseObj, cond);
}
var opts = {};
opts[clause] = cond;
return this.mergeOptions(opts);
var opts = {};
opts[clause] = cond;
return this.mergeOptions(opts);
},
/**
* @return {patio.Dataset} a cloned dataset with the filter arumgents applied to the WHERE/HAVING clause.
**/
filter: function (args, cb) {
args = [this.__opts["having"] ? "having" : "where"].concat(argsToArray(arguments));
return this._filter.apply(this, args);
args = [this.__opts["having"] ? "having" : "where"].concat(argsToArray(arguments));
return this._filter.apply(this, args);
},
/**
* @return {patio.Dataset} a cloned dataset with the FROM clause overridden.
*/
from: function (source) {
source = argsToArray(arguments);
var tableAliasNum = 0, sources = [];
source.forEach(function (s) {
if (isInstanceOf(s, Dataset)) {
source = argsToArray(arguments);
var tableAliasNum = 0, sources = [];
source.forEach(function (s) {
if (isInstanceOf(s, Dataset)) {
sources.push(new AliasedExpression(s, this._datasetAlias(++tableAliasNum)));
} else if (isHash(s)) {
} else if (isHash(s)) {
for (var i in s) {
sources.push(new AliasedExpression(new Identifier(i), s[i]));
}
} else if (isString(s)) {
sources.push(this.stringToIdentifier(s))
} else if (isString(s)) {
sources.push(this.stringToIdentifier(s));
} else {
sources.push(s);
}
}, this);
var o = {from: sources.length ? sources : null}
if (tableAliasNum) {
var o = {from: sources.length ? sources : null};
if (tableAliasNum) {
o.numDatasetSources = tableAliasNum;
}
return this.mergeOptions(o)
return this.mergeOptions(o);
},
/**
var fs = {};
var nonSqlOptions = this._static.NON_SQL_OPTIONS;
Object.keys(this.__opts).forEach(function (k) {
if (nonSqlOptions.indexOf(k) == -1) {
if (nonSqlOptions.indexOf(k) === -1) {
fs[k] = null;
}
});
group: function (columns) {
columns = argsToArray(arguments);
var self = this;
return this.mergeOptions({group: (array.compact(columns).length == 0 ? null : columns.map(function (c) {
return this.mergeOptions({group: (array.compact(columns).length === 0 ? null : columns.map(function (c) {
return isString(c) ? self.stringToIdentifier(c) : c;
}))});
},
**/
having: function () {
var cond = argsToArray(arguments).map(function (s) {
return isString(s) && s !== '' ? this.stringToIdentifier(s) : s
return isString(s) && s !== '' ? this.stringToIdentifier(s) : s;
}, this);
return this._filter.apply(this, ["having"].concat(cond));
},
if (!(having || where)) {
throw new QueryError("No current filter");
}
var o = {}
var o = {};
if (having) {
o.having = BooleanExpression.invert(having);
}
* @see patio.Dataset#joinTable
*/
join: function () {
return this.innerJoin.apply(this, arguments);
return this.innerJoin.apply(this, arguments);
},
/**
*/
joinTable: function (type, table, expr, options, cb) {
var args = argsToArray(arguments);
if (isFunction(args[args.length - 1])) {
var args = argsToArray(arguments);
if (isFunction(args[args.length - 1])) {
cb = args[args.length - 1];
args.pop();
} else {
cb = null;
cb = null;
}
type = args.shift(), table = args.shift(), expr = args.shift(), options = args.shift();
expr = isUndefined(expr) ? null : expr, options = isUndefined(options) ? {} : options;
type = args.shift(), table = args.shift(), expr = args.shift(), options = args.shift();
expr = isUndefined(expr) ? null : expr, options = isUndefined(options) ? {} : options;
var h;
var usingJoin = isArray(expr) && expr.length && expr.every(function (x) {
return isString(x) || isInstanceOf(x, Identifier)
var h;
var usingJoin = isArray(expr) && expr.length && expr.every(function (x) {
return isString(x) || isInstanceOf(x, Identifier);
});
if (usingJoin && !this.supportsJoinUsing) {
if (usingJoin && !this.supportsJoinUsing) {
h = {};
expr.forEach(function (s) {
h[s] = s;
});
return this.joinTable(type, table, h, options);
}
var tableAlias, lastAlias;
if (isHash(options)) {
tableAlias = options.tableAlias;
lastAlias = options.implicitQualifier;
var tableAlias, lastAlias;
if (isHash(options)) {
tableAlias = options.tableAlias;
lastAlias = options.implicitQualifier;
} else if (isString(options) || isInstanceOf(options, Identifier)) {
tableAlias = options;
lastAlias = null;
} else {
throw new QueryError("Invalid options format for joinTable %j4", [options]);
}
var tableAliasNum, tableName;
if (isInstanceOf(table, Dataset)) {
var tableAliasNum, tableName;
if (isInstanceOf(table, Dataset)) {
if (!tableAlias) {
tableAliasNum = (this.__opts.numDatasetSources || 0) + 1;
tableAlias = this._datasetAlias(tableAliasNum);
}
tableName = tableAlias;
} else {
if (!isUndefined(table.tableName)) {
if (!isUndefined(table.tableName)) {
table = table.tableName;
}
if (isArray(table)) {
if (isArray(table)) {
table = table.map(this.stringToIdentifier, this);
} else {
table = isString(table) ? this.stringToIdentifier(table) : table;
var parts = this._splitAlias(table), implicitTableAlias = parts[1];
table = parts[0]
tableAlias = tableAlias || implicitTableAlias;
tableName = tableAlias || table;
table = isString(table) ? this.stringToIdentifier(table) : table;
var parts = this._splitAlias(table), implicitTableAlias = parts[1];
table = parts[0];
tableAlias = tableAlias || implicitTableAlias;
tableName = tableAlias || table;
}
}
var join;
if (!expr && !cb) {
var join;
if (!expr && !cb) {
join = new JoinClause(type, table, tableAlias);
} else if (usingJoin) {
} else if (usingJoin) {
if (cb) {
throw new QueryError("cant use a cb if an array is given");
}
join = new JoinUsingClause(expr, type, table, tableAlias);
} else {
lastAlias = lastAlias || this.__opts["lastJoinedTable"] || this.firstSourceAlias;
if (Expression.isConditionSpecifier(expr)) {
var newExpr = [];
for (var i in expr) {
var val = expr[i];
if (isArray(val) && val.length == 2) {
lastAlias = lastAlias || this.__opts["lastJoinedTable"] || this.firstSourceAlias;
if (Expression.isConditionSpecifier(expr)) {
var newExpr = [];
for (var i in expr) {
var val = expr[i];
if (isArray(val) && val.length === 2) {
i = val[0], val = val[1];
}
var k = this.qualifiedColumnName(i, tableName), v;
if (isInstanceOf(val, Identifier)) {
v = val.qualify(lastAlias);
var k = this.qualifiedColumnName(i, tableName), v;
if (isInstanceOf(val, Identifier)) {
v = val.qualify(lastAlias);
} else {
v = val;
v = val;
}
newExpr.push([k, v]);
newExpr.push([k, v]);
}
expr = newExpr;
expr = newExpr;
}
if (isFunction(cb)) {
if (isFunction(cb)) {
var expr2 = cb.apply(sql, [tableName, lastAlias, this.__opts.join || []]);
expr = expr ? new BooleanExpression("AND", expr, expr2) : expr2;
}
join = new JoinOnClause(expr, type, table, tableAlias);
join = new JoinOnClause(expr, type, table, tableAlias);
}
var opts = {join: (this.__opts.join || []).concat([join]), lastJoinedTable: tableName};
if (tableAliasNum) {
var opts = {join: (this.__opts.join || []).concat([join]), lastJoinedTable: tableName};
if (tableAliasNum) {
opts.numDatasetSources = tableAliasNum;
}
return this.mergeOptions(opts);
return this.mergeOptions(opts);
},
if (this.__opts.sql) {
return this.fromSelf().limit(limit, offset);
}
if (isArray(limit) && limit.length == 2) {
if (isArray(limit) && limit.length === 2) {
offset = limit[0];
limit = limit[1] - limit[0] + 1;
}
* @return {patio.Dataset} a cloned dataset with the order changed.
* */
order: function (args) {
args = argsToArray(arguments);
var order = [];
args = compact(args).length ? args : null;
if (args) {
args.forEach(function (a) {
if (isString(a)) {
order.push(this.stringToIdentifier(a));
args = argsToArray(arguments);
var order = [];
args = compact(args).length ? args : null;
if (args) {
args.forEach(function (a) {
if (isString(a)) {
order.push(this.stringToIdentifier(a));
} else if (isFunction(a)) {
var res = a.apply(sql, [sql]);
order = order.concat(isArray(res) ? res : [res]);
} else {
order = null;
}
return this.mergeOptions({order: order});
return this.mergeOptions({order: order});
},
/**
* @return {patio.Dataset} a cloned dataset with the columns selected changed.
*/
select: function (args) {
args = flatten(argsToArray(arguments));
var columns = [];
args.forEach(function (c) {
if (isFunction(c)) {
args = flatten(argsToArray(arguments));
var columns = [];
args.forEach(function (c) {
if (isFunction(c)) {
var res = c.apply(sql, [sql]);
columns = columns.concat(isArray(res) ? res : [res]);
} else {
columns.push(c);
columns.push(c);
}
});
var select = [];
columns.forEach(function (c) {
if (isHash(c)) {
var select = [];
columns.forEach(function (c) {
if (isHash(c)) {
for (var i in c) {
select.push(new AliasedExpression(this.stringToIdentifier(i), c[i]));
}
} else if (isString(c)) {
select.push(this.stringToIdentifier(c));
} else if (isString(c)) {
select.push(this.stringToIdentifier(c));
} else {
select.push(c);
select.push(c);
}
}, this);
return this.mergeOptions({select: select});
return this.mergeOptions({select: select});
},
throw new QueryError("This dataset does not support common table expressions");
}
opts = opts || {};
var wit = (this.__opts["with"] || []).concat([merge(opts, {recursive: true, name: this.stringToIdentifier(name), dataset: nonRecursive.union(recursive, {all: opts.unionAll != false, fromSelf: false})})]);
var wit = (this.__opts["with"] || []).concat([merge(opts, {recursive: true, name: this.stringToIdentifier(name), dataset: nonRecursive.union(recursive, {all: opts.unionAll !== false, fromSelf: false})})]);
return this.mergeOptions({"with": wit});
},
* @return {patio.Dataset} a cloned dataset with the static sql set.
*/
withSql: function (sql) {
var args = argsToArray(arguments).slice(1);
if (args.length) {
sql = new PlaceHolderLiteralString(sql, args)
var args = argsToArray(arguments).slice(1);
if (args.length) {
sql = new PlaceHolderLiteralString(sql, args);
}
return this.mergeOptions({sql: sql});
return this.mergeOptions({sql: sql});
},
* @return {patio.Dataset} a cloned dataset with the condition group added to the WHERE/HAVING clause.
*/
_addGroupedCondition: function (addedByBool, groupedByBool) {
groupedByBool = isUndefined(groupedByBool) ? "AND" : groupedByBool;
var tOpts = this.__opts,
groupedByBool = isUndefined(groupedByBool) ? "AND" : groupedByBool;
var tOpts = this.__opts,
clause = (tOpts.having ? "having" : "where"),
clauseObj = tOpts[clause];
var args = argsToArray(arguments, 2);
args = args.length == 1 ? args[0] : args;
var opts = {};
if (clauseObj) {
addedByBool = isUndefined(addedByBool) ? "AND" : addedByBool;
opts[clause] = new BooleanExpression(addedByBool, clauseObj, this._filterExpr(args, null, groupedByBool));
var args = argsToArray(arguments, 2);
args = args.length === 1 ? args[0] : args;
var opts = {};
if (clauseObj) {
addedByBool = isUndefined(addedByBool) ? "AND" : addedByBool;
opts[clause] = new BooleanExpression(addedByBool, clauseObj, this._filterExpr(args, null, groupedByBool));
} else {
opts[clause] = this._filterExpr(args, null, groupedByBool);
}
return this.mergeOptions(opts);
return this.mergeOptions(opts);
},
/**
* Internal filter method so it works on either the having or where clauses.
*/
_filter: function (clause) {
var cond = argsToArray(arguments).slice(1), cb;
if (cond.length && isFunction(cond[cond.length - 1])) {
var cond = argsToArray(arguments).slice(1), cb;
if (cond.length && isFunction(cond[cond.length - 1])) {
cb = cond.pop();
}
cond = cond.length == 1 ? cond[0] : cond
if ((cond == null || cond == undefined || cond === "") || (isArray(cond) && cond.length == 0 && !cb) || (isObject(cond) && isEmpty(cond) && !cb)) {
cond = cond.length === 1 ? cond[0] : cond;
if ((cond == null || cond === undefined || cond === "") || (isArray(cond) && cond.length === 0 && !cb) || (isObject(cond) && isEmpty(cond) && !cb)) {
return this.mergeOptions();
} else {
cond = this._filterExpr(cond, cb);
var cl = this.__opts[clause];
cl && (cond = new BooleanExpression("AND", cl, cond));
var opts = {};
opts[clause] = cond;
return this.mergeOptions(opts);
cond = this._filterExpr(cond, cb);
var cl = this.__opts[clause];
cl && (cond = new BooleanExpression("AND", cl, cond));
var opts = {};
opts[clause] = cond;
return this.mergeOptions(opts);
}
},
* string that does not contain an alias {table}___{alias}.
*/
_splitAlias: function (c) {
var ret;
if (isInstanceOf(c, AliasedExpression)) {
var ret;
if (isInstanceOf(c, AliasedExpression)) {
ret = [c.expression, c.alias];
} else if (isString(c)) {
} else if (isString(c)) {
var parts = this._splitString(c), cTable = parts[0], column = parts[1], alias = parts[2];
if (alias) {
ret = [cTable ? new QualifiedIdentifier(cTable, column) : column, alias];
ret = [c, null];
}
} else {
ret = [c, null];
ret = [c, null];
}
return ret;
return ret;
},
pairs.push(new BooleanExpression(op, new Identifier(pair[0]), pair[1]));
});
}
return pairs.length == 1 ? pairs[0] : BooleanExpression.fromArgs(["AND"].concat(pairs));
return pairs.length === 1 ? pairs[0] : BooleanExpression.fromArgs(["AND"].concat(pairs));
},
/**
throw new QueryError("Between requires an array for the value");
}
}
var ret = pairs.length == 1 ? pairs[0] : BooleanExpression.fromArgs(["AND"].concat(pairs))
var ret = pairs.length === 1 ? pairs[0] : BooleanExpression.fromArgs(["AND"].concat(pairs));
return invert ? BooleanExpression.invert(ret) : ret;
},
* SQL expression object based on the expr type. See {@link patio.Dataset#filter}
*/
_filterExpr: function (expr, cb, joinCond) {
expr = (isUndefined(expr) || isNull(expr) || (isArray(expr) && !expr.length)) ? null : expr;
if (expr && cb) {
return new BooleanExpression(joinCond || "AND", this._filterExpr(expr, null, joinCond), this._filterExpr(cb, null, joinCond))
} else if (cb) {
expr = cb
expr = (isUndefined(expr) || isNull(expr) || (isArray(expr) && !expr.length)) ? null : expr;
if (expr && cb) {
return new BooleanExpression(joinCond || "AND", this._filterExpr(expr, null, joinCond), this._filterExpr(cb, null, joinCond));
} else if (cb) {
expr = cb;
}
if (isInstanceOf(expr, Expression)) {
if (isInstanceOf(expr, Expression)) {
if (isInstanceOf(expr, NumericExpression, StringExpression)) {
throw new QueryError("Invalid SQL Expression type : " + expr);
}
return expr;
} else if (isArray(expr)) {
if (expr.length) {
var first = expr[0];
if (isString(first)) {
} else if (isArray(expr)) {
if (expr.length) {
var first = expr[0];
if (isString(first)) {
return new PlaceHolderLiteralString(first, expr.slice(1), true);
} else if (Expression.isConditionSpecifier(expr)) {
return BooleanExpression.fromValuePairs(expr, joinCond)
} else if (Expression.isConditionSpecifier(expr)) {
return BooleanExpression.fromValuePairs(expr, joinCond);
} else {
return BooleanExpression.fromArgs([joinCond || "AND"].concat(expr.map(function (e) {
return this._filterExpr(e, null, joinCond);
}, this)));
}
}
} else if (isFunction(expr)) {
} else if (isFunction(expr)) {
return this._filterExpr(expr.call(sql, sql), null, joinCond);
} else if (isBoolean(expr)) {
} else if (isBoolean(expr)) {
return new BooleanExpression("NOOP", expr);
} else if (isString(expr)) {
} else if (isString(expr)) {
return this.stringToIdentifier(expr);
} else if (isInstanceOf(expr, LiteralString)) {
} else if (isInstanceOf(expr, LiteralString)) {
return new LiteralString("(" + expr + ")");
} else if (isHash(expr)) {
return BooleanExpression.fromValuePairs(expr, joinCond);
} else if (isHash(expr)) {
return BooleanExpression.fromValuePairs(expr, joinCond);
} else {
throw new QueryError("Invalid filter argument");
}
isSimpleSelectAll: function () {
var o = {}, opts = this.__opts, count = 0;
for (var i in opts) {
if (opts[i] != null && this._static.NON_SQL_OPTIONS.indexOf(i) == -1) {
if (opts[i] != null && this._static.NON_SQL_OPTIONS.indexOf(i) === -1) {
o[i] = opts[i];
count++;
}
}
var f = o.from
return count == 1 && f.length == 1 && (isString(f[0]) || isInstanceOf(f[0], AliasedExpression, Identifier));
var f = o.from;
return count === 1 && f.length === 1 && (isString(f[0]) || isInstanceOf(f[0], AliasedExpression, Identifier));
}
}
},
this.QUERY_METHODS = queryMethods.concat(joinMethods);
}
}
}).
as(module);
}).as(module);
* @ignore
*/
constructor: function () {
!Dataset && (Dataset = require("../index").Dataset);
this._super(arguments);
!Dataset && (Dataset = require("../index").Dataset);
this._super(arguments);
},
/**
* Logs an INFO level message to the "patio.Database" logger.
*/
logInfo: function () {
if (LOGGER.isInfo) {
LOGGER.info.apply(LOGGER, arguments);
if (LOGGER.isInfo) {
LOGGER.info.apply(LOGGER, arguments);
}
},
* Logs a DEBUG level message to the "patio.Database" logger.
*/
logDebug: function () {
if (LOGGER.isDebug) {
LOGGER.debug.apply(LOGGER, arguments);
if (LOGGER.isDebug) {
LOGGER.debug.apply(LOGGER, arguments);
}
},
* and all other queries with the duration at warn or info level.
* */
__logAndExecute: function (sql, args, cb) {
if (isFunction(args)) {
cb = args;
args = null;
if (isFunction(args)) {
cb = args;
args = null;
}
if (args) {
if (args) {
sql = format("%s; %j", sql, args);
}
sql = sql.trim();
var start = new Date(), self = this;
var ret;
if (isFunction(cb)) {
this.logInfo("Executing; %s", sql);
ret = new Promise();
cb().chain(function () {
self.logDebug("Duration: % 6dms; %s", new Date() - start, sql);
spreadArgs(ret.callback, arguments);
sql = sql.trim();
var start = new Date(), self = this;
var ret;
if (isFunction(cb)) {
this.logInfo("Executing; %s", sql);
ret = new Promise();
cb().chain(function () {
self.logDebug("Duration: % 6dms; %s", new Date() - start, sql);
spreadArgs(ret.callback, arguments);
},function (err) {
err = new QueryError(format("%s: %s", err.message, sql));
self.logError(err);
} else {
throw new QueryError("CB is required");
}
return ret.promise();
return ret.promise();
},
/*Log the given SQL and then execute it on the connection, used by
// Whether this dataset quotes identifiers.
/**@ignore*/
quoteIdentifiers:function(){
return this.__quoteIdentifiers;
return this.__quoteIdentifiers;
},
// Whether this dataset will provide accurate number of rows matched for
// rows matched by the dataset's filter.
/**@ignore*/
providesAccurateRowsMatched:function(){
return this.__providesAccurateRowsMatched;
return this.__providesAccurateRowsMatched;
},
//Whether the dataset requires SQL standard datetimes (false by default,
// as most allow strings with ISO 8601 format).
/**@ignore*/
requiresSqlStandardDateTimes:function(){
return this.__requiresSqlStandardDateTimes;
return this.__requiresSqlStandardDateTimes;
},
// Whether the dataset supports common table expressions (the WITH clause).
/**@ignore*/
supportsCte:function(){
return this.__supportsCte;
return this.__supportsCte;
},
// Whether the dataset supports the DISTINCT ON clause, false by default.
/**@ignore*/
supportsDistinctOn:function(){
return this.__supportsDistinctOn;
return this.__supportsDistinctOn;
},
//Whether the dataset supports the INTERSECT and EXCEPT compound operations, true by default.
/**@ignore*/
supportsIntersectExcept:function(){
return this.__supportsIntersectExcept;
return this.__supportsIntersectExcept;
},
//Whether the dataset supports the INTERSECT ALL and EXCEPT ALL compound operations, true by default.
/**@ignore*/
supportsIntersectExceptAll:function(){
return this.__supportsIntersectExceptAll;
return this.__supportsIntersectExceptAll;
},
//Whether the dataset supports the IS TRUE syntax.
/**@ignore*/
supportsIsTrue:function(){
return this.__supportsIsTrue;
return this.__supportsIsTrue;
},
//Whether the dataset supports the JOIN table USING (column1, ...) syntax.
/**@ignore*/
supportsJoinUsing:function(){
return this.__supportsJoinUsing;
return this.__supportsJoinUsing;
},
//Whether modifying joined datasets is supported.
/**@ignore*/
supportsModifyingJoins:function(){
return this.__supportsModifyingJoins;
return this.__supportsModifyingJoins;
},
//Whether the IN/NOT IN operators support multiple columns when an
/**@ignore*/
supportsMultipleColumnIn:function(){
return this.__supportsMultipleColumnIn;
return this.__supportsMultipleColumnIn;
},
//Whether the dataset supports timezones in literal timestamps
/**@ignore*/
supportsTimestampTimezones:function(){
return this.__supportsTimestampTimezones;
return this.__supportsTimestampTimezones;
},
//Whether the dataset supports fractional seconds in literal timestamps
/**@ignore*/
supportsTimestampUsecs:function(){
return this.__supportsTimestampUsecs;
return this.__supportsTimestampUsecs;
},
//Whether the dataset supports window functions.
/**@ignore*/
supportsWindowFunctions:function(){
return this.__supportsWindowFunctions;
return this.__supportsWindowFunctions;
}
},
// Whether this dataset quotes identifiers.
/**@ignore*/
quoteIdentifiers:function(val){
this.__quoteIdentifiers = val;
this.__quoteIdentifiers = val;
},
// Whether this dataset will provide accurate number of rows matched for
// rows matched by the dataset's filter.
/**@ignore*/
providesAccurateRowsMatched:function(val){
this.__providesAccurateRowsMatched = val;
this.__providesAccurateRowsMatched = val;
},
//Whether the dataset requires SQL standard datetimes (false by default,
// as most allow strings with ISO 8601 format).
/**@ignore*/
requiresSqlStandardDateTimes:function(val){
this.__requiresSqlStandardDateTimes = val;
this.__requiresSqlStandardDateTimes = val;
},
// Whether the dataset supports common table expressions (the WITH clause).
/**@ignore*/
supportsCte:function(val){
this.__supportsCte = val;
this.__supportsCte = val;
},
// Whether the dataset supports the DISTINCT ON clause, false by default.
/**@ignore*/
supportsDistinctOn:function(val){
this.__supportsDistinctOn = val;
this.__supportsDistinctOn = val;
},
//Whether the dataset supports the INTERSECT and EXCEPT compound operations, true by default.
/**@ignore*/
supportsIntersectExcept:function(val){
this.__supportsIntersectExcept = val;
this.__supportsIntersectExcept = val;
},
//Whether the dataset supports the INTERSECT ALL and EXCEPT ALL compound operations, true by default.
/**@ignore*/
supportsIntersectExceptAll:function(val){
this.__supportsIntersectExceptAll = val;
this.__supportsIntersectExceptAll = val;
},
//Whether the dataset supports the IS TRUE syntax.
/**@ignore*/
supportsIsTrue:function(val){
this.__supportsIsTrue = val;
this.__supportsIsTrue = val;
},
//Whether the dataset supports the JOIN table USING (column1, ...) syntax.
/**@ignore*/
supportsJoinUsing:function(val){
this.__supportsJoinUsing = val;
this.__supportsJoinUsing = val;
},
//Whether modifying joined datasets is supported.
/**@ignore*/
supportsModifyingJoins:function(val){
this.__supportsModifyingJoins = val;
this.__supportsModifyingJoins = val;
},
//Whether the IN/NOT IN operators support multiple columns when an
/**@ignore*/
supportsMultipleColumnIn:function(val){
this.__supportsMultipleColumnIn = val;
this.__supportsMultipleColumnIn = val;
},
//Whether the dataset supports timezones in literal timestamps
/**@ignore*/
supportsTimestampTimezones:function(val){
this.__supportsTimestampTimezones = val;
this.__supportsTimestampTimezones = val;
},
//Whether the dataset supports fractional seconds in literal timestamps
/**@ignore*/
supportsTimestampUsecs:function(val){
this.__supportsTimestampUsecs = val;
this.__supportsTimestampUsecs = val;
},
//Whether the dataset supports window functions.
/**@ignore*/
supportsWindowFunctions:function(val){
this.__supportsWindowFunctions = val;
this.__supportsWindowFunctions = val;
}
}
1
if the migration fails. #92andGrouped*
methods..then
to .chain
* Checks all deferred connection requests.
*/
__checkQueries: function () {
var fc = this.freeCount, def, defQueue = this.__deferredQueue;
while (fc-- >= 0 && defQueue.count) {
var fc = this.freeCount, def, defQueue = this.__deferredQueue;
while (fc-- >= 0 && defQueue.count) {
def = defQueue.dequeue();
var conn = this.getObject();
if (conn) {
* @return {comb.Promise} A promise to called back with a connection.
*/
getConnection: function () {
var ret = new Promise();
if (this.count > this.__maxObjects) {
var ret = new Promise();
if (this.count > this.__maxObjects) {
this.__deferredQueue.enqueue(ret);
} else {
//todo override getObject to make async so creating a connetion can execute setup sql
var conn = this.getObject();
if (!conn) {
var conn = this.getObject();
if (!conn) {
//we need to deffer it
this.__deferredQueue.enqueue(ret);
} else {
ret.callback(conn);
ret.callback(conn);
}
}
if (this.count > this.__maxObjects && !conn) {
if (this.count > this.__maxObjects && !conn) {
ret.errback(new Error("Unexpected ConnectionPool error"));
}
return ret.promise();
return ret.promise();
},
/**
*
*/
returnObject: function (obj) {
var self = this;
this.validate(obj).chain(function (valid) {
var index;
if (self.count <= self.__maxObjects && valid && (index = self.__inUseObjects.indexOf(obj)) > -1) {
self.__inUseObjects.splice(index, 1);
self.__freeObjects.enqueue(obj);
self.__checkQueries();
var self = this;
this.validate(obj).chain(function (valid) {
var index;
if (self.count <= self.__maxObjects && valid && (index = self.__inUseObjects.indexOf(obj)) > -1) {
self.__inUseObjects.splice(index, 1);
self.__freeObjects.enqueue(obj);
self.__checkQueries();
} else {
self.removeObject(obj);
}
* @return {*} an adapter specific connection.
*/
returnConnection: function (connection) {
this.returnObject(connection);
this.returnObject(connection);
},
createObject: function () {
* @return {comb.Promise} called back with a valid or invalid state.
*/
validate: function (conn) {
if (!this.__validateConnectionCB) {
if (!this.__validateConnectionCB) {
var ret = new Promise();
ret.callback(true);
return ret;
} else {
return this.__validateConnectionCB();
return this.__validateConnectionCB();
}
},
};
var isBlank = function (obj) {
var ret = false;
if (isUndefinedOrNull(obj)) {
ret = true;
} else if (isString(obj) || isArray(obj)) {
ret = obj.length === 0;
var ret = false;
if (isUndefinedOrNull(obj)) {
ret = true;
} else if (isString(obj) || isArray(obj)) {
ret = obj.length === 0;
} else if (isBoolean(obj) && !obj) {
ret = true;
} else if (isObject(obj) && isEmpty(obj)) {
ret = true;
}
return ret;
return ret;
};
var byteaParser = function (val) {
},
query: function (query) {
var ret = new Promise();
try {
this.connection.setMaxListeners(0);
var fields = [];
var q = this.connection.query(query, function (err, results) {
q.handleRowDescription = orig;
if (err) {
var ret = new Promise();
try {
this.connection.setMaxListeners(0);
var fields = [];
var q = this.connection.query(query, function (err, results) {
q.handleRowDescription = orig;
if (err) {
return ret.errback(err);
} else {
return ret.callback(results.rows, fields);
return ret.callback(results.rows, fields);
}
});
var orig = q.handleRowDescription;
q.handleRowDescription = function (msg) {
fields = msg.fields;
return orig.apply(q, arguments);
var orig = q.handleRowDescription;
q.handleRowDescription = function (msg) {
fields = msg.fields;
return orig.apply(q, arguments);
};
} catch (e) {
patio.logError(e);
}
return ret.promise();
return ret.promise();
}
}
});
function colCallback(o) {
return o;
return o;
}
DS = define(Dataset, {
instance: {
complexExpressionSql: function (op, args) {
var ret = "";
if (op === "^") {
var ret = "";
if (op === "^") {
var j = this._static.XOR_OP, c = false;
args.forEach(function (a) {
if (c) {
c = true;
}, true);
} else {
return this._super(arguments);
return this._super(arguments);
}
return ret;
},
},
_literalString: function (v) {
return "'" + v.replace(/\\/g, "\\\\").replace(/'/g, "''") + "'";
return "'" + v.replace(/\\/g, "\\\\").replace(/'/g, "''") + "'";
},
_deleteFromSql: function () {
},
_selectLockSql: function () {
if (this.__opts.lock === "share") {
if (this.__opts.lock === "share") {
return this._static.FOR_SHARE;
} else {
return this._super(arguments);
return this._super(arguments);
}
},
_selectWithSql: function () {
var optsWith = this.__opts["with"];
if (!isEmpty(optsWith) && optsWith.some(function (w) {
var optsWith = this.__opts["with"];
if (!isEmpty(optsWith) && optsWith.some(function (w) {
return w.recursive;
})) {
return this._static.SQL_WITH_RECURSIVE;
} else {
return this._super(arguments);
return this._super(arguments);
}
},
},
_quotedIdentifier: function (c) {
return format('"%s"', c);
return format('"%s"', c);
},
__fullTextStringJoin: function (cols) {
},
fetchRows: function (sql) {
var oi = this.outputIdentifier.bind(this), self = this;
return asyncArray(this.execute(sql).chain(function (rows, fields) {
var cols = [];
if (rows && rows.length) {
self.__columns = [];
var col, colOutputIdentifier, i = -1, l;
if (fields && fields.length) {
var oi = this.outputIdentifier.bind(this), self = this;
return asyncArray(this.execute(sql).chain(function (rows, fields) {
var cols = [];
if (rows && rows.length) {
self.__columns = [];
var col, colOutputIdentifier, i = -1, l;
if (fields && fields.length) {
l = fields.length;
while (++i < l) {
colOutputIdentifier = self.__columns[i] = oi(col = fields[i].name);
cols[i] = [colOutputIdentifier, colCallback, col];
}
} else {
fields = Object.keys(rows[0]);
l = fields.length;
while (++i < l) {
colOutputIdentifier = self.__columns[i] = oi(col = fields[i]);
cols[i] = [colOutputIdentifier, colCallback, col];
fields = Object.keys(rows[0]);
l = fields.length;
while (++i < l) {
colOutputIdentifier = self.__columns[i] = oi(col = fields[i]);
cols[i] = [colOutputIdentifier, colCallback, col];
}
}
}
return self.__processRows(rows, cols);
return self.__processRows(rows, cols);
}));
},
__processRows: function (rows, cols) {
//dp this so the callbacks are called in appropriate order also.
var ret = [], i = -1, l = rows.length, j = -1, k = cols.length, row, h, col;
while (++i < l) {
row = rows[i];
h = {};
j = -1;
while (++j < k) {
col = cols[j];
h[col[0]] = col[1](row[col[2]]);
var ret = [], i = -1, l = rows.length, j = -1, k = cols.length, row, h, col;
while (++i < l) {
row = rows[i];
h = {};
j = -1;
while (++j < k) {
col = cols[j];
h[col[0]] = col[1](row[col[2]]);
}
ret[i] = h;
ret[i] = h;
}
return ret;
return ret;
},
},
supportsDistinctOn: function () {
return true;
return true;
},
supportsModifyingJoins: function () {
return true;
return true;
},
supportsTimestampTimezones: function () {
return true;
return true;
}
}
},
validate: function (conn) {
return new Promise().callback(true).promise();
return new Promise().callback(true).promise();
},
execute: function (sql, opts, conn) {
var self = this;
return when(conn || this._getConnection()).chain(function (conn) {
return self.__execute(conn, sql, opts);
var self = this;
return when(conn || this._getConnection()).chain(function (conn) {
return self.__execute(conn, sql, opts);
});
},
__execute: function (conn, sql, opts, cb) {
var self = this;
return this.__logAndExecute(sql, function () {
return conn.query(sql);
var self = this;
return this.__logAndExecute(sql, function () {
return conn.query(sql);
})
.both(function () {
return self._returnConnection(conn);
return self._returnConnection(conn);
});
},
schemaParseTable: function (tableName, opts) {
var m = this.outputIdentifierFunc,
var m = this.outputIdentifierFunc,
m2 = this.inputIdentifierFunc;
var ds = this.metadataDataset
var ds = this.metadataDataset
.select(
"pg_attribute__attname___name",
sql["format_type"]("pg_type__oid", "pg_attribute__atttypmod").as(literal('"dbType"')),
.filter({"pg_attribute__attnum": {gt: 0}})
.filter({"pg_class__relname": m2(tableName)})
.order("pg_attribute__attnum");
ds = this.__filterSchema(ds, opts);
var currentSchema = null, self = this;
return ds.map(function (row) {
var sch = row.nspname;
delete row.nspname;
if (currentSchema) {
if (sch !== currentSchema) {
ds = this.__filterSchema(ds, opts);
var currentSchema = null, self = this;
return ds.map(function (row) {
var sch = row.nspname;
delete row.nspname;
if (currentSchema) {
if (sch !== currentSchema) {
var error = new Error("columns from two tables were returned please specify a schema");
self.logError(error);
}
} else {
currentSchema = sch;
currentSchema = sch;
}
if (isBlank(row["default"])) {
row["default"] = null;
if (isBlank(row["default"])) {
row["default"] = null;
}
row.type = self.schemaColumnType(row.dbType);
var fieldName = m(row.name);
delete row.name;
return [fieldName, row];
row.type = self.schemaColumnType(row.dbType);
var fieldName = m(row.name);
delete row.name;
return [fieldName, row];
});
//If opts includes a :schema option, or a default schema is used, restrict the dataset to
// that schema. Otherwise, just exclude the default PostgreSQL schemas except for public.
__filterSchema: function (ds, opts) {
opts = opts || {};
var schema = opts.schema, ret = ds;
if (schema) {
opts = opts || {};
var schema = opts.schema, ret = ds;
if (schema) {
ds = ds.filter({"pg_namespace__nspname": schema});
} else {
ds = ds.exclude({"pg_namespace__nspname": this.EXCLUDE_SCHEMAS});
ds = ds.exclude({"pg_namespace__nspname": this.EXCLUDE_SCHEMAS});
}
return ds;
return ds;
},
__notifySql: function (channel, payload) {
},
dataset: function () {
return new DS(this);
return new DS(this);
},
serialPrimaryKeyOptions: function () {
},
query: function (query) {
var ret = new Promise();
try {
this.connection.setMaxListeners(0);
this.connection.query(query, hitch(ret, ret.resolve));
var ret = new Promise();
try {
this.connection.setMaxListeners(0);
this.connection.query(query, hitch(ret, ret.resolve));
} catch (e) {
patio.logError(e);
}
return ret.promise();
return ret.promise();
}
}
});
},
fetchRows: function (sql) {
var self = this;
return asyncArray(this.execute(sql).chain(function (r, fields) {
var cols = [], i = -1, l = fields.length, col, fieldName, type, length, colIdentifier, selfCols = [];
self.__columns = selfCols;
while (++i < l) {
col = fields[i];
fieldName = col.name;
type = col.type;
length = col.fieldLength;
colIdentifier = self.outputIdentifier(fieldName);
selfCols[i] = colIdentifier;
cols[i] = [colIdentifier, DB.convertMysqlType(type === 1 && length !== 1 ? 2 : type), fieldName];
var self = this;
return asyncArray(this.execute(sql).chain(function (r, fields) {
var cols = [], i = -1, l = fields.length, col, fieldName, type, length, colIdentifier, selfCols = [];
self.__columns = selfCols;
while (++i < l) {
col = fields[i];
fieldName = col.name;
type = col.type;
length = col.fieldLength;
colIdentifier = self.outputIdentifier(fieldName);
selfCols[i] = colIdentifier;
cols[i] = [colIdentifier, DB.convertMysqlType(type === 1 && length !== 1 ? 2 : type), fieldName];
}
return self.__processRows(r, cols);
return self.__processRows(r, cols);
}));
},
__processRows: function (rows, cols) {
//dp this so the callbacks are called in appropriate order also.
var ret = [], i = -1, l = rows.length, j = -1, k = cols.length, row, h, col;
while (++i < l) {
row = rows[i];
h = {};
j = -1;
while (++j < k) {
col = cols[j];
h[col[0]] = col[1](row[col[2]]);
var ret = [], i = -1, l = rows.length, j = -1, k = cols.length, row, h, col;
while (++i < l) {
row = rows[i];
h = {};
j = -1;
while (++j < k) {
col = cols[j];
h[col[0]] = col[1](row[col[2]]);
}
ret[i] = h;
ret[i] = h;
}
return ret;
return ret;
},
//Don't allow graphing a dataset that splits multiple statements
//Set the :type option to select if it hasn't been set.
execute: function (sql, opts) {
opts = opts || {};
return this._super([sql, merge({type: "select"}, opts)]);
opts = opts || {};
return this._super([sql, merge({type: "select"}, opts)]);
},
//Set the :type option to :select if it hasn't been set.
},
validate: function (conn) {
return new Promise().callback(true).promise();
return new Promise().callback(true).promise();
},
execute: function (sql, opts, conn) {
var self = this;
return when(conn || this._getConnection()).chain(function (conn) {
return self.__execute(conn, sql, opts);
var self = this;
return when(conn || this._getConnection()).chain(function (conn) {
return self.__execute(conn, sql, opts);
});
},
__execute: function (conn, sql, opts, cb) {
var self = this;
return this.__logAndExecute(sql, function () {
return conn.query(sql);
var self = this;
return this.__logAndExecute(sql, function () {
return conn.query(sql);
})
.both(function () {
return self._returnConnection(conn);
return self._returnConnection(conn);
});
},
//Use the MySQL specific DESCRIBE syntax to get a table description.
schemaParseTable: function (tableName, opts) {
var m = this.outputIdentifierFunc, im = this.inputIdentifierFunc, self = this;
return this.metadataDataset.withSql("DESCRIBE ?", sql.identifier(im(tableName))).map(function (row) {
var ret = {};
var e = row[m("Extra")];
var allowNull = row[m("Null")];
var key = row[m("Key")];
ret.autoIncrement = e.match(/auto_increment/i) !== null;
ret.allowNull = allowNull.match(/Yes/i) !== null;
ret.primaryKey = key.match(/PRI/i) !== null;
var defaultValue = row[m("Default")];
ret["default"] = Buffer.isBuffer(defaultValue) ? defaultValue.toString() : defaultValue;
if (isEmpty(row["default"])) {
row["default"] = null;
var m = this.outputIdentifierFunc, im = this.inputIdentifierFunc, self = this;
return this.metadataDataset.withSql("DESCRIBE ?", sql.identifier(im(tableName))).map(function (row) {
var ret = {};
var e = row[m("Extra")];
var allowNull = row[m("Null")];
var key = row[m("Key")];
ret.autoIncrement = e.match(/auto_increment/i) !== null;
ret.allowNull = allowNull.match(/Yes/i) !== null;
ret.primaryKey = key.match(/PRI/i) !== null;
var defaultValue = row[m("Default")];
ret["default"] = Buffer.isBuffer(defaultValue) ? defaultValue.toString() : defaultValue;
if (isEmpty(row["default"])) {
row["default"] = null;
}
ret.dbType = row[m("Type")];
if (Buffer.isBuffer(ret.dbType)) {
ret.dbType = row[m("Type")];
if (Buffer.isBuffer(ret.dbType)) {
//handle case for field type being returned at 252 (i.e. BLOB)
ret.dbType = ret.dbType.toString();
ret.dbType = ret.dbType.toString();
}
ret.type = self.schemaColumnType(ret.dbType.toString("utf8"));
var fieldName = m(row[m("Field")]);
return [fieldName, ret];
ret.type = self.schemaColumnType(ret.dbType.toString("utf8"));
var fieldName = m(row[m("Field")]);
return [fieldName, ret];
});
},
//Convert tinyint(1) type to boolean if convert_tinyint_to_bool is true
schemaColumnType: function (dbType) {
return this._static.convertTinyintToBool && dbType === 'tinyint(1)' ? "boolean" : this._super(arguments);
return this._static.convertTinyintToBool && dbType === 'tinyint(1)' ? "boolean" : this._super(arguments);
},
},
dataset: function () {
return new DS(this);
return new DS(this);
}
}
},
},
convertMysqlType: function (type) {
var convert = this.convertTinyintToBool, convertDateTime = this.__convertInvalidDateTime, types = this.FIELD_TYPES;
if (!patio) {
var convert = this.convertTinyintToBool, convertDateTime = this.__convertInvalidDateTime, types = this.FIELD_TYPES;
if (!patio) {
patio = require("../index");
}
return function (o) {
var ret = o;
if (o !== null) {
switch (type) {
return function (o) {
var ret = o;
if (o !== null) {
switch (type) {
case types.FIELD_TYPE_TIMESTAMP:
case types.FIELD_TYPE_DATETIME:
ret = convertDate(o, "stringToDateTime", convertDateTime);
case types.FIELD_TYPE_MEDIUM_BLOB:
case types.FIELD_TYPE_LONG_BLOB:
case types.FIELD_TYPE_BLOB:
ret = new Buffer(o);
break;
ret = new Buffer(o);
break;
}
}
return ret;
return ret;
};
},
getters: {
convertTinyintToBool: function () {
return this.__convertTinyintToBool;
return this.__convertTinyintToBool;
},
convertInvalidDateTime: function () {
* @property {Boolean} hasSelectSource true if this dataset already has a select sources.
*/
constructor:function (db, opts) {
this._super(arguments);
this.db = db;
this.__opts = {};
this.__rowCb = null;
if (db) {
this.__quoteIdentifiers = db.quoteIdentifiers;
this.__identifierInputMethod = db.identifierInputMethod;
this.__identifierOutputMethod = db.identifierOutputMethod;
this._super(arguments);
this.db = db;
this.__opts = {};
this.__rowCb = null;
if (db) {
this.__quoteIdentifiers = db.quoteIdentifiers;
this.__identifierInputMethod = db.identifierInputMethod;
this.__identifierOutputMethod = db.identifierOutputMethod;
}
},
* @return [patio.Dataset] a cloned dataset with the merged options
**/
mergeOptions:function (opts) {
opts = isUndefined(opts) ? {} : opts;
var ds = new this._static(this.db, {});
ds.rowCb = this.rowCb;
this._static.FEATURES.forEach(function (f) {
ds[f] = this[f];
opts = isUndefined(opts) ? {} : opts;
var ds = new this._static(this.db, {});
ds.rowCb = this.rowCb;
this._static.FEATURES.forEach(function (f) {
ds[f] = this[f];
}, this);
var dsOpts = ds.__opts = merge({}, this.__opts, opts);
ds.identifierInputMethod = this.identifierInputMethod;
ds.identifierOutputMethod = this.identifierOutputMethod;
var columnChangeOpts = this._static.COLUMN_CHANGE_OPTS;
if (Object.keys(opts).some(function (o) {
return columnChangeOpts.indexOf(o) !== -1;
var dsOpts = ds.__opts = merge({}, this.__opts, opts);
ds.identifierInputMethod = this.identifierInputMethod;
ds.identifierOutputMethod = this.identifierOutputMethod;
var columnChangeOpts = this._static.COLUMN_CHANGE_OPTS;
if (Object.keys(opts).some(function (o) {
return columnChangeOpts.indexOf(o) !== -1;
})) {
dsOpts.columns = null;
dsOpts.columns = null;
}
return ds;
return ds;
},
* @return {patio.sql.Identifier|patio.sql.QualifiedIdentifier|patio.sql.AliasedExpression} an identifier generated based on the name string.
*/
stringToIdentifier:function (name) {
if (isString(name)) {
var parts = this._splitString(name);
var schema = parts[0], table = parts[1], alias = parts[2];
return (schema && table && alias
if (isString(name)) {
var parts = this._splitString(name);
var schema = parts[0], table = parts[1], alias = parts[2];
return (schema && table && alias
? new AliasedExpression(new QualifiedIdentifier(schema, table), alias)
: (schema && table
? new QualifiedIdentifier(schema, table)
: (table && alias
? new AliasedExpression(new Identifier(table), alias) : new Identifier(table))));
} else {
return name;
return name;
}
},
* </ul>
*/
_splitString:function (s) {
var ret, m;
if ((m = s.match(this._static.COLUMN_REF_RE1)) !== null) {
ret = m.slice(1);
var ret, m;
if ((m = s.match(this._static.COLUMN_REF_RE1)) !== null) {
ret = m.slice(1);
}
else if ((m = s.match(this._static.COLUMN_REF_RE2)) !== null) {
else if ((m = s.match(this._static.COLUMN_REF_RE2)) !== null) {
ret = [null, m[1], m[2]];
}
else if ((m = s.match(this._static.COLUMN_REF_RE3)) !== null) {
ret = [m[1], m[2], null];
else if ((m = s.match(this._static.COLUMN_REF_RE3)) !== null) {
ret = [m[1], m[2], null];
}
else {
ret = [null, s, null];
ret = [null, s, null];
}
return ret;
return ret;
},
/**
getters:{
rowCb:function () {
return this.__rowCb;
return this.__rowCb;
},
identifierInputMethod:function () {
return this.__identifierInputMethod;
return this.__identifierInputMethod;
},
identifierOutputMethod:function () {
return this.__identifierOutputMethod;
return this.__identifierOutputMethod;
},
firstSourceAlias:function () {
var source = this.__opts.from;
if (isUndefinedOrNull(source) || !source.length) {
var source = this.__opts.from;
if (isUndefinedOrNull(source) || !source.length) {
throw new DatasetError("No source specified for the query");
}
source = source[0];
if (isInstanceOf(source, AliasedExpression)) {
source = source[0];
if (isInstanceOf(source, AliasedExpression)) {
return source.alias;
} else if (isString(source)) {
} else if (isString(source)) {
var parts = this._splitString(source);
var alias = parts[2];
return alias ? alias : source;
} else {
return source;
return source;
}
},
/**@lends patio.Dataset.prototype*/
identifierInputMethod:function (meth) {
this.__identifierInputMethod = meth;
this.__identifierInputMethod = meth;
},
identifierOutputMethod:function (meth) {
this.__identifierOutputMethod = meth;
this.__identifierOutputMethod = meth;
},
rowCb:function (cb) {
if (isFunction(cb) || isNull(cb)) {
this.__rowCb = cb;
if (isFunction(cb) || isNull(cb)) {
this.__rowCb = cb;
} else {
throw new DatasetError("rowCb mus be a function");
}
* @borrows patio.Dataset#leftJoin as leftJoin
* */
constructor: function (options, fromDb) {
if (this.synced) {
this.__emitter = new EventEmitter();
this._super(arguments);
this.patio = patio || require("./index");
fromDb = isBoolean(fromDb) ? fromDb : false;
this.__changed = {};
this.__values = {};
if (fromDb) {
if (this.synced) {
this.__emitter = new EventEmitter();
this._super(arguments);
this.patio = patio || require("./index");
fromDb = isBoolean(fromDb) ? fromDb : false;
this.__changed = {};
this.__values = {};
if (fromDb) {
this._hook("pre", "load");
this.__isNew = false;
this.__setFromDb(options, true);
this._static.emit("load", this);
}
} else {
this.__isNew = true;
this.__set(options);
this.__isNew = true;
this.__set(options);
}
} else {
throw new ModelError("Model " + this.tableName + " has not been synced");
},
__set: function (values, ignore) {
values = values || {};
this.__ignore = ignore === true;
Object.keys(values).forEach(function (attribute) {
values = values || {};
this.__ignore = ignore === true;
Object.keys(values).forEach(function (attribute) {
var value = values[attribute];
//check if the column is a constrained value and is allowed to be set
!ignore && this._checkIfColumnIsConstrained(attribute);
this[attribute] = value;
}, this);
this.__ignore = false;
this.__ignore = false;
},
__setFromDb: function (values, ignore) {
},
synced: function () {
return this._static.synced;
return this._static.synced;
}
}
* Proxy the quoteSchemaTable method to the dataset
* */
__quoteSchemaTable: function (table) {
return this.__schemaUtiltyDataset.quoteSchemaTable(table);
return this.__schemaUtiltyDataset.quoteSchemaTable(table);
},
/**
* @field
* */
__schemaUtiltyDataset: function () {
this.__schemaUtiltyDs = this.__schemaUtiltyDs || this.dataset;
return this.__schemaUtiltyDs;
this.__schemaUtiltyDs = this.__schemaUtiltyDs || this.dataset;
return this.__schemaUtiltyDs;
}
}
isString = comb.isString,
define = comb.define,
isRegExp = comb.isRegExp,
Dataset, patio;
Dataset, patio, sql, Expression, AliasedExpression, CaseExpression, Cast,
ColumnAll, BooleanExpression;
var virtualRow = function (name) {
var WILDCARD = new LiteralString('*');
var QUESTION_MARK = new LiteralString('?');
var COMMA_SEPARATOR = new LiteralString(', ');
var DOUBLE_UNDERSCORE = '__';
var parts = name.split(DOUBLE_UNDERSCORE);
var table = parts[0], column = parts[1];
var ident = column ? QualifiedIdentifier.fromArgs([table, column]) : Identifier.fromArgs([name]);
var prox = methodMissing(ident, function (m) {
var DOUBLE_UNDERSCORE = '__';
var parts = name.split(DOUBLE_UNDERSCORE);
var table = parts[0], column = parts[1];
var ident = column ? QualifiedIdentifier.fromArgs([table, column]) : Identifier.fromArgs([name]);
var prox = methodMissing(ident, function (m) {
return function () {
var args = argsToArray(arguments);
return SQLFunction.fromArgs([m, name].concat(args));
}
};
}, column ? QualifiedIdentifier : Identifier);
var ret = createFunctionWrapper(prox, function (m) {
var args = argsToArray(arguments);
if (args.length) {
return SQLFunction.fromArgs([name].concat(args));
var ret = createFunctionWrapper(prox, function (m) {
var args = argsToArray(arguments);
if (args.length) {
return SQLFunction.fromArgs([name].concat(args));
} else {
return prox;
}
}, function () {
return SQLFunction.fromArgs(arguments);
});
ret.__proto__ = ident;
return ret;
ret["__proto__"] = ident;
return ret;
};
var DATE_METHODS = ["getDate", "getDay", "getFullYear", "getHours", "getMilliseconds", "getMinutes", "getMonth", "getSeconds",
var addDateMethod = function (op) {
return function () {
return this.date[op].apply(this.date, arguments);
}
};
};
/**
*/
var DateTime = function (y, m, d, h, min, s, ms) {
var args = argsToArray(arguments);
if(args.length === 0){
if (args.length === 0) {
this.date = new Date();
}else if (isDate(y)) {
} else if (isDate(y)) {
this.date = y;
} else {
var date = new Date(1970, 0, 1, 0, 0, 0);
* @name sql
* @memberOf patio
*/
var sql = {
sql = {
/**@lends patio.sql*/
/**
*
* @return {patio.sql.Identifier|patio.sql.QualifiedIdentifier|patio.sql.AliasedExpression} an identifier generated based on the name string.
*/
identifier:function (s) {
return sql.stringToIdentifier(s);
identifier: function (s) {
return sql.stringToIdentifier(s);
},
/**
* @see patio.sql.identifier
*/
stringToIdentifier:function (name) {
!Dataset && (Dataset = require("./dataset"));
return new Dataset().stringToIdentifier(name);
stringToIdentifier: function (name) {
!Dataset && (Dataset = require("./dataset"));
return new Dataset().stringToIdentifier(name);
},
/**
* @return {patio.sql.LiteralString|patio.sql.PlaceHolderLiteralString} an expression that can be used as an argument
* for {@link patio.Dataset} query methods.
*/
literal:function (s) {
var args = argsToArray(arguments);
return args.length > 1 ? PlaceHolderLiteralString.fromArgs(args) : new LiteralString(s);
literal: function (s) {
var args = argsToArray(arguments);
return args.length > 1 ? PlaceHolderLiteralString.fromArgs(args) : new LiteralString(s);
},
/**
* sql["case"]({a:sql.b}, sql.c, sql.d); //=> (CASE t.d WHEN t.a THEN t.b ELSE t.c END)
*
*/
"case":function (hash, /*args**/opts) {
"case": function (hash, /*args**/opts) {
var args = argsToArray(arguments, 1);
return CaseExpression.fromArgs([hashToArray(hash)].concat(args));
},
* patio.sql.sqlStringJoin([sql.a, 'b']) # SQL: a || 'b'
* patio.sql.sqlStringJoin(['a', sql.b], ' '); //=> 'a' || ' ' || b
*/
sqlStringJoin:function (arr, joiner) {
sqlStringJoin: function (arr, joiner) {
joiner = joiner || null;
var args;
arr = arr.map(function (a) {
return isInstanceOf(a, Expression, LiteralString, Boolean) || isNull(a) ? a : sql.stringToIdentifier(a)
return isInstanceOf(a, Expression, LiteralString, Boolean) || isNull(a) ? a : sql.stringToIdentifier(a);
});
if (joiner) {
var newJoiner = [];
return StringExpression.fromArgs(["||"].concat(args));
},
Year:Year,
TimeStamp:TimeStamp,
Time:Time,
DateTime:DateTime,
Float:Float,
Decimal:Decimal
Year: Year,
TimeStamp: TimeStamp,
Time: Time,
DateTime: DateTime,
Float: Float,
Decimal: Decimal
};
sql.__defineGetter__("patio", function () {
sql["__defineGetter__"]("patio", function () {
!patio && (patio = require("./index"));
return patio;
});
exports.sql = methodMissing(sql, function (name) {
return virtualRow(name);
return virtualRow(name);
});
var OPERTATOR_INVERSIONS = {
AND:"OR",
OR:"AND",
GT:"lte",
GTE:"lt",
LT:"gte",
LTE:"gt",
EQ:"neq",
NEQ:"eq",
LIKE:'NOT LIKE',
"NOT LIKE":"LIKE",
'!~*':'~*',
'~*':'!~*',
"~":'!~',
"IN":'NOTIN',
"NOTIN":"IN",
"IS":'IS NOT',
"ISNOT":"IS",
NOT:"NOOP",
NOOP:"NOT",
ILIKE:'NOT ILIKE',
NOTILIKE:"ILIKE"
AND: "OR",
OR: "AND",
GT: "lte",
GTE: "lt",
LT: "gte",
LTE: "gt",
EQ: "neq",
NEQ: "eq",
LIKE: 'NOT LIKE',
"NOT LIKE": "LIKE",
'!~*': '~*',
'~*': '!~*',
"~": '!~',
"IN": 'NOTIN',
"NOTIN": "IN",
"IS": 'IS NOT',
"ISNOT": "IS",
NOT: "NOOP",
NOOP: "NOT",
ILIKE: 'NOT ILIKE',
NOTILIKE: "ILIKE"
};
// Standard mathematical operators used in +NumericMethods+
var MATHEMATICAL_OPERATORS = {PLUS:"+", MINUS:"-", DIVIDE:"/", MULTIPLY:"*"};
var MATHEMATICAL_OPERATORS = {PLUS: "+", MINUS: "-", DIVIDE: "/", MULTIPLY: "*"};
// Bitwise mathematical operators used in +NumericMethods+
var BITWISE_OPERATORS = {bitWiseAnd:"&", bitWiseOr:"|", exclusiveOr:"^", leftShift:"<<", rightShift:">>"};
var BITWISE_OPERATORS = {bitWiseAnd: "&", bitWiseOr: "|", exclusiveOr: "^", leftShift: "<<", rightShift: ">>"};
var INEQUALITY_OPERATORS = {GT:">", GTE:">=", LT:"<", LTE:"<="};
var INEQUALITY_OPERATORS = {GT: ">", GTE: ">=", LT: "<", LTE: "<="};
//Hash of ruby operator symbols to SQL operators, used in +BooleanMethods+
var BOOLEAN_OPERATORS = {AND:"AND", OR:"OR"};
var BOOLEAN_OPERATORS = {AND: "AND", OR: "OR"};
//Operators that use IN/NOT IN for inclusion/exclusion
var IN_OPERATORS = {IN:"IN", NOTIN:'NOT IN'};
var IN_OPERATORS = {IN: "IN", NOTIN: 'NOT IN'};
//Operators that use IS, used for special casing to override literal true/false values
var IS_OPERATORS = {IS:"IS", ISNOT:'IS NOT'};
var IS_OPERATORS = {IS: "IS", ISNOT: 'IS NOT'};
//Operator symbols that take exactly two arguments
var TWO_ARITY_OPERATORS = merge({
EQ:'=',
NEQ:'!=', LIKE:"LIKE",
"NOT LIKE":'NOT LIKE',
ILIKE:"ILIKE",
"NOT ILIKE":'NOT ILIKE',
"~":"~",
'!~':"!~",
'~*':"~*",
'!~*':"!~*"}, INEQUALITY_OPERATORS, BITWISE_OPERATORS, IS_OPERATORS, IN_OPERATORS);
EQ: '=',
NEQ: '!=',
LIKE: "LIKE",
"NOT LIKE": 'NOT LIKE',
ILIKE: "ILIKE",
"NOT ILIKE": 'NOT ILIKE',
"~": "~",
'!~': "!~",
'~*': "~*",
'!~*': "!~*"
}, INEQUALITY_OPERATORS, BITWISE_OPERATORS, IS_OPERATORS, IN_OPERATORS);
//Operator symbols that take one or more arguments
var N_ARITY_OPERATORS = merge({"||":"||"}, BOOLEAN_OPERATORS, MATHEMATICAL_OPERATORS);
var N_ARITY_OPERATORS = merge({"||": "||"}, BOOLEAN_OPERATORS, MATHEMATICAL_OPERATORS);
//Operator symbols that take only a single argument
var ONE_ARITY_OPERATORS = {"NOT":"NOT", "NOOP":"NOOP"};
var ONE_ARITY_OPERATORS = {"NOT": "NOT", "NOOP": "NOOP"};
/**
* @class Mixin to provide alias methods to an expression.
* @memberOf patio.sql
*/
var AliasMethods = define(null, {
instance:{
instance: {
/**@lends patio.sql.AliasMethods.prototype*/
/**
*
* @return {patio.sql.AliasedExpression} the aliased expression.
*/
as:function (alias) {
return new AliasedExpression(this, alias);
as: function (alias) {
return new AliasedExpression(this, alias);
}
}
else {
return new BooleanExpression(op, this, expression);
}
}
};
};
/**
* @memberOf patio.sql
*/
var BitWiseMethods = define(null, {
instance:{
instance: {
/**@lends patio.sql.BitWiseMethods.prototype*/
/**
* @example
* sql.a.sqlNumber.bitWiseAnd("b"); //=> "a" & "b"
*/
bitWiseAnd:bitWiseMethod("bitWiseAnd"),
bitWiseAnd: bitWiseMethod("bitWiseAnd"),
/**
* Bitwise or
* @example
* sql.a.sqlNumber.bitWiseOr("b") //=> "a" | "b"
*/
bitWiseOr:bitWiseMethod("bitWiseOr"),
bitWiseOr: bitWiseMethod("bitWiseOr"),
/**
* Exclusive Or
*
* sql.a.sqlNumber.exclusiveOr("b") //=> "a" ^ "b"
*/
exclusiveOr:bitWiseMethod("exclusiveOr"),
exclusiveOr: bitWiseMethod("exclusiveOr"),
/**
* Bitwise shift left
*
* sql.a.sqlNumber.leftShift("b") // "a" << "b"
*/
leftShift:bitWiseMethod("leftShift"),
leftShift: bitWiseMethod("leftShift"),
/**
* Bitwise shift right
*
* sql.a.sqlNumber.rightShift("b") //=> "a" >> "b"
*/
rightShift:bitWiseMethod("rightShift")
rightShift: bitWiseMethod("rightShift")
}
}).as(sql, "BitWiseMethods");
else {
return new BooleanExpression(op, this, expression);
}
}
};
};
/**
* @memberOf patio.sql
*/
var BooleanMethods = define(null, {
instance:{
instance: {
/**@lends patio.sql.BooleanMethods.prototype*/
/**
*
* @return {patio.sql.BooleanExpression} a ANDed boolean expression.
*/
and:booleanMethod("and"),
and: booleanMethod("and"),
/**
* @function
*
* @return {patio.sql.BooleanExpression} a ORed boolean expression
*/
or:booleanMethod("or"),
or: booleanMethod("or"),
/**
* Logical NOT
*
* @return {patio.sql.BooleanExpression} a inverted boolean expression.
*/
not:function () {
not: function () {
return BooleanExpression.invert(this);
}
* @memberOf patio.sql
*/
var CastMethods = define(null, {
instance:{
instance: {
/**@lends patio.sql.CastMethods.prototype*/
/**
* Cast the reciever to the given SQL type.
*
* @return {patio.sql.Cast} the casted expression
*/
cast:function (type) {
cast: function (type) {
return new Cast(this, type);
},
*
* @return {patio.sql.NumericExpression} a casted numberic expression
*/
castNumeric:function (type) {
castNumeric: function (type) {
return this.cast(type || "integer").sqlNumber;
},
*
* @return {patio.sql.StringExpression} the casted string expression
*/
castString:function (type) {
castString: function (type) {
return this.cast(type || String).sqlString;
}
}
* </pre>
*/
var ComplexExpressionMethods = define(null, {
instance:{
instance: {
/**@ignore*/
getters:{
getters: {
/**
* @ignore
*/
sqlBoolean:function () {
sqlBoolean: function () {
return new BooleanExpression("noop", this);
},
/**
* @ignore
*/
sqlFunction:function () {
sqlFunction: function () {
return new SQLFunction(this);
},
/**
* @ignore
*/
sqlNumber:function () {
sqlNumber: function () {
return new NumericExpression("noop", this);
},
/**
* @ignore
*/
sqlString:function () {
sqlString: function () {
return new StringExpression("noop", this);
}
}
var inequalityMethod = function (op) {
return function (expression) {
if (isInstanceOf(expression, BooleanExpression)
|| isBoolean(expression)
|| isNull(expression)
|| (isHash(expression))
|| isArray(expression)) {
if (isInstanceOf(expression, BooleanExpression) ||
isBoolean(expression) ||
isNull(expression) ||
(isHash(expression)) ||
isArray(expression)) {
throw new ExpressionError("Cannot apply " + op + " to a boolean expression");
} else {
return new BooleanExpression(op, this, expression);
}
}
};
};
/**
* @memberOf patio.sql
*/
var InequalityMethods = define(null, {
instance:{
instance: {
/**@lends patio.sql.InequalityMethods.prototype*/
/**
*
* @return {patio.sql.BooleanExpression}
*/
gt:inequalityMethod("gt"),
gt: inequalityMethod("gt"),
/**
* @function Creates a gte {@link patio.sql.BooleanExpression} compared to this expression.
*
*
* @return {patio.sql.BooleanExpression}
*/
gte:inequalityMethod("gte"),
gte: inequalityMethod("gte"),
/**
* @function Creates a lt {@link patio.sql.BooleanExpression} compared to this expression.
*
*
* @return {patio.sql.BooleanExpression}
*/
lt:inequalityMethod("lt"),
lt: inequalityMethod("lt"),
/**
* @function Creates a lte {@link patio.sql.BooleanExpression} compared to this expression.
*
*
* @return {patio.sql.BooleanExpression}
*/
lte:inequalityMethod("lte"),
lte: inequalityMethod("lte"),
/**
* @function Creates a eq {@link patio.sql.BooleanExpression} compared to this expression.
*
*
* @return {patio.sql.BooleanExpression}
*/
eq:inequalityMethod("eq"),
eq: inequalityMethod("eq"),
neq:inequalityMethod("neq"),
neq: inequalityMethod("neq"),
/**
* @private
*
* @return {patio.sql.BooleanExpression} a boolean expression containing the between expression.
*/
between:function (items) {
return new BooleanExpression("AND", new BooleanExpression("gte", this, items[0]), new BooleanExpression("lte", this, items[1]))
between: function (items) {
return new BooleanExpression("AND", new BooleanExpression("gte", this, items[0]), new BooleanExpression("lte", this, items[1]));
}
}
}).as(sql, "InequalityMethods");
* @memberOf patio.sql
*/
var NoBooleanInputMethods = define(null, {
instance:{
constructor:function (op) {
instance: {
constructor: function (op) {
var args = argsToArray(arguments, 1);
args.forEach(function (expression) {
if ((isInstanceOf(expression, BooleanExpression))
|| isBoolean(expression)
|| isNull(expression)
|| (isObject(expression) && !isInstanceOf(expression, Expression, Dataset, LiteralString))
|| isArray(expression)) {
if ((isInstanceOf(expression, BooleanExpression)) ||
isBoolean(expression) ||
isNull(expression) ||
(isObject(expression) && !isInstanceOf(expression, Expression, Dataset, LiteralString)) ||
isArray(expression)) {
throw new ExpressionError("Cannot apply " + op + " to a boolean expression");
}
});
} else {
return new NumericExpression(op, this, expression);
}
}
};
};
* @memberOf patio.sql
*/
var NumericMethods = define(null, {
instance:{
instance: {
/**@lends patio.sql.NumericMethods.prototype*/
*
* @return {patio.sql.NumericExpression}
*/
plus:numericMethod("plus"),
plus: numericMethod("plus"),
/**
* @function Subtracts the provided expression from this expression and returns a {@link patio.sql.NumericExpression}.
*
* @return {patio.sql.NumericExpression}
*/
minus:numericMethod("minus"),
minus: numericMethod("minus"),
/**
* @function Divides this expression by the provided expression and returns a {@link patio.sql.NumericExpression}.
*
* @return {patio.sql.NumericExpression}
*/
divide:numericMethod("divide"),
divide: numericMethod("divide"),
/**
* @function Divides this expression by the provided expression and returns a {@link patio.sql.NumericExpression}.
*
* @return {patio.sql.NumericExpression}
*/
multiply:numericMethod("multiply")
multiply: numericMethod("multiply")
}
}).as(sql, "NumericMethods");
* @memberOf patio.sql
*/
var OrderedMethods = define(null, {
instance:{
instance: {
/**@lends patio.sql.OrderedMethods.prototype*/
/**
* before other values), or "last" to use NULLS LAST (so NULL values are ordered after other values).
* @return {patio.sql.OrderedExpression}
*/
asc:function (options) {
asc: function (options) {
return new OrderedExpression(this, false, options);
},
* before other values), or "last" to use NULLS LAST (so NULL values are ordered after other values).
* @return {patio.sql.OrderedExpression}
*/
desc:function (options) {
desc: function (options) {
return new OrderedExpression(this, true, options);
}
}
* @memberOf patio.sql
*/
var QualifyingMethods = define(null, {
instance:{
instance: {
/**@lends patio.sql.QualifyingMethods.prototype*/
/**
*
* @return {patio.sql.QualifiedIdentifier}
*/
qualify:function (qualifier) {
return new QualifiedIdentifier(qualifier, this);
qualify: function (qualifier) {
return new QualifiedIdentifier(qualifier, this);
},
/**
*
* @return {patio.sql.ColumnAll}
*/
all:function () {
all: function () {
return new ColumnAll(this);
}
* @memberOf patio.sql
*/
var StringMethods = define(null, {
instance:{
instance: {
/**@lends patio.sql.StringMethods.prototype*/
/**
*
* @return {patio.sql.BooleanExpression}
*/
ilike:function (expression) {
ilike: function (expression) {
expression = argsToArray(arguments);
return StringExpression.like.apply(StringExpression, [this].concat(expression).concat([
{caseInsensitive:true}
{caseInsensitive: true}
]));
},
*
* @param expression
*/
like:function (expression) {
like: function (expression) {
expression = argsToArray(arguments);
return StringExpression.like.apply(StringExpression, [this].concat(expression));
}
* @memberOf patio.sql
*/
var StringConcatenationMethods = define(null, {
instance:{
instance: {
/**@lends patio.sql.StringConcatenationMethods.prototype*/
/**
*
* @param expression expression to concatenate this expression with.
*/
concat:function (expression) {
concat: function (expression) {
return new StringExpression("||", this, expression);
}
}
* @memberOf patio.sql
*/
var SubscriptMethods = define(null, {
instance:{
instance: {
/**
* Return a {@link patio.sql.Subscript} with the given arguments, representing an
*
* @param subscript
*/
sqlSubscript:function (subscript) {
sqlSubscript: function (subscript) {
var args = argsToArray(arguments);
return new SubScript(this, flatten(args));
}
* @name Expression
* @memberOf patio.sql
*/
var Expression = define(null, {
Expression = define(null, {
instance:{
instance: {
/**@lends patio.sql.Expression.prototype*/
/**
* @param {patio.Dataset} ds the dataset that will be used to SQL-ify this expression.
* @return {String} a string literal version of this expression.
*/
sqlLiteral:function (ds) {
sqlLiteral: function (ds) {
return this.toString(ds);
}
},
static:{
static: {
/**@lends patio.sql.Expression*/
/**
*
* @return {patio.sql.Expression} an expression.
*/
fromArgs:function (args) {
var ret;
try {
ret = new this();
fromArgs: function (args) {
var ret, Self = this;
try {
ret = new Self();
} catch (ignore) {
}
this.apply(ret, args);
return ret;
this.apply(ret, args);
return ret;
},
/**
* @param {*} obj object to test if it is a condition specifier
* @return {Boolean} true if the object is a Hash or is an array of two element arrays.
*/
isConditionSpecifier:function (obj) {
return isHash(obj) || (isArray(obj) && obj.length && obj.every(function (i) {
return isArray(i) && i.length === 2;
isConditionSpecifier: function (obj) {
return isHash(obj) || (isArray(obj) && obj.length && obj.every(function (i) {
return isArray(i) && i.length === 2;
}));
}
}
var GenericExpression = define([Expression, AliasMethods, BooleanMethods, CastMethods, ComplexExpressionMethods, InequalityMethods, NumericMethods, OrderedMethods, StringMethods, SubscriptMethods]).as(sql, "GenericExpression");
var AliasedExpression = define(Expression, {
instance:{
AliasedExpression = define(Expression, {
instance: {
/**@lends patio.sql.AliasedExpression.prototype*/
/**
* @property alias the alias of the expression
*
*/
constructor:function (expression, alias) {
this.expression = expression;
this.alias = alias;
constructor: function (expression, alias) {
this.expression = expression;
this.alias = alias;
},
/**
*
* @return String the SQL alias fragment.
*/
toString:function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.aliasedExpressionSql(this);
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.aliasedExpressionSql(this);
}
}
}
).as(sql, "AliasedExpression");
var CaseExpression = define(GenericExpression, {
instance:{
CaseExpression = define(GenericExpression, {
instance: {
/**@lends patio.sql.CaseExpression.prototype*/
/**
* @property expression the expression of the {@link patio.sql.CaseExpression}.
* @property {Boolean} noExpression true if this {@link patio.sql.CaseExpression}'s expression is undefined.
*/
constructor:function (conditions, def, expression) {
constructor: function (conditions, def, expression) {
if (Expression.isConditionSpecifier(conditions)) {
this.conditions = toArray(conditions);
this.def = def;
*
* @return String the SQL case expression fragment.
*/
toString:function (ds) {
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.caseExpressionSql(this);
},
/**@ignore*/
getters:{
getters: {
/**@ignore*/
hasExpression:function () {
hasExpression: function () {
return !this.noExpression;
}
}
}).as(sql, "CaseExpression");
var Cast = define(GenericExpression, {
instance:{
Cast = define(GenericExpression, {
instance: {
/**@lends patio.sql.Cast*/
/**
* @property expr the expression to CAST.
* @property type the type to CAST the expression to.
*/
constructor:function (expr, type) {
constructor: function (expr, type) {
this.expr = expr;
this.type = type;
},
*
* @return String the SQL cast expression fragment.
*/
toString:function (ds) {
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.castSql(this.expr, this.type);
}).as(sql, "Cast");
var ColumnAll = define(Expression, {
instance:{
ColumnAll = define(Expression, {
instance: {
/**@lends patio.sql.ColumnAll.prototype*/
/**
*
* @property table the table this all column expression represents.
*/
constructor:function (table) {
constructor: function (table) {
this.table = table;
},
*
* @return String the SQL columnAll expression fragment.
*/
toString:function (ds) {
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.columnAllSql(this);
}).as(sql, "ColumnAll");
var ComplexExpression = define([Expression, AliasMethods, CastMethods, OrderedMethods, SubscriptMethods], {
instance:{
instance: {
/**@lends patio.sql.ComplexExpression.prototype*/
/**
* other than the second arg for an IN/NOT IN operator.</li>
* </p>
*/
constructor:function (op) {
if (op) {
var args = argsToArray(arguments,1 );
constructor: function (op) {
if (op) {
var args = argsToArray(arguments, 1);
//make a copy of the args
var origArgs = args.slice(0);
args.forEach(function (a, i) {
if (Expression.isConditionSpecifier(a)) {
var origArgs = args.slice(0);
args.forEach(function (a, i) {
if (Expression.isConditionSpecifier(a)) {
args[i] = BooleanExpression.fromValuePairs(a);
}
});
op = op.toUpperCase();
op = op.toUpperCase();
if (N_ARITY_OPERATORS.hasOwnProperty(op)) {
if (args.length < 1) {
throw new ExpressionError("The " + op + " operator requires at least 1 argument")
if (N_ARITY_OPERATORS.hasOwnProperty(op)) {
if (args.length < 1) {
throw new ExpressionError("The " + op + " operator requires at least 1 argument");
}
var oldArgs = args.slice(0);
args = [];
oldArgs.forEach(function (a) {
a instanceof ComplexExpression && a.op == op ? args = args.concat(a.args) : args.push(a);
var oldArgs = args.slice(0);
args = [];
oldArgs.forEach(function (a) {
a instanceof ComplexExpression && a.op === op ? args = args.concat(a.args) : args.push(a);
});
} else if (TWO_ARITY_OPERATORS.hasOwnProperty(op)) {
if (args.length != 2) {
} else if (TWO_ARITY_OPERATORS.hasOwnProperty(op)) {
if (args.length !== 2) {
throw new ExpressionError("The " + op + " operator requires precisely 2 arguments");
}
//With IN/NOT IN, even if the second argument is an array of two element arrays,
//don't convert it into a boolean expression, since it's definitely being used
//as a value list.
if (IN_OPERATORS[op]) {
args[1] = origArgs[1]
if (IN_OPERATORS[op]) {
args[1] = origArgs[1];
}
} else if (ONE_ARITY_OPERATORS.hasOwnProperty(op)) {
if (args.length != 1) {
if (args.length !== 1) {
throw new ExpressionError("The " + op + " operator requires only one argument");
}
} else {
throw new ExpressionError("Invalid operator " + op);
}
this.op = op;
this.args = args;
this.op = op;
this.args = args;
}
},
*
* @return String the SQL version of the {@link patio.sql.ComplexExpression}.
*/
toString:function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.complexExpressionSql(this.op, this.args);
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.complexExpressionSql(this.op, this.args);
}
},
static:{
static: {
/**@lends patio.sql.ComplexExpression*/
/**
* NOTILIKE:"ILIKE"
* }
*/
OPERATOR_INVERSIONS:OPERTATOR_INVERSIONS,
OPERATOR_INVERSIONS: OPERTATOR_INVERSIONS,
/**
* Default mathematical operators.
* @type Object
* @default {PLUS:"+", MINUS:"-", DIVIDE:"/", MULTIPLY:"*"}
*/
MATHEMATICAL_OPERATORS:MATHEMATICAL_OPERATORS,
MATHEMATICAL_OPERATORS: MATHEMATICAL_OPERATORS,
/**
* Default bitwise operators.
* @type Object
* @default {bitWiseAnd:"&", bitWiseOr:"|", exclusiveOr:"^", leftShift:"<<", rightShift:">>"}
*/
BITWISE_OPERATORS:BITWISE_OPERATORS,
BITWISE_OPERATORS: BITWISE_OPERATORS,
/**
* Default inequality operators.
*
* @type Object
* @default {GT:">",GTE:">=",LT:"<",LTE:"<="}
*/
INEQUALITY_OPERATORS:INEQUALITY_OPERATORS,
INEQUALITY_OPERATORS: INEQUALITY_OPERATORS,
/**
* Default boolean operators.
* @type Object
* @default {AND:"AND",OR:"OR"}
*/
BOOLEAN_OPERATORS:BOOLEAN_OPERATORS,
BOOLEAN_OPERATORS: BOOLEAN_OPERATORS,
/**
* Default IN operators.
* @type Object
* @default {IN:"IN",NOTIN:'NOT IN'}
*/
IN_OPERATORS:IN_OPERATORS,
IN_OPERATORS: IN_OPERATORS,
/**
* Default IS operators.
*
* @type Object
* @default {IS:"IS", ISNOT:'IS NOT'}
*/
IS_OPERATORS:IS_OPERATORS,
IS_OPERATORS: IS_OPERATORS,
/**
* Default two arity operators.
*
* NOTIN:'NOT IN'
* }
*/
TWO_ARITY_OPERATORS:TWO_ARITY_OPERATORS,
TWO_ARITY_OPERATORS: TWO_ARITY_OPERATORS,
/**
* Default N(multi) arity operators.
* DIVIDE:"/", MULTIPLY:"*"
* }
*/
N_ARITY_OPERATORS:N_ARITY_OPERATORS,
N_ARITY_OPERATORS: N_ARITY_OPERATORS,
/**
* Default ONE operators.
* "NOOP":"NOOP"
* }
*/
ONE_ARITY_OPERATORS:ONE_ARITY_OPERATORS
ONE_ARITY_OPERATORS: ONE_ARITY_OPERATORS
}
}).as(sql, "ComplexExpression");
* @name BooleanExpression
* @memberOf patio.sql
*/
var BooleanExpression = define([ComplexExpression, BooleanMethods], {
static:{
BooleanExpression = define([ComplexExpression, BooleanMethods], {
static: {
/**@lends patio.sql.BooleanExpression*/
/**
*
* @return {patio.sql.BooleanExpression} the inverted expression.
*/
invert:function (expression) {
if (isInstanceOf(expression, BooleanExpression)) {
var op = expression.op, newArgs;
if (op == "AND" || op == "OR") {
invert: 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);
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]));
* </pre>
* @return {patio.sql.BooleanExpression} expression composed of sub expressions built from the hash.
*/
fromValuePairs: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));
fromValuePairs: 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)) {
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(function (i) {
return isString(i) ? sql.stringToIdentifier(i) : i
return isString(i) ? sql.stringToIdentifier(i) : i;
}) : isString(k) ? sql.stringToIdentifier(k) : k;
ret = new BooleanExpression("IN", k, v);
} else if (isInstanceOf(v, NegativeBooleanConstant)) {
} else if (isInstanceOf(v, NegativeBooleanConstant)) {
ret = new BooleanExpression("ISNOT", k, v.constant);
} else if (isInstanceOf(v, BooleanConstant)) {
} 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);
} else if (isRegExp(v)) {
ret = StringExpression.like(sql.stringToIdentifier(k), v);
} 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);
ret = new BooleanExpression("EQ", sql.stringToIdentifier(k), v);
}
negate && (ret = BooleanExpression.invert(ret));
pairArr.push(ret);
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));
return pairArr.length == 1 ? pairArr[0] : BooleanExpression.fromArgs([op].concat(pairArr));
},
/**
*
* @return {patio.sql.Expression} an expression to use in the filter
*/
__filterObject:function (expr, key) {
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));
} else if (key && (twoArityOperators[k.toUpperCase()] || k.match(/between/i))) {
__filterObject: function (expr, key, op) {
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) {
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);
return this.__filterObject(expr, k, op);
}, this));
} else {
newKey = [sql.stringToIdentifier(newKey[0])];
if (k.match(/^like$/)) {
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$/)) {
} 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)) {
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());
//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));
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]);
newKey = k.split(",");
if (newKey.length == 1) {
newKey = sql.stringToIdentifier(newKey[0]);
}
opts = [
opts = [
[newKey, v]
];
pairs.push(BooleanExpression.fromValuePairs(opts));
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(["AND"].concat(pairs));
return pairs.length == 1 ? pairs[0] : BooleanExpression.fromArgs([op || "AND"].concat(pairs));
}
}
}).as(sql, "BooleanExpression");
var Constant = define(GenericExpression, {
instance:{
instance: {
/**@lends patio.sql.Constant.prototype*/
/**
* Represents constants or psuedo-constants (e.g.'CURRENT_DATE) in SQL.
* @augments patio.sql.GenericExpression
* @property {String} constant <b>READ ONLY</b> the contant.
*/
constructor:function (constant) {
constructor: function (constant) {
this.__constant = constant;
},
*
* @return String the SQL version of the {@link patio.sql.Constant}.
*/
toString:function (ds) {
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.constantSql(this.__constant);
},
getters:{
constant:function () {
getters: {
constant: function () {
return this.__constant;
}
}
* @memberOf patio.sql
*/
var BooleanConstant = define(Constant, {
instance:{
instance: {
/**@lends patio.sql.BooleanConstant.prototype*/
/**
*
* @return String the SQL version of the {@link patio.sql.BooleanConstant}.
*/
toString:function (ds) {
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.booleanConstantSql(this.__constant);
* @memberOf patio.sql
*/
var NegativeBooleanConstant = define(BooleanConstant, {
instance:{
instance: {
/**@lends patio.sql.NegativeBooleanConstant.prototype*/
/**
*
* @return String the SQL version of the {@link patio.sql.NegativeBooleanConstant}.
*/
toString:function (ds) {
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.negativeBooleanConstantSql(this.__constant);
* Constant for CURRENT DATE
* @type patio.sql.Constant
*/
CURRENT_DATE:new Constant("CURRENT_DATE"),
CURRENT_DATE: new Constant("CURRENT_DATE"),
/**
* Constant for CURRENT TIME
* @type patio.sql.Constant
*/
CURRENT_TIME:new Constant("CURRENT_TIME"),
CURRENT_TIME: new Constant("CURRENT_TIME"),
/**
* Constant for CURRENT TIMESTAMP
* @type patio.sql.Constant
*/
CURRENT_TIMESTAMP:new Constant("CURRENT_TIMESTAMP"),
CURRENT_TIMESTAMP: new Constant("CURRENT_TIMESTAMP"),
/**
* Constant for TRUE
* @type patio.sql.BooleanConstant
*/
SQLTRUE:new BooleanConstant(1),
SQLTRUE: new BooleanConstant(1),
/**
* Constant for TRUE
* @type patio.sql.BooleanConstant
*/
TRUE:new BooleanConstant(1),
TRUE: new BooleanConstant(1),
/**
* Constant for FALSE.
* @type patio.sql.BooleanConstant
*/
SQLFALSE:new BooleanConstant(0),
SQLFALSE: new BooleanConstant(0),
/**
* Constant for FALSE
* @type patio.sql.BooleanConstant
*/
FALSE:new BooleanConstant(0),
FALSE: new BooleanConstant(0),
/**
* Constant for NULL
* @type patio.sql.BooleanConstant
*/
NULL:new BooleanConstant(null),
NULL: new BooleanConstant(null),
/**
* Constant for NOT NULL
* @type patio.sql.NegativeBooleanConstant
*/
NOTNULL:new NegativeBooleanConstant(null)
NOTNULL: new NegativeBooleanConstant(null)
};
var Constants = sql.Constants
var Identifier = define([GenericExpression, QualifyingMethods], {
instance:{
instance: {
/**@lends patio.sql.Identifier.prototype*/
/**
*
* @property {String} value <b>READ ONLY</b> the column or table this identifier represents.
*/
constructor:function (value) {
this.__value = value;
constructor: function (value) {
this.__value = value;
},
/**
*
* @return String the SQL version of the {@link patio.sql.Identifier}.
*/
toString:function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.quoteIdentifier(this);
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.quoteIdentifier(this);
},
/**@ignore*/
getters:{
value:function () {
return this.__value;
getters: {
value: function () {
return this.__value;
}
}
}
}).as(sql, "Identifier");
var JoinClause = define(Expression, {
instance:{
instance: {
/**@lends patio.sql.JoinClause.prototype*/
/**
* @property table <b>READ ONLY</b> the table to join with
* @property joinType <b>READ ONLY</b> the alias to use for this join clause
* */
constructor:function (joinType, table, tableAlias) {
this.__joinType = joinType;
this.__table = table;
this.__tableAlias = tableAlias || null;
constructor: function (joinType, table, tableAlias) {
this.__joinType = joinType;
this.__table = table;
this.__tableAlias = tableAlias || null;
},
/**
*
* @return String the SQL version of the {@link patio.sql.JoinClause}.
*/
toString:function (ds) {
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.joinClauseSql(this);
},
/**@ignore*/
getters:{
joinType:function () {
return this.__joinType;
getters: {
joinType: function () {
return this.__joinType;
},
table:function () {
return this.__table;
table: function () {
return this.__table;
},
tableAlias:function () {
return this.__tableAlias;
tableAlias: function () {
return this.__tableAlias;
}
}
}
var JoinOnClause = define(JoinClause, {
instance:{
instance: {
/**@lends patio.sql.JoinOnClause.prototype*/
/**
* Represents an SQL JOIN clause with ON conditions. Created by {@link patio.Dataset} join methods.
* @param on the expression to filter with. See {@link patio.Dataset#filter}
* @property on <b>READ ONLY</b> the filter to use with joining the datasets.
*/
constructor:function (on, joinType, table, tableAlias) {
this.__on = on;
this._super(arguments, [joinType, table, tableAlias]);
constructor: function (on, joinType, table, tableAlias) {
this.__on = on;
this._super(arguments, [joinType, table, tableAlias]);
},
/**
*
* @return String the SQL version of the {@link patio.sql.JoinOnClause}.
*/
toString:function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.joinOnClauseSql(this);
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.joinOnClauseSql(this);
},
/**@ignore*/
getters:{
on:function () {
return this.__on;
getters: {
on: function () {
return this.__on;
}
}
}
var JoinUsingClause = define(JoinClause, {
instance:{
instance: {
/**@lends patio.sql.JoinUsingClause.prototype*/
/**
* @param using the column/s to use when joining.
* @property using <b>READ ONLY</b> the column/s to use when joining.
*/
constructor:function (using, joinType, table, tableAlias) {
constructor: function (using, joinType, table, tableAlias) {
this.__using = using.map(function (u) {
return isString(u) ? new Identifier(u) : u;
});
*
* @return String the SQL version of the {@link patio.sql.JoinUsingClause}.
*/
toString:function (ds) {
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.joinUsingClauseSql(this);
},
/**@ignore*/
getters:{
using:function () {
getters: {
using: function () {
return this.__using;
}
}
var PlaceHolderLiteralString = define(GenericExpression, {
instance:{
instance: {
/**@lends patio.sql.PlaceHolderLiteralString.prototype*/
/**
* replaced in the string.
* @property {String} parens <b>READ ONLY</b> set to true to wrap the string in parens.
*/
constructor:function (str, args, parens) {
parens = parens || false;
var v;
this.__str = str;
this.__args = isArray(args) && args.length == 1 && isHash((v = args[0])) ? v : args;
this.__parens = parens;
constructor: function (str, args, parens) {
parens = parens || false;
var v;
this.__str = str;
this.__args = isArray(args) && args.length == 1 && isHash((v = args[0])) ? v : args;
this.__parens = parens;
},
/**
*
* @return String the SQL version of the {@link patio.sql.PlaceHolderLiteralString}.
*/
toString:function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.placeholderLiteralStringSql(this);
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.placeholderLiteralStringSql(this);
},
/**@ignore*/
getters:{
str:function () {
return this.__str;
getters: {
str: function () {
return this.__str;
},
args:function () {
return this.__args;
args: function () {
return this.__args;
},
parens:function () {
return this.__parens;
parens: function () {
return this.__parens;
}
}
var SQLFunction = define(GenericExpression, {
instance:{
instance: {
/**@lends patio.sql.SQLFunction.prototype*/
/**
* @property {Array} args <b>READ ONLY</b> args arguments will be literalized through
* {@link patio.Dataset#literal} and placed into the SQL function call.
* */
constructor:function (f) {
var args = argsToArray(arguments).slice(1);
this.__f = isInstanceOf(f, Identifier) ? f.value : f, this.__args = args.map(function (a) {
return isString(a) ? sql.stringToIdentifier(a) : a;
constructor: function (f) {
var args = argsToArray(arguments).slice(1);
this.__f = isInstanceOf(f, Identifier) ? f.value : f, this.__args = args.map(function (a) {
return isString(a) ? sql.stringToIdentifier(a) : a;
});
},
*
* @return String the SQL version of the {@link patio.sql.SQLFunction}.
*/
toString:function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.functionSql(this);
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.functionSql(this);
},
/**@ignore*/
getters:{
f:function () {
return this.__f;
getters: {
f: function () {
return this.__f;
},
args:function () {
return this.__args;
args: function () {
return this.__args;
}
}
}
var OrderedExpression = define(Expression, {
instance:{
instance: {
/**@lends patio.sql.OrderedExpression.prototype*/
/**
* @property {String} [nulls=null] if value is "first" the null values will be first, if "last" then null values
* will be last
*/
constructor:function (expression, descending, opts) {
constructor: function (expression, descending, opts) {
descending = isBoolean(descending) ? descending : true;
opts = opts || {};
this.__expression = expression;
/**
* @return {patio.sql.OrderedExpression} a copy that is ordered ASC
*/
asc:function () {
return new OrderedExpression(this.__expression, false, {nulls:this.__nulls});
asc: function () {
return new OrderedExpression(this.__expression, false, {nulls: this.__nulls});
},
/**
* @return {patio.sql.OrderedExpression} Return a copy that is ordered DESC
*/
desc:function () {
return new OrderedExpression(this.__expression, true, {nulls:this.__nulls});
desc: function () {
return new OrderedExpression(this.__expression, true, {nulls: this.__nulls});
},
/**
* * @return {patio.sql.OrderedExpression} an inverted expression, changing ASC to DESC and NULLS FIRST to NULLS LAST.
* */
invert:function () {
return new OrderedExpression(this.__expression, !this.__descending, {nulls:this._static.INVERT_NULLS[this.__nulls] || this.__nulls});
invert: function () {
return new OrderedExpression(this.__expression, !this.__descending, {nulls: this._static.INVERT_NULLS[this.__nulls] || this.__nulls});
},
/**
*
* @return String the SQL version of the {@link patio.sql.OrderedExpression}.
*/
toString:function (ds) {
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.orderedExpressionSql(this);
},
/**@ignore*/
getters:{
expression:function () {
getters: {
expression: function () {
return this.__expression;
},
descending:function () {
descending: function () {
return this.__descending;
},
nulls:function () {
nulls: function () {
return this.__nulls;
}
}
},
static:{
static: {
/**@lends patio.sql.OrderedExpression*/
/**
* Hash that contains the inversions for "first" and "last".
* @type Object
* @default {first:"last", last:"first"}
*/
INVERT_NULLS:{first:"last", last:"first"}
INVERT_NULLS: {first: "last", last: "first"}
}
}).as(sql, "OrderedExpression");
var QualifiedIdentifier = define([GenericExpression, QualifyingMethods], {
instance:{
instance: {
/**@lends patio.sql.QualifiedIdentifier.prototype*/
/**
* @property table <b>READ ONLY</b> the table or schema to qualify the column or table to.
* @property column <b>READ ONLY</b> he column or table to qualify.
*/
constructor:function (table, column) {
this.__table = table;
this.__column = column;
constructor: function (table, column) {
this.__table = table;
this.__column = column;
},
/**
*
* @return String the SQL version of the {@link patio.sql.QualifiedIdentifier}.
*/
toString:function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.qualifiedIdentifierSql(this);
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.qualifiedIdentifierSql(this);
},
/**@ignore*/
getters:{
table:function () {
return this.__table;
getters: {
table: function () {
return this.__table;
},
column:function () {
return this.__column;
column: function () {
return this.__column;
}
}
}
var likeElement = function (re) {
var ret;
if (isRegExp(re)) {
ret = [("" + re).replace(/^\/|\/$|\/[i|m|g]*$/g, ""), true, re.ignoreCase]
var ret;
if (isRegExp(re)) {
ret = [("" + re).replace(/^\/|\/$|\/[i|m|g]*$/g, ""), true, re.ignoreCase]
} else {
ret = [re, false, false];
ret = [re, false, false];
}
return ret;
return ret;
};
/**
* @class Subclass of {@link patio.sql.ComplexExpression} where the expression results
* @memberOf patio.sql
*/
var StringExpression = define([ComplexExpression, StringMethods, StringConcatenationMethods, InequalityMethods, NoBooleanInputMethods], {
static:{
static: {
/**@lends patio.sql.StringExpression*/
/**
* StringExpression.like(sql.a, 'a%', {caseInsensitive : true}) //=> "a" ILIKE 'a%'
* StringExpression.like(sql.a, 'a%', /^a/i) //=> "a" LIKE 'a%' OR "a" ~* '^a'
*/
like:function (l) {
var args = argsToArray(arguments, 1);
var params = likeElement(l);
var likeMap = this.likeMap;
var lh = params[0], lre = params[1], lci = params[2];
var last = args[args.length - 1];
lci = (isHash(last) ? args.pop() : {})["caseInsensitive"] ? true : lci;
args = args.map(function (ce) {
var r, rre, rci;
var ceArr = likeElement(ce);
r = ceArr[0], rre = ceArr[1], rci = ceArr[2];
return new BooleanExpression(likeMap["" + (lre || rre) + (lci || rci)], l, r)
like: function (l) {
var args = argsToArray(arguments, 1);
var params = likeElement(l);
var likeMap = this.likeMap;
var lh = params[0], lre = params[1], lci = params[2];
var last = args[args.length - 1];
lci = (isHash(last) ? args.pop() : {})["caseInsensitive"] ? true : lci;
args = args.map(function (ce) {
var r, rre, rci;
var ceArr = likeElement(ce);
r = ceArr[0], rre = ceArr[1], rci = ceArr[2];
return new BooleanExpression(likeMap["" + (lre || rre) + (lci || rci)], l, r)
}, this);
return args.length == 1 ? args[0] : BooleanExpression.fromArgs(["OR"].concat(args));
return args.length == 1 ? args[0] : BooleanExpression.fromArgs(["OR"].concat(args));
},
/**
* LIKE expression.
* @type Object
*/
likeMap:{"truetrue":'~*', "truefalse":"~", "falsetrue":"ILIKE", "falsefalse":"LIKE"}
likeMap: {"truetrue": '~*', "truefalse": "~", "falsetrue": "ILIKE", "falsefalse": "LIKE"}
}
}).as(sql, "StringExpression");
var SubScript = define(GenericExpression, {
instance:{
instance: {
/**@lends patio.sql.SubScript.prototype*/
/**
* @param arrCol the SQL array column
* @param sub The array of subscripts to use (should be an array of numbers)
*/
constructor:function (arrCol, sub) {
constructor: function (arrCol, sub) {
//The SQL array column
this.__arrCol = arrCol;
//The array of subscripts to use (should be an array of numbers)
* Create a new {@link patio.sql.Subscript} appending the given subscript(s)
* the the current array of subscripts.
*/
addSub:function (sub) {
addSub: function (sub) {
return new SubScript(this.__arrCol, this.__sub.concat(sub));
},
*
* @return String the SQL version of the {@link patio.sql.SubScript}.
*/
toString:function (ds) {
toString: function (ds) {
!Dataset && (Dataset = require("./dataset"));
ds = ds || new Dataset();
return ds.subscriptSql(this);
},
/**@ignore*/
getters:{
f:function () {
getters: {
f: function () {
return this.__arrCol;
},
sub:function () {
sub: function () {
return this.__sub;
}
}
var addStringMethod = function (op) {
return function () {
return this.__str[op].apply(this.__str, arguments);
return this.__str[op].apply(this.__str, arguments);
}
};
var LiteralString = define([OrderedMethods, ComplexExpressionMethods, BooleanMethods, NumericMethods, StringMethods, InequalityMethods, AliasMethods], {
instance:{
instance: {
/**@lends patio.sql.LiteralString*/
/**
*
* @param {String} str the literal string.
*/
constructor:function (str) {
this.__str = str;
constructor: function (str) {
this.__str = str;
}
}
}).as(sql, "LiteralString");
if (!isFunction(this.schemaParseTable)) {
throw new Error("Schema parsing is not implemented on this database");
}
var ret = new Promise();
opts = opts || {};
var schemaParts = this.__schemaAndTable(table);
var sch = schemaParts[0], tableName = schemaParts[1];
if (opts.reload) {
delete this.schemas[quotedName];
}
if (this.schemas[quotedName]) {
ret = this.schemas[quotedName];
} else {
var self = this;
ret = this.schemas[quotedName] = this.schemaParseTable(tableName, opts).chain(function (cols) {
if (!cols || cols.length === 0) {
throw new Error("Error parsing schema, " + table + " no columns returns, table probably doesnt exist")
} else {
var schema = {};
cols.forEach(function (c) {
var name = c[0];
c = c[1];
c.jsDefault = self.__columnSchemaToJsDefault(c["default"], c.type);
schema[name] = c;
});
return schema;
}
});
}
return ret.promise();
var self = this;
return this.schemaParseTable(tableName, opts).chain(function (cols) {
if (!cols || cols.length === 0) {
throw new Error("Error parsing schema, " + table + " no columns returns, table probably doesnt exist")
} else {
var schema = {};
cols.forEach(function (c) {
var name = c[0];
c = c[1];
c.jsDefault = self.__columnSchemaToJsDefault(c["default"], c.type);
schema[name] = c;
});
return schema;
}
});
},
/**
*/
removeCachedSchema: function (table) {
if (this.schemas && !isEmpty(this.schemas)) {
delete this.schemas[this.__quoteSchemaTable(table)];
delete this.schemas[this.__quoteSchemaTable(table)];
}
},
},
_getConnection: function () {
return this.pool.getConnection();
return this.pool.getConnection();
},
_returnConnection: function (conn) {
if (!this.alreadyInTransaction(conn)) {
this.pool.returnConnection(conn);
if (!this.alreadyInTransaction(conn)) {
this.pool.returnConnection(conn);
}
},
//Convert the given default, which should be a database specific string, into
//a javascript object.
__columnSchemaToJsDefault: function (def, type) {
if (isNull(def) || isUndefined(def)) {
return null;
if (isNull(def) || isUndefined(def)) {
return null;
}
var origDefault = def, m, datePattern, dateTimePattern, timeStampPattern, timePattern;
if (this.type === "postgres" && (m = def.match(this.POSTGRES_DEFAULT_RE)) !== null) {
var origDefault = def, m, datePattern, dateTimePattern, timeStampPattern, timePattern;
if (this.type === "postgres" && (m = def.match(this.POSTGRES_DEFAULT_RE)) !== null) {
def = m[1] || m[2];
dateTimePattern = this.POSTGRES_DATE_TIME_PATTERN;
timePattern = this.POSTGRES_TIME_PATTERN;
}
if (this.type === "mssql" && (m = def.match(this.MSSQL_DEFAULT_RE)) !== null) {
if (this.type === "mssql" && (m = def.match(this.MSSQL_DEFAULT_RE)) !== null) {
def = m[1] || m[2];
}
if (["string", "blob", "date", "datetime", "year", "timestamp", "time", "enum"].indexOf(type) !== -1) {
if (["string", "blob", "date", "datetime", "year", "timestamp", "time", "enum"].indexOf(type) !== -1) {
if (this.type === "mysql") {
if (["date", "datetime", "time", "timestamp"].indexOf(type) !== -1 && def.match(this.MYSQL_TIMESTAMP_RE)) {
return null;
}
def = m[1].replace("''", "'");
}
var ret = null;
try {
switch (type) {
var ret = null;
try {
switch (type) {
case "boolean":
if (def.match(/[f0]/i)) {
ret = false;
ret = def;
break;
case "integer":
ret = parseInt(def, 10);
if (isNaN(ret)) {
ret = null;
ret = parseInt(def, 10);
if (isNaN(ret)) {
ret = null;
}
break;
break;
case "float":
case "decimal":
ret = parseFloat(def, 10);
}
} catch (e) {
}
return ret;
return ret;
},
/**
* @private
*/
schemaColumnType: function (dbType) {
var ret = dbType, m;
if (dbType.match(/^interval$/i)) {
var ret = dbType, m;
if (dbType.match(/^interval$/i)) {
ret = "interval";
} else if (dbType.match(/^(character( varying)?|n?(var)?char)/i)) {
ret = "string";
} else if (dbType.match(/^int(eger)?|(big|small|tiny)int/i)) {
ret = "integer";
} else if (dbType.match(/^date$/i)) {
ret = "date";
} else if (dbType.match(/^year/i)) {
} else if (dbType.match(/^(character( varying)?|n?(var)?char)/i)) {
ret = "string";
} else if (dbType.match(/^int(eger)?|(big|small|tiny)int/i)) {
ret = "integer";
} else if (dbType.match(/^date$/i)) {
ret = "date";
} else if (dbType.match(/^year/i)) {
ret = "year";
} else if (dbType.match(/^((small)?datetime|timestamp( with(out)? time zone)?)$/i)) {
} else if (dbType.match(/^((small)?datetime|timestamp( with(out)? time zone)?)$/i)) {
ret = "datetime";
} else if (dbType.match(/^time( with(out)? timezone)?$/i)) {
} else if (dbType.match(/^time( with(out)? timezone)?$/i)) {
ret = "time";
} else if (dbType.match(/^(bit|boolean)$/i)) {
} else if (dbType.match(/^(bit|boolean)$/i)) {
ret = "boolean";
} else if (dbType.match(/^(real|float|double( precision)?)$/i)) {
} else if (dbType.match(/^(real|float|double( precision)?)$/i)) {
ret = "float";
} else if ((m = dbType.match(/^(?:(?:(?:num(?:ber|eric)?|decimal|double)(?:\(\d+,\s*(\d+)\))?)|(?:small)?money)/i))) {
ret = m[1] && m[1] === '0' ? "integer" : "decimal";
} else if (dbType.match(/n?text/i)) {
ret = "text";
} else if (dbType.match(/bytea|[bc]lob|image|(var)?binary/i)) {
ret = "blob";
} else if (dbType.match(/^enum/i)) {
ret = "enum";
} else if ((m = dbType.match(/^(?:(?:(?:num(?:ber|eric)?|decimal|double)(?:\(\d+,\s*(\d+)\))?)|(?:small)?money)/i))) {
ret = m[1] && m[1] === '0' ? "integer" : "decimal";
} else if (dbType.match(/n?text/i)) {
ret = "text";
} else if (dbType.match(/bytea|[bc]lob|image|(var)?binary/i)) {
ret = "blob";
} else if (dbType.match(/^enum/i)) {
ret = "enum";
} else if (dbType.match(/^set/i)) {
ret = "set";
}
return ret;
return ret;
},
/**
* @return {Boolean} true if this dabase is currently in a transaction.
*/
alreadyInTransaction: function (conn, opts) {
opts = opts || {};
return this.__transactions.indexOf(conn) !== -1 && (!this.supportsSavepoints || !opts.savepoint);
opts = opts || {};
return this.__transactions.indexOf(conn) !== -1 && (!this.supportsSavepoints || !opts.savepoint);
},
/**@ignore*/
* @type Function
*/
outputIdentifierFunc: function () {
var ds = this.dataset;
return function (ident) {
return ds.outputIdentifier(ident);
var ds = this.dataset;
return function (ident) {
return ds.outputIdentifier(ident);
};
},
* @type Function
*/
inputIdentifierFunc: function () {
var ds = this.dataset;
return function (ident) {
return ds.inputIdentifier(ident);
var ds = this.dataset;
return function (ident) {
return ds.inputIdentifier(ident);
};
},
* @type patio.Dataset
*/
metadataDataset: function () {
if (this.__metadataDataset) {
return this.__metadataDataset;
if (this.__metadataDataset) {
return this.__metadataDataset;
}
var ds = this.dataset;
ds.identifierInputMethod = this.identifierInputMethod;
constructor:function () {
//We initialize these here because otherwise
//the will be blank because of recursive dependencies.
!patio && (patio = require("../index"));
!Dataset && (Dataset = patio.Dataset);
this._super(arguments);
!patio && (patio = require("../index"));
!Dataset && (Dataset = patio.Dataset);
this._super(arguments);
},
/**
*
*/
qualifiedColumnName:function (column, table) {
if (isString(column)) {
var parts = this._splitString(column);
var columnTable = parts[0], alias = parts[2], tableAlias;
column = parts[1];
if (!columnTable) {
if (isInstanceOf(table, Identifier)) {
table = table.value;
if (isString(column)) {
var parts = this._splitString(column);
var columnTable = parts[0], alias = parts[2], tableAlias;
column = parts[1];
if (!columnTable) {
if (isInstanceOf(table, Identifier)) {
table = table.value;
}
if (isInstanceOf(table, AliasedExpression)) {
if (isInstanceOf(table, AliasedExpression)) {
tableAlias = table.alias;
} else if (isInstanceOf(table, QualifiedIdentifier)) {
} else if (isInstanceOf(table, QualifiedIdentifier)) {
tableAlias = table;
} else {
parts = this._splitString(table);
var schema = parts[0], tableAlias = parts[2];
table = parts[1];
if (schema) {
parts = this._splitString(table);
var schema = parts[0], tableAlias = parts[2];
table = parts[1];
if (schema) {
tableAlias = new Identifier(tableAlias) || new QualifiedIdentifier(schema, table);
}
}
columnTable = tableAlias || table;
columnTable = tableAlias || table;
}
return new QualifiedIdentifier(columnTable, column);
return new QualifiedIdentifier(columnTable, column);
} else if (isInstanceOf(column, Identifier)) {
return column.qualify(table);
} else {
* @return {String} a literal representation of the value.
*/
literal:function (v) {
if (isInstanceOf(v, LiteralString)) {
if (isInstanceOf(v, LiteralString)) {
return "" + v;
} else if (isString(v)) {
return this._literalString(v);
} else if (isNumber(v)) {
return this._literalNumber(v);
} else if (isString(v)) {
return this._literalString(v);
} else if (isNumber(v)) {
return this._literalNumber(v);
}
else if (isInstanceOf(v, Expression)) {
return this._literalExpression(v);
else if (isInstanceOf(v, Expression)) {
return this._literalExpression(v);
}
else if (isInstanceOf(v, Dataset)) {
else if (isInstanceOf(v, Dataset)) {
return this._literalDataset(v);
}
else if (isArray(v)) {
return this._literalArray(v);
} else if (isInstanceOf(v, sql.Year)) {
else if (isArray(v)) {
return this._literalArray(v);
} else if (isInstanceOf(v, sql.Year)) {
return this._literalYear(v);
} else if (isInstanceOf(v, sql.TimeStamp, sql.DateTime)) {
} else if (isInstanceOf(v, sql.TimeStamp, sql.DateTime)) {
return this._literalTimestamp(v);
} else if (isDate(v)) {
} else if (isDate(v)) {
return this._literalDate(v);
} else if (isInstanceOf(v, sql.Time)) {
} else if (isInstanceOf(v, sql.Time)) {
return this._literalTime(v);
} else if (Buffer.isBuffer(v)) {
} else if (Buffer.isBuffer(v)) {
return this._literalBuffer(v);
} else if (isNull(v)) {
} else if (isNull(v)) {
return this._literalNull();
}
else if (isBoolean(v)) {
return this._literalBoolean(v);
else if (isBoolean(v)) {
return this._literalBoolean(v);
}
else if (isHash(v)) {
return this._literalObject(v);
//Prepares an SQL statement by calling all clause methods for the given statement type.
_clauseSql:function (type) {
var sql = [("" + type).toUpperCase()];
try {
this._static[sql + "_CLAUSE_METHODS"].forEach(function (m) {
if (m.match("With")) {
this[m](sql);
var sql = [("" + type).toUpperCase()];
try {
this._static[sql + "_CLAUSE_METHODS"].forEach(function (m) {
if (m.match("With")) {
this[m](sql);
} else {
var sqlRet = this[m]();
if (sqlRet) {
sql.push(sqlRet);
var sqlRet = this[m]();
if (sqlRet) {
sql.push(sqlRet);
}
}
}, this);
} catch (e) {
throw e;
}
return sql.join("");
return sql.join("");
},
//SQL fragment for Array
_arraySql:function (a) {
return !a.length ? '(NULL)' : "(" + this.__expressionList(a) + ")";
return !a.length ? '(NULL)' : "(" + this.__expressionList(a) + ")";
},
//This method quotes the given name with the SQL standard double quote.
* SQL fragment for AliasedExpression
*/
aliasedExpressionSql:function (ae) {
return this.__asSql(this.literal(ae.expression), ae.alias);
return this.__asSql(this.literal(ae.expression), ae.alias);
},
/**
* SQL fragment for complex expressions
**/
complexExpressionSql:function (op, args) {
var newOp;
var isOperators = this._static.IS_OPERATORS, isLiterals = this._static.IS_LITERALS;
if ((newOp = isOperators[op]) != null) {
var r = args[1], v = isNull(r) ? isLiterals.NULL : isLiterals[r];
if (r == null || this.supportsIsTrue) {
if (isUndefined(v)) {
var newOp;
var isOperators = this._static.IS_OPERATORS, isLiterals = this._static.IS_LITERALS;
if ((newOp = isOperators[op]) != null) {
var r = args[1], v = isNull(r) ? isLiterals.NULL : isLiterals[r];
if (r == null || this.supportsIsTrue) {
if (isUndefined(v)) {
throw new QueryError(string.format("Invalid argument('%s') used for IS operator", r));
}
l = args[0];
return string.format("(%s %s %s)", isString(l) ? l : this.literal(l), newOp, v);
l = args[0];
return string.format("(%s %s %s)", isString(l) ? l : this.literal(l), newOp, v);
} else if (op == "IS") {
return this.complexExpressionSql("EQ", args);
} else {
null)]);
}
} else if (["IN", "NOTIN"].indexOf(op) != -1) {
} else if (["IN", "NOTIN"].indexOf(op) != -1) {
var cols = args[0], vals = args[1], colArray = isArray(cols), valArray = false, emptyValArray = false;
if (isArray(vals)) {
ComplexExpression.IN_OPERATORS[op], this.literal(vals));
}
}
} else if ((newOp = this._static.TWO_ARITY_OPERATORS[op]) != null) {
var l = args[0];
return format("(%s %s %s)", isString(l) ? l : this.literal(l), newOp,
} else if ((newOp = this._static.TWO_ARITY_OPERATORS[op]) != null) {
var l = args[0];
return format("(%s %s %s)", isString(l) ? l : this.literal(l), newOp,
this.literal(args[1]));
} else if ((newOp = this._static.N_ARITY_OPERATORS[op]) != null) {
return string.format("(%s)", args.map(this.literal, this).join(" " + newOp + " "));
} else if ((newOp = this._static.N_ARITY_OPERATORS[op]) != null) {
return string.format("(%s)", args.map(this.literal, this).join(" " + newOp + " "));
} else if (op == "NOT") {
return string.format("NOT %s", this.literal(args[0]));
} else if (op == "NOOP") {
* SQL fragment specifying an SQL function call
* */
functionSql:function (f) {
var args = f.args
return string.format("%s%s", f.f, args.length == 0 ? '()' : this.literal(args));
var args = f.args
return string.format("%s%s", f.f, args.length == 0 ? '()' : this.literal(args));
},
/**
* SQL fragment specifying a JOIN clause without ON or USING.
* */
joinClauseSql:function (jc) {
var table = jc.table
var tableAlias = jc.tableAlias
if (table === tableAlias) {
var table = jc.table
var tableAlias = jc.tableAlias
if (table === tableAlias) {
tableAlias = null;
}
var tref = this.__tableRef(table);
return string.format(" %s %s", this._joinTypeSql(jc.joinType),
var tref = this.__tableRef(table);
return string.format(" %s %s", this._joinTypeSql(jc.joinType),
tableAlias ? this.__asSql(tref, tableAlias) : tref);
},
* SQL fragment specifying a JOIN clause with ON.
**/
joinOnClauseSql:function (jc) {
return string.format("%s ON %s", this.joinClauseSql(jc), this.literal(this._filterExpr(jc.on)));
return string.format("%s ON %s", this.joinClauseSql(jc), this.literal(this._filterExpr(jc.on)));
},
/**
* SQL fragment for a literal string with placeholders
* */
placeholderLiteralStringSql:function (pls) {
var args = pls.args;
var s;
if (isHash(args)) {
var args = pls.args;
var s;
if (isHash(args)) {
for (var i in args) {
args[i] = this.literal(args[i]);
}
s = string.format(pls.str, args);
} else {
s = pls.str.replace(this._static.QUESTION_MARK, "%s");
args = toArray(args).map(this.literal, this);
s = string.format(s, args);
s = pls.str.replace(this._static.QUESTION_MARK, "%s");
args = toArray(args).map(this.literal, this);
s = string.format(s, args);
}
if (pls.parens) {
if (pls.parens) {
s = string.format("(%s)", s);
}
return s;
return s;
},
* a table and a column (or schema and table).
*/
qualifiedIdentifierSql:function (qcr) {
return [qcr.table, qcr.column].map(
return [qcr.table, qcr.column].map(
function (x) {
return [QualifiedIdentifier, Identifier, String].some(function (c) {
return x instanceof c
return [QualifiedIdentifier, Identifier, String].some(function (c) {
return x instanceof c
}) ? this.literal(x) : this.quoteIdentifier(x)
}, this).join('.');
},
* quote the name with {@link patio.dataset._Sql#_quotedIdentifier}.
*/
quoteIdentifier:function (name) {
if (isInstanceOf(name, LiteralString)) {
return name;
if (isInstanceOf(name, LiteralString)) {
return name;
} else {
if (isInstanceOf(name, Identifier)) {
name = name.value;
if (isInstanceOf(name, Identifier)) {
name = name.value;
}
name = this.inputIdentifier(name);
if (this.quoteIdentifiers) {
name = this._quotedIdentifier(name)
name = this.inputIdentifier(name);
if (this.quoteIdentifiers) {
name = this._quotedIdentifier(name)
}
}
return name;
return name;
},
/**
* identifierOutputMethod.
*/
inputIdentifier:function (v) {
var i = this.__identifierInputMethod;
v = v.toString(this);
return !isUndefinedOrNull(i) ?
var i = this.__identifierInputMethod;
v = v.toString(this);
return !isUndefinedOrNull(i) ?
isFunction(v[i]) ?
v[i]() :
isFunction(comb[i]) ?
* identifierOutputMethod.
*/
outputIdentifier:function (v) {
(v == '' && (v = 'untitled'));
var i = this.__identifierOutputMethod;
return !isUndefinedOrNull(i) ?
(v == '' && (v = 'untitled'));
var i = this.__identifierOutputMethod;
return !isUndefinedOrNull(i) ?
isFunction(v[i]) ?
v[i]() :
isFunction(comb[i]) ?
* quoted (if quoting identifiers)
*/
quoteSchemaTable:function (table) {
var parts = this.schemaAndTable(table);
var schema = parts[0];
table = parts[1];
return string.format("%s%s", schema ? this.quoteIdentifier(schema) + "." : "", this.quoteIdentifier(table));
var parts = this.schemaAndTable(table);
var schema = parts[0];
table = parts[1];
return string.format("%s%s", schema ? this.quoteIdentifier(schema) + "." : "", this.quoteIdentifier(table));
},
* Split the schema information from the table
*/
schemaAndTable:function (tableName) {
var sch = this.db ? this.db.defaultSchema || null : null;
if (isString(tableName)) {
var parts = this._splitString(tableName);
var s = parts[0], table = parts[1];
return [s || sch, table];
} else if (isInstanceOf(tableName, QualifiedIdentifier)) {
var sch = this.db ? this.db.defaultSchema || null : null;
if (isString(tableName)) {
var parts = this._splitString(tableName);
var s = parts[0], table = parts[1];
return [s || sch, table];
} else if (isInstanceOf(tableName, QualifiedIdentifier)) {
return [tableName.table, tableName.column]
} else if (isInstanceOf(tableName, Identifier)) {
return [null, tableName.value];
} else if (isInstanceOf(tableName, Identifier)) {
return [null, tableName.value];
} else {
throw new QueryError("table should be a QualifiedIdentifier, Identifier, or String");
}
* SQL fragment for specifying an alias. expression should already be literalized.
*/
__asSql:function (expression, alias) {
return string.format("%s AS %s", expression, this.quoteIdentifier(alias));
return string.format("%s AS %s", expression, this.quoteIdentifier(alias));
},
/**
* column names. If the array is empty, a wildcard (*) is returned.
*/
__columnList:function (columns) {
return (!columns || columns.length == 0) ? this._static.WILDCARD : this.__expressionList(columns);
return (!columns || columns.length == 0) ? this._static.WILDCARD : this.__expressionList(columns);
},
/**
* expressions.
*/
__expressionList:function (columns) {
return columns.map(this.literal, this).join(this._static.COMMA_SEPARATOR);
return columns.map(this.literal, this).join(this._static.COMMA_SEPARATOR);
},
//Format the timestamp based on the default_timestamp_format, with a couple
* and converts to uppercase/
*/
_joinTypeSql:function (joinType) {
return (joinType || "").replace(/([a-z]+)|([A-Z][a-z]+)/g,
return (joinType || "").replace(/([a-z]+)|([A-Z][a-z]+)/g,
function (m) {
return m.toUpperCase() + " ";
return m.toUpperCase() + " ";
}
).trimRight() + " JOIN";
},
* @return SQL fragment for Array. Treats as an expression if an array of all two pairs, or as a SQL array otherwise.
*/
_literalArray:function (v) {
return Expression.isConditionSpecifier(v) ? this._literalExpression(BooleanExpression.fromValuePairs(v)) : this._arraySql(v);
return Expression.isConditionSpecifier(v) ? this._literalExpression(BooleanExpression.fromValuePairs(v)) : this._arraySql(v);
},
/**
* @return SQL fragment for a number.
*/
_literalNumber:function (num) {
var ret = "" + num;
if (isNaN(num) || num == Infinity) {
var ret = "" + num;
if (isNaN(num) || num == Infinity) {
ret = string.format("'%s'", ret);
}
return ret;
return ret;
},
/**
* @return SQL fragment for a boolean.
*/
_literalBoolean:function (b) {
return b ? this._static.BOOL_TRUE : this._static.BOOL_FALSE;
return b ? this._static.BOOL_TRUE : this._static.BOOL_FALSE;
},
/**
* @return SQL fragment for SQL::Expression, result depends on the specific type of expression.
* */
_literalExpression:function (v) {
return v.toString(this);
return v.toString(this);
},
/**
* @return SQL fragment for String. Doubles \ and ' by default.
* */
_literalString:function (v) {
var parts = this._splitString(v);
var table = parts[0], column = parts[1], alias = parts[2];
if (!alias) {
return column && table ? this._literalExpression(QualifiedIdentifier.fromArgs([table, column])) : "'"
var parts = this._splitString(v);
var table = parts[0], column = parts[1], alias = parts[2];
if (!alias) {
return column && table ? this._literalExpression(QualifiedIdentifier.fromArgs([table, column])) : "'"
+ v.replace(/\\/g, "\\\\").replace(/'/g, "''") + "'"
} else {
return this.literal(new AliasedExpression(column
/*SQL STATEMENT CREATION METHODS*/
_selectQualifySql:function () {
var o = this.__opts;
var table = this.__opts.alwaysQualify;
if (table && !o.sql) {
var o = this.__opts;
var table = this.__opts.alwaysQualify;
if (table && !o.sql) {
array.intersect(Object.keys(o), this._static.QUALIFY_KEYS).forEach(function (k) {
o[k] = this._qualifiedExpression(o[k], table);
}, this);
* @return the columns selected
* */
_selectColumnsSql:function () {
return " " + this.__columnList(this.__opts.select);
return " " + this.__columnList(this.__opts.select);
},
/**@return the DISTINCT clause.*/
_selectDistinctSql:function () {
var distinct = this.__opts.distinct, ret = [];
if (distinct) {
var distinct = this.__opts.distinct, ret = [];
if (distinct) {
ret.push(" DISTINCT");
if (distinct.length) {
ret.push(format(" ON (%s)", this.__expressionList(distinct)));
}
}
return ret.join("");
return ret.join("");
},
/**
* work on all databases.
**/
_selectCompoundsSql:function () {
var opts = this.__opts, compounds = opts.compounds, ret = [];
if (compounds) {
var opts = this.__opts, compounds = opts.compounds, ret = [];
if (compounds) {
compounds.forEach(function (c) {
var type = c[0], dataset = c[1], all = c[2];
ret.push(string.format(" %s%s %s", type.toUpperCase(), all ? " ALL" : "", this._subselectSql(dataset)));
}, this);
}
return ret.join("");
return ret.join("");
},
/**
* @return the sql to add the list of tables to select FROM
**/
_selectFromSql:function () {
var from = this.__opts.from;
return from ? string.format(" %s%s", this._static.FROM, this._sourceList(from)) : "";
var from = this.__opts.from;
return from ? string.format(" %s%s", this._static.FROM, this._sourceList(from)) : "";
},
/**
* @return the GROUP BY clause
**/
_selectGroupSql:function () {
var group = this.__opts.group;
return group ? string.format(" GROUP BY %s", this.__expressionList(group)) : "";
var group = this.__opts.group;
return group ? string.format(" GROUP BY %s", this.__expressionList(group)) : "";
},
*@return the sql to add the filter criteria in the HAVING clause
**/
_selectHavingSql:function () {
var having = this.__opts.having;
return having ? string.format(" HAVING %s", this.literal(having)) : "";
var having = this.__opts.having;
return having ? string.format(" HAVING %s", this.literal(having)) : "";
},
/**
* @return the JOIN clause.
**/
_selectJoinSql:function () {
var join = this.__opts.join, ret = [];
if (join) {
join.forEach(function (j) {
ret.push(this.literal(j));
var join = this.__opts.join, ret = [];
if (join) {
join.forEach(function (j) {
ret.push(this.literal(j));
}, this);
}
return ret.join("");
return ret.join("");
},
/**
* @return the LIMIT and OFFSET clauses.
* */
_selectLimitSql:function () {
var ret = [], limit = this.__opts.limit, offset = this.__opts.offset;
!isUndefined(limit) && !isNull(limit) && (ret.push(format(" LIMIT %s", this.literal(limit))));
!isUndefined(offset) && !isNull(offset) && (ret.push(format(" OFFSET %s", this.literal(offset))));
return ret.join("");
var ret = [], limit = this.__opts.limit, offset = this.__opts.offset;
!isUndefined(limit) && !isNull(limit) && (ret.push(format(" LIMIT %s", this.literal(limit))));
!isUndefined(offset) && !isNull(offset) && (ret.push(format(" OFFSET %s", this.literal(offset))));
return ret.join("");
},
/**
* @return SQL for different locking modes.
**/
_selectLockSql:function () {
var lock = this.__opts.lock, ret = [];
if (lock) {
var lock = this.__opts.lock, ret = [];
if (lock) {
if (lock == "update") {
ret.push(this._static.FOR_UPDATE);
} else {
ret.push(" ", lock);
}
}
return ret.join("");
return ret.join("");
},
/**
* @return the SQL ORDER BY clause fragment.
*/
_selectOrderSql:function () {
var order = this.__opts.order;
return order ? string.format(" ORDER BY %s", this.__expressionList(order)) : "";
var order = this.__opts.order;
return order ? string.format(" ORDER BY %s", this.__expressionList(order)) : "";
},
/**
* @return the SQL WHERE clause fragment.
*/
_selectWhereSql:function () {
var where = this.__opts.where;
return where ? string.format(" WHERE %s", this.literal(where)) : "";
var where = this.__opts.where;
return where ? string.format(" WHERE %s", this.literal(where)) : "";
},
/**
* @param sql
*/
_selectWithSql:function (sql) {
var wit = this.__opts["with"];
if (wit && wit.length) {
var wit = this.__opts["with"];
if (wit && wit.length) {
//sql.length = 0;
var base = sql.join("");
sql.length = 0;
* Converts an array of source names into into a comma separated list.
**/
_sourceList:function (source) {
if (!Array.isArray(source)) {
if (!Array.isArray(source)) {
source = [source];
}
if (!source || !source.length) {
if (!source || !source.length) {
throw new QueryError("No source specified for the query");
}
return " " + source.map(
return " " + source.map(
function (s) {
return this.__tableRef(s);
return this.__tableRef(s);
}, this).join(this._static.COMMA_SEPARATOR);
},
* we literalize nonstrings.
**/
_staticSql:function (sql) {
return isString(sql) ? sql : this.literal(sql);
return isString(sql) ? sql : this.literal(sql);
},
* @returns SQL fragment specifying a table name.
**/
__tableRef:function (t) {
return isString(t) ? this._quotedIdentifier(t) : this.literal(t);
return isString(t) ? this._quotedIdentifier(t) : this.literal(t);
},
getters:{
//Same as selectS, not aliased directly to make subclassing simpler.
sql:function () {
return this.selectSql;
return this.selectSql;
},
selectSql:function () {
if (this.__opts.sql) return this._staticSql(this.__opts.sql);
else return this._clauseSql("select");
if (this.__opts.sql) return this._staticSql(this.__opts.sql);
else return this._clauseSql("select");
},
deleteSql:function () {
* @type String
*/
identifierInputMethod:function () {
return this.__identifierInputMethod;
return this.__identifierInputMethod;
},
/**
* @type String
*/
identifierOutputMethod:function () {
return this.__identifierOutputMethod;
return this.__identifierOutputMethod;
},
/**
* @default true
*/
quoteIdentifiers:function () {
return this.__quoteIdentifiers;
return this.__quoteIdentifiers;
}
},
/**@ignore*/
constructor: function () {
if (!Dataset) {
if (!Dataset) {
Dataset = require("../index").Dataset;
}
this._super(arguments);
this._super(arguments);
},
* @return {comb.Promise} a promise that is resolved when the action has completed.
*/
forEach: function (block, cb) {
var rowCb, ret;
if (this.__opts.graph) {
var rowCb, ret;
if (this.__opts.graph) {
ret = this.graphEach(block);
} else {
ret = this.fetchRows(this.selectSql);
if ((rowCb = this.rowCb)) {
ret = this.fetchRows(this.selectSql);
if ((rowCb = this.rowCb)) {
ret = ret.map(function (r) {
return rowCb(r);
});
}
if (block) {
if (block) {
ret = ret.forEach(block);
}
}
return ret.classic(cb);
return ret.classic(cb);
},
/**
* @return {comb.Promise} a promise resolved with the array of mapped values.
*/
map: function (column, cb) {
var ret = this.forEach();
column && (ret = ret[isFunction(column) ? "map" : "pluck"](column))
return ret.classic(cb).promise();
var ret = this.forEach();
column && (ret = ret[isFunction(column) ? "map" : "pluck"](column))
return ret.classic(cb).promise();
},
/**
* readOnly server unless a specific server is set.
*/
execute: function (sql, opts) {
return this.db.execute(sql, merge({server: this.__opts.server || "readOnly"}, opts || {}));
return this.db.execute(sql, merge({server: this.__opts.server || "readOnly"}, opts || {}));
},
/**
*
*/
constructor: function () {
if (comb.isUndefinedOrNull(this.__associations)) {
this.__associations = {};
if (comb.isUndefinedOrNull(this.__associations)) {
this.__associations = {};
}
this._super(arguments);
this._super(arguments);
},
reload: function () {
var ret = null;
try {
if (!action.action(value)) {
ret = format(actionOpts.message, errOpts);
ret = format(actionOpts.message, errOpts);
}
} catch (e) {
ret = format(actionOpts.message, errOpts);
ret = format(actionOpts.message, errOpts);
}
return ret;
}
var Dataset;
function conditionedJoin(type) {
var args = argsToArray(arguments, 1);
return this.joinTable.apply(this, [type].concat(args));
var args = argsToArray(arguments, 1);
return this.joinTable.apply(this, [type].concat(args));
}
function unConditionJoin(type, table) {
* @ignore
*/
constructor: function () {
!Dataset && (Dataset = require("../index").Dataset);
this._super(arguments);
this._static.CONDITIONED_JOIN_TYPES.forEach(function (type) {
if (!this[type + "Join"]) {
this[type + "Join"] = hitch(this, conditionedJoin, type);
!Dataset && (Dataset = require("../index").Dataset);
this._super(arguments);
this._static.CONDITIONED_JOIN_TYPES.forEach(function (type) {
if (!this[type + "Join"]) {
this[type + "Join"] = hitch(this, conditionedJoin, type);
}
}, this);
this._static.UNCONDITIONED_JOIN_TYPES.forEach(function (type) {
if (!this[type + "Join"]) {
this[type + "Join"] = hitch(this, unConditionJoin, type);
this._static.UNCONDITIONED_JOIN_TYPES.forEach(function (type) {
if (!this[type + "Join"]) {
this[type + "Join"] = hitch(this, unConditionJoin, type);
}
}, this);
var clause = (tOpts.having ? "having" : "where"), clauseObj = tOpts[clause];
if (clauseObj) {
var args = argsToArray(arguments);
args = args.length == 1 ? args[0] : args;
args = args.length === 1 ? args[0] : args;
var opts = {};
opts[clause] = new BooleanExpression("OR", clauseObj, this._filterExpr(args));
return this.mergeOptions(opts);
* @return {patio.Dataset} a cloned dataset with the condition 'or group' added to the WHERE/HAVING clause.
*/
andGroupedOr: function (filterExp) {
return this._addGroupedCondition("AND", "OR", filterExp);
return this._addGroupedCondition("AND", "OR", filterExp);
},
/**
return this.or.apply(this, arguments);
} else {
var args = argsToArray(arguments);
args = args.length == 1 ? args[0] : args;
args = args.length === 1 ? args[0] : args;
var opts = {};
opts[clause] = this._filterExpr(args, null, "AND");
return this.mergeOptions(opts);
* @return {patio.Dataset} a cloned dataset with the excluded conditions applied to the HAVING/WHERE clause.
*/
exclude: function () {
var cond = argsToArray(arguments), tOpts = this.__opts;
var clause = (tOpts["having"] ? "having" : "where"), clauseObj = tOpts[clause];
cond = cond.length > 1 ? cond : cond[0];
cond = this._filterExpr.call(this, cond);
cond = BooleanExpression.invert(cond);
if (clauseObj) {
cond = new BooleanExpression("AND", clauseObj, cond)
var cond = argsToArray(arguments), tOpts = this.__opts;
var clause = (tOpts["having"] ? "having" : "where"), clauseObj = tOpts[clause];
cond = cond.length > 1 ? cond : cond[0];
cond = this._filterExpr.call(this, cond);
cond = BooleanExpression.invert(cond);
if (clauseObj) {
cond = new BooleanExpression("AND", clauseObj, cond);
}
var opts = {};
opts[clause] = cond;
return this.mergeOptions(opts);
var opts = {};
opts[clause] = cond;
return this.mergeOptions(opts);
},
/**
* @return {patio.Dataset} a cloned dataset with the filter arumgents applied to the WHERE/HAVING clause.
**/
filter: function (args, cb) {
args = [this.__opts["having"] ? "having" : "where"].concat(argsToArray(arguments));
return this._filter.apply(this, args);
args = [this.__opts["having"] ? "having" : "where"].concat(argsToArray(arguments));
return this._filter.apply(this, args);
},
/**
* @return {patio.Dataset} a cloned dataset with the FROM clause overridden.
*/
from: function (source) {
source = argsToArray(arguments);
var tableAliasNum = 0, sources = [];
source.forEach(function (s) {
if (isInstanceOf(s, Dataset)) {
source = argsToArray(arguments);
var tableAliasNum = 0, sources = [];
source.forEach(function (s) {
if (isInstanceOf(s, Dataset)) {
sources.push(new AliasedExpression(s, this._datasetAlias(++tableAliasNum)));
} else if (isHash(s)) {
} else if (isHash(s)) {
for (var i in s) {
sources.push(new AliasedExpression(new Identifier(i), s[i]));
}
} else if (isString(s)) {
sources.push(this.stringToIdentifier(s))
} else if (isString(s)) {
sources.push(this.stringToIdentifier(s));
} else {
sources.push(s);
}
}, this);
var o = {from: sources.length ? sources : null}
if (tableAliasNum) {
var o = {from: sources.length ? sources : null};
if (tableAliasNum) {
o.numDatasetSources = tableAliasNum;
}
return this.mergeOptions(o)
return this.mergeOptions(o);
},
/**
var fs = {};
var nonSqlOptions = this._static.NON_SQL_OPTIONS;
Object.keys(this.__opts).forEach(function (k) {
if (nonSqlOptions.indexOf(k) == -1) {
if (nonSqlOptions.indexOf(k) === -1) {
fs[k] = null;
}
});
group: function (columns) {
columns = argsToArray(arguments);
var self = this;
return this.mergeOptions({group: (array.compact(columns).length == 0 ? null : columns.map(function (c) {
return this.mergeOptions({group: (array.compact(columns).length === 0 ? null : columns.map(function (c) {
return isString(c) ? self.stringToIdentifier(c) : c;
}))});
},
**/
having: function () {
var cond = argsToArray(arguments).map(function (s) {
return isString(s) && s !== '' ? this.stringToIdentifier(s) : s
return isString(s) && s !== '' ? this.stringToIdentifier(s) : s;
}, this);
return this._filter.apply(this, ["having"].concat(cond));
},
if (!(having || where)) {
throw new QueryError("No current filter");
}
var o = {}
var o = {};
if (having) {
o.having = BooleanExpression.invert(having);
}
* @see patio.Dataset#joinTable
*/
join: function () {
return this.innerJoin.apply(this, arguments);
return this.innerJoin.apply(this, arguments);
},
/**
*/
joinTable: function (type, table, expr, options, cb) {
var args = argsToArray(arguments);
if (isFunction(args[args.length - 1])) {
var args = argsToArray(arguments);
if (isFunction(args[args.length - 1])) {
cb = args[args.length - 1];
args.pop();
} else {
cb = null;
cb = null;
}
type = args.shift(), table = args.shift(), expr = args.shift(), options = args.shift();
expr = isUndefined(expr) ? null : expr, options = isUndefined(options) ? {} : options;
type = args.shift(), table = args.shift(), expr = args.shift(), options = args.shift();
expr = isUndefined(expr) ? null : expr, options = isUndefined(options) ? {} : options;
var h;
var usingJoin = isArray(expr) && expr.length && expr.every(function (x) {
return isString(x) || isInstanceOf(x, Identifier)
var h;
var usingJoin = isArray(expr) && expr.length && expr.every(function (x) {
return isString(x) || isInstanceOf(x, Identifier);
});
if (usingJoin && !this.supportsJoinUsing) {
if (usingJoin && !this.supportsJoinUsing) {
h = {};
expr.forEach(function (s) {
h[s] = s;
});
return this.joinTable(type, table, h, options);
}
var tableAlias, lastAlias;
if (isHash(options)) {
tableAlias = options.tableAlias;
lastAlias = options.implicitQualifier;
var tableAlias, lastAlias;
if (isHash(options)) {
tableAlias = options.tableAlias;
lastAlias = options.implicitQualifier;
} else if (isString(options) || isInstanceOf(options, Identifier)) {
tableAlias = options;
lastAlias = null;
} else {
throw new QueryError("Invalid options format for joinTable %j4", [options]);
}
var tableAliasNum, tableName;
if (isInstanceOf(table, Dataset)) {
var tableAliasNum, tableName;
if (isInstanceOf(table, Dataset)) {
if (!tableAlias) {
tableAliasNum = (this.__opts.numDatasetSources || 0) + 1;
tableAlias = this._datasetAlias(tableAliasNum);
}
tableName = tableAlias;
} else {
if (!isUndefined(table.tableName)) {
if (!isUndefined(table.tableName)) {
table = table.tableName;
}
if (isArray(table)) {
if (isArray(table)) {
table = table.map(this.stringToIdentifier, this);
} else {
table = isString(table) ? this.stringToIdentifier(table) : table;
var parts = this._splitAlias(table), implicitTableAlias = parts[1];
table = parts[0]
tableAlias = tableAlias || implicitTableAlias;
tableName = tableAlias || table;
table = isString(table) ? this.stringToIdentifier(table) : table;
var parts = this._splitAlias(table), implicitTableAlias = parts[1];
table = parts[0];
tableAlias = tableAlias || implicitTableAlias;
tableName = tableAlias || table;
}
}
var join;
if (!expr && !cb) {
var join;
if (!expr && !cb) {
join = new JoinClause(type, table, tableAlias);
} else if (usingJoin) {
} else if (usingJoin) {
if (cb) {
throw new QueryError("cant use a cb if an array is given");
}
join = new JoinUsingClause(expr, type, table, tableAlias);
} else {
lastAlias = lastAlias || this.__opts["lastJoinedTable"] || this.firstSourceAlias;
if (Expression.isConditionSpecifier(expr)) {
var newExpr = [];
for (var i in expr) {
var val = expr[i];
if (isArray(val) && val.length == 2) {
lastAlias = lastAlias || this.__opts["lastJoinedTable"] || this.firstSourceAlias;
if (Expression.isConditionSpecifier(expr)) {
var newExpr = [];
for (var i in expr) {
var val = expr[i];
if (isArray(val) && val.length === 2) {
i = val[0], val = val[1];
}
var k = this.qualifiedColumnName(i, tableName), v;
if (isInstanceOf(val, Identifier)) {
v = val.qualify(lastAlias);
var k = this.qualifiedColumnName(i, tableName), v;
if (isInstanceOf(val, Identifier)) {
v = val.qualify(lastAlias);
} else {
v = val;
v = val;
}
newExpr.push([k, v]);
newExpr.push([k, v]);
}
expr = newExpr;
expr = newExpr;
}
if (isFunction(cb)) {
if (isFunction(cb)) {
var expr2 = cb.apply(sql, [tableName, lastAlias, this.__opts.join || []]);
expr = expr ? new BooleanExpression("AND", expr, expr2) : expr2;
}
join = new JoinOnClause(expr, type, table, tableAlias);
join = new JoinOnClause(expr, type, table, tableAlias);
}
var opts = {join: (this.__opts.join || []).concat([join]), lastJoinedTable: tableName};
if (tableAliasNum) {
var opts = {join: (this.__opts.join || []).concat([join]), lastJoinedTable: tableName};
if (tableAliasNum) {
opts.numDatasetSources = tableAliasNum;
}
return this.mergeOptions(opts);
return this.mergeOptions(opts);
},
if (this.__opts.sql) {
return this.fromSelf().limit(limit, offset);
}
if (isArray(limit) && limit.length == 2) {
if (isArray(limit) && limit.length === 2) {
offset = limit[0];
limit = limit[1] - limit[0] + 1;
}
* @return {patio.Dataset} a cloned dataset with the order changed.
* */
order: function (args) {
args = argsToArray(arguments);
var order = [];
args = compact(args).length ? args : null;
if (args) {
args.forEach(function (a) {
if (isString(a)) {
order.push(this.stringToIdentifier(a));
args = argsToArray(arguments);
var order = [];
args = compact(args).length ? args : null;
if (args) {
args.forEach(function (a) {
if (isString(a)) {
order.push(this.stringToIdentifier(a));
} else if (isFunction(a)) {
var res = a.apply(sql, [sql]);
order = order.concat(isArray(res) ? res : [res]);
} else {
order = null;
}
return this.mergeOptions({order: order});
return this.mergeOptions({order: order});
},
/**
* @return {patio.Dataset} a cloned dataset with the columns selected changed.
*/
select: function (args) {
args = flatten(argsToArray(arguments));
var columns = [];
args.forEach(function (c) {
if (isFunction(c)) {
args = flatten(argsToArray(arguments));
var columns = [];
args.forEach(function (c) {
if (isFunction(c)) {
var res = c.apply(sql, [sql]);
columns = columns.concat(isArray(res) ? res : [res]);
} else {
columns.push(c);
columns.push(c);
}
});
var select = [];
columns.forEach(function (c) {
if (isHash(c)) {
var select = [];
columns.forEach(function (c) {
if (isHash(c)) {
for (var i in c) {
select.push(new AliasedExpression(this.stringToIdentifier(i), c[i]));
}
} else if (isString(c)) {
select.push(this.stringToIdentifier(c));
} else if (isString(c)) {
select.push(this.stringToIdentifier(c));
} else {
select.push(c);
select.push(c);
}
}, this);
return this.mergeOptions({select: select});
return this.mergeOptions({select: select});
},
throw new QueryError("This dataset does not support common table expressions");
}
opts = opts || {};
var wit = (this.__opts["with"] || []).concat([merge(opts, {recursive: true, name: this.stringToIdentifier(name), dataset: nonRecursive.union(recursive, {all: opts.unionAll != false, fromSelf: false})})]);
var wit = (this.__opts["with"] || []).concat([merge(opts, {recursive: true, name: this.stringToIdentifier(name), dataset: nonRecursive.union(recursive, {all: opts.unionAll !== false, fromSelf: false})})]);
return this.mergeOptions({"with": wit});
},
* @return {patio.Dataset} a cloned dataset with the static sql set.
*/
withSql: function (sql) {
var args = argsToArray(arguments).slice(1);
if (args.length) {
sql = new PlaceHolderLiteralString(sql, args)
var args = argsToArray(arguments).slice(1);
if (args.length) {
sql = new PlaceHolderLiteralString(sql, args);
}
return this.mergeOptions({sql: sql});
return this.mergeOptions({sql: sql});
},
* @return {patio.Dataset} a cloned dataset with the condition group added to the WHERE/HAVING clause.
*/
_addGroupedCondition: function (addedByBool, groupedByBool) {
groupedByBool = isUndefined(groupedByBool) ? "AND" : groupedByBool;
var tOpts = this.__opts,
groupedByBool = isUndefined(groupedByBool) ? "AND" : groupedByBool;
var tOpts = this.__opts,
clause = (tOpts.having ? "having" : "where"),
clauseObj = tOpts[clause];
var args = argsToArray(arguments, 2);
args = args.length == 1 ? args[0] : args;
var opts = {};
if (clauseObj) {
addedByBool = isUndefined(addedByBool) ? "AND" : addedByBool;
opts[clause] = new BooleanExpression(addedByBool, clauseObj, this._filterExpr(args, null, groupedByBool));
var args = argsToArray(arguments, 2);
args = args.length === 1 ? args[0] : args;
var opts = {};
if (clauseObj) {
addedByBool = isUndefined(addedByBool) ? "AND" : addedByBool;
opts[clause] = new BooleanExpression(addedByBool, clauseObj, this._filterExpr(args, null, groupedByBool));
} else {
opts[clause] = this._filterExpr(args, null, groupedByBool);
}
return this.mergeOptions(opts);
return this.mergeOptions(opts);
},
/**
* Internal filter method so it works on either the having or where clauses.
*/
_filter: function (clause) {
var cond = argsToArray(arguments).slice(1), cb;
if (cond.length && isFunction(cond[cond.length - 1])) {
var cond = argsToArray(arguments).slice(1), cb;
if (cond.length && isFunction(cond[cond.length - 1])) {
cb = cond.pop();
}
cond = cond.length == 1 ? cond[0] : cond
if ((cond == null || cond == undefined || cond === "") || (isArray(cond) && cond.length == 0 && !cb) || (isObject(cond) && isEmpty(cond) && !cb)) {
cond = cond.length === 1 ? cond[0] : cond;
if ((cond == null || cond === undefined || cond === "") || (isArray(cond) && cond.length === 0 && !cb) || (isObject(cond) && isEmpty(cond) && !cb)) {
return this.mergeOptions();
} else {
cond = this._filterExpr(cond, cb);
var cl = this.__opts[clause];
cl && (cond = new BooleanExpression("AND", cl, cond));
var opts = {};
opts[clause] = cond;
return this.mergeOptions(opts);
cond = this._filterExpr(cond, cb);
var cl = this.__opts[clause];
cl && (cond = new BooleanExpression("AND", cl, cond));
var opts = {};
opts[clause] = cond;
return this.mergeOptions(opts);
}
},
* string that does not contain an alias {table}___{alias}.
*/
_splitAlias: function (c) {
var ret;
if (isInstanceOf(c, AliasedExpression)) {
var ret;
if (isInstanceOf(c, AliasedExpression)) {
ret = [c.expression, c.alias];
} else if (isString(c)) {
} else if (isString(c)) {
var parts = this._splitString(c), cTable = parts[0], column = parts[1], alias = parts[2];
if (alias) {
ret = [cTable ? new QualifiedIdentifier(cTable, column) : column, alias];
ret = [c, null];
}
} else {
ret = [c, null];
ret = [c, null];
}
return ret;
return ret;
},
pairs.push(new BooleanExpression(op, new Identifier(pair[0]), pair[1]));
});
}
return pairs.length == 1 ? pairs[0] : BooleanExpression.fromArgs(["AND"].concat(pairs));
return pairs.length === 1 ? pairs[0] : BooleanExpression.fromArgs(["AND"].concat(pairs));
},
/**
throw new QueryError("Between requires an array for the value");
}
}
var ret = pairs.length == 1 ? pairs[0] : BooleanExpression.fromArgs(["AND"].concat(pairs))
var ret = pairs.length === 1 ? pairs[0] : BooleanExpression.fromArgs(["AND"].concat(pairs));
return invert ? BooleanExpression.invert(ret) : ret;
},
* SQL expression object based on the expr type. See {@link patio.Dataset#filter}
*/
_filterExpr: function (expr, cb, joinCond) {
expr = (isUndefined(expr) || isNull(expr) || (isArray(expr) && !expr.length)) ? null : expr;
if (expr && cb) {
return new BooleanExpression(joinCond || "AND", this._filterExpr(expr, null, joinCond), this._filterExpr(cb, null, joinCond))
} else if (cb) {
expr = cb
expr = (isUndefined(expr) || isNull(expr) || (isArray(expr) && !expr.length)) ? null : expr;
if (expr && cb) {
return new BooleanExpression(joinCond || "AND", this._filterExpr(expr, null, joinCond), this._filterExpr(cb, null, joinCond));
} else if (cb) {
expr = cb;
}
if (isInstanceOf(expr, Expression)) {
if (isInstanceOf(expr, Expression)) {
if (isInstanceOf(expr, NumericExpression, StringExpression)) {
throw new QueryError("Invalid SQL Expression type : " + expr);
}
return expr;
} else if (isArray(expr)) {
if (expr.length) {
var first = expr[0];
if (isString(first)) {
} else if (isArray(expr)) {
if (expr.length) {
var first = expr[0];
if (isString(first)) {
return new PlaceHolderLiteralString(first, expr.slice(1), true);
} else if (Expression.isConditionSpecifier(expr)) {
return BooleanExpression.fromValuePairs(expr, joinCond)
} else if (Expression.isConditionSpecifier(expr)) {
return BooleanExpression.fromValuePairs(expr, joinCond);
} else {
return BooleanExpression.fromArgs([joinCond || "AND"].concat(expr.map(function (e) {
return this._filterExpr(e, null, joinCond);
}, this)));
}
}
} else if (isFunction(expr)) {
} else if (isFunction(expr)) {
return this._filterExpr(expr.call(sql, sql), null, joinCond);
} else if (isBoolean(expr)) {
} else if (isBoolean(expr)) {
return new BooleanExpression("NOOP", expr);
} else if (isString(expr)) {
} else if (isString(expr)) {
return this.stringToIdentifier(expr);
} else if (isInstanceOf(expr, LiteralString)) {
} else if (isInstanceOf(expr, LiteralString)) {
return new LiteralString("(" + expr + ")");
} else if (isHash(expr)) {
return BooleanExpression.fromValuePairs(expr, joinCond);
} else if (isHash(expr)) {
return BooleanExpression.fromValuePairs(expr, joinCond);
} else {
throw new QueryError("Invalid filter argument");
}
isSimpleSelectAll: function () {
var o = {}, opts = this.__opts, count = 0;
for (var i in opts) {
if (opts[i] != null && this._static.NON_SQL_OPTIONS.indexOf(i) == -1) {
if (opts[i] != null && this._static.NON_SQL_OPTIONS.indexOf(i) === -1) {
o[i] = opts[i];
count++;
}
}
var f = o.from
return count == 1 && f.length == 1 && (isString(f[0]) || isInstanceOf(f[0], AliasedExpression, Identifier));
var f = o.from;
return count === 1 && f.length === 1 && (isString(f[0]) || isInstanceOf(f[0], AliasedExpression, Identifier));
}
}
},
this.QUERY_METHODS = queryMethods.concat(joinMethods);
}
}
}).
as(module);
}).as(module);
* @ignore
*/
constructor: function () {
!Dataset && (Dataset = require("../index").Dataset);
this._super(arguments);
!Dataset && (Dataset = require("../index").Dataset);
this._super(arguments);
},
/**
* Logs an INFO level message to the "patio.Database" logger.
*/
logInfo: function () {
if (LOGGER.isInfo) {
LOGGER.info.apply(LOGGER, arguments);
if (LOGGER.isInfo) {
LOGGER.info.apply(LOGGER, arguments);
}
},
* Logs a DEBUG level message to the "patio.Database" logger.
*/
logDebug: function () {
if (LOGGER.isDebug) {
LOGGER.debug.apply(LOGGER, arguments);
if (LOGGER.isDebug) {
LOGGER.debug.apply(LOGGER, arguments);
}
},
* and all other queries with the duration at warn or info level.
* */
__logAndExecute: function (sql, args, cb) {
if (isFunction(args)) {
cb = args;
args = null;
if (isFunction(args)) {
cb = args;
args = null;
}
if (args) {
if (args) {
sql = format("%s; %j", sql, args);
}
sql = sql.trim();
var start = new Date(), self = this;
var ret;
if (isFunction(cb)) {
this.logInfo("Executing; %s", sql);
ret = new Promise();
cb().chain(function () {
self.logDebug("Duration: % 6dms; %s", new Date() - start, sql);
spreadArgs(ret.callback, arguments);
sql = sql.trim();
var start = new Date(), self = this;
var ret;
if (isFunction(cb)) {
this.logInfo("Executing; %s", sql);
ret = new Promise();
cb().chain(function () {
self.logDebug("Duration: % 6dms; %s", new Date() - start, sql);
spreadArgs(ret.callback, arguments);
},function (err) {
err = new QueryError(format("%s: %s", err.message, sql));
self.logError(err);
} else {
throw new QueryError("CB is required");
}
return ret.promise();
return ret.promise();
},
/*Log the given SQL and then execute it on the connection, used by
// Whether this dataset quotes identifiers.
/**@ignore*/
quoteIdentifiers:function(){
return this.__quoteIdentifiers;
return this.__quoteIdentifiers;
},
// Whether this dataset will provide accurate number of rows matched for
// rows matched by the dataset's filter.
/**@ignore*/
providesAccurateRowsMatched:function(){
return this.__providesAccurateRowsMatched;
return this.__providesAccurateRowsMatched;
},
//Whether the dataset requires SQL standard datetimes (false by default,
// as most allow strings with ISO 8601 format).
/**@ignore*/
requiresSqlStandardDateTimes:function(){
return this.__requiresSqlStandardDateTimes;
return this.__requiresSqlStandardDateTimes;
},
// Whether the dataset supports common table expressions (the WITH clause).
/**@ignore*/
supportsCte:function(){
return this.__supportsCte;
return this.__supportsCte;
},
// Whether the dataset supports the DISTINCT ON clause, false by default.
/**@ignore*/
supportsDistinctOn:function(){
return this.__supportsDistinctOn;
return this.__supportsDistinctOn;
},
//Whether the dataset supports the INTERSECT and EXCEPT compound operations, true by default.
/**@ignore*/
supportsIntersectExcept:function(){
return this.__supportsIntersectExcept;
return this.__supportsIntersectExcept;
},
//Whether the dataset supports the INTERSECT ALL and EXCEPT ALL compound operations, true by default.
/**@ignore*/
supportsIntersectExceptAll:function(){
return this.__supportsIntersectExceptAll;
return this.__supportsIntersectExceptAll;
},
//Whether the dataset supports the IS TRUE syntax.
/**@ignore*/
supportsIsTrue:function(){
return this.__supportsIsTrue;
return this.__supportsIsTrue;
},
//Whether the dataset supports the JOIN table USING (column1, ...) syntax.
/**@ignore*/
supportsJoinUsing:function(){
return this.__supportsJoinUsing;
return this.__supportsJoinUsing;
},
//Whether modifying joined datasets is supported.
/**@ignore*/
supportsModifyingJoins:function(){
return this.__supportsModifyingJoins;
return this.__supportsModifyingJoins;
},
//Whether the IN/NOT IN operators support multiple columns when an
/**@ignore*/
supportsMultipleColumnIn:function(){
return this.__supportsMultipleColumnIn;
return this.__supportsMultipleColumnIn;
},
//Whether the dataset supports timezones in literal timestamps
/**@ignore*/
supportsTimestampTimezones:function(){
return this.__supportsTimestampTimezones;
return this.__supportsTimestampTimezones;
},
//Whether the dataset supports fractional seconds in literal timestamps
/**@ignore*/
supportsTimestampUsecs:function(){
return this.__supportsTimestampUsecs;
return this.__supportsTimestampUsecs;
},
//Whether the dataset supports window functions.
/**@ignore*/
supportsWindowFunctions:function(){
return this.__supportsWindowFunctions;
return this.__supportsWindowFunctions;
}
},
// Whether this dataset quotes identifiers.
/**@ignore*/
quoteIdentifiers:function(val){
this.__quoteIdentifiers = val;
this.__quoteIdentifiers = val;
},
// Whether this dataset will provide accurate number of rows matched for
// rows matched by the dataset's filter.
/**@ignore*/
providesAccurateRowsMatched:function(val){
this.__providesAccurateRowsMatched = val;
this.__providesAccurateRowsMatched = val;
},
//Whether the dataset requires SQL standard datetimes (false by default,
// as most allow strings with ISO 8601 format).
/**@ignore*/
requiresSqlStandardDateTimes:function(val){
this.__requiresSqlStandardDateTimes = val;
this.__requiresSqlStandardDateTimes = val;
},
// Whether the dataset supports common table expressions (the WITH clause).
/**@ignore*/
supportsCte:function(val){
this.__supportsCte = val;
this.__supportsCte = val;
},
// Whether the dataset supports the DISTINCT ON clause, false by default.
/**@ignore*/
supportsDistinctOn:function(val){
this.__supportsDistinctOn = val;
this.__supportsDistinctOn = val;
},
//Whether the dataset supports the INTERSECT and EXCEPT compound operations, true by default.
/**@ignore*/
supportsIntersectExcept:function(val){
this.__supportsIntersectExcept = val;
this.__supportsIntersectExcept = val;
},
//Whether the dataset supports the INTERSECT ALL and EXCEPT ALL compound operations, true by default.
/**@ignore*/
supportsIntersectExceptAll:function(val){
this.__supportsIntersectExceptAll = val;
this.__supportsIntersectExceptAll = val;
},
//Whether the dataset supports the IS TRUE syntax.
/**@ignore*/
supportsIsTrue:function(val){
this.__supportsIsTrue = val;
this.__supportsIsTrue = val;
},
//Whether the dataset supports the JOIN table USING (column1, ...) syntax.
/**@ignore*/
supportsJoinUsing:function(val){
this.__supportsJoinUsing = val;
this.__supportsJoinUsing = val;
},
//Whether modifying joined datasets is supported.
/**@ignore*/
supportsModifyingJoins:function(val){
this.__supportsModifyingJoins = val;
this.__supportsModifyingJoins = val;
},
//Whether the IN/NOT IN operators support multiple columns when an
/**@ignore*/
supportsMultipleColumnIn:function(val){
this.__supportsMultipleColumnIn = val;
this.__supportsMultipleColumnIn = val;
},
//Whether the dataset supports timezones in literal timestamps
/**@ignore*/
supportsTimestampTimezones:function(val){
this.__supportsTimestampTimezones = val;
this.__supportsTimestampTimezones = val;
},
//Whether the dataset supports fractional seconds in literal timestamps
/**@ignore*/
supportsTimestampUsecs:function(val){
this.__supportsTimestampUsecs = val;
this.__supportsTimestampUsecs = val;
},
//Whether the dataset supports window functions.
/**@ignore*/
supportsWindowFunctions:function(val){
this.__supportsWindowFunctions = val;
this.__supportsWindowFunctions = val;
}
}
function (){ var cond = argsToArray(arguments).map(function (s) { - return isString(s) && s !== '' ? this.stringToIdentifier(s) : s + return isString(s) && s !== '' ? this.stringToIdentifier(s) : s; }, this); return this._filter.apply(this, ["having"].concat(cond)); @@ -10240,7 +10240,7 @@if (!(having || where)) { throw new QueryError("No current filter"); } - var o = {} + var o = {}; if (having) { o.having = BooleanExpression.invert(having); } @@ -11093,7 +11093,7 @@
expr = isUndefined(expr) ? null : expr, options = isUndefined(options) ? {} : options; var h; var usingJoin = isArray(expr) && expr.length && expr.every(function (x) { - return isString(x) || isInstanceOf(x, Identifier) + return isString(x) || isInstanceOf(x, Identifier); }); if (usingJoin && !this.supportsJoinUsing) { h = {}; @@ -11128,7 +11128,7 @@
} else { table = isString(table) ? this.stringToIdentifier(table) : table; var parts = this._splitAlias(table), implicitTableAlias = parts[1]; - table = parts[0] + table = parts[0]; tableAlias = tableAlias || implicitTableAlias; tableName = tableAlias || table; } @@ -11147,7 +11147,7 @@
var newExpr = []; for (var i in expr) { var val = expr[i]; - if (isArray(val) && val.length == 2) { + if (isArray(val) && val.length === 2) { i = val[0], val = val[1]; } var k = this.qualifiedColumnName(i, tableName), v; @@ -11400,7 +11400,7 @@
if (this.__opts.sql) { return this.fromSelf().limit(limit, offset); } - if (isArray(limit) && limit.length == 2) { + if (isArray(limit) && limit.length === 2) { offset = limit[0]; limit = limit[1] - limit[0] + 1; } @@ -12484,7 +12484,7 @@
var clause = (tOpts.having ? "having" : "where"), clauseObj = tOpts[clause]; if (clauseObj) { var args = argsToArray(arguments); - args = args.length == 1 ? args[0] : args; + args = args.length === 1 ? args[0] : args; var opts = {}; opts[clause] = new BooleanExpression("OR", clauseObj, this._filterExpr(args)); return this.mergeOptions(opts); @@ -12565,7 +12565,7 @@
return this.or.apply(this, arguments); } else { var args = argsToArray(arguments); - args = args.length == 1 ? args[0] : args; + args = args.length === 1 ? args[0] : args; var opts = {}; opts[clause] = this._filterExpr(args, null, "AND"); return this.mergeOptions(opts); @@ -16078,7 +16078,7 @@
throw new QueryError("This dataset does not support common table expressions"); } opts = opts || {}; - var wit = (this.__opts["with"] || []).concat([merge(opts, {recursive: true, name: this.stringToIdentifier(name), dataset: nonRecursive.union(recursive, {all: opts.unionAll != false, fromSelf: false})})]); + var wit = (this.__opts["with"] || []).concat([merge(opts, {recursive: true, name: this.stringToIdentifier(name), dataset: nonRecursive.union(recursive, {all: opts.unionAll !== false, fromSelf: false})})]); return this.mergeOptions({"with": wit}); } @@ -16141,7 +16141,7 @@
function (sql){ var args = argsToArray(arguments).slice(1); if (args.length) { - sql = new PlaceHolderLiteralString(sql, args) + sql = new PlaceHolderLiteralString(sql, args); } return this.mergeOptions({sql: sql}); diff --git a/docs/patio_sql.html b/docs/patio_sql.html index 8a26e9f7..6a286ed6 100644 --- a/docs/patio_sql.html +++ b/docs/patio_sql.html @@ -554,129 +554,6 @@ - - Source -
-{ - /**@lends patio.sql*/ - /** - * Returns a {@link patio.sql.Identifier}, {@link patio.sql.QualifiedIdentifier}, - * or {@link patio.sql.ALiasedExpression} depending on the format of the string - * passed in. - * - * <ul> - * <li>For columns : table__column___alias.</li> - * <li>For tables : schema__table___alias.</li> - * </ul> - * each portion of the identifier is optional. See example below - * - * @example - * - * patio.sql.identifier("a") //= > new patio.sql.Identifier("a"); - * patio.sql.identifier("table__column"); //=> new patio.sql.QualifiedIdentifier(table, column); - * patio.sql.identifier("table__column___alias"); - * //=> new patio.sql.AliasedExpression(new patio.sql.QualifiedIdentifier(table, column), alias); - * - * @param {String} name the name to covert to an an {@link patio.sql.Identifier}, {@link patio.sql.QualifiedIdentifier}, - * or {@link patio.sql.AliasedExpression}. - * - * @return {patio.sql.Identifier|patio.sql.QualifiedIdentifier|patio.sql.AliasedExpression} an identifier generated based on the name string. - */ - identifier:function (s) { - return sql.stringToIdentifier(s); - }, - /** - * @see patio.sql.identifier - */ - stringToIdentifier:function (name) { - !Dataset && (Dataset = require("./dataset")); - return new Dataset().stringToIdentifier(name); - }, - /** - * Creates a {@link patio.sql.LiteralString} or {@link patio.sql.PlaceHolderLiteralString} - * depending on the arguments passed in. If a single string is passed in then - * it is assumed to be a {@link patio.sql.LiteralString}. If more than one argument is - * passed in then it is assumed to be a {@link patio.sql.PlaceHolderLiteralString}. - * - * @example - * - * //a literal string that will be placed in an SQL query with out quoting. - * patio.sql.literal("a"); //=> new patio.sql.LiteralString('a'); - * - * //a placeholder string that will have ? replaced with the {@link patio.Dataset#literal} version of - * //the arugment and replaced in the string. - * patio.sql.literal("a = ?", 1) //=> a = 1 - * patio.sql.literal("a = ?", "b"); //=> a = 'b' - * patio.sql.literal("a = {a} AND b = {b}", {a : 1, b : 2}); //=> a = 1 AND b = 2 - * - * @param {String ...} s variable number of arguments where the first argument - * is a string. If multiple arguments are passed it is a assumed to be a {@link patio.sql.PlaceHolderLiteralString} - * - * @return {patio.sql.LiteralString|patio.sql.PlaceHolderLiteralString} an expression that can be used as an argument - * for {@link patio.Dataset} query methods. - */ - literal:function (s) { - var args = argsToArray(arguments); - return args.length > 1 ? PlaceHolderLiteralString.fromArgs(args) : new LiteralString(s); - }, - /** - * Returns a {@link patio.sql.CaseExpression}. See {@link patio.sql.CaseExpression} for argument types. - * - * @example - * - * sql["case"]({a:sql.b}, sql.c, sql.d); //=> (CASE t.d WHEN t.a THEN t.b ELSE t.c END) - * - */ - "case":function (hash, /*args**/opts) { - var args = argsToArray(arguments, 1); - return CaseExpression.fromArgs([hashToArray(hash)].concat(args)); - }, - /** - * Creates a {@link patio.sql.StringExpression} - * - * Return a {@link patio.sql.StringExpression} representing an SQL string made up of the - * concatenation of this array's elements. If an joiner is passed - * it is used in between each element of the array in the SQL - * concatenation. - * - * @example - * patio.sql.sqlStringJoin(["a"]); //=> a - * //you can use sql.* as a shortcut to get an identifier - * patio.sql.sqlStringJoin([sql.identifier("a"), sql.b]);//=> a || b - * patio.sql.sqlStringJoin([sql.a, 'b']) # SQL: a || 'b' - * patio.sql.sqlStringJoin(['a', sql.b], ' '); //=> 'a' || ' ' || b - */ - sqlStringJoin:function (arr, joiner) { - joiner = joiner || null; - var args; - arr = arr.map(function (a) { - return isInstanceOf(a, Expression, LiteralString, Boolean) || isNull(a) ? a : sql.stringToIdentifier(a) - }); - if (joiner) { - var newJoiner = []; - for (var i = 0; i < arr.length; i++) { - newJoiner.push(joiner); - } - args = array.flatten(array.zip(arr, newJoiner)); - args.pop(); - } else { - args = arr; - } - args = args.map(function (a) { - return isInstanceOf(a, Expression, LiteralString, Boolean) || isNull(a) ? a : "" + a; - }); - return StringExpression.fromArgs(["||"].concat(args)); - }, - Year:Year, - TimeStamp:TimeStamp, - Time:Time, - DateTime:DateTime, - Float:Float, - Decimal:Decimal -} -- -
Property | Type | Default Value | Description |
NegativeBooleanConstant | declaration | define(BooleanConstant, { | Represents inverse boolean constants (currently only NOTNULL). A special class to allow for special behavior. |
-define([ComplexExpression, BooleanMethods], { -- - @@ -522,6 +515,8 @@
null
] : the key that the hash corresponds to
-function (expr,key){ +function (expr,key,op){ 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)); + 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]; @@ -553,7 +548,7 @@@@ -675,14 +670,14 @@//(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); + return this.__filterObject(expr, k, op); }, this)); } else { newKey = [sql.stringToIdentifier(newKey[0])]; @@ -562,7 +557,7 @@
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})))); + 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); @@ -590,7 +585,7 @@
} //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(["AND"].concat(pairs)); + return pairs.length == 1 ? pairs[0] : BooleanExpression.fromArgs([op || "AND"].concat(pairs)); }
function (op){ if (op) { - var args = argsToArray(arguments,1 ); + var args = argsToArray(arguments, 1); //make a copy of the args var origArgs = args.slice(0); args.forEach(function (a, i) { @@ -572,25 +572,25 @@diff --git a/docs/patio_sql_DateTime.html b/docs/patio_sql_DateTime.html index 2162c62a..e2c5eaa9 100644 --- a/docs/patio_sql_DateTime.html +++ b/docs/patio_sql_DateTime.html @@ -421,9 +421,9 @@Constructor
op = op.toUpperCase(); if (N_ARITY_OPERATORS.hasOwnProperty(op)) { if (args.length < 1) { - throw new ExpressionError("The " + op + " operator requires at least 1 argument") + throw new ExpressionError("The " + op + " operator requires at least 1 argument"); } var oldArgs = args.slice(0); args = []; oldArgs.forEach(function (a) { - a instanceof ComplexExpression && a.op == op ? args = args.concat(a.args) : args.push(a); + a instanceof ComplexExpression && a.op === op ? args = args.concat(a.args) : args.push(a); }); } else if (TWO_ARITY_OPERATORS.hasOwnProperty(op)) { - if (args.length != 2) { + if (args.length !== 2) { throw new ExpressionError("The " + op + " operator requires precisely 2 arguments"); } //With IN/NOT IN, even if the second argument is an array of two element arrays, //don't convert it into a boolean expression, since it's definitely being used //as a value list. if (IN_OPERATORS[op]) { - args[1] = origArgs[1] + args[1] = origArgs[1]; } } else if (ONE_ARITY_OPERATORS.hasOwnProperty(op)) { - if (args.length != 1) { + if (args.length !== 1) { throw new ExpressionError("The " + op + " operator requires only one argument"); } } else { diff --git a/docs/patio_sql_Constants.html b/docs/patio_sql_Constants.html index 0badefc9..ae37584b 100644 --- a/docs/patio_sql_Constants.html +++ b/docs/patio_sql_Constants.html @@ -404,47 +404,47 @@ * Constant for CURRENT DATE * @type patio.sql.Constant */ - CURRENT_DATE:new Constant("CURRENT_DATE"), + CURRENT_DATE: new Constant("CURRENT_DATE"), /** * Constant for CURRENT TIME * @type patio.sql.Constant */ - CURRENT_TIME:new Constant("CURRENT_TIME"), + CURRENT_TIME: new Constant("CURRENT_TIME"), /** * Constant for CURRENT TIMESTAMP * @type patio.sql.Constant */ - CURRENT_TIMESTAMP:new Constant("CURRENT_TIMESTAMP"), + CURRENT_TIMESTAMP: new Constant("CURRENT_TIMESTAMP"), /** * Constant for TRUE * @type patio.sql.BooleanConstant */ - SQLTRUE:new BooleanConstant(1), + SQLTRUE: new BooleanConstant(1), /** * Constant for TRUE * @type patio.sql.BooleanConstant */ - TRUE:new BooleanConstant(1), + TRUE: new BooleanConstant(1), /** * Constant for FALSE. * @type patio.sql.BooleanConstant */ - SQLFALSE:new BooleanConstant(0), + SQLFALSE: new BooleanConstant(0), /** * Constant for FALSE * @type patio.sql.BooleanConstant */ - FALSE:new BooleanConstant(0), + FALSE: new BooleanConstant(0), /** * Constant for NULL * @type patio.sql.BooleanConstant */ - NULL:new BooleanConstant(null), + NULL: new BooleanConstant(null), /** * Constant for NOT NULL * @type patio.sql.NegativeBooleanConstant */ - NOTNULL:new NegativeBooleanConstant(null) + NOTNULL: new NegativeBooleanConstant(null) }
function (y,m,d,h,min,s,ms){ var args = argsToArray(arguments); - if(args.length === 0){ + if (args.length === 0) { this.date = new Date(); - }else if (isDate(y)) { + } else if (isDate(y)) { this.date = y; } else { var date = new Date(1970, 0, 1, 0, 0, 0); diff --git a/docs/patio_sql_Expression.html b/docs/patio_sql_Expression.html index 96ff841e..e763e87f 100644 --- a/docs/patio_sql_Expression.html +++ b/docs/patio_sql_Expression.html @@ -471,13 +471,6 @@Constructor
- - Source --define(null, { -- - @@ -531,9 +524,9 @@Source
function (args){ - var ret; + var ret, Self = this; try { - ret = new this(); + ret = new Self(); } catch (ignore) { } this.apply(ret, args); diff --git a/docs/patio_sql_InequalityMethods.html b/docs/patio_sql_InequalityMethods.html index 9174616c..abe746f5 100644 --- a/docs/patio_sql_InequalityMethods.html +++ b/docs/patio_sql_InequalityMethods.html @@ -568,7 +568,7 @@Source
function (items){ - return new BooleanExpression("AND", new BooleanExpression("gte", this, items[0]), new BooleanExpression("lte", this, items[1])) + return new BooleanExpression("AND", new BooleanExpression("gte", this, items[0]), new BooleanExpression("lte", this, items[1])); }diff --git a/docs/patio_sql_OrderedExpression.html b/docs/patio_sql_OrderedExpression.html index 492d433d..37bebc58 100644 --- a/docs/patio_sql_OrderedExpression.html +++ b/docs/patio_sql_OrderedExpression.html @@ -554,7 +554,7 @@Source
function (){ - return new OrderedExpression(this.__expression, false, {nulls:this.__nulls}); + return new OrderedExpression(this.__expression, false, {nulls: this.__nulls}); }@@ -597,7 +597,7 @@Source
function (){ - return new OrderedExpression(this.__expression, true, {nulls:this.__nulls}); + return new OrderedExpression(this.__expression, true, {nulls: this.__nulls}); }@@ -641,7 +641,7 @@Source
function (){ - return new OrderedExpression(this.__expression, !this.__descending, {nulls:this._static.INVERT_NULLS[this.__nulls] || this.__nulls}); + return new OrderedExpression(this.__expression, !this.__descending, {nulls: this._static.INVERT_NULLS[this.__nulls] || this.__nulls}); }diff --git a/docs/patio_sql_StringExpression.html b/docs/patio_sql_StringExpression.html index 08b2fde6..7424a6a7 100644 --- a/docs/patio_sql_StringExpression.html +++ b/docs/patio_sql_StringExpression.html @@ -445,7 +445,7 @@ Static Properties -
Property | Type | Default Value | Description | ||||||||
likeMap | Object | {"truetrue":'~*', "truefalse":"~", "falsetrue":"ILIKE", "falsefalse":"LIKE"} | Like map used to by patio.sql.StringExpression.like to create the +
function (expression){ expression = argsToArray(arguments); return StringExpression.like.apply(StringExpression, [this].concat(expression).concat([ - {caseInsensitive:true} + {caseInsensitive: true} ])); } diff --git a/lib/database/query.js b/lib/database/query.js index 1548e80b..aecf620f 100755 --- a/lib/database/query.js +++ b/lib/database/query.js @@ -282,7 +282,6 @@ var Database = define(null, { if (!isFunction(this.schemaParseTable)) { throw new Error("Schema parsing is not implemented on this database"); } - var ret = new Promise(); opts = opts || {}; var schemaParts = this.__schemaAndTable(table); var sch = schemaParts[0], tableName = schemaParts[1]; @@ -291,26 +290,21 @@ var Database = define(null, { if (opts.reload) { delete this.schemas[quotedName]; } - if (this.schemas[quotedName]) { - ret = this.schemas[quotedName]; - } else { - var self = this; - ret = this.schemas[quotedName] = this.schemaParseTable(tableName, opts).chain(function (cols) { - if (!cols || cols.length === 0) { - throw new Error("Error parsing schema, " + table + " no columns returns, table probably doesnt exist") - } else { - var schema = {}; - cols.forEach(function (c) { - var name = c[0]; - c = c[1]; - c.jsDefault = self.__columnSchemaToJsDefault(c["default"], c.type); - schema[name] = c; - }); - return schema; - } - }); - } - return ret.promise(); + var self = this; + return this.schemaParseTable(tableName, opts).chain(function (cols) { + if (!cols || cols.length === 0) { + throw new Error("Error parsing schema, " + table + " no columns returns, table probably doesnt exist") + } else { + var schema = {}; + cols.forEach(function (c) { + var name = c[0]; + c = c[1]; + c.jsDefault = self.__columnSchemaToJsDefault(c["default"], c.type); + schema[name] = c; + }); + return schema; + } + }); }, /** diff --git a/lib/dataset/query.js b/lib/dataset/query.js index 4622a6a0..ae96cf49 100755 --- a/lib/dataset/query.js +++ b/lib/dataset/query.js @@ -152,7 +152,7 @@ define(null, { var clause = (tOpts.having ? "having" : "where"), clauseObj = tOpts[clause]; if (clauseObj) { var args = argsToArray(arguments); - args = args.length == 1 ? args[0] : args; + args = args.length === 1 ? args[0] : args; var opts = {}; opts[clause] = new BooleanExpression("OR", clauseObj, this._filterExpr(args)); return this.mergeOptions(opts); @@ -261,7 +261,7 @@ define(null, { return this.or.apply(this, arguments); } else { var args = argsToArray(arguments); - args = args.length == 1 ? args[0] : args; + args = args.length === 1 ? args[0] : args; var opts = {}; opts[clause] = this._filterExpr(args, null, "AND"); return this.mergeOptions(opts); @@ -391,7 +391,7 @@ define(null, { cond = this._filterExpr.call(this, cond); cond = BooleanExpression.invert(cond); if (clauseObj) { - cond = new BooleanExpression("AND", clauseObj, cond) + cond = new BooleanExpression("AND", clauseObj, cond); } var opts = {}; opts[clause] = cond; @@ -526,17 +526,17 @@ define(null, { sources.push(new AliasedExpression(new Identifier(i), s[i])); } } else if (isString(s)) { - sources.push(this.stringToIdentifier(s)) + sources.push(this.stringToIdentifier(s)); } else { sources.push(s); } }, this); - var o = {from: sources.length ? sources : null} + var o = {from: sources.length ? sources : null}; if (tableAliasNum) { o.numDatasetSources = tableAliasNum; } - return this.mergeOptions(o) + return this.mergeOptions(o); }, /** @@ -564,7 +564,7 @@ define(null, { var fs = {}; var nonSqlOptions = this._static.NON_SQL_OPTIONS; Object.keys(this.__opts).forEach(function (k) { - if (nonSqlOptions.indexOf(k) == -1) { + if (nonSqlOptions.indexOf(k) === -1) { fs[k] = null; } }); @@ -652,7 +652,7 @@ define(null, { group: function (columns) { columns = argsToArray(arguments); var self = this; - return this.mergeOptions({group: (array.compact(columns).length == 0 ? null : columns.map(function (c) { + return this.mergeOptions({group: (array.compact(columns).length === 0 ? null : columns.map(function (c) { return isString(c) ? self.stringToIdentifier(c) : c; }))}); }, @@ -706,7 +706,7 @@ define(null, { **/ having: function () { var cond = argsToArray(arguments).map(function (s) { - return isString(s) && s !== '' ? this.stringToIdentifier(s) : s + return isString(s) && s !== '' ? this.stringToIdentifier(s) : s; }, this); return this._filter.apply(this, ["having"].concat(cond)); }, @@ -767,7 +767,7 @@ define(null, { if (!(having || where)) { throw new QueryError("No current filter"); } - var o = {} + var o = {}; if (having) { o.having = BooleanExpression.invert(having); } @@ -901,7 +901,7 @@ define(null, { var h; var usingJoin = isArray(expr) && expr.length && expr.every(function (x) { - return isString(x) || isInstanceOf(x, Identifier) + return isString(x) || isInstanceOf(x, Identifier); }); if (usingJoin && !this.supportsJoinUsing) { h = {}; @@ -936,7 +936,7 @@ define(null, { } else { table = isString(table) ? this.stringToIdentifier(table) : table; var parts = this._splitAlias(table), implicitTableAlias = parts[1]; - table = parts[0] + table = parts[0]; tableAlias = tableAlias || implicitTableAlias; tableName = tableAlias || table; } @@ -955,7 +955,7 @@ define(null, { var newExpr = []; for (var i in expr) { var val = expr[i]; - if (isArray(val) && val.length == 2) { + if (isArray(val) && val.length === 2) { i = val[0], val = val[1]; } var k = this.qualifiedColumnName(i, tableName), v; @@ -1010,7 +1010,7 @@ define(null, { if (this.__opts.sql) { return this.fromSelf().limit(limit, offset); } - if (isArray(limit) && limit.length == 2) { + if (isArray(limit) && limit.length === 2) { offset = limit[0]; limit = limit[1] - limit[0] + 1; } @@ -1941,7 +1941,7 @@ define(null, { throw new QueryError("This dataset does not support common table expressions"); } opts = opts || {}; - var wit = (this.__opts["with"] || []).concat([merge(opts, {recursive: true, name: this.stringToIdentifier(name), dataset: nonRecursive.union(recursive, {all: opts.unionAll != false, fromSelf: false})})]); + var wit = (this.__opts["with"] || []).concat([merge(opts, {recursive: true, name: this.stringToIdentifier(name), dataset: nonRecursive.union(recursive, {all: opts.unionAll !== false, fromSelf: false})})]); return this.mergeOptions({"with": wit}); }, @@ -1961,7 +1961,7 @@ define(null, { withSql: function (sql) { var args = argsToArray(arguments).slice(1); if (args.length) { - sql = new PlaceHolderLiteralString(sql, args) + sql = new PlaceHolderLiteralString(sql, args); } return this.mergeOptions({sql: sql}); }, @@ -2044,7 +2044,7 @@ define(null, { clause = (tOpts.having ? "having" : "where"), clauseObj = tOpts[clause]; var args = argsToArray(arguments, 2); - args = args.length == 1 ? args[0] : args; + args = args.length === 1 ? args[0] : args; var opts = {}; if (clauseObj) { addedByBool = isUndefined(addedByBool) ? "AND" : addedByBool; @@ -2066,8 +2066,8 @@ define(null, { if (cond.length && isFunction(cond[cond.length - 1])) { cb = cond.pop(); } - cond = cond.length == 1 ? cond[0] : cond - if ((cond == null || cond == undefined || cond === "") || (isArray(cond) && cond.length == 0 && !cb) || (isObject(cond) && isEmpty(cond) && !cb)) { + cond = cond.length === 1 ? cond[0] : cond; + if ((cond == null || cond === undefined || cond === "") || (isArray(cond) && cond.length === 0 && !cb) || (isObject(cond) && isEmpty(cond) && !cb)) { return this.mergeOptions(); } else { cond = this._filterExpr(cond, cb); @@ -2151,7 +2151,7 @@ define(null, { pairs.push(new BooleanExpression(op, new Identifier(pair[0]), pair[1])); }); } - return pairs.length == 1 ? pairs[0] : BooleanExpression.fromArgs(["AND"].concat(pairs)); + return pairs.length === 1 ? pairs[0] : BooleanExpression.fromArgs(["AND"].concat(pairs)); }, /** @@ -2180,7 +2180,7 @@ define(null, { throw new QueryError("Between requires an array for the value"); } } - var ret = pairs.length == 1 ? pairs[0] : BooleanExpression.fromArgs(["AND"].concat(pairs)) + var ret = pairs.length === 1 ? pairs[0] : BooleanExpression.fromArgs(["AND"].concat(pairs)); return invert ? BooleanExpression.invert(ret) : ret; }, @@ -2220,9 +2220,9 @@ define(null, { _filterExpr: function (expr, cb, joinCond) { expr = (isUndefined(expr) || isNull(expr) || (isArray(expr) && !expr.length)) ? null : expr; if (expr && cb) { - return new BooleanExpression(joinCond || "AND", this._filterExpr(expr, null, joinCond), this._filterExpr(cb, null, joinCond)) + return new BooleanExpression(joinCond || "AND", this._filterExpr(expr, null, joinCond), this._filterExpr(cb, null, joinCond)); } else if (cb) { - expr = cb + expr = cb; } if (isInstanceOf(expr, Expression)) { if (isInstanceOf(expr, NumericExpression, StringExpression)) { @@ -2235,7 +2235,7 @@ define(null, { if (isString(first)) { return new PlaceHolderLiteralString(first, expr.slice(1), true); } else if (Expression.isConditionSpecifier(expr)) { - return BooleanExpression.fromValuePairs(expr, joinCond) + return BooleanExpression.fromValuePairs(expr, joinCond); } else { return BooleanExpression.fromArgs([joinCond || "AND"].concat(expr.map(function (e) { return this._filterExpr(e, null, joinCond); @@ -2268,13 +2268,13 @@ define(null, { isSimpleSelectAll: function () { var o = {}, opts = this.__opts, count = 0; for (var i in opts) { - if (opts[i] != null && this._static.NON_SQL_OPTIONS.indexOf(i) == -1) { + if (opts[i] != null && this._static.NON_SQL_OPTIONS.indexOf(i) === -1) { o[i] = opts[i]; count++; } } - var f = o.from - return count == 1 && f.length == 1 && (isString(f[0]) || isInstanceOf(f[0], AliasedExpression, Identifier)); + var f = o.from; + return count === 1 && f.length === 1 && (isString(f[0]) || isInstanceOf(f[0], AliasedExpression, Identifier)); } } }, @@ -2345,5 +2345,4 @@ define(null, { this.QUERY_METHODS = queryMethods.concat(joinMethods); } } -}). - as(module); +}).as(module); diff --git a/lib/sql.js b/lib/sql.js index 8fcfb4aa..45f545a3 100755 --- a/lib/sql.js +++ b/lib/sql.js @@ -20,13 +20,11 @@ var comb = require("comb-proxy"), isString = comb.isString, define = comb.define, isRegExp = comb.isRegExp, - Dataset, patio; + Dataset, patio, sql, Expression, AliasedExpression, CaseExpression, Cast, + ColumnAll, BooleanExpression; var virtualRow = function (name) { - var WILDCARD = new LiteralString('*'); - var QUESTION_MARK = new LiteralString('?'); - var COMMA_SEPARATOR = new LiteralString(', '); var DOUBLE_UNDERSCORE = '__'; var parts = name.split(DOUBLE_UNDERSCORE); @@ -36,7 +34,7 @@ var virtualRow = function (name) { return function () { var args = argsToArray(arguments); return SQLFunction.fromArgs([m, name].concat(args)); - } + }; }, column ? QualifiedIdentifier : Identifier); var ret = createFunctionWrapper(prox, function (m) { var args = argsToArray(arguments); @@ -48,7 +46,7 @@ var virtualRow = function (name) { }, function () { return SQLFunction.fromArgs(arguments); }); - ret.__proto__ = ident; + ret["__proto__"] = ident; return ret; }; @@ -62,7 +60,7 @@ var DATE_METHODS = ["getDate", "getDay", "getFullYear", "getHours", "getMillisec var addDateMethod = function (op) { return function () { return this.date[op].apply(this.date, arguments); - } + }; }; /** @@ -219,9 +217,9 @@ DATE_METHODS.forEach(function (op) { */ var DateTime = function (y, m, d, h, min, s, ms) { var args = argsToArray(arguments); - if(args.length === 0){ + if (args.length === 0) { this.date = new Date(); - }else if (isDate(y)) { + } else if (isDate(y)) { this.date = y; } else { var date = new Date(1970, 0, 1, 0, 0, 0); @@ -370,7 +368,7 @@ var hashToArray = function (hash) { * @name sql * @memberOf patio */ -var sql = { +sql = { /**@lends patio.sql*/ /** @@ -396,14 +394,14 @@ var sql = { * * @return {patio.sql.Identifier|patio.sql.QualifiedIdentifier|patio.sql.AliasedExpression} an identifier generated based on the name string. */ - identifier:function (s) { + identifier: function (s) { return sql.stringToIdentifier(s); }, /** * @see patio.sql.identifier */ - stringToIdentifier:function (name) { + stringToIdentifier: function (name) { !Dataset && (Dataset = require("./dataset")); return new Dataset().stringToIdentifier(name); }, @@ -431,7 +429,7 @@ var sql = { * @return {patio.sql.LiteralString|patio.sql.PlaceHolderLiteralString} an expression that can be used as an argument * for {@link patio.Dataset} query methods. */ - literal:function (s) { + literal: function (s) { var args = argsToArray(arguments); return args.length > 1 ? PlaceHolderLiteralString.fromArgs(args) : new LiteralString(s); }, @@ -444,7 +442,7 @@ var sql = { * sql["case"]({a:sql.b}, sql.c, sql.d); //=> (CASE t.d WHEN t.a THEN t.b ELSE t.c END) * */ - "case":function (hash, /*args**/opts) { + "case": function (hash, /*args**/opts) { var args = argsToArray(arguments, 1); return CaseExpression.fromArgs([hashToArray(hash)].concat(args)); }, @@ -464,11 +462,11 @@ var sql = { * patio.sql.sqlStringJoin([sql.a, 'b']) # SQL: a || 'b' * patio.sql.sqlStringJoin(['a', sql.b], ' '); //=> 'a' || ' ' || b */ - sqlStringJoin:function (arr, joiner) { + sqlStringJoin: function (arr, joiner) { joiner = joiner || null; var args; arr = arr.map(function (a) { - return isInstanceOf(a, Expression, LiteralString, Boolean) || isNull(a) ? a : sql.stringToIdentifier(a) + return isInstanceOf(a, Expression, LiteralString, Boolean) || isNull(a) ? a : sql.stringToIdentifier(a); }); if (joiner) { var newJoiner = []; @@ -486,16 +484,16 @@ var sql = { return StringExpression.fromArgs(["||"].concat(args)); }, - Year:Year, - TimeStamp:TimeStamp, - Time:Time, - DateTime:DateTime, - Float:Float, - Decimal:Decimal + Year: Year, + TimeStamp: TimeStamp, + Time: Time, + DateTime: DateTime, + Float: Float, + Decimal: Decimal }; -sql.__defineGetter__("patio", function () { +sql["__defineGetter__"]("patio", function () { !patio && (patio = require("./index")); return patio; }); @@ -505,64 +503,66 @@ exports.sql = methodMissing(sql, function (name) { }); var OPERTATOR_INVERSIONS = { - AND:"OR", - OR:"AND", - GT:"lte", - GTE:"lt", - LT:"gte", - LTE:"gt", - EQ:"neq", - NEQ:"eq", - LIKE:'NOT LIKE', - "NOT LIKE":"LIKE", - '!~*':'~*', - '~*':'!~*', - "~":'!~', - "IN":'NOTIN', - "NOTIN":"IN", - "IS":'IS NOT', - "ISNOT":"IS", - NOT:"NOOP", - NOOP:"NOT", - ILIKE:'NOT ILIKE', - NOTILIKE:"ILIKE" + AND: "OR", + OR: "AND", + GT: "lte", + GTE: "lt", + LT: "gte", + LTE: "gt", + EQ: "neq", + NEQ: "eq", + LIKE: 'NOT LIKE', + "NOT LIKE": "LIKE", + '!~*': '~*', + '~*': '!~*', + "~": '!~', + "IN": 'NOTIN', + "NOTIN": "IN", + "IS": 'IS NOT', + "ISNOT": "IS", + NOT: "NOOP", + NOOP: "NOT", + ILIKE: 'NOT ILIKE', + NOTILIKE: "ILIKE" }; // Standard mathematical operators used in +NumericMethods+ -var MATHEMATICAL_OPERATORS = {PLUS:"+", MINUS:"-", DIVIDE:"/", MULTIPLY:"*"}; +var MATHEMATICAL_OPERATORS = {PLUS: "+", MINUS: "-", DIVIDE: "/", MULTIPLY: "*"}; // Bitwise mathematical operators used in +NumericMethods+ -var BITWISE_OPERATORS = {bitWiseAnd:"&", bitWiseOr:"|", exclusiveOr:"^", leftShift:"<<", rightShift:">>"}; +var BITWISE_OPERATORS = {bitWiseAnd: "&", bitWiseOr: "|", exclusiveOr: "^", leftShift: "<<", rightShift: ">>"}; -var INEQUALITY_OPERATORS = {GT:">", GTE:">=", LT:"<", LTE:"<="}; +var INEQUALITY_OPERATORS = {GT: ">", GTE: ">=", LT: "<", LTE: "<="}; //Hash of ruby operator symbols to SQL operators, used in +BooleanMethods+ -var BOOLEAN_OPERATORS = {AND:"AND", OR:"OR"}; +var BOOLEAN_OPERATORS = {AND: "AND", OR: "OR"}; //Operators that use IN/NOT IN for inclusion/exclusion -var IN_OPERATORS = {IN:"IN", NOTIN:'NOT IN'}; +var IN_OPERATORS = {IN: "IN", NOTIN: 'NOT IN'}; //Operators that use IS, used for special casing to override literal true/false values -var IS_OPERATORS = {IS:"IS", ISNOT:'IS NOT'}; +var IS_OPERATORS = {IS: "IS", ISNOT: 'IS NOT'}; //Operator symbols that take exactly two arguments var TWO_ARITY_OPERATORS = merge({ - EQ:'=', - NEQ:'!=', LIKE:"LIKE", - "NOT LIKE":'NOT LIKE', - ILIKE:"ILIKE", - "NOT ILIKE":'NOT ILIKE', - "~":"~", - '!~':"!~", - '~*':"~*", - '!~*':"!~*"}, INEQUALITY_OPERATORS, BITWISE_OPERATORS, IS_OPERATORS, IN_OPERATORS); + EQ: '=', + NEQ: '!=', + LIKE: "LIKE", + "NOT LIKE": 'NOT LIKE', + ILIKE: "ILIKE", + "NOT ILIKE": 'NOT ILIKE', + "~": "~", + '!~': "!~", + '~*': "~*", + '!~*': "!~*" +}, INEQUALITY_OPERATORS, BITWISE_OPERATORS, IS_OPERATORS, IN_OPERATORS); //Operator symbols that take one or more arguments -var N_ARITY_OPERATORS = merge({"||":"||"}, BOOLEAN_OPERATORS, MATHEMATICAL_OPERATORS); +var N_ARITY_OPERATORS = merge({"||": "||"}, BOOLEAN_OPERATORS, MATHEMATICAL_OPERATORS); //Operator symbols that take only a single argument -var ONE_ARITY_OPERATORS = {"NOT":"NOT", "NOOP":"NOOP"}; +var ONE_ARITY_OPERATORS = {"NOT": "NOT", "NOOP": "NOOP"}; /** * @class Mixin to provide alias methods to an expression. @@ -571,7 +571,7 @@ var ONE_ARITY_OPERATORS = {"NOT":"NOT", "NOOP":"NOOP"}; * @memberOf patio.sql */ var AliasMethods = define(null, { - instance:{ + instance: { /**@lends patio.sql.AliasMethods.prototype*/ /** @@ -587,7 +587,7 @@ var AliasMethods = define(null, { * * @return {patio.sql.AliasedExpression} the aliased expression. */ - as:function (alias) { + as: function (alias) { return new AliasedExpression(this, alias); } @@ -602,7 +602,7 @@ var bitWiseMethod = function (op) { else { return new BooleanExpression(op, this, expression); } - } + }; }; /** @@ -620,7 +620,7 @@ var bitWiseMethod = function (op) { * @memberOf patio.sql */ var BitWiseMethods = define(null, { - instance:{ + instance: { /**@lends patio.sql.BitWiseMethods.prototype*/ /** @@ -629,7 +629,7 @@ var BitWiseMethods = define(null, { * @example * sql.a.sqlNumber.bitWiseAnd("b"); //=> "a" & "b" */ - bitWiseAnd:bitWiseMethod("bitWiseAnd"), + bitWiseAnd: bitWiseMethod("bitWiseAnd"), /** * Bitwise or @@ -637,7 +637,7 @@ var BitWiseMethods = define(null, { * @example * sql.a.sqlNumber.bitWiseOr("b") //=> "a" | "b" */ - bitWiseOr:bitWiseMethod("bitWiseOr"), + bitWiseOr: bitWiseMethod("bitWiseOr"), /** * Exclusive Or @@ -646,7 +646,7 @@ var BitWiseMethods = define(null, { * * sql.a.sqlNumber.exclusiveOr("b") //=> "a" ^ "b" */ - exclusiveOr:bitWiseMethod("exclusiveOr"), + exclusiveOr: bitWiseMethod("exclusiveOr"), /** * Bitwise shift left @@ -655,7 +655,7 @@ var BitWiseMethods = define(null, { * * sql.a.sqlNumber.leftShift("b") // "a" << "b" */ - leftShift:bitWiseMethod("leftShift"), + leftShift: bitWiseMethod("leftShift"), /** * Bitwise shift right @@ -664,7 +664,7 @@ var BitWiseMethods = define(null, { * * sql.a.sqlNumber.rightShift("b") //=> "a" >> "b" */ - rightShift:bitWiseMethod("rightShift") + rightShift: bitWiseMethod("rightShift") } }).as(sql, "BitWiseMethods"); @@ -676,7 +676,7 @@ var booleanMethod = function (op) { else { return new BooleanExpression(op, this, expression); } - } + }; }; /** @@ -693,7 +693,7 @@ var booleanMethod = function (op) { * @memberOf patio.sql */ var BooleanMethods = define(null, { - instance:{ + instance: { /**@lends patio.sql.BooleanMethods.prototype*/ /** @@ -707,7 +707,7 @@ var BooleanMethods = define(null, { * * @return {patio.sql.BooleanExpression} a ANDed boolean expression. */ - and:booleanMethod("and"), + and: booleanMethod("and"), /** * @function @@ -719,7 +719,7 @@ var BooleanMethods = define(null, { * * @return {patio.sql.BooleanExpression} a ORed boolean expression */ - or:booleanMethod("or"), + or: booleanMethod("or"), /** * Logical NOT @@ -730,7 +730,7 @@ var BooleanMethods = define(null, { * * @return {patio.sql.BooleanExpression} a inverted boolean expression. */ - not:function () { + not: function () { return BooleanExpression.invert(this); } @@ -744,7 +744,7 @@ var BooleanMethods = define(null, { * @memberOf patio.sql */ var CastMethods = define(null, { - instance:{ + instance: { /**@lends patio.sql.CastMethods.prototype*/ /** * Cast the reciever to the given SQL type. @@ -756,7 +756,7 @@ var CastMethods = define(null, { * * @return {patio.sql.Cast} the casted expression */ - cast:function (type) { + cast: function (type) { return new Cast(this, type); }, @@ -772,7 +772,7 @@ var CastMethods = define(null, { * * @return {patio.sql.NumericExpression} a casted numberic expression */ - castNumeric:function (type) { + castNumeric: function (type) { return this.cast(type || "integer").sqlNumber; }, @@ -788,7 +788,7 @@ var CastMethods = define(null, { * * @return {patio.sql.StringExpression} the casted string expression */ - castString:function (type) { + castString: function (type) { return this.cast(type || String).sqlString; } } @@ -815,14 +815,14 @@ var CastMethods = define(null, { * */ var ComplexExpressionMethods = define(null, { - instance:{ + instance: { /**@ignore*/ - getters:{ + getters: { /** * @ignore */ - sqlBoolean:function () { + sqlBoolean: function () { return new BooleanExpression("noop", this); }, @@ -830,7 +830,7 @@ var ComplexExpressionMethods = define(null, { /** * @ignore */ - sqlFunction:function () { + sqlFunction: function () { return new SQLFunction(this); }, @@ -838,14 +838,14 @@ var ComplexExpressionMethods = define(null, { /** * @ignore */ - sqlNumber:function () { + sqlNumber: function () { return new NumericExpression("noop", this); }, /** * @ignore */ - sqlString:function () { + sqlString: function () { return new StringExpression("noop", this); } } @@ -854,16 +854,16 @@ var ComplexExpressionMethods = define(null, { var inequalityMethod = function (op) { return function (expression) { - if (isInstanceOf(expression, BooleanExpression) - || isBoolean(expression) - || isNull(expression) - || (isHash(expression)) - || isArray(expression)) { + if (isInstanceOf(expression, BooleanExpression) || + isBoolean(expression) || + isNull(expression) || + (isHash(expression)) || + isArray(expression)) { throw new ExpressionError("Cannot apply " + op + " to a boolean expression"); } else { return new BooleanExpression(op, this, expression); } - } + }; }; /** @@ -881,7 +881,7 @@ var inequalityMethod = function (op) { * @memberOf patio.sql */ var InequalityMethods = define(null, { - instance:{ + instance: { /**@lends patio.sql.InequalityMethods.prototype*/ /** @@ -892,7 +892,7 @@ var InequalityMethods = define(null, { * * @return {patio.sql.BooleanExpression} */ - gt:inequalityMethod("gt"), + gt: inequalityMethod("gt"), /** * @function Creates a gte {@link patio.sql.BooleanExpression} compared to this expression. * @@ -902,7 +902,7 @@ var InequalityMethods = define(null, { * * @return {patio.sql.BooleanExpression} */ - gte:inequalityMethod("gte"), + gte: inequalityMethod("gte"), /** * @function Creates a lt {@link patio.sql.BooleanExpression} compared to this expression. * @@ -912,7 +912,7 @@ var InequalityMethods = define(null, { * * @return {patio.sql.BooleanExpression} */ - lt:inequalityMethod("lt"), + lt: inequalityMethod("lt"), /** * @function Creates a lte {@link patio.sql.BooleanExpression} compared to this expression. * @@ -922,7 +922,7 @@ var InequalityMethods = define(null, { * * @return {patio.sql.BooleanExpression} */ - lte:inequalityMethod("lte"), + lte: inequalityMethod("lte"), /** * @function Creates a eq {@link patio.sql.BooleanExpression} compared to this expression. * @@ -932,9 +932,9 @@ var InequalityMethods = define(null, { * * @return {patio.sql.BooleanExpression} */ - eq:inequalityMethod("eq"), + eq: inequalityMethod("eq"), - neq:inequalityMethod("neq"), + neq: inequalityMethod("neq"), /** * @private @@ -950,8 +950,8 @@ var InequalityMethods = define(null, { * * @return {patio.sql.BooleanExpression} a boolean expression containing the between expression. */ - between:function (items) { - return new BooleanExpression("AND", new BooleanExpression("gte", this, items[0]), new BooleanExpression("lte", this, items[1])) + between: function (items) { + return new BooleanExpression("AND", new BooleanExpression("gte", this, items[0]), new BooleanExpression("lte", this, items[1])); } } }).as(sql, "InequalityMethods"); @@ -965,15 +965,15 @@ var InequalityMethods = define(null, { * @memberOf patio.sql */ var NoBooleanInputMethods = define(null, { - instance:{ - constructor:function (op) { + instance: { + constructor: function (op) { var args = argsToArray(arguments, 1); args.forEach(function (expression) { - if ((isInstanceOf(expression, BooleanExpression)) - || isBoolean(expression) - || isNull(expression) - || (isObject(expression) && !isInstanceOf(expression, Expression, Dataset, LiteralString)) - || isArray(expression)) { + if ((isInstanceOf(expression, BooleanExpression)) || + isBoolean(expression) || + isNull(expression) || + (isObject(expression) && !isInstanceOf(expression, Expression, Dataset, LiteralString)) || + isArray(expression)) { throw new ExpressionError("Cannot apply " + op + " to a boolean expression"); } }); @@ -989,7 +989,7 @@ var numericMethod = function (op) { } else { return new NumericExpression(op, this, expression); } - } + }; }; @@ -1007,7 +1007,7 @@ var numericMethod = function (op) { * @memberOf patio.sql */ var NumericMethods = define(null, { - instance:{ + instance: { /**@lends patio.sql.NumericMethods.prototype*/ @@ -1020,7 +1020,7 @@ var NumericMethods = define(null, { * * @return {patio.sql.NumericExpression} */ - plus:numericMethod("plus"), + plus: numericMethod("plus"), /** * @function Subtracts the provided expression from this expression and returns a {@link patio.sql.NumericExpression}. @@ -1031,7 +1031,7 @@ var NumericMethods = define(null, { * * @return {patio.sql.NumericExpression} */ - minus:numericMethod("minus"), + minus: numericMethod("minus"), /** * @function Divides this expression by the provided expression and returns a {@link patio.sql.NumericExpression}. @@ -1042,7 +1042,7 @@ var NumericMethods = define(null, { * * @return {patio.sql.NumericExpression} */ - divide:numericMethod("divide"), + divide: numericMethod("divide"), /** * @function Divides this expression by the provided expression and returns a {@link patio.sql.NumericExpression}. @@ -1053,7 +1053,7 @@ var NumericMethods = define(null, { * * @return {patio.sql.NumericExpression} */ - multiply:numericMethod("multiply") + multiply: numericMethod("multiply") } }).as(sql, "NumericMethods"); @@ -1072,7 +1072,7 @@ var NumericMethods = define(null, { * @memberOf patio.sql */ var OrderedMethods = define(null, { - instance:{ + instance: { /**@lends patio.sql.OrderedMethods.prototype*/ /** @@ -1087,7 +1087,7 @@ var OrderedMethods = define(null, { * before other values), or "last" to use NULLS LAST (so NULL values are ordered after other values). * @return {patio.sql.OrderedExpression} */ - asc:function (options) { + asc: function (options) { return new OrderedExpression(this, false, options); }, @@ -1103,7 +1103,7 @@ var OrderedMethods = define(null, { * before other values), or "last" to use NULLS LAST (so NULL values are ordered after other values). * @return {patio.sql.OrderedExpression} */ - desc:function (options) { + desc: function (options) { return new OrderedExpression(this, true, options); } } @@ -1123,7 +1123,7 @@ var OrderedMethods = define(null, { * @memberOf patio.sql */ var QualifyingMethods = define(null, { - instance:{ + instance: { /**@lends patio.sql.QualifyingMethods.prototype*/ /** @@ -1138,7 +1138,7 @@ var QualifyingMethods = define(null, { * * @return {patio.sql.QualifiedIdentifier} */ - qualify:function (qualifier) { + qualify: function (qualifier) { return new QualifiedIdentifier(qualifier, this); }, @@ -1152,7 +1152,7 @@ var QualifyingMethods = define(null, { * * @return {patio.sql.ColumnAll} */ - all:function () { + all: function () { return new ColumnAll(this); } @@ -1174,7 +1174,7 @@ var QualifyingMethods = define(null, { * @memberOf patio.sql */ var StringMethods = define(null, { - instance:{ + instance: { /**@lends patio.sql.StringMethods.prototype*/ /** @@ -1186,10 +1186,10 @@ var StringMethods = define(null, { * * @return {patio.sql.BooleanExpression} */ - ilike:function (expression) { + ilike: function (expression) { expression = argsToArray(arguments); return StringExpression.like.apply(StringExpression, [this].concat(expression).concat([ - {caseInsensitive:true} + {caseInsensitive: true} ])); }, @@ -1203,7 +1203,7 @@ var StringMethods = define(null, { * * @param expression */ - like:function (expression) { + like: function (expression) { expression = argsToArray(arguments); return StringExpression.like.apply(StringExpression, [this].concat(expression)); } @@ -1221,7 +1221,7 @@ var StringMethods = define(null, { * @memberOf patio.sql */ var StringConcatenationMethods = define(null, { - instance:{ + instance: { /**@lends patio.sql.StringConcatenationMethods.prototype*/ /** @@ -1234,7 +1234,7 @@ var StringConcatenationMethods = define(null, { * * @param expression expression to concatenate this expression with. */ - concat:function (expression) { + concat: function (expression) { return new StringExpression("||", this, expression); } } @@ -1252,7 +1252,7 @@ var StringConcatenationMethods = define(null, { * @memberOf patio.sql */ var SubscriptMethods = define(null, { - instance:{ + instance: { /** * Return a {@link patio.sql.Subscript} with the given arguments, representing an @@ -1265,7 +1265,7 @@ var SubscriptMethods = define(null, { * * @param subscript */ - sqlSubscript:function (subscript) { + sqlSubscript: function (subscript) { var args = argsToArray(arguments); return new SubScript(this, flatten(args)); } @@ -1279,9 +1279,9 @@ var SubscriptMethods = define(null, { * @name Expression * @memberOf patio.sql */ -var Expression = define(null, { +Expression = define(null, { - instance:{ + instance: { /**@lends patio.sql.Expression.prototype*/ /** @@ -1290,13 +1290,13 @@ var Expression = define(null, { * @param {patio.Dataset} ds the dataset that will be used to SQL-ify this expression. * @return {String} a string literal version of this expression. */ - sqlLiteral:function (ds) { + sqlLiteral: function (ds) { return this.toString(ds); } }, - static:{ + static: { /**@lends patio.sql.Expression*/ /** @@ -1310,10 +1310,10 @@ var Expression = define(null, { * * @return {patio.sql.Expression} an expression. */ - fromArgs:function (args) { - var ret; + fromArgs: function (args) { + var ret, Self = this; try { - ret = new this(); + ret = new Self(); } catch (ignore) { } this.apply(ret, args); @@ -1333,7 +1333,7 @@ var Expression = define(null, { * @param {*} obj object to test if it is a condition specifier * @return {Boolean} true if the object is a Hash or is an array of two element arrays. */ - isConditionSpecifier:function (obj) { + isConditionSpecifier: function (obj) { return isHash(obj) || (isArray(obj) && obj.length && obj.every(function (i) { return isArray(i) && i.length === 2; })); @@ -1362,8 +1362,8 @@ var Expression = define(null, { var GenericExpression = define([Expression, AliasMethods, BooleanMethods, CastMethods, ComplexExpressionMethods, InequalityMethods, NumericMethods, OrderedMethods, StringMethods, SubscriptMethods]).as(sql, "GenericExpression"); -var AliasedExpression = define(Expression, { - instance:{ +AliasedExpression = define(Expression, { + instance: { /**@lends patio.sql.AliasedExpression.prototype*/ /** @@ -1379,7 +1379,7 @@ var AliasedExpression = define(Expression, { * @property alias the alias of the expression * */ - constructor:function (expression, alias) { + constructor: function (expression, alias) { this.expression = expression; this.alias = alias; }, @@ -1391,7 +1391,7 @@ var AliasedExpression = define(Expression, { * * @return String the SQL alias fragment. */ - toString:function (ds) { + toString: function (ds) { !Dataset && (Dataset = require("./dataset")); ds = ds || new Dataset(); return ds.aliasedExpressionSql(this); @@ -1401,8 +1401,8 @@ var AliasedExpression = define(Expression, { ).as(sql, "AliasedExpression"); -var CaseExpression = define(GenericExpression, { - instance:{ +CaseExpression = define(GenericExpression, { + instance: { /**@lends patio.sql.CaseExpression.prototype*/ /** @@ -1423,7 +1423,7 @@ var CaseExpression = define(GenericExpression, { * @property expression the expression of the {@link patio.sql.CaseExpression}. * @property {Boolean} noExpression true if this {@link patio.sql.CaseExpression}'s expression is undefined. */ - constructor:function (conditions, def, expression) { + constructor: function (conditions, def, expression) { if (Expression.isConditionSpecifier(conditions)) { this.conditions = toArray(conditions); this.def = def; @@ -1440,16 +1440,16 @@ var CaseExpression = define(GenericExpression, { * * @return String the SQL case expression fragment. */ - toString:function (ds) { + toString: function (ds) { !Dataset && (Dataset = require("./dataset")); ds = ds || new Dataset(); return ds.caseExpressionSql(this); }, /**@ignore*/ - getters:{ + getters: { /**@ignore*/ - hasExpression:function () { + hasExpression: function () { return !this.noExpression; } } @@ -1457,8 +1457,8 @@ var CaseExpression = define(GenericExpression, { }).as(sql, "CaseExpression"); -var Cast = define(GenericExpression, { - instance:{ +Cast = define(GenericExpression, { + instance: { /**@lends patio.sql.Cast*/ /** @@ -1472,7 +1472,7 @@ var Cast = define(GenericExpression, { * @property expr the expression to CAST. * @property type the type to CAST the expression to. */ - constructor:function (expr, type) { + constructor: function (expr, type) { this.expr = expr; this.type = type; }, @@ -1485,7 +1485,7 @@ var Cast = define(GenericExpression, { * * @return String the SQL cast expression fragment. */ - toString:function (ds) { + toString: function (ds) { !Dataset && (Dataset = require("./dataset")); ds = ds || new Dataset(); return ds.castSql(this.expr, this.type); @@ -1494,8 +1494,8 @@ var Cast = define(GenericExpression, { }).as(sql, "Cast"); -var ColumnAll = define(Expression, { - instance:{ +ColumnAll = define(Expression, { + instance: { /**@lends patio.sql.ColumnAll.prototype*/ /** @@ -1508,7 +1508,7 @@ var ColumnAll = define(Expression, { * * @property table the table this all column expression represents. */ - constructor:function (table) { + constructor: function (table) { this.table = table; }, @@ -1520,7 +1520,7 @@ var ColumnAll = define(Expression, { * * @return String the SQL columnAll expression fragment. */ - toString:function (ds) { + toString: function (ds) { !Dataset && (Dataset = require("./dataset")); ds = ds || new Dataset(); return ds.columnAllSql(this); @@ -1529,7 +1529,7 @@ var ColumnAll = define(Expression, { }).as(sql, "ColumnAll"); var ComplexExpression = define([Expression, AliasMethods, CastMethods, OrderedMethods, SubscriptMethods], { - instance:{ + instance: { /**@lends patio.sql.ComplexExpression.prototype*/ /** @@ -1558,9 +1558,9 @@ var ComplexExpression = define([Expression, AliasMethods, CastMethods, OrderedMe * other than the second arg for an IN/NOT IN operator. * */ - constructor:function (op) { + constructor: function (op) { if (op) { - var args = argsToArray(arguments,1 ); + var args = argsToArray(arguments, 1); //make a copy of the args var origArgs = args.slice(0); args.forEach(function (a, i) { @@ -1572,26 +1572,26 @@ var ComplexExpression = define([Expression, AliasMethods, CastMethods, OrderedMe if (N_ARITY_OPERATORS.hasOwnProperty(op)) { if (args.length < 1) { - throw new ExpressionError("The " + op + " operator requires at least 1 argument") + throw new ExpressionError("The " + op + " operator requires at least 1 argument"); } var oldArgs = args.slice(0); args = []; oldArgs.forEach(function (a) { - a instanceof ComplexExpression && a.op == op ? args = args.concat(a.args) : args.push(a); + a instanceof ComplexExpression && a.op === op ? args = args.concat(a.args) : args.push(a); }); } else if (TWO_ARITY_OPERATORS.hasOwnProperty(op)) { - if (args.length != 2) { + if (args.length !== 2) { throw new ExpressionError("The " + op + " operator requires precisely 2 arguments"); } //With IN/NOT IN, even if the second argument is an array of two element arrays, //don't convert it into a boolean expression, since it's definitely being used //as a value list. if (IN_OPERATORS[op]) { - args[1] = origArgs[1] + args[1] = origArgs[1]; } } else if (ONE_ARITY_OPERATORS.hasOwnProperty(op)) { - if (args.length != 1) { + if (args.length !== 1) { throw new ExpressionError("The " + op + " operator requires only one argument"); } } else { @@ -1610,14 +1610,14 @@ var ComplexExpression = define([Expression, AliasMethods, CastMethods, OrderedMe * * @return String the SQL version of the {@link patio.sql.ComplexExpression}. */ - toString:function (ds) { + toString: function (ds) { !Dataset && (Dataset = require("./dataset")); ds = ds || new Dataset(); return ds.complexExpressionSql(this.op, this.args); } }, - static:{ + static: { /**@lends patio.sql.ComplexExpression*/ /** @@ -1647,7 +1647,7 @@ var ComplexExpression = define([Expression, AliasMethods, CastMethods, OrderedMe * NOTILIKE:"ILIKE" * } */ - OPERATOR_INVERSIONS:OPERTATOR_INVERSIONS, + OPERATOR_INVERSIONS: OPERTATOR_INVERSIONS, /** * Default mathematical operators. @@ -1655,7 +1655,7 @@ var ComplexExpression = define([Expression, AliasMethods, CastMethods, OrderedMe * @type Object * @default {PLUS:"+", MINUS:"-", DIVIDE:"/", MULTIPLY:"*"} */ - MATHEMATICAL_OPERATORS:MATHEMATICAL_OPERATORS, + MATHEMATICAL_OPERATORS: MATHEMATICAL_OPERATORS, /** * Default bitwise operators. @@ -1663,14 +1663,14 @@ var ComplexExpression = define([Expression, AliasMethods, CastMethods, OrderedMe * @type Object * @default {bitWiseAnd:"&", bitWiseOr:"|", exclusiveOr:"^", leftShift:"<<", rightShift:">>"} */ - BITWISE_OPERATORS:BITWISE_OPERATORS, + BITWISE_OPERATORS: BITWISE_OPERATORS, /** * Default inequality operators. * * @type Object * @default {GT:">",GTE:">=",LT:"<",LTE:"<="} */ - INEQUALITY_OPERATORS:INEQUALITY_OPERATORS, + INEQUALITY_OPERATORS: INEQUALITY_OPERATORS, /** * Default boolean operators. @@ -1678,7 +1678,7 @@ var ComplexExpression = define([Expression, AliasMethods, CastMethods, OrderedMe * @type Object * @default {AND:"AND",OR:"OR"} */ - BOOLEAN_OPERATORS:BOOLEAN_OPERATORS, + BOOLEAN_OPERATORS: BOOLEAN_OPERATORS, /** * Default IN operators. @@ -1686,14 +1686,14 @@ var ComplexExpression = define([Expression, AliasMethods, CastMethods, OrderedMe * @type Object * @default {IN:"IN",NOTIN:'NOT IN'} */ - IN_OPERATORS:IN_OPERATORS, + IN_OPERATORS: IN_OPERATORS, /** * Default IS operators. * * @type Object * @default {IS:"IS", ISNOT:'IS NOT'} */ - IS_OPERATORS:IS_OPERATORS, + IS_OPERATORS: IS_OPERATORS, /** * Default two arity operators. * @@ -1723,7 +1723,7 @@ var ComplexExpression = define([Expression, AliasMethods, CastMethods, OrderedMe * NOTIN:'NOT IN' * } */ - TWO_ARITY_OPERATORS:TWO_ARITY_OPERATORS, + TWO_ARITY_OPERATORS: TWO_ARITY_OPERATORS, /** * Default N(multi) arity operators. @@ -1738,7 +1738,7 @@ var ComplexExpression = define([Expression, AliasMethods, CastMethods, OrderedMe * DIVIDE:"/", MULTIPLY:"*" * } */ - N_ARITY_OPERATORS:N_ARITY_OPERATORS, + N_ARITY_OPERATORS: N_ARITY_OPERATORS, /** * Default ONE operators. @@ -1749,7 +1749,7 @@ var ComplexExpression = define([Expression, AliasMethods, CastMethods, OrderedMe * "NOOP":"NOOP" * } */ - ONE_ARITY_OPERATORS:ONE_ARITY_OPERATORS + ONE_ARITY_OPERATORS: ONE_ARITY_OPERATORS } }).as(sql, "ComplexExpression"); @@ -1763,8 +1763,8 @@ var ComplexExpression = define([Expression, AliasMethods, CastMethods, OrderedMe * @name BooleanExpression * @memberOf patio.sql */ -var BooleanExpression = define([ComplexExpression, BooleanMethods], { - static:{ +BooleanExpression = define([ComplexExpression, BooleanMethods], { + static: { /**@lends patio.sql.BooleanExpression*/ /** @@ -1781,10 +1781,10 @@ var BooleanExpression = define([ComplexExpression, BooleanMethods], { * * @return {patio.sql.BooleanExpression} the inverted expression. */ - invert:function (expression) { + invert: function (expression) { if (isInstanceOf(expression, BooleanExpression)) { var op = expression.op, newArgs; - if (op == "AND" || op == "OR") { + if (op === "AND" || op === "OR") { newArgs = [OPERTATOR_INVERSIONS[op]].concat(expression.args.map(function (arg) { return BooleanExpression.invert(arg); })); @@ -1829,20 +1829,20 @@ var BooleanExpression = define([ComplexExpression, BooleanMethods], { * * @return {patio.sql.BooleanExpression} expression composed of sub expressions built from the hash. */ - fromValuePairs:function (a, op, negate) { + fromValuePairs: 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)); + 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(function (i) { - return isString(i) ? sql.stringToIdentifier(i) : i + return isString(i) ? sql.stringToIdentifier(i) : i; }) : isString(k) ? sql.stringToIdentifier(k) : k; ret = new BooleanExpression("IN", k, v); } else if (isInstanceOf(v, NegativeBooleanConstant)) { @@ -1852,7 +1852,7 @@ var BooleanExpression = define([ComplexExpression, BooleanMethods], { } else if (isNull(v) || isBoolean(v)) { ret = new BooleanExpression("IS", k, v); } else if (isHash(v)) { - ret = BooleanExpression.__filterObject(v, k); + ret = BooleanExpression.__filterObject(v, k, op); } else if (isRegExp(v)) { ret = StringExpression.like(sql.stringToIdentifier(k), v); } else { @@ -1887,13 +1887,13 @@ var BooleanExpression = define([ComplexExpression, BooleanMethods], { * * @return {patio.sql.Expression} an expression to use in the filter */ - __filterObject:function (expr, key) { + __filterObject: function (expr, key, op) { 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)); + 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]; @@ -1902,7 +1902,7 @@ var BooleanExpression = define([ComplexExpression, BooleanMethods], { //(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); + return this.__filterObject(expr, k, op); }, this)); } else { newKey = [sql.stringToIdentifier(newKey[0])]; @@ -1912,7 +1912,7 @@ var BooleanExpression = define([ComplexExpression, BooleanMethods], { 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})))); + 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); @@ -1940,14 +1940,14 @@ var BooleanExpression = define([ComplexExpression, BooleanMethods], { } //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(["AND"].concat(pairs)); + return pairs.length == 1 ? pairs[0] : BooleanExpression.fromArgs([op || "AND"].concat(pairs)); } } }).as(sql, "BooleanExpression"); var Constant = define(GenericExpression, { - instance:{ + instance: { /**@lends patio.sql.Constant.prototype*/ /** * Represents constants or psuedo-constants (e.g.'CURRENT_DATE) in SQL. @@ -1956,7 +1956,7 @@ var Constant = define(GenericExpression, { * @augments patio.sql.GenericExpression * @property {String} constant READ ONLY the contant. */ - constructor:function (constant) { + constructor: function (constant) { this.__constant = constant; }, @@ -1968,14 +1968,14 @@ var Constant = define(GenericExpression, { * * @return String the SQL version of the {@link patio.sql.Constant}. */ - toString:function (ds) { + toString: function (ds) { !Dataset && (Dataset = require("./dataset")); ds = ds || new Dataset(); return ds.constantSql(this.__constant); }, - getters:{ - constant:function () { + getters: { + constant: function () { return this.__constant; } } @@ -1989,7 +1989,7 @@ var Constant = define(GenericExpression, { * @memberOf patio.sql */ var BooleanConstant = define(Constant, { - instance:{ + instance: { /**@lends patio.sql.BooleanConstant.prototype*/ /** @@ -2000,7 +2000,7 @@ var BooleanConstant = define(Constant, { * * @return String the SQL version of the {@link patio.sql.BooleanConstant}. */ - toString:function (ds) { + toString: function (ds) { !Dataset && (Dataset = require("./dataset")); ds = ds || new Dataset(); return ds.booleanConstantSql(this.__constant); @@ -2017,7 +2017,7 @@ var BooleanConstant = define(Constant, { * @memberOf patio.sql */ var NegativeBooleanConstant = define(BooleanConstant, { - instance:{ + instance: { /**@lends patio.sql.NegativeBooleanConstant.prototype*/ /** @@ -2028,7 +2028,7 @@ var NegativeBooleanConstant = define(BooleanConstant, { * * @return String the SQL version of the {@link patio.sql.NegativeBooleanConstant}. */ - toString:function (ds) { + toString: function (ds) { !Dataset && (Dataset = require("./dataset")); ds = ds || new Dataset(); return ds.negativeBooleanConstantSql(this.__constant); @@ -2049,61 +2049,61 @@ sql.Constants = { * Constant for CURRENT DATE * @type patio.sql.Constant */ - CURRENT_DATE:new Constant("CURRENT_DATE"), + CURRENT_DATE: new Constant("CURRENT_DATE"), /** * Constant for CURRENT TIME * @type patio.sql.Constant */ - CURRENT_TIME:new Constant("CURRENT_TIME"), + CURRENT_TIME: new Constant("CURRENT_TIME"), /** * Constant for CURRENT TIMESTAMP * @type patio.sql.Constant */ - CURRENT_TIMESTAMP:new Constant("CURRENT_TIMESTAMP"), + CURRENT_TIMESTAMP: new Constant("CURRENT_TIMESTAMP"), /** * Constant for TRUE * @type patio.sql.BooleanConstant */ - SQLTRUE:new BooleanConstant(1), + SQLTRUE: new BooleanConstant(1), /** * Constant for TRUE * @type patio.sql.BooleanConstant */ - TRUE:new BooleanConstant(1), + TRUE: new BooleanConstant(1), /** * Constant for FALSE. * @type patio.sql.BooleanConstant */ - SQLFALSE:new BooleanConstant(0), + SQLFALSE: new BooleanConstant(0), /** * Constant for FALSE * @type patio.sql.BooleanConstant */ - FALSE:new BooleanConstant(0), + FALSE: new BooleanConstant(0), /** * Constant for NULL * @type patio.sql.BooleanConstant */ - NULL:new BooleanConstant(null), + NULL: new BooleanConstant(null), /** * Constant for NOT NULL * @type patio.sql.NegativeBooleanConstant */ - NOTNULL:new NegativeBooleanConstant(null) + NOTNULL: new NegativeBooleanConstant(null) }; var Constants = sql.Constants var Identifier = define([GenericExpression, QualifyingMethods], { - instance:{ + instance: { /**@lends patio.sql.Identifier.prototype*/ /** @@ -2119,7 +2119,7 @@ var Identifier = define([GenericExpression, QualifyingMethods], { * * @property {String} value READ ONLY the column or table this identifier represents. */ - constructor:function (value) { + constructor: function (value) { this.__value = value; }, @@ -2131,15 +2131,15 @@ var Identifier = define([GenericExpression, QualifyingMethods], { * * @return String the SQL version of the {@link patio.sql.Identifier}. */ - toString:function (ds) { + toString: function (ds) { !Dataset && (Dataset = require("./dataset")); ds = ds || new Dataset(); return ds.quoteIdentifier(this); }, /**@ignore*/ - getters:{ - value:function () { + getters: { + value: function () { return this.__value; } } @@ -2147,7 +2147,7 @@ var Identifier = define([GenericExpression, QualifyingMethods], { }).as(sql, "Identifier"); var JoinClause = define(Expression, { - instance:{ + instance: { /**@lends patio.sql.JoinClause.prototype*/ /** @@ -2164,7 +2164,7 @@ var JoinClause = define(Expression, { * @property table READ ONLY the table to join with * @property joinType READ ONLY the alias to use for this join clause * */ - constructor:function (joinType, table, tableAlias) { + constructor: function (joinType, table, tableAlias) { this.__joinType = joinType; this.__table = table; this.__tableAlias = tableAlias || null; @@ -2178,23 +2178,23 @@ var JoinClause = define(Expression, { * * @return String the SQL version of the {@link patio.sql.JoinClause}. */ - toString:function (ds) { + toString: function (ds) { !Dataset && (Dataset = require("./dataset")); ds = ds || new Dataset(); return ds.joinClauseSql(this); }, /**@ignore*/ - getters:{ - joinType:function () { + getters: { + joinType: function () { return this.__joinType; }, - table:function () { + table: function () { return this.__table; }, - tableAlias:function () { + tableAlias: function () { return this.__tableAlias; } } @@ -2203,7 +2203,7 @@ var JoinClause = define(Expression, { var JoinOnClause = define(JoinClause, { - instance:{ + instance: { /**@lends patio.sql.JoinOnClause.prototype*/ /** * Represents an SQL JOIN clause with ON conditions. Created by {@link patio.Dataset} join methods. @@ -2214,7 +2214,7 @@ var JoinOnClause = define(JoinClause, { * @param on the expression to filter with. See {@link patio.Dataset#filter} * @property on READ ONLY the filter to use with joining the datasets. */ - constructor:function (on, joinType, table, tableAlias) { + constructor: function (on, joinType, table, tableAlias) { this.__on = on; this._super(arguments, [joinType, table, tableAlias]); }, @@ -2227,15 +2227,15 @@ var JoinOnClause = define(JoinClause, { * * @return String the SQL version of the {@link patio.sql.JoinOnClause}. */ - toString:function (ds) { + toString: function (ds) { !Dataset && (Dataset = require("./dataset")); ds = ds || new Dataset(); return ds.joinOnClauseSql(this); }, /**@ignore*/ - getters:{ - on:function () { + getters: { + on: function () { return this.__on; } } @@ -2244,7 +2244,7 @@ var JoinOnClause = define(JoinClause, { var JoinUsingClause = define(JoinClause, { - instance:{ + instance: { /**@lends patio.sql.JoinUsingClause.prototype*/ /** @@ -2258,7 +2258,7 @@ var JoinUsingClause = define(JoinClause, { * @param using the column/s to use when joining. * @property using READ ONLY the column/s to use when joining. */ - constructor:function (using, joinType, table, tableAlias) { + constructor: function (using, joinType, table, tableAlias) { this.__using = using.map(function (u) { return isString(u) ? new Identifier(u) : u; }); @@ -2273,15 +2273,15 @@ var JoinUsingClause = define(JoinClause, { * * @return String the SQL version of the {@link patio.sql.JoinUsingClause}. */ - toString:function (ds) { + toString: function (ds) { !Dataset && (Dataset = require("./dataset")); ds = ds || new Dataset(); return ds.joinUsingClauseSql(this); }, /**@ignore*/ - getters:{ - using:function () { + getters: { + using: function () { return this.__using; } } @@ -2290,7 +2290,7 @@ var JoinUsingClause = define(JoinClause, { var PlaceHolderLiteralString = define(GenericExpression, { - instance:{ + instance: { /**@lends patio.sql.PlaceHolderLiteralString.prototype*/ /** @@ -2312,7 +2312,7 @@ var PlaceHolderLiteralString = define(GenericExpression, { * replaced in the string. * @property {String} parens READ ONLY set to true to wrap the string in parens. */ - constructor:function (str, args, parens) { + constructor: function (str, args, parens) { parens = parens || false; var v; this.__str = str; @@ -2328,22 +2328,22 @@ var PlaceHolderLiteralString = define(GenericExpression, { * * @return String the SQL version of the {@link patio.sql.PlaceHolderLiteralString}. */ - toString:function (ds) { + toString: function (ds) { !Dataset && (Dataset = require("./dataset")); ds = ds || new Dataset(); return ds.placeholderLiteralStringSql(this); }, /**@ignore*/ - getters:{ - str:function () { + getters: { + str: function () { return this.__str; }, - args:function () { + args: function () { return this.__args; }, - parens:function () { + parens: function () { return this.__parens; } @@ -2353,7 +2353,7 @@ var PlaceHolderLiteralString = define(GenericExpression, { var SQLFunction = define(GenericExpression, { - instance:{ + instance: { /**@lends patio.sql.SQLFunction.prototype*/ /** @@ -2370,7 +2370,7 @@ var SQLFunction = define(GenericExpression, { * @property {Array} args READ ONLY args arguments will be literalized through * {@link patio.Dataset#literal} and placed into the SQL function call. * */ - constructor:function (f) { + constructor: function (f) { var args = argsToArray(arguments).slice(1); this.__f = isInstanceOf(f, Identifier) ? f.value : f, this.__args = args.map(function (a) { return isString(a) ? sql.stringToIdentifier(a) : a; @@ -2385,19 +2385,19 @@ var SQLFunction = define(GenericExpression, { * * @return String the SQL version of the {@link patio.sql.SQLFunction}. */ - toString:function (ds) { + toString: function (ds) { !Dataset && (Dataset = require("./dataset")); ds = ds || new Dataset(); return ds.functionSql(this); }, /**@ignore*/ - getters:{ - f:function () { + getters: { + f: function () { return this.__f; }, - args:function () { + args: function () { return this.__args; } } @@ -2419,7 +2419,7 @@ var NumericExpression = define([ComplexExpression, BitWiseMethods, NumericMethod var OrderedExpression = define(Expression, { - instance:{ + instance: { /**@lends patio.sql.OrderedExpression.prototype*/ /** @@ -2441,7 +2441,7 @@ var OrderedExpression = define(Expression, { * @property {String} [nulls=null] if value is "first" the null values will be first, if "last" then null values * will be last */ - constructor:function (expression, descending, opts) { + constructor: function (expression, descending, opts) { descending = isBoolean(descending) ? descending : true; opts = opts || {}; this.__expression = expression; @@ -2453,22 +2453,22 @@ var OrderedExpression = define(Expression, { /** * @return {patio.sql.OrderedExpression} a copy that is ordered ASC */ - asc:function () { - return new OrderedExpression(this.__expression, false, {nulls:this.__nulls}); + asc: function () { + return new OrderedExpression(this.__expression, false, {nulls: this.__nulls}); }, /** * @return {patio.sql.OrderedExpression} Return a copy that is ordered DESC */ - desc:function () { - return new OrderedExpression(this.__expression, true, {nulls:this.__nulls}); + desc: function () { + return new OrderedExpression(this.__expression, true, {nulls: this.__nulls}); }, /** * * @return {patio.sql.OrderedExpression} an inverted expression, changing ASC to DESC and NULLS FIRST to NULLS LAST. * */ - invert:function () { - return new OrderedExpression(this.__expression, !this.__descending, {nulls:this._static.INVERT_NULLS[this.__nulls] || this.__nulls}); + invert: function () { + return new OrderedExpression(this.__expression, !this.__descending, {nulls: this._static.INVERT_NULLS[this.__nulls] || this.__nulls}); }, /** @@ -2479,38 +2479,38 @@ var OrderedExpression = define(Expression, { * * @return String the SQL version of the {@link patio.sql.OrderedExpression}. */ - toString:function (ds) { + toString: function (ds) { !Dataset && (Dataset = require("./dataset")); ds = ds || new Dataset(); return ds.orderedExpressionSql(this); }, /**@ignore*/ - getters:{ - expression:function () { + getters: { + expression: function () { return this.__expression; }, - descending:function () { + descending: function () { return this.__descending; }, - nulls:function () { + nulls: function () { return this.__nulls; } } }, - static:{ + static: { /**@lends patio.sql.OrderedExpression*/ /** * Hash that contains the inversions for "first" and "last". * @type Object * @default {first:"last", last:"first"} */ - INVERT_NULLS:{first:"last", last:"first"} + INVERT_NULLS: {first: "last", last: "first"} } }).as(sql, "OrderedExpression"); var QualifiedIdentifier = define([GenericExpression, QualifyingMethods], { - instance:{ + instance: { /**@lends patio.sql.QualifiedIdentifier.prototype*/ /** @@ -2526,7 +2526,7 @@ var QualifiedIdentifier = define([GenericExpression, QualifyingMethods], { * @property table READ ONLY the table or schema to qualify the column or table to. * @property column READ ONLY he column or table to qualify. */ - constructor:function (table, column) { + constructor: function (table, column) { this.__table = table; this.__column = column; }, @@ -2539,19 +2539,19 @@ var QualifiedIdentifier = define([GenericExpression, QualifyingMethods], { * * @return String the SQL version of the {@link patio.sql.QualifiedIdentifier}. */ - toString:function (ds) { + toString: function (ds) { !Dataset && (Dataset = require("./dataset")); ds = ds || new Dataset(); return ds.qualifiedIdentifierSql(this); }, /**@ignore*/ - getters:{ - table:function () { + getters: { + table: function () { return this.__table; }, - column:function () { + column: function () { return this.__column; } } @@ -2581,7 +2581,7 @@ var likeElement = function (re) { * @memberOf patio.sql */ var StringExpression = define([ComplexExpression, StringMethods, StringConcatenationMethods, InequalityMethods, NoBooleanInputMethods], { - static:{ + static: { /**@lends patio.sql.StringExpression*/ /** @@ -2609,7 +2609,7 @@ var StringExpression = define([ComplexExpression, StringMethods, StringConcatena * StringExpression.like(sql.a, 'a%', {caseInsensitive : true}) //=> "a" ILIKE 'a%' * StringExpression.like(sql.a, 'a%', /^a/i) //=> "a" LIKE 'a%' OR "a" ~* '^a' */ - like:function (l) { + like: function (l) { var args = argsToArray(arguments, 1); var params = likeElement(l); var likeMap = this.likeMap; @@ -2630,14 +2630,14 @@ var StringExpression = define([ComplexExpression, StringMethods, StringConcatena * LIKE expression. * @type Object */ - likeMap:{"truetrue":'~*', "truefalse":"~", "falsetrue":"ILIKE", "falsefalse":"LIKE"} + likeMap: {"truetrue": '~*', "truefalse": "~", "falsetrue": "ILIKE", "falsefalse": "LIKE"} } }).as(sql, "StringExpression"); var SubScript = define(GenericExpression, { - instance:{ + instance: { /**@lends patio.sql.SubScript.prototype*/ /** @@ -2648,7 +2648,7 @@ var SubScript = define(GenericExpression, { * @param arrCol the SQL array column * @param sub The array of subscripts to use (should be an array of numbers) */ - constructor:function (arrCol, sub) { + constructor: function (arrCol, sub) { //The SQL array column this.__arrCol = arrCol; //The array of subscripts to use (should be an array of numbers) @@ -2659,7 +2659,7 @@ var SubScript = define(GenericExpression, { * Create a new {@link patio.sql.Subscript} appending the given subscript(s) * the the current array of subscripts. */ - addSub:function (sub) { + addSub: function (sub) { return new SubScript(this.__arrCol, this.__sub.concat(sub)); }, @@ -2671,19 +2671,19 @@ var SubScript = define(GenericExpression, { * * @return String the SQL version of the {@link patio.sql.SubScript}. */ - toString:function (ds) { + toString: function (ds) { !Dataset && (Dataset = require("./dataset")); ds = ds || new Dataset(); return ds.subscriptSql(this); }, /**@ignore*/ - getters:{ - f:function () { + getters: { + f: function () { return this.__arrCol; }, - sub:function () { + sub: function () { return this.__sub; } } @@ -2702,7 +2702,7 @@ var addStringMethod = function (op) { }; var LiteralString = define([OrderedMethods, ComplexExpressionMethods, BooleanMethods, NumericMethods, StringMethods, InequalityMethods, AliasMethods], { - instance:{ + instance: { /**@lends patio.sql.LiteralString*/ /** @@ -2719,7 +2719,7 @@ var LiteralString = define([OrderedMethods, ComplexExpressionMethods, BooleanMet * * @param {String} str the literal string. */ - constructor:function (str) { + constructor: function (str) { this.__str = str; } } diff --git a/package.json b/package.json index c7eb3aaf..2edee0f8 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "patio", "description": "Patio query engine and ORM", - "version": "0.2.14", + "version": "0.2.15", "keywords": [ "ORM", "object relation mapper", diff --git a/test/adapters/mysql.test.js b/test/adapters/mysql.test.js index 34b3e459..6fec7860 100644 --- a/test/adapters/mysql.test.js +++ b/test/adapters/mysql.test.js @@ -650,6 +650,7 @@ if (process.env.PATIO_DB === "mysql" || process.env.NODE_ENV === 'test-coverage' assert.deepEqual(sqls, [ "CREATE TABLE items (id integer, list enum('one'))", "DESCRIBE items", + "DESCRIBE items", "ALTER TABLE items CHANGE COLUMN id id int(8) UNSIGNED NULL", "ALTER TABLE items CHANGE COLUMN list list enum('two') NULL" ]); @@ -1313,4 +1314,4 @@ if (process.env.PATIO_DB === "mysql" || process.env.NODE_ENV === 'test-coverage' return patio.disconnect(); }); }); -} \ No newline at end of file +} diff --git a/test/dataset/query.test.js b/test/dataset/query.test.js index 8761d48e..8618691e 100755 --- a/test/dataset/query.test.js +++ b/test/dataset/query.test.js @@ -14,7 +14,7 @@ var it = require('it'), hitch = comb.hitch; -it.describe("Dataset queries",function (it) { +it.describe("Dataset queries", function (it) { patio.identifierInputMethod = null; patio.identifierOutputMethod = null; @@ -471,6 +471,10 @@ it.describe("Dataset queries",function (it) { ['y', 3] ]).sql, "SELECT * FROM test WHERE ((x = 1) AND ((y = 2) OR (y = 3)))"); }); + + it.should("work with hashes", function () { + assert.equal(d1.andGroupedOr({y: "z", z: "y"}).sql, "SELECT * FROM test WHERE ((x = 1) AND ((y = 'z') OR (z = 'y')))"); + }); }); it.describe("#andGroupedAnd", function (it) { @@ -2335,4 +2339,4 @@ it.describe("Dataset queries",function (it) { it.afterAll(comb.hitch(patio, "disconnect")); -}).as(module); +}); \ No newline at end of file |