query.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. "use strict";
  2. var __defProp = Object.defineProperty;
  3. var __defProps = Object.defineProperties;
  4. var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
  5. var __getOwnPropSymbols = Object.getOwnPropertySymbols;
  6. var __hasOwnProp = Object.prototype.hasOwnProperty;
  7. var __propIsEnum = Object.prototype.propertyIsEnumerable;
  8. var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
  9. var __spreadValues = (a, b) => {
  10. for (var prop in b || (b = {}))
  11. if (__hasOwnProp.call(b, prop))
  12. __defNormalProp(a, prop, b[prop]);
  13. if (__getOwnPropSymbols)
  14. for (var prop of __getOwnPropSymbols(b)) {
  15. if (__propIsEnum.call(b, prop))
  16. __defNormalProp(a, prop, b[prop]);
  17. }
  18. return a;
  19. };
  20. var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
  21. var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
  22. var __export = (target, all) => {
  23. __markAsModule(target);
  24. for (var name in all)
  25. __defProp(target, name, { get: all[name], enumerable: true });
  26. };
  27. __export(exports, {
  28. OracleQuery: () => OracleQuery
  29. });
  30. const AbstractQuery = require("../abstract/query");
  31. const SequelizeErrors = require("../../errors");
  32. const parserStore = require("../parserStore")("oracle");
  33. const _ = require("lodash");
  34. const Utils = require("../../utils");
  35. const { logger } = require("../../utils/logger");
  36. const debug = logger.debugContext("sql:oracle");
  37. class OracleQuery extends AbstractQuery {
  38. constructor(connection, sequelize, options) {
  39. super(connection, sequelize, options);
  40. this.options = _.extend({
  41. logging: console.log,
  42. plain: false,
  43. raw: false
  44. }, options || {});
  45. this.checkLoggingOption();
  46. this.outFormat = options.outFormat || this.sequelize.connectionManager.lib.OBJECT;
  47. }
  48. getInsertIdField() {
  49. return "id";
  50. }
  51. getExecOptions() {
  52. const execOpts = { outFormat: this.outFormat, autoCommit: this.autoCommit };
  53. const oracledb = this.sequelize.connectionManager.lib;
  54. if (this.model && this.isSelectQuery()) {
  55. const fInfo = {};
  56. const keys = Object.keys(this.model.tableAttributes);
  57. for (const key of keys) {
  58. const keyValue = this.model.tableAttributes[key];
  59. if (keyValue.type.key === "DECIMAL") {
  60. fInfo[key] = { type: oracledb.STRING };
  61. }
  62. if (keyValue.type.key === "BIGINT") {
  63. fInfo[key] = { type: oracledb.STRING };
  64. }
  65. }
  66. if (fInfo) {
  67. execOpts.fetchInfo = fInfo;
  68. }
  69. }
  70. return execOpts;
  71. }
  72. _convertBindAttributes(bindingDictionary, oracledb) {
  73. if (this.model && this.options[bindingDictionary]) {
  74. const keys = Object.keys(this.model.tableAttributes);
  75. for (const key of keys) {
  76. const keyValue = this.model.tableAttributes[key];
  77. if (keyValue.type.key === "BIGINT") {
  78. const oldBinding = this.options[bindingDictionary][key];
  79. if (oldBinding) {
  80. this.options[bindingDictionary][key] = __spreadProps(__spreadValues({}, oldBinding), {
  81. type: oracledb.STRING,
  82. maxSize: 1e7
  83. });
  84. }
  85. }
  86. }
  87. }
  88. }
  89. async run(sql, parameters) {
  90. const oracledb = this.sequelize.connectionManager.lib;
  91. const complete = this._logQuery(sql, debug, parameters);
  92. const outParameters = [];
  93. const bindParameters = [];
  94. const bindDef = [];
  95. if (!sql.match(/END;$/)) {
  96. this.sql = sql.replace(/; *$/, "");
  97. } else {
  98. this.sql = sql;
  99. }
  100. if (this.options.outBindAttributes && (Array.isArray(parameters) || _.isPlainObject(parameters))) {
  101. this._convertBindAttributes("outBindAttributes", oracledb);
  102. outParameters.push(...Object.values(this.options.outBindAttributes));
  103. if (this.isUpsertQuery()) {
  104. outParameters.push({ dir: oracledb.BIND_OUT });
  105. }
  106. }
  107. this.bindParameters = outParameters;
  108. if (Array.isArray(parameters) || _.isPlainObject(parameters)) {
  109. if (this.options.executeMany) {
  110. this._convertBindAttributes("inbindAttributes", oracledb);
  111. bindDef.push(...Object.values(this.options.inbindAttributes));
  112. bindDef.push(...outParameters);
  113. this.bindParameters = parameters;
  114. } else if (this.isRawQuery()) {
  115. this.bindParameters = parameters;
  116. } else {
  117. Object.values(parameters).forEach((value) => {
  118. bindParameters.push(value);
  119. });
  120. bindParameters.push(...outParameters);
  121. Object.assign(this.bindParameters, bindParameters);
  122. }
  123. }
  124. if (this.sql.startsWith("BEGIN TRANSACTION")) {
  125. this.autocommit = false;
  126. return Promise.resolve();
  127. }
  128. if (this.sql.startsWith("SET AUTOCOMMIT ON")) {
  129. this.autocommit = true;
  130. return Promise.resolve();
  131. }
  132. if (this.sql.startsWith("SET AUTOCOMMIT OFF")) {
  133. this.autocommit = false;
  134. return Promise.resolve();
  135. }
  136. if (this.sql.startsWith("DECLARE x NUMBER")) {
  137. if (this.autoCommit === void 0) {
  138. if (this.connection.uuid) {
  139. this.autoCommit = false;
  140. } else {
  141. this.autoCommit = true;
  142. }
  143. }
  144. try {
  145. await this.connection.execute(this.sql, this.bindParameters, { autoCommit: this.autoCommit });
  146. return Object.create(null);
  147. } catch (error) {
  148. throw this.formatError(error);
  149. } finally {
  150. complete();
  151. }
  152. }
  153. if (this.sql.startsWith("BEGIN")) {
  154. if (this.autoCommit === void 0) {
  155. if (this.connection.uuid) {
  156. this.autoCommit = false;
  157. } else {
  158. this.autoCommit = true;
  159. }
  160. }
  161. try {
  162. const result = await this.connection.execute(this.sql, this.bindParameters, {
  163. outFormat: this.outFormat,
  164. autoCommit: this.autoCommit
  165. });
  166. if (!Array.isArray(result.outBinds)) {
  167. return [result.outBinds];
  168. }
  169. return result.outBinds;
  170. } catch (error) {
  171. throw this.formatError(error);
  172. } finally {
  173. complete();
  174. }
  175. }
  176. if (this.sql.startsWith("COMMIT TRANSACTION")) {
  177. try {
  178. await this.connection.commit();
  179. return Object.create(null);
  180. } catch (error) {
  181. throw this.formatError(error);
  182. } finally {
  183. complete();
  184. }
  185. }
  186. if (this.sql.startsWith("ROLLBACK TRANSACTION")) {
  187. try {
  188. await this.connection.rollback();
  189. return Object.create(null);
  190. } catch (error) {
  191. throw this.formatError(error);
  192. } finally {
  193. complete();
  194. }
  195. }
  196. if (this.sql.startsWith("SET TRANSACTION")) {
  197. try {
  198. await this.connection.execute(this.sql, [], { autoCommit: false });
  199. return Object.create(null);
  200. } catch (error) {
  201. throw this.formatError(error);
  202. } finally {
  203. complete();
  204. }
  205. }
  206. if (this.autoCommit === void 0) {
  207. if (this.connection.uuid) {
  208. this.autoCommit = false;
  209. } else {
  210. this.autoCommit = true;
  211. }
  212. }
  213. if ("inputParameters" in this.options && this.options.inputParameters !== null) {
  214. Object.assign(this.bindParameters, this.options.inputParameters);
  215. }
  216. const execOpts = this.getExecOptions();
  217. if (this.options.executeMany && bindDef.length > 0) {
  218. execOpts.bindDefs = bindDef;
  219. }
  220. const executePromise = this.options.executeMany ? this.connection.executeMany(this.sql, this.bindParameters, execOpts) : this.connection.execute(this.sql, this.bindParameters, execOpts);
  221. try {
  222. const result = await executePromise;
  223. return this.formatResults(result);
  224. } catch (error) {
  225. throw this.formatError(error);
  226. } finally {
  227. complete();
  228. }
  229. }
  230. static formatBindParameters(sql, values, dialect) {
  231. const replacementFunc = (match, key, values2) => {
  232. if (values2[key] !== void 0) {
  233. return `:${key}`;
  234. }
  235. return void 0;
  236. };
  237. sql = AbstractQuery.formatBindParameters(sql, values, dialect, replacementFunc)[0];
  238. return [sql, values];
  239. }
  240. _getAttributeMap(attrsMap, rawAttributes) {
  241. attrsMap = Object.assign(attrsMap, _.reduce(rawAttributes, (mp, _2, key) => {
  242. const catalogKey = this.sequelize.queryInterface.queryGenerator.getCatalogName(key);
  243. mp[catalogKey] = key;
  244. return mp;
  245. }, {}));
  246. }
  247. _processRows(rows) {
  248. let result = rows;
  249. let attrsMap = {};
  250. if (this.sequelize.options.quoteIdentifiers === false) {
  251. attrsMap = _.reduce(this.options.attributes, (mp, v) => {
  252. if (typeof v === "object") {
  253. v = v[1];
  254. }
  255. const catalogv = this.sequelize.queryInterface.queryGenerator.getCatalogName(v);
  256. mp[catalogv] = v;
  257. return mp;
  258. }, {});
  259. if (this.model) {
  260. this._getAttributeMap(attrsMap, this.model.rawAttributes);
  261. }
  262. if (this.options.aliasesMapping) {
  263. const obj = Object.fromEntries(this.options.aliasesMapping);
  264. rows = rows.map((row) => _.toPairs(row).reduce((acc, [key, value]) => {
  265. const mapping = Object.values(obj).find((element) => {
  266. const catalogElement = this.sequelize.queryInterface.queryGenerator.getCatalogName(element);
  267. return catalogElement === key;
  268. });
  269. if (mapping)
  270. acc[mapping || key] = value;
  271. return acc;
  272. }, {}));
  273. }
  274. result = rows.map((row) => {
  275. return _.mapKeys(row, (value, key) => {
  276. const targetAttr = attrsMap[key];
  277. if (typeof targetAttr === "string" && targetAttr !== key) {
  278. return targetAttr;
  279. }
  280. return key;
  281. });
  282. });
  283. }
  284. if (this.model) {
  285. result = result.map((row) => {
  286. return _.mapValues(row, (value, key) => {
  287. if (this.model.rawAttributes[key] && this.model.rawAttributes[key].type) {
  288. let typeid = this.model.rawAttributes[key].type.toLocaleString();
  289. if (this.model.rawAttributes[key].type.key === "JSON") {
  290. value = JSON.parse(value);
  291. }
  292. if (typeid.indexOf("(") > -1 && this.model.rawAttributes[key].type.key !== "BOOLEAN") {
  293. typeid = typeid.substr(0, typeid.indexOf("("));
  294. }
  295. const parse = parserStore.get(typeid);
  296. if (value !== null & !!parse) {
  297. value = parse(value);
  298. }
  299. }
  300. return value;
  301. });
  302. });
  303. }
  304. return result;
  305. }
  306. formatResults(data) {
  307. let result = this.instance;
  308. if (this.isInsertQuery(data)) {
  309. let insertData;
  310. if (data.outBinds) {
  311. const keys = Object.keys(this.options.outBindAttributes);
  312. insertData = data.outBinds;
  313. if (this.instance) {
  314. insertData = [insertData];
  315. }
  316. const res = insertData.map((row) => {
  317. const obj = {};
  318. row.forEach((element, index) => {
  319. obj[keys[index]] = element[0];
  320. });
  321. return obj;
  322. });
  323. insertData = res;
  324. if (!this.instance) {
  325. result = res;
  326. }
  327. }
  328. this.handleInsertQuery(insertData);
  329. return [result, data.rowsAffected];
  330. }
  331. if (this.isShowTablesQuery()) {
  332. result = this.handleShowTablesQuery(data.rows);
  333. } else if (this.isDescribeQuery()) {
  334. result = {};
  335. const table = Object.keys(this.sequelize.models);
  336. const modelAttributes = {};
  337. if (this.sequelize.models && table.length > 0) {
  338. this._getAttributeMap(modelAttributes, this.sequelize.models[table[0]].rawAttributes);
  339. }
  340. data.rows.forEach((_result) => {
  341. if (_result.Default) {
  342. _result.Default = _result.Default.replace("('", "").replace("')", "").replace(/'/g, "");
  343. }
  344. if (!(modelAttributes[_result.COLUMN_NAME] in result)) {
  345. let key = modelAttributes[_result.COLUMN_NAME];
  346. if (!key) {
  347. key = _result.COLUMN_NAME;
  348. }
  349. result[key] = {
  350. type: _result.DATA_TYPE.toUpperCase(),
  351. allowNull: _result.NULLABLE === "N" ? false : true,
  352. defaultValue: void 0,
  353. primaryKey: _result.CONSTRAINT_TYPE === "P"
  354. };
  355. }
  356. });
  357. } else if (this.isShowIndexesQuery()) {
  358. result = this.handleShowIndexesQuery(data.rows);
  359. } else if (this.isSelectQuery()) {
  360. const rows = data.rows;
  361. const result2 = this._processRows(rows);
  362. return this.handleSelectQuery(result2);
  363. } else if (this.isCallQuery()) {
  364. result = data.rows[0];
  365. } else if (this.isUpdateQuery()) {
  366. result = [result, data.rowsAffected];
  367. } else if (this.isBulkUpdateQuery()) {
  368. result = data.rowsAffected;
  369. } else if (this.isBulkDeleteQuery()) {
  370. result = data.rowsAffected;
  371. } else if (this.isVersionQuery()) {
  372. const version = data.rows[0].VERSION_FULL;
  373. if (version) {
  374. const versions = version.split(".");
  375. result = `${versions[0]}.${versions[1]}.${versions[2]}`;
  376. } else {
  377. result = "0.0.0";
  378. }
  379. } else if (this.isForeignKeysQuery()) {
  380. result = data.rows;
  381. } else if (this.isUpsertQuery()) {
  382. data = data.outBinds;
  383. const keys = Object.keys(this.options.outBindAttributes);
  384. const obj = {};
  385. for (const k in keys) {
  386. obj[keys[k]] = data[k];
  387. }
  388. obj.isUpdate = data[data.length - 1];
  389. data = obj;
  390. result = [{ isNewRecord: data.isUpdate, value: data }, data.isUpdate == 0];
  391. } else if (this.isShowConstraintsQuery()) {
  392. result = this.handleShowConstraintsQuery(data);
  393. } else if (this.isRawQuery()) {
  394. if (data && data.rows) {
  395. return [data.rows, data.metaData];
  396. }
  397. return [data, data];
  398. }
  399. return result;
  400. }
  401. handleShowConstraintsQuery(data) {
  402. return data.rows.map((result) => {
  403. const constraint = {};
  404. for (const key in result) {
  405. constraint[_.camelCase(key)] = result[key].toLowerCase();
  406. }
  407. return constraint;
  408. });
  409. }
  410. handleShowTablesQuery(results) {
  411. return results.map((resultSet) => {
  412. return {
  413. tableName: resultSet.TABLE_NAME,
  414. schema: resultSet.TABLE_SCHEMA
  415. };
  416. });
  417. }
  418. formatError(err) {
  419. let match;
  420. match = err.message.match(/unique constraint ([\s\S]*) violated/);
  421. if (match && match.length > 1) {
  422. match[1] = match[1].replace("(", "").replace(")", "").split(".")[1];
  423. const errors = [];
  424. let fields = [], message = "Validation error", uniqueKey = null;
  425. if (this.model) {
  426. const uniqueKeys = Object.keys(this.model.uniqueKeys);
  427. const currKey = uniqueKeys.find((key) => {
  428. return key.toUpperCase() === match[1].toUpperCase() || key.toUpperCase() === `"${match[1].toUpperCase()}"`;
  429. });
  430. if (currKey) {
  431. uniqueKey = this.model.uniqueKeys[currKey];
  432. fields = uniqueKey.fields;
  433. }
  434. if (uniqueKey && !!uniqueKey.msg) {
  435. message = uniqueKey.msg;
  436. }
  437. fields.forEach((field) => {
  438. errors.push(new SequelizeErrors.ValidationErrorItem(this.getUniqueConstraintErrorMessage(field), "unique violation", field, null));
  439. });
  440. }
  441. return new SequelizeErrors.UniqueConstraintError({
  442. message,
  443. errors,
  444. err,
  445. fields
  446. });
  447. }
  448. match = err.message.match(/ORA-02291/) || err.message.match(/ORA-02292/);
  449. if (match && match.length > 0) {
  450. return new SequelizeErrors.ForeignKeyConstraintError({
  451. fields: null,
  452. index: match[1],
  453. parent: err
  454. });
  455. }
  456. match = err.message.match(/ORA-02443/);
  457. if (match && match.length > 0) {
  458. return new SequelizeErrors.UnknownConstraintError(match[1]);
  459. }
  460. return new SequelizeErrors.DatabaseError(err);
  461. }
  462. isShowIndexesQuery() {
  463. return this.sql.indexOf("SELECT i.index_name,i.table_name, i.column_name, u.uniqueness") > -1;
  464. }
  465. isSelectCountQuery() {
  466. return this.sql.toUpperCase().indexOf("SELECT COUNT(") > -1;
  467. }
  468. handleShowIndexesQuery(data) {
  469. const acc = [];
  470. data.forEach((indexRecord) => {
  471. if (!acc[indexRecord.INDEX_NAME]) {
  472. acc[indexRecord.INDEX_NAME] = {
  473. unique: indexRecord.UNIQUENESS === "UNIQUE" ? true : false,
  474. primary: indexRecord.CONSTRAINT_TYPE === "P",
  475. name: indexRecord.INDEX_NAME.toLowerCase(),
  476. tableName: indexRecord.TABLE_NAME.toLowerCase(),
  477. type: void 0
  478. };
  479. acc[indexRecord.INDEX_NAME].fields = [];
  480. }
  481. acc[indexRecord.INDEX_NAME].fields.push({
  482. attribute: indexRecord.COLUMN_NAME,
  483. length: void 0,
  484. order: indexRecord.DESCEND,
  485. collate: void 0
  486. });
  487. });
  488. const returnIndexes = [];
  489. const accKeys = Object.keys(acc);
  490. for (const accKey of accKeys) {
  491. const columns = {};
  492. columns.fields = acc[accKey].fields;
  493. if (acc[accKey].name.match(/sys_c[0-9]*/)) {
  494. acc[accKey].name = Utils.nameIndex(columns, acc[accKey].tableName).name;
  495. }
  496. returnIndexes.push(acc[accKey]);
  497. }
  498. return returnIndexes;
  499. }
  500. handleInsertQuery(results, metaData) {
  501. if (this.instance && results.length > 0) {
  502. if ("pkReturnVal" in results[0]) {
  503. results[0][this.model.primaryKeyAttribute] = results[0].pkReturnVal;
  504. delete results[0].pkReturnVal;
  505. }
  506. const autoIncrementField = this.model.autoIncrementAttribute;
  507. let autoIncrementFieldAlias = null, id = null;
  508. if (Object.prototype.hasOwnProperty.call(this.model.rawAttributes, autoIncrementField) && this.model.rawAttributes[autoIncrementField].field !== void 0)
  509. autoIncrementFieldAlias = this.model.rawAttributes[autoIncrementField].field;
  510. id = id || results && results[0][this.getInsertIdField()];
  511. id = id || metaData && metaData[this.getInsertIdField()];
  512. id = id || results && results[0][autoIncrementField];
  513. id = id || autoIncrementFieldAlias && results && results[0][autoIncrementFieldAlias];
  514. this.instance[autoIncrementField] = id;
  515. }
  516. }
  517. }
  518. //# sourceMappingURL=query.js.map