import { PgIndexOpClass } from "../indexes.cjs";
import { entityKind } from "../../entity.cjs";
import { SQL } from "../../sql/sql.cjs";
import { Update } from "../../utils.cjs";
import { Column } from "../../column.cjs";
import { ColumnType, GeneratedColumnConfig, GeneratedIdentityConfig } from "../../column-builder.cjs";
import { PgTable } from "../table.cjs";
import { UpdateDeleteAction } from "../foreign-keys.cjs";

//#region src/pg-core/columns/common.d.ts
type PgArrayDimension = 0 | 1 | 2 | 3 | 4 | 5;
type PgArrayDimensionString = '[]' | '[][]' | '[][][]' | '[][][][]' | '[][][][][]';
type ArrayDimensionStringToNumber<T extends PgArrayDimensionString> = T extends '[]' ? 1 : T extends '[][]' ? 2 : T extends '[][][]' ? 3 : T extends '[][][][]' ? 4 : T extends '[][][][][]' ? 5 : never;
interface PgColumnBuilderConfig {
  dataType: ColumnType;
  data: unknown;
  driverParam: unknown;
  notNull?: boolean;
  hasDefault?: boolean;
  isPrimaryKey?: boolean;
  isAutoincrement?: boolean;
  hasRuntimeDefault?: boolean;
  enumValues?: string[];
  identity?: 'always' | 'byDefault';
  generated?: unknown;
  dimensions?: PgArrayDimension;
  $type?: unknown;
}
interface PgColumnBuilderRuntimeConfig<TData> {
  name: string;
  keyAsName: boolean;
  notNull: boolean;
  default: TData | SQL | undefined;
  defaultFn: (() => TData | SQL) | undefined;
  onUpdateFn: (() => TData | SQL) | undefined;
  hasDefault: boolean;
  primaryKey: boolean;
  isUnique: boolean;
  uniqueName: string | undefined;
  uniqueType: string | undefined;
  dataType: string;
  columnType: string;
  generated: GeneratedColumnConfig<TData> | undefined;
  generatedIdentity: GeneratedIdentityConfig | undefined;
  dimensions?: PgArrayDimension;
}
interface PgColumnBaseConfig<out TDataType extends ColumnType = ColumnType> {
  name: string;
  dataType: TDataType;
  tableName: string;
  notNull: boolean;
  hasDefault: boolean;
  isPrimaryKey: boolean;
  isAutoincrement: boolean;
  hasRuntimeDefault: boolean;
  data: unknown;
  driverParam: unknown;
  enumValues: string[] | undefined;
  generated: unknown;
  identity: undefined | 'always' | 'byDefault';
}
type WrapArray<T, N extends number> = N extends 1 ? T[] : N extends 2 ? T[][] : N extends 3 ? T[][][] : N extends 4 ? T[][][][] : N extends 5 ? T[][][][][] : T;
type SetNotNull<T> = T & {
  readonly _: {
    notNull: true;
  };
};
type SetHasDefault<T> = T & {
  readonly _: {
    hasDefault: true;
  };
};
type SetIsPrimaryKey<T> = T & {
  readonly _: {
    isPrimaryKey: true;
    notNull: true;
  };
};
type SetHasRuntimeDefault<T> = T & {
  readonly _: {
    hasRuntimeDefault: true;
    hasDefault: true;
  };
};
type Set$Type<T, TType> = T & {
  readonly _: {
    $type: TType;
  };
};
type SetHasGenerated<T> = T & {
  readonly _: {
    hasDefault: true;
    generated: true;
  };
};
type SetDimensions<T, TDim extends PgArrayDimension> = T & {
  readonly _: {
    dimensions: TDim;
  };
};
type SetIdentity<T, TType extends 'always' | 'byDefault'> = T & {
  readonly _: {
    notNull: true;
    hasDefault: true;
    identity: TType;
  };
};
type HasIdentity<T, TType extends 'always' | 'byDefault'> = SetIdentity<T, TType>;
type GetBaseData<T> = T extends {
  $type: infer U;
} ? U : T extends {
  data: infer D;
} ? D : unknown;
type ResolvePgColumnConfig<out T extends PgColumnBuilderConfig, out TTableName extends string, out TData = (T['dimensions'] extends 1 | 2 | 3 | 4 | 5 ? WrapArray<GetBaseData<T>, T['dimensions']> : GetBaseData<T>)> = {
  name: string;
  tableName: TTableName;
  dataType: T['dataType'];
  data: TData;
  driverParam: T['dimensions'] extends 1 | 2 | 3 | 4 | 5 ? WrapArray<T['driverParam'], T['dimensions']> | string : T['driverParam'];
  notNull: T['notNull'] extends true ? true : false;
  hasDefault: T['hasDefault'] extends true ? true : false;
  isPrimaryKey: false;
  isAutoincrement: false;
  hasRuntimeDefault: false;
  enumValues: T extends {
    enumValues: infer E extends string[];
  } ? E : undefined;
  identity: T['identity'] extends 'always' | 'byDefault' ? T['identity'] : undefined;
  generated: T['generated'] extends true ? true : undefined;
} & {};
interface AnyPgColumnBuilder {
  readonly _: PgColumnBuilderConfig;
}
type PgBuildColumn<TTableName extends string, TBuilder extends AnyPgColumnBuilder, TBuiltConfig extends PgColumnBaseConfig<ColumnType> = ResolvePgColumnConfig<TBuilder['_'], TTableName>> = PgColumn<ColumnType, TBuiltConfig, {}>;
type PgBuildColumns<out TTableName extends string, out TConfigMap extends Record<string, AnyPgColumnBuilder>> = { [Key in keyof TConfigMap]: PgBuildColumn<TTableName, TConfigMap[Key]> } & {};
type PgBuildExtraConfigColumns<out TConfigMap extends Record<string, AnyPgColumnBuilder>> = { [Key in keyof TConfigMap]: ExtraConfigColumn } & {};
type PgColumns = Record<string, PgColumn>;
interface ReferenceConfig {
  ref: () => PgColumn;
  config: {
    name?: string;
    onUpdate?: UpdateDeleteAction;
    onDelete?: UpdateDeleteAction;
  };
}
declare abstract class PgColumnBuilder<out T extends PgColumnBuilderConfig = PgColumnBuilderConfig, out TRuntimeConfig extends object = object> {
  static readonly [entityKind]: string;
  readonly _: T;
  private foreignKeyConfigs;
  protected config: PgColumnBuilderRuntimeConfig<T['data']> & TRuntimeConfig;
  constructor(name: string, dataType: ColumnType, columnType: string);
  /**
   * Changes the data type of the column. Commonly used with `json` columns. Also, useful for branded types.
   *
   * @example
   * ```ts
   * const users = pgTable('users', {
   * 	id: integer('id').$type<UserId>().primaryKey(),
   * 	details: json('details').$type<UserDetails>().notNull(),
   * });
   * ```
   */
  $type<TType>(): Set$Type<this, TType>;
  /**
   * Adds a `not null` clause to the column definition.
   *
   * Affects the `select` model of the table - columns *without* `not null` will be nullable on select.
   */
  notNull(): SetNotNull<this>;
  /**
   * Adds a `default <value>` clause to the column definition.
   *
   * Affects the `insert` model of the table - columns *with* `default` are optional on insert.
   *
   * If you need to set a dynamic default value, use {@link $defaultFn} instead.
   */
  default(value: (this['_'] extends {
    dimensions: 1 | 2 | 3 | 4 | 5;
  } ? WrapArray<this['_'] extends {
    $type: infer U;
  } ? U : this['_']['data'], this['_']['dimensions']> : this['_'] extends {
    $type: infer U;
  } ? U : this['_']['data']) | SQL): SetHasDefault<this>;
  /**
   * Adds a dynamic default value to the column.
   * The function will be called when the row is inserted, and the returned value will be used as the column value.
   *
   * **Note:** This value does not affect the `drizzle-kit` behavior, it is only used at runtime in `drizzle-orm`.
   */
  $defaultFn(fn: () => (this['_'] extends {
    dimensions: 1 | 2 | 3 | 4 | 5;
  } ? WrapArray<this['_'] extends {
    $type: infer U;
  } ? U : this['_']['data'], this['_']['dimensions']> : this['_'] extends {
    $type: infer U;
  } ? U : this['_']['data']) | SQL): SetHasRuntimeDefault<this>;
  /**
   * Alias for {@link $defaultFn}.
   */
  $default(fn: () => (this['_'] extends {
    dimensions: 1 | 2 | 3 | 4 | 5;
  } ? WrapArray<this['_'] extends {
    $type: infer U;
  } ? U : this['_']['data'], this['_']['dimensions']> : this['_'] extends {
    $type: infer U;
  } ? U : this['_']['data']) | SQL): SetHasRuntimeDefault<this>;
  /**
   * Adds a dynamic update value to the column.
   * The function will be called when the row is updated, and the returned value will be used as the column value if none is provided.
   * If no `default` (or `$defaultFn`) value is provided, the function will be called when the row is inserted as well, and the returned value will be used as the column value.
   *
   * **Note:** This value does not affect the `drizzle-kit` behavior, it is only used at runtime in `drizzle-orm`.
   */
  $onUpdateFn(fn: () => (this['_'] extends {
    dimensions: 1 | 2 | 3 | 4 | 5;
  } ? WrapArray<this['_'] extends {
    $type: infer U;
  } ? U : this['_']['data'], this['_']['dimensions']> : this['_'] extends {
    $type: infer U;
  } ? U : this['_']['data']) | SQL): SetHasDefault<this>;
  /**
   * Alias for {@link $onUpdateFn}.
   */
  $onUpdate(fn: () => (this['_'] extends {
    dimensions: 1 | 2 | 3 | 4 | 5;
  } ? WrapArray<this['_'] extends {
    $type: infer U;
  } ? U : this['_']['data'], this['_']['dimensions']> : this['_'] extends {
    $type: infer U;
  } ? U : this['_']['data']) | SQL): SetHasDefault<this>;
  /**
   * Adds a `primary key` clause to the column definition. This implicitly makes the column `not null`.
   *
   * In SQLite, `integer primary key` implicitly makes the column auto-incrementing.
   */
  primaryKey(): SetIsPrimaryKey<this>;
  /**
   * Makes this column a PostgreSQL array column.
   *
   * @example
   * ```ts
   * const t = pgTable('t', {
   *   // 1D array: number[]
   *   tags: integer().array(),
   *   // Or explicitly: integer().array('[]')
   *   // 2D array: number[][]
   *   matrix: integer().array('[][]'),
   * });
   * ```
   */
  array(): SetDimensions<this, 1>;
  array<TDim extends PgArrayDimensionString>(dimensions: TDim): SetDimensions<this, ArrayDimensionStringToNumber<TDim>>;
  references(ref: ReferenceConfig['ref'], config?: ReferenceConfig['config']): this;
  unique(name?: string, config?: {
    nulls: 'distinct' | 'not distinct';
  }): this;
  generatedAlwaysAs(as: SQL | (() => SQL)): SetHasGenerated<this>;
}
declare abstract class PgColumn<out TColumnType extends ColumnType = any, out T extends PgColumnBaseConfig<TColumnType> = PgColumnBaseConfig<TColumnType>, out TRuntimeConfig extends object = {}> extends Column<T, TRuntimeConfig> {
  static readonly [entityKind]: string;
  readonly dimensions: PgArrayDimension;
  constructor(table: PgTable, config: PgColumnBuilderRuntimeConfig<T['data']> & TRuntimeConfig);
  /**
   * Transforms this built column back into a fresh {@link PgColumnBuilder} in the exact same state:
   * a bare `toBuilder()` yields a builder whose built column is config-identical to this one.
   *
   * Useful for deriving a table from an existing one — pass the returned builder to `pgTable()` or
   * `pgSchema().table()` — while adjusting individual clauses through {@link overrides}.
   */
  toBuilder(overrides?: PgColumnToBuilderOverrides<T['data']>): PgColumnBuilder;
}
interface PgColumnToBuilderOverrides<TData = unknown> {
  name?: string;
  notNull?: boolean;
  primaryKey?: boolean;
  default?: TData | SQL | undefined;
  defaultFn?: (() => TData | SQL) | undefined;
  onUpdateFn?: (() => TData | SQL) | undefined;
  unique?: boolean | {
    name?: string;
    nulls?: 'distinct' | 'not distinct';
  };
  generated?: GeneratedColumnConfig<TData> | undefined;
  generatedIdentity?: GeneratedIdentityConfig | undefined;
}
type PgColumnConstructor = new (table: PgTable, config: any) => PgColumn;
declare class PgClonedColumnBuilder extends PgColumnBuilder {
  static readonly [entityKind]: string;
  private readonly ColumnClass;
  constructor(config: PgColumnBuilderRuntimeConfig<unknown>, ColumnClass: PgColumnConstructor);
}
type IndexedExtraConfigType = {
  order?: 'asc' | 'desc';
  nulls?: 'first' | 'last';
  opClass?: string;
};
declare class ExtraConfigColumn<out T extends PgColumnBaseConfig<ColumnType> = PgColumnBaseConfig<ColumnType>> extends PgColumn<ColumnType, T, IndexedExtraConfigType> {
  static readonly [entityKind]: string;
  /** @itnernal */
  readonly codec: undefined;
  getSQLType(): string;
  indexConfig: IndexedExtraConfigType;
  defaultConfig: IndexedExtraConfigType;
  asc(): Omit<this, 'asc' | 'desc'>;
  desc(): Omit<this, 'asc' | 'desc'>;
  nullsFirst(): Omit<this, 'nullsFirst' | 'nullsLast'>;
  nullsLast(): Omit<this, 'nullsFirst' | 'nullsLast'>;
  /**
   * ### PostgreSQL documentation quote
   *
   * > An operator class with optional parameters can be specified for each column of an index.
   * The operator class identifies the operators to be used by the index for that column.
   * For example, a B-tree index on four-byte integers would use the int4_ops class;
   * this operator class includes comparison functions for four-byte integers.
   * In practice the default operator class for the column's data type is usually sufficient.
   * The main point of having operator classes is that for some data types, there could be more than one meaningful ordering.
   * For example, we might want to sort a complex-number data type either by absolute value or by real part.
   * We could do this by defining two operator classes for the data type and then selecting the proper class when creating an index.
   * More information about operator classes check:
   *
   * ### Useful links
   * https://www.postgresql.org/docs/current/sql-createindex.html
   *
   * https://www.postgresql.org/docs/current/indexes-opclass.html
   *
   * https://www.postgresql.org/docs/current/xindex.html
   *
   * ### Additional types
   * If you have the `pg_vector` extension installed in your database, you can use the
   * `vector_l2_ops`, `vector_ip_ops`, `vector_cosine_ops`, `vector_l1_ops`, `bit_hamming_ops`, `bit_jaccard_ops`, `halfvec_l2_ops`, `sparsevec_l2_ops` options, which are predefined types.
   *
   * **You can always specify any string you want in the operator class, in case Drizzle doesn't have it natively in its types**
   *
   * @param opClass
   * @returns
   */
  op(opClass: PgIndexOpClass): Omit<this, 'op'>;
}
declare class IndexedColumn {
  static readonly [entityKind]: string;
  constructor(name: string, keyAsName: boolean, type: string, indexConfig: IndexedExtraConfigType);
  name: string;
  keyAsName: boolean;
  type: string;
  indexConfig: IndexedExtraConfigType;
}
type AnyPgColumn<TPartial extends Partial<PgColumnBaseConfig<ColumnType>> = {}> = PgColumn<any, Required<Update<PgColumnBaseConfig<ColumnType>, TPartial>>>;
//#endregion
export { AnyPgColumn, AnyPgColumnBuilder, ExtraConfigColumn, HasIdentity, IndexedColumn, IndexedExtraConfigType, PgArrayDimension, PgBuildColumn, PgBuildColumns, PgBuildExtraConfigColumns, PgClonedColumnBuilder, PgColumn, PgColumnBaseConfig, PgColumnBuilder, PgColumnBuilderConfig, PgColumnBuilderRuntimeConfig, PgColumnToBuilderOverrides, PgColumns, ReferenceConfig, ResolvePgColumnConfig, Set$Type, SetDimensions, SetHasDefault, SetHasGenerated, SetHasRuntimeDefault, SetIdentity, SetIsPrimaryKey, SetNotNull };
//# sourceMappingURL=common.d.cts.map