query-interface.js 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. 'use strict';
  2. const _ = require('lodash');
  3. const Utils = require('../../utils');
  4. const QueryTypes = require('../../query-types');
  5. const Op = require('../../operators');
  6. const { QueryInterface } = require('../abstract/query-interface');
  7. /**
  8. * The interface that Sequelize uses to talk with MSSQL database
  9. */
  10. class MSSqlQueryInterface extends QueryInterface {
  11. /**
  12. * A wrapper that fixes MSSQL's inability to cleanly remove columns from existing tables if they have a default constraint.
  13. *
  14. * @override
  15. */
  16. async removeColumn(tableName, attributeName, options) {
  17. options = { raw: true, ...options || {} };
  18. const findConstraintSql = this.queryGenerator.getDefaultConstraintQuery(tableName, attributeName);
  19. const [results0] = await this.sequelize.query(findConstraintSql, options);
  20. if (results0.length) {
  21. // No default constraint found -- we can cleanly remove the column
  22. const dropConstraintSql = this.queryGenerator.dropConstraintQuery(tableName, results0[0].name);
  23. await this.sequelize.query(dropConstraintSql, options);
  24. }
  25. const findForeignKeySql = this.queryGenerator.getForeignKeyQuery(tableName, attributeName);
  26. const [results] = await this.sequelize.query(findForeignKeySql, options);
  27. if (results.length) {
  28. // No foreign key constraints found, so we can remove the column
  29. const dropForeignKeySql = this.queryGenerator.dropForeignKeyQuery(tableName, results[0].constraint_name);
  30. await this.sequelize.query(dropForeignKeySql, options);
  31. }
  32. //Check if the current column is a primaryKey
  33. const primaryKeyConstraintSql = this.queryGenerator.getPrimaryKeyConstraintQuery(tableName, attributeName);
  34. const [result] = await this.sequelize.query(primaryKeyConstraintSql, options);
  35. if (result.length) {
  36. const dropConstraintSql = this.queryGenerator.dropConstraintQuery(tableName, result[0].constraintName);
  37. await this.sequelize.query(dropConstraintSql, options);
  38. }
  39. const removeSql = this.queryGenerator.removeColumnQuery(tableName, attributeName);
  40. return this.sequelize.query(removeSql, options);
  41. }
  42. /**
  43. * @override
  44. */
  45. async upsert(tableName, insertValues, updateValues, where, options) {
  46. const model = options.model;
  47. const wheres = [];
  48. options = { ...options };
  49. if (!Utils.isWhereEmpty(where)) {
  50. wheres.push(where);
  51. }
  52. // Lets combine unique keys and indexes into one
  53. let indexes = Object.values(model.uniqueKeys).map(item => item.fields);
  54. indexes = indexes.concat(Object.values(model._indexes).filter(item => item.unique).map(item => item.fields));
  55. const attributes = Object.keys(insertValues);
  56. for (const index of indexes) {
  57. if (_.intersection(attributes, index).length === index.length) {
  58. where = {};
  59. for (const field of index) {
  60. where[field] = insertValues[field];
  61. }
  62. wheres.push(where);
  63. }
  64. }
  65. where = { [Op.or]: wheres };
  66. options.type = QueryTypes.UPSERT;
  67. options.raw = true;
  68. const sql = this.queryGenerator.upsertQuery(tableName, insertValues, updateValues, where, model, options);
  69. return await this.sequelize.query(sql, options);
  70. }
  71. }
  72. exports.MSSqlQueryInterface = MSSqlQueryInterface;