| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671 |
- "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;
- };
- const Utils = require("../../utils");
- const util = require("util");
- const DataTypes = require("../../data-types");
- const AbstractQueryGenerator = require("../abstract/query-generator");
- const semver = require("semver");
- const _ = require("lodash");
- const POSTGRES_RESERVED_WORDS = "all,analyse,analyze,and,any,array,as,asc,asymmetric,authorization,binary,both,case,cast,check,collate,collation,column,concurrently,constraint,create,cross,current_catalog,current_date,current_role,current_schema,current_time,current_timestamp,current_user,default,deferrable,desc,distinct,do,else,end,except,false,fetch,for,foreign,freeze,from,full,grant,group,having,ilike,in,initially,inner,intersect,into,is,isnull,join,lateral,leading,left,like,limit,localtime,localtimestamp,natural,not,notnull,null,offset,on,only,or,order,outer,overlaps,placing,primary,references,returning,right,select,session_user,similar,some,symmetric,table,tablesample,then,to,trailing,true,union,unique,user,using,variadic,verbose,when,where,window,with".split(",");
- class PostgresQueryGenerator extends AbstractQueryGenerator {
- setSearchPath(searchPath) {
- return `SET search_path to ${searchPath};`;
- }
- createDatabaseQuery(databaseName, options) {
- options = __spreadValues({
- encoding: null,
- collate: null
- }, options);
- const values = {
- database: this.quoteTable(databaseName),
- encoding: options.encoding ? ` ENCODING = ${this.escape(options.encoding)}` : "",
- collation: options.collate ? ` LC_COLLATE = ${this.escape(options.collate)}` : "",
- ctype: options.ctype ? ` LC_CTYPE = ${this.escape(options.ctype)}` : "",
- template: options.template ? ` TEMPLATE = ${this.escape(options.template)}` : ""
- };
- return `CREATE DATABASE ${values.database}${values.encoding}${values.collation}${values.ctype}${values.template};`;
- }
- dropDatabaseQuery(databaseName) {
- return `DROP DATABASE IF EXISTS ${this.quoteTable(databaseName)};`;
- }
- createSchema(schema) {
- const databaseVersion = _.get(this, "sequelize.options.databaseVersion", 0);
- if (databaseVersion && semver.gte(databaseVersion, "9.2.0")) {
- return `CREATE SCHEMA IF NOT EXISTS ${this.quoteIdentifier(schema)};`;
- }
- return `CREATE SCHEMA ${this.quoteIdentifier(schema)};`;
- }
- dropSchema(schema) {
- return `DROP SCHEMA IF EXISTS ${this.quoteIdentifier(schema)} CASCADE;`;
- }
- showSchemasQuery() {
- return "SELECT schema_name FROM information_schema.schemata WHERE schema_name <> 'information_schema' AND schema_name != 'public' AND schema_name !~ E'^pg_';";
- }
- versionQuery() {
- return "SHOW SERVER_VERSION";
- }
- createTableQuery(tableName, attributes, options) {
- options = __spreadValues({}, options);
- const databaseVersion = _.get(this, "sequelize.options.databaseVersion", 0);
- const attrStr = [];
- let comments = "";
- let columnComments = "";
- const quotedTable = this.quoteTable(tableName);
- if (options.comment && typeof options.comment === "string") {
- comments += `; COMMENT ON TABLE ${quotedTable} IS ${this.escape(options.comment)}`;
- }
- for (const attr in attributes) {
- const quotedAttr = this.quoteIdentifier(attr);
- const i = attributes[attr].indexOf("COMMENT ");
- if (i !== -1) {
- const escapedCommentText = this.escape(attributes[attr].substring(i + 8));
- columnComments += `; COMMENT ON COLUMN ${quotedTable}.${quotedAttr} IS ${escapedCommentText}`;
- attributes[attr] = attributes[attr].substring(0, i);
- }
- const dataType = this.dataTypeMapping(tableName, attr, attributes[attr]);
- attrStr.push(`${quotedAttr} ${dataType}`);
- }
- let attributesClause = attrStr.join(", ");
- if (options.uniqueKeys) {
- _.each(options.uniqueKeys, (columns) => {
- if (columns.customIndex) {
- attributesClause += `, UNIQUE (${columns.fields.map((field) => this.quoteIdentifier(field)).join(", ")})`;
- }
- });
- }
- const pks = _.reduce(attributes, (acc, attribute, key) => {
- if (attribute.includes("PRIMARY KEY")) {
- acc.push(this.quoteIdentifier(key));
- }
- return acc;
- }, []).join(",");
- if (pks.length > 0) {
- attributesClause += `, PRIMARY KEY (${pks})`;
- }
- return `CREATE TABLE ${databaseVersion === 0 || semver.gte(databaseVersion, "9.1.0") ? "IF NOT EXISTS " : ""}${quotedTable} (${attributesClause})${comments}${columnComments};`;
- }
- dropTableQuery(tableName, options) {
- options = options || {};
- return `DROP TABLE IF EXISTS ${this.quoteTable(tableName)}${options.cascade ? " CASCADE" : ""};`;
- }
- showTablesQuery() {
- const schema = this.options.schema || "public";
- return `SELECT table_name FROM information_schema.tables WHERE table_schema = ${this.escape(schema)} AND table_type LIKE '%TABLE' AND table_name != 'spatial_ref_sys';`;
- }
- tableExistsQuery(tableName) {
- const table = tableName.tableName || tableName;
- const schema = tableName.schema || "public";
- return `SELECT table_name FROM information_schema.tables WHERE table_schema = ${this.escape(schema)} AND table_name = ${this.escape(table)}`;
- }
- describeTableQuery(tableName, schema) {
- schema = schema || this.options.schema || "public";
- return `SELECT pk.constraint_type as "Constraint",c.column_name as "Field", c.column_default as "Default",c.is_nullable as "Null", (CASE WHEN c.udt_name = 'hstore' THEN c.udt_name ELSE c.data_type END) || (CASE WHEN c.character_maximum_length IS NOT NULL THEN '(' || c.character_maximum_length || ')' ELSE '' END) as "Type", (SELECT array_agg(e.enumlabel) FROM pg_catalog.pg_type t JOIN pg_catalog.pg_enum e ON t.oid=e.enumtypid WHERE t.typname=c.udt_name) AS "special", (SELECT pgd.description FROM pg_catalog.pg_statio_all_tables AS st INNER JOIN pg_catalog.pg_description pgd on (pgd.objoid=st.relid) WHERE c.ordinal_position=pgd.objsubid AND c.table_name=st.relname) AS "Comment" FROM information_schema.columns c LEFT JOIN (SELECT tc.table_schema, tc.table_name, cu.column_name, tc.constraint_type FROM information_schema.TABLE_CONSTRAINTS tc JOIN information_schema.KEY_COLUMN_USAGE cu ON tc.table_schema=cu.table_schema and tc.table_name=cu.table_name and tc.constraint_name=cu.constraint_name and tc.constraint_type='PRIMARY KEY') pk ON pk.table_schema=c.table_schema AND pk.table_name=c.table_name AND pk.column_name=c.column_name WHERE c.table_name = ${this.escape(tableName)} AND c.table_schema = ${this.escape(schema)}`;
- }
- _checkValidJsonStatement(stmt) {
- if (typeof stmt !== "string") {
- return false;
- }
- const jsonFunctionRegex = /^\s*((?:[a-z]+_){0,2}jsonb?(?:_[a-z]+){0,2})\([^)]*\)/i;
- const jsonOperatorRegex = /^\s*(->>?|#>>?|@>|<@|\?[|&]?|\|{2}|#-)/i;
- const tokenCaptureRegex = /^\s*((?:([`"'])(?:(?!\2).|\2{2})*\2)|[\w\d\s]+|[().,;+-])/i;
- 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 = jsonFunctionRegex.exec(string);
- if (functionMatches) {
- currentIndex += functionMatches[0].indexOf("(");
- hasJsonFunction = true;
- continue;
- }
- const operatorMatches = jsonOperatorRegex.exec(string);
- if (operatorMatches) {
- currentIndex += operatorMatches[0].length;
- hasJsonFunction = true;
- continue;
- }
- const tokenMatches = tokenCaptureRegex.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;
- }
- hasInvalidToken |= openingBrackets !== closingBrackets;
- if (hasJsonFunction && hasInvalidToken) {
- throw new Error(`Invalid json statement: ${stmt}`);
- }
- return hasJsonFunction;
- }
- handleSequelizeMethod(smth, tableName, factory, options, prepend) {
- 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) {
- let str;
- 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;
- }
- }
- return super.handleSequelizeMethod.call(this, smth, tableName, factory, options, prepend);
- }
- addColumnQuery(table, key, attribute) {
- const dbDataType = this.attributeToSQL(attribute, { context: "addColumn", table, key });
- const dataType = attribute.type || attribute;
- const definition = this.dataTypeMapping(table, key, dbDataType);
- const quotedKey = this.quoteIdentifier(key);
- const quotedTable = this.quoteTable(this.extractTableDetails(table));
- let query = `ALTER TABLE ${quotedTable} ADD COLUMN ${quotedKey} ${definition};`;
- if (dataType instanceof DataTypes.ENUM) {
- query = this.pgEnum(table, key, dataType) + query;
- } else if (dataType.type && dataType.type instanceof DataTypes.ENUM) {
- query = this.pgEnum(table, key, dataType.type) + query;
- }
- return query;
- }
- removeColumnQuery(tableName, attributeName) {
- const quotedTableName = this.quoteTable(this.extractTableDetails(tableName));
- const quotedAttributeName = this.quoteIdentifier(attributeName);
- return `ALTER TABLE ${quotedTableName} DROP COLUMN ${quotedAttributeName};`;
- }
- changeColumnQuery(tableName, attributes) {
- const query = (subQuery) => `ALTER TABLE ${this.quoteTable(tableName)} ALTER COLUMN ${subQuery};`;
- const sql = [];
- for (const attributeName in attributes) {
- let definition = this.dataTypeMapping(tableName, attributeName, attributes[attributeName]);
- let attrSql = "";
- if (definition.includes("NOT NULL")) {
- attrSql += query(`${this.quoteIdentifier(attributeName)} SET NOT NULL`);
- definition = definition.replace("NOT NULL", "").trim();
- } else if (!definition.includes("REFERENCES")) {
- attrSql += query(`${this.quoteIdentifier(attributeName)} DROP NOT NULL`);
- }
- if (definition.includes("DEFAULT")) {
- attrSql += query(`${this.quoteIdentifier(attributeName)} SET DEFAULT ${definition.match(/DEFAULT ([^;]+)/)[1]}`);
- definition = definition.replace(/(DEFAULT[^;]+)/, "").trim();
- } else if (!definition.includes("REFERENCES")) {
- attrSql += query(`${this.quoteIdentifier(attributeName)} DROP DEFAULT`);
- }
- if (attributes[attributeName].startsWith("ENUM(")) {
- attrSql += this.pgEnum(tableName, attributeName, attributes[attributeName]);
- definition = definition.replace(/^ENUM\(.+\)/, this.pgEnumName(tableName, attributeName, { schema: false }));
- definition += ` USING (${this.quoteIdentifier(attributeName)}::${this.pgEnumName(tableName, attributeName)})`;
- }
- if (definition.match(/UNIQUE;*$/)) {
- definition = definition.replace(/UNIQUE;*$/, "");
- attrSql += query(`ADD UNIQUE (${this.quoteIdentifier(attributeName)})`).replace("ALTER COLUMN", "");
- }
- if (definition.includes("REFERENCES")) {
- definition = definition.replace(/.+?(?=REFERENCES)/, "");
- attrSql += query(`ADD FOREIGN KEY (${this.quoteIdentifier(attributeName)}) ${definition}`).replace("ALTER COLUMN", "");
- } else {
- attrSql += query(`${this.quoteIdentifier(attributeName)} TYPE ${definition}`);
- }
- sql.push(attrSql);
- }
- return sql.join("");
- }
- renameColumnQuery(tableName, attrBefore, attributes) {
- const attrString = [];
- for (const attributeName in attributes) {
- attrString.push(`${this.quoteIdentifier(attrBefore)} TO ${this.quoteIdentifier(attributeName)}`);
- }
- return `ALTER TABLE ${this.quoteTable(tableName)} RENAME COLUMN ${attrString.join(", ")};`;
- }
- fn(fnName, tableName, parameters, body, returns, language) {
- fnName = fnName || "testfunc";
- language = language || "plpgsql";
- returns = returns ? `RETURNS ${returns}` : "";
- parameters = parameters || "";
- return `CREATE OR REPLACE FUNCTION pg_temp.${fnName}(${parameters}) ${returns} AS $func$ BEGIN ${body} END; $func$ LANGUAGE ${language}; SELECT * FROM pg_temp.${fnName}();`;
- }
- truncateTableQuery(tableName, options = {}) {
- return [
- `TRUNCATE ${this.quoteTable(tableName)}`,
- options.restartIdentity ? " RESTART IDENTITY" : "",
- options.cascade ? " CASCADE" : ""
- ].join("");
- }
- deleteQuery(tableName, where, options = {}, model) {
- const table = this.quoteTable(tableName);
- let whereClause = this.getWhereConditions(where, null, model, options);
- const limit = options.limit ? ` LIMIT ${this.escape(options.limit)}` : "";
- let primaryKeys = "";
- let primaryKeysSelection = "";
- if (whereClause) {
- whereClause = ` WHERE ${whereClause}`;
- }
- if (options.limit) {
- if (!model) {
- throw new Error("Cannot LIMIT delete without a model.");
- }
- const pks = Object.values(model.primaryKeys).map((pk) => this.quoteIdentifier(pk.field)).join(",");
- primaryKeys = model.primaryKeyAttributes.length > 1 ? `(${pks})` : pks;
- primaryKeysSelection = pks;
- return `DELETE FROM ${table} WHERE ${primaryKeys} IN (SELECT ${primaryKeysSelection} FROM ${table}${whereClause}${limit})`;
- }
- return `DELETE FROM ${table}${whereClause}`;
- }
- showIndexesQuery(tableName) {
- let schemaJoin = "";
- let schemaWhere = "";
- if (typeof tableName !== "string") {
- schemaJoin = ", pg_namespace s";
- schemaWhere = ` AND s.oid = t.relnamespace AND s.nspname = '${tableName.schema}'`;
- tableName = tableName.tableName;
- }
- return `SELECT i.relname AS name, ix.indisprimary AS primary, ix.indisunique AS unique, ix.indkey AS indkey, array_agg(a.attnum) as column_indexes, array_agg(a.attname) AS column_names, pg_get_indexdef(ix.indexrelid) AS definition FROM pg_class t, pg_class i, pg_index ix, pg_attribute a${schemaJoin} WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND t.relkind = 'r' and t.relname = '${tableName}'${schemaWhere} GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;`;
- }
- showConstraintsQuery(tableName) {
- return [
- 'SELECT constraint_catalog AS "constraintCatalog",',
- 'constraint_schema AS "constraintSchema",',
- 'constraint_name AS "constraintName",',
- 'table_catalog AS "tableCatalog",',
- 'table_schema AS "tableSchema",',
- 'table_name AS "tableName",',
- 'constraint_type AS "constraintType",',
- 'is_deferrable AS "isDeferrable",',
- 'initially_deferred AS "initiallyDeferred"',
- "from INFORMATION_SCHEMA.table_constraints",
- `WHERE table_name='${tableName}';`
- ].join(" ");
- }
- removeIndexQuery(tableName, indexNameOrAttributes, options) {
- let indexName = indexNameOrAttributes;
- if (typeof indexName !== "string") {
- indexName = Utils.underscore(`${tableName}_${indexNameOrAttributes.join("_")}`);
- }
- return [
- "DROP INDEX",
- options && options.concurrently && "CONCURRENTLY",
- `IF EXISTS ${this.quoteIdentifiers(indexName)}`
- ].filter(Boolean).join(" ");
- }
- addLimitAndOffset(options) {
- let fragment = "";
- if (options.limit != null) {
- fragment += " LIMIT " + this.escape(options.limit);
- }
- if (options.offset != null) {
- fragment += " OFFSET " + this.escape(options.offset);
- }
- return fragment;
- }
- attributeToSQL(attribute, options) {
- if (!_.isPlainObject(attribute)) {
- attribute = {
- type: attribute
- };
- }
- let type;
- if (attribute.type instanceof DataTypes.ENUM || attribute.type instanceof DataTypes.ARRAY && attribute.type.type instanceof DataTypes.ENUM) {
- const enumType = attribute.type.type || attribute.type;
- let values = attribute.values;
- if (enumType.values && !attribute.values) {
- values = enumType.values;
- }
- if (Array.isArray(values) && values.length > 0) {
- type = `ENUM(${values.map((value) => this.escape(value)).join(", ")})`;
- if (attribute.type instanceof DataTypes.ARRAY) {
- type += "[]";
- }
- } else {
- throw new Error("Values for ENUM haven't been defined.");
- }
- }
- if (!type) {
- type = attribute.type;
- }
- let sql = type.toString();
- if (Object.prototype.hasOwnProperty.call(attribute, "allowNull") && !attribute.allowNull) {
- sql += " NOT NULL";
- }
- if (attribute.autoIncrement) {
- if (attribute.autoIncrementIdentity) {
- sql += " GENERATED BY DEFAULT AS IDENTITY";
- } else {
- sql += " SERIAL";
- }
- }
- if (Utils.defaultValueSchemable(attribute.defaultValue)) {
- sql += ` DEFAULT ${this.escape(attribute.defaultValue, attribute)}`;
- }
- if (attribute.unique === true) {
- sql += " UNIQUE";
- }
- if (attribute.primaryKey) {
- sql += " PRIMARY KEY";
- }
- if (attribute.references) {
- let referencesTable = this.quoteTable(attribute.references.model);
- let schema;
- if (options.schema) {
- schema = options.schema;
- } else if ((!attribute.references.model || typeof attribute.references.model == "string") && options.table && options.table.schema) {
- schema = options.table.schema;
- }
- if (schema) {
- referencesTable = this.quoteTable(this.addSchema({
- tableName: referencesTable,
- _schema: schema
- }));
- }
- let referencesKey;
- if (!options.withoutForeignKeyConstraints) {
- if (attribute.references.key) {
- referencesKey = this.quoteIdentifiers(attribute.references.key);
- } else {
- referencesKey = this.quoteIdentifier("id");
- }
- sql += ` REFERENCES ${referencesTable} (${referencesKey})`;
- if (attribute.onDelete) {
- sql += ` ON DELETE ${attribute.onDelete.toUpperCase()}`;
- }
- if (attribute.onUpdate) {
- sql += ` ON UPDATE ${attribute.onUpdate.toUpperCase()}`;
- }
- if (attribute.references.deferrable) {
- sql += ` ${attribute.references.deferrable.toString(this)}`;
- }
- }
- }
- if (attribute.comment && typeof attribute.comment === "string") {
- if (options && ["addColumn", "changeColumn"].includes(options.context)) {
- const quotedAttr = this.quoteIdentifier(options.key);
- const escapedCommentText = this.escape(attribute.comment);
- sql += `; COMMENT ON COLUMN ${this.quoteTable(options.table)}.${quotedAttr} IS ${escapedCommentText}`;
- } else {
- sql += ` COMMENT ${attribute.comment}`;
- }
- }
- return sql;
- }
- deferConstraintsQuery(options) {
- return options.deferrable.toString(this);
- }
- setConstraintQuery(columns, type) {
- let columnFragment = "ALL";
- if (columns) {
- columnFragment = columns.map((column) => this.quoteIdentifier(column)).join(", ");
- }
- return `SET CONSTRAINTS ${columnFragment} ${type}`;
- }
- setDeferredQuery(columns) {
- return this.setConstraintQuery(columns, "DEFERRED");
- }
- setImmediateQuery(columns) {
- return this.setConstraintQuery(columns, "IMMEDIATE");
- }
- attributesToSQL(attributes, options) {
- const result = {};
- for (const key in attributes) {
- const attribute = attributes[key];
- result[attribute.field || key] = this.attributeToSQL(attribute, __spreadValues({ key }, options));
- }
- return result;
- }
- createTrigger(tableName, triggerName, eventType, fireOnSpec, functionName, functionParams, optionsArray) {
- const decodedEventType = this.decodeTriggerEventType(eventType);
- const eventSpec = this.expandTriggerEventSpec(fireOnSpec);
- const expandedOptions = this.expandOptions(optionsArray);
- const paramList = this._expandFunctionParamList(functionParams);
- return `CREATE ${this.triggerEventTypeIsConstraint(eventType)}TRIGGER ${this.quoteIdentifier(triggerName)} ${decodedEventType} ${eventSpec} ON ${this.quoteTable(tableName)}${expandedOptions ? ` ${expandedOptions}` : ""} EXECUTE PROCEDURE ${functionName}(${paramList});`;
- }
- dropTrigger(tableName, triggerName) {
- return `DROP TRIGGER ${this.quoteIdentifier(triggerName)} ON ${this.quoteTable(tableName)} RESTRICT;`;
- }
- renameTrigger(tableName, oldTriggerName, newTriggerName) {
- return `ALTER TRIGGER ${this.quoteIdentifier(oldTriggerName)} ON ${this.quoteTable(tableName)} RENAME TO ${this.quoteIdentifier(newTriggerName)};`;
- }
- createFunction(functionName, params, returnType, language, body, optionsArray, options) {
- if (!functionName || !returnType || !language || !body)
- throw new Error("createFunction missing some parameters. Did you pass functionName, returnType, language and body?");
- const paramList = this._expandFunctionParamList(params);
- const variableList = options && options.variables ? this._expandFunctionVariableList(options.variables) : "";
- const expandedOptionsArray = this.expandOptions(optionsArray);
- const statement = options && options.force ? "CREATE OR REPLACE FUNCTION" : "CREATE FUNCTION";
- return `${statement} ${functionName}(${paramList}) RETURNS ${returnType} AS $func$ ${variableList} BEGIN ${body} END; $func$ language '${language}'${expandedOptionsArray};`;
- }
- dropFunction(functionName, params) {
- if (!functionName)
- throw new Error("requires functionName");
- const paramList = this._expandFunctionParamList(params);
- return `DROP FUNCTION ${functionName}(${paramList}) RESTRICT;`;
- }
- renameFunction(oldFunctionName, params, newFunctionName) {
- const paramList = this._expandFunctionParamList(params);
- return `ALTER FUNCTION ${oldFunctionName}(${paramList}) RENAME TO ${newFunctionName};`;
- }
- pgEscapeAndQuote(val) {
- return this.quoteIdentifier(Utils.removeTicks(this.escape(val), "'"));
- }
- _expandFunctionParamList(params) {
- if (params === void 0 || !Array.isArray(params)) {
- throw new Error("_expandFunctionParamList: function parameters array required, including an empty one for no arguments");
- }
- const paramList = [];
- params.forEach((curParam) => {
- const paramDef = [];
- if (curParam.type) {
- if (curParam.direction) {
- paramDef.push(curParam.direction);
- }
- if (curParam.name) {
- paramDef.push(curParam.name);
- }
- paramDef.push(curParam.type);
- } else {
- throw new Error("function or trigger used with a parameter without any type");
- }
- const joined = paramDef.join(" ");
- if (joined)
- paramList.push(joined);
- });
- return paramList.join(", ");
- }
- _expandFunctionVariableList(variables) {
- if (!Array.isArray(variables)) {
- throw new Error("_expandFunctionVariableList: function variables must be an array");
- }
- const variableDefinitions = [];
- variables.forEach((variable) => {
- if (!variable.name || !variable.type) {
- throw new Error("function variable must have a name and type");
- }
- let variableDefinition = `DECLARE ${variable.name} ${variable.type}`;
- if (variable.default) {
- variableDefinition += ` := ${variable.default}`;
- }
- variableDefinition += ";";
- variableDefinitions.push(variableDefinition);
- });
- return variableDefinitions.join(" ");
- }
- expandOptions(options) {
- return options === void 0 || _.isEmpty(options) ? "" : options.join(" ");
- }
- decodeTriggerEventType(eventSpecifier) {
- const EVENT_DECODER = {
- "after": "AFTER",
- "before": "BEFORE",
- "instead_of": "INSTEAD OF",
- "after_constraint": "AFTER"
- };
- if (!EVENT_DECODER[eventSpecifier]) {
- throw new Error(`Invalid trigger event specified: ${eventSpecifier}`);
- }
- return EVENT_DECODER[eventSpecifier];
- }
- triggerEventTypeIsConstraint(eventSpecifier) {
- return eventSpecifier === "after_constraint" ? "CONSTRAINT " : "";
- }
- expandTriggerEventSpec(fireOnSpec) {
- if (_.isEmpty(fireOnSpec)) {
- throw new Error("no table change events specified to trigger on");
- }
- return _.map(fireOnSpec, (fireValue, fireKey) => {
- const EVENT_MAP = {
- "insert": "INSERT",
- "update": "UPDATE",
- "delete": "DELETE",
- "truncate": "TRUNCATE"
- };
- if (!EVENT_MAP[fireValue]) {
- throw new Error(`parseTriggerEventSpec: undefined trigger event ${fireKey}`);
- }
- let eventSpec = EVENT_MAP[fireValue];
- if (eventSpec === "UPDATE") {
- if (Array.isArray(fireValue) && fireValue.length > 0) {
- eventSpec += ` OF ${fireValue.join(", ")}`;
- }
- }
- return eventSpec;
- }).join(" OR ");
- }
- pgEnumName(tableName, attr, options) {
- options = options || {};
- const tableDetails = this.extractTableDetails(tableName, options);
- let enumName = Utils.addTicks(Utils.generateEnumName(tableDetails.tableName, attr), '"');
- if (options.schema !== false && tableDetails.schema) {
- enumName = this.quoteIdentifier(tableDetails.schema) + tableDetails.delimiter + enumName;
- }
- return enumName;
- }
- pgListEnums(tableName, attrName, options) {
- let enumName = "";
- const tableDetails = this.extractTableDetails(tableName, options);
- if (tableDetails.tableName && attrName) {
- enumName = ` AND t.typname=${this.pgEnumName(tableDetails.tableName, attrName, { schema: false }).replace(/"/g, "'")}`;
- }
- return `SELECT t.typname enum_name, array_agg(e.enumlabel ORDER BY enumsortorder) enum_value FROM pg_type t JOIN pg_enum e ON t.oid = e.enumtypid JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace WHERE n.nspname = '${tableDetails.schema}'${enumName} GROUP BY 1`;
- }
- pgEnum(tableName, attr, dataType, options) {
- const enumName = this.pgEnumName(tableName, attr, options);
- let values;
- if (dataType.values) {
- values = `ENUM(${dataType.values.map((value) => this.escape(value)).join(", ")})`;
- } else {
- values = dataType.toString().match(/^ENUM\(.+\)/)[0];
- }
- let sql = `DO ${this.escape(`BEGIN CREATE TYPE ${enumName} AS ${values}; EXCEPTION WHEN duplicate_object THEN null; END`)};`;
- if (!!options && options.force === true) {
- sql = this.pgEnumDrop(tableName, attr) + sql;
- }
- return sql;
- }
- pgEnumAdd(tableName, attr, value, options) {
- const enumName = this.pgEnumName(tableName, attr);
- let sql = `ALTER TYPE ${enumName} ADD VALUE `;
- if (semver.gte(this.sequelize.options.databaseVersion, "9.3.0")) {
- sql += "IF NOT EXISTS ";
- }
- sql += this.escape(value);
- if (options.before) {
- sql += ` BEFORE ${this.escape(options.before)}`;
- } else if (options.after) {
- sql += ` AFTER ${this.escape(options.after)}`;
- }
- return sql;
- }
- pgEnumDrop(tableName, attr, enumName) {
- enumName = enumName || this.pgEnumName(tableName, attr);
- return `DROP TYPE IF EXISTS ${enumName}; `;
- }
- fromArray(text) {
- text = text.replace(/^{/, "").replace(/}$/, "");
- let matches = text.match(/("(?:\\.|[^"\\\\])*"|[^,]*)(?:\s*,\s*|\s*$)/ig);
- if (matches.length < 1) {
- return [];
- }
- matches = matches.map((m) => m.replace(/",$/, "").replace(/,$/, "").replace(/(^"|"$)/g, ""));
- return matches.slice(0, -1);
- }
- dataTypeMapping(tableName, attr, dataType) {
- if (dataType.includes("PRIMARY KEY")) {
- dataType = dataType.replace("PRIMARY KEY", "");
- }
- if (dataType.includes("SERIAL")) {
- if (dataType.includes("BIGINT")) {
- dataType = dataType.replace("SERIAL", "BIGSERIAL");
- dataType = dataType.replace("BIGINT", "");
- } else if (dataType.includes("SMALLINT")) {
- dataType = dataType.replace("SERIAL", "SMALLSERIAL");
- dataType = dataType.replace("SMALLINT", "");
- } else {
- dataType = dataType.replace("INTEGER", "");
- }
- dataType = dataType.replace("NOT NULL", "");
- }
- if (dataType.startsWith("ENUM(")) {
- dataType = dataType.replace(/^ENUM\(.+\)/, this.pgEnumName(tableName, attr));
- }
- return dataType;
- }
- getForeignKeysQuery(tableName) {
- return `SELECT conname as constraint_name, pg_catalog.pg_get_constraintdef(r.oid, true) as condef FROM pg_catalog.pg_constraint r WHERE r.conrelid = (SELECT oid FROM pg_class WHERE relname = '${tableName}' LIMIT 1) AND r.contype = 'f' ORDER BY 1;`;
- }
- _getForeignKeyReferencesQueryPrefix() {
- return "SELECT DISTINCT tc.constraint_name as constraint_name, tc.constraint_schema as constraint_schema, tc.constraint_catalog as constraint_catalog, tc.table_name as table_name,tc.table_schema as table_schema,tc.table_catalog as table_catalog,tc.initially_deferred as initially_deferred,tc.is_deferrable as is_deferrable,kcu.column_name as column_name,ccu.table_schema AS referenced_table_schema,ccu.table_catalog AS referenced_table_catalog,ccu.table_name AS referenced_table_name,ccu.column_name AS referenced_column_name FROM information_schema.table_constraints AS tc JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name JOIN information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name ";
- }
- getForeignKeyReferencesQuery(tableName, catalogName, schemaName) {
- return `${this._getForeignKeyReferencesQueryPrefix()}WHERE constraint_type = 'FOREIGN KEY' AND tc.table_name = '${tableName}'${catalogName ? ` AND tc.table_catalog = '${catalogName}'` : ""}${schemaName ? ` AND tc.table_schema = '${schemaName}'` : ""}`;
- }
- getForeignKeyReferenceQuery(table, columnName) {
- const tableName = table.tableName || table;
- const schema = table.schema;
- return `${this._getForeignKeyReferencesQueryPrefix()}WHERE constraint_type = 'FOREIGN KEY' AND tc.table_name='${tableName}' AND kcu.column_name = '${columnName}'${schema ? ` AND tc.table_schema = '${schema}'` : ""}`;
- }
- dropForeignKeyQuery(tableName, foreignKey) {
- return `ALTER TABLE ${this.quoteTable(tableName)} DROP CONSTRAINT ${this.quoteIdentifier(foreignKey)};`;
- }
- quoteIdentifier(identifier, force) {
- const optForceQuote = force || false;
- const optQuoteIdentifiers = this.options.quoteIdentifiers !== false;
- const rawIdentifier = Utils.removeTicks(identifier, '"');
- if (optForceQuote === true || optQuoteIdentifiers !== false || identifier.includes(".") || identifier.includes("->") || POSTGRES_RESERVED_WORDS.includes(rawIdentifier.toLowerCase())) {
- return Utils.addTicks(rawIdentifier, '"');
- }
- return rawIdentifier;
- }
- }
- module.exports = PostgresQueryGenerator;
- //# sourceMappingURL=query-generator.js.map
|