lib/dialects/snowflake/query-generator.js
- "use strict";
- var __defProp = Object.defineProperty;
- var __defProps = Object.defineProperties;
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
- 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 __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
- const _ = require("lodash");
- const Utils = require("../../utils");
- const AbstractQueryGenerator = require("../abstract/query-generator");
- const util = require("util");
- const Op = require("../../operators");
- 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;
- const FOREIGN_KEY_FIELDS = [
- "CONSTRAINT_NAME as constraint_name",
- "CONSTRAINT_NAME as constraintName",
- "CONSTRAINT_SCHEMA as constraintSchema",
- "CONSTRAINT_SCHEMA as constraintCatalog",
- "TABLE_NAME as tableName",
- "TABLE_SCHEMA as tableSchema",
- "TABLE_SCHEMA as tableCatalog",
- "COLUMN_NAME as columnName",
- "REFERENCED_TABLE_SCHEMA as referencedTableSchema",
- "REFERENCED_TABLE_SCHEMA as referencedTableCatalog",
- "REFERENCED_TABLE_NAME as referencedTableName",
- "REFERENCED_COLUMN_NAME as referencedColumnName"
- ].join(",");
- const SNOWFLAKE_RESERVED_WORDS = "account,all,alter,and,any,as,between,by,case,cast,check,column,connect,connections,constraint,create,cross,current,current_date,current_time,current_timestamp,current_user,database,delete,distinct,drop,else,exists,false,following,for,from,full,grant,group,gscluster,having,ilike,in,increment,inner,insert,intersect,into,is,issue,join,lateral,left,like,localtime,localtimestamp,minus,natural,not,null,of,on,or,order,organization,qualify,regexp,revoke,right,rlike,row,rows,sample,schema,select,set,some,start,table,tablesample,then,to,trigger,true,try_cast,union,unique,update,using,values,view,when,whenever,where,with".split(",");
- const typeWithoutDefault = /* @__PURE__ */ new Set(["BLOB", "TEXT", "GEOMETRY", "JSON"]);
- class SnowflakeQueryGenerator extends AbstractQueryGenerator {
- constructor(options) {
- super(options);
- this.OperatorMap = __spreadProps(__spreadValues({}, this.OperatorMap), {
- [Op.regexp]: "REGEXP",
- [Op.notRegexp]: "NOT REGEXP"
- });
- }
- createDatabaseQuery(databaseName, options) {
- options = __spreadValues({
- charset: null,
- collate: null
- }, options);
- return Utils.joinSQLFragments([
- "CREATE DATABASE IF NOT EXISTS",
- this.quoteIdentifier(databaseName),
- options.charset && `DEFAULT CHARACTER SET ${this.escape(options.charset)}`,
- options.collate && `DEFAULT COLLATE ${this.escape(options.collate)}`,
- ";"
- ]);
- }
- dropDatabaseQuery(databaseName) {
- return `DROP DATABASE IF EXISTS ${this.quoteIdentifier(databaseName)};`;
- }
- createSchema() {
- return "SHOW TABLES";
- }
- showSchemasQuery() {
- return "SHOW TABLES";
- }
- versionQuery() {
- return "SELECT CURRENT_VERSION()";
- }
- createTableQuery(tableName, attributes, options) {
- options = __spreadValues({
- charset: null,
- rowFormat: null
- }, options);
- const primaryKeys = [];
- const foreignKeys = {};
- const attrStr = [];
- for (const attr in attributes) {
- if (!Object.prototype.hasOwnProperty.call(attributes, attr))
- continue;
- const dataType = attributes[attr];
- let match;
- if (dataType.includes("PRIMARY KEY")) {
- primaryKeys.push(attr);
- if (dataType.includes("REFERENCES")) {
- match = dataType.match(/^(.+) (REFERENCES.*)$/);
- attrStr.push(`${this.quoteIdentifier(attr)} ${match[1].replace("PRIMARY KEY", "")}`);
- foreignKeys[attr] = match[2];
- } else {
- attrStr.push(`${this.quoteIdentifier(attr)} ${dataType.replace("PRIMARY KEY", "")}`);
- }
- } else if (dataType.includes("REFERENCES")) {
- match = dataType.match(/^(.+) (REFERENCES.*)$/);
- attrStr.push(`${this.quoteIdentifier(attr)} ${match[1]}`);
- foreignKeys[attr] = match[2];
- } else {
- attrStr.push(`${this.quoteIdentifier(attr)} ${dataType}`);
- }
- }
- const table = this.quoteTable(tableName);
- let attributesClause = attrStr.join(", ");
- const pkString = primaryKeys.map((pk) => this.quoteIdentifier(pk)).join(", ");
- if (options.uniqueKeys) {
- _.each(options.uniqueKeys, (columns, indexName) => {
- if (columns.customIndex) {
- if (typeof indexName !== "string") {
- indexName = `uniq_${tableName}_${columns.fields.join("_")}`;
- }
- attributesClause += `, UNIQUE ${this.quoteIdentifier(indexName)} (${columns.fields.map((field) => this.quoteIdentifier(field)).join(", ")})`;
- }
- });
- }
- if (pkString.length > 0) {
- attributesClause += `, PRIMARY KEY (${pkString})`;
- }
- for (const fkey in foreignKeys) {
- if (Object.prototype.hasOwnProperty.call(foreignKeys, fkey)) {
- attributesClause += `, FOREIGN KEY (${this.quoteIdentifier(fkey)}) ${foreignKeys[fkey]}`;
- }
- }
- return Utils.joinSQLFragments([
- "CREATE TABLE IF NOT EXISTS",
- table,
- `(${attributesClause})`,
- options.comment && typeof options.comment === "string" && `COMMENT ${this.escape(options.comment)}`,
- options.charset && `DEFAULT CHARSET=${options.charset}`,
- options.collate && `COLLATE ${options.collate}`,
- options.rowFormat && `ROW_FORMAT=${options.rowFormat}`,
- ";"
- ]);
- }
- describeTableQuery(tableName, schema, schemaDelimiter) {
- const table = this.quoteTable(this.addSchema({
- tableName,
- _schema: schema,
- _schemaDelimiter: schemaDelimiter
- }));
- return `SHOW FULL COLUMNS FROM ${table};`;
- }
- showTablesQuery(database) {
- return Utils.joinSQLFragments([
- "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'",
- database ? `AND TABLE_SCHEMA = ${this.escape(database)}` : "AND TABLE_SCHEMA NOT IN ( 'INFORMATION_SCHEMA', 'PERFORMANCE_SCHEMA', 'SYS')",
- ";"
- ]);
- }
- addColumnQuery(table, key, dataType) {
- return Utils.joinSQLFragments([
- "ALTER TABLE",
- this.quoteTable(table),
- "ADD",
- this.quoteIdentifier(key),
- this.attributeToSQL(dataType, {
- context: "addColumn",
- tableName: table,
- foreignKey: key
- }),
- ";"
- ]);
- }
- removeColumnQuery(tableName, attributeName) {
- return Utils.joinSQLFragments([
- "ALTER TABLE",
- this.quoteTable(tableName),
- "DROP",
- this.quoteIdentifier(attributeName),
- ";"
- ]);
- }
- changeColumnQuery(tableName, attributes) {
- const query = (...subQuerys) => Utils.joinSQLFragments([
- "ALTER TABLE",
- this.quoteTable(tableName),
- "ALTER COLUMN",
- ...subQuerys,
- ";"
- ]);
- const sql = [];
- for (const attributeName in attributes) {
- let definition = this.dataTypeMapping(tableName, attributeName, attributes[attributeName]);
- const attrSql = [];
- if (definition.includes("NOT NULL")) {
- attrSql.push(query(this.quoteIdentifier(attributeName), "SET NOT NULL"));
- definition = definition.replace("NOT NULL", "").trim();
- } else if (!definition.includes("REFERENCES")) {
- attrSql.push(query(this.quoteIdentifier(attributeName), "DROP NOT NULL"));
- }
- if (definition.includes("DEFAULT")) {
- attrSql.push(query(this.quoteIdentifier(attributeName), "SET DEFAULT", definition.match(/DEFAULT ([^;]+)/)[1]));
- definition = definition.replace(/(DEFAULT[^;]+)/, "").trim();
- } else if (!definition.includes("REFERENCES")) {
- attrSql.push(query(this.quoteIdentifier(attributeName), "DROP DEFAULT"));
- }
- if (definition.match(/UNIQUE;*$/)) {
- definition = definition.replace(/UNIQUE;*$/, "");
- attrSql.push(query("ADD UNIQUE (", this.quoteIdentifier(attributeName), ")").replace("ALTER COLUMN", ""));
- }
- if (definition.includes("REFERENCES")) {
- definition = definition.replace(/.+?(?=REFERENCES)/, "");
- attrSql.push(query("ADD FOREIGN KEY (", this.quoteIdentifier(attributeName), ")", definition).replace("ALTER COLUMN", ""));
- } else {
- attrSql.push(query(this.quoteIdentifier(attributeName), "TYPE", definition));
- }
- sql.push(attrSql.join(""));
- }
- return sql.join("");
- }
- renameColumnQuery(tableName, attrBefore, attributes) {
- const attrString = [];
- for (const attrName in attributes) {
- const definition = attributes[attrName];
- attrString.push(`'${attrBefore}' '${attrName}' ${definition}`);
- }
- return Utils.joinSQLFragments([
- "ALTER TABLE",
- this.quoteTable(tableName),
- "RENAME COLUMN",
- attrString.join(" to "),
- ";"
- ]);
- }
- handleSequelizeMethod(attr, tableName, factory, options, prepend) {
- if (attr instanceof Utils.Json) {
- if (attr.conditions) {
- const conditions = this.parseConditionObject(attr.conditions).map((condition) => `${this.jsonPathExtractionQuery(condition.path[0], _.tail(condition.path))} = '${condition.value}'`);
- return conditions.join(" AND ");
- }
- if (attr.path) {
- let str;
- if (this._checkValidJsonStatement(attr.path)) {
- str = attr.path;
- } else {
- const paths = _.toPath(attr.path);
- const column = paths.shift();
- str = this.jsonPathExtractionQuery(column, paths);
- }
- if (attr.value) {
- str += util.format(" = %s", this.escape(attr.value));
- }
- return str;
- }
- } else if (attr instanceof Utils.Cast) {
- if (/timestamp/i.test(attr.type)) {
- attr.type = "datetime";
- } else if (attr.json && /boolean/i.test(attr.type)) {
- attr.type = "char";
- } else if (/double precision/i.test(attr.type) || /boolean/i.test(attr.type) || /integer/i.test(attr.type)) {
- attr.type = "decimal";
- } else if (/text/i.test(attr.type)) {
- attr.type = "char";
- }
- }
- return super.handleSequelizeMethod(attr, tableName, factory, options, prepend);
- }
- truncateTableQuery(tableName) {
- return Utils.joinSQLFragments([
- "TRUNCATE",
- this.quoteTable(tableName)
- ]);
- }
- 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 (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 Utils.joinSQLFragments([
- "DELETE FROM",
- table,
- "WHERE",
- primaryKeys,
- "IN (SELECT",
- primaryKeysSelection,
- "FROM",
- table,
- whereClause,
- limit,
- ")",
- ";"
- ]);
- }
- return Utils.joinSQLFragments([
- "DELETE FROM",
- table,
- whereClause,
- ";"
- ]);
- }
- showIndexesQuery() {
- return "SELECT '' FROM DUAL";
- }
- showConstraintsQuery(table, constraintName) {
- const tableName = table.tableName || table;
- const schemaName = table.schema;
- return Utils.joinSQLFragments([
- "SELECT CONSTRAINT_CATALOG AS constraintCatalog,",
- "CONSTRAINT_NAME AS constraintName,",
- "CONSTRAINT_SCHEMA AS constraintSchema,",
- "CONSTRAINT_TYPE AS constraintType,",
- "TABLE_NAME AS tableName,",
- "TABLE_SCHEMA AS tableSchema",
- "from INFORMATION_SCHEMA.TABLE_CONSTRAINTS",
- `WHERE table_name='${tableName}'`,
- constraintName && `AND constraint_name = '${constraintName}'`,
- schemaName && `AND TABLE_SCHEMA = '${schemaName}'`,
- ";"
- ]);
- }
- removeIndexQuery(tableName, indexNameOrAttributes) {
- let indexName = indexNameOrAttributes;
- if (typeof indexName !== "string") {
- indexName = Utils.underscore(`${tableName}_${indexNameOrAttributes.join("_")}`);
- }
- return Utils.joinSQLFragments([
- "DROP INDEX",
- this.quoteIdentifier(indexName),
- "ON",
- this.quoteTable(tableName),
- ";"
- ]);
- }
- attributeToSQL(attribute, options) {
- if (!_.isPlainObject(attribute)) {
- attribute = {
- type: attribute
- };
- }
- const attributeString = attribute.type.toString({ escape: this.escape.bind(this) });
- let template = attributeString;
- if (attribute.allowNull === false) {
- template += " NOT NULL";
- }
- if (attribute.autoIncrement) {
- template += " AUTOINCREMENT";
- }
- if (!typeWithoutDefault.has(attributeString) && attribute.type._binary !== true && Utils.defaultValueSchemable(attribute.defaultValue)) {
- template += ` DEFAULT ${this.escape(attribute.defaultValue)}`;
- }
- if (attribute.unique === true) {
- template += " UNIQUE";
- }
- if (attribute.primaryKey) {
- template += " PRIMARY KEY";
- }
- if (attribute.comment) {
- template += ` COMMENT ${this.escape(attribute.comment)}`;
- }
- if (attribute.first) {
- template += " FIRST";
- }
- if (attribute.after) {
- template += ` AFTER ${this.quoteIdentifier(attribute.after)}`;
- }
- if (attribute.references) {
- if (options && options.context === "addColumn" && options.foreignKey) {
- const attrName = this.quoteIdentifier(options.foreignKey);
- const fkName = this.quoteIdentifier(`${options.tableName}_${attrName}_foreign_idx`);
- template += `, ADD CONSTRAINT ${fkName} FOREIGN KEY (${attrName})`;
- }
- 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) {
- template += ` ON DELETE ${attribute.onDelete.toUpperCase()}`;
- }
- if (attribute.onUpdate) {
- template += ` ON UPDATE ${attribute.onUpdate.toUpperCase()}`;
- }
- }
- return template;
- }
- attributesToSQL(attributes, options) {
- const result = {};
- for (const key in attributes) {
- const attribute = attributes[key];
- result[attribute.field || key] = this.attributeToSQL(attribute, options);
- }
- return result;
- }
- _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;
- }
- 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", "");
- }
- return dataType;
- }
- getForeignKeysQuery(table, schemaName) {
- const tableName = table.tableName || table;
- return Utils.joinSQLFragments([
- "SELECT",
- FOREIGN_KEY_FIELDS,
- `FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE where TABLE_NAME = '${tableName}'`,
- `AND CONSTRAINT_NAME!='PRIMARY' AND CONSTRAINT_SCHEMA='${schemaName}'`,
- "AND REFERENCED_TABLE_NAME IS NOT NULL",
- ";"
- ]);
- }
- getForeignKeyQuery(table, columnName) {
- const quotedSchemaName = table.schema ? wrapSingleQuote(table.schema) : "";
- const quotedTableName = wrapSingleQuote(table.tableName || table);
- const quotedColumnName = wrapSingleQuote(columnName);
- return Utils.joinSQLFragments([
- "SELECT",
- FOREIGN_KEY_FIELDS,
- "FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE",
- "WHERE (",
- [
- `REFERENCED_TABLE_NAME = ${quotedTableName}`,
- table.schema && `AND REFERENCED_TABLE_SCHEMA = ${quotedSchemaName}`,
- `AND REFERENCED_COLUMN_NAME = ${quotedColumnName}`
- ],
- ") OR (",
- [
- `TABLE_NAME = ${quotedTableName}`,
- table.schema && `AND TABLE_SCHEMA = ${quotedSchemaName}`,
- `AND COLUMN_NAME = ${quotedColumnName}`,
- "AND REFERENCED_TABLE_NAME IS NOT NULL"
- ],
- ")"
- ]);
- }
- dropForeignKeyQuery(tableName, foreignKey) {
- return Utils.joinSQLFragments([
- "ALTER TABLE",
- this.quoteTable(tableName),
- "DROP FOREIGN KEY",
- this.quoteIdentifier(foreignKey),
- ";"
- ]);
- }
- addLimitAndOffset(options) {
- let fragment = [];
- if (options.offset !== null && options.offset !== void 0 && options.offset !== 0) {
- fragment = fragment.concat([" LIMIT ", this.escape(options.limit), " OFFSET ", this.escape(options.offset)]);
- } else if (options.limit !== null && options.limit !== void 0) {
- fragment = [" LIMIT ", this.escape(options.limit)];
- }
- return fragment.join("");
- }
- 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("->") || SNOWFLAKE_RESERVED_WORDS.includes(rawIdentifier.toLowerCase())) {
- return Utils.addTicks(rawIdentifier, '"');
- }
- return rawIdentifier;
- }
- }
- function wrapSingleQuote(identifier) {
- return Utils.addTicks(identifier, "'");
- }
- module.exports = SnowflakeQueryGenerator;
- //# sourceMappingURL=query-generator.js.map