"use strict"; var __defProp = Object.defineProperty; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __markAsModule = (target) => __defProp(target, "__esModule", { value: true }); var __export = (target, all) => { __markAsModule(target); for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; __export(exports, { OracleQueryGenerator: () => OracleQueryGenerator }); const Utils = require("../../utils"); const DataTypes = require("../../data-types"); const AbstractQueryGenerator = require("../abstract/query-generator"); const _ = require("lodash"); const util = require("util"); const Transaction = require("../../transaction"); const ORACLE_RESERVED_WORDS = ["ACCESS", "ADD", "ALL", "ALTER", "AND", "ANY", "ARRAYLEN", "AS", "ASC", "AUDIT", "BETWEEN", "BY", "CHAR", "CHECK", "CLUSTER", "COLUMN", "COMMENT", "COMPRESS", "CONNECT", "CREATE", "CURRENT", "DATE", "DECIMAL", "DEFAULT", "DELETE", "DESC", "DISTINCT", "DROP", "ELSE", "EXCLUSIVE", "EXISTS", "FILE", "FLOAT", "FOR", "FROM", "GRANT", "GROUP", "HAVING", "IDENTIFIED", "IMMEDIATE", "IN", "INCREMENT", "INDEX", "INITIAL", "INSERT", "INTEGER", "INTERSECT", "INTO", "IS", "LEVEL", "LIKE", "LOCK", "LONG", "MAXEXTENTS", "MINUS", "MODE", "MODIFY", "NOAUDIT", "NOCOMPRESS", "NOT", "NOTFOUND", "NOWAIT", "NULL", "NUMBER", "OF", "OFFLINE", "ON", "ONLINE", "OPTION", "OR", "ORDER", "PCTFREE", "PRIOR", "PRIVILEGES", "PUBLIC", "RAW", "RENAME", "RESOURCE", "REVOKE", "ROW", "ROWID", "ROWLABEL", "ROWNUM", "ROWS", "SELECT", "SESSION", "SET", "SHARE", "SIZE", "SMALLINT", "SQLBUF", "START", "SUCCESSFUL", "SYNONYM", "SYSDATE", "TABLE", "THEN", "TO", "TRIGGER", "UID", "UNION", "UNIQUE", "UPDATE", "USER", "VALIDATE", "VALUES", "VARCHAR", "VARCHAR2", "VIEW", "WHENEVER", "WHERE", "WITH"]; const JSON_FUNCTION_REGEX = /^\s*((?:[a-z]+_){0,2}jsonb?(?:_[a-z]+){0,2})\([^)]*\)/i; const JSON_OPERATOR_REGEX = /^\s*(->>?|@>|<@|\?[|&]?|\|{2}|#-)/i; const TOKEN_CAPTURE_REGEX = /^\s*((?:([`"'])(?:(?!\2).|\2{2})*\2)|[\w\d\s]+|[().,;+-])/i; class OracleQueryGenerator extends AbstractQueryGenerator { constructor(options) { super(options); } getCatalogName(value) { if (value) { if (this.options.quoteIdentifiers === false) { const quotedValue = this.quoteIdentifier(value); if (quotedValue === value) { value = value.toUpperCase(); } } } return value; } getSchemaNameAndTableName(table) { const tableName = this.getCatalogName(table.tableName || table); const schemaName = this.getCatalogName(table.schema); return [tableName, schemaName]; } createSchema(schema) { const quotedSchema = this.quoteIdentifier(schema); return [ "DECLARE", "USER_FOUND BOOLEAN := FALSE;", "BEGIN", " BEGIN", " EXECUTE IMMEDIATE ", this.escape(`CREATE USER ${quotedSchema} IDENTIFIED BY 12345 DEFAULT TABLESPACE USERS`), ";", " EXCEPTION WHEN OTHERS THEN", " IF SQLCODE != -1920 THEN", " RAISE;", " ELSE", " USER_FOUND := TRUE;", " END IF;", " END;", " IF NOT USER_FOUND THEN", " EXECUTE IMMEDIATE ", this.escape(`GRANT "CONNECT" TO ${quotedSchema}`), ";", " EXECUTE IMMEDIATE ", this.escape(`GRANT CREATE TABLE TO ${quotedSchema}`), ";", " EXECUTE IMMEDIATE ", this.escape(`GRANT CREATE VIEW TO ${quotedSchema}`), ";", " EXECUTE IMMEDIATE ", this.escape(`GRANT CREATE ANY TRIGGER TO ${quotedSchema}`), ";", " EXECUTE IMMEDIATE ", this.escape(`GRANT CREATE ANY PROCEDURE TO ${quotedSchema}`), ";", " EXECUTE IMMEDIATE ", this.escape(`GRANT CREATE SEQUENCE TO ${quotedSchema}`), ";", " EXECUTE IMMEDIATE ", this.escape(`GRANT CREATE SYNONYM TO ${quotedSchema}`), ";", " EXECUTE IMMEDIATE ", this.escape(`ALTER USER ${quotedSchema} QUOTA UNLIMITED ON USERS`), ";", " END IF;", "END;" ].join(" "); } showSchemasQuery() { return `SELECT USERNAME AS "schema_name" FROM ALL_USERS WHERE COMMON = ('NO') AND USERNAME != user`; } dropSchema(schema) { return [ "BEGIN", "EXECUTE IMMEDIATE ", this.escape(`DROP USER ${this.quoteTable(schema)} CASCADE`), ";", "EXCEPTION WHEN OTHERS THEN", " IF SQLCODE != -1918 THEN", " RAISE;", " END IF;", "END;" ].join(" "); } versionQuery() { return "SELECT VERSION_FULL FROM PRODUCT_COMPONENT_VERSION WHERE PRODUCT LIKE 'Oracle%'"; } createTableQuery(tableName, attributes, options) { const primaryKeys = [], foreignKeys = Object.create(null), attrStr = [], checkStr = []; const values = { table: this.quoteTable(tableName) }; for (let attr in attributes) { if (!Object.prototype.hasOwnProperty.call(attributes, attr)) continue; const dataType = attributes[attr]; attr = this.quoteIdentifier(attr); if (dataType.includes("PRIMARY KEY")) { primaryKeys.push(attr); if (dataType.includes("REFERENCES")) { const match = dataType.match(/^(.+) (REFERENCES.*)$/); attrStr.push(`${attr} ${match[1].replace(/PRIMARY KEY/, "")}`); foreignKeys[attr] = match[2]; } else { attrStr.push(`${attr} ${dataType.replace(/PRIMARY KEY/, "").trim()}`); } } else if (dataType.includes("REFERENCES")) { const match = dataType.match(/^(.+) (REFERENCES.*)$/); attrStr.push(`${attr} ${match[1]}`); foreignKeys[attr] = match[2]; } else { attrStr.push(`${attr} ${dataType}`); } } values["attributes"] = attrStr.join(", "); const pkString = primaryKeys.map((pk) => this.quoteIdentifier(pk)).join(", "); if (pkString.length > 0) { values.attributes += `,PRIMARY KEY (${pkString})`; } for (const fkey in foreignKeys) { if (!Object.prototype.hasOwnProperty.call(foreignKeys, fkey)) continue; if (foreignKeys[fkey].indexOf("ON DELETE NO ACTION") > -1) { foreignKeys[fkey] = foreignKeys[fkey].replace("ON DELETE NO ACTION", ""); } values.attributes += `,FOREIGN KEY (${this.quoteIdentifier(fkey)}) ${foreignKeys[fkey]}`; } if (checkStr.length > 0) { values.attributes += `, ${checkStr.join(", ")}`; } if (options && options.indexes && options.indexes.length > 0) { const idxToDelete = []; options.indexes.forEach((index, idx) => { if ("unique" in index && (index.unique === true || index.unique.length > 0 && index.unique !== false)) { const fields = index.fields.map((field) => { if (typeof field === "string") { return field; } return field.attribute; }); let canContinue = true; if (options.uniqueKeys) { const keys = Object.keys(options.uniqueKeys); for (let fieldIdx = 0; fieldIdx < keys.length; fieldIdx++) { const currUnique = options.uniqueKeys[keys[fieldIdx]]; if (currUnique.fields.length === fields.length) { for (let i = 0; i < currUnique.fields.length; i++) { const field = currUnique.fields[i]; if (_.includes(fields, field)) { canContinue = false; } else { canContinue = true; break; } } } } if (canContinue) { const indexName = "name" in index ? index.name : ""; const constraintToAdd = { name: indexName, fields }; if (!("uniqueKeys" in options)) { options.uniqueKeys = {}; } options.uniqueKeys[indexName] = constraintToAdd; idxToDelete.push(idx); } else { idxToDelete.push(idx); } } } }); idxToDelete.forEach((idx) => { options.indexes.splice(idx, 1); }); } if (options && !!options.uniqueKeys) { _.each(options.uniqueKeys, (columns, indexName) => { let canBeUniq = false; primaryKeys.forEach((primaryKey) => { primaryKey = primaryKey.replace(/"/g, ""); if (!_.includes(columns.fields, primaryKey)) { canBeUniq = true; } }); columns.fields.forEach((field) => { let currField = ""; if (!_.isString(field)) { currField = field.attribute.replace(/[.,"\s]/g, ""); } else { currField = field.replace(/[.,"\s]/g, ""); } if (currField in attributes) { if (attributes[currField].toUpperCase().indexOf("UNIQUE") > -1 && canBeUniq) { const attrToReplace = attributes[currField].replace("UNIQUE", ""); values.attributes = values.attributes.replace(attributes[currField], attrToReplace); } } }); if (canBeUniq) { const index = options.uniqueKeys[columns.name]; delete options.uniqueKeys[columns.name]; indexName = indexName.replace(/[.,\s]/g, ""); columns.name = indexName; options.uniqueKeys[indexName] = index; if (indexName.length === 0) { values.attributes += `,UNIQUE (${columns.fields.map((field) => this.quoteIdentifier(field)).join(", ")})`; } else { values.attributes += `, CONSTRAINT ${this.quoteIdentifier(indexName)} UNIQUE (${columns.fields.map((field) => this.quoteIdentifier(field)).join(", ")})`; } } }); } const query = Utils.joinSQLFragments([ "CREATE TABLE", values.table, `(${values.attributes})` ]); return Utils.joinSQLFragments([ "BEGIN", "EXECUTE IMMEDIATE", `${this.escape(query)};`, "EXCEPTION WHEN OTHERS THEN", "IF SQLCODE != -955 THEN", "RAISE;", "END IF;", "END;" ]); } tableExistsQuery(table) { const [tableName, schemaName] = this.getSchemaNameAndTableName(table); return `SELECT TABLE_NAME FROM ALL_TABLES WHERE TABLE_NAME = ${this.escape(tableName)} AND OWNER = ${table.schema ? this.escape(schemaName) : "USER"}`; } describeTableQuery(tableName, schema) { const currTableName = this.getCatalogName(tableName.tableName || tableName); schema = this.getCatalogName(schema); return [ "SELECT atc.COLUMN_NAME, atc.DATA_TYPE, atc.DATA_LENGTH, atc.CHAR_LENGTH, atc.DEFAULT_LENGTH, atc.NULLABLE, ucc.constraint_type ", "FROM all_tab_columns atc ", "LEFT OUTER JOIN ", "(SELECT acc.column_name, acc.table_name, ac.constraint_type FROM all_cons_columns acc INNER JOIN all_constraints ac ON acc.constraint_name = ac.constraint_name) ucc ", "ON (atc.table_name = ucc.table_name AND atc.COLUMN_NAME = ucc.COLUMN_NAME) ", schema ? `WHERE (atc.OWNER = ${this.escape(schema)}) ` : "WHERE atc.OWNER = USER ", `AND (atc.TABLE_NAME = ${this.escape(currTableName)})`, "ORDER BY atc.COLUMN_NAME, CONSTRAINT_TYPE DESC" ].join(""); } renameTableQuery(before, after) { return Utils.joinSQLFragments([ "ALTER TABLE", this.quoteTable(before), "RENAME TO", this.quoteTable(after) ]); } showConstraintsQuery(table) { const tableName = this.getCatalogName(table.tableName || table); return `SELECT CONSTRAINT_NAME constraint_name FROM user_cons_columns WHERE table_name = ${this.escape(tableName)}`; } showTablesQuery() { return `SELECT owner as table_schema, table_name, 0 as lvl FROM all_tables where OWNER IN(SELECT USERNAME AS "schema_name" FROM ALL_USERS WHERE ORACLE_MAINTAINED = 'N')`; } dropTableQuery(tableName) { return Utils.joinSQLFragments([ "BEGIN ", "EXECUTE IMMEDIATE 'DROP TABLE", this.quoteTable(tableName), "CASCADE CONSTRAINTS PURGE';", "EXCEPTION WHEN OTHERS THEN", " IF SQLCODE != -942 THEN", " RAISE;", " END IF;", "END;" ]); } addIndexQuery(tableName, attributes, options, rawTablename) { if (typeof tableName !== "string" && attributes.name) { attributes.name = `${tableName.schema}.${attributes.name}`; } return super.addIndexQuery(tableName, attributes, options, rawTablename); } addConstraintQuery(tableName, options) { options = options || {}; if (options.onUpdate) { delete options.onUpdate; } if (options.onDelete && options.onDelete.toUpperCase() === "NO ACTION") { delete options.onDelete; } const constraintSnippet = this.getConstraintSnippet(tableName, options); tableName = this.quoteTable(tableName); return `ALTER TABLE ${tableName} ADD ${constraintSnippet};`; } addColumnQuery(table, key, dataType) { dataType.field = key; const attribute = Utils.joinSQLFragments([ this.quoteIdentifier(key), this.attributeToSQL(dataType, { attributeName: key, context: "addColumn" }) ]); return Utils.joinSQLFragments([ "ALTER TABLE", this.quoteTable(table), "ADD", attribute ]); } removeColumnQuery(tableName, attributeName) { return Utils.joinSQLFragments([ "ALTER TABLE", this.quoteTable(tableName), "DROP COLUMN", this.quoteIdentifier(attributeName), ";" ]); } _alterForeignKeyConstraint(definition, table, attributeName) { const [tableName, schemaName] = this.getSchemaNameAndTableName(table); const attributeNameConstant = this.escape(this.getCatalogName(attributeName)); const schemaNameConstant = table.schema ? this.escape(this.getCatalogName(schemaName)) : "USER"; const tableNameConstant = this.escape(this.getCatalogName(tableName)); const getConsNameQuery = [ "SELECT constraint_name INTO cons_name", "FROM (", " SELECT DISTINCT cc.owner, cc.table_name, cc.constraint_name, cc.column_name AS cons_columns", " FROM all_cons_columns cc, all_constraints c", " WHERE cc.owner = c.owner", " AND cc.table_name = c.table_name", " AND cc.constraint_name = c.constraint_name", " AND c.constraint_type = 'R'", " GROUP BY cc.owner, cc.table_name, cc.constraint_name, cc.column_name", ")", "WHERE owner =", schemaNameConstant, "AND table_name =", tableNameConstant, "AND cons_columns =", attributeNameConstant, ";" ].join(" "); const secondQuery = Utils.joinSQLFragments([ `ALTER TABLE ${this.quoteIdentifier(tableName)}`, "ADD FOREIGN KEY", `(${this.quoteIdentifier(attributeName)})`, definition.replace(/.+?(?=REFERENCES)/, "") ]); return [ "BEGIN", getConsNameQuery, "EXCEPTION", "WHEN NO_DATA_FOUND THEN", " CONS_NAME := NULL;", "END;", "IF CONS_NAME IS NOT NULL THEN", ` EXECUTE IMMEDIATE 'ALTER TABLE ${this.quoteTable(table)} DROP CONSTRAINT "'||CONS_NAME||'"';`, "END IF;", `EXECUTE IMMEDIATE ${this.escape(secondQuery)};` ].join(" "); } _modifyQuery(definition, table, attributeName) { const query = Utils.joinSQLFragments([ "ALTER TABLE", this.quoteTable(table), "MODIFY", this.quoteIdentifier(attributeName), definition ]); const secondQuery = query.replace("NOT NULL", "").replace("NULL", ""); return [ "BEGIN", `EXECUTE IMMEDIATE ${this.escape(query)};`, "EXCEPTION", "WHEN OTHERS THEN", " IF SQLCODE = -1442 OR SQLCODE = -1451 THEN", ` EXECUTE IMMEDIATE ${this.escape(secondQuery)};`, " ELSE", " RAISE;", " END IF;", "END;" ].join(" "); } changeColumnQuery(table, attributes) { const sql = [ "DECLARE", "CONS_NAME VARCHAR2(200);", "BEGIN" ]; for (const attributeName in attributes) { if (!Object.prototype.hasOwnProperty.call(attributes, attributeName)) continue; const definition = attributes[attributeName]; if (definition.match(/REFERENCES/)) { sql.push(this._alterForeignKeyConstraint(definition, table, attributeName)); } else { sql.push(this._modifyQuery(definition, table, attributeName)); } } sql.push("END;"); return sql.join(" "); } renameColumnQuery(tableName, attrBefore, attributes) { const newName = Object.keys(attributes)[0]; return `ALTER TABLE ${this.quoteTable(tableName)} RENAME COLUMN ${this.quoteIdentifier(attrBefore)} TO ${this.quoteIdentifier(newName)}`; } populateInsertQueryReturnIntoBinds(returningModelAttributes, returnTypes, inbindLength, returnAttributes, options) { const oracledb = this.sequelize.connectionManager.lib; const outBindAttributes = Object.create(null); const outbind = []; const outbindParam = this.bindParam(outbind, inbindLength); returningModelAttributes.forEach((element, index) => { if (element.startsWith('"')) { element = element.substring(1, element.length - 1); } outBindAttributes[element] = Object.assign(returnTypes[index]._getBindDef(oracledb), { dir: oracledb.BIND_OUT }); const returnAttribute = `${this.format(void 0, void 0, { context: "INSERT" }, outbindParam)}`; returnAttributes.push(returnAttribute); }); options.outBindAttributes = outBindAttributes; } upsertQuery(tableName, insertValues, updateValues, where, model, options) { const rawAttributes = model.rawAttributes; const updateQuery = this.updateQuery(tableName, updateValues, where, options, rawAttributes); options.bind = updateQuery.bind; const insertQuery = this.insertQuery(tableName, insertValues, rawAttributes, options); const sql = [ "DECLARE ", "BEGIN ", updateQuery.query ? [ updateQuery.query, "; ", " IF ( SQL%ROWCOUNT = 0 ) THEN ", insertQuery.query, " :isUpdate := 0; ", "ELSE ", " :isUpdate := 1; ", " END IF; " ].join("") : [ insertQuery.query, " :isUpdate := 0; ", "EXCEPTION WHEN OTHERS THEN", " IF SQLCODE != -1 THEN", " RAISE;", " END IF;" ].join(""), "END;" ]; const query = sql.join(""); const result = { query }; if (options.bindParam !== false) { result.bind = updateQuery.bind || insertQuery.bind; } return result; } bulkInsertQuery(tableName, fieldValueHashes, options, fieldMappedAttributes) { options = options || {}; options.executeMany = true; fieldMappedAttributes = fieldMappedAttributes || {}; const tuples = []; const allColumns = {}; const inBindBindDefMap = {}; const outBindBindDefMap = {}; const oracledb = this.sequelize.connectionManager.lib; for (const fieldValueHash of fieldValueHashes) { _.forOwn(fieldValueHash, (value, key) => { allColumns[key] = fieldMappedAttributes[key] && fieldMappedAttributes[key].autoIncrement === true && value === null; }); } let inBindPosition; for (const fieldValueHash of fieldValueHashes) { const tuple = []; const inbindParam = options.bindParam === void 0 ? this.bindParam(tuple) : options.bindParam; const tempBindPositions = Object.keys(allColumns).map((key) => { if (allColumns[key] === true) { if (fieldValueHash[key] !== null) { throw Error("For an auto-increment column either all row must be null or non-null, a mix of null and non-null is not allowed!"); } return "DEFAULT"; } return this.format(fieldValueHash[key], fieldMappedAttributes[key], { context: "INSERT" }, inbindParam); }); if (!inBindPosition) { inBindPosition = tempBindPositions; } tuples.push(tuple); } const returnColumn = []; const returnColumnBindPositions = []; const insertColumns = []; for (const key of Object.keys(allColumns)) { if (fieldMappedAttributes[key]) { const bindDef = fieldMappedAttributes[key].type._getBindDef(oracledb); if (allColumns[key]) { bindDef.dir = oracledb.BIND_OUT; outBindBindDefMap[key] = bindDef; returnColumn.push(this.quoteIdentifier(key)); returnColumnBindPositions.push(`:${tuples[0].length + returnColumn.length}`); } else { bindDef.dir = oracledb.BIND_IN; inBindBindDefMap[key] = bindDef; } } insertColumns.push(this.quoteIdentifier(key)); } let query = Utils.joinSQLFragments([ "INSERT", "INTO", this.quoteTable(tableName), `(${insertColumns.join(",")})`, "VALUES", `(${inBindPosition})` ]); if (returnColumn.length > 0) { options.outBindAttributes = outBindBindDefMap; query = Utils.joinSQLFragments([ query, "RETURNING", `${returnColumn.join(",")}`, "INTO", `${returnColumnBindPositions}` ]); } const result = { query }; result.bind = tuples; options.inbindAttributes = inBindBindDefMap; return result; } truncateTableQuery(tableName) { return `TRUNCATE TABLE ${this.quoteTable(tableName)}`; } deleteQuery(tableName, where, options, model) { options = options || {}; const table = tableName; where = this.getWhereConditions(where, null, model, options); let queryTmpl; if (options.limit) { const whereTmpl = where ? ` AND ${where}` : ""; queryTmpl = `DELETE FROM ${this.quoteTable(table)} WHERE rowid IN (SELECT rowid FROM ${this.quoteTable(table)} WHERE rownum <= ${this.escape(options.limit)}${whereTmpl})`; } else { const whereTmpl = where ? ` WHERE ${where}` : ""; queryTmpl = `DELETE FROM ${this.quoteTable(table)}${whereTmpl}`; } return queryTmpl; } showIndexesQuery(table) { const [tableName, owner] = this.getSchemaNameAndTableName(table); const sql = [ "SELECT i.index_name,i.table_name, i.column_name, u.uniqueness, i.descend, c.constraint_type ", "FROM all_ind_columns i ", "INNER JOIN all_indexes u ", "ON (u.table_name = i.table_name AND u.index_name = i.index_name) ", "LEFT OUTER JOIN all_constraints c ", "ON (c.table_name = i.table_name AND c.index_name = i.index_name) ", `WHERE i.table_name = ${this.escape(tableName)}`, " AND u.table_owner = ", owner ? this.escape(owner) : "USER", " ORDER BY index_name, column_position" ]; return sql.join(""); } removeIndexQuery(tableName, indexNameOrAttributes) { let indexName = indexNameOrAttributes; if (typeof indexName !== "string") { indexName = Utils.underscore(`${tableName}_${indexNameOrAttributes.join("_")}`); } return `DROP INDEX ${this.quoteIdentifier(indexName)}`; } attributeToSQL(attribute, options) { if (!_.isPlainObject(attribute)) { attribute = { type: attribute }; } attribute.onUpdate = ""; if (attribute.references) { if (attribute.Model && attribute.Model.tableName === attribute.references.model) { this.sequelize.log("Oracle does not support self referencial constraints, we will remove it but we recommend restructuring your query"); attribute.onDelete = ""; } } let template; template = attribute.type.toSql ? attribute.type.toSql() : ""; if (attribute.type instanceof DataTypes.JSON) { template += ` CHECK (${this.quoteIdentifier(options.attributeName)} IS JSON)`; return template; } if (Utils.defaultValueSchemable(attribute.defaultValue)) { template += ` DEFAULT ${this.escape(attribute.defaultValue)}`; } if (attribute.allowNull === false) { template += " NOT NULL"; } if (attribute.type instanceof DataTypes.ENUM) { if (attribute.type.values && !attribute.values) attribute.values = attribute.type.values; template += ` CHECK (${this.quoteIdentifier(options.attributeName)} IN(${_.map(attribute.values, (value) => { return this.escape(value); }).join(", ")}))`; return template; } if (attribute.type instanceof DataTypes.BOOLEAN) { template += ` CHECK (${this.quoteIdentifier(options.attributeName)} IN('1', '0'))`; return template; } if (attribute.autoIncrement) { template = " NUMBER(*,0) GENERATED BY DEFAULT ON NULL AS IDENTITY"; } else if (attribute.type && attribute.type.key === DataTypes.DOUBLE.key) { template = attribute.type.toSql(); } else if (attribute.type) { let unsignedTemplate = ""; if (attribute.type._unsigned) { attribute.type._unsigned = false; unsignedTemplate += ` check(${this.quoteIdentifier(options.attributeName)} >= 0)`; } template = attribute.type.toString(); if (attribute.type && attribute.type !== "TEXT" && attribute.type._binary !== true && Utils.defaultValueSchemable(attribute.defaultValue)) { template += ` DEFAULT ${this.escape(attribute.defaultValue)}`; } if (!attribute.autoIncrement) { if (attribute.allowNull === false) { template += " NOT NULL"; } else if (!attribute.primaryKey && !Utils.defaultValueSchemable(attribute.defaultValue)) { template += " NULL"; } } template += unsignedTemplate; } else { template = ""; } if (attribute.unique === true && !attribute.primaryKey) { template += " UNIQUE"; } if (attribute.primaryKey) { template += " PRIMARY KEY"; } if ((!options || !options.withoutForeignKeyConstraints) && attribute.references) { template += ` REFERENCES ${this.quoteTable(attribute.references.model)}`; if (attribute.references.key) { template += ` (${this.quoteIdentifier(attribute.references.key)})`; } else { template += ` (${this.quoteIdentifier("id")})`; } if (attribute.onDelete && attribute.onDelete.toUpperCase() !== "NO ACTION") { template += ` ON DELETE ${attribute.onDelete.toUpperCase()}`; } } return template; } attributesToSQL(attributes, options) { const result = {}; for (const key in attributes) { const attribute = attributes[key]; const attributeName = attribute.field || key; result[attributeName] = this.attributeToSQL(attribute, __spreadValues({ attributeName }, options)); } return result; } createTrigger() { throwMethodUndefined("createTrigger"); } dropTrigger() { throwMethodUndefined("dropTrigger"); } renameTrigger() { throwMethodUndefined("renameTrigger"); } createFunction() { throwMethodUndefined("createFunction"); } dropFunction() { throwMethodUndefined("dropFunction"); } renameFunction() { throwMethodUndefined("renameFunction"); } getConstraintsOnColumn(table, column) { const [tableName, schemaName] = this.getSchemaNameAndTableName(table); column = this.getCatalogName(column); const sql = [ "SELECT CONSTRAINT_NAME FROM user_cons_columns WHERE TABLE_NAME = ", this.escape(tableName), " and OWNER = ", table.schema ? this.escape(schemaName) : "USER", " and COLUMN_NAME = ", this.escape(column), " AND POSITION IS NOT NULL ORDER BY POSITION" ].join(""); return sql; } getForeignKeysQuery(table) { const [tableName, schemaName] = this.getSchemaNameAndTableName(table); const sql = [ 'SELECT DISTINCT a.table_name "tableName", a.constraint_name "constraintName", a.owner "owner", a.column_name "columnName",', ' b.table_name "referencedTableName", b.column_name "referencedColumnName"', " FROM all_cons_columns a", " JOIN all_constraints c ON a.owner = c.owner AND a.constraint_name = c.constraint_name", " JOIN all_cons_columns b ON c.owner = b.owner AND c.r_constraint_name = b.constraint_name", " WHERE c.constraint_type = 'R'", " AND a.table_name = ", this.escape(tableName), " AND a.owner = ", table.schema ? this.escape(schemaName) : "USER", " ORDER BY a.table_name, a.constraint_name" ].join(""); return sql; } dropForeignKeyQuery(tableName, foreignKey) { return this.dropConstraintQuery(tableName, foreignKey); } getPrimaryKeyConstraintQuery(table) { const [tableName, schemaName] = this.getSchemaNameAndTableName(table); const sql = [ "SELECT cols.column_name, atc.identity_column ", "FROM all_constraints cons, all_cons_columns cols ", "INNER JOIN all_tab_columns atc ON(atc.table_name = cols.table_name AND atc.COLUMN_NAME = cols.COLUMN_NAME )", "WHERE cols.table_name = ", this.escape(tableName), "AND cols.owner = ", table.schema ? this.escape(schemaName) : "USER ", "AND cons.constraint_type = 'P' ", "AND cons.constraint_name = cols.constraint_name ", "AND cons.owner = cols.owner ", "ORDER BY cols.table_name, cols.position" ].join(""); return sql; } dropConstraintQuery(tableName, constraintName) { return `ALTER TABLE ${this.quoteTable(tableName)} DROP CONSTRAINT ${constraintName}`; } setIsolationLevelQuery(value, options) { if (options.parent) { return; } switch (value) { case Transaction.ISOLATION_LEVELS.READ_UNCOMMITTED: case Transaction.ISOLATION_LEVELS.READ_COMMITTED: return "SET TRANSACTION ISOLATION LEVEL READ COMMITTED;"; case Transaction.ISOLATION_LEVELS.REPEATABLE_READ: return "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;"; default: throw new Error(`isolation level "${value}" is not supported`); } } getAliasToken() { return ""; } startTransactionQuery(transaction) { if (transaction.parent) { return `SAVEPOINT ${this.quoteIdentifier(transaction.name)}`; } return "BEGIN TRANSACTION"; } commitTransactionQuery(transaction) { if (transaction.parent) { return; } return "COMMIT TRANSACTION"; } rollbackTransactionQuery(transaction) { if (transaction.parent) { return `ROLLBACK TO SAVEPOINT ${this.quoteIdentifier(transaction.name)}`; } return "ROLLBACK TRANSACTION"; } handleSequelizeMethod(smth, tableName, factory, options, prepend) { let str; if (smth instanceof Utils.Json) { if (smth.conditions) { const conditions = this.parseConditionObject(smth.conditions).map((condition) => `${this.jsonPathExtractionQuery(condition.path[0], _.tail(condition.path))} = '${condition.value}'`); return conditions.join(" AND "); } if (smth.path) { if (this._checkValidJsonStatement(smth.path)) { str = smth.path; } else { const paths = _.toPath(smth.path); const column = paths.shift(); str = this.jsonPathExtractionQuery(column, paths); } if (smth.value) { str += util.format(" = %s", this.escape(smth.value)); } return str; } } if (smth instanceof Utils.Cast) { if (smth.val instanceof Utils.SequelizeMethod) { str = this.handleSequelizeMethod(smth.val, tableName, factory, options, prepend); if (smth.type === "boolean") { str = `(CASE WHEN ${str}='true' THEN 1 ELSE 0 END)`; return `CAST(${str} AS NUMBER)`; } if (smth.type === "timestamptz" && /json_value\(/.test(str)) { str = str.slice(0, -1); return `${str} RETURNING TIMESTAMP WITH TIME ZONE)`; } } } return super.handleSequelizeMethod(smth, tableName, factory, options, prepend); } _checkValidJsonStatement(stmt) { if (typeof stmt !== "string") { return false; } let currentIndex = 0; let openingBrackets = 0; let closingBrackets = 0; let hasJsonFunction = false; let hasInvalidToken = false; while (currentIndex < stmt.length) { const string = stmt.substr(currentIndex); const functionMatches = JSON_FUNCTION_REGEX.exec(string); if (functionMatches) { currentIndex += functionMatches[0].indexOf("("); hasJsonFunction = true; continue; } const operatorMatches = JSON_OPERATOR_REGEX.exec(string); if (operatorMatches) { currentIndex += operatorMatches[0].length; hasJsonFunction = true; continue; } const tokenMatches = TOKEN_CAPTURE_REGEX.exec(string); if (tokenMatches) { const capturedToken = tokenMatches[1]; if (capturedToken === "(") { openingBrackets++; } else if (capturedToken === ")") { closingBrackets++; } else if (capturedToken === ";") { hasInvalidToken = true; break; } currentIndex += tokenMatches[0].length; continue; } break; } if (hasJsonFunction && (hasInvalidToken || openingBrackets !== closingBrackets)) { throw new Error(`Invalid json statement: ${stmt}`); } return hasJsonFunction; } jsonPathExtractionQuery(column, path) { let paths = _.toPath(path); const quotedColumn = this.isIdentifierQuoted(column) ? column : this.quoteIdentifier(column); paths = paths.map((subPath) => { return /\D/.test(subPath) ? Utils.addTicks(subPath, '"') : subPath; }); const pathStr = this.escape(["$"].concat(paths).join(".").replace(/\.(\d+)(?:(?=\.)|$)/g, (__, digit) => `[${digit}]`)); return `json_value(${quotedColumn},${pathStr})`; } addLimitAndOffset(options, model) { let fragment = ""; const offset = options.offset || 0, isSubQuery = options.hasIncludeWhere || options.hasIncludeRequired || options.hasMultiAssociation; let orders = {}; if (options.order) { orders = this.getQueryOrders(options, model, isSubQuery); } if (options.limit || options.offset) { if (!orders.mainQueryOrder || !orders.mainQueryOrder.length || isSubQuery && (!orders.subQueryOrder || !orders.subQueryOrder.length)) { const tablePkFragment = `${this.quoteTable(options.tableAs || model.name)}.${this.quoteIdentifier(model.primaryKeyField)}`; fragment += ` ORDER BY ${tablePkFragment}`; } if (options.offset || options.limit) { fragment += ` OFFSET ${this.escape(offset)} ROWS`; } if (options.limit) { fragment += ` FETCH NEXT ${this.escape(options.limit)} ROWS ONLY`; } } return fragment; } booleanValue(value) { return value ? 1 : 0; } quoteIdentifier(identifier, force = false) { const optForceQuote = force; const optQuoteIdentifiers = this.options.quoteIdentifiers !== false; const rawIdentifier = Utils.removeTicks(identifier, '"'); const regExp = /^(([\w][\w\d_]*))$/g; if (optForceQuote !== true && optQuoteIdentifiers === false && regExp.test(rawIdentifier) && !ORACLE_RESERVED_WORDS.includes(rawIdentifier.toUpperCase())) { return rawIdentifier; } return Utils.addTicks(rawIdentifier, '"'); } bindParam(bind, posOffset = 0) { return (value) => { bind.push(value); return `:${bind.length + posOffset}`; }; } authTestQuery() { return "SELECT 1+1 AS result FROM DUAL"; } } function throwMethodUndefined(methodName) { throw new Error(`The method "${methodName}" is not defined! Please add it to your sql dialect.`); } //# sourceMappingURL=query-generator.js.map