query.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. "use strict";
  2. var __defProp = Object.defineProperty;
  3. var __getOwnPropSymbols = Object.getOwnPropertySymbols;
  4. var __hasOwnProp = Object.prototype.hasOwnProperty;
  5. var __propIsEnum = Object.prototype.propertyIsEnumerable;
  6. var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
  7. var __spreadValues = (a, b) => {
  8. for (var prop in b || (b = {}))
  9. if (__hasOwnProp.call(b, prop))
  10. __defNormalProp(a, prop, b[prop]);
  11. if (__getOwnPropSymbols)
  12. for (var prop of __getOwnPropSymbols(b)) {
  13. if (__propIsEnum.call(b, prop))
  14. __defNormalProp(a, prop, b[prop]);
  15. }
  16. return a;
  17. };
  18. const AbstractQuery = require("../abstract/query");
  19. const sequelizeErrors = require("../../errors");
  20. const _ = require("lodash");
  21. const { logger } = require("../../utils/logger");
  22. const ER_DUP_ENTRY = 1062;
  23. const ER_DEADLOCK = 1213;
  24. const ER_ROW_IS_REFERENCED = 1451;
  25. const ER_NO_REFERENCED_ROW = 1452;
  26. const debug = logger.debugContext("sql:mysql");
  27. class Query extends AbstractQuery {
  28. constructor(connection, sequelize, options) {
  29. super(connection, sequelize, __spreadValues({ showWarnings: false }, options));
  30. }
  31. static formatBindParameters(sql, values, dialect) {
  32. const bindParam = [];
  33. const replacementFunc = (match, key, values_) => {
  34. if (values_[key] !== void 0) {
  35. bindParam.push(values_[key]);
  36. return "?";
  37. }
  38. return void 0;
  39. };
  40. sql = AbstractQuery.formatBindParameters(sql, values, dialect, replacementFunc)[0];
  41. return [sql, bindParam.length > 0 ? bindParam : void 0];
  42. }
  43. async run(sql, parameters) {
  44. this.sql = sql;
  45. const { connection, options } = this;
  46. const showWarnings = this.sequelize.options.showWarnings || options.showWarnings;
  47. const complete = this._logQuery(sql, debug, parameters);
  48. if (parameters) {
  49. debug("parameters(%j)", parameters);
  50. }
  51. let results;
  52. const errForStack = new Error();
  53. try {
  54. if (parameters && parameters.length) {
  55. results = await new Promise((resolve, reject) => {
  56. connection.execute(sql, parameters, (error, result) => error ? reject(error) : resolve(result)).setMaxListeners(100);
  57. });
  58. } else {
  59. results = await new Promise((resolve, reject) => {
  60. connection.query({ sql }, (error, result) => error ? reject(error) : resolve(result)).setMaxListeners(100);
  61. });
  62. }
  63. } catch (error) {
  64. if (options.transaction && error.errno === ER_DEADLOCK) {
  65. try {
  66. await options.transaction.rollback();
  67. } catch (error_) {
  68. }
  69. options.transaction.finished = "rollback";
  70. }
  71. error.sql = sql;
  72. error.parameters = parameters;
  73. throw this.formatError(error, errForStack.stack);
  74. } finally {
  75. complete();
  76. }
  77. if (showWarnings && results && results.warningStatus > 0) {
  78. await this.logWarnings(results);
  79. }
  80. return this.formatResults(results);
  81. }
  82. formatResults(data) {
  83. let result = this.instance;
  84. if (this.isInsertQuery(data)) {
  85. this.handleInsertQuery(data);
  86. if (!this.instance) {
  87. if (data.constructor.name === "ResultSetHeader" && this.model && this.model.autoIncrementAttribute && this.model.autoIncrementAttribute === this.model.primaryKeyAttribute && this.model.rawAttributes[this.model.primaryKeyAttribute]) {
  88. const startId = data[this.getInsertIdField()];
  89. result = [];
  90. for (let i = startId; i < startId + data.affectedRows; i++) {
  91. result.push({ [this.model.rawAttributes[this.model.primaryKeyAttribute].field]: i });
  92. }
  93. } else {
  94. result = data[this.getInsertIdField()];
  95. }
  96. }
  97. }
  98. if (this.isSelectQuery()) {
  99. return this.handleSelectQuery(data);
  100. }
  101. if (this.isShowTablesQuery()) {
  102. return this.handleShowTablesQuery(data);
  103. }
  104. if (this.isDescribeQuery()) {
  105. result = {};
  106. for (const _result of data) {
  107. const enumRegex = /^enum/i;
  108. result[_result.Field] = {
  109. type: enumRegex.test(_result.Type) ? _result.Type.replace(enumRegex, "ENUM") : _result.Type.toUpperCase(),
  110. allowNull: _result.Null === "YES",
  111. defaultValue: _result.Default,
  112. primaryKey: _result.Key === "PRI",
  113. autoIncrement: Object.prototype.hasOwnProperty.call(_result, "Extra") && _result.Extra.toLowerCase() === "auto_increment",
  114. comment: _result.Comment ? _result.Comment : null
  115. };
  116. }
  117. return result;
  118. }
  119. if (this.isShowIndexesQuery()) {
  120. return this.handleShowIndexesQuery(data);
  121. }
  122. if (this.isCallQuery()) {
  123. return data[0];
  124. }
  125. if (this.isBulkUpdateQuery() || this.isBulkDeleteQuery()) {
  126. return data.affectedRows;
  127. }
  128. if (this.isVersionQuery()) {
  129. return data[0].version;
  130. }
  131. if (this.isForeignKeysQuery()) {
  132. return data;
  133. }
  134. if (this.isUpsertQuery()) {
  135. return [result, data.affectedRows === 1];
  136. }
  137. if (this.isInsertQuery() || this.isUpdateQuery()) {
  138. return [result, data.affectedRows];
  139. }
  140. if (this.isShowConstraintsQuery()) {
  141. return data;
  142. }
  143. if (this.isRawQuery()) {
  144. return [data, data];
  145. }
  146. return result;
  147. }
  148. async logWarnings(results) {
  149. const warningResults = await this.run("SHOW WARNINGS");
  150. const warningMessage = `MySQL Warnings (${this.connection.uuid || "default"}): `;
  151. const messages = [];
  152. for (const _warningRow of warningResults) {
  153. if (_warningRow === void 0 || typeof _warningRow[Symbol.iterator] !== "function") {
  154. continue;
  155. }
  156. for (const _warningResult of _warningRow) {
  157. if (Object.prototype.hasOwnProperty.call(_warningResult, "Message")) {
  158. messages.push(_warningResult.Message);
  159. } else {
  160. for (const _objectKey of _warningResult.keys()) {
  161. messages.push([_objectKey, _warningResult[_objectKey]].join(": "));
  162. }
  163. }
  164. }
  165. }
  166. this.sequelize.log(warningMessage + messages.join("; "), this.options);
  167. return results;
  168. }
  169. formatError(err, errStack) {
  170. const errCode = err.errno || err.code;
  171. switch (errCode) {
  172. case ER_DUP_ENTRY: {
  173. const match = err.message.match(/Duplicate entry '([\s\S]*)' for key '?((.|\s)*?)'?$/);
  174. let fields = {};
  175. let message = "Validation error";
  176. const values = match ? match[1].split("-") : void 0;
  177. const fieldKey = match ? match[2].split(".").pop() : void 0;
  178. const fieldVal = match ? match[1] : void 0;
  179. const uniqueKey = this.model && this.model.uniqueKeys[fieldKey];
  180. if (uniqueKey) {
  181. if (uniqueKey.msg)
  182. message = uniqueKey.msg;
  183. fields = _.zipObject(uniqueKey.fields, values);
  184. } else {
  185. fields[fieldKey] = fieldVal;
  186. }
  187. const errors = [];
  188. _.forOwn(fields, (value, field) => {
  189. errors.push(new sequelizeErrors.ValidationErrorItem(this.getUniqueConstraintErrorMessage(field), "unique violation", field, value, this.instance, "not_unique"));
  190. });
  191. return new sequelizeErrors.UniqueConstraintError({ message, errors, parent: err, fields, stack: errStack });
  192. }
  193. case ER_ROW_IS_REFERENCED:
  194. case ER_NO_REFERENCED_ROW: {
  195. const match = err.message.match(/CONSTRAINT ([`"])(.*)\1 FOREIGN KEY \(\1(.*)\1\) REFERENCES \1(.*)\1 \(\1(.*)\1\)/);
  196. const quoteChar = match ? match[1] : "`";
  197. const fields = match ? match[3].split(new RegExp(`${quoteChar}, *${quoteChar}`)) : void 0;
  198. return new sequelizeErrors.ForeignKeyConstraintError({
  199. reltype: String(errCode) === String(ER_ROW_IS_REFERENCED) ? "parent" : "child",
  200. table: match ? match[4] : void 0,
  201. fields,
  202. value: fields && fields.length && this.instance && this.instance[fields[0]] || void 0,
  203. index: match ? match[2] : void 0,
  204. parent: err,
  205. stack: errStack
  206. });
  207. }
  208. default:
  209. return new sequelizeErrors.DatabaseError(err, { stack: errStack });
  210. }
  211. }
  212. handleShowIndexesQuery(data) {
  213. data = data.reduce((acc, item) => {
  214. if (!(item.Key_name in acc)) {
  215. acc[item.Key_name] = item;
  216. item.fields = [];
  217. }
  218. acc[item.Key_name].fields[item.Seq_in_index - 1] = {
  219. attribute: item.Column_name,
  220. length: item.Sub_part || void 0,
  221. order: item.Collation === "A" ? "ASC" : void 0
  222. };
  223. delete item.column_name;
  224. return acc;
  225. }, {});
  226. return _.map(data, (item) => ({
  227. primary: item.Key_name === "PRIMARY",
  228. fields: item.fields,
  229. name: item.Key_name,
  230. tableName: item.Table,
  231. unique: item.Non_unique !== 1,
  232. type: item.Index_type
  233. }));
  234. }
  235. }
  236. module.exports = Query;
  237. module.exports.Query = Query;
  238. module.exports.default = Query;
  239. //# sourceMappingURL=query.js.map