"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var query_generator_typescript_exports = {};
__export(query_generator_typescript_exports, {
  AbstractQueryGeneratorTypeScript: () => AbstractQueryGeneratorTypeScript,
  CREATE_DATABASE_QUERY_SUPPORTABLE_OPTIONS: () => CREATE_DATABASE_QUERY_SUPPORTABLE_OPTIONS,
  CREATE_SCHEMA_QUERY_SUPPORTABLE_OPTIONS: () => CREATE_SCHEMA_QUERY_SUPPORTABLE_OPTIONS,
  DROP_SCHEMA_QUERY_SUPPORTABLE_OPTIONS: () => DROP_SCHEMA_QUERY_SUPPORTABLE_OPTIONS,
  DROP_TABLE_QUERY_SUPPORTABLE_OPTIONS: () => DROP_TABLE_QUERY_SUPPORTABLE_OPTIONS,
  LIST_DATABASES_QUERY_SUPPORTABLE_OPTIONS: () => LIST_DATABASES_QUERY_SUPPORTABLE_OPTIONS,
  LIST_TABLES_QUERY_SUPPORTABLE_OPTIONS: () => LIST_TABLES_QUERY_SUPPORTABLE_OPTIONS,
  QUOTE_TABLE_SUPPORTABLE_OPTIONS: () => QUOTE_TABLE_SUPPORTABLE_OPTIONS,
  REMOVE_COLUMN_QUERY_SUPPORTABLE_OPTIONS: () => REMOVE_COLUMN_QUERY_SUPPORTABLE_OPTIONS,
  REMOVE_CONSTRAINT_QUERY_SUPPORTABLE_OPTIONS: () => REMOVE_CONSTRAINT_QUERY_SUPPORTABLE_OPTIONS,
  REMOVE_INDEX_QUERY_SUPPORTABLE_OPTIONS: () => REMOVE_INDEX_QUERY_SUPPORTABLE_OPTIONS,
  RENAME_TABLE_QUERY_SUPPORTABLE_OPTIONS: () => RENAME_TABLE_QUERY_SUPPORTABLE_OPTIONS,
  SHOW_CONSTRAINTS_QUERY_SUPPORTABLE_OPTIONS: () => SHOW_CONSTRAINTS_QUERY_SUPPORTABLE_OPTIONS,
  START_TRANSACTION_QUERY_SUPPORTABLE_OPTIONS: () => START_TRANSACTION_QUERY_SUPPORTABLE_OPTIONS,
  TRUNCATE_TABLE_QUERY_SUPPORTABLE_OPTIONS: () => TRUNCATE_TABLE_QUERY_SUPPORTABLE_OPTIONS
});
module.exports = __toCommonJS(query_generator_typescript_exports);
var import_utils = require("@sequelize/utils");
var import_isObject = __toESM(require("lodash/isObject"));
var import_node_crypto = require("node:crypto");
var import_node_util = __toESM(require("node:util"));
var import_deferrable = require("../deferrable.js");
var import_association_path = require("../expression-builders/association-path.js");
var import_attribute = require("../expression-builders/attribute.js");
var import_base_sql_expression = require("../expression-builders/base-sql-expression.js");
var import_cast = require("../expression-builders/cast.js");
var import_col = require("../expression-builders/col.js");
var import_dialect_aware_fn = require("../expression-builders/dialect-aware-fn.js");
var import_fn = require("../expression-builders/fn.js");
var import_identifier = require("../expression-builders/identifier.js");
var import_json_path = require("../expression-builders/json-path.js");
var import_list = require("../expression-builders/list.js");
var import_literal = require("../expression-builders/literal.js");
var import_value = require("../expression-builders/value.js");
var import_where = require("../expression-builders/where.js");
var import_index_hints = require("../index-hints.js");
var import_operators = require("../operators.js");
var import_sql_string = require("../sql-string.js");
var import_table_hints = require("../table-hints.js");
var import_check = require("../utils/check.js");
var import_deprecations = require("../utils/deprecations.js");
var import_dialect = require("../utils/dialect.js");
var import_join_sql_fragments = require("../utils/join-sql-fragments.js");
var import_model_utils = require("../utils/model-utils.js");
var import_data_types = require("./data-types.js");
var import_query_generator_internal = require("./query-generator-internal.js");
var import_where_sql_builder = require("./where-sql-builder.js");
const CREATE_DATABASE_QUERY_SUPPORTABLE_OPTIONS = /* @__PURE__ */ new Set([
  "charset",
  "collate",
  "ctype",
  "encoding",
  "template"
]);
const CREATE_SCHEMA_QUERY_SUPPORTABLE_OPTIONS = /* @__PURE__ */ new Set([
  "authorization",
  "charset",
  "collate",
  "comment",
  "ifNotExists",
  "replace"
]);
const DROP_SCHEMA_QUERY_SUPPORTABLE_OPTIONS = /* @__PURE__ */ new Set([
  "cascade",
  "ifExists"
]);
const DROP_TABLE_QUERY_SUPPORTABLE_OPTIONS = /* @__PURE__ */ new Set([
  "cascade"
]);
const LIST_DATABASES_QUERY_SUPPORTABLE_OPTIONS = /* @__PURE__ */ new Set([
  "skip"
]);
const LIST_TABLES_QUERY_SUPPORTABLE_OPTIONS = /* @__PURE__ */ new Set([
  "schema"
]);
const QUOTE_TABLE_SUPPORTABLE_OPTIONS = /* @__PURE__ */ new Set([
  "indexHints",
  "tableHints"
]);
const REMOVE_COLUMN_QUERY_SUPPORTABLE_OPTIONS = /* @__PURE__ */ new Set([
  "ifExists",
  "cascade"
]);
const REMOVE_CONSTRAINT_QUERY_SUPPORTABLE_OPTIONS = /* @__PURE__ */ new Set(["ifExists", "cascade"]);
const REMOVE_INDEX_QUERY_SUPPORTABLE_OPTIONS = /* @__PURE__ */ new Set([
  "concurrently",
  "ifExists",
  "cascade"
]);
const RENAME_TABLE_QUERY_SUPPORTABLE_OPTIONS = /* @__PURE__ */ new Set([
  "changeSchema"
]);
const SHOW_CONSTRAINTS_QUERY_SUPPORTABLE_OPTIONS = /* @__PURE__ */ new Set(["columnName", "constraintName", "constraintType"]);
const START_TRANSACTION_QUERY_SUPPORTABLE_OPTIONS = /* @__PURE__ */ new Set(["readOnly", "transactionType"]);
const TRUNCATE_TABLE_QUERY_SUPPORTABLE_OPTIONS = /* @__PURE__ */ new Set([
  "cascade",
  "restartIdentity"
]);
class AbstractQueryGeneratorTypeScript {
  dialect;
  #internals;
  constructor(dialect, internals = new import_query_generator_internal.AbstractQueryGeneratorInternal(dialect)) {
    this.dialect = dialect;
    this.#internals = internals;
  }
  get #whereGenerator() {
    return this.#internals.whereSqlBuilder;
  }
  get sequelize() {
    return this.dialect.sequelize;
  }
  get options() {
    return this.sequelize.options;
  }
  createDatabaseQuery(_database, _options) {
    if (this.dialect.supports.multiDatabases) {
      throw new Error(
        `${this.dialect.name} declares supporting databases but createDatabaseQuery is not implemented.`
      );
    }
    throw new Error(`Databases are not supported in ${this.dialect.name}.`);
  }
  dropDatabaseQuery(database) {
    if (this.dialect.supports.multiDatabases) {
      return `DROP DATABASE IF EXISTS ${this.quoteIdentifier(database)}`;
    }
    throw new Error(`Databases are not supported in ${this.dialect.name}.`);
  }
  listDatabasesQuery(_options) {
    if (this.dialect.supports.multiDatabases) {
      throw new Error(
        `${this.dialect.name} declares supporting databases but listDatabasesQuery is not implemented.`
      );
    }
    throw new Error(`Databases are not supported in ${this.dialect.name}.`);
  }
  createSchemaQuery(schemaName, options) {
    if (!this.dialect.supports.schemas) {
      throw new Error(`Schemas are not supported in ${this.dialect.name}.`);
    }
    if (options) {
      (0, import_check.rejectInvalidOptions)(
        "createSchemaQuery",
        this.dialect,
        CREATE_SCHEMA_QUERY_SUPPORTABLE_OPTIONS,
        this.dialect.supports.createSchema,
        options
      );
    }
    return (0, import_join_sql_fragments.joinSQLFragments)([
      "CREATE",
      options?.replace ? "OR REPLACE" : "",
      "SCHEMA",
      options?.ifNotExists ? "IF NOT EXISTS" : "",
      this.quoteIdentifier(schemaName),
      options?.authorization ? `AUTHORIZATION ${options.authorization instanceof import_literal.Literal ? this.#internals.formatLiteral(options.authorization) : this.quoteIdentifier(options.authorization)}` : "",
      options?.charset ? `DEFAULT CHARACTER SET ${this.escape(options.charset)}` : "",
      options?.collate ? `DEFAULT COLLATE ${this.escape(options.collate)}` : "",
      options?.comment ? `COMMENT ${this.escape(options.comment)}` : ""
    ]);
  }
  dropSchemaQuery(schemaName, options) {
    if (!this.dialect.supports.schemas) {
      throw new Error(`Schemas are not supported in ${this.dialect.name}.`);
    }
    if (options) {
      (0, import_check.rejectInvalidOptions)(
        "dropSchemaQuery",
        this.dialect,
        DROP_SCHEMA_QUERY_SUPPORTABLE_OPTIONS,
        this.dialect.supports.dropSchema,
        options
      );
    }
    return (0, import_join_sql_fragments.joinSQLFragments)([
      "DROP SCHEMA",
      options?.ifExists ? "IF EXISTS" : "",
      this.quoteIdentifier(schemaName),
      options?.cascade ? "CASCADE" : ""
    ]);
  }
  listSchemasQuery(_options) {
    if (this.dialect.supports.schemas) {
      throw new Error(
        `${this.dialect.name} declares supporting schema but listSchemasQuery is not implemented.`
      );
    }
    throw new Error(`Schemas are not supported in ${this.dialect.name}.`);
  }
  describeTableQuery(tableName) {
    return `DESCRIBE ${this.quoteTable(tableName)};`;
  }
  dropTableQuery(tableName, options) {
    if (options) {
      (0, import_check.rejectInvalidOptions)(
        "dropTableQuery",
        this.dialect,
        DROP_TABLE_QUERY_SUPPORTABLE_OPTIONS,
        this.dialect.supports.dropTable,
        options
      );
    }
    return (0, import_join_sql_fragments.joinSQLFragments)([
      "DROP TABLE IF EXISTS",
      this.quoteTable(tableName),
      options?.cascade ? "CASCADE" : ""
    ]);
  }
  listTablesQuery(_options) {
    throw new Error(`listTablesQuery has not been implemented in ${this.dialect.name}.`);
  }
  renameTableQuery(beforeTableName, afterTableName, options) {
    const beforeTable = this.extractTableDetails(beforeTableName);
    const afterTable = this.extractTableDetails(afterTableName);
    if (beforeTable.schema !== afterTable.schema && !options?.changeSchema) {
      throw new Error(
        "To move a table between schemas, you must set `options.changeSchema` to true."
      );
    }
    return `ALTER TABLE ${this.quoteTable(beforeTableName)} RENAME TO ${this.quoteTable(afterTableName)}`;
  }
  truncateTableQuery(_tableName, _options) {
    throw new Error(`truncateTableQuery has not been implemented in ${this.dialect.name}.`);
  }
  removeColumnQuery(tableName, columnName, options) {
    if (options) {
      (0, import_check.rejectInvalidOptions)(
        "removeColumnQuery",
        this.dialect,
        REMOVE_COLUMN_QUERY_SUPPORTABLE_OPTIONS,
        this.dialect.supports.removeColumn,
        options
      );
    }
    return (0, import_join_sql_fragments.joinSQLFragments)([
      "ALTER TABLE",
      this.quoteTable(tableName),
      "DROP COLUMN",
      options?.ifExists ? "IF EXISTS" : "",
      this.quoteIdentifier(columnName),
      options?.cascade ? "CASCADE" : ""
    ]);
  }
  addConstraintQuery(tableName, options) {
    if (!this.dialect.supports.constraints.add) {
      throw new Error(`Add constraint queries are not supported by ${this.dialect.name} dialect`);
    }
    return (0, import_join_sql_fragments.joinSQLFragments)([
      "ALTER TABLE",
      this.quoteTable(tableName),
      "ADD",
      this.#internals.getConstraintSnippet(tableName, options)
    ]);
  }
  removeConstraintQuery(tableName, constraintName, options) {
    if (!this.dialect.supports.constraints.remove) {
      throw new Error(
        `Remove constraint queries are not supported by ${this.dialect.name} dialect`
      );
    }
    if (options) {
      (0, import_check.rejectInvalidOptions)(
        "removeConstraintQuery",
        this.dialect,
        REMOVE_CONSTRAINT_QUERY_SUPPORTABLE_OPTIONS,
        this.dialect.supports.constraints.removeOptions,
        options
      );
    }
    return (0, import_join_sql_fragments.joinSQLFragments)([
      "ALTER TABLE",
      this.quoteTable(tableName),
      "DROP CONSTRAINT",
      options?.ifExists ? "IF EXISTS" : "",
      this.quoteIdentifier(constraintName),
      options?.cascade ? "CASCADE" : ""
    ]);
  }
  setConstraintCheckingQuery(type, constraints) {
    if (!this.dialect.supports.constraints.deferrable) {
      throw new Error(`Deferrable constraints are not supported by ${this.dialect.name} dialect`);
    }
    let constraintFragment = "ALL";
    if (type instanceof import_deferrable.ConstraintChecking) {
      if (type.constraints?.length) {
        constraintFragment = type.constraints.map((constraint) => this.quoteIdentifier(constraint)).join(", ");
      }
      return `SET CONSTRAINTS ${constraintFragment} ${type.toString()}`;
    }
    if (constraints?.length) {
      constraintFragment = constraints.map((constraint) => this.quoteIdentifier(constraint)).join(", ");
    }
    return `SET CONSTRAINTS ${constraintFragment} ${type.toString()}`;
  }
  showConstraintsQuery(_tableName, _options) {
    throw new Error(`showConstraintsQuery has not been implemented in ${this.dialect.name}.`);
  }
  showIndexesQuery(_tableName) {
    throw new Error(`showIndexesQuery has not been implemented in ${this.dialect.name}.`);
  }
  removeIndexQuery(_tableName, _indexNameOrAttributes, _options) {
    throw new Error(`removeIndexQuery has not been implemented in ${this.dialect.name}.`);
  }
  /**
   * Generates an SQL query that returns all foreign keys of a table or the foreign key constraint of a given column.
   *
   * @deprecated Use {@link showConstraintsQuery} instead.
   * @param _tableName The table or associated model.
   * @param _columnName The name of the column. Not supported by SQLite.
   * @returns The generated SQL query.
   */
  getForeignKeyQuery(_tableName, _columnName) {
    throw new Error(`getForeignKeyQuery has been deprecated. Use showConstraintsQuery instead.`);
  }
  /**
   * Generates an SQL query that drops a foreign key constraint.
   *
   * @deprecated Use {@link removeConstraintQuery} instead.
   * @param _tableName The table or associated model.
   * @param _foreignKey The name of the foreign key constraint.
   */
  dropForeignKeyQuery(_tableName, _foreignKey) {
    throw new Error(`dropForeignKeyQuery has been deprecated. Use removeConstraintQuery instead.`);
  }
  /**
   * Returns a query that commits a transaction.
   */
  commitTransactionQuery() {
    if (this.dialect.supports.connectionTransactionMethods) {
      throw new Error(
        `commitTransactionQuery is not supported by the ${this.dialect.name} dialect.`
      );
    }
    return "COMMIT";
  }
  /**
   * Returns a query that creates a savepoint.
   *
   * @param savepointName
   */
  createSavepointQuery(savepointName) {
    if (!this.dialect.supports.savepoints) {
      throw new Error(`Savepoints are not supported by ${this.dialect.name}.`);
    }
    return `SAVEPOINT ${this.quoteIdentifier(savepointName)}`;
  }
  /**
   * Returns a query that rollbacks a savepoint.
   *
   * @param savepointName
   */
  rollbackSavepointQuery(savepointName) {
    if (!this.dialect.supports.savepoints) {
      throw new Error(`Savepoints are not supported by ${this.dialect.name}.`);
    }
    return `ROLLBACK TO SAVEPOINT ${this.quoteIdentifier(savepointName)}`;
  }
  /**
   * Returns a query that rollbacks a transaction.
   */
  rollbackTransactionQuery() {
    if (this.dialect.supports.connectionTransactionMethods) {
      throw new Error(
        `rollbackTransactionQuery is not supported by the ${this.dialect.name} dialect.`
      );
    }
    return "ROLLBACK";
  }
  /**
   * Returns a query that sets the transaction isolation level.
   *
   * @param isolationLevel
   */
  setIsolationLevelQuery(isolationLevel) {
    if (!this.dialect.supports.isolationLevels) {
      throw new Error(`Isolation levels are not supported by ${this.dialect.name}.`);
    }
    if (!this.dialect.supports.connectionTransactionMethods) {
      return `SET TRANSACTION ISOLATION LEVEL ${isolationLevel}`;
    }
    throw new Error(`setIsolationLevelQuery is not supported by the ${this.dialect.name} dialect.`);
  }
  /**
   * Returns a query that starts a transaction.
   *
   * @param options
   */
  startTransactionQuery(options) {
    if (this.dialect.supports.connectionTransactionMethods) {
      throw new Error(
        `startTransactionQuery is not supported by the ${this.dialect.name} dialect.`
      );
    }
    if (options) {
      (0, import_check.rejectInvalidOptions)(
        "startTransactionQuery",
        this.dialect,
        START_TRANSACTION_QUERY_SUPPORTABLE_OPTIONS,
        this.dialect.supports.startTransaction,
        options
      );
    }
    return (0, import_join_sql_fragments.joinSQLFragments)([
      this.dialect.supports.startTransaction.useBegin ? "BEGIN" : "START",
      "TRANSACTION",
      options?.readOnly ? "READ ONLY" : ""
    ]);
  }
  /**
   * Generates a unique identifier for the current transaction.
   */
  generateTransactionId() {
    return (0, import_node_crypto.randomUUID)();
  }
  // TODO: rename to "normalizeTable" & move to sequelize class
  extractTableDetails(tableOrModel, options) {
    const tableIdentifier = (0, import_model_utils.extractTableIdentifier)(tableOrModel);
    if (!(0, import_utils.isPlainObject)(tableIdentifier)) {
      throw new Error(
        `Invalid input received, got ${import_node_util.default.inspect(tableOrModel)}, expected a Model Class, a TableNameWithSchema object, or a table name string`
      );
    }
    return {
      ...tableIdentifier,
      schema: options?.schema || tableIdentifier.schema || this.options.schema || this.dialect.getDefaultSchema(),
      delimiter: options?.delimiter || tableIdentifier.delimiter || "."
    };
  }
  /**
   * Quote table name with optional alias and schema attribution
   *
   * @param param table string or object
   * @param options options
   */
  quoteTable(param, options) {
    if (options) {
      (0, import_check.rejectInvalidOptions)(
        "quoteTable",
        this.dialect,
        QUOTE_TABLE_SUPPORTABLE_OPTIONS,
        {
          indexHints: this.dialect.supports.indexHints,
          tableHints: this.dialect.supports.tableHints
        },
        options
      );
    }
    if ((0, import_model_utils.isModelStatic)(param)) {
      param = param.table;
    }
    const tableName = this.extractTableDetails(param);
    if ((0, import_isObject.default)(param) && ("as" in param || "name" in param)) {
      throw new Error(
        'parameters "as" and "name" are not allowed in the first parameter of quoteTable, pass them as the second parameter.'
      );
    }
    let sql = "";
    if (this.dialect.supports.schemas) {
      if (tableName.schema && tableName.schema !== this.dialect.getDefaultSchema()) {
        sql += `${this.quoteIdentifier(tableName.schema)}.`;
      }
      sql += this.quoteIdentifier(tableName.tableName);
    } else {
      const fakeSchemaPrefix = tableName.schema && tableName.schema !== this.dialect.getDefaultSchema() ? tableName.schema + (tableName.delimiter || ".") : "";
      sql += this.quoteIdentifier(fakeSchemaPrefix + tableName.tableName);
    }
    if (options?.alias) {
      sql += ` AS ${this.quoteIdentifier(options.alias === true ? tableName.tableName : options.alias)}`;
    }
    if (options?.indexHints) {
      for (const hint of options.indexHints) {
        if (import_index_hints.IndexHints[hint.type]) {
          sql += ` ${import_index_hints.IndexHints[hint.type]} INDEX (${hint.values.map((indexName) => this.quoteIdentifier(indexName)).join(",")})`;
        } else {
          throw new Error(
            `The index hint type "${hint.type}" is invalid or not supported by dialect "${this.dialect.name}".`
          );
        }
      }
    }
    if (options?.tableHints) {
      const hints = [];
      for (const hint of options.tableHints) {
        if (import_table_hints.TableHints[hint]) {
          hints.push(import_table_hints.TableHints[hint]);
        } else {
          throw new Error(
            `The table hint "${hint}" is invalid or not supported by dialect "${this.dialect.name}".`
          );
        }
      }
      if (hints.length) {
        sql += ` WITH (${hints.join(", ")})`;
      }
    }
    return sql;
  }
  /**
   * Adds quotes to identifier
   *
   * @param identifier
   * @param _force
   */
  // TODO: memoize last result
  quoteIdentifier(identifier, _force) {
    return (0, import_dialect.quoteIdentifier)(identifier, this.dialect.TICK_CHAR_LEFT, this.dialect.TICK_CHAR_RIGHT);
  }
  isSameTable(tableA, tableB) {
    if (tableA === tableB) {
      return true;
    }
    tableA = this.extractTableDetails(tableA);
    tableB = this.extractTableDetails(tableB);
    return tableA.tableName === tableB.tableName && tableA.schema === tableB.schema;
  }
  whereQuery(where, options) {
    const query = this.whereItemsQuery(where, options);
    if (query && query.length > 0) {
      return `WHERE ${query}`;
    }
    return "";
  }
  whereItemsQuery(where, options) {
    return this.#whereGenerator.formatWhereOptions(where, options);
  }
  formatSqlExpression(piece, options) {
    if (piece instanceof import_literal.Literal) {
      return this.#internals.formatLiteral(piece, options);
    }
    if (piece instanceof import_fn.Fn) {
      return this.#internals.formatFn(piece, options);
    }
    if (piece instanceof import_list.List) {
      return this.escapeList(piece.values, options);
    }
    if (piece instanceof import_value.Value) {
      return this.escape(piece.value, options);
    }
    if (piece instanceof import_identifier.Identifier) {
      return piece.values.map((value) => {
        if ((0, import_utils.isString)(value)) {
          return this.quoteIdentifier(value);
        }
        return this.quoteTable(value);
      }).join(".");
    }
    if (piece instanceof import_cast.Cast) {
      return this.#internals.formatCast(piece, options);
    }
    if (piece instanceof import_col.Col) {
      return this.#internals.formatCol(piece, options);
    }
    if (piece instanceof import_attribute.Attribute) {
      return this.#internals.formatAttribute(piece, options);
    }
    if (piece instanceof import_where.Where) {
      if (piece.where instanceof import_where_sql_builder.PojoWhere) {
        return this.#whereGenerator.formatPojoWhere(piece.where, options);
      }
      return this.#whereGenerator.formatWhereOptions(piece.where, options);
    }
    if (piece instanceof import_json_path.JsonPath) {
      return this.#internals.formatJsonPath(piece, options);
    }
    if (piece instanceof import_association_path.AssociationPath) {
      return this.#internals.formatAssociationPath(piece);
    }
    if (piece instanceof import_dialect_aware_fn.DialectAwareFn) {
      return this.#internals.formatDialectAwareFn(piece, options);
    }
    throw new Error(`Unknown sequelize method ${piece.constructor.name}`);
  }
  /**
   * The goal of this method is to execute the equivalent of json_unquote for the current dialect.
   *
   * @param _arg
   * @param _options
   */
  formatUnquoteJson(_arg, _options) {
    if (!this.dialect.supports.jsonOperations) {
      throw new Error(`Unquoting JSON is not supported by ${this.dialect.name} dialect.`);
    }
    throw new Error(`formatUnquoteJson has not been implemented in ${this.dialect.name}.`);
  }
  /**
   * @param _sqlExpression ⚠️ This is not an identifier, it's a raw SQL expression. It will be inlined in the query.
   * @param _path The JSON path, where each item is one level of the path
   * @param _unquote Whether the result should be unquoted (depending on dialect: ->> and #>> operators, json_unquote function). Defaults to `false`.
   */
  jsonPathExtractionQuery(_sqlExpression, _path, _unquote) {
    if (!this.dialect.supports.jsonOperations) {
      throw new Error(`JSON Paths are not supported in ${this.dialect.name}.`);
    }
    throw new Error(`jsonPathExtractionQuery has not been implemented in ${this.dialect.name}.`);
  }
  /**
   * Escapes a value (e.g. a string, number or date) as an SQL value (as opposed to an identifier).
   *
   * @param value The value to escape
   * @param options The options to use when escaping the value
   */
  escape(value, options = import_utils.EMPTY_OBJECT) {
    if ((0, import_utils.isPlainObject)(value) && import_operators.Op.col in value) {
      (0, import_deprecations.noOpCol)();
      value = new import_col.Col(value[import_operators.Op.col]);
    }
    if (value instanceof import_base_sql_expression.BaseSqlExpression) {
      return this.formatSqlExpression(value, options);
    }
    if (value === void 0) {
      throw new TypeError('"undefined" cannot be escaped');
    }
    let { type } = options;
    if (type != null) {
      type = this.sequelize.normalizeDataType(type);
    }
    if (value === null && // we handle null values ourselves by default, unless the data type explicitly accepts null
    (!(type instanceof import_data_types.AbstractDataType) || !type.acceptsNull())) {
      if (options.bindParam) {
        return options.bindParam(null);
      }
      return "NULL";
    }
    if (type == null || typeof type === "string") {
      type = (0, import_sql_string.bestGuessDataTypeOfVal)(value, this.dialect);
    } else {
      type = this.sequelize.normalizeDataType(type);
    }
    this.sequelize.validateValue(value, type);
    if (options.bindParam) {
      return type.getBindParamSql(value, options);
    }
    return type.escape(value);
  }
  /**
   * Escapes an array of values (e.g. strings, numbers or dates) as an SQL List of values.
   *
   * @param values The list of values to escape
   * @param options
   *
   * @example
   * ```ts
   * const values = [1, 2, 3];
   * queryGenerator.escapeList([1, 2, 3]); // '(1, 2, 3)'
   */
  escapeList(values, options) {
    return `(${values.map((value) => this.escape(value, options)).join(", ")})`;
  }
  getUuidV1FunctionCall() {
    if (!this.dialect.supports.uuidV1Generation) {
      throw new Error(`UUID V1 generation is not supported by ${this.dialect.name} dialect.`);
    }
    throw new Error(`getUuidV1FunctionCall has not been implemented in ${this.dialect.name}.`);
  }
  getUuidV4FunctionCall() {
    if (!this.dialect.supports.uuidV4Generation) {
      throw new Error(`UUID V4 generation is not supported by ${this.dialect.name} dialect.`);
    }
    throw new Error(`getUuidV4FunctionCall has not been implemented in ${this.dialect.name}.`);
  }
  getToggleForeignKeyChecksQuery(_enable) {
    throw new Error(`${this.dialect.name} does not support toggling foreign key checks`);
  }
  versionQuery() {
    throw new Error(`${this.dialect.name} did not implement versionQuery`);
  }
  tableExistsQuery(tableName) {
    const table = this.extractTableDetails(tableName);
    return `SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = ${this.escape(table.tableName)} AND TABLE_SCHEMA = ${this.escape(table.schema)}`;
  }
  bulkDeleteQuery(tableOrModel, options) {
    const table = this.quoteTable(tableOrModel);
    const modelDefinition = (0, import_model_utils.extractModelDefinition)(tableOrModel);
    const whereOptions = { ...options, model: modelDefinition };
    const whereFragment = whereOptions.where ? this.whereQuery(whereOptions.where, whereOptions) : "";
    if (whereOptions.limit && !this.dialect.supports.delete.limit) {
      if (!modelDefinition) {
        throw new Error(
          "Using LIMIT in bulkDeleteQuery requires specifying a model or model definition."
        );
      }
      const pks = (0, import_utils.join)(
        (0, import_utils.map)(
          modelDefinition.primaryKeysAttributeNames.values(),
          (attrName) => this.quoteIdentifier(modelDefinition.getColumnName(attrName))
        ),
        ", "
      );
      const primaryKeys = modelDefinition.primaryKeysAttributeNames.size > 1 ? `(${pks})` : pks;
      return (0, import_join_sql_fragments.joinSQLFragments)([
        `DELETE FROM ${table} WHERE ${primaryKeys} IN (`,
        `SELECT ${pks} FROM ${table}`,
        whereFragment,
        `ORDER BY ${pks}`,
        this.#internals.addLimitAndOffset(whereOptions),
        ")"
      ]);
    }
    return (0, import_join_sql_fragments.joinSQLFragments)([
      `DELETE FROM ${this.quoteTable(tableOrModel)}`,
      whereFragment,
      this.#internals.addLimitAndOffset(whereOptions)
    ]);
  }
  __TEST__getInternals() {
    if (process.env.npm_lifecycle_event !== "mocha") {
      throw new Error("You can only access the internals of the query generator in test mode.");
    }
    return this.#internals;
  }
}
//# sourceMappingURL=query-generator-typescript.js.map
