query-interface.js 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003
  1. var Utils = require(__dirname + '/utils')
  2. , DataTypes = require(__dirname + '/data-types')
  3. , SQLiteQueryInterface = require(__dirname + '/dialects/sqlite/query-interface')
  4. , Transaction = require(__dirname + '/transaction')
  5. , QueryTypes = require('./query-types')
  6. module.exports = (function() {
  7. var QueryInterface = function(sequelize) {
  8. this.sequelize = sequelize
  9. this.QueryGenerator = require('./dialects/' + this.sequelize.options.dialect + '/query-generator')
  10. this.QueryGenerator.options = this.sequelize.options
  11. this.QueryGenerator._dialect = this.sequelize.dialect
  12. this.QueryGenerator.sequelize = this.sequelize
  13. }
  14. Utils.addEventEmitter(QueryInterface)
  15. QueryInterface.prototype.createSchema = function(schema) {
  16. var sql = this.QueryGenerator.createSchema(schema)
  17. return queryAndEmit.call(this, sql, 'createSchema')
  18. }
  19. QueryInterface.prototype.dropSchema = function(schema) {
  20. var sql = this.QueryGenerator.dropSchema(schema)
  21. return queryAndEmit.call(this, sql, 'dropSchema')
  22. }
  23. QueryInterface.prototype.dropAllSchemas = function() {
  24. var self = this
  25. return new Utils.CustomEventEmitter(function(emitter) {
  26. var chainer = new Utils.QueryChainer()
  27. self.showAllSchemas().success(function(schemaNames) {
  28. schemaNames.forEach(function(schemaName) {
  29. chainer.add(self.dropSchema(schemaName))
  30. })
  31. chainer
  32. .run()
  33. .success(function() {
  34. self.emit('dropAllSchemas', null)
  35. emitter.emit('success', null)
  36. })
  37. .error(function(err) {
  38. self.emit('dropAllSchemas', err)
  39. emitter.emit('error', err)
  40. })
  41. }).error(function(err) {
  42. self.emit('dropAllSchemas', err)
  43. emitter.emit('error', err)
  44. })
  45. }).run()
  46. }
  47. QueryInterface.prototype.showAllSchemas = function(options) {
  48. var self = this
  49. options = Utils._.extend({
  50. transaction: null,
  51. raw: true
  52. }, options || {})
  53. return new Utils.CustomEventEmitter(function(emitter) {
  54. var showSchemasSql = self.QueryGenerator.showSchemasQuery()
  55. self.sequelize.query(showSchemasSql, null, options).success(function(schemaNames) {
  56. self.emit('showAllSchemas', null)
  57. emitter.emit('success', Utils._.flatten(Utils._.map(schemaNames, function(value){ return (!!value.schema_name ? value.schema_name : value) })))
  58. }).error(function(err) {
  59. self.emit('showAllSchemas', err)
  60. emitter.emit('error', err)
  61. })
  62. }).run()
  63. }
  64. QueryInterface.prototype.createTable = function(tableName, attributes, options) {
  65. var attributeHashes = {}
  66. , dataTypeValues = Utils._.values(DataTypes)
  67. , keys = Object.keys(attributes)
  68. , keyLen = keys.length
  69. , self = this
  70. , sql = ''
  71. , i = 0
  72. for (i = 0; i < keyLen; i++) {
  73. if (dataTypeValues.indexOf(attributes[keys[i]]) > -1) {
  74. attributeHashes[keys[i]] = { type: attributes[keys[i]], allowNull: true }
  75. } else {
  76. attributeHashes[keys[i]] = attributes[keys[i]]
  77. }
  78. }
  79. options = Utils._.extend({
  80. logging: this.sequelize.options.logging
  81. }, options || {})
  82. return new Utils.CustomEventEmitter(function(emitter) {
  83. // Postgres requires a special SQL command for enums
  84. if (self.sequelize.options.dialect === "postgres") {
  85. var chainer = new Utils.QueryChainer()
  86. // For backwards-compatibility, public schemas don't need to
  87. // explicitly state their schema when creating a new enum type
  88. , getTableName = (!options || !options.schema || options.schema === "public" ? '' : options.schema + '_') + tableName
  89. for (i = 0; i < keyLen; i++) {
  90. if (attributes[keys[i]].toString().match(/^ENUM\(/) || attributes[keys[i]].toString() === "ENUM" || (attributes[keys[i]].type && attributes[keys[i]].type.toString() === "ENUM")) {
  91. sql = self.QueryGenerator.pgListEnums(getTableName, keys[i], options)
  92. chainer.add(self.sequelize.query(sql, null, { plain: true, raw: true, type: QueryTypes.SELECT, logging: options.logging }))
  93. }
  94. }
  95. chainer.runSerially().success(function(results) {
  96. var chainer2 = new Utils.QueryChainer()
  97. // Find the table that we're trying to create throgh DAOFactoryManager
  98. , daoTable = self.sequelize.daoFactoryManager.daos.filter(function(dao) { return dao.tableName === tableName })
  99. , enumIdx = 0
  100. daoTable = daoTable.length > 0 ? daoTable[0] : null
  101. for (i = 0; i < keyLen; i++) {
  102. if (attributes[keys[i]].toString().match(/^ENUM\(/) || attributes[keys[i]].toString() === "ENUM" || (attributes[keys[i]].type && attributes[keys[i]].type.toString() === "ENUM")) {
  103. // If the enum type doesn't exist then create it
  104. if (!results[enumIdx]) {
  105. sql = self.QueryGenerator.pgEnum(getTableName, keys[i], attributes[keys[i]], options)
  106. chainer2.add(self.sequelize.query(sql, null, { raw: true, logging: options.logging }))
  107. } else if (!!results[enumIdx] && !!daoTable) {
  108. var enumVals = self.QueryGenerator.fromArray(results[enumIdx].enum_value)
  109. , vals = daoTable.rawAttributes[keys[i]].values
  110. vals.forEach(function(value, idx) {
  111. // reset out after/before options since it's for every enum value
  112. options.before = null
  113. options.after = null
  114. if (enumVals.indexOf(value) === -1) {
  115. if (!!vals[idx+1]) {
  116. options.before = vals[idx+1]
  117. }
  118. else if (!!vals[idx-1]) {
  119. options.after = vals[idx-1]
  120. }
  121. chainer2.add(self.sequelize.query(self.QueryGenerator.pgEnumAdd(getTableName, keys[i], value, options)))
  122. }
  123. })
  124. enumIdx++
  125. }
  126. }
  127. }
  128. attributes = self.QueryGenerator.attributesToSQL(attributeHashes)
  129. sql = self.QueryGenerator.createTableQuery(tableName, attributes, options)
  130. chainer2.run().success(function() {
  131. queryAndEmit
  132. .call(self, sql, 'createTable', options)
  133. .success(function(res) {
  134. self.emit('createTable', null)
  135. emitter.emit('success', res)
  136. })
  137. .error(function(err) {
  138. self.emit('createTable', err)
  139. emitter.emit('error', err)
  140. })
  141. .on('sql', function(sql) {
  142. emitter.emit('sql', sql)
  143. })
  144. }).error(function(err) {
  145. emitter.emit('error', err)
  146. }).on('sql', function(sql) {
  147. emitter.emit('sql', sql)
  148. })
  149. })
  150. } else {
  151. attributes = self.QueryGenerator.attributesToSQL(attributeHashes)
  152. sql = self.QueryGenerator.createTableQuery(tableName, attributes, options)
  153. queryAndEmit.call(self, sql, 'createTable', options).success(function(results) {
  154. self.emit('createTable', null)
  155. emitter.emit('success', results)
  156. }).error(function(err) {
  157. self.emit('createTable', err)
  158. emitter.emit('error', err)
  159. }).on('sql', function(sql) {
  160. emitter.emit('sql', sql)
  161. })
  162. }
  163. }).run()
  164. }
  165. QueryInterface.prototype.dropTable = function(tableName, options) {
  166. // if we're forcing we should be cascading unless explicitly stated otherwise
  167. options = options || {}
  168. options.cascade = options.cascade || options.force || false
  169. var sql = this.QueryGenerator.dropTableQuery(tableName, options)
  170. , self = this
  171. return new Utils.CustomEventEmitter(function(emitter) {
  172. var chainer = new Utils.QueryChainer()
  173. chainer.add(self, 'queryAndEmit', [sql, 'dropTable'], options)
  174. // Since postgres has a special case for enums, we should drop the related
  175. // enum type within the table and attribute
  176. if (self.sequelize.options.dialect === "postgres") {
  177. // Find the table that we're trying to drop
  178. daoTable = self.sequelize.daoFactoryManager.daos.filter(function(dao) {
  179. return dao.tableName === tableName
  180. })
  181. // Just in case if we're trying to drop a non-existing table
  182. daoTable = daoTable.length > 0 ? daoTable[0] : null
  183. if (!!daoTable) {
  184. var getTableName = (!options || !options.schema || options.schema === "public" ? '' : options.schema + '_') + tableName
  185. var keys = Object.keys(daoTable.rawAttributes)
  186. , keyLen = keys.length
  187. , i = 0
  188. for (i = 0; i < keyLen; i++) {
  189. if (daoTable.rawAttributes[keys[i]].type && daoTable.rawAttributes[keys[i]].type.toString() === "ENUM") {
  190. chainer.add(self.sequelize, 'query', [self.QueryGenerator.pgEnumDrop(getTableName, keys[i]), null, {logging: options.logging, raw: true}])
  191. }
  192. }
  193. }
  194. }
  195. chainer.runSerially().success(function(results) {
  196. emitter.emit('success', results[0])
  197. self.emit('dropTable', null)
  198. }).error(function(err) {
  199. emitter.emit('error', err)
  200. self.emit('dropTable', err)
  201. }).on('sql', function(sql) {
  202. emitter.emit('sql', sql)
  203. })
  204. }).run()
  205. }
  206. QueryInterface.prototype.dropAllTables = function(options) {
  207. var self = this
  208. if (!options) {
  209. options = {}
  210. }
  211. var skip = options.skip || [];
  212. if (this.sequelize.options.dialect === 'sqlite') {
  213. // sqlite needs some special treatment as it cannot drop a column
  214. return SQLiteQueryInterface.dropAllTables.call(this, options)
  215. } else {
  216. return new Utils.CustomEventEmitter(function(dropAllTablesEmitter) {
  217. var events = []
  218. , chainer = new Utils.QueryChainer()
  219. , onError = function(err) {
  220. self.emit('dropAllTables', err)
  221. dropAllTablesEmitter.emit('error', err)
  222. }
  223. self.showAllTables().success(function(tableNames) {
  224. self.getForeignKeysForTables(tableNames).success(function(foreignKeys) {
  225. // add the foreign key removal query to the chainer
  226. Object.keys(foreignKeys).forEach(function(tableName) {
  227. foreignKeys[tableName].forEach(function(foreignKey) {
  228. var sql = self.QueryGenerator.dropForeignKeyQuery(tableName, foreignKey)
  229. chainer.add(self.sequelize, 'query', [ sql ])
  230. })
  231. })
  232. // add the table removal query to the chainer
  233. tableNames.forEach(function(tableName) {
  234. // if tableName is not in the Array of tables names then dont drop it
  235. if (skip.indexOf(tableName) === -1) {
  236. chainer.add(self, 'dropTable', [ tableName, { cascade: true } ])
  237. }
  238. })
  239. chainer
  240. .runSerially()
  241. .success(function() {
  242. self.emit('dropAllTables', null)
  243. dropAllTablesEmitter.emit('success', null)
  244. })
  245. .error(onError)
  246. }).error(onError)
  247. }).error(onError)
  248. }).run()
  249. }
  250. }
  251. QueryInterface.prototype.dropAllEnums = function(options) {
  252. if (this.sequelize.getDialect() !== 'postgres') {
  253. return new Utils.CustomEventEmitter(function (emitter) {
  254. emitter.emit('success')
  255. }).run()
  256. }
  257. options = options || {}
  258. var self = this
  259. , emitter = new Utils.CustomEventEmitter()
  260. , chainer = new Utils.QueryChainer()
  261. , sql = this.QueryGenerator.pgListEnums()
  262. this.sequelize.query(sql, null, { plain: false, raw: true, type: QueryTypes.SELECT, logging: options.logging })
  263. .proxy(emitter, {events: ['sql', 'error']})
  264. .success(function (results) {
  265. results.forEach(function (result) {
  266. chainer.add(self.sequelize.query(
  267. self.QueryGenerator.pgEnumDrop(null, null, result.enum_name),
  268. null,
  269. {logging: options.logging, raw: true}
  270. ))
  271. })
  272. chainer.run().proxy(emitter)
  273. })
  274. return emitter
  275. }
  276. QueryInterface.prototype.renameTable = function(before, after) {
  277. var sql = this.QueryGenerator.renameTableQuery(before, after)
  278. return queryAndEmit.call(this, sql, 'renameTable')
  279. }
  280. QueryInterface.prototype.showAllTables = function(options) {
  281. var self = this
  282. options = Utils._.extend({
  283. transaction: null,
  284. raw: true
  285. }, options || {})
  286. return new Utils.CustomEventEmitter(function(emitter) {
  287. var showTablesSql = self.QueryGenerator.showTablesQuery()
  288. self.sequelize.query(showTablesSql, null, options).success(function(tableNames) {
  289. self.emit('showAllTables', null)
  290. emitter.emit('success', Utils._.flatten(tableNames))
  291. }).error(function(err) {
  292. self.emit('showAllTables', err)
  293. emitter.emit('error', err)
  294. })
  295. }).run()
  296. }
  297. QueryInterface.prototype.describeTable = function(tableName, options) {
  298. var self = this
  299. , schema = null
  300. , schemaDelimiter = null
  301. if (typeof options === "string") {
  302. schema = options
  303. }
  304. else if (typeof options === "object") {
  305. schema = options.schema || null
  306. schemaDelimiter = options.schemaDelimiter || null
  307. }
  308. return new Utils.CustomEventEmitter(function(emitter) {
  309. var sql;
  310. if (self.QueryGenerator.describeTableQuery) {
  311. sql = self.QueryGenerator.describeTableQuery(tableName, schema, schemaDelimiter)
  312. } else {
  313. var table = self.QueryGenerator.quoteIdentifier(self.QueryGenerator.addSchema({tableName: tableName, options: {schema: schema, schemaDelimiter: schemaDelimiter}}), self.QueryGenerator.options.quoteIdentifiers)
  314. sql = 'DESCRIBE ' + table + ';'
  315. }
  316. self.sequelize.query(sql, null, { raw: true }).success(function(data) {
  317. if(Utils._.isEmpty(data)) {
  318. // If no data is returned from the query, then the table name may be wrong.
  319. // Query generators that use information_schema for retrieving table info will just return an empty result set,
  320. // it will not throw an error like built-ins do (e.g. DESCRIBE on MySql).
  321. emitter.emit('error', 'No description found for "' + tableName + '" table. Check the table name and schema; remember, they _are_ case sensitive.')
  322. } else {
  323. emitter.emit('success', data)
  324. }
  325. }).error(function(err) {
  326. emitter.emit('error', err)
  327. }).on('sql', function(sql) {
  328. emitter.emit('sql', sql)
  329. })
  330. }).run()
  331. }
  332. QueryInterface.prototype.addColumn = function(tableName, attributeName, dataTypeOrOptions) {
  333. var attributes = {}
  334. if (Utils._.values(DataTypes).indexOf(dataTypeOrOptions) > -1) {
  335. attributes[attributeName] = { type: dataTypeOrOptions, allowNull: true }
  336. } else {
  337. attributes[attributeName] = dataTypeOrOptions
  338. }
  339. var options = this.QueryGenerator.attributesToSQL(attributes)
  340. , sql = this.QueryGenerator.addColumnQuery(tableName, options)
  341. return queryAndEmit.call(this, sql, 'addColumn')
  342. }
  343. QueryInterface.prototype.removeColumn = function(tableName, attributeName) {
  344. if (this.sequelize.options.dialect === 'sqlite') {
  345. // sqlite needs some special treatment as it cannot drop a column
  346. return new Utils.CustomEventEmitter(function(emitter) {
  347. SQLiteQueryInterface.removeColumn.call(this, tableName, attributeName, emitter, queryAndEmit)
  348. }.bind(this)).run()
  349. } else {
  350. var sql = this.QueryGenerator.removeColumnQuery(tableName, attributeName)
  351. return queryAndEmit.call(this, sql, 'removeColumn')
  352. }
  353. }
  354. QueryInterface.prototype.changeColumn = function(tableName, attributeName, dataTypeOrOptions) {
  355. var attributes = {}
  356. if (Utils._.values(DataTypes).indexOf(dataTypeOrOptions) > -1) {
  357. attributes[attributeName] = { type: dataTypeOrOptions, allowNull: true }
  358. } else {
  359. attributes[attributeName] = dataTypeOrOptions
  360. }
  361. if (this.sequelize.options.dialect === 'sqlite') {
  362. // sqlite needs some special treatment as it cannot change a column
  363. return new Utils.CustomEventEmitter(function(emitter) {
  364. SQLiteQueryInterface.changeColumn.call(this, tableName, attributes, emitter, queryAndEmit)
  365. }.bind(this)).run()
  366. } else {
  367. var options = this.QueryGenerator.attributesToSQL(attributes)
  368. , sql = this.QueryGenerator.changeColumnQuery(tableName, options)
  369. return queryAndEmit.call(this, sql, 'changeColumn')
  370. }
  371. }
  372. QueryInterface.prototype.renameColumn = function(tableName, attrNameBefore, attrNameAfter) {
  373. return new Utils.CustomEventEmitter(function(emitter) {
  374. this.describeTable(tableName).success(function(data) {
  375. data = data[attrNameBefore] || {}
  376. var options = {}
  377. options[attrNameAfter] = {
  378. attribute: attrNameAfter,
  379. type: data.type,
  380. allowNull: data.allowNull,
  381. defaultValue: data.defaultValue
  382. }
  383. if (this.sequelize.options.dialect === 'sqlite') {
  384. // sqlite needs some special treatment as it cannot rename a column
  385. SQLiteQueryInterface.renameColumn.call(this, tableName, attrNameBefore, attrNameAfter, emitter, queryAndEmit)
  386. } else {
  387. var sql = this.QueryGenerator.renameColumnQuery(tableName,
  388. attrNameBefore,
  389. this.QueryGenerator.attributesToSQL(options)
  390. )
  391. queryAndEmit.call(this, sql, 'renameColumn', {}, emitter)
  392. }
  393. }.bind(this))
  394. .error(function(err) {
  395. this.emit('renameColumn', err)
  396. emitter.emit('error', err)
  397. }.bind(this))
  398. }.bind(this)).run()
  399. }
  400. QueryInterface.prototype.addIndex = function(tableName, attributes, options) {
  401. var sql = this.QueryGenerator.addIndexQuery(tableName, attributes, options)
  402. return queryAndEmit.call(this, sql, 'addIndex')
  403. }
  404. QueryInterface.prototype.showIndex = function(tableName, options) {
  405. var sql = this.QueryGenerator.showIndexQuery(tableName, options)
  406. return queryAndEmit.call(this, sql, 'showIndex')
  407. }
  408. QueryInterface.prototype.getForeignKeysForTables = function(tableNames) {
  409. var self = this
  410. return new Utils.CustomEventEmitter(function(emitter) {
  411. if (tableNames.length === 0) {
  412. emitter.emit('success', {})
  413. } else {
  414. var chainer = new Utils.QueryChainer()
  415. tableNames.forEach(function(tableName) {
  416. var sql = self.QueryGenerator.getForeignKeysQuery(tableName, self.sequelize.config.database)
  417. chainer.add(self.sequelize, 'query', [sql])
  418. })
  419. chainer.runSerially().proxy(emitter, {
  420. skipEvents: ['success']
  421. }).success(function(results) {
  422. var result = {}
  423. tableNames.forEach(function(tableName, i) {
  424. result[tableName] = Utils._.compact(results[i]).map(function(r) { return r.constraint_name })
  425. })
  426. emitter.emit('success', result)
  427. })
  428. }
  429. }).run()
  430. }
  431. QueryInterface.prototype.removeIndex = function(tableName, indexNameOrAttributes) {
  432. var sql = this.QueryGenerator.removeIndexQuery(tableName, indexNameOrAttributes)
  433. return queryAndEmit.call(this, sql, "removeIndex")
  434. }
  435. QueryInterface.prototype.insert = function(dao, tableName, values, options) {
  436. var sql = this.QueryGenerator.insertQuery(tableName, values, dao.daoFactory.rawAttributes)
  437. return queryAndEmit.call(this, [sql, dao, options], 'insert', {
  438. success: function(obj) { obj.isNewRecord = false }
  439. })
  440. }
  441. QueryInterface.prototype.bulkInsert = function(tableName, records, options) {
  442. var sql = this.QueryGenerator.bulkInsertQuery(tableName, records, options)
  443. return queryAndEmit.call(this, [sql, null, options], 'bulkInsert')
  444. }
  445. QueryInterface.prototype.update = function(dao, tableName, values, identifier, options) {
  446. var self = this
  447. , restrict = false
  448. , sql = self.QueryGenerator.updateQuery(tableName, values, identifier, options, dao.daoFactory.rawAttributes)
  449. // Check for a restrict field
  450. if (!!dao.daoFactory && !!dao.daoFactory.associations) {
  451. var keys = Object.keys(dao.daoFactory.associations)
  452. , length = keys.length
  453. for (var i = 0; i < length; i++) {
  454. if (dao.daoFactory.associations[keys[i]].options && dao.daoFactory.associations[keys[i]].options.onUpdate && dao.daoFactory.associations[keys[i]].options.onUpdate === "restrict") {
  455. restrict = true
  456. }
  457. }
  458. }
  459. return new Utils.CustomEventEmitter(function(emitter) {
  460. var chainer = new Utils.QueryChainer()
  461. chainer.add(self, 'queryAndEmit', [[sql, dao, options], 'delete'])
  462. chainer.runSerially()
  463. .success(function(results){
  464. emitter.query = { sql: sql }
  465. emitter.emit('success', results[0])
  466. emitter.emit('sql', sql)
  467. })
  468. .error(function(err) {
  469. emitter.query = { sql: sql }
  470. emitter.emit('error', err)
  471. emitter.emit('sql', sql)
  472. })
  473. .on('sql', function(sql) {
  474. emitter.emit('sql', sql)
  475. })
  476. }).run()
  477. }
  478. QueryInterface.prototype.bulkUpdate = function(tableName, values, identifier, options) {
  479. var self = this
  480. , sql = self.QueryGenerator.updateQuery(tableName, values, identifier, options)
  481. return new Utils.CustomEventEmitter(function(emitter) {
  482. var chainer = new Utils.QueryChainer()
  483. chainer.add(self, 'queryAndEmit', [[sql, null, options], 'bulkUpdate'])
  484. return chainer.runSerially()
  485. .success(function(results){
  486. emitter.query = { sql: sql }
  487. emitter.emit('sql', sql)
  488. emitter.emit('success', results[0])
  489. })
  490. .error(function(err) {
  491. emitter.query = { sql: sql }
  492. emitter.emit('sql', sql)
  493. emitter.emit('error', err)
  494. })
  495. }).run()
  496. }
  497. QueryInterface.prototype.delete = function(dao, tableName, identifier, options) {
  498. var self = this
  499. , restrict = false
  500. , cascades = []
  501. , sql = self.QueryGenerator.deleteQuery(tableName, identifier, null, dao.daoFactory)
  502. // Check for a restrict field
  503. if (!!dao.daoFactory && !!dao.daoFactory.associations) {
  504. var keys = Object.keys(dao.daoFactory.associations)
  505. , length = keys.length
  506. for (var i = 0; i < length; i++) {
  507. if (dao.daoFactory.associations[keys[i]].options && dao.daoFactory.associations[keys[i]].options.onDelete) {
  508. if (dao.daoFactory.associations[keys[i]].options.onDelete === "restrict") {
  509. restrict = true
  510. }
  511. else if (dao.daoFactory.associations[keys[i]].options.onDelete === "cascade" && dao.daoFactory.associations[keys[i]].options.useHooks === true) {
  512. cascades[cascades.length] = dao.daoFactory.associations[keys[i]].accessors.get
  513. }
  514. }
  515. }
  516. }
  517. return new Utils.CustomEventEmitter(function(emitter) {
  518. var tick = 0
  519. var iterate = function(err, i) {
  520. if (!!err || i >= cascades.length) {
  521. return run(err)
  522. }
  523. dao[cascades[i]]().success(function(tasks) {
  524. if (tasks === null || tasks.length < 1) {
  525. return run()
  526. }
  527. tasks = Array.isArray(tasks) ? tasks : [tasks]
  528. var ii = 0
  529. var next = function(err, ii) {
  530. if (!!err || ii >= tasks.length) {
  531. return iterate(err)
  532. }
  533. tasks[ii].destroy().error(function(err) {
  534. return iterate(err)
  535. })
  536. .success(function() {
  537. ii++
  538. if (ii >= tasks.length) {
  539. tick++
  540. return iterate(null, tick)
  541. }
  542. next(null, ii)
  543. })
  544. }
  545. next(null, ii)
  546. })
  547. }
  548. var run = function(err) {
  549. if (!!err) {
  550. return emitter.emit('error', err)
  551. }
  552. var chainer = new Utils.QueryChainer()
  553. chainer.add(self, 'queryAndEmit', [[sql, dao, options], 'delete'])
  554. chainer.runSerially()
  555. .success(function(results){
  556. emitter.query = { sql: sql }
  557. emitter.emit('sql', sql)
  558. emitter.emit('success', results[1])
  559. })
  560. .error(function(err) {
  561. emitter.query = { sql: sql }
  562. emitter.emit('sql', sql)
  563. emitter.emit('error', err)
  564. })
  565. }
  566. if (cascades.length > 0) {
  567. iterate(null, tick)
  568. } else {
  569. run()
  570. }
  571. }).run()
  572. }
  573. QueryInterface.prototype.bulkDelete = function(tableName, identifier, options) {
  574. var self = this
  575. var sql = self.QueryGenerator.deleteQuery(tableName, identifier, Utils._.defaults(options || {}, {limit: null}))
  576. return new Utils.CustomEventEmitter(function(emitter) {
  577. var chainer = new Utils.QueryChainer()
  578. chainer.add(self, 'queryAndEmit', [[sql, null, options], 'bulkDelete', options])
  579. chainer.runSerially()
  580. .success(function(results){
  581. emitter.query = { sql: sql }
  582. emitter.emit('sql', sql)
  583. emitter.emit('success', results[0])
  584. })
  585. .error(function(err) {
  586. emitter.query = { sql: sql }
  587. emitter.emit('sql', sql)
  588. emitter.emit('error', err)
  589. })
  590. }).run()
  591. }
  592. QueryInterface.prototype.select = function(factory, tableName, options, queryOptions) {
  593. options = options || {}
  594. // See if we need to merge options and factory.scopeObj
  595. // we're doing this on the QueryInterface level because it's a bridge between
  596. // sequelize and the databases
  597. if (Object.keys(factory.scopeObj).length > 0) {
  598. if (!!options) {
  599. Utils.injectScope.call(factory, options, true)
  600. }
  601. var scopeObj = buildScope.call(factory)
  602. Object.keys(scopeObj).forEach(function(method) {
  603. if (typeof scopeObj[method] === "number" || !Utils._.isEmpty(scopeObj[method])) {
  604. options[method] = scopeObj[method]
  605. }
  606. })
  607. }
  608. var sql = this.QueryGenerator.selectQuery(tableName, options, factory)
  609. queryOptions = Utils._.extend({}, queryOptions, {
  610. include: options.include,
  611. includeNames: options.includeNames,
  612. includeMap: options.includeMap,
  613. hasSingleAssociation: options.hasSingleAssociation,
  614. hasMultiAssociation: options.hasMultiAssociation
  615. })
  616. return queryAndEmit.call(this, [sql, factory, queryOptions], 'select')
  617. }
  618. QueryInterface.prototype.increment = function(dao, tableName, values, identifier, options) {
  619. var sql = this.QueryGenerator.incrementQuery(tableName, values, identifier, options.attributes)
  620. return queryAndEmit.call(this, [sql, dao, options], 'increment')
  621. }
  622. QueryInterface.prototype.rawSelect = function(tableName, options, attributeSelector) {
  623. var self = this
  624. if (attributeSelector === undefined) {
  625. throw new Error('Please pass an attribute selector!')
  626. }
  627. return new Utils.CustomEventEmitter(function(emitter) {
  628. var sql = self.QueryGenerator.selectQuery(tableName, options)
  629. , queryOptions = Utils._.extend({ transaction: options.transaction }, { plain: true, raw: true, type: QueryTypes.SELECT })
  630. , query = self.sequelize.query(sql, null, queryOptions)
  631. query
  632. .success(function(data) {
  633. var result = data ? data[attributeSelector] : null
  634. if (options && options.dataType) {
  635. var dataType = options.dataType;
  636. if (dataType instanceof DataTypes.DECIMAL || dataType instanceof DataTypes.FLOAT) {
  637. result = parseFloat(result);
  638. } else if (dataType === DataTypes.INTEGER || dataType instanceof DataTypes.BIGINT) {
  639. result = parseInt(result, 10);
  640. } else if (dataType === DataTypes.DATE) {
  641. result = new Date(result + 'Z');
  642. } else if (dataType === DataTypes.STRING) {
  643. // Nothing to do, result is already a string.
  644. }
  645. }
  646. self.emit('rawSelect', null)
  647. emitter.emit('success', result)
  648. })
  649. .error(function(err) {
  650. self.emit('rawSelect', err)
  651. emitter.emit('error', err)
  652. })
  653. .on('sql', function(sql) {
  654. emitter.emit('sql', sql)
  655. })
  656. }).run()
  657. }
  658. QueryInterface.prototype.createTrigger = function(tableName, triggerName, timingType, fireOnArray,
  659. functionName, functionParams, optionsArray) {
  660. var sql = this.QueryGenerator.createTrigger(tableName, triggerName, timingType, fireOnArray, functionName
  661. , functionParams, optionsArray)
  662. if (sql){
  663. return queryAndEmit.call(this, sql, 'createTrigger')
  664. } else {
  665. return new Utils.CustomEventEmitter(function(emitter) {
  666. this.emit('createTrigger', null)
  667. emitter.emit('success')
  668. }).run()
  669. }
  670. }
  671. QueryInterface.prototype.dropTrigger = function(tableName, triggerName) {
  672. var sql = this.QueryGenerator.dropTrigger(tableName, triggerName)
  673. if (sql){
  674. return queryAndEmit.call(this, sql, 'dropTrigger')
  675. } else {
  676. return new Utils.CustomEventEmitter(function(emitter) {
  677. this.emit('dropTrigger', null)
  678. emitter.emit('success')
  679. }).run()
  680. }
  681. }
  682. QueryInterface.prototype.renameTrigger = function(tableName, oldTriggerName, newTriggerName) {
  683. var sql = this.QueryGenerator.renameTrigger(tableName, oldTriggerName, newTriggerName)
  684. if (sql){
  685. return queryAndEmit.call(this, sql, 'renameTrigger')
  686. } else {
  687. return new Utils.CustomEventEmitter(function(emitter) {
  688. this.emit('renameTrigger', null)
  689. emitter.emit('success')
  690. }).run()
  691. }
  692. }
  693. QueryInterface.prototype.createFunction = function(functionName, params, returnType, language, body, options) {
  694. var sql = this.QueryGenerator.createFunction(functionName, params, returnType, language, body, options)
  695. if (sql){
  696. return queryAndEmit.call(this, sql, 'createFunction')
  697. } else {
  698. return new Utils.CustomEventEmitter(function(emitter) {
  699. this.emit('createFunction', null)
  700. emitter.emit('success')
  701. }).run()
  702. }
  703. }
  704. QueryInterface.prototype.dropFunction = function(functionName, params) {
  705. var sql = this.QueryGenerator.dropFunction(functionName, params)
  706. if (sql){
  707. return queryAndEmit.call(this, sql, 'dropFunction')
  708. } else {
  709. return new Utils.CustomEventEmitter(function(emitter) {
  710. this.emit('dropFunction', null)
  711. emitter.emit('success')
  712. }).run()
  713. }
  714. }
  715. QueryInterface.prototype.renameFunction = function(oldFunctionName, params, newFunctionName) {
  716. var sql = this.QueryGenerator.renameFunction(oldFunctionName, params, newFunctionName)
  717. if (sql){
  718. return queryAndEmit.call(this, sql, 'renameFunction')
  719. } else {
  720. return new Utils.CustomEventEmitter(function(emitter) {
  721. this.emit('renameFunction', null)
  722. emitter.emit('success')
  723. }).run()
  724. }
  725. }
  726. // Helper methods useful for querying
  727. /**
  728. * Escape an identifier (e.g. a table or attribute name). If force is true,
  729. * the identifier will be quoted even if the `quoteIdentifiers` option is
  730. * false.
  731. */
  732. QueryInterface.prototype.quoteIdentifier = function(identifier, force) {
  733. return this.QueryGenerator.quoteIdentifier(identifier, force)
  734. }
  735. /**
  736. * Split an identifier into .-separated tokens and quote each part.
  737. * If force is true, the identifier will be quoted even if the
  738. * `quoteIdentifiers` option is false.
  739. */
  740. QueryInterface.prototype.quoteIdentifiers = function(identifiers, force) {
  741. return this.QueryGenerator.quoteIdentifiers(identifiers, force)
  742. }
  743. /**
  744. * Escape a value (e.g. a string, number or date)
  745. */
  746. QueryInterface.prototype.escape = function(value) {
  747. return this.QueryGenerator.escape(value)
  748. }
  749. QueryInterface.prototype.setAutocommit = function(transaction, value) {
  750. if (!transaction || !(transaction instanceof Transaction)) {
  751. throw new Error('Unable to set autocommit for a transaction without transaction object!')
  752. }
  753. var sql = this.QueryGenerator.setAutocommitQuery(value)
  754. return this.queryAndEmit([sql, null, { transaction: transaction }], 'setAutocommit')
  755. }
  756. QueryInterface.prototype.setIsolationLevel = function(transaction, value) {
  757. if (!transaction || !(transaction instanceof Transaction)) {
  758. throw new Error('Unable to set isolation level for a transaction without transaction object!')
  759. }
  760. var sql = this.QueryGenerator.setIsolationLevelQuery(value)
  761. return this.queryAndEmit([sql, null, { transaction: transaction }], 'setIsolationLevel')
  762. }
  763. QueryInterface.prototype.startTransaction = function(transaction, options) {
  764. if (!transaction || !(transaction instanceof Transaction)) {
  765. throw new Error('Unable to start a transaction without transaction object!')
  766. }
  767. options = Utils._.extend({
  768. transaction: transaction
  769. }, options || {})
  770. var sql = this.QueryGenerator.startTransactionQuery(options)
  771. return this.queryAndEmit([sql, null, options], 'startTransaction')
  772. }
  773. QueryInterface.prototype.commitTransaction = function(transaction, options) {
  774. if (!transaction || !(transaction instanceof Transaction)) {
  775. throw new Error('Unable to commit a transaction without transaction object!')
  776. }
  777. options = Utils._.extend({
  778. transaction: transaction
  779. }, options || {})
  780. var sql = this.QueryGenerator.commitTransactionQuery(options)
  781. return this.queryAndEmit([sql, null, options], 'commitTransaction')
  782. }
  783. QueryInterface.prototype.rollbackTransaction = function(transaction, options) {
  784. if (!transaction || !(transaction instanceof Transaction)) {
  785. throw new Error('Unable to rollback a transaction without transaction object!')
  786. }
  787. options = Utils._.extend({
  788. transaction: transaction
  789. }, options || {})
  790. var sql = this.QueryGenerator.rollbackTransactionQuery(options)
  791. return this.queryAndEmit([sql, null, options], 'rollbackTransaction')
  792. }
  793. // private
  794. var buildScope = function() {
  795. var smart
  796. // Use smartWhere to convert several {where} objects into a single where object
  797. smart = Utils.smartWhere(this.scopeObj.where || [], this.daoFactoryManager.sequelize.options.dialect)
  798. smart = Utils.compileSmartWhere.call(this, smart, this.daoFactoryManager.sequelize.options.dialect)
  799. return {limit: this.scopeObj.limit || null, offset: this.scopeObj.offset || null, where: smart, order: (this.scopeObj.order || []).join(', ')}
  800. }
  801. var queryAndEmit = QueryInterface.prototype.queryAndEmit = function(sqlOrQueryParams, methodName, options, emitter) {
  802. options = Utils._.extend({
  803. success: function(){},
  804. error: function(){},
  805. transaction: null,
  806. logging: this.sequelize.options.logging
  807. }, options || {})
  808. var execQuery = function(emitter) {
  809. if (Array.isArray(sqlOrQueryParams)) {
  810. if (sqlOrQueryParams.length === 1) {
  811. sqlOrQueryParams.push(null)
  812. }
  813. if (sqlOrQueryParams.length === 2) {
  814. sqlOrQueryParams.push(typeof options === "object" ? options : {})
  815. }
  816. emitter.query = this.sequelize.query.apply(this.sequelize, sqlOrQueryParams)
  817. } else {
  818. emitter.query = this.sequelize.query(sqlOrQueryParams, null, options)
  819. }
  820. emitter
  821. .query
  822. .success(function(obj) {
  823. if (options.success) {
  824. options.success(obj)
  825. }
  826. this.emit(methodName, null)
  827. emitter.emit('success', obj)
  828. }.bind(this))
  829. .error(function(err) {
  830. if (options.error) {
  831. options.error(err)
  832. }
  833. this.emit(methodName, err)
  834. emitter.emit('error', err)
  835. }.bind(this))
  836. .on('sql', function(sql) {
  837. emitter.emit('sql', sql)
  838. })
  839. }.bind(this)
  840. if (!!emitter) {
  841. execQuery(emitter)
  842. } else {
  843. return new Utils.CustomEventEmitter(execQuery).run()
  844. }
  845. }
  846. return QueryInterface
  847. })()