1 | 'use strict';
|
2 |
|
3 | const _ = require('lodash');
|
4 |
|
5 | const Utils = require('./utils');
|
6 | const DataTypes = require('./data-types');
|
7 | const SQLiteQueryInterface = require('./dialects/sqlite/query-interface');
|
8 | const MSSQLQueryInterface = require('./dialects/mssql/query-interface');
|
9 | const MySQLQueryInterface = require('./dialects/mysql/query-interface');
|
10 | const PostgresQueryInterface = require('./dialects/postgres/query-interface');
|
11 | const Transaction = require('./transaction');
|
12 | const Promise = require('./promise');
|
13 | const QueryTypes = require('./query-types');
|
14 | const Op = require('./operators');
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 | class QueryInterface {
|
22 | constructor(sequelize) {
|
23 | this.sequelize = sequelize;
|
24 | this.QueryGenerator = this.sequelize.dialect.QueryGenerator;
|
25 | }
|
26 |
|
27 | |
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 | createDatabase(database, options) {
|
41 | options = options || {};
|
42 | const sql = this.QueryGenerator.createDatabaseQuery(database, options);
|
43 | return this.sequelize.query(sql, options);
|
44 | }
|
45 |
|
46 | |
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 | dropDatabase(database, options) {
|
55 | options = options || {};
|
56 | const sql = this.QueryGenerator.dropDatabaseQuery(database);
|
57 | return this.sequelize.query(sql, options);
|
58 | }
|
59 |
|
60 | |
61 |
|
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 | createSchema(schema, options) {
|
69 | options = options || {};
|
70 | const sql = this.QueryGenerator.createSchema(schema);
|
71 | return this.sequelize.query(sql, options);
|
72 | }
|
73 |
|
74 | |
75 |
|
76 |
|
77 |
|
78 |
|
79 |
|
80 |
|
81 |
|
82 | dropSchema(schema, options) {
|
83 | options = options || {};
|
84 | const sql = this.QueryGenerator.dropSchema(schema);
|
85 | return this.sequelize.query(sql, options);
|
86 | }
|
87 |
|
88 | |
89 |
|
90 |
|
91 |
|
92 |
|
93 |
|
94 |
|
95 | dropAllSchemas(options) {
|
96 | options = options || {};
|
97 |
|
98 | if (!this.QueryGenerator._dialect.supports.schemas) {
|
99 | return this.sequelize.drop(options);
|
100 | }
|
101 | return this.showAllSchemas(options).map(schemaName => this.dropSchema(schemaName, options));
|
102 | }
|
103 |
|
104 | |
105 |
|
106 |
|
107 |
|
108 |
|
109 |
|
110 |
|
111 | showAllSchemas(options) {
|
112 | options = Object.assign({}, options, {
|
113 | raw: true,
|
114 | type: this.sequelize.QueryTypes.SELECT
|
115 | });
|
116 |
|
117 | const showSchemasSql = this.QueryGenerator.showSchemasQuery(options);
|
118 |
|
119 | return this.sequelize.query(showSchemasSql, options).then(schemaNames => _.flatten(
|
120 | schemaNames.map(value => value.schema_name ? value.schema_name : value)
|
121 | ));
|
122 | }
|
123 |
|
124 | |
125 |
|
126 |
|
127 |
|
128 |
|
129 |
|
130 |
|
131 |
|
132 |
|
133 | databaseVersion(options) {
|
134 | return this.sequelize.query(
|
135 | this.QueryGenerator.versionQuery(),
|
136 | Object.assign({}, options, { type: QueryTypes.VERSION })
|
137 | );
|
138 | }
|
139 |
|
140 | |
141 |
|
142 |
|
143 |
|
144 |
|
145 |
|
146 |
|
147 |
|
148 |
|
149 |
|
150 |
|
151 |
|
152 |
|
153 |
|
154 |
|
155 |
|
156 |
|
157 |
|
158 |
|
159 |
|
160 |
|
161 |
|
162 |
|
163 |
|
164 |
|
165 |
|
166 |
|
167 |
|
168 |
|
169 |
|
170 |
|
171 |
|
172 |
|
173 |
|
174 |
|
175 |
|
176 |
|
177 |
|
178 |
|
179 |
|
180 |
|
181 |
|
182 |
|
183 |
|
184 |
|
185 |
|
186 |
|
187 |
|
188 |
|
189 |
|
190 |
|
191 |
|
192 |
|
193 | createTable(tableName, attributes, options, model) {
|
194 | let sql = '';
|
195 | let promise;
|
196 |
|
197 | options = _.clone(options) || {};
|
198 |
|
199 | if (options && options.uniqueKeys) {
|
200 | _.forOwn(options.uniqueKeys, uniqueKey => {
|
201 | if (uniqueKey.customIndex === undefined) {
|
202 | uniqueKey.customIndex = true;
|
203 | }
|
204 | });
|
205 | }
|
206 |
|
207 | if (model) {
|
208 | options.uniqueKeys = options.uniqueKeys || model.uniqueKeys;
|
209 | }
|
210 |
|
211 | attributes = _.mapValues(
|
212 | attributes,
|
213 | attribute => this.sequelize.normalizeAttribute(attribute)
|
214 | );
|
215 |
|
216 |
|
217 | if (this.sequelize.options.dialect === 'postgres') {
|
218 | promise = PostgresQueryInterface.ensureEnums(this, tableName, attributes, options, model);
|
219 | } else {
|
220 | promise = Promise.resolve();
|
221 | }
|
222 |
|
223 | if (
|
224 | !tableName.schema &&
|
225 | (options.schema || !!model && model._schema)
|
226 | ) {
|
227 | tableName = this.QueryGenerator.addSchema({
|
228 | tableName,
|
229 | _schema: !!model && model._schema || options.schema
|
230 | });
|
231 | }
|
232 |
|
233 | attributes = this.QueryGenerator.attributesToSQL(attributes, { table: tableName, context: 'createTable' });
|
234 | sql = this.QueryGenerator.createTableQuery(tableName, attributes, options);
|
235 |
|
236 | return promise.then(() => this.sequelize.query(sql, options));
|
237 | }
|
238 |
|
239 | |
240 |
|
241 |
|
242 |
|
243 |
|
244 |
|
245 |
|
246 |
|
247 | dropTable(tableName, options) {
|
248 |
|
249 | options = _.clone(options) || {};
|
250 | options.cascade = options.cascade || options.force || false;
|
251 |
|
252 | let sql = this.QueryGenerator.dropTableQuery(tableName, options);
|
253 |
|
254 | return this.sequelize.query(sql, options).then(() => {
|
255 | const promises = [];
|
256 |
|
257 |
|
258 |
|
259 | if (this.sequelize.options.dialect === 'postgres') {
|
260 | const instanceTable = this.sequelize.modelManager.getModel(tableName, { attribute: 'tableName' });
|
261 |
|
262 | if (instanceTable) {
|
263 | const getTableName = (!options || !options.schema || options.schema === 'public' ? '' : `${options.schema}_`) + tableName;
|
264 |
|
265 | const keys = Object.keys(instanceTable.rawAttributes);
|
266 | const keyLen = keys.length;
|
267 |
|
268 | for (let i = 0; i < keyLen; i++) {
|
269 | if (instanceTable.rawAttributes[keys[i]].type instanceof DataTypes.ENUM) {
|
270 | sql = this.QueryGenerator.pgEnumDrop(getTableName, keys[i]);
|
271 | options.supportsSearchPath = false;
|
272 | promises.push(this.sequelize.query(sql, Object.assign({}, options, { raw: true })));
|
273 | }
|
274 | }
|
275 | }
|
276 | }
|
277 |
|
278 | return Promise.all(promises).get(0);
|
279 | });
|
280 | }
|
281 |
|
282 | |
283 |
|
284 |
|
285 |
|
286 |
|
287 |
|
288 |
|
289 |
|
290 | dropAllTables(options) {
|
291 | options = options || {};
|
292 | const skip = options.skip || [];
|
293 |
|
294 | const dropAllTables = tableNames => Promise.each(tableNames, tableName => {
|
295 |
|
296 | if (!skip.includes(tableName.tableName || tableName)) {
|
297 | return this.dropTable(tableName, Object.assign({}, options, { cascade: true }) );
|
298 | }
|
299 | });
|
300 |
|
301 | return this.showAllTables(options).then(tableNames => {
|
302 | if (this.sequelize.options.dialect === 'sqlite') {
|
303 | return this.sequelize.query('PRAGMA foreign_keys;', options).then(result => {
|
304 | const foreignKeysAreEnabled = result.foreign_keys === 1;
|
305 |
|
306 | if (foreignKeysAreEnabled) {
|
307 | return this.sequelize.query('PRAGMA foreign_keys = OFF', options)
|
308 | .then(() => dropAllTables(tableNames))
|
309 | .then(() => this.sequelize.query('PRAGMA foreign_keys = ON', options));
|
310 | }
|
311 | return dropAllTables(tableNames);
|
312 | });
|
313 | }
|
314 | return this.getForeignKeysForTables(tableNames, options).then(foreignKeys => {
|
315 | const queries = [];
|
316 |
|
317 | tableNames.forEach(tableName => {
|
318 | let normalizedTableName = tableName;
|
319 | if (_.isObject(tableName)) {
|
320 | normalizedTableName = `${tableName.schema}.${tableName.tableName}`;
|
321 | }
|
322 |
|
323 | foreignKeys[normalizedTableName].forEach(foreignKey => {
|
324 | queries.push(this.QueryGenerator.dropForeignKeyQuery(tableName, foreignKey));
|
325 | });
|
326 | });
|
327 |
|
328 | return Promise.each(queries, q => this.sequelize.query(q, options))
|
329 | .then(() => dropAllTables(tableNames));
|
330 | });
|
331 | });
|
332 | }
|
333 |
|
334 | |
335 |
|
336 |
|
337 |
|
338 |
|
339 |
|
340 |
|
341 |
|
342 |
|
343 | dropEnum(enumName, options) {
|
344 | if (this.sequelize.getDialect() !== 'postgres') {
|
345 | return Promise.resolve();
|
346 | }
|
347 |
|
348 | options = options || {};
|
349 |
|
350 | return this.sequelize.query(
|
351 | this.QueryGenerator.pgEnumDrop(null, null, this.QueryGenerator.pgEscapeAndQuote(enumName)),
|
352 | Object.assign({}, options, { raw: true })
|
353 | );
|
354 | }
|
355 |
|
356 | |
357 |
|
358 |
|
359 |
|
360 |
|
361 |
|
362 |
|
363 |
|
364 | dropAllEnums(options) {
|
365 | if (this.sequelize.getDialect() !== 'postgres') {
|
366 | return Promise.resolve();
|
367 | }
|
368 |
|
369 | options = options || {};
|
370 |
|
371 | return this.pgListEnums(null, options).map(result => this.sequelize.query(
|
372 | this.QueryGenerator.pgEnumDrop(null, null, this.QueryGenerator.pgEscapeAndQuote(result.enum_name)),
|
373 | Object.assign({}, options, { raw: true })
|
374 | ));
|
375 | }
|
376 |
|
377 | |
378 |
|
379 |
|
380 |
|
381 |
|
382 |
|
383 |
|
384 |
|
385 |
|
386 | pgListEnums(tableName, options) {
|
387 | options = options || {};
|
388 | const sql = this.QueryGenerator.pgListEnums(tableName);
|
389 | return this.sequelize.query(sql, Object.assign({}, options, { plain: false, raw: true, type: QueryTypes.SELECT }));
|
390 | }
|
391 |
|
392 | |
393 |
|
394 |
|
395 |
|
396 |
|
397 |
|
398 |
|
399 |
|
400 |
|
401 | renameTable(before, after, options) {
|
402 | options = options || {};
|
403 | const sql = this.QueryGenerator.renameTableQuery(before, after);
|
404 | return this.sequelize.query(sql, options);
|
405 | }
|
406 |
|
407 | |
408 |
|
409 |
|
410 |
|
411 |
|
412 |
|
413 |
|
414 |
|
415 |
|
416 |
|
417 | showAllTables(options) {
|
418 | options = Object.assign({}, options, {
|
419 | raw: true,
|
420 | type: QueryTypes.SHOWTABLES
|
421 | });
|
422 |
|
423 | const showTablesSql = this.QueryGenerator.showTablesQuery();
|
424 | return this.sequelize.query(showTablesSql, options).then(tableNames => _.flatten(tableNames));
|
425 | }
|
426 |
|
427 | |
428 |
|
429 |
|
430 |
|
431 |
|
432 |
|
433 |
|
434 |
|
435 |
|
436 |
|
437 |
|
438 |
|
439 |
|
440 |
|
441 |
|
442 |
|
443 |
|
444 |
|
445 |
|
446 |
|
447 |
|
448 |
|
449 |
|
450 |
|
451 |
|
452 | describeTable(tableName, options) {
|
453 | let schema = null;
|
454 | let schemaDelimiter = null;
|
455 |
|
456 | if (typeof options === 'string') {
|
457 | schema = options;
|
458 | } else if (typeof options === 'object' && options !== null) {
|
459 | schema = options.schema || null;
|
460 | schemaDelimiter = options.schemaDelimiter || null;
|
461 | }
|
462 |
|
463 | if (typeof tableName === 'object' && tableName !== null) {
|
464 | schema = tableName.schema;
|
465 | tableName = tableName.tableName;
|
466 | }
|
467 |
|
468 | const sql = this.QueryGenerator.describeTableQuery(tableName, schema, schemaDelimiter);
|
469 | options = Object.assign({}, options, { type: QueryTypes.DESCRIBE });
|
470 |
|
471 | return this.sequelize.query(sql, options).then(data => {
|
472 | |
473 |
|
474 |
|
475 |
|
476 |
|
477 | if (_.isEmpty(data)) {
|
478 | throw new Error(`No description found for "${tableName}" table. Check the table name and schema; remember, they _are_ case sensitive.`);
|
479 | }
|
480 |
|
481 | return data;
|
482 | }).catch(e => {
|
483 | if (e.original && e.original.code === 'ER_NO_SUCH_TABLE') {
|
484 | throw Error(`No description found for "${tableName}" table. Check the table name and schema; remember, they _are_ case sensitive.`);
|
485 | }
|
486 |
|
487 | throw e;
|
488 | });
|
489 | }
|
490 |
|
491 | |
492 |
|
493 |
|
494 |
|
495 |
|
496 |
|
497 |
|
498 |
|
499 |
|
500 |
|
501 |
|
502 |
|
503 |
|
504 |
|
505 |
|
506 |
|
507 | addColumn(table, key, attribute, options) {
|
508 | if (!table || !key || !attribute) {
|
509 | throw new Error('addColumn takes at least 3 arguments (table, attribute name, attribute definition)');
|
510 | }
|
511 |
|
512 | options = options || {};
|
513 | attribute = this.sequelize.normalizeAttribute(attribute);
|
514 | return this.sequelize.query(this.QueryGenerator.addColumnQuery(table, key, attribute), options);
|
515 | }
|
516 |
|
517 | |
518 |
|
519 |
|
520 |
|
521 |
|
522 |
|
523 |
|
524 |
|
525 |
|
526 | removeColumn(tableName, attributeName, options) {
|
527 | options = options || {};
|
528 | switch (this.sequelize.options.dialect) {
|
529 | case 'sqlite':
|
530 |
|
531 | return SQLiteQueryInterface.removeColumn(this, tableName, attributeName, options);
|
532 | case 'mssql':
|
533 |
|
534 | return MSSQLQueryInterface.removeColumn(this, tableName, attributeName, options);
|
535 | case 'mysql':
|
536 | case 'mariadb':
|
537 |
|
538 | return MySQLQueryInterface.removeColumn(this, tableName, attributeName, options);
|
539 | default:
|
540 | return this.sequelize.query(this.QueryGenerator.removeColumnQuery(tableName, attributeName), options);
|
541 | }
|
542 | }
|
543 |
|
544 | |
545 |
|
546 |
|
547 |
|
548 |
|
549 |
|
550 |
|
551 |
|
552 |
|
553 |
|
554 | changeColumn(tableName, attributeName, dataTypeOrOptions, options) {
|
555 | const attributes = {};
|
556 | options = options || {};
|
557 |
|
558 | if (_.values(DataTypes).includes(dataTypeOrOptions)) {
|
559 | attributes[attributeName] = { type: dataTypeOrOptions, allowNull: true };
|
560 | } else {
|
561 | attributes[attributeName] = dataTypeOrOptions;
|
562 | }
|
563 |
|
564 | attributes[attributeName] = this.sequelize.normalizeAttribute(attributes[attributeName]);
|
565 |
|
566 | if (this.sequelize.options.dialect === 'sqlite') {
|
567 |
|
568 | return SQLiteQueryInterface.changeColumn(this, tableName, attributes, options);
|
569 | }
|
570 | const query = this.QueryGenerator.attributesToSQL(attributes, {
|
571 | context: 'changeColumn',
|
572 | table: tableName
|
573 | });
|
574 | const sql = this.QueryGenerator.changeColumnQuery(tableName, query);
|
575 |
|
576 | return this.sequelize.query(sql, options);
|
577 | }
|
578 |
|
579 | |
580 |
|
581 |
|
582 |
|
583 |
|
584 |
|
585 |
|
586 |
|
587 |
|
588 |
|
589 | renameColumn(tableName, attrNameBefore, attrNameAfter, options) {
|
590 | options = options || {};
|
591 | return this.describeTable(tableName, options).then(data => {
|
592 | if (!data[attrNameBefore]) {
|
593 | throw new Error(`Table ${tableName} doesn't have the column ${attrNameBefore}`);
|
594 | }
|
595 |
|
596 | data = data[attrNameBefore] || {};
|
597 |
|
598 | const _options = {};
|
599 |
|
600 | _options[attrNameAfter] = {
|
601 | attribute: attrNameAfter,
|
602 | type: data.type,
|
603 | allowNull: data.allowNull,
|
604 | defaultValue: data.defaultValue
|
605 | };
|
606 |
|
607 |
|
608 | if (data.defaultValue === null && !data.allowNull) {
|
609 | delete _options[attrNameAfter].defaultValue;
|
610 | }
|
611 |
|
612 | if (this.sequelize.options.dialect === 'sqlite') {
|
613 |
|
614 | return SQLiteQueryInterface.renameColumn(this, tableName, attrNameBefore, attrNameAfter, options);
|
615 | }
|
616 | const sql = this.QueryGenerator.renameColumnQuery(
|
617 | tableName,
|
618 | attrNameBefore,
|
619 | this.QueryGenerator.attributesToSQL(_options)
|
620 | );
|
621 | return this.sequelize.query(sql, options);
|
622 | });
|
623 | }
|
624 |
|
625 | |
626 |
|
627 |
|
628 |
|
629 |
|
630 |
|
631 |
|
632 |
|
633 |
|
634 |
|
635 |
|
636 |
|
637 |
|
638 |
|
639 |
|
640 |
|
641 |
|
642 |
|
643 | addIndex(tableName, attributes, options, rawTablename) {
|
644 |
|
645 | if (!Array.isArray(attributes)) {
|
646 | rawTablename = options;
|
647 | options = attributes;
|
648 | attributes = options.fields;
|
649 | }
|
650 |
|
651 | if (!rawTablename) {
|
652 |
|
653 | rawTablename = tableName;
|
654 | }
|
655 |
|
656 | options = Utils.cloneDeep(options);
|
657 | options.fields = attributes;
|
658 | const sql = this.QueryGenerator.addIndexQuery(tableName, options, rawTablename);
|
659 | return this.sequelize.query(sql, Object.assign({}, options, { supportsSearchPath: false }));
|
660 | }
|
661 |
|
662 | |
663 |
|
664 |
|
665 |
|
666 |
|
667 |
|
668 |
|
669 |
|
670 |
|
671 | showIndex(tableName, options) {
|
672 | const sql = this.QueryGenerator.showIndexesQuery(tableName, options);
|
673 | return this.sequelize.query(sql, Object.assign({}, options, { type: QueryTypes.SHOWINDEXES }));
|
674 | }
|
675 |
|
676 | getForeignKeysForTables(tableNames, options) {
|
677 | if (tableNames.length === 0) {
|
678 | return Promise.resolve({});
|
679 | }
|
680 |
|
681 | options = Object.assign({}, options || {}, { type: QueryTypes.FOREIGNKEYS });
|
682 |
|
683 | return Promise.map(tableNames, tableName =>
|
684 | this.sequelize.query(this.QueryGenerator.getForeignKeysQuery(tableName, this.sequelize.config.database), options)
|
685 | ).then(results => {
|
686 | const result = {};
|
687 |
|
688 | tableNames.forEach((tableName, i) => {
|
689 | if (_.isObject(tableName)) {
|
690 | tableName = `${tableName.schema}.${tableName.tableName}`;
|
691 | }
|
692 |
|
693 | result[tableName] = Array.isArray(results[i])
|
694 | ? results[i].map(r => r.constraint_name)
|
695 | : [results[i] && results[i].constraint_name];
|
696 |
|
697 | result[tableName] = result[tableName].filter(_.identity);
|
698 | });
|
699 |
|
700 | return result;
|
701 | });
|
702 | }
|
703 |
|
704 | |
705 |
|
706 |
|
707 |
|
708 |
|
709 |
|
710 |
|
711 |
|
712 |
|
713 |
|
714 |
|
715 |
|
716 |
|
717 | getForeignKeyReferencesForTable(tableName, options) {
|
718 | const queryOptions = Object.assign({}, options, {
|
719 | type: QueryTypes.FOREIGNKEYS
|
720 | });
|
721 | const catalogName = this.sequelize.config.database;
|
722 | switch (this.sequelize.options.dialect) {
|
723 | case 'sqlite':
|
724 |
|
725 | return SQLiteQueryInterface.getForeignKeyReferencesForTable(this, tableName, queryOptions);
|
726 | case 'postgres':
|
727 | {
|
728 |
|
729 |
|
730 | const query = this.QueryGenerator.getForeignKeyReferencesQuery(tableName, catalogName);
|
731 | return this.sequelize.query(query, queryOptions)
|
732 | .then(result => result.map(Utils.camelizeObjectKeys));
|
733 | }
|
734 | case 'mssql':
|
735 | case 'mysql':
|
736 | case 'mariadb':
|
737 | default: {
|
738 | const query = this.QueryGenerator.getForeignKeysQuery(tableName, catalogName);
|
739 | return this.sequelize.query(query, queryOptions);
|
740 | }
|
741 | }
|
742 | }
|
743 |
|
744 | |
745 |
|
746 |
|
747 |
|
748 |
|
749 |
|
750 |
|
751 |
|
752 |
|
753 | removeIndex(tableName, indexNameOrAttributes, options) {
|
754 | options = options || {};
|
755 | const sql = this.QueryGenerator.removeIndexQuery(tableName, indexNameOrAttributes);
|
756 | return this.sequelize.query(sql, options);
|
757 | }
|
758 |
|
759 | |
760 |
|
761 |
|
762 |
|
763 |
|
764 |
|
765 |
|
766 |
|
767 |
|
768 |
|
769 |
|
770 |
|
771 |
|
772 |
|
773 |
|
774 |
|
775 |
|
776 |
|
777 |
|
778 |
|
779 |
|
780 |
|
781 |
|
782 |
|
783 |
|
784 |
|
785 |
|
786 |
|
787 |
|
788 |
|
789 |
|
790 |
|
791 |
|
792 |
|
793 |
|
794 |
|
795 |
|
796 |
|
797 |
|
798 |
|
799 |
|
800 |
|
801 |
|
802 |
|
803 |
|
804 |
|
805 |
|
806 |
|
807 |
|
808 |
|
809 |
|
810 |
|
811 |
|
812 |
|
813 |
|
814 |
|
815 |
|
816 |
|
817 |
|
818 |
|
819 |
|
820 |
|
821 | addConstraint(tableName, attributes, options, rawTablename) {
|
822 | if (!Array.isArray(attributes)) {
|
823 | rawTablename = options;
|
824 | options = attributes;
|
825 | attributes = options.fields;
|
826 | }
|
827 |
|
828 | if (!options.type) {
|
829 | throw new Error('Constraint type must be specified through options.type');
|
830 | }
|
831 |
|
832 | if (!rawTablename) {
|
833 |
|
834 | rawTablename = tableName;
|
835 | }
|
836 |
|
837 | options = Utils.cloneDeep(options);
|
838 | options.fields = attributes;
|
839 |
|
840 | if (this.sequelize.dialect.name === 'sqlite') {
|
841 | return SQLiteQueryInterface.addConstraint(this, tableName, options, rawTablename);
|
842 | }
|
843 | const sql = this.QueryGenerator.addConstraintQuery(tableName, options, rawTablename);
|
844 | return this.sequelize.query(sql, options);
|
845 | }
|
846 |
|
847 | showConstraint(tableName, constraintName, options) {
|
848 | const sql = this.QueryGenerator.showConstraintsQuery(tableName, constraintName);
|
849 | return this.sequelize.query(sql, Object.assign({}, options, { type: QueryTypes.SHOWCONSTRAINTS }));
|
850 | }
|
851 |
|
852 | |
853 |
|
854 |
|
855 |
|
856 |
|
857 |
|
858 |
|
859 |
|
860 |
|
861 | removeConstraint(tableName, constraintName, options) {
|
862 | options = options || {};
|
863 |
|
864 | switch (this.sequelize.options.dialect) {
|
865 | case 'mysql':
|
866 | case 'mariadb':
|
867 |
|
868 | return MySQLQueryInterface.removeConstraint(this, tableName, constraintName, options);
|
869 | case 'sqlite':
|
870 | return SQLiteQueryInterface.removeConstraint(this, tableName, constraintName, options);
|
871 | default:
|
872 | const sql = this.QueryGenerator.removeConstraintQuery(tableName, constraintName);
|
873 | return this.sequelize.query(sql, options);
|
874 | }
|
875 | }
|
876 |
|
877 | insert(instance, tableName, values, options) {
|
878 | options = Utils.cloneDeep(options);
|
879 | options.hasTrigger = instance && instance.constructor.options.hasTrigger;
|
880 | const sql = this.QueryGenerator.insertQuery(tableName, values, instance && instance.constructor.rawAttributes, options);
|
881 |
|
882 | options.type = QueryTypes.INSERT;
|
883 | options.instance = instance;
|
884 |
|
885 | return this.sequelize.query(sql, options).then(results => {
|
886 | if (instance) results[0].isNewRecord = false;
|
887 | return results;
|
888 | });
|
889 | }
|
890 |
|
891 | |
892 |
|
893 |
|
894 |
|
895 |
|
896 |
|
897 |
|
898 |
|
899 |
|
900 |
|
901 |
|
902 |
|
903 | upsert(tableName, insertValues, updateValues, where, model, options) {
|
904 | const wheres = [];
|
905 | const attributes = Object.keys(insertValues);
|
906 | let indexes = [];
|
907 | let indexFields;
|
908 |
|
909 | options = _.clone(options);
|
910 |
|
911 | if (!Utils.isWhereEmpty(where)) {
|
912 | wheres.push(where);
|
913 | }
|
914 |
|
915 |
|
916 | indexes = _.map(model.uniqueKeys, value => {
|
917 | return value.fields;
|
918 | });
|
919 |
|
920 | model._indexes.forEach(value => {
|
921 | if (value.unique) {
|
922 |
|
923 | indexFields = value.fields.map(field => {
|
924 | if (_.isPlainObject(field)) {
|
925 | return field.attribute;
|
926 | }
|
927 | return field;
|
928 | });
|
929 | indexes.push(indexFields);
|
930 | }
|
931 | });
|
932 |
|
933 | for (const index of indexes) {
|
934 | if (_.intersection(attributes, index).length === index.length) {
|
935 | where = {};
|
936 | for (const field of index) {
|
937 | where[field] = insertValues[field];
|
938 | }
|
939 | wheres.push(where);
|
940 | }
|
941 | }
|
942 |
|
943 | where = { [Op.or]: wheres };
|
944 |
|
945 | options.type = QueryTypes.UPSERT;
|
946 | options.raw = true;
|
947 |
|
948 | const sql = this.QueryGenerator.upsertQuery(tableName, insertValues, updateValues, where, model, options);
|
949 | return this.sequelize.query(sql, options).then(result => {
|
950 | switch (this.sequelize.options.dialect) {
|
951 | case 'postgres':
|
952 | return [result.created, result.primary_key];
|
953 |
|
954 | case 'mssql':
|
955 | return [
|
956 | result.$action === 'INSERT',
|
957 | result[model.primaryKeyField]
|
958 | ];
|
959 |
|
960 |
|
961 |
|
962 | case 'mysql':
|
963 | case 'mariadb':
|
964 | return [result === 1, undefined];
|
965 |
|
966 | default:
|
967 | return [result, undefined];
|
968 | }
|
969 | });
|
970 | }
|
971 |
|
972 | |
973 |
|
974 |
|
975 |
|
976 |
|
977 |
|
978 |
|
979 |
|
980 |
|
981 |
|
982 |
|
983 |
|
984 |
|
985 |
|
986 |
|
987 |
|
988 |
|
989 |
|
990 |
|
991 |
|
992 |
|
993 | bulkInsert(tableName, records, options, attributes) {
|
994 | options = _.clone(options) || {};
|
995 | options.type = QueryTypes.INSERT;
|
996 |
|
997 | return this.sequelize.query(
|
998 | this.QueryGenerator.bulkInsertQuery(tableName, records, options, attributes),
|
999 | options
|
1000 | ).then(results => results[0]);
|
1001 | }
|
1002 |
|
1003 | update(instance, tableName, values, identifier, options) {
|
1004 | options = _.clone(options || {});
|
1005 | options.hasTrigger = !!(instance && instance._modelOptions && instance._modelOptions.hasTrigger);
|
1006 |
|
1007 | const sql = this.QueryGenerator.updateQuery(tableName, values, identifier, options, instance.constructor.rawAttributes);
|
1008 |
|
1009 | options.type = QueryTypes.UPDATE;
|
1010 |
|
1011 | options.instance = instance;
|
1012 | return this.sequelize.query(sql, options);
|
1013 | }
|
1014 |
|
1015 | |
1016 |
|
1017 |
|
1018 |
|
1019 |
|
1020 |
|
1021 |
|
1022 |
|
1023 |
|
1024 |
|
1025 |
|
1026 |
|
1027 |
|
1028 |
|
1029 |
|
1030 |
|
1031 |
|
1032 |
|
1033 |
|
1034 | bulkUpdate(tableName, values, identifier, options, attributes) {
|
1035 | options = Utils.cloneDeep(options);
|
1036 | if (typeof identifier === 'object') identifier = Utils.cloneDeep(identifier);
|
1037 |
|
1038 | const sql = this.QueryGenerator.updateQuery(tableName, values, identifier, options, attributes);
|
1039 | const table = _.isObject(tableName) ? tableName : { tableName };
|
1040 | const model = _.find(this.sequelize.modelManager.models, { tableName: table.tableName });
|
1041 |
|
1042 | options.model = model;
|
1043 | return this.sequelize.query(sql, options);
|
1044 | }
|
1045 |
|
1046 | delete(instance, tableName, identifier, options) {
|
1047 | const cascades = [];
|
1048 | const sql = this.QueryGenerator.deleteQuery(tableName, identifier, {}, instance.constructor);
|
1049 |
|
1050 | options = _.clone(options) || {};
|
1051 |
|
1052 |
|
1053 | if (!!instance.constructor && !!instance.constructor.associations) {
|
1054 | const keys = Object.keys(instance.constructor.associations);
|
1055 | const length = keys.length;
|
1056 | let association;
|
1057 |
|
1058 | for (let i = 0; i < length; i++) {
|
1059 | association = instance.constructor.associations[keys[i]];
|
1060 | if (association.options && association.options.onDelete &&
|
1061 | association.options.onDelete.toLowerCase() === 'cascade' &&
|
1062 | association.options.useHooks === true) {
|
1063 | cascades.push(association.accessors.get);
|
1064 | }
|
1065 | }
|
1066 | }
|
1067 |
|
1068 | return Promise.each(cascades, cascade => {
|
1069 | return instance[cascade](options).then(instances => {
|
1070 |
|
1071 | if (!instances) {
|
1072 | return Promise.resolve();
|
1073 | }
|
1074 |
|
1075 | if (!Array.isArray(instances)) instances = [instances];
|
1076 |
|
1077 | return Promise.each(instances, instance => instance.destroy(options));
|
1078 | });
|
1079 | }).then(() => {
|
1080 | options.instance = instance;
|
1081 | return this.sequelize.query(sql, options);
|
1082 | });
|
1083 | }
|
1084 |
|
1085 | |
1086 |
|
1087 |
|
1088 |
|
1089 |
|
1090 |
|
1091 |
|
1092 |
|
1093 |
|
1094 |
|
1095 |
|
1096 | bulkDelete(tableName, where, options, model) {
|
1097 | options = Utils.cloneDeep(options);
|
1098 | options = _.defaults(options, { limit: null });
|
1099 |
|
1100 | if (options.truncate === true) {
|
1101 | return this.sequelize.query(
|
1102 | this.QueryGenerator.truncateTableQuery(tableName, options),
|
1103 | options
|
1104 | );
|
1105 | }
|
1106 |
|
1107 | if (typeof identifier === 'object') where = Utils.cloneDeep(where);
|
1108 |
|
1109 | return this.sequelize.query(
|
1110 | this.QueryGenerator.deleteQuery(tableName, where, options, model),
|
1111 | options
|
1112 | );
|
1113 | }
|
1114 |
|
1115 | select(model, tableName, optionsArg) {
|
1116 | const options = Object.assign({}, optionsArg, { type: QueryTypes.SELECT, model });
|
1117 |
|
1118 | return this.sequelize.query(
|
1119 | this.QueryGenerator.selectQuery(tableName, options, model),
|
1120 | options
|
1121 | );
|
1122 | }
|
1123 |
|
1124 | increment(model, tableName, values, identifier, options) {
|
1125 | options = Utils.cloneDeep(options);
|
1126 |
|
1127 | const sql = this.QueryGenerator.arithmeticQuery('+', tableName, values, identifier, options, options.attributes);
|
1128 |
|
1129 | options.type = QueryTypes.UPDATE;
|
1130 | options.model = model;
|
1131 |
|
1132 | return this.sequelize.query(sql, options);
|
1133 | }
|
1134 |
|
1135 | decrement(model, tableName, values, identifier, options) {
|
1136 | options = Utils.cloneDeep(options);
|
1137 |
|
1138 | const sql = this.QueryGenerator.arithmeticQuery('-', tableName, values, identifier, options, options.attributes);
|
1139 |
|
1140 | options.type = QueryTypes.UPDATE;
|
1141 | options.model = model;
|
1142 |
|
1143 | return this.sequelize.query(sql, options);
|
1144 | }
|
1145 |
|
1146 | rawSelect(tableName, options, attributeSelector, Model) {
|
1147 | options = Utils.cloneDeep(options);
|
1148 | options = _.defaults(options, {
|
1149 | raw: true,
|
1150 | plain: true,
|
1151 | type: QueryTypes.SELECT
|
1152 | });
|
1153 |
|
1154 | const sql = this.QueryGenerator.selectQuery(tableName, options, Model);
|
1155 |
|
1156 | if (attributeSelector === undefined) {
|
1157 | throw new Error('Please pass an attribute selector!');
|
1158 | }
|
1159 |
|
1160 | return this.sequelize.query(sql, options).then(data => {
|
1161 | if (!options.plain) {
|
1162 | return data;
|
1163 | }
|
1164 |
|
1165 | const result = data ? data[attributeSelector] : null;
|
1166 |
|
1167 | if (!options || !options.dataType) {
|
1168 | return result;
|
1169 | }
|
1170 |
|
1171 | const dataType = options.dataType;
|
1172 |
|
1173 | if (dataType instanceof DataTypes.DECIMAL || dataType instanceof DataTypes.FLOAT) {
|
1174 | if (result !== null) {
|
1175 | return parseFloat(result);
|
1176 | }
|
1177 | }
|
1178 | if (dataType instanceof DataTypes.INTEGER || dataType instanceof DataTypes.BIGINT) {
|
1179 | return parseInt(result, 10);
|
1180 | }
|
1181 | if (dataType instanceof DataTypes.DATE) {
|
1182 | if (result !== null && !(result instanceof Date)) {
|
1183 | return new Date(result);
|
1184 | }
|
1185 | }
|
1186 | return result;
|
1187 | });
|
1188 | }
|
1189 |
|
1190 | createTrigger(tableName, triggerName, timingType, fireOnArray, functionName, functionParams, optionsArray, options) {
|
1191 | const sql = this.QueryGenerator.createTrigger(tableName, triggerName, timingType, fireOnArray, functionName, functionParams, optionsArray);
|
1192 | options = options || {};
|
1193 | if (sql) {
|
1194 | return this.sequelize.query(sql, options);
|
1195 | }
|
1196 | return Promise.resolve();
|
1197 | }
|
1198 |
|
1199 | dropTrigger(tableName, triggerName, options) {
|
1200 | const sql = this.QueryGenerator.dropTrigger(tableName, triggerName);
|
1201 | options = options || {};
|
1202 |
|
1203 | if (sql) {
|
1204 | return this.sequelize.query(sql, options);
|
1205 | }
|
1206 | return Promise.resolve();
|
1207 | }
|
1208 |
|
1209 | renameTrigger(tableName, oldTriggerName, newTriggerName, options) {
|
1210 | const sql = this.QueryGenerator.renameTrigger(tableName, oldTriggerName, newTriggerName);
|
1211 | options = options || {};
|
1212 |
|
1213 | if (sql) {
|
1214 | return this.sequelize.query(sql, options);
|
1215 | }
|
1216 | return Promise.resolve();
|
1217 | }
|
1218 |
|
1219 | |
1220 |
|
1221 |
|
1222 |
|
1223 |
|
1224 |
|
1225 |
|
1226 |
|
1227 |
|
1228 |
|
1229 |
|
1230 |
|
1231 |
|
1232 |
|
1233 |
|
1234 |
|
1235 |
|
1236 |
|
1237 |
|
1238 |
|
1239 |
|
1240 |
|
1241 |
|
1242 |
|
1243 |
|
1244 |
|
1245 |
|
1246 |
|
1247 |
|
1248 |
|
1249 |
|
1250 |
|
1251 |
|
1252 |
|
1253 |
|
1254 |
|
1255 |
|
1256 | createFunction(functionName, params, returnType, language, body, optionsArray, options) {
|
1257 | const sql = this.QueryGenerator.createFunction(functionName, params, returnType, language, body, optionsArray, options);
|
1258 | options = options || {};
|
1259 |
|
1260 | if (sql) {
|
1261 | return this.sequelize.query(sql, options);
|
1262 | }
|
1263 | return Promise.resolve();
|
1264 | }
|
1265 |
|
1266 | |
1267 |
|
1268 |
|
1269 |
|
1270 |
|
1271 |
|
1272 |
|
1273 |
|
1274 |
|
1275 |
|
1276 |
|
1277 |
|
1278 |
|
1279 |
|
1280 |
|
1281 |
|
1282 |
|
1283 |
|
1284 | dropFunction(functionName, params, options) {
|
1285 | const sql = this.QueryGenerator.dropFunction(functionName, params);
|
1286 | options = options || {};
|
1287 |
|
1288 | if (sql) {
|
1289 | return this.sequelize.query(sql, options);
|
1290 | }
|
1291 | return Promise.resolve();
|
1292 | }
|
1293 |
|
1294 | |
1295 |
|
1296 |
|
1297 |
|
1298 |
|
1299 |
|
1300 |
|
1301 |
|
1302 |
|
1303 |
|
1304 |
|
1305 |
|
1306 |
|
1307 |
|
1308 |
|
1309 |
|
1310 |
|
1311 |
|
1312 |
|
1313 |
|
1314 | renameFunction(oldFunctionName, params, newFunctionName, options) {
|
1315 | const sql = this.QueryGenerator.renameFunction(oldFunctionName, params, newFunctionName);
|
1316 | options = options || {};
|
1317 |
|
1318 | if (sql) {
|
1319 | return this.sequelize.query(sql, options);
|
1320 | }
|
1321 | return Promise.resolve();
|
1322 | }
|
1323 |
|
1324 |
|
1325 |
|
1326 | |
1327 |
|
1328 |
|
1329 |
|
1330 |
|
1331 |
|
1332 |
|
1333 |
|
1334 | quoteIdentifier(identifier, force) {
|
1335 | return this.QueryGenerator.quoteIdentifier(identifier, force);
|
1336 | }
|
1337 |
|
1338 | quoteTable(identifier) {
|
1339 | return this.QueryGenerator.quoteTable(identifier);
|
1340 | }
|
1341 |
|
1342 | |
1343 |
|
1344 |
|
1345 |
|
1346 |
|
1347 |
|
1348 |
|
1349 |
|
1350 | quoteIdentifiers(identifiers, force) {
|
1351 | return this.QueryGenerator.quoteIdentifiers(identifiers, force);
|
1352 | }
|
1353 |
|
1354 | |
1355 |
|
1356 |
|
1357 |
|
1358 |
|
1359 |
|
1360 |
|
1361 | escape(value) {
|
1362 | return this.QueryGenerator.escape(value);
|
1363 | }
|
1364 |
|
1365 | setIsolationLevel(transaction, value, options) {
|
1366 | if (!transaction || !(transaction instanceof Transaction)) {
|
1367 | throw new Error('Unable to set isolation level for a transaction without transaction object!');
|
1368 | }
|
1369 |
|
1370 | if (transaction.parent || !value) {
|
1371 |
|
1372 | return Promise.resolve();
|
1373 | }
|
1374 |
|
1375 | options = Object.assign({}, options, {
|
1376 | transaction: transaction.parent || transaction
|
1377 | });
|
1378 |
|
1379 | const sql = this.QueryGenerator.setIsolationLevelQuery(value, {
|
1380 | parent: transaction.parent
|
1381 | });
|
1382 |
|
1383 | if (!sql) return Promise.resolve();
|
1384 |
|
1385 | return this.sequelize.query(sql, options);
|
1386 | }
|
1387 |
|
1388 | startTransaction(transaction, options) {
|
1389 | if (!transaction || !(transaction instanceof Transaction)) {
|
1390 | throw new Error('Unable to start a transaction without transaction object!');
|
1391 | }
|
1392 |
|
1393 | options = Object.assign({}, options, {
|
1394 | transaction: transaction.parent || transaction
|
1395 | });
|
1396 | options.transaction.name = transaction.parent ? transaction.name : undefined;
|
1397 | const sql = this.QueryGenerator.startTransactionQuery(transaction);
|
1398 |
|
1399 | return this.sequelize.query(sql, options);
|
1400 | }
|
1401 |
|
1402 | deferConstraints(transaction, options) {
|
1403 | options = Object.assign({}, options, {
|
1404 | transaction: transaction.parent || transaction
|
1405 | });
|
1406 |
|
1407 | const sql = this.QueryGenerator.deferConstraintsQuery(options);
|
1408 |
|
1409 | if (sql) {
|
1410 | return this.sequelize.query(sql, options);
|
1411 | }
|
1412 |
|
1413 | return Promise.resolve();
|
1414 | }
|
1415 |
|
1416 | commitTransaction(transaction, options) {
|
1417 | if (!transaction || !(transaction instanceof Transaction)) {
|
1418 | throw new Error('Unable to commit a transaction without transaction object!');
|
1419 | }
|
1420 | if (transaction.parent) {
|
1421 |
|
1422 | return Promise.resolve();
|
1423 | }
|
1424 |
|
1425 | options = Object.assign({}, options, {
|
1426 | transaction: transaction.parent || transaction,
|
1427 | supportsSearchPath: false,
|
1428 | completesTransaction: true
|
1429 | });
|
1430 |
|
1431 | const sql = this.QueryGenerator.commitTransactionQuery(transaction);
|
1432 | const promise = this.sequelize.query(sql, options);
|
1433 |
|
1434 | transaction.finished = 'commit';
|
1435 |
|
1436 | return promise;
|
1437 | }
|
1438 |
|
1439 | rollbackTransaction(transaction, options) {
|
1440 | if (!transaction || !(transaction instanceof Transaction)) {
|
1441 | throw new Error('Unable to rollback a transaction without transaction object!');
|
1442 | }
|
1443 |
|
1444 | options = Object.assign({}, options, {
|
1445 | transaction: transaction.parent || transaction,
|
1446 | supportsSearchPath: false,
|
1447 | completesTransaction: true
|
1448 | });
|
1449 | options.transaction.name = transaction.parent ? transaction.name : undefined;
|
1450 | const sql = this.QueryGenerator.rollbackTransactionQuery(transaction);
|
1451 | const promise = this.sequelize.query(sql, options);
|
1452 |
|
1453 | transaction.finished = 'rollback';
|
1454 |
|
1455 | return promise;
|
1456 | }
|
1457 | }
|
1458 |
|
1459 | module.exports = QueryInterface;
|
1460 | module.exports.QueryInterface = QueryInterface;
|
1461 | module.exports.default = QueryInterface;
|