{ "version": 3, "sources": ["../../../src/dialects/postgres/query-interface.js"], "sourcesContent": ["'use strict';\n\nconst DataTypes = require('../../data-types');\nconst QueryTypes = require('../../query-types');\nconst { QueryInterface } = require('../abstract/query-interface');\nconst Utils = require('../../utils');\nconst Deferrable = require('../../deferrable');\n\n/**\n * The interface that Sequelize uses to talk with Postgres database\n */\nclass PostgresQueryInterface extends QueryInterface {\n /**\n * Ensure enum and their values.\n *\n * @param {string} tableName Name of table to create\n * @param {object} attributes Object representing a list of normalized table attributes\n * @param {object} [options]\n * @param {Model} [model]\n *\n * @protected\n */\n async ensureEnums(tableName, attributes, options, model) {\n const keys = Object.keys(attributes);\n const keyLen = keys.length;\n\n let sql = '';\n let promises = [];\n let i = 0;\n\n for (i = 0; i < keyLen; i++) {\n const attribute = attributes[keys[i]];\n const type = attribute.type;\n\n if (\n type instanceof DataTypes.ENUM ||\n type instanceof DataTypes.ARRAY && type.type instanceof DataTypes.ENUM //ARRAY sub type is ENUM\n ) {\n sql = this.queryGenerator.pgListEnums(tableName, attribute.field || keys[i], options);\n promises.push(this.sequelize.query(\n sql,\n { ...options, plain: true, raw: true, type: QueryTypes.SELECT }\n ));\n }\n }\n\n const results = await Promise.all(promises);\n promises = [];\n let enumIdx = 0;\n\n // This little function allows us to re-use the same code that prepends or appends new value to enum array\n const addEnumValue = (field, value, relativeValue, position = 'before', spliceStart = promises.length) => {\n const valueOptions = { ...options };\n valueOptions.before = null;\n valueOptions.after = null;\n\n switch (position) {\n case 'after':\n valueOptions.after = relativeValue;\n break;\n case 'before':\n default:\n valueOptions.before = relativeValue;\n break;\n }\n\n promises.splice(spliceStart, 0, () => {\n return this.sequelize.query(this.queryGenerator.pgEnumAdd(\n tableName, field, value, valueOptions\n ), valueOptions);\n });\n };\n\n for (i = 0; i < keyLen; i++) {\n const attribute = attributes[keys[i]];\n const type = attribute.type;\n const enumType = type.type || type;\n const field = attribute.field || keys[i];\n\n if (\n type instanceof DataTypes.ENUM ||\n type instanceof DataTypes.ARRAY && enumType instanceof DataTypes.ENUM //ARRAY sub type is ENUM\n ) {\n // If the enum type doesn't exist then create it\n if (!results[enumIdx]) {\n promises.push(() => {\n return this.sequelize.query(this.queryGenerator.pgEnum(tableName, field, enumType, options), { ...options, raw: true });\n });\n } else if (!!results[enumIdx] && !!model) {\n const enumVals = this.queryGenerator.fromArray(results[enumIdx].enum_value);\n const vals = enumType.values;\n\n // Going through already existing values allows us to make queries that depend on those values\n // We will prepend all new values between the old ones, but keep in mind - we can't change order of already existing values\n // Then we append the rest of new values AFTER the latest already existing value\n // E.g.: [1,2] -> [0,2,1] ==> [1,0,2]\n // E.g.: [1,2,3] -> [2,1,3,4] ==> [1,2,3,4]\n // E.g.: [1] -> [0,2,3] ==> [1,0,2,3]\n let lastOldEnumValue;\n let rightestPosition = -1;\n for (let oldIndex = 0; oldIndex < enumVals.length; oldIndex++) {\n const enumVal = enumVals[oldIndex];\n const newIdx = vals.indexOf(enumVal);\n lastOldEnumValue = enumVal;\n\n if (newIdx === -1) {\n continue;\n }\n\n const newValuesBefore = vals.slice(0, newIdx);\n const promisesLength = promises.length;\n // we go in reverse order so we could stop when we meet old value\n for (let reverseIdx = newValuesBefore.length - 1; reverseIdx >= 0; reverseIdx--) {\n if (~enumVals.indexOf(newValuesBefore[reverseIdx])) {\n break;\n }\n\n addEnumValue(field, newValuesBefore[reverseIdx], lastOldEnumValue, 'before', promisesLength);\n }\n\n // we detect the most 'right' position of old value in new enum array so we can append new values to it\n if (newIdx > rightestPosition) {\n rightestPosition = newIdx;\n }\n }\n\n if (lastOldEnumValue && rightestPosition < vals.length - 1) {\n const remainingEnumValues = vals.slice(rightestPosition + 1);\n for (let reverseIdx = remainingEnumValues.length - 1; reverseIdx >= 0; reverseIdx--) {\n addEnumValue(field, remainingEnumValues[reverseIdx], lastOldEnumValue, 'after');\n }\n }\n\n enumIdx++;\n }\n }\n }\n\n const result = await promises\n .reduce(async (promise, asyncFunction) => await asyncFunction(await promise), Promise.resolve());\n\n // If ENUM processed, then refresh OIDs\n if (promises.length) {\n await this.sequelize.dialect.connectionManager._refreshDynamicOIDs();\n }\n return result;\n }\n\n /**\n * @override\n */\n async getForeignKeyReferencesForTable(table, options) {\n const queryOptions = {\n ...options,\n type: QueryTypes.FOREIGNKEYS\n };\n\n // postgres needs some special treatment as those field names returned are all lowercase\n // in order to keep same result with other dialects.\n const query = this.queryGenerator.getForeignKeyReferencesQuery(table.tableName || table, this.sequelize.config.database, table.schema);\n const result = await this.sequelize.query(query, queryOptions);\n\n return result.map(fkMeta => {\n const { initiallyDeferred, isDeferrable, ...remaining } = Utils.camelizeObjectKeys(fkMeta);\n\n return {\n ...remaining,\n deferrable: isDeferrable === 'NO' ? Deferrable.NOT\n : initiallyDeferred === 'NO' ? Deferrable.INITIALLY_IMMEDIATE\n : Deferrable.INITIALLY_DEFERRED\n };\n });\n }\n\n /**\n * Drop specified enum from database (Postgres only)\n *\n * @param {string} [enumName] Enum name to drop\n * @param {object} options Query options\n *\n * @returns {Promise}\n */\n async dropEnum(enumName, options) {\n options = options || {};\n\n return this.sequelize.query(\n this.queryGenerator.pgEnumDrop(null, null, this.queryGenerator.pgEscapeAndQuote(enumName)),\n { ...options, raw: true }\n );\n }\n\n /**\n * Drop all enums from database (Postgres only)\n *\n * @param {object} options Query options\n *\n * @returns {Promise}\n */\n async dropAllEnums(options) {\n options = options || {};\n\n const enums = await this.pgListEnums(null, options);\n\n return await Promise.all(enums.map(result => this.sequelize.query(\n this.queryGenerator.pgEnumDrop(null, null, this.queryGenerator.pgEscapeAndQuote(result.enum_name)),\n { ...options, raw: true }\n )));\n }\n\n /**\n * List all enums (Postgres only)\n *\n * @param {string} [tableName] Table whose enum to list\n * @param {object} [options] Query options\n *\n * @returns {Promise}\n */\n async pgListEnums(tableName, options) {\n options = options || {};\n const sql = this.queryGenerator.pgListEnums(tableName);\n return this.sequelize.query(sql, { ...options, plain: false, raw: true, type: QueryTypes.SELECT });\n }\n\n /**\n * Since postgres has a special case for enums, we should drop the related\n * enum type within the table and attribute\n *\n * @override\n */\n async dropTable(tableName, options) {\n await super.dropTable(tableName, options);\n const promises = [];\n const instanceTable = this.sequelize.modelManager.getModel(tableName, { attribute: 'tableName' });\n\n if (!instanceTable) {\n // Do nothing when model is not available\n return;\n }\n\n const getTableName = (!options || !options.schema || options.schema === 'public' ? '' : `${options.schema}_`) + tableName;\n\n const keys = Object.keys(instanceTable.rawAttributes);\n const keyLen = keys.length;\n\n for (let i = 0; i < keyLen; i++) {\n if (instanceTable.rawAttributes[keys[i]].type instanceof DataTypes.ENUM) {\n const sql = this.queryGenerator.pgEnumDrop(getTableName, keys[i]);\n options.supportsSearchPath = false;\n promises.push(this.sequelize.query(sql, { ...options, raw: true }));\n }\n }\n\n await Promise.all(promises);\n }\n}\n\nexports.PostgresQueryInterface = PostgresQueryInterface;\n"], "mappings": "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", "names": [] }