---
title: "Table and Column Models"
description: "Table and Column Models supply the core structural foundation for defining database entities, column definitions, and schema metadata across all supported dialects. They provide the base abstractio..."
last_updated: "2026-10-12T08:14:00.746407+00:00"
canonical_url: "https://www.doc0.dev/docs/e1b68fed-3c4e-4c95-b2ba-ebf050f78025/technical/core-architecture/table-and-column-models"
---

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [drizzle-orm/src/sqlite-core/columns/common.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/sqlite-core/columns/common.ts)
- [drizzle-kit/src/introspect-pg.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-kit/src/introspect-pg.ts)
- [drizzle-orm/type-tests/sqlite/tables.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/type-tests/sqlite/tables.ts)
- [drizzle-orm/src/sqlite-core/table.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/sqlite-core/table.ts)
- [drizzle-kit/src/introspect-gel.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-kit/src/introspect-gel.ts)
- [drizzle-orm/src/column-builder.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/column-builder.ts)
- [drizzle-orm/src/pg-core/indexes.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/pg-core/indexes.ts)
- [drizzle-kit/src/introspect-singlestore.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-kit/src/introspect-singlestore.ts)
- [drizzle-kit/src/introspect-mysql.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-kit/src/introspect-mysql.ts)
- [drizzle-kit/src/sqlgenerator.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-kit/src/sqlgenerator.ts)
- [drizzle-orm/src/gel-core/dialect.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/gel-core/dialect.ts)
- [drizzle-orm/src/sqlite-core/dialect.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/sqlite-core/dialect.ts)
- [drizzle-orm/src/singlestore-core/dialect.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/singlestore-core/dialect.ts)
- [drizzle-orm/src/gel-core/columns/common.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/gel-core/columns/common.ts)
- [drizzle-orm/src/sqlite-core/primary-keys.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/sqlite-core/primary-keys.ts)
- [drizzle-orm/src/table.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/table.ts)
- [drizzle-orm/src/gel-core/indexes.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/gel-core/indexes.ts)
- [drizzle-orm/src/pg-core/columns/common.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/pg-core/columns/common.ts)
- [drizzle-kit/src/introspect-sqlite.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-kit/src/introspect-sqlite.ts)
- [drizzle-orm/src/sqlite-core/indexes.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/sqlite-core/indexes.ts)
- [drizzle-orm/src/pg-core/table.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/pg-core/table.ts)
- [drizzle-orm/src/mysql-core/columns/common.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/mysql-core/columns/common.ts)
- [drizzle-orm/src/alias.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/alias.ts)
- [drizzle-orm/src/sqlite-core/db.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/sqlite-core/db.ts)
- [drizzle-orm/src/sqlite-core/columns/integer.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/sqlite-core/columns/integer.ts)
- [drizzle-orm/src/mysql-core/table.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/mysql-core/table.ts)
- [drizzle-orm/src/gel-core/table.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/gel-core/table.ts)
- [drizzle-orm/src/sqlite-core/foreign-keys.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/sqlite-core/foreign-keys.ts)
- [drizzle-orm/src/mysql-core/indexes.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/mysql-core/indexes.ts)
- [drizzle-orm/src/sqlite-core/utils.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/sqlite-core/utils.ts)
</details>

## Overview

Table and Column Models supply the core structural foundation for defining database entities, column definitions, and schema metadata across all supported dialects. They provide the base abstractions and symbol branding needed to construct typed tables, configure column builders, establish foreign keys, and map driver values.

Sources: [drizzle-orm/src/table.ts:42-118](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/table.ts#L42-L118)

By combining declarative TypeScript types with runtime column transformers and table proxy handlers, this system bridges high-level schema definitions with low-level SQL query generation and relational query execution.

Sources: [drizzle-orm/src/alias.ts:10-75](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/alias.ts#L10-L75), [drizzle-orm/src/column-builder.ts:11-26](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/column-builder.ts#L11-L26)

## Core Table Architecture and Invariants

### Base Table Class and Symbol Branding

The `Table` class serves as the root abstraction for all schema entities, implementing `SQLWrapper` and carrying static metadata alongside internal symbol properties. Each table instance is branded at runtime using `IsDrizzleTable` and maintains configuration traits through TypeScript mapped types (`TableConfig`, `InferSelectModel`, and `InferInsertModel`). 

Internal state tracking relies on a set of exported symbols located on `Table.Symbol`. These symbols isolate metadata properties from user-defined column names, preserving clean namespace separation for table names, schemas, and alias mapping flags.

```typescript
export class Table<T extends TableConfig = TableConfig> implements SQLWrapper {
	static readonly [entityKind]: string = 'Table';

	declare readonly _: {
		readonly brand: 'Table';
		readonly config: T;
		readonly name: T['name'];
		readonly schema: T['schema'];
		readonly columns: T['columns'];
		readonly inferSelect: InferSelectModel<Table<T>>;
		readonly inferInsert: InferInsertModel<Table<T>>;
	};
...
```
Sources: [drizzle-orm/src/table.ts:42-60](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/table.ts#L42-L60)

| Symbol Name | Runtime Symbol Key | Purpose |
| :--- | :--- | :--- |
| `Name` | `drizzle:TableName` | Stores the active table name (modifiable during aliasing). |
| `Schema` | `drizzle:Schema` | Stores the optional database schema identifier. |
| `OriginalName` | `drizzle:OriginalName` | Preserves the initial unaliased table name. |
| `Columns` | `drizzle:Columns` | Holds the record mapping column keys to column definitions. |
| `ExtraConfigColumns` | `drizzle:ExtraConfigColumns` | Stores extra configuration columns during table building. |
| `BaseName` | `drizzle:BaseName` | Preserves the pre-transformation name before `tableCreator` hooks. |
| `IsAlias` | `drizzle:IsAlias` | Boolean flag indicating whether the table instance is an alias. |
| `ExtraConfigBuilder` | `drizzle:ExtraConfigBuilder` | Callback reference for evaluating extra table constraints and indexes. |

Sources: [drizzle-orm/src/table.ts:20-40](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/table.ts#L20-L40), [drizzle-orm/src/table.ts:65-112](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/table.ts#L65-L112)

> [!NOTE]
> The `isTable` runtime check validates table instances exclusively by inspecting whether `IsDrizzleTable` exists on the target object, ensuring fast identification without relying on `instanceof` checks that can fail across module boundary versions.
> 
> Sources: [drizzle-orm/src/table.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/table.ts#L120-L122)

### Entity Metadata and Relational Inference

Tables expose inference utilities (`$inferSelect` and `$inferInsert`) that evaluate column definitions to construct strict TypeScript models. The `InferModelFromColumns` type maps column configurations, handling database column name remapping when `dbColumnNames` is enabled and distinguishing required versus optional insert keys using column operation markers (`RequiredKeyOnly` and `OptionalKeyOnly`).

```typescript
export type InferModelFromColumns<
	TColumns extends Record<string, Column>,
	TInferMode extends 'select' | 'insert' = 'select',
	TConfig extends { dbColumnNames: boolean; override?: boolean } = { dbColumnNames: false; override: false },
> = Simplify<
	TInferMode extends 'insert' ?
			& {
				[
					Key in keyof TColumns & string as RequiredKeyOnly<
						MapColumnName<Key, TColumns[Key], TConfig['dbColumnNames']>,
						TColumns[Key]
					>
				]: GetColumnData<TColumns[Key], 'query'>;
			}
			& {
				[
					Key in keyof TColumns & string as OptionalKeyOnly<
						MapColumnName<Key, TColumns[Key], TConfig['dbColumnNames']>,
						TColumns[Key],
						TConfig['override']
					>
				]?: GetColumnData<TColumns[Key], 'query'> | undefined;
			}
		: {
			[
				Key in keyof TColumns & string as MapColumnName<
					Key,
					TColumns[Key],
					TConfig['dbColumnNames']
				>
			]: GetColumnData<TColumns[Key], 'query'>;
		}
>;
```
Sources: [drizzle-orm/src/table.ts:155-187](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/table.ts#L155-L187)

Functions such as `getTableName` and `getTableUniqueName` extract structural metadata directly from table symbols, providing fully qualified namespace strings (`schema.tablename`) for query builders and the [relational query engine](https://www.doc0.dev/docs/e1b68fed-3c4e-4c95-b2ba-ebf050f78025/technical/core-architecture/relational-query-engine).

```typescript
export function getTableName<T extends Table>(table: T): T['_']['name'] {
	return table[TableName];
}

export function getTableUniqueName<T extends Table>(table: T): `${T['_']['schema']}.${T['_']['name']}` {
	return `${table[Schema] ?? 'public'}.${table[TableName]}`;
}
```
Sources: [drizzle-orm/src/table.ts:143-149](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/table.ts#L143-L149)

## Column Builder Lifecycle and Configuration

### Configuration Contracts and Type Mapping

Column builders manage the definition and serialization attributes of database columns before they are materialized into table columns. The core configuration contract relies on `ColumnBuilderBaseConfig`, which enforces properties such as column name, data type, column type, driver parameters, and enumerated values. The `MakeColumnConfig` utility type processes these base configurations to determine nullability, default presence, primary key status, autoincrement flags, and generated identity configurations across table columns.

```typescript
export interface ColumnBuilderBaseConfig<TDataType extends ColumnDataType, TColumnType extends string> {
	name: string;
	dataType: TDataType;
	columnType: TColumnType;
	data: unknown;
	driverParam: unknown;
	enumValues: string[] | undefined;
}

export type MakeColumnConfig<
	T extends ColumnBuilderBaseConfig<ColumnDataType, string>,
	TTableName extends string,
	TData = T extends { $type: infer U } ? U : T['data'],
> = {
	name: T['name'];
	tableName: TTableName;
	dataType: T['dataType'];
	columnType: T['columnType'];
	data: TData;
	driverParam: T['driverParam'];
	notNull: T extends { notNull: true } ? true : false;
	hasDefault: T extends { hasDefault: true } ? true : false;
	isPrimaryKey: T extends { isPrimaryKey: true } ? true : false;
	isAutoincrement: T extends { isAutoincrement: true } ? true : false;
	hasRuntimeDefault: T extends { hasRuntimeDefault: true } ? true : false;
	enumValues: T['enumValues'];
	baseColumn: T extends { baseBuilder: infer U extends ColumnBuilderBase } ? BuildColumn<TTableName, U, 'common'>
		: never;
	identity: T extends { identity: 'always' } ? 'always' : T extends { identity: 'byDefault' } ? 'byDefault' : undefined;
	generated: T extends { generated: infer G } ? unknown extends G ? undefined
		: G extends undefined ? undefined
		: G
		: undefined;
} & {};
```
Sources: [drizzle-orm/src/column-builder.ts:46-79](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/column-builder.ts#L46-L79)

Supported primitive data types span string, number, boolean, array, json, date, bigint, custom, buffer, dateDuration, duration, relDuration, localTime, localDate, and localDateTime. Dialect targets are explicitly restricted to pg, mysql, sqlite, singlestore, common, and gel.

```typescript
export type ColumnDataType =
	| 'string'
	| 'number'
	| 'boolean'
	| 'array'
	| 'json'
	| 'date'
	| 'bigint'
	| 'custom'
	| 'buffer'
	| 'dateDuration'
	| 'duration'
	| 'relDuration'
	| 'localTime'
	| 'localDate'
	| 'localDateTime';

export type Dialect = 'pg' | 'mysql' | 'sqlite' | 'singlestore' | 'common' | 'gel';
```
Sources: [drizzle-orm/src/column-builder.ts:11-28](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/column-builder.ts#L11-L28)

> [!NOTE]
> `ColumnBuilderRuntimeConfig` stores active runtime flags such as `keyAsName`, `notNull`, `hasDefault`, `default`, `defaultFn`, and `onUpdateFn` to evaluate column behaviors during schema building and statement generation.
> 
> Sources: [drizzle-orm/src/column-builder.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/column-builder.ts#L102-L109)

### SQLite Integer, Timestamp, and Boolean Builders

SQLite columns demonstrate specialized builder lifecycles and driver value transformations through `SQLiteBaseIntegerBuilder` and its concrete extensions. The `integer` factory function parses optional names and configurations, branching to construct `SQLiteIntegerBuilder`, `SQLiteTimestampBuilder`, or `SQLiteBooleanBuilder` depending on the selected mode.

```typescript
export interface IntegerConfig<
	TMode extends 'number' | 'timestamp' | 'timestamp_ms' | 'boolean' =
		| 'number'
		| 'timestamp'
		| 'timestamp_ms'
		| 'boolean',
> {
	mode: TMode;
}

export function integer(): SQLiteIntegerBuilderInitial<''>;
export function integer<TMode extends IntegerConfig['mode']>(
	config?: IntegerConfig<TMode>,
): Or<Equal<TMode, 'timestamp'>, Equal<TMode, 'timestamp_ms'>> extends true ? SQLiteTimestampBuilderInitial<''>
	: Equal<TMode, 'boolean'> extends true ? SQLiteBooleanBuilderInitial<''>
	: SQLiteIntegerBuilderInitial<''>;
export function integer<TName extends string, TMode extends IntegerConfig['mode']>(
	name: TName,
	config?: IntegerConfig<TMode>,
): Or<Equal<TMode, 'timestamp'>, Equal<TMode, 'timestamp_ms'>> extends true ? SQLiteTimestampBuilderInitial<TName>
	: Equal<TMode, 'boolean'> extends true ? SQLiteBooleanBuilderInitial<TName>
	: SQLiteIntegerBuilderInitial<TName>;
export function integer(a?: string | IntegerConfig, b?: IntegerConfig) {
	const { name, config } = getColumnNameAndConfig<IntegerConfig | undefined>(a, b);
	if (config?.mode === 'timestamp' || config?.mode === 'timestamp_ms') {
		return new SQLiteTimestampBuilder(name, config.mode);
	}
	if (config?.mode === 'boolean') {
		return new SQLiteBooleanBuilder(name, config.mode);
	}
	return new SQLiteIntegerBuilder(name);
}

export const int = integer;
```
Sources: [drizzle-orm/src/sqlite-core/columns/integer.ts:204-237](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/sqlite-core/columns/integer.ts#L204-L237)

| Column Type | Mode Parameter | Driver Parameter Type | Mapped JavaScript Type | Driver Mapping Logic |
| :--- | :--- | :--- | :--- | :--- |
| `SQLiteInteger` | `number` (default) | `number` | `number` | Direct integer storage. |
| `SQLiteTimestamp` | `timestamp` | `number` | `Date` | Multiplies or divides by `1000` for epoch seconds. |
| `SQLiteTimestamp` | `timestamp_ms` | `number` | `Date` | Preserves millisecond epoch numbers directly. |
| `SQLiteBoolean` | `boolean` | `number` | `boolean` | Translates integer `1` and `0` to boolean values. |

Sources: [drizzle-orm/src/sqlite-core/columns/integer.ts:66-202](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/sqlite-core/columns/integer.ts#L66-L202)

```mermaid
flowchart TD
    A["integer(name, config)"] --> B{config?.mode}
    B -->|timestamp / timestamp_ms| C["SQLiteTimestampBuilder"]
    B -->|boolean| D["SQLiteBooleanBuilder"]
    B -->|undefined / number| E["SQLiteIntegerBuilder"]
    C --> F["SQLiteTimestamp.mapFromDriverValue / mapToDriverValue"]
    D --> G["SQLiteBoolean.mapFromDriverValue / mapToDriverValue"]
    E --> H["SQLiteInteger"]
```
Sources: [drizzle-orm/src/sqlite-core/columns/integer.ts:143-202](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/sqlite-core/columns/integer.ts#L143-L202), [drizzle-orm/src/sqlite-core/columns/integer.ts:228-235](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/sqlite-core/columns/integer.ts#L228-L235)

> [!CAUTION]
> Calling `defaultNow()` on a `SQLiteTimestampBuilder` is deprecated; column defaults should be assigned using `.default()` with custom SQL expressions instead.
> 
> Sources: [drizzle-orm/src/sqlite-core/columns/integer.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/sqlite-core/columns/integer.ts#L117-L124)

## Dialect Table Instantiation and Normalization

### Table Creation Functions and Schemas

Table instantiation across database engines relies on dialect-specific table classes that extend the core `Table` abstraction while managing engine-specific symbols and configuration types. The `SQLiteTable` class defines `InlineForeignKeys` symbol branding to track foreign keys declared within column definitions SQLiteTable:

```typescript
export const InlineForeignKeys = Symbol.for('drizzle:SQLiteInlineForeignKeys');

export class SQLiteTable<T extends TableConfig = TableConfig> extends Table<T> {
	static override readonly [entityKind]: string = 'SQLiteTable';

	/** @internal */
	static override readonly Symbol = Object.assign({}, Table.Symbol, {
		InlineForeignKeys: InlineForeignKeys as typeof InlineForeignKeys,
	});

	/** @internal */
	override [Table.Symbol.Columns]!: NonNullable<T['columns']>;

	/** @internal */
	[InlineForeignKeys]: ForeignKey[] = [];

	/** @internal */
	override [Table.Symbol.ExtraConfigBuilder]:
		| ((self: Record<string, SQLiteColumn>) => SQLiteTableExtraConfig)
		| undefined = undefined;
}
```
Sources: [drizzle-orm/src/sqlite-core/table.ts:27-47](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/sqlite-core/table.ts#L27-L47)

Similarly, `PgTable` in PostgreSQL and `GelTable` in Gel introduce both `InlineForeignKeys` and `EnableRLS` symbols to support row-level security policy toggles and inline constraints PgTable, GelTable:

```typescript
/** @internal */
export const InlineForeignKeys = Symbol.for('drizzle:PgInlineForeignKeys');
/** @internal */
export const EnableRLS = Symbol.for('drizzle:EnableRLS');

export class PgTable<T extends TableConfig = TableConfig> extends Table<T> {
	static override readonly [entityKind]: string = 'PgTable';

	/** @internal */
	static override readonly Symbol = Object.assign({}, Table.Symbol, {
		InlineForeignKeys: InlineForeignKeys as typeof InlineForeignKeys,
		EnableRLS: EnableRLS as typeof EnableRLS,
	});

	/**@internal */
	[InlineForeignKeys]: ForeignKey[] = [];

	/** @internal */
	[EnableRLS]: boolean = false;

	/** @internal */
	override [Table.Symbol.ExtraConfigBuilder]: ((self: Record<string, PgColumn>) => PgTableExtraConfig) | undefined =
		undefined;

	/** @internal */
	override [Table.Symbol.ExtraConfigColumns]: Record<string, ExtraConfigColumn> = {};
}
```
Sources: [drizzle-orm/src/pg-core/table.ts:28-54](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/pg-core/table.ts#L28-L54)

```typescript
/** @internal */
export const InlineForeignKeys = Symbol.for('drizzle:GelInlineForeignKeys');
/** @internal */
export const EnableRLS = Symbol.for('drizzle:EnableRLS');

export class GelTable<T extends TableConfig = TableConfig> extends Table<T> {
	static override readonly [entityKind]: string = 'GelTable';

	/** @internal */
	static override readonly Symbol = Object.assign({}, Table.Symbol, {
		InlineForeignKeys: InlineForeignKeys as typeof InlineForeignKeys,
		EnableRLS: EnableRLS as typeof EnableRLS,
	});

	/**@internal */
	[InlineForeignKeys]: ForeignKey[] = [];

	/** @internal */
	[EnableRLS]: boolean = false;

	/** @internal */
	override [Table.Symbol.ExtraConfigBuilder]: ((self: Record<string, GelColumn>) => GelTableExtraConfig) | undefined =
		undefined;

	/** @internal */
	override [Table.Symbol.ExtraConfigColumns]: Record<string, GelExtraConfigColumn> = {};
}
```
Sources: [drizzle-orm/src/gel-core/table.ts:28-54](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/gel-core/table.ts#L28-L54)

`MySqlTable` implements equivalent symbol tracking for MySQL environments MySqlTable:

```typescript
/** @internal */
export const InlineForeignKeys = Symbol.for('drizzle:MySqlInlineForeignKeys');

export class MySqlTable<T extends TableConfig = TableConfig> extends Table<T> {
	static override readonly [entityKind]: string = 'MySqlTable';

	declare protected $columns: T['columns'];

	/** @internal */
	static override readonly Symbol = Object.assign({}, Table.Symbol, {
		InlineForeignKeys: InlineForeignKeys as typeof InlineForeignKeys,
	});

	/** @internal */
	override [Table.Symbol.Columns]!: NonNullable<T['columns']>;

	/** @internal */
	[InlineForeignKeys]: ForeignKey[] = [];

	/** @internal */
	override [Table.Symbol.ExtraConfigBuilder]:
		| ((self: Record<string, MySqlColumn>) => MySqlTableExtraConfig)
		| undefined = undefined;
}
```
Sources: [drizzle-orm/src/mysql-core/table.ts:26-49](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/mysql-core/table.ts#L26-L49)

### Column Builder Parsing and Normalization

During table construction, column definitions can be provided either as a static record map or via a callback function receiving engine-specific column builders (`SQLiteColumnBuilders`, `PgColumnsBuilders`, `MySqlColumnBuilders`, or `GelColumnsBuilders`). The normalization routine resolves these definitions, sets column names, and instantiates the underlying column objects pgTableWithSchema, mysqlTableWithSchema, gelTableWithSchema:

```typescript
export function pgTableWithSchema<
	TTableName extends string,
	TSchemaName extends string | undefined,
	TColumnsMap extends Record<string, PgColumnBuilderBase>,
>(
	name: TTableName,
	columns: TColumnsMap | ((columnTypes: PgColumnsBuilders) => TColumnsMap),
	extraConfig:
		| ((self: BuildExtraConfigColumns<TTableName, TColumnsMap, 'pg'>) => PgTableExtraConfig | PgTableExtraConfigValue[])
		| undefined,
	schema: TSchemaName,
	baseName = name,
): PgTableWithColumns<{
	name: TTableName;
	schema: TSchemaName;
	columns: BuildColumns<TTableName, TColumnsMap, 'pg'>;
	dialect: 'pg';
}> {
	const rawTable = new PgTable<{
		name: TTableName;
		schema: TSchemaName;
		columns: BuildColumns<TTableName, TColumnsMap, 'pg'>;
		dialect: 'pg';
	}>(name, schema, baseName);

	const parsedColumns: TColumnsMap = typeof columns === 'function' ? columns(getPgColumnBuilders()) : columns;

	const builtColumns = Object.fromEntries(
		Object.entries(parsedColumns).map(([name, colBuilderBase]) => {
			const colBuilder = colBuilderBase as PgColumnBuilder;
			colBuilder.setName(name);
			const column = colBuilder.build(rawTable);
			rawTable[InlineForeignKeys].push(...colBuilder.buildForeignKeys(column, rawTable));
			return [name, column];
		}),
	) as unknown as BuildColumns<TTableName, TColumnsMap, 'pg'>;

	const builtColumnsForExtraConfig = Object.fromEntries(
		Object.entries(parsedColumns).map(([name, colBuilderBase]) => {
			const colBuilder = colBuilderBase as PgColumnBuilder;
			colBuilder.setName(name);
			const column = colBuilder.buildExtraConfigColumn(rawTable);
			return [name, column];
		}),
	) as unknown as BuildExtraConfigColumns<TTableName, TColumnsMap, 'pg'>;

	const table = Object.assign(rawTable, builtColumns);

	table[Table.Symbol.Columns] = builtColumns;
	table[Table.Symbol.ExtraConfigColumns] = builtColumnsForExtraConfig;

	if (extraConfig) {
		table[PgTable.Symbol.ExtraConfigBuilder] = extraConfig as any;
	}

	return Object.assign(table, {
		enableRLS: () => {
			table[PgTable.Symbol.EnableRLS] = true;
			return table as PgTableWithColumns<{
				name: TTableName;
				schema: TSchemaName;
				columns: BuildColumns<TTableName, TColumnsMap, 'pg'>;
				dialect: 'pg';
			}>;
		},
	});
}
```
Sources: [drizzle-orm/src/pg-core/table.ts:71-137](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/pg-core/table.ts#L71-L137)

```typescript
export function mysqlTableWithSchema<
	TTableName extends string,
	TSchemaName extends string | undefined,
	TColumnsMap extends Record<string, MySqlColumnBuilderBase>,
>(
	name: TTableName,
	columns: TColumnsMap | ((columnTypes: MySqlColumnBuilders) => TColumnsMap),
	extraConfig:
		| ((
			self: BuildColumns<TTableName, TColumnsMap, 'mysql'>,
		) => MySqlTableExtraConfig | MySqlTableExtraConfigValue[])
		| undefined,
	schema: TSchemaName,
	baseName = name,
): MySqlTableWithColumns<{
	name: TTableName;
	schema: TSchemaName;
	columns: BuildColumns<TTableName, TColumnsMap, 'mysql'>;
	dialect: 'mysql';
}> {
	const rawTable = new MySqlTable<{
		name: TTableName;
		schema: TSchemaName;
		columns: BuildColumns<TTableName, TColumnsMap, 'mysql'>;
		dialect: 'mysql';
	}>(name, schema, baseName);

	const parsedColumns: TColumnsMap = typeof columns === 'function' ? columns(getMySqlColumnBuilders()) : columns;

	const builtColumns = Object.fromEntries(
		Object.entries(parsedColumns).map(([name, colBuilderBase]) => {
			const colBuilder = colBuilderBase as MySqlColumnBuilder;
			colBuilder.setName(name);
			const column = colBuilder.build(rawTable);
			rawTable[InlineForeignKeys].push(...colBuilder.buildForeignKeys(column, rawTable));
			return [name, column];
		}),
	) as unknown as BuildColumns<TTableName, TColumnsMap, 'mysql'>;

	const table = Object.assign(rawTable, builtColumns);

	table[Table.Symbol.Columns] = builtColumns;
	table[Table.Symbol.ExtraConfigColumns] = builtColumns as unknown as BuildExtraConfigColumns<
		TTableName,
		TColumnsMap,
		'mysql'
	>;

	if (extraConfig) {
		table[MySqlTable.Symbol.ExtraConfigBuilder] = extraConfig as unknown as (
			self: Record<string, MySqlColumn>,
		) => MySqlTableExtraConfig;
	}

	return table;
}
```
Sources: [drizzle-orm/src/mysql-core/table.ts:61-116](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/mysql-core/table.ts#L61-L116)

```typescript
export function gelTableWithSchema<
	TTableName extends string,
	TSchemaName extends string | undefined,
	TColumnsMap extends Record<string, GelColumnBuilderBase>,
>(
	name: TTableName,
	columns: TColumnsMap | ((columnTypes: GelColumnsBuilders) => TColumnsMap),
	extraConfig:
		| ((
			self: BuildExtraConfigColumns<TTableName, TColumnsMap, 'gel'>,
		) => GelTableExtraConfig | GelTableExtraConfigValue[])
		| undefined,
	schema: TSchemaName,
	baseName = name,
): GelTableWithColumns<{
	name: TTableName;
	schema: TSchemaName;
	columns: BuildColumns<TTableName, TColumnsMap, 'gel'>;
	dialect: 'gel';
}> {
	const rawTable = new GelTable<{
		name: TTableName;
		schema: TSchemaName;
		columns: BuildColumns<TTableName, TColumnsMap, 'gel'>;
		dialect: 'gel';
	}>(name, schema, baseName);

	const parsedColumns: TColumnsMap = typeof columns === 'function' ? columns(getGelColumnBuilders()) : columns;

	const builtColumns = Object.fromEntries(
		Object.entries(parsedColumns).map(([name, colBuilderBase]) => {
			const colBuilder = colBuilderBase as GelColumnBuilder;
			colBuilder.setName(name);
			const column = colBuilder.build(rawTable);
			rawTable[InlineForeignKeys].push(...colBuilder.buildForeignKeys(column, rawTable));
			return [name, column];
		}),
	) as unknown as BuildColumns<TTableName, TColumnsMap, 'gel'>;

	const builtColumnsForExtraConfig = Object.fromEntries(
		Object.entries(parsedColumns).map(([name, colBuilderBase]) => {
			const colBuilder = colBuilderBase as GelColumnBuilder;
			colBuilder.setName(name);
			const column = colBuilder.buildExtraConfigColumn(rawTable);
			return [name, column];
		}),
	) as unknown as BuildExtraConfigColumns<TTableName, TColumnsMap, 'gel'>;

	const table = Object.assign(rawTable, builtColumns);

	table[Table.Symbol.Columns] = builtColumns;
	table[Table.Symbol.ExtraConfigColumns] = builtColumnsForExtraConfig;

	if (extraConfig) {
		table[GelTable.Symbol.ExtraConfigBuilder] = extraConfig as any;
	}

	return Object.assign(table, {
		enableRLS: () => {
			table[GelTable.Symbol.EnableRLS] = true;
			return table as GelTableWithColumns<{
				name: TTableName;
				schema: TSchemaName;
				columns: BuildColumns<TTableName, TColumnsMap, 'gel'>;
				dialect: 'gel';
			}>;
		},
	});
}
```
Sources: [drizzle-orm/src/gel-core/table.ts:73-141](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/gel-core/table.ts#L73-L141)

> [!NOTE]
> PostgreSQL and Gel table factories build both standard columns and extra config columns (`buildExtraConfigColumn`), enabling table-level constraints to reference column metadata prior to schema serialization.
> 
> Sources: [drizzle-orm/src/pg-core/table.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/pg-core/table.ts#L98-L120), [drizzle-orm/src/gel-core/table.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/gel-core/table.ts#L102-L124)

> [!WARNING]
> Passing an object instead of an array as the third parameter (`extraConfig`) to table builder functions is deprecated and will be removed in future releases across SQLite, MySQL, and Gel.
> 
> Sources: [drizzle-orm/src/sqlite-core/table.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/sqlite-core/table.ts#L89-L110), [drizzle-orm/src/mysql-core/table.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/mysql-core/table.ts#L148-L169), [drizzle-orm/src/gel-core/table.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/gel-core/table.ts#L143-L165)

## Table Proxies and Alias Remapping

### Proxy Handlers and Identifier Aliasing

Table and column aliasing leverage JavaScript `Proxy` objects to intercept property access, symbol evaluation, and schema traversal across query builders and dialect runtimes. The `TableAliasProxyHandler` intercepts core table symbols such as `Table.Symbol.IsAlias`, `Table.Symbol.Name`, and `Table.Symbol.OriginalName` to substitute alias strings while mapping column property accesses through `ColumnAliasProxyHandler` drizzle-orm/src/alias.ts.

```typescript
export class TableAliasProxyHandler<T extends Table | View> implements ProxyHandler<T> {
	static readonly [entityKind]: string = 'TableAliasProxyHandler';

	constructor(private alias: string, private replaceOriginalName: boolean) {}

	get(target: T, prop: string | symbol): any {
		if (prop === Table.Symbol.IsAlias) {
			return true;
		}

		if (prop === Table.Symbol.Name) {
			return this.alias;
		}

		if (this.replaceOriginalName && prop === Table.Symbol.OriginalName) {
			return this.alias;
		}

		if (prop === ViewBaseConfig) {
			return {
				...target[ViewBaseConfig as keyof typeof target],
				name: this.alias,
				isAlias: true,
			};
		}

		if (prop === Table.Symbol.Columns) {
			const columns = (target as Table)[Table.Symbol.Columns];
			if (!columns) {
				return columns;
			}

			const proxiedColumns: { [key: string]: any } = {};

			Object.keys(columns).map((key) => {
				proxiedColumns[key] = new Proxy(
					columns[key]!,
					new ColumnAliasProxyHandler(new Proxy(target, this)),
				);
			});

			return proxiedColumns;
		}

		const value = target[prop as keyof typeof target];
		if (is(value, Column)) {
			return new Proxy(value as AnyColumn, new ColumnAliasProxyHandler(new Proxy(target, this)));
		}

		return value;
	}
}
```
Sources: [drizzle-orm/src/alias.ts:24-75](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/alias.ts#L24-L75)

The proxy mechanism ensures that references to columns or nested relations inherit the modified table context without mutating the underlying schema definitions. Dialect query builders such as SQLiteDialect incorporate these proxy utilities to handle self-joins, derived tables, and subquery projections drizzle-orm/src/sqlite-core/dialect.ts, drizzle-orm/src/singlestore-core/dialect.ts.

```typescript
export function aliasedTable<T extends Table | View>(
	table: T,
	tableAlias: string,
): T {
	return new Proxy(table, new TableAliasProxyHandler(tableAlias, false)) as any;
}

export function aliasedRelation<T extends Relation>(relation: T, tableAlias: string): T {
	return new Proxy(relation, new RelationTableAliasProxyHandler(tableAlias));
}

export function aliasedTableColumn<T extends AnyColumn>(column: T, tableAlias: string): T {
	return new Proxy(
		column,
		new ColumnAliasProxyHandler(new Proxy(column.table, new TableAliasProxyHandler(tableAlias, false))),
	);
}

```
Sources: [drizzle-orm/src/alias.ts:91-108](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/alias.ts#L91-L108)

> [!NOTE]
> `TableAliasProxyHandler` conditionally overrides `Table.Symbol.OriginalName` based on the boolean flag `replaceOriginalName`, allowing subqueries to retain or overwrite their underlying table identifier during compilation.
> 
> Sources: [drizzle-orm/src/alias.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/alias.ts#L27-L40)

### SQL Expression Rewrites

When queries contain nested expressions, subqueries, or aliased chunks, column references within the AST must be recursively updated to match the active table alias. The `mapColumnsInSQLToAlias` function inspects query chunks and wraps columns and subqueries with the designated alias proxy drizzle-orm/src/alias.ts.

```typescript
export function mapColumnsInSQLToAlias(query: SQL, alias: string): SQL {
	return sql.join(query.queryChunks.map((c) => {
		if (is(c, Column)) {
			return aliasedTableColumn(c, alias);
		}
		if (is(c, SQL)) {
			return mapColumnsInSQLToAlias(c, alias);
		}
		if (is(c, SQL.Aliased)) {
			return mapColumnsInAliasedSQLToAlias(c, alias);
		}
		return c;
	}));
}
```
Sources: [drizzle-orm/src/alias.ts:113-126](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/alias.ts#L113-L126)

| Proxy Handler | Target Entity | Intercepted Symbols / Properties | Purpose |
| --- | --- | --- | --- |
| `ColumnAliasProxyHandler` | `Column` | `'table'` | Binds column references to the aliased table or view container. |
| `TableAliasProxyHandler` | `Table` \| `View` | `IsAlias`, `Name`, `OriginalName`, `Columns`, `ViewBaseConfig` | Remaps table identifiers, flags, and column maps to use alias names. |
| `RelationTableAliasProxyHandler` | `Relation` | `'sourceTable'` | Recursively proxies relation source tables for relational graph queries. |

Sources: [drizzle-orm/src/alias.ts:10-89](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/alias.ts#L10-L89)

## Constraint Resolution and Schema Utilities

### Runtime Table Configuration and Entity Inspection

Table configurations, schema constraints, and builder metadata are inspected and resolved at runtime via utility functions like `getTableConfig`. For SQLite tables, this function iterates over column definitions, inline foreign keys, and extra configuration builders, instantiating and categorizing indexes, checks, unique constraints, primary keys, and foreign keys into a unified configuration object drizzle-orm/src/sqlite-core/utils.ts.

```typescript
export function getTableConfig<TTable extends SQLiteTable>(table: TTable) {
	const columns = Object.values(table[SQLiteTable.Symbol.Columns]);
	const indexes: Index[] = [];
	const checks: Check[] = [];
	const primaryKeys: PrimaryKey[] = [];
	const uniqueConstraints: UniqueConstraint[] = [];
	const foreignKeys: ForeignKey[] = Object.values(table[SQLiteTable.Symbol.InlineForeignKeys]);
	const name = table[Table.Symbol.Name];

	const extraConfigBuilder = table[SQLiteTable.Symbol.ExtraConfigBuilder];

	if (extraConfigBuilder !== undefined) {
		const extraConfig = extraConfigBuilder(table[SQLiteTable.Symbol.Columns]);
		const extraValues = Array.isArray(extraConfig) ? extraConfig.flat(1) as any[] : Object.values(extraConfig);
		for (const builder of Object.values(extraValues)) {
			if (is(builder, IndexBuilder)) {
				indexes.push(builder.build(table));
			} else if (is(builder, CheckBuilder)) {
				checks.push(builder.build(table));
			} else if (is(builder, UniqueConstraintBuilder)) {
				uniqueConstraints.push(builder.build(table));
			} else if (is(builder, PrimaryKeyBuilder)) {
				primaryKeys.push(builder.build(table));
			} else if (is(builder, ForeignKeyBuilder)) {
				foreignKeys.push(builder.build(table));
			}
		}
	}

	return {
		columns,
		indexes,
		foreignKeys,
		checks,
		primaryKeys,
		uniqueConstraints,
		name,
	};
}
```
Sources: [drizzle-orm/src/sqlite-core/utils.ts:19-57](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/sqlite-core/utils.ts#L19-L57)

Entity resolution checks use type guards to differentiate builder instances such as `IndexBuilder`, `CheckBuilder`, `UniqueConstraintBuilder`, `PrimaryKeyBuilder`, and `ForeignKeyBuilder`, ensuring each constraint is correctly built against the target table instance prior to AST compilation drizzle-orm/src/sqlite-core/utils.ts.

```typescript
for (const builder of Object.values(extraValues)) {
	if (is(builder, IndexBuilder)) {
		indexes.push(builder.build(table));
	} else if (is(builder, CheckBuilder)) {
		checks.push(builder.build(table));
	} else if (is(builder, UniqueConstraintBuilder)) {
		uniqueConstraints.push(builder.build(table));
	} else if (is(builder, PrimaryKeyBuilder)) {
		primaryKeys.push(builder.build(table));
	} else if (is(builder, ForeignKeyBuilder)) {
		foreignKeys.push(builder.build(table));
	}
}
```
Sources: [drizzle-orm/src/sqlite-core/utils.ts:33-45](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/sqlite-core/utils.ts#L33-L45)

> [!NOTE]
> `extractUsedTable` evaluates table inputs across `SQLiteTable`, `Subquery`, `SQLiteViewBase`, and `SQL` expression instances to resolve base table names and used table arrays during AST traversal.
> 
> Sources: [drizzle-orm/src/sqlite-core/utils.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/sqlite-core/utils.ts#L59-L70)

### Index Builders and Dialect-Specific Options

Index configuration differs across dialects to accommodate specialized storage parameters, concurrency flags, and locking algorithms. PostgreSQL index builders support partial index conditions via `where`, storage options via `with`, access methods, and concurrency modifiers via `concurrently` and `only` drizzle-orm/src/pg-core/indexes.ts.

```typescript
interface IndexConfig {
	name?: string;

	columns: Partial<IndexedColumn | SQL>[];

	/**
	 * If true, the index will be created as `create unique index` instead of `create index`.
	 */
	unique: boolean;

	/**
	 * If true, the index will be created as `create index concurrently` instead of `create index`.
	 */
	concurrently?: boolean;

	/**
	 * If true, the index will be created as `create index ... on only <table>` instead of `create index ... on <table>`.
	 */
	only: boolean;

	/**
	 * Condition for partial index.
	 */
	where?: SQL;

	/**
	 * The optional WITH clause specifies storage parameters for the index
	 */
	with?: Record<string, any>;

	/**
	 * The optional WITH clause method for the index
	 */
	method?: 'btree' | string;
}
```
Sources: [drizzle-orm/src/pg-core/indexes.ts:8-42](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/pg-core/indexes.ts#L8-L42)

MySQL index builders manage index construction algorithms and locks directly within their configuration contracts drizzle-orm/src/mysql-core/indexes.ts.

```typescript
interface IndexConfig {
	name: string;

	columns: IndexColumn[];

	/**
	 * If true, the index will be created as `create unique index` instead of `create index`.
	 */
	unique?: boolean;

	/**
	 * If set, the index will be created as `create index ... using { 'btree' | 'hash' }`.
	 */
	using?: 'btree' | 'hash';

	/**
	 * If set, the index will be created as `create index ... algorithm { 'default' | 'inplace' | 'copy' }`.
	 */
	algorithm?: 'default' | 'inplace' | 'copy';

	/**
	 * If set, adds locks to the index creation.
	 */
	lock?: 'default' | 'none' | 'shared' | 'exclusive';
}
```
Sources: [drizzle-orm/src/mysql-core/indexes.ts:6-30](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/mysql-core/indexes.ts#L6-L30)

| Index Configuration Property | Dialects Supported | Purpose / Values |
| --- | --- | --- |
| `name` | PostgreSQL, MySQL | Optional or required string identifier for the index. |
| `columns` | PostgreSQL, MySQL | Array of indexed columns or raw `SQL` expressions. |
| `unique` | PostgreSQL, MySQL | Boolean flag creating a unique index. |
| `concurrently` | PostgreSQL | Creates the index without locking concurrent writes (`create index concurrently`). |
| `only` | PostgreSQL | Restricts index creation to the specified table without inheritance children. |
| `where` | PostgreSQL | Defines a partial index condition using a `SQL` expression. |
| `method` | PostgreSQL, MySQL | Index access method (e.g., `'btree'`, `'hash'`, `'gist'`, `'gin'`, `'brin'`, `'hnsw'`, `'ivfflat'`). |
| `algorithm` | MySQL | Specifies index creation algorithm: `'default'`, `'inplace'`, `'copy'`. |
| `lock` | MySQL | Adds concurrency locks during index creation: `'default'`, `'none'`, `'shared'`, `'exclusive'`. |

Sources: [drizzle-orm/src/pg-core/indexes.ts:8-42](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/pg-core/indexes.ts#L8-L42), [drizzle-orm/src/mysql-core/indexes.ts:6-30](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/mysql-core/indexes.ts#L6-L30)

## Related

- [Dialects And Schema Schema Definition](https://www.doc0.dev/docs/e1b68fed-3c4e-4c95-b2ba-ebf050f78025/technical/dialects-and-schema/dialects-and-schema-schema-definition)
- [Relational Query Engine](https://www.doc0.dev/docs/e1b68fed-3c4e-4c95-b2ba-ebf050f78025/technical/core-architecture/relational-query-engine)


## Sitemap

See the full [sitemap](https://www.doc0.dev/docs/e1b68fed-3c4e-4c95-b2ba-ebf050f78025/llms.txt) for all pages in this wiki.
