lib/query-interface.js
var Utils = require(__dirname + '/utils')
, DataTypes = require(__dirname + '/data-types')
, SQLiteQueryInterface = require(__dirname + '/dialects/sqlite/query-interface')
, Transaction = require(__dirname + '/transaction')
, QueryTypes = require('./query-types')
module.exports = (function() {
var QueryInterface = function(sequelize) {
this.sequelize = sequelize
this.QueryGenerator = require('./dialects/' + this.sequelize.options.dialect + '/query-generator')
this.QueryGenerator.options = this.sequelize.options
this.QueryGenerator._dialect = this.sequelize.dialect
this.QueryGenerator.sequelize = this.sequelize
}
Utils.addEventEmitter(QueryInterface)
QueryInterface.prototype.createSchema = function(schema) {
var sql = this.QueryGenerator.createSchema(schema)
return queryAndEmit.call(this, sql, 'createSchema')
}
QueryInterface.prototype.dropSchema = function(schema) {
var sql = this.QueryGenerator.dropSchema(schema)
return queryAndEmit.call(this, sql, 'dropSchema')
}
QueryInterface.prototype.dropAllSchemas = function() {
var self = this
return new Utils.CustomEventEmitter(function(emitter) {
var chainer = new Utils.QueryChainer()
self.showAllSchemas().success(function(schemaNames) {
schemaNames.forEach(function(schemaName) {
chainer.add(self.dropSchema(schemaName))
})
chainer
.run()
.success(function() {
self.emit('dropAllSchemas', null)
emitter.emit('success', null)
})
.error(function(err) {
self.emit('dropAllSchemas', err)
emitter.emit('error', err)
})
}).error(function(err) {
self.emit('dropAllSchemas', err)
emitter.emit('error', err)
})
}).run()
}
QueryInterface.prototype.showAllSchemas = function(options) {
var self = this
options = Utils._.extend({
transaction: null,
raw: true
}, options || {})
return new Utils.CustomEventEmitter(function(emitter) {
var showSchemasSql = self.QueryGenerator.showSchemasQuery()
self.sequelize.query(showSchemasSql, null, options).success(function(schemaNames) {
self.emit('showAllSchemas', null)
emitter.emit('success', Utils._.flatten(Utils._.map(schemaNames, function(value){ return (!!value.schema_name ? value.schema_name : value) })))
}).error(function(err) {
self.emit('showAllSchemas', err)
emitter.emit('error', err)
})
}).run()
}
QueryInterface.prototype.createTable = function(tableName, attributes, options) {
var attributeHashes = {}
, dataTypeValues = Utils._.values(DataTypes)
, keys = Object.keys(attributes)
, keyLen = keys.length
, self = this
, sql = ''
, i = 0
for (i = 0; i < keyLen; i++) {
if (dataTypeValues.indexOf(attributes[keys[i]]) > -1) {
attributeHashes[keys[i]] = { type: attributes[keys[i]], allowNull: true }
} else {
attributeHashes[keys[i]] = attributes[keys[i]]
}
}
options = Utils._.extend({
logging: this.sequelize.options.logging
}, options || {})
return new Utils.CustomEventEmitter(function(emitter) {
// Postgres requires a special SQL command for enums
if (self.sequelize.options.dialect === "postgres") {
var chainer = new Utils.QueryChainer()
// For backwards-compatibility, public schemas don't need to
// explicitly state their schema when creating a new enum type
, getTableName = (!options || !options.schema || options.schema === "public" ? '' : options.schema + '_') + tableName
for (i = 0; i < keyLen; i++) {
if (attributes[keys[i]].toString().match(/^ENUM\(/) || attributes[keys[i]].toString() === "ENUM" || (attributes[keys[i]].type && attributes[keys[i]].type.toString() === "ENUM")) {
sql = self.QueryGenerator.pgListEnums(getTableName, keys[i], options)
chainer.add(self.sequelize.query(sql, null, { plain: true, raw: true, type: QueryTypes.SELECT, logging: options.logging }))
}
}
chainer.runSerially().success(function(results) {
var chainer2 = new Utils.QueryChainer()
// Find the table that we're trying to create throgh DAOFactoryManager
, daoTable = self.sequelize.daoFactoryManager.daos.filter(function(dao) { return dao.tableName === tableName })
, enumIdx = 0
daoTable = daoTable.length > 0 ? daoTable[0] : null
for (i = 0; i < keyLen; i++) {
if (attributes[keys[i]].toString().match(/^ENUM\(/) || attributes[keys[i]].toString() === "ENUM" || (attributes[keys[i]].type && attributes[keys[i]].type.toString() === "ENUM")) {
// If the enum type doesn't exist then create it
if (!results[enumIdx]) {
sql = self.QueryGenerator.pgEnum(getTableName, keys[i], attributes[keys[i]], options)
chainer2.add(self.sequelize.query(sql, null, { raw: true, logging: options.logging }))
} else if (!!results[enumIdx] && !!daoTable) {
var enumVals = self.QueryGenerator.fromArray(results[enumIdx].enum_value)
, vals = daoTable.rawAttributes[keys[i]].values
vals.forEach(function(value, idx) {
// reset out after/before options since it's for every enum value
options.before = null
options.after = null
if (enumVals.indexOf(value) === -1) {
if (!!vals[idx+1]) {
options.before = vals[idx+1]
}
else if (!!vals[idx-1]) {
options.after = vals[idx-1]
}
chainer2.add(self.sequelize.query(self.QueryGenerator.pgEnumAdd(getTableName, keys[i], value, options)))
}
})
enumIdx++
}
}
}
attributes = self.QueryGenerator.attributesToSQL(attributeHashes)
sql = self.QueryGenerator.createTableQuery(tableName, attributes, options)
chainer2.run().success(function() {
queryAndEmit
.call(self, sql, 'createTable', options)
.success(function(res) {
self.emit('createTable', null)
emitter.emit('success', res)
})
.error(function(err) {
self.emit('createTable', err)
emitter.emit('error', err)
})
.on('sql', function(sql) {
emitter.emit('sql', sql)
})
}).error(function(err) {
emitter.emit('error', err)
}).on('sql', function(sql) {
emitter.emit('sql', sql)
})
})
} else {
attributes = self.QueryGenerator.attributesToSQL(attributeHashes)
sql = self.QueryGenerator.createTableQuery(tableName, attributes, options)
queryAndEmit.call(self, sql, 'createTable', options).success(function(results) {
self.emit('createTable', null)
emitter.emit('success', results)
}).error(function(err) {
self.emit('createTable', err)
emitter.emit('error', err)
}).on('sql', function(sql) {
emitter.emit('sql', sql)
})
}
}).run()
}
QueryInterface.prototype.dropTable = function(tableName, options) {
// if we're forcing we should be cascading unless explicitly stated otherwise
options = options || {}
options.cascade = options.cascade || options.force || false
var sql = this.QueryGenerator.dropTableQuery(tableName, options)
, self = this
return new Utils.CustomEventEmitter(function(emitter) {
var chainer = new Utils.QueryChainer()
chainer.add(self, 'queryAndEmit', [sql, 'dropTable'], options)
// Since postgres has a special case for enums, we should drop the related
// enum type within the table and attribute
if (self.sequelize.options.dialect === "postgres") {
// Find the table that we're trying to drop
daoTable = self.sequelize.daoFactoryManager.daos.filter(function(dao) {
return dao.tableName === tableName
})
// Just in case if we're trying to drop a non-existing table
daoTable = daoTable.length > 0 ? daoTable[0] : null
if (!!daoTable) {
var getTableName = (!options || !options.schema || options.schema === "public" ? '' : options.schema + '_') + tableName
var keys = Object.keys(daoTable.rawAttributes)
, keyLen = keys.length
, i = 0
for (i = 0; i < keyLen; i++) {
if (daoTable.rawAttributes[keys[i]].type && daoTable.rawAttributes[keys[i]].type.toString() === "ENUM") {
chainer.add(self.sequelize, 'query', [self.QueryGenerator.pgEnumDrop(getTableName, keys[i]), null, {logging: options.logging, raw: true}])
}
}
}
}
chainer.runSerially().success(function(results) {
emitter.emit('success', results[0])
self.emit('dropTable', null)
}).error(function(err) {
emitter.emit('error', err)
self.emit('dropTable', err)
}).on('sql', function(sql) {
emitter.emit('sql', sql)
})
}).run()
}
QueryInterface.prototype.dropAllTables = function(options) {
var self = this
if (!options) {
options = {}
}
var skip = options.skip || [];
if (this.sequelize.options.dialect === 'sqlite') {
// sqlite needs some special treatment as it cannot drop a column
return SQLiteQueryInterface.dropAllTables.call(this, options)
} else {
return new Utils.CustomEventEmitter(function(dropAllTablesEmitter) {
var events = []
, chainer = new Utils.QueryChainer()
, onError = function(err) {
self.emit('dropAllTables', err)
dropAllTablesEmitter.emit('error', err)
}
self.showAllTables().success(function(tableNames) {
self.getForeignKeysForTables(tableNames).success(function(foreignKeys) {
// add the foreign key removal query to the chainer
Object.keys(foreignKeys).forEach(function(tableName) {
foreignKeys[tableName].forEach(function(foreignKey) {
var sql = self.QueryGenerator.dropForeignKeyQuery(tableName, foreignKey)
chainer.add(self.sequelize, 'query', [ sql ])
})
})
// add the table removal query to the chainer
tableNames.forEach(function(tableName) {
// if tableName is not in the Array of tables names then dont drop it
if (skip.indexOf(tableName) === -1) {
chainer.add(self, 'dropTable', [ tableName, { cascade: true } ])
}
})
chainer
.runSerially()
.success(function() {
self.emit('dropAllTables', null)
dropAllTablesEmitter.emit('success', null)
})
.error(onError)
}).error(onError)
}).error(onError)
}).run()
}
}
QueryInterface.prototype.dropAllEnums = function(options) {
if (this.sequelize.getDialect() !== 'postgres') {
return new Utils.CustomEventEmitter(function (emitter) {
emitter.emit('success')
}).run()
}
options = options || {}
var self = this
, emitter = new Utils.CustomEventEmitter()
, chainer = new Utils.QueryChainer()
, sql = this.QueryGenerator.pgListEnums()
this.sequelize.query(sql, null, { plain: false, raw: true, type: QueryTypes.SELECT, logging: options.logging })
.proxy(emitter, {events: ['sql', 'error']})
.success(function (results) {
results.forEach(function (result) {
chainer.add(self.sequelize.query(
self.QueryGenerator.pgEnumDrop(null, null, result.enum_name),
null,
{logging: options.logging, raw: true}
))
})
chainer.run().proxy(emitter)
})
return emitter
}
QueryInterface.prototype.renameTable = function(before, after) {
var sql = this.QueryGenerator.renameTableQuery(before, after)
return queryAndEmit.call(this, sql, 'renameTable')
}
QueryInterface.prototype.showAllTables = function(options) {
var self = this
options = Utils._.extend({
transaction: null,
raw: true
}, options || {})
return new Utils.CustomEventEmitter(function(emitter) {
var showTablesSql = self.QueryGenerator.showTablesQuery()
self.sequelize.query(showTablesSql, null, options).success(function(tableNames) {
self.emit('showAllTables', null)
emitter.emit('success', Utils._.flatten(tableNames))
}).error(function(err) {
self.emit('showAllTables', err)
emitter.emit('error', err)
})
}).run()
}
QueryInterface.prototype.describeTable = function(tableName, options) {
var self = this
, schema = null
, schemaDelimiter = null
if (typeof options === "string") {
schema = options
}
else if (typeof options === "object") {
schema = options.schema || null
schemaDelimiter = options.schemaDelimiter || null
}
return new Utils.CustomEventEmitter(function(emitter) {
var sql;
if (self.QueryGenerator.describeTableQuery) {
sql = self.QueryGenerator.describeTableQuery(tableName, schema, schemaDelimiter)
} else {
var table = self.QueryGenerator.quoteIdentifier(self.QueryGenerator.addSchema({tableName: tableName, options: {schema: schema, schemaDelimiter: schemaDelimiter}}), self.QueryGenerator.options.quoteIdentifiers)
sql = 'DESCRIBE ' + table + ';'
}
self.sequelize.query(sql, null, { raw: true }).success(function(data) {
if(Utils._.isEmpty(data)) {
// If no data is returned from the query, then the table name may be wrong.
// Query generators that use information_schema for retrieving table info will just return an empty result set,
// it will not throw an error like built-ins do (e.g. DESCRIBE on MySql).
emitter.emit('error', 'No description found for "' + tableName + '" table. Check the table name and schema; remember, they _are_ case sensitive.')
} else {
emitter.emit('success', data)
}
}).error(function(err) {
emitter.emit('error', err)
}).on('sql', function(sql) {
emitter.emit('sql', sql)
})
}).run()
}
QueryInterface.prototype.addColumn = function(tableName, attributeName, dataTypeOrOptions) {
var attributes = {}
if (Utils._.values(DataTypes).indexOf(dataTypeOrOptions) > -1) {
attributes[attributeName] = { type: dataTypeOrOptions, allowNull: true }
} else {
attributes[attributeName] = dataTypeOrOptions
}
var options = this.QueryGenerator.attributesToSQL(attributes)
, sql = this.QueryGenerator.addColumnQuery(tableName, options)
return queryAndEmit.call(this, sql, 'addColumn')
}
QueryInterface.prototype.removeColumn = function(tableName, attributeName) {
if (this.sequelize.options.dialect === 'sqlite') {
// sqlite needs some special treatment as it cannot drop a column
return new Utils.CustomEventEmitter(function(emitter) {
SQLiteQueryInterface.removeColumn.call(this, tableName, attributeName, emitter, queryAndEmit)
}.bind(this)).run()
} else {
var sql = this.QueryGenerator.removeColumnQuery(tableName, attributeName)
return queryAndEmit.call(this, sql, 'removeColumn')
}
}
QueryInterface.prototype.changeColumn = function(tableName, attributeName, dataTypeOrOptions) {
var attributes = {}
if (Utils._.values(DataTypes).indexOf(dataTypeOrOptions) > -1) {
attributes[attributeName] = { type: dataTypeOrOptions, allowNull: true }
} else {
attributes[attributeName] = dataTypeOrOptions
}
if (this.sequelize.options.dialect === 'sqlite') {
// sqlite needs some special treatment as it cannot change a column
return new Utils.CustomEventEmitter(function(emitter) {
SQLiteQueryInterface.changeColumn.call(this, tableName, attributes, emitter, queryAndEmit)
}.bind(this)).run()
} else {
var options = this.QueryGenerator.attributesToSQL(attributes)
, sql = this.QueryGenerator.changeColumnQuery(tableName, options)
return queryAndEmit.call(this, sql, 'changeColumn')
}
}
QueryInterface.prototype.renameColumn = function(tableName, attrNameBefore, attrNameAfter) {
return new Utils.CustomEventEmitter(function(emitter) {
this.describeTable(tableName).success(function(data) {
data = data[attrNameBefore] || {}
var options = {}
options[attrNameAfter] = {
attribute: attrNameAfter,
type: data.type,
allowNull: data.allowNull,
defaultValue: data.defaultValue
}
if (this.sequelize.options.dialect === 'sqlite') {
// sqlite needs some special treatment as it cannot rename a column
SQLiteQueryInterface.renameColumn.call(this, tableName, attrNameBefore, attrNameAfter, emitter, queryAndEmit)
} else {
var sql = this.QueryGenerator.renameColumnQuery(tableName,
attrNameBefore,
this.QueryGenerator.attributesToSQL(options)
)
queryAndEmit.call(this, sql, 'renameColumn', {}, emitter)
}
}.bind(this))
.error(function(err) {
this.emit('renameColumn', err)
emitter.emit('error', err)
}.bind(this))
}.bind(this)).run()
}
QueryInterface.prototype.addIndex = function(tableName, attributes, options) {
var sql = this.QueryGenerator.addIndexQuery(tableName, attributes, options)
return queryAndEmit.call(this, sql, 'addIndex')
}
QueryInterface.prototype.showIndex = function(tableName, options) {
var sql = this.QueryGenerator.showIndexQuery(tableName, options)
return queryAndEmit.call(this, sql, 'showIndex')
}
QueryInterface.prototype.getForeignKeysForTables = function(tableNames) {
var self = this
return new Utils.CustomEventEmitter(function(emitter) {
if (tableNames.length === 0) {
emitter.emit('success', {})
} else {
var chainer = new Utils.QueryChainer()
tableNames.forEach(function(tableName) {
var sql = self.QueryGenerator.getForeignKeysQuery(tableName, self.sequelize.config.database)
chainer.add(self.sequelize, 'query', [sql])
})
chainer.runSerially().proxy(emitter, {
skipEvents: ['success']
}).success(function(results) {
var result = {}
tableNames.forEach(function(tableName, i) {
result[tableName] = Utils._.compact(results[i]).map(function(r) { return r.constraint_name })
})
emitter.emit('success', result)
})
}
}).run()
}
QueryInterface.prototype.removeIndex = function(tableName, indexNameOrAttributes) {
var sql = this.QueryGenerator.removeIndexQuery(tableName, indexNameOrAttributes)
return queryAndEmit.call(this, sql, "removeIndex")
}
QueryInterface.prototype.insert = function(dao, tableName, values, options) {
var sql = this.QueryGenerator.insertQuery(tableName, values, dao.daoFactory.rawAttributes)
return queryAndEmit.call(this, [sql, dao, options], 'insert', {
success: function(obj) { obj.isNewRecord = false }
})
}
QueryInterface.prototype.bulkInsert = function(tableName, records, options) {
var sql = this.QueryGenerator.bulkInsertQuery(tableName, records, options)
return queryAndEmit.call(this, [sql, null, options], 'bulkInsert')
}
QueryInterface.prototype.update = function(dao, tableName, values, identifier, options) {
var self = this
, restrict = false
, sql = self.QueryGenerator.updateQuery(tableName, values, identifier, options, dao.daoFactory.rawAttributes)
// Check for a restrict field
if (!!dao.daoFactory && !!dao.daoFactory.associations) {
var keys = Object.keys(dao.daoFactory.associations)
, length = keys.length
for (var i = 0; i < length; i++) {
if (dao.daoFactory.associations[keys[i]].options && dao.daoFactory.associations[keys[i]].options.onUpdate && dao.daoFactory.associations[keys[i]].options.onUpdate === "restrict") {
restrict = true
}
}
}
return new Utils.CustomEventEmitter(function(emitter) {
var chainer = new Utils.QueryChainer()
chainer.add(self, 'queryAndEmit', [[sql, dao, options], 'delete'])
chainer.runSerially()
.success(function(results){
emitter.query = { sql: sql }
emitter.emit('success', results[0])
emitter.emit('sql', sql)
})
.error(function(err) {
emitter.query = { sql: sql }
emitter.emit('error', err)
emitter.emit('sql', sql)
})
.on('sql', function(sql) {
emitter.emit('sql', sql)
})
}).run()
}
QueryInterface.prototype.bulkUpdate = function(tableName, values, identifier, options) {
var self = this
, sql = self.QueryGenerator.updateQuery(tableName, values, identifier, options)
return new Utils.CustomEventEmitter(function(emitter) {
var chainer = new Utils.QueryChainer()
chainer.add(self, 'queryAndEmit', [[sql, null, options], 'bulkUpdate'])
return chainer.runSerially()
.success(function(results){
emitter.query = { sql: sql }
emitter.emit('sql', sql)
emitter.emit('success', results[0])
})
.error(function(err) {
emitter.query = { sql: sql }
emitter.emit('sql', sql)
emitter.emit('error', err)
})
}).run()
}
QueryInterface.prototype.delete = function(dao, tableName, identifier, options) {
var self = this
, restrict = false
, cascades = []
, sql = self.QueryGenerator.deleteQuery(tableName, identifier, null, dao.daoFactory)
// Check for a restrict field
if (!!dao.daoFactory && !!dao.daoFactory.associations) {
var keys = Object.keys(dao.daoFactory.associations)
, length = keys.length
for (var i = 0; i < length; i++) {
if (dao.daoFactory.associations[keys[i]].options && dao.daoFactory.associations[keys[i]].options.onDelete) {
if (dao.daoFactory.associations[keys[i]].options.onDelete === "restrict") {
restrict = true
}
else if (dao.daoFactory.associations[keys[i]].options.onDelete === "cascade" && dao.daoFactory.associations[keys[i]].options.useHooks === true) {
cascades[cascades.length] = dao.daoFactory.associations[keys[i]].accessors.get
}
}
}
}
return new Utils.CustomEventEmitter(function(emitter) {
var tick = 0
var iterate = function(err, i) {
if (!!err || i >= cascades.length) {
return run(err)
}
dao[cascades[i]]().success(function(tasks) {
if (tasks === null || tasks.length < 1) {
return run()
}
tasks = Array.isArray(tasks) ? tasks : [tasks]
var ii = 0
var next = function(err, ii) {
if (!!err || ii >= tasks.length) {
return iterate(err)
}
tasks[ii].destroy().error(function(err) {
return iterate(err)
})
.success(function() {
ii++
if (ii >= tasks.length) {
tick++
return iterate(null, tick)
}
next(null, ii)
})
}
next(null, ii)
})
}
var run = function(err) {
if (!!err) {
return emitter.emit('error', err)
}
var chainer = new Utils.QueryChainer()
chainer.add(self, 'queryAndEmit', [[sql, dao, options], 'delete'])
chainer.runSerially()
.success(function(results){
emitter.query = { sql: sql }
emitter.emit('sql', sql)
emitter.emit('success', results[1])
})
.error(function(err) {
emitter.query = { sql: sql }
emitter.emit('sql', sql)
emitter.emit('error', err)
})
}
if (cascades.length > 0) {
iterate(null, tick)
} else {
run()
}
}).run()
}
QueryInterface.prototype.bulkDelete = function(tableName, identifier, options) {
var self = this
var sql = self.QueryGenerator.deleteQuery(tableName, identifier, Utils._.defaults(options || {}, {limit: null}))
return new Utils.CustomEventEmitter(function(emitter) {
var chainer = new Utils.QueryChainer()
chainer.add(self, 'queryAndEmit', [[sql, null, options], 'bulkDelete', options])
chainer.runSerially()
.success(function(results){
emitter.query = { sql: sql }
emitter.emit('sql', sql)
emitter.emit('success', results[0])
})
.error(function(err) {
emitter.query = { sql: sql }
emitter.emit('sql', sql)
emitter.emit('error', err)
})
}).run()
}
QueryInterface.prototype.select = function(factory, tableName, options, queryOptions) {
options = options || {}
// See if we need to merge options and factory.scopeObj
// we're doing this on the QueryInterface level because it's a bridge between
// sequelize and the databases
if (Object.keys(factory.scopeObj).length > 0) {
if (!!options) {
Utils.injectScope.call(factory, options, true)
}
var scopeObj = buildScope.call(factory)
Object.keys(scopeObj).forEach(function(method) {
if (typeof scopeObj[method] === "number" || !Utils._.isEmpty(scopeObj[method])) {
options[method] = scopeObj[method]
}
})
}
var sql = this.QueryGenerator.selectQuery(tableName, options, factory)
queryOptions = Utils._.extend({}, queryOptions, {
include: options.include,
includeNames: options.includeNames,
includeMap: options.includeMap,
hasSingleAssociation: options.hasSingleAssociation,
hasMultiAssociation: options.hasMultiAssociation
})
return queryAndEmit.call(this, [sql, factory, queryOptions], 'select')
}
QueryInterface.prototype.increment = function(dao, tableName, values, identifier, options) {
var sql = this.QueryGenerator.incrementQuery(tableName, values, identifier, options.attributes)
return queryAndEmit.call(this, [sql, dao, options], 'increment')
}
QueryInterface.prototype.rawSelect = function(tableName, options, attributeSelector) {
var self = this
if (attributeSelector === undefined) {
throw new Error('Please pass an attribute selector!')
}
return new Utils.CustomEventEmitter(function(emitter) {
var sql = self.QueryGenerator.selectQuery(tableName, options)
, queryOptions = Utils._.extend({ transaction: options.transaction }, { plain: true, raw: true, type: QueryTypes.SELECT })
, query = self.sequelize.query(sql, null, queryOptions)
query
.success(function(data) {
var result = data ? (data[attributeSelector] || data[attributeSelector.toUpperCase()]) : null
if (options && options.dataType) {
var dataType = options.dataType;
if (dataType instanceof DataTypes.DECIMAL || dataType instanceof DataTypes.FLOAT) {
result = parseFloat(result);
} else if (dataType === DataTypes.INTEGER || dataType instanceof DataTypes.BIGINT) {
result = parseInt(result, 10);
} else if (dataType === DataTypes.DATE) {
result = new Date(result + 'Z');
} else if (dataType === DataTypes.STRING) {
// Nothing to do, result is already a string.
}
}
self.emit('rawSelect', null)
emitter.emit('success', result)
})
.error(function(err) {
self.emit('rawSelect', err)
emitter.emit('error', err)
})
.on('sql', function(sql) {
emitter.emit('sql', sql)
})
}).run()
}
QueryInterface.prototype.createTrigger = function(tableName, triggerName, timingType, fireOnArray,
functionName, functionParams, optionsArray) {
var sql = this.QueryGenerator.createTrigger(tableName, triggerName, timingType, fireOnArray, functionName
, functionParams, optionsArray)
if (sql){
return queryAndEmit.call(this, sql, 'createTrigger')
} else {
return new Utils.CustomEventEmitter(function(emitter) {
this.emit('createTrigger', null)
emitter.emit('success')
}).run()
}
}
QueryInterface.prototype.dropTrigger = function(tableName, triggerName) {
var sql = this.QueryGenerator.dropTrigger(tableName, triggerName)
if (sql){
return queryAndEmit.call(this, sql, 'dropTrigger')
} else {
return new Utils.CustomEventEmitter(function(emitter) {
this.emit('dropTrigger', null)
emitter.emit('success')
}).run()
}
}
QueryInterface.prototype.renameTrigger = function(tableName, oldTriggerName, newTriggerName) {
var sql = this.QueryGenerator.renameTrigger(tableName, oldTriggerName, newTriggerName)
if (sql){
return queryAndEmit.call(this, sql, 'renameTrigger')
} else {
return new Utils.CustomEventEmitter(function(emitter) {
this.emit('renameTrigger', null)
emitter.emit('success')
}).run()
}
}
QueryInterface.prototype.createFunction = function(functionName, params, returnType, language, body, options) {
var sql = this.QueryGenerator.createFunction(functionName, params, returnType, language, body, options)
if (sql){
return queryAndEmit.call(this, sql, 'createFunction')
} else {
return new Utils.CustomEventEmitter(function(emitter) {
this.emit('createFunction', null)
emitter.emit('success')
}).run()
}
}
QueryInterface.prototype.dropFunction = function(functionName, params) {
var sql = this.QueryGenerator.dropFunction(functionName, params)
if (sql){
return queryAndEmit.call(this, sql, 'dropFunction')
} else {
return new Utils.CustomEventEmitter(function(emitter) {
this.emit('dropFunction', null)
emitter.emit('success')
}).run()
}
}
QueryInterface.prototype.renameFunction = function(oldFunctionName, params, newFunctionName) {
var sql = this.QueryGenerator.renameFunction(oldFunctionName, params, newFunctionName)
if (sql){
return queryAndEmit.call(this, sql, 'renameFunction')
} else {
return new Utils.CustomEventEmitter(function(emitter) {
this.emit('renameFunction', null)
emitter.emit('success')
}).run()
}
}
// Helper methods useful for querying
/**
* Escape an identifier (e.g. a table or attribute name). If force is true,
* the identifier will be quoted even if the `quoteIdentifiers` option is
* false.
*/
QueryInterface.prototype.quoteIdentifier = function(identifier, force) {
return this.QueryGenerator.quoteIdentifier(identifier, force)
}
/**
* Split an identifier into .-separated tokens and quote each part.
* If force is true, the identifier will be quoted even if the
* `quoteIdentifiers` option is false.
*/
QueryInterface.prototype.quoteIdentifiers = function(identifiers, force) {
return this.QueryGenerator.quoteIdentifiers(identifiers, force)
}
/**
* Escape a value (e.g. a string, number or date)
*/
QueryInterface.prototype.escape = function(value) {
return this.QueryGenerator.escape(value)
}
QueryInterface.prototype.setAutocommit = function(transaction, value) {
if (!transaction || !(transaction instanceof Transaction)) {
throw new Error('Unable to set autocommit for a transaction without transaction object!')
}
var sql = this.QueryGenerator.setAutocommitQuery(value)
return this.queryAndEmit([sql, null, { transaction: transaction }], 'setAutocommit')
}
QueryInterface.prototype.setIsolationLevel = function(transaction, value) {
if (!transaction || !(transaction instanceof Transaction)) {
throw new Error('Unable to set isolation level for a transaction without transaction object!')
}
var sql = this.QueryGenerator.setIsolationLevelQuery(value)
return this.queryAndEmit([sql, null, { transaction: transaction }], 'setIsolationLevel')
}
QueryInterface.prototype.startTransaction = function(transaction, options) {
if (!transaction || !(transaction instanceof Transaction)) {
throw new Error('Unable to start a transaction without transaction object!')
}
options = Utils._.extend({
transaction: transaction
}, options || {})
var sql = this.QueryGenerator.startTransactionQuery(options)
return this.queryAndEmit([sql, null, options], 'startTransaction')
}
QueryInterface.prototype.commitTransaction = function(transaction, options) {
if (!transaction || !(transaction instanceof Transaction)) {
throw new Error('Unable to commit a transaction without transaction object!')
}
options = Utils._.extend({
transaction: transaction
}, options || {})
var sql = this.QueryGenerator.commitTransactionQuery(options)
return this.queryAndEmit([sql, null, options], 'commitTransaction')
}
QueryInterface.prototype.rollbackTransaction = function(transaction, options) {
if (!transaction || !(transaction instanceof Transaction)) {
throw new Error('Unable to rollback a transaction without transaction object!')
}
options = Utils._.extend({
transaction: transaction
}, options || {})
var sql = this.QueryGenerator.rollbackTransactionQuery(options)
return this.queryAndEmit([sql, null, options], 'rollbackTransaction')
}
// private
var buildScope = function() {
var smart
// Use smartWhere to convert several {where} objects into a single where object
smart = Utils.smartWhere(this.scopeObj.where || [], this.daoFactoryManager.sequelize.options.dialect)
smart = Utils.compileSmartWhere.call(this, smart, this.daoFactoryManager.sequelize.options.dialect)
return {limit: this.scopeObj.limit || null, offset: this.scopeObj.offset || null, where: smart, order: (this.scopeObj.order || []).join(', ')}
}
var queryAndEmit = QueryInterface.prototype.queryAndEmit = function(sqlOrQueryParams, methodName, options, emitter) {
options = Utils._.extend({
success: function(){},
error: function(){},
transaction: null,
logging: this.sequelize.options.logging
}, options || {})
var execQuery = function(emitter) {
if (Array.isArray(sqlOrQueryParams)) {
if (sqlOrQueryParams.length === 1) {
sqlOrQueryParams.push(null)
}
if (sqlOrQueryParams.length === 2) {
sqlOrQueryParams.push(typeof options === "object" ? options : {})
}
emitter.query = this.sequelize.query.apply(this.sequelize, sqlOrQueryParams)
} else {
emitter.query = this.sequelize.query(sqlOrQueryParams, null, options)
}
emitter
.query
.success(function(obj) {
if (options.success) {
options.success(obj)
}
this.emit(methodName, null)
emitter.emit('success', obj)
}.bind(this))
.error(function(err) {
if (options.error) {
options.error(err)
}
this.emit(methodName, err)
emitter.emit('error', err)
}.bind(this))
.on('sql', function(sql) {
emitter.emit('sql', sql)
})
}.bind(this)
if (!!emitter) {
execQuery(emitter)
} else {
return new Utils.CustomEventEmitter(execQuery).run()
}
}
return QueryInterface
})()