From ecd9b5742334c512d7b2caced03b4da6a22bb9cb Mon Sep 17 00:00:00 2001 From: Gabriel Cipriano Date: Wed, 26 Feb 2025 11:30:42 +0100 Subject: [PATCH 1/7] chore: clone mysql-core as googlesql --- drizzle-orm/src/googlesql/alias.ts | 11 + drizzle-orm/src/googlesql/checks.ts | 32 + drizzle-orm/src/googlesql/columns/all.ts | 58 + drizzle-orm/src/googlesql/columns/bigint.ts | 118 ++ drizzle-orm/src/googlesql/columns/binary.ts | 64 + drizzle-orm/src/googlesql/columns/boolean.ts | 55 + drizzle-orm/src/googlesql/columns/char.ts | 85 ++ drizzle-orm/src/googlesql/columns/common.ts | 154 ++ drizzle-orm/src/googlesql/columns/custom.ts | 232 +++ .../src/googlesql/columns/date.common.ts | 42 + drizzle-orm/src/googlesql/columns/date.ts | 113 ++ drizzle-orm/src/googlesql/columns/datetime.ts | 135 ++ drizzle-orm/src/googlesql/columns/decimal.ts | 80 + drizzle-orm/src/googlesql/columns/double.ts | 76 + drizzle-orm/src/googlesql/columns/enum.ts | 69 + drizzle-orm/src/googlesql/columns/float.ts | 76 + drizzle-orm/src/googlesql/columns/index.ts | 25 + drizzle-orm/src/googlesql/columns/int.ts | 67 + drizzle-orm/src/googlesql/columns/json.ts | 47 + .../src/googlesql/columns/mediumint.ts | 67 + drizzle-orm/src/googlesql/columns/real.ts | 75 + drizzle-orm/src/googlesql/columns/serial.ts | 72 + drizzle-orm/src/googlesql/columns/smallint.ts | 67 + drizzle-orm/src/googlesql/columns/text.ts | 109 ++ drizzle-orm/src/googlesql/columns/time.ts | 67 + .../src/googlesql/columns/timestamp.ts | 125 ++ drizzle-orm/src/googlesql/columns/tinyint.ts | 67 + .../src/googlesql/columns/varbinary.ts | 65 + drizzle-orm/src/googlesql/columns/varchar.ts | 84 ++ drizzle-orm/src/googlesql/columns/year.ts | 45 + drizzle-orm/src/googlesql/db.ts | 532 +++++++ drizzle-orm/src/googlesql/dialect.ts | 1148 +++++++++++++++ drizzle-orm/src/googlesql/expressions.ts | 25 + drizzle-orm/src/googlesql/foreign-keys.ts | 126 ++ drizzle-orm/src/googlesql/index.ts | 17 + drizzle-orm/src/googlesql/indexes.ts | 108 ++ drizzle-orm/src/googlesql/primary-keys.ts | 63 + .../src/googlesql/query-builders/count.ts | 79 + .../src/googlesql/query-builders/delete.ts | 207 +++ .../src/googlesql/query-builders/index.ts | 6 + .../src/googlesql/query-builders/insert.ts | 330 +++++ .../googlesql/query-builders/query-builder.ts | 116 ++ .../src/googlesql/query-builders/query.ts | 157 ++ .../src/googlesql/query-builders/select.ts | 1290 +++++++++++++++++ .../googlesql/query-builders/select.types.ts | 440 ++++++ .../src/googlesql/query-builders/update.ts | 246 ++++ drizzle-orm/src/googlesql/schema.ts | 40 + drizzle-orm/src/googlesql/session.ts | 157 ++ drizzle-orm/src/googlesql/subquery.ts | 35 + drizzle-orm/src/googlesql/table.ts | 229 +++ .../src/googlesql/unique-constraint.ts | 65 + drizzle-orm/src/googlesql/utils.ts | 80 + drizzle-orm/src/googlesql/view-base.ts | 15 + drizzle-orm/src/googlesql/view-common.ts | 1 + drizzle-orm/src/googlesql/view.ts | 199 +++ 55 files changed, 8093 insertions(+) create mode 100644 drizzle-orm/src/googlesql/alias.ts create mode 100644 drizzle-orm/src/googlesql/checks.ts create mode 100644 drizzle-orm/src/googlesql/columns/all.ts create mode 100644 drizzle-orm/src/googlesql/columns/bigint.ts create mode 100644 drizzle-orm/src/googlesql/columns/binary.ts create mode 100644 drizzle-orm/src/googlesql/columns/boolean.ts create mode 100644 drizzle-orm/src/googlesql/columns/char.ts create mode 100644 drizzle-orm/src/googlesql/columns/common.ts create mode 100644 drizzle-orm/src/googlesql/columns/custom.ts create mode 100644 drizzle-orm/src/googlesql/columns/date.common.ts create mode 100644 drizzle-orm/src/googlesql/columns/date.ts create mode 100644 drizzle-orm/src/googlesql/columns/datetime.ts create mode 100644 drizzle-orm/src/googlesql/columns/decimal.ts create mode 100644 drizzle-orm/src/googlesql/columns/double.ts create mode 100644 drizzle-orm/src/googlesql/columns/enum.ts create mode 100644 drizzle-orm/src/googlesql/columns/float.ts create mode 100644 drizzle-orm/src/googlesql/columns/index.ts create mode 100644 drizzle-orm/src/googlesql/columns/int.ts create mode 100644 drizzle-orm/src/googlesql/columns/json.ts create mode 100644 drizzle-orm/src/googlesql/columns/mediumint.ts create mode 100644 drizzle-orm/src/googlesql/columns/real.ts create mode 100644 drizzle-orm/src/googlesql/columns/serial.ts create mode 100644 drizzle-orm/src/googlesql/columns/smallint.ts create mode 100644 drizzle-orm/src/googlesql/columns/text.ts create mode 100644 drizzle-orm/src/googlesql/columns/time.ts create mode 100644 drizzle-orm/src/googlesql/columns/timestamp.ts create mode 100644 drizzle-orm/src/googlesql/columns/tinyint.ts create mode 100644 drizzle-orm/src/googlesql/columns/varbinary.ts create mode 100644 drizzle-orm/src/googlesql/columns/varchar.ts create mode 100644 drizzle-orm/src/googlesql/columns/year.ts create mode 100644 drizzle-orm/src/googlesql/db.ts create mode 100644 drizzle-orm/src/googlesql/dialect.ts create mode 100644 drizzle-orm/src/googlesql/expressions.ts create mode 100644 drizzle-orm/src/googlesql/foreign-keys.ts create mode 100644 drizzle-orm/src/googlesql/index.ts create mode 100644 drizzle-orm/src/googlesql/indexes.ts create mode 100644 drizzle-orm/src/googlesql/primary-keys.ts create mode 100644 drizzle-orm/src/googlesql/query-builders/count.ts create mode 100644 drizzle-orm/src/googlesql/query-builders/delete.ts create mode 100644 drizzle-orm/src/googlesql/query-builders/index.ts create mode 100644 drizzle-orm/src/googlesql/query-builders/insert.ts create mode 100644 drizzle-orm/src/googlesql/query-builders/query-builder.ts create mode 100644 drizzle-orm/src/googlesql/query-builders/query.ts create mode 100644 drizzle-orm/src/googlesql/query-builders/select.ts create mode 100644 drizzle-orm/src/googlesql/query-builders/select.types.ts create mode 100644 drizzle-orm/src/googlesql/query-builders/update.ts create mode 100644 drizzle-orm/src/googlesql/schema.ts create mode 100644 drizzle-orm/src/googlesql/session.ts create mode 100644 drizzle-orm/src/googlesql/subquery.ts create mode 100644 drizzle-orm/src/googlesql/table.ts create mode 100644 drizzle-orm/src/googlesql/unique-constraint.ts create mode 100644 drizzle-orm/src/googlesql/utils.ts create mode 100644 drizzle-orm/src/googlesql/view-base.ts create mode 100644 drizzle-orm/src/googlesql/view-common.ts create mode 100644 drizzle-orm/src/googlesql/view.ts diff --git a/drizzle-orm/src/googlesql/alias.ts b/drizzle-orm/src/googlesql/alias.ts new file mode 100644 index 0000000000..8320c5533d --- /dev/null +++ b/drizzle-orm/src/googlesql/alias.ts @@ -0,0 +1,11 @@ +import { TableAliasProxyHandler } from '~/alias.ts'; +import type { BuildAliasTable } from './query-builders/select.types.ts'; +import type { MySqlTable } from './table.ts'; +import type { MySqlViewBase } from './view-base.ts'; + +export function alias( + table: TTable, + alias: TAlias, +): BuildAliasTable { + return new Proxy(table, new TableAliasProxyHandler(alias, false)) as any; +} diff --git a/drizzle-orm/src/googlesql/checks.ts b/drizzle-orm/src/googlesql/checks.ts new file mode 100644 index 0000000000..af9a29f6ae --- /dev/null +++ b/drizzle-orm/src/googlesql/checks.ts @@ -0,0 +1,32 @@ +import { entityKind } from '~/entity.ts'; +import type { SQL } from '~/sql/sql.ts'; +import type { MySqlTable } from './table.ts'; + +export class CheckBuilder { + static readonly [entityKind]: string = 'MySqlCheckBuilder'; + + protected brand!: 'MySqlConstraintBuilder'; + + constructor(public name: string, public value: SQL) {} + + /** @internal */ + build(table: MySqlTable): Check { + return new Check(table, this); + } +} + +export class Check { + static readonly [entityKind]: string = 'MySqlCheck'; + + readonly name: string; + readonly value: SQL; + + constructor(public table: MySqlTable, builder: CheckBuilder) { + this.name = builder.name; + this.value = builder.value; + } +} + +export function check(name: string, value: SQL): CheckBuilder { + return new CheckBuilder(name, value); +} diff --git a/drizzle-orm/src/googlesql/columns/all.ts b/drizzle-orm/src/googlesql/columns/all.ts new file mode 100644 index 0000000000..44c03eff0c --- /dev/null +++ b/drizzle-orm/src/googlesql/columns/all.ts @@ -0,0 +1,58 @@ +import { bigint } from './bigint.ts'; +import { binary } from './binary.ts'; +import { boolean } from './boolean.ts'; +import { char } from './char.ts'; +import { customType } from './custom.ts'; +import { date } from './date.ts'; +import { datetime } from './datetime.ts'; +import { decimal } from './decimal.ts'; +import { double } from './double.ts'; +import { mysqlEnum } from './enum.ts'; +import { float } from './float.ts'; +import { int } from './int.ts'; +import { json } from './json.ts'; +import { mediumint } from './mediumint.ts'; +import { real } from './real.ts'; +import { serial } from './serial.ts'; +import { smallint } from './smallint.ts'; +import { longtext, mediumtext, text, tinytext } from './text.ts'; +import { time } from './time.ts'; +import { timestamp } from './timestamp.ts'; +import { tinyint } from './tinyint.ts'; +import { varbinary } from './varbinary.ts'; +import { varchar } from './varchar.ts'; +import { year } from './year.ts'; + +export function getMySqlColumnBuilders() { + return { + bigint, + binary, + boolean, + char, + customType, + date, + datetime, + decimal, + double, + mysqlEnum, + float, + int, + json, + mediumint, + real, + serial, + smallint, + text, + time, + timestamp, + tinyint, + varbinary, + varchar, + year, + longtext, + mediumtext, + tinytext, + }; +} + +export type MySqlColumnBuilders = ReturnType; diff --git a/drizzle-orm/src/googlesql/columns/bigint.ts b/drizzle-orm/src/googlesql/columns/bigint.ts new file mode 100644 index 0000000000..0973a13461 --- /dev/null +++ b/drizzle-orm/src/googlesql/columns/bigint.ts @@ -0,0 +1,118 @@ +import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; +import type { ColumnBaseConfig } from '~/column.ts'; +import { entityKind } from '~/entity.ts'; +import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import { getColumnNameAndConfig } from '~/utils.ts'; +import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; + +export type MySqlBigInt53BuilderInitial = MySqlBigInt53Builder<{ + name: TName; + dataType: 'number'; + columnType: 'MySqlBigInt53'; + data: number; + driverParam: number | string; + enumValues: undefined; +}>; + +export class MySqlBigInt53Builder> + extends MySqlColumnBuilderWithAutoIncrement +{ + static override readonly [entityKind]: string = 'MySqlBigInt53Builder'; + + constructor(name: T['name'], unsigned: boolean = false) { + super(name, 'number', 'MySqlBigInt53'); + this.config.unsigned = unsigned; + } + + /** @internal */ + override build( + table: AnyMySqlTable<{ name: TTableName }>, + ): MySqlBigInt53> { + return new MySqlBigInt53>( + table, + this.config as ColumnBuilderRuntimeConfig, + ); + } +} + +export class MySqlBigInt53> + extends MySqlColumnWithAutoIncrement +{ + static override readonly [entityKind]: string = 'MySqlBigInt53'; + + getSQLType(): string { + return `bigint${this.config.unsigned ? ' unsigned' : ''}`; + } + + override mapFromDriverValue(value: number | string): number { + if (typeof value === 'number') { + return value; + } + return Number(value); + } +} + +export type MySqlBigInt64BuilderInitial = MySqlBigInt64Builder<{ + name: TName; + dataType: 'bigint'; + columnType: 'MySqlBigInt64'; + data: bigint; + driverParam: string; + enumValues: undefined; +}>; + +export class MySqlBigInt64Builder> + extends MySqlColumnBuilderWithAutoIncrement +{ + static override readonly [entityKind]: string = 'MySqlBigInt64Builder'; + + constructor(name: T['name'], unsigned: boolean = false) { + super(name, 'bigint', 'MySqlBigInt64'); + this.config.unsigned = unsigned; + } + + /** @internal */ + override build( + table: AnyMySqlTable<{ name: TTableName }>, + ): MySqlBigInt64> { + return new MySqlBigInt64>( + table, + this.config as ColumnBuilderRuntimeConfig, + ); + } +} + +export class MySqlBigInt64> + extends MySqlColumnWithAutoIncrement +{ + static override readonly [entityKind]: string = 'MySqlBigInt64'; + + getSQLType(): string { + return `bigint${this.config.unsigned ? ' unsigned' : ''}`; + } + + // eslint-disable-next-line unicorn/prefer-native-coercion-functions + override mapFromDriverValue(value: string): bigint { + return BigInt(value); + } +} + +export interface MySqlBigIntConfig { + mode: T; + unsigned?: boolean; +} + +export function bigint( + config: MySqlBigIntConfig, +): TMode extends 'number' ? MySqlBigInt53BuilderInitial<''> : MySqlBigInt64BuilderInitial<''>; +export function bigint( + name: TName, + config: MySqlBigIntConfig, +): TMode extends 'number' ? MySqlBigInt53BuilderInitial : MySqlBigInt64BuilderInitial; +export function bigint(a?: string | MySqlBigIntConfig, b?: MySqlBigIntConfig) { + const { name, config } = getColumnNameAndConfig(a, b); + if (config.mode === 'number') { + return new MySqlBigInt53Builder(name, config.unsigned); + } + return new MySqlBigInt64Builder(name, config.unsigned); +} diff --git a/drizzle-orm/src/googlesql/columns/binary.ts b/drizzle-orm/src/googlesql/columns/binary.ts new file mode 100644 index 0000000000..e670066536 --- /dev/null +++ b/drizzle-orm/src/googlesql/columns/binary.ts @@ -0,0 +1,64 @@ +import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; +import type { ColumnBaseConfig } from '~/column.ts'; +import { entityKind } from '~/entity.ts'; +import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import { getColumnNameAndConfig } from '~/utils.ts'; +import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; + +export type MySqlBinaryBuilderInitial = MySqlBinaryBuilder<{ + name: TName; + dataType: 'string'; + columnType: 'MySqlBinary'; + data: string; + driverParam: string; + enumValues: undefined; +}>; + +export class MySqlBinaryBuilder> extends MySqlColumnBuilder< + T, + MySqlBinaryConfig +> { + static override readonly [entityKind]: string = 'MySqlBinaryBuilder'; + + constructor(name: T['name'], length: number | undefined) { + super(name, 'string', 'MySqlBinary'); + this.config.length = length; + } + + /** @internal */ + override build( + table: AnyMySqlTable<{ name: TTableName }>, + ): MySqlBinary> { + return new MySqlBinary>(table, this.config as ColumnBuilderRuntimeConfig); + } +} + +export class MySqlBinary> extends MySqlColumn< + T, + MySqlBinaryConfig +> { + static override readonly [entityKind]: string = 'MySqlBinary'; + + length: number | undefined = this.config.length; + + getSQLType(): string { + return this.length === undefined ? `binary` : `binary(${this.length})`; + } +} + +export interface MySqlBinaryConfig { + length?: number; +} + +export function binary(): MySqlBinaryBuilderInitial<''>; +export function binary( + config?: MySqlBinaryConfig, +): MySqlBinaryBuilderInitial<''>; +export function binary( + name: TName, + config?: MySqlBinaryConfig, +): MySqlBinaryBuilderInitial; +export function binary(a?: string | MySqlBinaryConfig, b: MySqlBinaryConfig = {}) { + const { name, config } = getColumnNameAndConfig(a, b); + return new MySqlBinaryBuilder(name, config.length); +} diff --git a/drizzle-orm/src/googlesql/columns/boolean.ts b/drizzle-orm/src/googlesql/columns/boolean.ts new file mode 100644 index 0000000000..2057496b6b --- /dev/null +++ b/drizzle-orm/src/googlesql/columns/boolean.ts @@ -0,0 +1,55 @@ +import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; +import type { ColumnBaseConfig } from '~/column.ts'; +import { entityKind } from '~/entity.ts'; +import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; + +export type MySqlBooleanBuilderInitial = MySqlBooleanBuilder<{ + name: TName; + dataType: 'boolean'; + columnType: 'MySqlBoolean'; + data: boolean; + driverParam: number | boolean; + enumValues: undefined; +}>; + +export class MySqlBooleanBuilder> + extends MySqlColumnBuilder +{ + static override readonly [entityKind]: string = 'MySqlBooleanBuilder'; + + constructor(name: T['name']) { + super(name, 'boolean', 'MySqlBoolean'); + } + + /** @internal */ + override build( + table: AnyMySqlTable<{ name: TTableName }>, + ): MySqlBoolean> { + return new MySqlBoolean>( + table, + this.config as ColumnBuilderRuntimeConfig, + ); + } +} + +export class MySqlBoolean> extends MySqlColumn { + static override readonly [entityKind]: string = 'MySqlBoolean'; + + getSQLType(): string { + return 'boolean'; + } + + override mapFromDriverValue(value: number | boolean): boolean { + if (typeof value === 'boolean') { + return value; + } + return value === 1; + } +} + +export function boolean(): MySqlBooleanBuilderInitial<''>; +export function boolean(name: TName): MySqlBooleanBuilderInitial; +export function boolean(name?: string) { + return new MySqlBooleanBuilder(name ?? ''); +} diff --git a/drizzle-orm/src/googlesql/columns/char.ts b/drizzle-orm/src/googlesql/columns/char.ts new file mode 100644 index 0000000000..55743a5d4a --- /dev/null +++ b/drizzle-orm/src/googlesql/columns/char.ts @@ -0,0 +1,85 @@ +import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; +import type { ColumnBaseConfig } from '~/column.ts'; +import { entityKind } from '~/entity.ts'; +import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import { getColumnNameAndConfig, type Writable } from '~/utils.ts'; +import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; + +export type MySqlCharBuilderInitial< + TName extends string, + TEnum extends [string, ...string[]], + TLength extends number | undefined, +> = MySqlCharBuilder<{ + name: TName; + dataType: 'string'; + columnType: 'MySqlChar'; + data: TEnum[number]; + driverParam: number | string; + enumValues: TEnum; + length: TLength; +}>; + +export class MySqlCharBuilder< + T extends ColumnBuilderBaseConfig<'string', 'MySqlChar'> & { length?: number | undefined }, +> extends MySqlColumnBuilder< + T, + MySqlCharConfig, + { length: T['length'] } +> { + static override readonly [entityKind]: string = 'MySqlCharBuilder'; + + constructor(name: T['name'], config: MySqlCharConfig) { + super(name, 'string', 'MySqlChar'); + this.config.length = config.length; + this.config.enum = config.enum; + } + + /** @internal */ + override build( + table: AnyMySqlTable<{ name: TTableName }>, + ): MySqlChar & { length: T['length']; enumValues: T['enumValues'] }> { + return new MySqlChar & { length: T['length']; enumValues: T['enumValues'] }>( + table, + this.config as ColumnBuilderRuntimeConfig, + ); + } +} + +export class MySqlChar & { length?: number | undefined }> + extends MySqlColumn, { length: T['length'] }> +{ + static override readonly [entityKind]: string = 'MySqlChar'; + + readonly length: T['length'] = this.config.length; + override readonly enumValues = this.config.enum; + + getSQLType(): string { + return this.length === undefined ? `char` : `char(${this.length})`; + } +} + +export interface MySqlCharConfig< + TEnum extends readonly string[] | string[] | undefined = readonly string[] | string[] | undefined, + TLength extends number | undefined = number | undefined, +> { + enum?: TEnum; + length?: TLength; +} + +export function char(): MySqlCharBuilderInitial<'', [string, ...string[]], undefined>; +export function char, L extends number | undefined>( + config?: MySqlCharConfig, L>, +): MySqlCharBuilderInitial<'', Writable, L>; +export function char< + TName extends string, + U extends string, + T extends Readonly<[U, ...U[]]>, + L extends number | undefined, +>( + name: TName, + config?: MySqlCharConfig, L>, +): MySqlCharBuilderInitial, L>; +export function char(a?: string | MySqlCharConfig, b: MySqlCharConfig = {}): any { + const { name, config } = getColumnNameAndConfig(a, b); + return new MySqlCharBuilder(name, config as any); +} diff --git a/drizzle-orm/src/googlesql/columns/common.ts b/drizzle-orm/src/googlesql/columns/common.ts new file mode 100644 index 0000000000..289c420ae7 --- /dev/null +++ b/drizzle-orm/src/googlesql/columns/common.ts @@ -0,0 +1,154 @@ +import { ColumnBuilder } from '~/column-builder.ts'; +import type { + ColumnBuilderBase, + ColumnBuilderBaseConfig, + ColumnBuilderExtraConfig, + ColumnBuilderRuntimeConfig, + ColumnDataType, + HasDefault, + HasGenerated, + IsAutoincrement, + MakeColumnConfig, +} from '~/column-builder.ts'; +import type { ColumnBaseConfig } from '~/column.ts'; +import { Column } from '~/column.ts'; +import { entityKind } from '~/entity.ts'; +import type { ForeignKey, UpdateDeleteAction } from '~/mysql-core/foreign-keys.ts'; +import { ForeignKeyBuilder } from '~/mysql-core/foreign-keys.ts'; +import type { AnyMySqlTable, MySqlTable } from '~/mysql-core/table.ts'; +import type { SQL } from '~/sql/sql.ts'; +import type { Update } from '~/utils.ts'; +import { uniqueKeyName } from '../unique-constraint.ts'; + +export interface ReferenceConfig { + ref: () => MySqlColumn; + actions: { + onUpdate?: UpdateDeleteAction; + onDelete?: UpdateDeleteAction; + }; +} + +export interface MySqlColumnBuilderBase< + T extends ColumnBuilderBaseConfig = ColumnBuilderBaseConfig, + TTypeConfig extends object = object, +> extends ColumnBuilderBase {} + +export interface MySqlGeneratedColumnConfig { + mode?: 'virtual' | 'stored'; +} + +export abstract class MySqlColumnBuilder< + T extends ColumnBuilderBaseConfig = ColumnBuilderBaseConfig & { + data: any; + }, + TRuntimeConfig extends object = object, + TTypeConfig extends object = object, + TExtraConfig extends ColumnBuilderExtraConfig = ColumnBuilderExtraConfig, +> extends ColumnBuilder + implements MySqlColumnBuilderBase +{ + static override readonly [entityKind]: string = 'MySqlColumnBuilder'; + + private foreignKeyConfigs: ReferenceConfig[] = []; + + references(ref: ReferenceConfig['ref'], actions: ReferenceConfig['actions'] = {}): this { + this.foreignKeyConfigs.push({ ref, actions }); + return this; + } + + unique(name?: string): this { + this.config.isUnique = true; + this.config.uniqueName = name; + return this; + } + + generatedAlwaysAs(as: SQL | T['data'] | (() => SQL), config?: MySqlGeneratedColumnConfig): HasGenerated { + this.config.generated = { + as, + type: 'always', + mode: config?.mode ?? 'virtual', + }; + return this as any; + } + + /** @internal */ + buildForeignKeys(column: MySqlColumn, table: MySqlTable): ForeignKey[] { + return this.foreignKeyConfigs.map(({ ref, actions }) => { + return ((ref, actions) => { + const builder = new ForeignKeyBuilder(() => { + const foreignColumn = ref(); + return { columns: [column], foreignColumns: [foreignColumn] }; + }); + if (actions.onUpdate) { + builder.onUpdate(actions.onUpdate); + } + if (actions.onDelete) { + builder.onDelete(actions.onDelete); + } + return builder.build(table); + })(ref, actions); + }); + } + + /** @internal */ + abstract build( + table: AnyMySqlTable<{ name: TTableName }>, + ): MySqlColumn>; +} + +// To understand how to use `MySqlColumn` and `AnyMySqlColumn`, see `Column` and `AnyColumn` documentation. +export abstract class MySqlColumn< + T extends ColumnBaseConfig = ColumnBaseConfig, + TRuntimeConfig extends object = {}, + TTypeConfig extends object = {}, +> extends Column { + static override readonly [entityKind]: string = 'MySqlColumn'; + + constructor( + override readonly table: MySqlTable, + config: ColumnBuilderRuntimeConfig, + ) { + if (!config.uniqueName) { + config.uniqueName = uniqueKeyName(table, [config.name]); + } + super(table, config); + } +} + +export type AnyMySqlColumn> = {}> = MySqlColumn< + Required, TPartial>> +>; + +export interface MySqlColumnWithAutoIncrementConfig { + autoIncrement: boolean; +} + +export abstract class MySqlColumnBuilderWithAutoIncrement< + T extends ColumnBuilderBaseConfig = ColumnBuilderBaseConfig, + TRuntimeConfig extends object = object, + TExtraConfig extends ColumnBuilderExtraConfig = ColumnBuilderExtraConfig, +> extends MySqlColumnBuilder { + static override readonly [entityKind]: string = 'MySqlColumnBuilderWithAutoIncrement'; + + constructor(name: NonNullable, dataType: T['dataType'], columnType: T['columnType']) { + super(name, dataType, columnType); + this.config.autoIncrement = false; + } + + autoincrement(): IsAutoincrement> { + this.config.autoIncrement = true; + this.config.hasDefault = true; + return this as IsAutoincrement>; + } +} + +export abstract class MySqlColumnWithAutoIncrement< + T extends ColumnBaseConfig = ColumnBaseConfig, + TRuntimeConfig extends object = object, +> extends MySqlColumn { + static override readonly [entityKind]: string = 'MySqlColumnWithAutoIncrement'; + + readonly autoIncrement: boolean = this.config.autoIncrement; +} diff --git a/drizzle-orm/src/googlesql/columns/custom.ts b/drizzle-orm/src/googlesql/columns/custom.ts new file mode 100644 index 0000000000..50585bece1 --- /dev/null +++ b/drizzle-orm/src/googlesql/columns/custom.ts @@ -0,0 +1,232 @@ +import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; +import type { ColumnBaseConfig } from '~/column.ts'; +import { entityKind } from '~/entity.ts'; +import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import type { SQL } from '~/sql/sql.ts'; +import { type Equal, getColumnNameAndConfig } from '~/utils.ts'; +import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; + +export type ConvertCustomConfig> = + & { + name: TName; + dataType: 'custom'; + columnType: 'MySqlCustomColumn'; + data: T['data']; + driverParam: T['driverData']; + enumValues: undefined; + } + & (T['notNull'] extends true ? { notNull: true } : {}) + & (T['default'] extends true ? { hasDefault: true } : {}); + +export interface MySqlCustomColumnInnerConfig { + customTypeValues: CustomTypeValues; +} + +export class MySqlCustomColumnBuilder> + extends MySqlColumnBuilder< + T, + { + fieldConfig: CustomTypeValues['config']; + customTypeParams: CustomTypeParams; + }, + { + mysqlColumnBuilderBrand: 'MySqlCustomColumnBuilderBrand'; + } + > +{ + static override readonly [entityKind]: string = 'MySqlCustomColumnBuilder'; + + constructor( + name: T['name'], + fieldConfig: CustomTypeValues['config'], + customTypeParams: CustomTypeParams, + ) { + super(name, 'custom', 'MySqlCustomColumn'); + this.config.fieldConfig = fieldConfig; + this.config.customTypeParams = customTypeParams; + } + + /** @internal */ + build( + table: AnyMySqlTable<{ name: TTableName }>, + ): MySqlCustomColumn> { + return new MySqlCustomColumn>( + table, + this.config as ColumnBuilderRuntimeConfig, + ); + } +} + +export class MySqlCustomColumn> extends MySqlColumn { + static override readonly [entityKind]: string = 'MySqlCustomColumn'; + + private sqlName: string; + private mapTo?: (value: T['data']) => T['driverParam']; + private mapFrom?: (value: T['driverParam']) => T['data']; + + constructor( + table: AnyMySqlTable<{ name: T['tableName'] }>, + config: MySqlCustomColumnBuilder['config'], + ) { + super(table, config); + this.sqlName = config.customTypeParams.dataType(config.fieldConfig); + this.mapTo = config.customTypeParams.toDriver; + this.mapFrom = config.customTypeParams.fromDriver; + } + + getSQLType(): string { + return this.sqlName; + } + + override mapFromDriverValue(value: T['driverParam']): T['data'] { + return typeof this.mapFrom === 'function' ? this.mapFrom(value) : value as T['data']; + } + + override mapToDriverValue(value: T['data']): T['driverParam'] { + return typeof this.mapTo === 'function' ? this.mapTo(value) : value as T['data']; + } +} + +export type CustomTypeValues = { + /** + * Required type for custom column, that will infer proper type model + * + * Examples: + * + * If you want your column to be `string` type after selecting/or on inserting - use `data: string`. Like `text`, `varchar` + * + * If you want your column to be `number` type after selecting/or on inserting - use `data: number`. Like `integer` + */ + data: unknown; + + /** + * Type helper, that represents what type database driver is accepting for specific database data type + */ + driverData?: unknown; + + /** + * What config type should be used for {@link CustomTypeParams} `dataType` generation + */ + config?: Record; + + /** + * Whether the config argument should be required or not + * @default false + */ + configRequired?: boolean; + + /** + * If your custom data type should be notNull by default you can use `notNull: true` + * + * @example + * const customSerial = customType<{ data: number, notNull: true, default: true }>({ + * dataType() { + * return 'serial'; + * }, + * }); + */ + notNull?: boolean; + + /** + * If your custom data type has default you can use `default: true` + * + * @example + * const customSerial = customType<{ data: number, notNull: true, default: true }>({ + * dataType() { + * return 'serial'; + * }, + * }); + */ + default?: boolean; +}; + +export interface CustomTypeParams { + /** + * Database data type string representation, that is used for migrations + * @example + * ``` + * `jsonb`, `text` + * ``` + * + * If database data type needs additional params you can use them from `config` param + * @example + * ``` + * `varchar(256)`, `numeric(2,3)` + * ``` + * + * To make `config` be of specific type please use config generic in {@link CustomTypeValues} + * + * @example + * Usage example + * ``` + * dataType() { + * return 'boolean'; + * }, + * ``` + * Or + * ``` + * dataType(config) { + * return typeof config.length !== 'undefined' ? `varchar(${config.length})` : `varchar`; + * } + * ``` + */ + dataType: (config: T['config'] | (Equal extends true ? never : undefined)) => string; + + /** + * Optional mapping function, between user input and driver + * @example + * For example, when using jsonb we need to map JS/TS object to string before writing to database + * ``` + * toDriver(value: TData): string { + * return JSON.stringify(value); + * } + * ``` + */ + toDriver?: (value: T['data']) => T['driverData'] | SQL; + + /** + * Optional mapping function, that is responsible for data mapping from database to JS/TS code + * @example + * For example, when using timestamp we need to map string Date representation to JS Date + * ``` + * fromDriver(value: string): Date { + * return new Date(value); + * }, + * ``` + */ + fromDriver?: (value: T['driverData']) => T['data']; +} + +/** + * Custom mysql database data type generator + */ +export function customType( + customTypeParams: CustomTypeParams, +): Equal extends true ? { + & T['config']>( + fieldConfig: TConfig, + ): MySqlCustomColumnBuilder>; + ( + dbName: TName, + fieldConfig: T['config'], + ): MySqlCustomColumnBuilder>; + } + : { + (): MySqlCustomColumnBuilder>; + & T['config']>( + fieldConfig?: TConfig, + ): MySqlCustomColumnBuilder>; + ( + dbName: TName, + fieldConfig?: T['config'], + ): MySqlCustomColumnBuilder>; + } +{ + return ( + a?: TName | T['config'], + b?: T['config'], + ): MySqlCustomColumnBuilder> => { + const { name, config } = getColumnNameAndConfig(a, b); + return new MySqlCustomColumnBuilder(name as ConvertCustomConfig['name'], config, customTypeParams); + }; +} diff --git a/drizzle-orm/src/googlesql/columns/date.common.ts b/drizzle-orm/src/googlesql/columns/date.common.ts new file mode 100644 index 0000000000..75faad5b85 --- /dev/null +++ b/drizzle-orm/src/googlesql/columns/date.common.ts @@ -0,0 +1,42 @@ +import type { + ColumnBuilderBaseConfig, + ColumnBuilderExtraConfig, + ColumnDataType, + HasDefault, +} from '~/column-builder.ts'; +import type { ColumnBaseConfig } from '~/column.ts'; +import { entityKind } from '~/entity.ts'; +import { sql } from '~/sql/sql.ts'; +import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; + +export interface MySqlDateColumnBaseConfig { + hasOnUpdateNow: boolean; +} + +export abstract class MySqlDateColumnBaseBuilder< + T extends ColumnBuilderBaseConfig, + TRuntimeConfig extends object = object, + TExtraConfig extends ColumnBuilderExtraConfig = ColumnBuilderExtraConfig, +> extends MySqlColumnBuilder { + static override readonly [entityKind]: string = 'MySqlDateColumnBuilder'; + + defaultNow() { + return this.default(sql`(now())`); + } + + // "on update now" also adds an implicit default value to the column - https://dev.mysql.com/doc/refman/8.0/en/timestamp-initialization.html + onUpdateNow(): HasDefault { + this.config.hasOnUpdateNow = true; + this.config.hasDefault = true; + return this as HasDefault; + } +} + +export abstract class MySqlDateBaseColumn< + T extends ColumnBaseConfig, + TRuntimeConfig extends object = object, +> extends MySqlColumn { + static override readonly [entityKind]: string = 'MySqlDateColumn'; + + readonly hasOnUpdateNow: boolean = this.config.hasOnUpdateNow; +} diff --git a/drizzle-orm/src/googlesql/columns/date.ts b/drizzle-orm/src/googlesql/columns/date.ts new file mode 100644 index 0000000000..f3797ee6e7 --- /dev/null +++ b/drizzle-orm/src/googlesql/columns/date.ts @@ -0,0 +1,113 @@ +import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; +import type { ColumnBaseConfig } from '~/column.ts'; +import { entityKind } from '~/entity.ts'; +import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import { type Equal, getColumnNameAndConfig } from '~/utils.ts'; +import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; + +export type MySqlDateBuilderInitial = MySqlDateBuilder<{ + name: TName; + dataType: 'date'; + columnType: 'MySqlDate'; + data: Date; + driverParam: string | number; + enumValues: undefined; +}>; + +export class MySqlDateBuilder> extends MySqlColumnBuilder { + static override readonly [entityKind]: string = 'MySqlDateBuilder'; + + constructor(name: T['name']) { + super(name, 'date', 'MySqlDate'); + } + + /** @internal */ + override build( + table: AnyMySqlTable<{ name: TTableName }>, + ): MySqlDate> { + return new MySqlDate>(table, this.config as ColumnBuilderRuntimeConfig); + } +} + +export class MySqlDate> extends MySqlColumn { + static override readonly [entityKind]: string = 'MySqlDate'; + + constructor( + table: AnyMySqlTable<{ name: T['tableName'] }>, + config: MySqlDateBuilder['config'], + ) { + super(table, config); + } + + getSQLType(): string { + return `date`; + } + + override mapFromDriverValue(value: string): Date { + return new Date(value); + } +} + +export type MySqlDateStringBuilderInitial = MySqlDateStringBuilder<{ + name: TName; + dataType: 'string'; + columnType: 'MySqlDateString'; + data: string; + driverParam: string | number; + enumValues: undefined; +}>; + +export class MySqlDateStringBuilder> + extends MySqlColumnBuilder +{ + static override readonly [entityKind]: string = 'MySqlDateStringBuilder'; + + constructor(name: T['name']) { + super(name, 'string', 'MySqlDateString'); + } + + /** @internal */ + override build( + table: AnyMySqlTable<{ name: TTableName }>, + ): MySqlDateString> { + return new MySqlDateString>( + table, + this.config as ColumnBuilderRuntimeConfig, + ); + } +} + +export class MySqlDateString> extends MySqlColumn { + static override readonly [entityKind]: string = 'MySqlDateString'; + + constructor( + table: AnyMySqlTable<{ name: T['tableName'] }>, + config: MySqlDateStringBuilder['config'], + ) { + super(table, config); + } + + getSQLType(): string { + return `date`; + } +} + +export interface MySqlDateConfig { + mode?: TMode; +} + +export function date(): MySqlDateBuilderInitial<''>; +export function date( + config?: MySqlDateConfig, +): Equal extends true ? MySqlDateStringBuilderInitial<''> : MySqlDateBuilderInitial<''>; +export function date( + name: TName, + config?: MySqlDateConfig, +): Equal extends true ? MySqlDateStringBuilderInitial : MySqlDateBuilderInitial; +export function date(a?: string | MySqlDateConfig, b?: MySqlDateConfig) { + const { name, config } = getColumnNameAndConfig(a, b); + if (config?.mode === 'string') { + return new MySqlDateStringBuilder(name); + } + return new MySqlDateBuilder(name); +} diff --git a/drizzle-orm/src/googlesql/columns/datetime.ts b/drizzle-orm/src/googlesql/columns/datetime.ts new file mode 100644 index 0000000000..ea5b917b92 --- /dev/null +++ b/drizzle-orm/src/googlesql/columns/datetime.ts @@ -0,0 +1,135 @@ +import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; +import type { ColumnBaseConfig } from '~/column.ts'; +import { entityKind } from '~/entity.ts'; +import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import { type Equal, getColumnNameAndConfig } from '~/utils.ts'; +import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; + +export type MySqlDateTimeBuilderInitial = MySqlDateTimeBuilder<{ + name: TName; + dataType: 'date'; + columnType: 'MySqlDateTime'; + data: Date; + driverParam: string | number; + enumValues: undefined; +}>; + +export class MySqlDateTimeBuilder> + extends MySqlColumnBuilder +{ + static override readonly [entityKind]: string = 'MySqlDateTimeBuilder'; + + constructor(name: T['name'], config: MySqlDatetimeConfig | undefined) { + super(name, 'date', 'MySqlDateTime'); + this.config.fsp = config?.fsp; + } + + /** @internal */ + override build( + table: AnyMySqlTable<{ name: TTableName }>, + ): MySqlDateTime> { + return new MySqlDateTime>( + table, + this.config as ColumnBuilderRuntimeConfig, + ); + } +} + +export class MySqlDateTime> extends MySqlColumn { + static override readonly [entityKind]: string = 'MySqlDateTime'; + + readonly fsp: number | undefined; + + constructor( + table: AnyMySqlTable<{ name: T['tableName'] }>, + config: MySqlDateTimeBuilder['config'], + ) { + super(table, config); + this.fsp = config.fsp; + } + + getSQLType(): string { + const precision = this.fsp === undefined ? '' : `(${this.fsp})`; + return `datetime${precision}`; + } + + override mapToDriverValue(value: Date): unknown { + return value.toISOString().replace('T', ' ').replace('Z', ''); + } + + override mapFromDriverValue(value: string): Date { + return new Date(value.replace(' ', 'T') + 'Z'); + } +} + +export type MySqlDateTimeStringBuilderInitial = MySqlDateTimeStringBuilder<{ + name: TName; + dataType: 'string'; + columnType: 'MySqlDateTimeString'; + data: string; + driverParam: string | number; + enumValues: undefined; +}>; + +export class MySqlDateTimeStringBuilder> + extends MySqlColumnBuilder +{ + static override readonly [entityKind]: string = 'MySqlDateTimeStringBuilder'; + + constructor(name: T['name'], config: MySqlDatetimeConfig | undefined) { + super(name, 'string', 'MySqlDateTimeString'); + this.config.fsp = config?.fsp; + } + + /** @internal */ + override build( + table: AnyMySqlTable<{ name: TTableName }>, + ): MySqlDateTimeString> { + return new MySqlDateTimeString>( + table, + this.config as ColumnBuilderRuntimeConfig, + ); + } +} + +export class MySqlDateTimeString> extends MySqlColumn { + static override readonly [entityKind]: string = 'MySqlDateTimeString'; + + readonly fsp: number | undefined; + + constructor( + table: AnyMySqlTable<{ name: T['tableName'] }>, + config: MySqlDateTimeStringBuilder['config'], + ) { + super(table, config); + this.fsp = config.fsp; + } + + getSQLType(): string { + const precision = this.fsp === undefined ? '' : `(${this.fsp})`; + return `datetime${precision}`; + } +} + +export type DatetimeFsp = 0 | 1 | 2 | 3 | 4 | 5 | 6; + +export interface MySqlDatetimeConfig { + mode?: TMode; + fsp?: DatetimeFsp; +} + +export function datetime(): MySqlDateTimeBuilderInitial<''>; +export function datetime( + config?: MySqlDatetimeConfig, +): Equal extends true ? MySqlDateTimeStringBuilderInitial<''> : MySqlDateTimeBuilderInitial<''>; +export function datetime( + name: TName, + config?: MySqlDatetimeConfig, +): Equal extends true ? MySqlDateTimeStringBuilderInitial : MySqlDateTimeBuilderInitial; +export function datetime(a?: string | MySqlDatetimeConfig, b?: MySqlDatetimeConfig) { + const { name, config } = getColumnNameAndConfig(a, b); + if (config?.mode === 'string') { + return new MySqlDateTimeStringBuilder(name, config); + } + return new MySqlDateTimeBuilder(name, config); +} diff --git a/drizzle-orm/src/googlesql/columns/decimal.ts b/drizzle-orm/src/googlesql/columns/decimal.ts new file mode 100644 index 0000000000..76b0ba8a10 --- /dev/null +++ b/drizzle-orm/src/googlesql/columns/decimal.ts @@ -0,0 +1,80 @@ +import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; +import type { ColumnBaseConfig } from '~/column.ts'; +import { entityKind } from '~/entity.ts'; +import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import { getColumnNameAndConfig } from '~/utils.ts'; +import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; + +export type MySqlDecimalBuilderInitial = MySqlDecimalBuilder<{ + name: TName; + dataType: 'string'; + columnType: 'MySqlDecimal'; + data: string; + driverParam: string; + enumValues: undefined; +}>; + +export class MySqlDecimalBuilder< + T extends ColumnBuilderBaseConfig<'string', 'MySqlDecimal'>, +> extends MySqlColumnBuilderWithAutoIncrement { + static override readonly [entityKind]: string = 'MySqlDecimalBuilder'; + + constructor(name: T['name'], config: MySqlDecimalConfig | undefined) { + super(name, 'string', 'MySqlDecimal'); + this.config.precision = config?.precision; + this.config.scale = config?.scale; + this.config.unsigned = config?.unsigned; + } + + /** @internal */ + override build( + table: AnyMySqlTable<{ name: TTableName }>, + ): MySqlDecimal> { + return new MySqlDecimal>( + table, + this.config as ColumnBuilderRuntimeConfig, + ); + } +} + +export class MySqlDecimal> + extends MySqlColumnWithAutoIncrement +{ + static override readonly [entityKind]: string = 'MySqlDecimal'; + + readonly precision: number | undefined = this.config.precision; + readonly scale: number | undefined = this.config.scale; + readonly unsigned: boolean | undefined = this.config.unsigned; + + getSQLType(): string { + let type = ''; + if (this.precision !== undefined && this.scale !== undefined) { + type += `decimal(${this.precision},${this.scale})`; + } else if (this.precision === undefined) { + type += 'decimal'; + } else { + type += `decimal(${this.precision})`; + } + type = type === 'decimal(10,0)' || type === 'decimal(10)' ? 'decimal' : type; + return this.unsigned ? `${type} unsigned` : type; + } +} + +export interface MySqlDecimalConfig { + precision?: number; + scale?: number; + unsigned?: boolean; +} + +export function decimal(): MySqlDecimalBuilderInitial<''>; +export function decimal( + config: MySqlDecimalConfig, +): MySqlDecimalBuilderInitial<''>; +export function decimal( + name: TName, + config?: MySqlDecimalConfig, +): MySqlDecimalBuilderInitial; +export function decimal(a?: string | MySqlDecimalConfig, b: MySqlDecimalConfig = {}) { + const { name, config } = getColumnNameAndConfig(a, b); + return new MySqlDecimalBuilder(name, config); +} diff --git a/drizzle-orm/src/googlesql/columns/double.ts b/drizzle-orm/src/googlesql/columns/double.ts new file mode 100644 index 0000000000..bc23fc74c0 --- /dev/null +++ b/drizzle-orm/src/googlesql/columns/double.ts @@ -0,0 +1,76 @@ +import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; +import type { ColumnBaseConfig } from '~/column.ts'; +import { entityKind } from '~/entity.ts'; +import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import { getColumnNameAndConfig } from '~/utils.ts'; +import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; + +export type MySqlDoubleBuilderInitial = MySqlDoubleBuilder<{ + name: TName; + dataType: 'number'; + columnType: 'MySqlDouble'; + data: number; + driverParam: number | string; + enumValues: undefined; +}>; + +export class MySqlDoubleBuilder> + extends MySqlColumnBuilderWithAutoIncrement +{ + static override readonly [entityKind]: string = 'MySqlDoubleBuilder'; + + constructor(name: T['name'], config: MySqlDoubleConfig | undefined) { + super(name, 'number', 'MySqlDouble'); + this.config.precision = config?.precision; + this.config.scale = config?.scale; + this.config.unsigned = config?.unsigned; + } + + /** @internal */ + override build( + table: AnyMySqlTable<{ name: TTableName }>, + ): MySqlDouble> { + return new MySqlDouble>(table, this.config as ColumnBuilderRuntimeConfig); + } +} + +export class MySqlDouble> + extends MySqlColumnWithAutoIncrement +{ + static override readonly [entityKind]: string = 'MySqlDouble'; + + readonly precision: number | undefined = this.config.precision; + readonly scale: number | undefined = this.config.scale; + readonly unsigned: boolean | undefined = this.config.unsigned; + + getSQLType(): string { + let type = ''; + if (this.precision !== undefined && this.scale !== undefined) { + type += `double(${this.precision},${this.scale})`; + } else if (this.precision === undefined) { + type += 'double'; + } else { + type += `double(${this.precision})`; + } + return this.unsigned ? `${type} unsigned` : type; + } +} + +export interface MySqlDoubleConfig { + precision?: number; + scale?: number; + unsigned?: boolean; +} + +export function double(): MySqlDoubleBuilderInitial<''>; +export function double( + config?: MySqlDoubleConfig, +): MySqlDoubleBuilderInitial<''>; +export function double( + name: TName, + config?: MySqlDoubleConfig, +): MySqlDoubleBuilderInitial; +export function double(a?: string | MySqlDoubleConfig, b?: MySqlDoubleConfig) { + const { name, config } = getColumnNameAndConfig(a, b); + return new MySqlDoubleBuilder(name, config); +} diff --git a/drizzle-orm/src/googlesql/columns/enum.ts b/drizzle-orm/src/googlesql/columns/enum.ts new file mode 100644 index 0000000000..384e07d170 --- /dev/null +++ b/drizzle-orm/src/googlesql/columns/enum.ts @@ -0,0 +1,69 @@ +import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; +import type { ColumnBaseConfig } from '~/column.ts'; +import { entityKind } from '~/entity.ts'; +import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import { getColumnNameAndConfig, type Writable } from '~/utils.ts'; +import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; + +export type MySqlEnumColumnBuilderInitial = + MySqlEnumColumnBuilder<{ + name: TName; + dataType: 'string'; + columnType: 'MySqlEnumColumn'; + data: TEnum[number]; + driverParam: string; + enumValues: TEnum; + }>; + +export class MySqlEnumColumnBuilder> + extends MySqlColumnBuilder +{ + static override readonly [entityKind]: string = 'MySqlEnumColumnBuilder'; + + constructor(name: T['name'], values: T['enumValues']) { + super(name, 'string', 'MySqlEnumColumn'); + this.config.enumValues = values; + } + + /** @internal */ + override build( + table: AnyMySqlTable<{ name: TTableName }>, + ): MySqlEnumColumn & { enumValues: T['enumValues'] }> { + return new MySqlEnumColumn & { enumValues: T['enumValues'] }>( + table, + this.config as ColumnBuilderRuntimeConfig, + ); + } +} + +export class MySqlEnumColumn> + extends MySqlColumn +{ + static override readonly [entityKind]: string = 'MySqlEnumColumn'; + + override readonly enumValues = this.config.enumValues; + + getSQLType(): string { + return `enum(${this.enumValues!.map((value) => `'${value}'`).join(',')})`; + } +} + +export function mysqlEnum>( + values: T | Writable, +): MySqlEnumColumnBuilderInitial<'', Writable>; +export function mysqlEnum>( + name: TName, + values: T | Writable, +): MySqlEnumColumnBuilderInitial>; +export function mysqlEnum( + a?: string | readonly [string, ...string[]] | [string, ...string[]], + b?: readonly [string, ...string[]] | [string, ...string[]], +): any { + const { name, config: values } = getColumnNameAndConfig(a, b); + + if (values.length === 0) { + throw new Error(`You have an empty array for "${name}" enum values`); + } + + return new MySqlEnumColumnBuilder(name, values as any); +} diff --git a/drizzle-orm/src/googlesql/columns/float.ts b/drizzle-orm/src/googlesql/columns/float.ts new file mode 100644 index 0000000000..e368740a0e --- /dev/null +++ b/drizzle-orm/src/googlesql/columns/float.ts @@ -0,0 +1,76 @@ +import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; +import type { ColumnBaseConfig } from '~/column.ts'; +import { entityKind } from '~/entity.ts'; +import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import { getColumnNameAndConfig } from '~/utils.ts'; +import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; + +export type MySqlFloatBuilderInitial = MySqlFloatBuilder<{ + name: TName; + dataType: 'number'; + columnType: 'MySqlFloat'; + data: number; + driverParam: number | string; + enumValues: undefined; +}>; + +export class MySqlFloatBuilder> + extends MySqlColumnBuilderWithAutoIncrement +{ + static override readonly [entityKind]: string = 'MySqlFloatBuilder'; + + constructor(name: T['name'], config: MySqlFloatConfig | undefined) { + super(name, 'number', 'MySqlFloat'); + this.config.precision = config?.precision; + this.config.scale = config?.scale; + this.config.unsigned = config?.unsigned; + } + + /** @internal */ + override build( + table: AnyMySqlTable<{ name: TTableName }>, + ): MySqlFloat> { + return new MySqlFloat>(table, this.config as ColumnBuilderRuntimeConfig); + } +} + +export class MySqlFloat> + extends MySqlColumnWithAutoIncrement +{ + static override readonly [entityKind]: string = 'MySqlFloat'; + + readonly precision: number | undefined = this.config.precision; + readonly scale: number | undefined = this.config.scale; + readonly unsigned: boolean | undefined = this.config.unsigned; + + getSQLType(): string { + let type = ''; + if (this.precision !== undefined && this.scale !== undefined) { + type += `float(${this.precision},${this.scale})`; + } else if (this.precision === undefined) { + type += 'float'; + } else { + type += `float(${this.precision})`; + } + return this.unsigned ? `${type} unsigned` : type; + } +} + +export interface MySqlFloatConfig { + precision?: number; + scale?: number; + unsigned?: boolean; +} + +export function float(): MySqlFloatBuilderInitial<''>; +export function float( + config?: MySqlFloatConfig, +): MySqlFloatBuilderInitial<''>; +export function float( + name: TName, + config?: MySqlFloatConfig, +): MySqlFloatBuilderInitial; +export function float(a?: string | MySqlFloatConfig, b?: MySqlFloatConfig) { + const { name, config } = getColumnNameAndConfig(a, b); + return new MySqlFloatBuilder(name, config); +} diff --git a/drizzle-orm/src/googlesql/columns/index.ts b/drizzle-orm/src/googlesql/columns/index.ts new file mode 100644 index 0000000000..b51f0fac48 --- /dev/null +++ b/drizzle-orm/src/googlesql/columns/index.ts @@ -0,0 +1,25 @@ +export * from './bigint.ts'; +export * from './binary.ts'; +export * from './boolean.ts'; +export * from './char.ts'; +export * from './common.ts'; +export * from './custom.ts'; +export * from './date.ts'; +export * from './datetime.ts'; +export * from './decimal.ts'; +export * from './double.ts'; +export * from './enum.ts'; +export * from './float.ts'; +export * from './int.ts'; +export * from './json.ts'; +export * from './mediumint.ts'; +export * from './real.ts'; +export * from './serial.ts'; +export * from './smallint.ts'; +export * from './text.ts'; +export * from './time.ts'; +export * from './timestamp.ts'; +export * from './tinyint.ts'; +export * from './varbinary.ts'; +export * from './varchar.ts'; +export * from './year.ts'; diff --git a/drizzle-orm/src/googlesql/columns/int.ts b/drizzle-orm/src/googlesql/columns/int.ts new file mode 100644 index 0000000000..79b93bdf75 --- /dev/null +++ b/drizzle-orm/src/googlesql/columns/int.ts @@ -0,0 +1,67 @@ +import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; +import type { ColumnBaseConfig } from '~/column.ts'; +import { entityKind } from '~/entity.ts'; +import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import { getColumnNameAndConfig } from '~/utils.ts'; +import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; + +export type MySqlIntBuilderInitial = MySqlIntBuilder<{ + name: TName; + dataType: 'number'; + columnType: 'MySqlInt'; + data: number; + driverParam: number | string; + enumValues: undefined; +}>; + +export class MySqlIntBuilder> + extends MySqlColumnBuilderWithAutoIncrement +{ + static override readonly [entityKind]: string = 'MySqlIntBuilder'; + + constructor(name: T['name'], config?: MySqlIntConfig) { + super(name, 'number', 'MySqlInt'); + this.config.unsigned = config ? config.unsigned : false; + } + + /** @internal */ + override build( + table: AnyMySqlTable<{ name: TTableName }>, + ): MySqlInt> { + return new MySqlInt>(table, this.config as ColumnBuilderRuntimeConfig); + } +} + +export class MySqlInt> + extends MySqlColumnWithAutoIncrement +{ + static override readonly [entityKind]: string = 'MySqlInt'; + + getSQLType(): string { + return `int${this.config.unsigned ? ' unsigned' : ''}`; + } + + override mapFromDriverValue(value: number | string): number { + if (typeof value === 'string') { + return Number(value); + } + return value; + } +} + +export interface MySqlIntConfig { + unsigned?: boolean; +} + +export function int(): MySqlIntBuilderInitial<''>; +export function int( + config?: MySqlIntConfig, +): MySqlIntBuilderInitial<''>; +export function int( + name: TName, + config?: MySqlIntConfig, +): MySqlIntBuilderInitial; +export function int(a?: string | MySqlIntConfig, b?: MySqlIntConfig) { + const { name, config } = getColumnNameAndConfig(a, b); + return new MySqlIntBuilder(name, config); +} diff --git a/drizzle-orm/src/googlesql/columns/json.ts b/drizzle-orm/src/googlesql/columns/json.ts new file mode 100644 index 0000000000..12d11bd4a5 --- /dev/null +++ b/drizzle-orm/src/googlesql/columns/json.ts @@ -0,0 +1,47 @@ +import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; +import type { ColumnBaseConfig } from '~/column.ts'; +import { entityKind } from '~/entity.ts'; +import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; + +export type MySqlJsonBuilderInitial = MySqlJsonBuilder<{ + name: TName; + dataType: 'json'; + columnType: 'MySqlJson'; + data: unknown; + driverParam: string; + enumValues: undefined; +}>; + +export class MySqlJsonBuilder> extends MySqlColumnBuilder { + static override readonly [entityKind]: string = 'MySqlJsonBuilder'; + + constructor(name: T['name']) { + super(name, 'json', 'MySqlJson'); + } + + /** @internal */ + override build( + table: AnyMySqlTable<{ name: TTableName }>, + ): MySqlJson> { + return new MySqlJson>(table, this.config as ColumnBuilderRuntimeConfig); + } +} + +export class MySqlJson> extends MySqlColumn { + static override readonly [entityKind]: string = 'MySqlJson'; + + getSQLType(): string { + return 'json'; + } + + override mapToDriverValue(value: T['data']): string { + return JSON.stringify(value); + } +} + +export function json(): MySqlJsonBuilderInitial<''>; +export function json(name: TName): MySqlJsonBuilderInitial; +export function json(name?: string) { + return new MySqlJsonBuilder(name ?? ''); +} diff --git a/drizzle-orm/src/googlesql/columns/mediumint.ts b/drizzle-orm/src/googlesql/columns/mediumint.ts new file mode 100644 index 0000000000..7ba5cc9449 --- /dev/null +++ b/drizzle-orm/src/googlesql/columns/mediumint.ts @@ -0,0 +1,67 @@ +import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; +import type { ColumnBaseConfig } from '~/column.ts'; +import { entityKind } from '~/entity.ts'; +import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import { getColumnNameAndConfig } from '~/utils.ts'; +import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; +import type { MySqlIntConfig } from './int.ts'; + +export type MySqlMediumIntBuilderInitial = MySqlMediumIntBuilder<{ + name: TName; + dataType: 'number'; + columnType: 'MySqlMediumInt'; + data: number; + driverParam: number | string; + enumValues: undefined; +}>; + +export class MySqlMediumIntBuilder> + extends MySqlColumnBuilderWithAutoIncrement +{ + static override readonly [entityKind]: string = 'MySqlMediumIntBuilder'; + + constructor(name: T['name'], config?: MySqlIntConfig) { + super(name, 'number', 'MySqlMediumInt'); + this.config.unsigned = config ? config.unsigned : false; + } + + /** @internal */ + override build( + table: AnyMySqlTable<{ name: TTableName }>, + ): MySqlMediumInt> { + return new MySqlMediumInt>( + table, + this.config as ColumnBuilderRuntimeConfig, + ); + } +} + +export class MySqlMediumInt> + extends MySqlColumnWithAutoIncrement +{ + static override readonly [entityKind]: string = 'MySqlMediumInt'; + + getSQLType(): string { + return `mediumint${this.config.unsigned ? ' unsigned' : ''}`; + } + + override mapFromDriverValue(value: number | string): number { + if (typeof value === 'string') { + return Number(value); + } + return value; + } +} + +export function mediumint(): MySqlMediumIntBuilderInitial<''>; +export function mediumint( + config?: MySqlIntConfig, +): MySqlMediumIntBuilderInitial<''>; +export function mediumint( + name: TName, + config?: MySqlIntConfig, +): MySqlMediumIntBuilderInitial; +export function mediumint(a?: string | MySqlIntConfig, b?: MySqlIntConfig) { + const { name, config } = getColumnNameAndConfig(a, b); + return new MySqlMediumIntBuilder(name, config); +} diff --git a/drizzle-orm/src/googlesql/columns/real.ts b/drizzle-orm/src/googlesql/columns/real.ts new file mode 100644 index 0000000000..c6b4473108 --- /dev/null +++ b/drizzle-orm/src/googlesql/columns/real.ts @@ -0,0 +1,75 @@ +import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; +import type { ColumnBaseConfig } from '~/column.ts'; +import { entityKind } from '~/entity.ts'; +import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import { getColumnNameAndConfig } from '~/utils.ts'; +import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; + +export type MySqlRealBuilderInitial = MySqlRealBuilder<{ + name: TName; + dataType: 'number'; + columnType: 'MySqlReal'; + data: number; + driverParam: number | string; + enumValues: undefined; +}>; + +export class MySqlRealBuilder> + extends MySqlColumnBuilderWithAutoIncrement< + T, + MySqlRealConfig + > +{ + static override readonly [entityKind]: string = 'MySqlRealBuilder'; + + constructor(name: T['name'], config: MySqlRealConfig | undefined) { + super(name, 'number', 'MySqlReal'); + this.config.precision = config?.precision; + this.config.scale = config?.scale; + } + + /** @internal */ + override build( + table: AnyMySqlTable<{ name: TTableName }>, + ): MySqlReal> { + return new MySqlReal>(table, this.config as ColumnBuilderRuntimeConfig); + } +} + +export class MySqlReal> extends MySqlColumnWithAutoIncrement< + T, + MySqlRealConfig +> { + static override readonly [entityKind]: string = 'MySqlReal'; + + precision: number | undefined = this.config.precision; + scale: number | undefined = this.config.scale; + + getSQLType(): string { + if (this.precision !== undefined && this.scale !== undefined) { + return `real(${this.precision}, ${this.scale})`; + } else if (this.precision === undefined) { + return 'real'; + } else { + return `real(${this.precision})`; + } + } +} + +export interface MySqlRealConfig { + precision?: number; + scale?: number; +} + +export function real(): MySqlRealBuilderInitial<''>; +export function real( + config?: MySqlRealConfig, +): MySqlRealBuilderInitial<''>; +export function real( + name: TName, + config?: MySqlRealConfig, +): MySqlRealBuilderInitial; +export function real(a?: string | MySqlRealConfig, b: MySqlRealConfig = {}) { + const { name, config } = getColumnNameAndConfig(a, b); + return new MySqlRealBuilder(name, config); +} diff --git a/drizzle-orm/src/googlesql/columns/serial.ts b/drizzle-orm/src/googlesql/columns/serial.ts new file mode 100644 index 0000000000..90fd7a2e5e --- /dev/null +++ b/drizzle-orm/src/googlesql/columns/serial.ts @@ -0,0 +1,72 @@ +import type { + ColumnBuilderBaseConfig, + ColumnBuilderRuntimeConfig, + HasDefault, + IsAutoincrement, + IsPrimaryKey, + MakeColumnConfig, + NotNull, +} from '~/column-builder.ts'; +import type { ColumnBaseConfig } from '~/column.ts'; +import { entityKind } from '~/entity.ts'; +import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; + +export type MySqlSerialBuilderInitial = IsAutoincrement< + IsPrimaryKey< + NotNull< + HasDefault< + MySqlSerialBuilder<{ + name: TName; + dataType: 'number'; + columnType: 'MySqlSerial'; + data: number; + driverParam: number; + enumValues: undefined; + }> + > + > + > +>; + +export class MySqlSerialBuilder> + extends MySqlColumnBuilderWithAutoIncrement +{ + static override readonly [entityKind]: string = 'MySqlSerialBuilder'; + + constructor(name: T['name']) { + super(name, 'number', 'MySqlSerial'); + this.config.hasDefault = true; + this.config.autoIncrement = true; + } + + /** @internal */ + override build( + table: AnyMySqlTable<{ name: TTableName }>, + ): MySqlSerial> { + return new MySqlSerial>(table, this.config as ColumnBuilderRuntimeConfig); + } +} + +export class MySqlSerial< + T extends ColumnBaseConfig<'number', 'MySqlSerial'>, +> extends MySqlColumnWithAutoIncrement { + static override readonly [entityKind]: string = 'MySqlSerial'; + + getSQLType(): string { + return 'serial'; + } + + override mapFromDriverValue(value: number | string): number { + if (typeof value === 'string') { + return Number(value); + } + return value; + } +} + +export function serial(): MySqlSerialBuilderInitial<''>; +export function serial(name: TName): MySqlSerialBuilderInitial; +export function serial(name?: string) { + return new MySqlSerialBuilder(name ?? ''); +} diff --git a/drizzle-orm/src/googlesql/columns/smallint.ts b/drizzle-orm/src/googlesql/columns/smallint.ts new file mode 100644 index 0000000000..87083f0fab --- /dev/null +++ b/drizzle-orm/src/googlesql/columns/smallint.ts @@ -0,0 +1,67 @@ +import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; +import type { ColumnBaseConfig } from '~/column.ts'; +import { entityKind } from '~/entity.ts'; +import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import { getColumnNameAndConfig } from '~/utils.ts'; +import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; +import type { MySqlIntConfig } from './int.ts'; + +export type MySqlSmallIntBuilderInitial = MySqlSmallIntBuilder<{ + name: TName; + dataType: 'number'; + columnType: 'MySqlSmallInt'; + data: number; + driverParam: number | string; + enumValues: undefined; +}>; + +export class MySqlSmallIntBuilder> + extends MySqlColumnBuilderWithAutoIncrement +{ + static override readonly [entityKind]: string = 'MySqlSmallIntBuilder'; + + constructor(name: T['name'], config?: MySqlIntConfig) { + super(name, 'number', 'MySqlSmallInt'); + this.config.unsigned = config ? config.unsigned : false; + } + + /** @internal */ + override build( + table: AnyMySqlTable<{ name: TTableName }>, + ): MySqlSmallInt> { + return new MySqlSmallInt>( + table, + this.config as ColumnBuilderRuntimeConfig, + ); + } +} + +export class MySqlSmallInt> + extends MySqlColumnWithAutoIncrement +{ + static override readonly [entityKind]: string = 'MySqlSmallInt'; + + getSQLType(): string { + return `smallint${this.config.unsigned ? ' unsigned' : ''}`; + } + + override mapFromDriverValue(value: number | string): number { + if (typeof value === 'string') { + return Number(value); + } + return value; + } +} + +export function smallint(): MySqlSmallIntBuilderInitial<''>; +export function smallint( + config?: MySqlIntConfig, +): MySqlSmallIntBuilderInitial<''>; +export function smallint( + name: TName, + config?: MySqlIntConfig, +): MySqlSmallIntBuilderInitial; +export function smallint(a?: string | MySqlIntConfig, b?: MySqlIntConfig) { + const { name, config } = getColumnNameAndConfig(a, b); + return new MySqlSmallIntBuilder(name, config); +} diff --git a/drizzle-orm/src/googlesql/columns/text.ts b/drizzle-orm/src/googlesql/columns/text.ts new file mode 100644 index 0000000000..6106fd45bf --- /dev/null +++ b/drizzle-orm/src/googlesql/columns/text.ts @@ -0,0 +1,109 @@ +import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; +import type { ColumnBaseConfig } from '~/column.ts'; +import { entityKind } from '~/entity.ts'; +import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import { getColumnNameAndConfig, type Writable } from '~/utils.ts'; +import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; + +export type MySqlTextColumnType = 'tinytext' | 'text' | 'mediumtext' | 'longtext'; + +export type MySqlTextBuilderInitial = MySqlTextBuilder<{ + name: TName; + dataType: 'string'; + columnType: 'MySqlText'; + data: TEnum[number]; + driverParam: string; + enumValues: TEnum; +}>; + +export class MySqlTextBuilder> extends MySqlColumnBuilder< + T, + { textType: MySqlTextColumnType; enumValues: T['enumValues'] } +> { + static override readonly [entityKind]: string = 'MySqlTextBuilder'; + + constructor(name: T['name'], textType: MySqlTextColumnType, config: MySqlTextConfig) { + super(name, 'string', 'MySqlText'); + this.config.textType = textType; + this.config.enumValues = config.enum; + } + + /** @internal */ + override build( + table: AnyMySqlTable<{ name: TTableName }>, + ): MySqlText> { + return new MySqlText>(table, this.config as ColumnBuilderRuntimeConfig); + } +} + +export class MySqlText> + extends MySqlColumn +{ + static override readonly [entityKind]: string = 'MySqlText'; + + readonly textType: MySqlTextColumnType = this.config.textType; + + override readonly enumValues = this.config.enumValues; + + getSQLType(): string { + return this.textType; + } +} + +export interface MySqlTextConfig< + TEnum extends readonly string[] | string[] | undefined = readonly string[] | string[] | undefined, +> { + enum?: TEnum; +} + +export function text(): MySqlTextBuilderInitial<'', [string, ...string[]]>; +export function text>( + config?: MySqlTextConfig>, +): MySqlTextBuilderInitial<'', Writable>; +export function text>( + name: TName, + config?: MySqlTextConfig>, +): MySqlTextBuilderInitial>; +export function text(a?: string | MySqlTextConfig, b: MySqlTextConfig = {}): any { + const { name, config } = getColumnNameAndConfig(a, b); + return new MySqlTextBuilder(name, 'text', config as any); +} + +export function tinytext(): MySqlTextBuilderInitial<'', [string, ...string[]]>; +export function tinytext>( + config?: MySqlTextConfig>, +): MySqlTextBuilderInitial<'', Writable>; +export function tinytext>( + name: TName, + config?: MySqlTextConfig>, +): MySqlTextBuilderInitial>; +export function tinytext(a?: string | MySqlTextConfig, b: MySqlTextConfig = {}): any { + const { name, config } = getColumnNameAndConfig(a, b); + return new MySqlTextBuilder(name, 'tinytext', config as any); +} + +export function mediumtext(): MySqlTextBuilderInitial<'', [string, ...string[]]>; +export function mediumtext>( + config?: MySqlTextConfig>, +): MySqlTextBuilderInitial<'', Writable>; +export function mediumtext>( + name: TName, + config?: MySqlTextConfig>, +): MySqlTextBuilderInitial>; +export function mediumtext(a?: string | MySqlTextConfig, b: MySqlTextConfig = {}): any { + const { name, config } = getColumnNameAndConfig(a, b); + return new MySqlTextBuilder(name, 'mediumtext', config as any); +} + +export function longtext(): MySqlTextBuilderInitial<'', [string, ...string[]]>; +export function longtext>( + config?: MySqlTextConfig>, +): MySqlTextBuilderInitial<'', Writable>; +export function longtext>( + name: TName, + config?: MySqlTextConfig>, +): MySqlTextBuilderInitial>; +export function longtext(a?: string | MySqlTextConfig, b: MySqlTextConfig = {}): any { + const { name, config } = getColumnNameAndConfig(a, b); + return new MySqlTextBuilder(name, 'longtext', config as any); +} diff --git a/drizzle-orm/src/googlesql/columns/time.ts b/drizzle-orm/src/googlesql/columns/time.ts new file mode 100644 index 0000000000..7ca5426ec5 --- /dev/null +++ b/drizzle-orm/src/googlesql/columns/time.ts @@ -0,0 +1,67 @@ +import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; +import type { ColumnBaseConfig } from '~/column.ts'; +import { entityKind } from '~/entity.ts'; +import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import { getColumnNameAndConfig } from '~/utils.ts'; +import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; + +export type MySqlTimeBuilderInitial = MySqlTimeBuilder<{ + name: TName; + dataType: 'string'; + columnType: 'MySqlTime'; + data: string; + driverParam: string | number; + enumValues: undefined; +}>; + +export class MySqlTimeBuilder> extends MySqlColumnBuilder< + T, + TimeConfig +> { + static override readonly [entityKind]: string = 'MySqlTimeBuilder'; + + constructor( + name: T['name'], + config: TimeConfig | undefined, + ) { + super(name, 'string', 'MySqlTime'); + this.config.fsp = config?.fsp; + } + + /** @internal */ + override build( + table: AnyMySqlTable<{ name: TTableName }>, + ): MySqlTime> { + return new MySqlTime>(table, this.config as ColumnBuilderRuntimeConfig); + } +} + +export class MySqlTime< + T extends ColumnBaseConfig<'string', 'MySqlTime'>, +> extends MySqlColumn { + static override readonly [entityKind]: string = 'MySqlTime'; + + readonly fsp: number | undefined = this.config.fsp; + + getSQLType(): string { + const precision = this.fsp === undefined ? '' : `(${this.fsp})`; + return `time${precision}`; + } +} + +export type TimeConfig = { + fsp?: 0 | 1 | 2 | 3 | 4 | 5 | 6; +}; + +export function time(): MySqlTimeBuilderInitial<''>; +export function time( + config?: TimeConfig, +): MySqlTimeBuilderInitial<''>; +export function time( + name: TName, + config?: TimeConfig, +): MySqlTimeBuilderInitial; +export function time(a?: string | TimeConfig, b?: TimeConfig) { + const { name, config } = getColumnNameAndConfig(a, b); + return new MySqlTimeBuilder(name, config); +} diff --git a/drizzle-orm/src/googlesql/columns/timestamp.ts b/drizzle-orm/src/googlesql/columns/timestamp.ts new file mode 100644 index 0000000000..2ccc2925f4 --- /dev/null +++ b/drizzle-orm/src/googlesql/columns/timestamp.ts @@ -0,0 +1,125 @@ +import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; +import type { ColumnBaseConfig } from '~/column.ts'; +import { entityKind } from '~/entity.ts'; +import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import { type Equal, getColumnNameAndConfig } from '~/utils.ts'; +import { MySqlDateBaseColumn, MySqlDateColumnBaseBuilder } from './date.common.ts'; + +export type MySqlTimestampBuilderInitial = MySqlTimestampBuilder<{ + name: TName; + dataType: 'date'; + columnType: 'MySqlTimestamp'; + data: Date; + driverParam: string | number; + enumValues: undefined; +}>; + +export class MySqlTimestampBuilder> + extends MySqlDateColumnBaseBuilder +{ + static override readonly [entityKind]: string = 'MySqlTimestampBuilder'; + + constructor(name: T['name'], config: MySqlTimestampConfig | undefined) { + super(name, 'date', 'MySqlTimestamp'); + this.config.fsp = config?.fsp; + } + + /** @internal */ + override build( + table: AnyMySqlTable<{ name: TTableName }>, + ): MySqlTimestamp> { + return new MySqlTimestamp>( + table, + this.config as ColumnBuilderRuntimeConfig, + ); + } +} + +export class MySqlTimestamp> + extends MySqlDateBaseColumn +{ + static override readonly [entityKind]: string = 'MySqlTimestamp'; + + readonly fsp: number | undefined = this.config.fsp; + + getSQLType(): string { + const precision = this.fsp === undefined ? '' : `(${this.fsp})`; + return `timestamp${precision}`; + } + + override mapFromDriverValue(value: string): Date { + return new Date(value + '+0000'); + } + + override mapToDriverValue(value: Date): string { + return value.toISOString().slice(0, -1).replace('T', ' '); + } +} + +export type MySqlTimestampStringBuilderInitial = MySqlTimestampStringBuilder<{ + name: TName; + dataType: 'string'; + columnType: 'MySqlTimestampString'; + data: string; + driverParam: string | number; + enumValues: undefined; +}>; + +export class MySqlTimestampStringBuilder> + extends MySqlDateColumnBaseBuilder +{ + static override readonly [entityKind]: string = 'MySqlTimestampStringBuilder'; + + constructor(name: T['name'], config: MySqlTimestampConfig | undefined) { + super(name, 'string', 'MySqlTimestampString'); + this.config.fsp = config?.fsp; + } + + /** @internal */ + override build( + table: AnyMySqlTable<{ name: TTableName }>, + ): MySqlTimestampString> { + return new MySqlTimestampString>( + table, + this.config as ColumnBuilderRuntimeConfig, + ); + } +} + +export class MySqlTimestampString> + extends MySqlDateBaseColumn +{ + static override readonly [entityKind]: string = 'MySqlTimestampString'; + + readonly fsp: number | undefined = this.config.fsp; + + getSQLType(): string { + const precision = this.fsp === undefined ? '' : `(${this.fsp})`; + return `timestamp${precision}`; + } +} + +export type TimestampFsp = 0 | 1 | 2 | 3 | 4 | 5 | 6; + +export interface MySqlTimestampConfig { + mode?: TMode; + fsp?: TimestampFsp; +} + +export function timestamp(): MySqlTimestampBuilderInitial<''>; +export function timestamp( + config?: MySqlTimestampConfig, +): Equal extends true ? MySqlTimestampStringBuilderInitial<''> + : MySqlTimestampBuilderInitial<''>; +export function timestamp( + name: TName, + config?: MySqlTimestampConfig, +): Equal extends true ? MySqlTimestampStringBuilderInitial + : MySqlTimestampBuilderInitial; +export function timestamp(a?: string | MySqlTimestampConfig, b: MySqlTimestampConfig = {}) { + const { name, config } = getColumnNameAndConfig(a, b); + if (config?.mode === 'string') { + return new MySqlTimestampStringBuilder(name, config); + } + return new MySqlTimestampBuilder(name, config); +} diff --git a/drizzle-orm/src/googlesql/columns/tinyint.ts b/drizzle-orm/src/googlesql/columns/tinyint.ts new file mode 100644 index 0000000000..890f169bd4 --- /dev/null +++ b/drizzle-orm/src/googlesql/columns/tinyint.ts @@ -0,0 +1,67 @@ +import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; +import type { ColumnBaseConfig } from '~/column.ts'; +import { entityKind } from '~/entity.ts'; +import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import { getColumnNameAndConfig } from '~/utils.ts'; +import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; +import type { MySqlIntConfig } from './int.ts'; + +export type MySqlTinyIntBuilderInitial = MySqlTinyIntBuilder<{ + name: TName; + dataType: 'number'; + columnType: 'MySqlTinyInt'; + data: number; + driverParam: number | string; + enumValues: undefined; +}>; + +export class MySqlTinyIntBuilder> + extends MySqlColumnBuilderWithAutoIncrement +{ + static override readonly [entityKind]: string = 'MySqlTinyIntBuilder'; + + constructor(name: T['name'], config?: MySqlIntConfig) { + super(name, 'number', 'MySqlTinyInt'); + this.config.unsigned = config ? config.unsigned : false; + } + + /** @internal */ + override build( + table: AnyMySqlTable<{ name: TTableName }>, + ): MySqlTinyInt> { + return new MySqlTinyInt>( + table, + this.config as ColumnBuilderRuntimeConfig, + ); + } +} + +export class MySqlTinyInt> + extends MySqlColumnWithAutoIncrement +{ + static override readonly [entityKind]: string = 'MySqlTinyInt'; + + getSQLType(): string { + return `tinyint${this.config.unsigned ? ' unsigned' : ''}`; + } + + override mapFromDriverValue(value: number | string): number { + if (typeof value === 'string') { + return Number(value); + } + return value; + } +} + +export function tinyint(): MySqlTinyIntBuilderInitial<''>; +export function tinyint( + config?: MySqlIntConfig, +): MySqlTinyIntBuilderInitial<''>; +export function tinyint( + name: TName, + config?: MySqlIntConfig, +): MySqlTinyIntBuilderInitial; +export function tinyint(a?: string | MySqlIntConfig, b?: MySqlIntConfig) { + const { name, config } = getColumnNameAndConfig(a, b); + return new MySqlTinyIntBuilder(name, config); +} diff --git a/drizzle-orm/src/googlesql/columns/varbinary.ts b/drizzle-orm/src/googlesql/columns/varbinary.ts new file mode 100644 index 0000000000..837de8dcbe --- /dev/null +++ b/drizzle-orm/src/googlesql/columns/varbinary.ts @@ -0,0 +1,65 @@ +import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; +import type { ColumnBaseConfig } from '~/column.ts'; +import { entityKind } from '~/entity.ts'; +import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import { getColumnNameAndConfig } from '~/utils.ts'; +import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; + +export type MySqlVarBinaryBuilderInitial = MySqlVarBinaryBuilder<{ + name: TName; + dataType: 'string'; + columnType: 'MySqlVarBinary'; + data: string; + driverParam: string; + enumValues: undefined; +}>; + +export class MySqlVarBinaryBuilder> + extends MySqlColumnBuilder +{ + static override readonly [entityKind]: string = 'MySqlVarBinaryBuilder'; + + /** @internal */ + constructor(name: T['name'], config: MySqlVarbinaryOptions) { + super(name, 'string', 'MySqlVarBinary'); + this.config.length = config?.length; + } + + /** @internal */ + override build( + table: AnyMySqlTable<{ name: TTableName }>, + ): MySqlVarBinary> { + return new MySqlVarBinary>( + table, + this.config as ColumnBuilderRuntimeConfig, + ); + } +} + +export class MySqlVarBinary< + T extends ColumnBaseConfig<'string', 'MySqlVarBinary'>, +> extends MySqlColumn { + static override readonly [entityKind]: string = 'MySqlVarBinary'; + + length: number | undefined = this.config.length; + + getSQLType(): string { + return this.length === undefined ? `varbinary` : `varbinary(${this.length})`; + } +} + +export interface MySqlVarbinaryOptions { + length: number; +} + +export function varbinary( + config: MySqlVarbinaryOptions, +): MySqlVarBinaryBuilderInitial<''>; +export function varbinary( + name: TName, + config: MySqlVarbinaryOptions, +): MySqlVarBinaryBuilderInitial; +export function varbinary(a?: string | MySqlVarbinaryOptions, b?: MySqlVarbinaryOptions) { + const { name, config } = getColumnNameAndConfig(a, b); + return new MySqlVarBinaryBuilder(name, config); +} diff --git a/drizzle-orm/src/googlesql/columns/varchar.ts b/drizzle-orm/src/googlesql/columns/varchar.ts new file mode 100644 index 0000000000..0a0bde8574 --- /dev/null +++ b/drizzle-orm/src/googlesql/columns/varchar.ts @@ -0,0 +1,84 @@ +import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; +import type { ColumnBaseConfig } from '~/column.ts'; +import { entityKind } from '~/entity.ts'; +import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import { getColumnNameAndConfig, type Writable } from '~/utils.ts'; +import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; + +export type MySqlVarCharBuilderInitial< + TName extends string, + TEnum extends [string, ...string[]], + TLength extends number | undefined, +> = MySqlVarCharBuilder< + { + name: TName; + dataType: 'string'; + columnType: 'MySqlVarChar'; + data: TEnum[number]; + driverParam: number | string; + enumValues: TEnum; + length: TLength; + } +>; + +export class MySqlVarCharBuilder< + T extends ColumnBuilderBaseConfig<'string', 'MySqlVarChar'> & { length?: number | undefined }, +> extends MySqlColumnBuilder> { + static override readonly [entityKind]: string = 'MySqlVarCharBuilder'; + + /** @internal */ + constructor(name: T['name'], config: MySqlVarCharConfig) { + super(name, 'string', 'MySqlVarChar'); + this.config.length = config.length; + this.config.enum = config.enum; + } + + /** @internal */ + override build( + table: AnyMySqlTable<{ name: TTableName }>, + ): MySqlVarChar & { length: T['length']; enumValues: T['enumValues'] }> { + return new MySqlVarChar & { length: T['length']; enumValues: T['enumValues'] }>( + table, + this.config as ColumnBuilderRuntimeConfig, + ); + } +} + +export class MySqlVarChar & { length?: number | undefined }> + extends MySqlColumn, { length: T['length'] }> +{ + static override readonly [entityKind]: string = 'MySqlVarChar'; + + readonly length: number | undefined = this.config.length; + + override readonly enumValues = this.config.enum; + + getSQLType(): string { + return this.length === undefined ? `varchar` : `varchar(${this.length})`; + } +} + +export interface MySqlVarCharConfig< + TEnum extends string[] | readonly string[] | undefined = string[] | readonly string[] | undefined, + TLength extends number | undefined = number | undefined, +> { + enum?: TEnum; + length?: TLength; +} + +export function varchar, L extends number | undefined>( + config: MySqlVarCharConfig, L>, +): MySqlVarCharBuilderInitial<'', Writable, L>; +export function varchar< + TName extends string, + U extends string, + T extends Readonly<[U, ...U[]]>, + L extends number | undefined, +>( + name: TName, + config: MySqlVarCharConfig, L>, +): MySqlVarCharBuilderInitial, L>; +export function varchar(a?: string | MySqlVarCharConfig, b?: MySqlVarCharConfig): any { + const { name, config } = getColumnNameAndConfig(a, b); + return new MySqlVarCharBuilder(name, config as any); +} diff --git a/drizzle-orm/src/googlesql/columns/year.ts b/drizzle-orm/src/googlesql/columns/year.ts new file mode 100644 index 0000000000..4e4ae4faf4 --- /dev/null +++ b/drizzle-orm/src/googlesql/columns/year.ts @@ -0,0 +1,45 @@ +import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; +import type { ColumnBaseConfig } from '~/column.ts'; +import { entityKind } from '~/entity.ts'; +import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; + +export type MySqlYearBuilderInitial = MySqlYearBuilder<{ + name: TName; + dataType: 'number'; + columnType: 'MySqlYear'; + data: number; + driverParam: number; + enumValues: undefined; +}>; + +export class MySqlYearBuilder> extends MySqlColumnBuilder { + static override readonly [entityKind]: string = 'MySqlYearBuilder'; + + constructor(name: T['name']) { + super(name, 'number', 'MySqlYear'); + } + + /** @internal */ + override build( + table: AnyMySqlTable<{ name: TTableName }>, + ): MySqlYear> { + return new MySqlYear>(table, this.config as ColumnBuilderRuntimeConfig); + } +} + +export class MySqlYear< + T extends ColumnBaseConfig<'number', 'MySqlYear'>, +> extends MySqlColumn { + static override readonly [entityKind]: string = 'MySqlYear'; + + getSQLType(): string { + return `year`; + } +} + +export function year(): MySqlYearBuilderInitial<''>; +export function year(name: TName): MySqlYearBuilderInitial; +export function year(name?: string) { + return new MySqlYearBuilder(name ?? ''); +} diff --git a/drizzle-orm/src/googlesql/db.ts b/drizzle-orm/src/googlesql/db.ts new file mode 100644 index 0000000000..6f79488383 --- /dev/null +++ b/drizzle-orm/src/googlesql/db.ts @@ -0,0 +1,532 @@ +import type { ResultSetHeader } from 'mysql2/promise'; +import { entityKind } from '~/entity.ts'; +import type { TypedQueryBuilder } from '~/query-builders/query-builder.ts'; +import type { ExtractTablesWithRelations, RelationalSchemaConfig, TablesRelationalConfig } from '~/relations.ts'; +import { SelectionProxyHandler } from '~/selection-proxy.ts'; +import { type ColumnsSelection, type SQL, sql, type SQLWrapper } from '~/sql/sql.ts'; +import { WithSubquery } from '~/subquery.ts'; +import type { DrizzleTypeError } from '~/utils.ts'; +import type { MySqlDialect } from './dialect.ts'; +import { MySqlCountBuilder } from './query-builders/count.ts'; +import { + MySqlDeleteBase, + MySqlInsertBuilder, + MySqlSelectBuilder, + MySqlUpdateBuilder, + QueryBuilder, +} from './query-builders/index.ts'; +import { RelationalQueryBuilder } from './query-builders/query.ts'; +import type { SelectedFields } from './query-builders/select.types.ts'; +import type { + Mode, + MySqlQueryResultHKT, + MySqlQueryResultKind, + MySqlSession, + MySqlTransaction, + MySqlTransactionConfig, + PreparedQueryHKTBase, +} from './session.ts'; +import type { WithBuilder } from './subquery.ts'; +import type { MySqlTable } from './table.ts'; +import type { MySqlViewBase } from './view-base.ts'; + +export class MySqlDatabase< + TQueryResult extends MySqlQueryResultHKT, + TPreparedQueryHKT extends PreparedQueryHKTBase, + TFullSchema extends Record = {}, + TSchema extends TablesRelationalConfig = ExtractTablesWithRelations, +> { + static readonly [entityKind]: string = 'MySqlDatabase'; + + declare readonly _: { + readonly schema: TSchema | undefined; + readonly fullSchema: TFullSchema; + readonly tableNamesMap: Record; + }; + + query: TFullSchema extends Record + ? DrizzleTypeError<'Seems like the schema generic is missing - did you forget to add it to your DB type?'> + : { + [K in keyof TSchema]: RelationalQueryBuilder; + }; + + constructor( + /** @internal */ + readonly dialect: MySqlDialect, + /** @internal */ + readonly session: MySqlSession, + schema: RelationalSchemaConfig | undefined, + protected readonly mode: Mode, + ) { + this._ = schema + ? { + schema: schema.schema, + fullSchema: schema.fullSchema as TFullSchema, + tableNamesMap: schema.tableNamesMap, + } + : { + schema: undefined, + fullSchema: {} as TFullSchema, + tableNamesMap: {}, + }; + this.query = {} as typeof this['query']; + if (this._.schema) { + for (const [tableName, columns] of Object.entries(this._.schema)) { + (this.query as MySqlDatabase>['query'])[tableName] = + new RelationalQueryBuilder( + schema!.fullSchema, + this._.schema, + this._.tableNamesMap, + schema!.fullSchema[tableName] as MySqlTable, + columns, + dialect, + session, + this.mode, + ); + } + } + } + + /** + * Creates a subquery that defines a temporary named result set as a CTE. + * + * It is useful for breaking down complex queries into simpler parts and for reusing the result set in subsequent parts of the query. + * + * See docs: {@link https://orm.drizzle.team/docs/select#with-clause} + * + * @param alias The alias for the subquery. + * + * Failure to provide an alias will result in a DrizzleTypeError, preventing the subquery from being referenced in other queries. + * + * @example + * + * ```ts + * // Create a subquery with alias 'sq' and use it in the select query + * const sq = db.$with('sq').as(db.select().from(users).where(eq(users.id, 42))); + * + * const result = await db.with(sq).select().from(sq); + * ``` + * + * To select arbitrary SQL values as fields in a CTE and reference them in other CTEs or in the main query, you need to add aliases to them: + * + * ```ts + * // Select an arbitrary SQL value as a field in a CTE and reference it in the main query + * const sq = db.$with('sq').as(db.select({ + * name: sql`upper(${users.name})`.as('name'), + * }) + * .from(users)); + * + * const result = await db.with(sq).select({ name: sq.name }).from(sq); + * ``` + */ + $with: WithBuilder = (alias: string, selection?: ColumnsSelection) => { + const self = this; + const as = ( + qb: + | TypedQueryBuilder + | SQL + | ((qb: QueryBuilder) => TypedQueryBuilder | SQL), + ) => { + if (typeof qb === 'function') { + qb = qb(new QueryBuilder(self.dialect)); + } + + return new Proxy( + new WithSubquery( + qb.getSQL(), + selection ?? ('getSelectedFields' in qb ? qb.getSelectedFields() ?? {} : {}) as SelectedFields, + alias, + true, + ), + new SelectionProxyHandler({ alias, sqlAliasedBehavior: 'alias', sqlBehavior: 'error' }), + ); + }; + return { as }; + }; + + $count( + source: MySqlTable | MySqlViewBase | SQL | SQLWrapper, + filters?: SQL, + ) { + return new MySqlCountBuilder({ source, filters, session: this.session }); + } + + /** + * Incorporates a previously defined CTE (using `$with`) into the main query. + * + * This method allows the main query to reference a temporary named result set. + * + * See docs: {@link https://orm.drizzle.team/docs/select#with-clause} + * + * @param queries The CTEs to incorporate into the main query. + * + * @example + * + * ```ts + * // Define a subquery 'sq' as a CTE using $with + * const sq = db.$with('sq').as(db.select().from(users).where(eq(users.id, 42))); + * + * // Incorporate the CTE 'sq' into the main query and select from it + * const result = await db.with(sq).select().from(sq); + * ``` + */ + with(...queries: WithSubquery[]) { + const self = this; + + /** + * Creates a select query. + * + * Calling this method with no arguments will select all columns from the table. Pass a selection object to specify the columns you want to select. + * + * Use `.from()` method to specify which table to select from. + * + * See docs: {@link https://orm.drizzle.team/docs/select} + * + * @param fields The selection object. + * + * @example + * + * ```ts + * // Select all columns and all rows from the 'cars' table + * const allCars: Car[] = await db.select().from(cars); + * + * // Select specific columns and all rows from the 'cars' table + * const carsIdsAndBrands: { id: number; brand: string }[] = await db.select({ + * id: cars.id, + * brand: cars.brand + * }) + * .from(cars); + * ``` + * + * Like in SQL, you can use arbitrary expressions as selection fields, not just table columns: + * + * ```ts + * // Select specific columns along with expression and all rows from the 'cars' table + * const carsIdsAndLowerNames: { id: number; lowerBrand: string }[] = await db.select({ + * id: cars.id, + * lowerBrand: sql`lower(${cars.brand})`, + * }) + * .from(cars); + * ``` + */ + function select(): MySqlSelectBuilder; + function select( + fields: TSelection, + ): MySqlSelectBuilder; + function select(fields?: SelectedFields): MySqlSelectBuilder { + return new MySqlSelectBuilder({ + fields: fields ?? undefined, + session: self.session, + dialect: self.dialect, + withList: queries, + }); + } + + /** + * Adds `distinct` expression to the select query. + * + * Calling this method will return only unique values. When multiple columns are selected, it returns rows with unique combinations of values in these columns. + * + * Use `.from()` method to specify which table to select from. + * + * See docs: {@link https://orm.drizzle.team/docs/select#distinct} + * + * @param fields The selection object. + * + * @example + * ```ts + * // Select all unique rows from the 'cars' table + * await db.selectDistinct() + * .from(cars) + * .orderBy(cars.id, cars.brand, cars.color); + * + * // Select all unique brands from the 'cars' table + * await db.selectDistinct({ brand: cars.brand }) + * .from(cars) + * .orderBy(cars.brand); + * ``` + */ + function selectDistinct(): MySqlSelectBuilder; + function selectDistinct( + fields: TSelection, + ): MySqlSelectBuilder; + function selectDistinct( + fields?: SelectedFields, + ): MySqlSelectBuilder { + return new MySqlSelectBuilder({ + fields: fields ?? undefined, + session: self.session, + dialect: self.dialect, + withList: queries, + distinct: true, + }); + } + + /** + * Creates an update query. + * + * Calling this method without `.where()` clause will update all rows in a table. The `.where()` clause specifies which rows should be updated. + * + * Use `.set()` method to specify which values to update. + * + * See docs: {@link https://orm.drizzle.team/docs/update} + * + * @param table The table to update. + * + * @example + * + * ```ts + * // Update all rows in the 'cars' table + * await db.update(cars).set({ color: 'red' }); + * + * // Update rows with filters and conditions + * await db.update(cars).set({ color: 'red' }).where(eq(cars.brand, 'BMW')); + * ``` + */ + function update( + table: TTable, + ): MySqlUpdateBuilder { + return new MySqlUpdateBuilder(table, self.session, self.dialect, queries); + } + + /** + * Creates a delete query. + * + * Calling this method without `.where()` clause will delete all rows in a table. The `.where()` clause specifies which rows should be deleted. + * + * See docs: {@link https://orm.drizzle.team/docs/delete} + * + * @param table The table to delete from. + * + * @example + * + * ```ts + * // Delete all rows in the 'cars' table + * await db.delete(cars); + * + * // Delete rows with filters and conditions + * await db.delete(cars).where(eq(cars.color, 'green')); + * ``` + */ + function delete_( + table: TTable, + ): MySqlDeleteBase { + return new MySqlDeleteBase(table, self.session, self.dialect, queries); + } + + return { select, selectDistinct, update, delete: delete_ }; + } + + /** + * Creates a select query. + * + * Calling this method with no arguments will select all columns from the table. Pass a selection object to specify the columns you want to select. + * + * Use `.from()` method to specify which table to select from. + * + * See docs: {@link https://orm.drizzle.team/docs/select} + * + * @param fields The selection object. + * + * @example + * + * ```ts + * // Select all columns and all rows from the 'cars' table + * const allCars: Car[] = await db.select().from(cars); + * + * // Select specific columns and all rows from the 'cars' table + * const carsIdsAndBrands: { id: number; brand: string }[] = await db.select({ + * id: cars.id, + * brand: cars.brand + * }) + * .from(cars); + * ``` + * + * Like in SQL, you can use arbitrary expressions as selection fields, not just table columns: + * + * ```ts + * // Select specific columns along with expression and all rows from the 'cars' table + * const carsIdsAndLowerNames: { id: number; lowerBrand: string }[] = await db.select({ + * id: cars.id, + * lowerBrand: sql`lower(${cars.brand})`, + * }) + * .from(cars); + * ``` + */ + select(): MySqlSelectBuilder; + select(fields: TSelection): MySqlSelectBuilder; + select(fields?: SelectedFields): MySqlSelectBuilder { + return new MySqlSelectBuilder({ fields: fields ?? undefined, session: this.session, dialect: this.dialect }); + } + + /** + * Adds `distinct` expression to the select query. + * + * Calling this method will return only unique values. When multiple columns are selected, it returns rows with unique combinations of values in these columns. + * + * Use `.from()` method to specify which table to select from. + * + * See docs: {@link https://orm.drizzle.team/docs/select#distinct} + * + * @param fields The selection object. + * + * @example + * ```ts + * // Select all unique rows from the 'cars' table + * await db.selectDistinct() + * .from(cars) + * .orderBy(cars.id, cars.brand, cars.color); + * + * // Select all unique brands from the 'cars' table + * await db.selectDistinct({ brand: cars.brand }) + * .from(cars) + * .orderBy(cars.brand); + * ``` + */ + selectDistinct(): MySqlSelectBuilder; + selectDistinct( + fields: TSelection, + ): MySqlSelectBuilder; + selectDistinct(fields?: SelectedFields): MySqlSelectBuilder { + return new MySqlSelectBuilder({ + fields: fields ?? undefined, + session: this.session, + dialect: this.dialect, + distinct: true, + }); + } + + /** + * Creates an update query. + * + * Calling this method without `.where()` clause will update all rows in a table. The `.where()` clause specifies which rows should be updated. + * + * Use `.set()` method to specify which values to update. + * + * See docs: {@link https://orm.drizzle.team/docs/update} + * + * @param table The table to update. + * + * @example + * + * ```ts + * // Update all rows in the 'cars' table + * await db.update(cars).set({ color: 'red' }); + * + * // Update rows with filters and conditions + * await db.update(cars).set({ color: 'red' }).where(eq(cars.brand, 'BMW')); + * ``` + */ + update(table: TTable): MySqlUpdateBuilder { + return new MySqlUpdateBuilder(table, this.session, this.dialect); + } + + /** + * Creates an insert query. + * + * Calling this method will create new rows in a table. Use `.values()` method to specify which values to insert. + * + * See docs: {@link https://orm.drizzle.team/docs/insert} + * + * @param table The table to insert into. + * + * @example + * + * ```ts + * // Insert one row + * await db.insert(cars).values({ brand: 'BMW' }); + * + * // Insert multiple rows + * await db.insert(cars).values([{ brand: 'BMW' }, { brand: 'Porsche' }]); + * ``` + */ + insert(table: TTable): MySqlInsertBuilder { + return new MySqlInsertBuilder(table, this.session, this.dialect); + } + + /** + * Creates a delete query. + * + * Calling this method without `.where()` clause will delete all rows in a table. The `.where()` clause specifies which rows should be deleted. + * + * See docs: {@link https://orm.drizzle.team/docs/delete} + * + * @param table The table to delete from. + * + * @example + * + * ```ts + * // Delete all rows in the 'cars' table + * await db.delete(cars); + * + * // Delete rows with filters and conditions + * await db.delete(cars).where(eq(cars.color, 'green')); + * ``` + */ + delete(table: TTable): MySqlDeleteBase { + return new MySqlDeleteBase(table, this.session, this.dialect); + } + + execute( + query: SQLWrapper | string, + ): Promise> { + return this.session.execute(typeof query === 'string' ? sql.raw(query) : query.getSQL()); + } + + transaction( + transaction: ( + tx: MySqlTransaction, + config?: MySqlTransactionConfig, + ) => Promise, + config?: MySqlTransactionConfig, + ): Promise { + return this.session.transaction(transaction, config); + } +} + +export type MySQLWithReplicas = Q & { $primary: Q }; + +export const withReplicas = < + HKT extends MySqlQueryResultHKT, + TPreparedQueryHKT extends PreparedQueryHKTBase, + TFullSchema extends Record, + TSchema extends TablesRelationalConfig, + Q extends MySqlDatabase< + HKT, + TPreparedQueryHKT, + TFullSchema, + TSchema extends Record ? ExtractTablesWithRelations : TSchema + >, +>( + primary: Q, + replicas: [Q, ...Q[]], + getReplica: (replicas: Q[]) => Q = () => replicas[Math.floor(Math.random() * replicas.length)]!, +): MySQLWithReplicas => { + const select: Q['select'] = (...args: []) => getReplica(replicas).select(...args); + const selectDistinct: Q['selectDistinct'] = (...args: []) => getReplica(replicas).selectDistinct(...args); + const $count: Q['$count'] = (...args: [any]) => getReplica(replicas).$count(...args); + const $with: Q['with'] = (...args: []) => getReplica(replicas).with(...args); + + const update: Q['update'] = (...args: [any]) => primary.update(...args); + const insert: Q['insert'] = (...args: [any]) => primary.insert(...args); + const $delete: Q['delete'] = (...args: [any]) => primary.delete(...args); + const execute: Q['execute'] = (...args: [any]) => primary.execute(...args); + const transaction: Q['transaction'] = (...args: [any, any]) => primary.transaction(...args); + + return { + ...primary, + update, + insert, + delete: $delete, + execute, + transaction, + $primary: primary, + select, + selectDistinct, + $count, + with: $with, + get query() { + return getReplica(replicas).query; + }, + }; +}; diff --git a/drizzle-orm/src/googlesql/dialect.ts b/drizzle-orm/src/googlesql/dialect.ts new file mode 100644 index 0000000000..8661359ab7 --- /dev/null +++ b/drizzle-orm/src/googlesql/dialect.ts @@ -0,0 +1,1148 @@ +import { aliasedTable, aliasedTableColumn, mapColumnsInAliasedSQLToAlias, mapColumnsInSQLToAlias } from '~/alias.ts'; +import { CasingCache } from '~/casing.ts'; +import { Column } from '~/column.ts'; +import { entityKind, is } from '~/entity.ts'; +import { DrizzleError } from '~/errors.ts'; +import { and, eq } from '~/expressions.ts'; +import type { MigrationConfig, MigrationMeta } from '~/migrator.ts'; +import { + type BuildRelationalQueryResult, + type DBQueryConfig, + getOperators, + getOrderByOperators, + Many, + normalizeRelation, + One, + type Relation, + type TableRelationalConfig, + type TablesRelationalConfig, +} from '~/relations.ts'; +import { Param, SQL, sql, View } from '~/sql/sql.ts'; +import type { Name, Placeholder, QueryWithTypings, SQLChunk } from '~/sql/sql.ts'; +import { Subquery } from '~/subquery.ts'; +import { getTableName, getTableUniqueName, Table } from '~/table.ts'; +import { type Casing, orderSelectedFields, type UpdateSet } from '~/utils.ts'; +import { ViewBaseConfig } from '~/view-common.ts'; +import { MySqlColumn } from './columns/common.ts'; +import type { MySqlDeleteConfig } from './query-builders/delete.ts'; +import type { MySqlInsertConfig } from './query-builders/insert.ts'; +import type { + AnyMySqlSelectQueryBuilder, + MySqlSelectConfig, + MySqlSelectJoinConfig, + SelectedFieldsOrdered, +} from './query-builders/select.types.ts'; +import type { MySqlUpdateConfig } from './query-builders/update.ts'; +import type { MySqlSession } from './session.ts'; +import { MySqlTable } from './table.ts'; +import { MySqlViewBase } from './view-base.ts'; + +export interface MySqlDialectConfig { + casing?: Casing; +} + +export class MySqlDialect { + static readonly [entityKind]: string = 'MySqlDialect'; + + /** @internal */ + readonly casing: CasingCache; + + constructor(config?: MySqlDialectConfig) { + this.casing = new CasingCache(config?.casing); + } + + async migrate( + migrations: MigrationMeta[], + session: MySqlSession, + config: Omit, + ): Promise { + const migrationsTable = config.migrationsTable ?? '__drizzle_migrations'; + const migrationTableCreate = sql` + create table if not exists ${sql.identifier(migrationsTable)} ( + id serial primary key, + hash text not null, + created_at bigint + ) + `; + await session.execute(migrationTableCreate); + + const dbMigrations = await session.all<{ id: number; hash: string; created_at: string }>( + sql`select id, hash, created_at from ${sql.identifier(migrationsTable)} order by created_at desc limit 1`, + ); + + const lastDbMigration = dbMigrations[0]; + + await session.transaction(async (tx) => { + for (const migration of migrations) { + if ( + !lastDbMigration + || Number(lastDbMigration.created_at) < migration.folderMillis + ) { + for (const stmt of migration.sql) { + await tx.execute(sql.raw(stmt)); + } + await tx.execute( + sql`insert into ${ + sql.identifier(migrationsTable) + } (\`hash\`, \`created_at\`) values(${migration.hash}, ${migration.folderMillis})`, + ); + } + } + }); + } + + escapeName(name: string): string { + return `\`${name}\``; + } + + escapeParam(_num: number): string { + return `?`; + } + + escapeString(str: string): string { + return `'${str.replace(/'/g, "''")}'`; + } + + private buildWithCTE(queries: Subquery[] | undefined): SQL | undefined { + if (!queries?.length) return undefined; + + const withSqlChunks = [sql`with `]; + for (const [i, w] of queries.entries()) { + withSqlChunks.push(sql`${sql.identifier(w._.alias)} as (${w._.sql})`); + if (i < queries.length - 1) { + withSqlChunks.push(sql`, `); + } + } + withSqlChunks.push(sql` `); + return sql.join(withSqlChunks); + } + + buildDeleteQuery({ table, where, returning, withList, limit, orderBy }: MySqlDeleteConfig): SQL { + const withSql = this.buildWithCTE(withList); + + const returningSql = returning + ? sql` returning ${this.buildSelection(returning, { isSingleTable: true })}` + : undefined; + + const whereSql = where ? sql` where ${where}` : undefined; + + const orderBySql = this.buildOrderBy(orderBy); + + const limitSql = this.buildLimit(limit); + + return sql`${withSql}delete from ${table}${whereSql}${orderBySql}${limitSql}${returningSql}`; + } + + buildUpdateSet(table: MySqlTable, set: UpdateSet): SQL { + const tableColumns = table[Table.Symbol.Columns]; + + const columnNames = Object.keys(tableColumns).filter((colName) => + set[colName] !== undefined || tableColumns[colName]?.onUpdateFn !== undefined + ); + + const setSize = columnNames.length; + return sql.join(columnNames.flatMap((colName, i) => { + const col = tableColumns[colName]!; + + const value = set[colName] ?? sql.param(col.onUpdateFn!(), col); + const res = sql`${sql.identifier(this.casing.getColumnCasing(col))} = ${value}`; + + if (i < setSize - 1) { + return [res, sql.raw(', ')]; + } + return [res]; + })); + } + + buildUpdateQuery({ table, set, where, returning, withList, limit, orderBy }: MySqlUpdateConfig): SQL { + const withSql = this.buildWithCTE(withList); + + const setSql = this.buildUpdateSet(table, set); + + const returningSql = returning + ? sql` returning ${this.buildSelection(returning, { isSingleTable: true })}` + : undefined; + + const whereSql = where ? sql` where ${where}` : undefined; + + const orderBySql = this.buildOrderBy(orderBy); + + const limitSql = this.buildLimit(limit); + + return sql`${withSql}update ${table} set ${setSql}${whereSql}${orderBySql}${limitSql}${returningSql}`; + } + + /** + * Builds selection SQL with provided fields/expressions + * + * Examples: + * + * `select from` + * + * `insert ... returning ` + * + * If `isSingleTable` is true, then columns won't be prefixed with table name + */ + private buildSelection( + fields: SelectedFieldsOrdered, + { isSingleTable = false }: { isSingleTable?: boolean } = {}, + ): SQL { + const columnsLen = fields.length; + + const chunks = fields + .flatMap(({ field }, i) => { + const chunk: SQLChunk[] = []; + + if (is(field, SQL.Aliased) && field.isSelectionField) { + chunk.push(sql.identifier(field.fieldAlias)); + } else if (is(field, SQL.Aliased) || is(field, SQL)) { + const query = is(field, SQL.Aliased) ? field.sql : field; + + if (isSingleTable) { + chunk.push( + new SQL( + query.queryChunks.map((c) => { + if (is(c, MySqlColumn)) { + return sql.identifier(this.casing.getColumnCasing(c)); + } + return c; + }), + ), + ); + } else { + chunk.push(query); + } + + if (is(field, SQL.Aliased)) { + chunk.push(sql` as ${sql.identifier(field.fieldAlias)}`); + } + } else if (is(field, Column)) { + if (isSingleTable) { + chunk.push(sql.identifier(this.casing.getColumnCasing(field))); + } else { + chunk.push(field); + } + } + + if (i < columnsLen - 1) { + chunk.push(sql`, `); + } + + return chunk; + }); + + return sql.join(chunks); + } + + private buildLimit(limit: number | Placeholder | undefined): SQL | undefined { + return typeof limit === 'object' || (typeof limit === 'number' && limit >= 0) + ? sql` limit ${limit}` + : undefined; + } + + private buildOrderBy(orderBy: (MySqlColumn | SQL | SQL.Aliased)[] | undefined): SQL | undefined { + return orderBy && orderBy.length > 0 ? sql` order by ${sql.join(orderBy, sql`, `)}` : undefined; + } + + private buildIndex({ + indexes, + indexFor, + }: { + indexes: string[] | undefined; + indexFor: 'USE' | 'FORCE' | 'IGNORE'; + }): SQL | undefined { + return indexes && indexes.length > 0 + ? sql` ${sql.raw(indexFor)} INDEX (${sql.raw(indexes.join(`, `))})` + : undefined; + } + + buildSelectQuery( + { + withList, + fields, + fieldsFlat, + where, + having, + table, + joins, + orderBy, + groupBy, + limit, + offset, + lockingClause, + distinct, + setOperators, + useIndex, + forceIndex, + ignoreIndex, + }: MySqlSelectConfig, + ): SQL { + const fieldsList = fieldsFlat ?? orderSelectedFields(fields); + for (const f of fieldsList) { + if ( + is(f.field, Column) + && getTableName(f.field.table) + !== (is(table, Subquery) + ? table._.alias + : is(table, MySqlViewBase) + ? table[ViewBaseConfig].name + : is(table, SQL) + ? undefined + : getTableName(table)) + && !((table) => + joins?.some(({ alias }) => + alias === (table[Table.Symbol.IsAlias] ? getTableName(table) : table[Table.Symbol.BaseName]) + ))(f.field.table) + ) { + const tableName = getTableName(f.field.table); + throw new Error( + `Your "${ + f.path.join('->') + }" field references a column "${tableName}"."${f.field.name}", but the table "${tableName}" is not part of the query! Did you forget to join it?`, + ); + } + } + + const isSingleTable = !joins || joins.length === 0; + + const withSql = this.buildWithCTE(withList); + + const distinctSql = distinct ? sql` distinct` : undefined; + + const selection = this.buildSelection(fieldsList, { isSingleTable }); + + const tableSql = (() => { + if (is(table, Table) && table[Table.Symbol.OriginalName] !== table[Table.Symbol.Name]) { + return sql`${sql.identifier(table[Table.Symbol.OriginalName])} ${sql.identifier(table[Table.Symbol.Name])}`; + } + + return table; + })(); + + const joinsArray: SQL[] = []; + + if (joins) { + for (const [index, joinMeta] of joins.entries()) { + if (index === 0) { + joinsArray.push(sql` `); + } + const table = joinMeta.table; + const lateralSql = joinMeta.lateral ? sql` lateral` : undefined; + + if (is(table, MySqlTable)) { + const tableName = table[MySqlTable.Symbol.Name]; + const tableSchema = table[MySqlTable.Symbol.Schema]; + const origTableName = table[MySqlTable.Symbol.OriginalName]; + const alias = tableName === origTableName ? undefined : joinMeta.alias; + const useIndexSql = this.buildIndex({ indexes: joinMeta.useIndex, indexFor: 'USE' }); + const forceIndexSql = this.buildIndex({ indexes: joinMeta.forceIndex, indexFor: 'FORCE' }); + const ignoreIndexSql = this.buildIndex({ indexes: joinMeta.ignoreIndex, indexFor: 'IGNORE' }); + joinsArray.push( + sql`${sql.raw(joinMeta.joinType)} join${lateralSql} ${ + tableSchema ? sql`${sql.identifier(tableSchema)}.` : undefined + }${sql.identifier(origTableName)}${useIndexSql}${forceIndexSql}${ignoreIndexSql}${ + alias && sql` ${sql.identifier(alias)}` + } on ${joinMeta.on}`, + ); + } else if (is(table, View)) { + const viewName = table[ViewBaseConfig].name; + const viewSchema = table[ViewBaseConfig].schema; + const origViewName = table[ViewBaseConfig].originalName; + const alias = viewName === origViewName ? undefined : joinMeta.alias; + joinsArray.push( + sql`${sql.raw(joinMeta.joinType)} join${lateralSql} ${ + viewSchema ? sql`${sql.identifier(viewSchema)}.` : undefined + }${sql.identifier(origViewName)}${alias && sql` ${sql.identifier(alias)}`} on ${joinMeta.on}`, + ); + } else { + joinsArray.push( + sql`${sql.raw(joinMeta.joinType)} join${lateralSql} ${table} on ${joinMeta.on}`, + ); + } + if (index < joins.length - 1) { + joinsArray.push(sql` `); + } + } + } + + const joinsSql = sql.join(joinsArray); + + const whereSql = where ? sql` where ${where}` : undefined; + + const havingSql = having ? sql` having ${having}` : undefined; + + const orderBySql = this.buildOrderBy(orderBy); + + const groupBySql = groupBy && groupBy.length > 0 ? sql` group by ${sql.join(groupBy, sql`, `)}` : undefined; + + const limitSql = this.buildLimit(limit); + + const offsetSql = offset ? sql` offset ${offset}` : undefined; + + const useIndexSql = this.buildIndex({ indexes: useIndex, indexFor: 'USE' }); + + const forceIndexSql = this.buildIndex({ indexes: forceIndex, indexFor: 'FORCE' }); + + const ignoreIndexSql = this.buildIndex({ indexes: ignoreIndex, indexFor: 'IGNORE' }); + + let lockingClausesSql; + if (lockingClause) { + const { config, strength } = lockingClause; + lockingClausesSql = sql` for ${sql.raw(strength)}`; + if (config.noWait) { + lockingClausesSql.append(sql` no wait`); + } else if (config.skipLocked) { + lockingClausesSql.append(sql` skip locked`); + } + } + + const finalQuery = + sql`${withSql}select${distinctSql} ${selection} from ${tableSql}${useIndexSql}${forceIndexSql}${ignoreIndexSql}${joinsSql}${whereSql}${groupBySql}${havingSql}${orderBySql}${limitSql}${offsetSql}${lockingClausesSql}`; + + if (setOperators.length > 0) { + return this.buildSetOperations(finalQuery, setOperators); + } + + return finalQuery; + } + + buildSetOperations(leftSelect: SQL, setOperators: MySqlSelectConfig['setOperators']): SQL { + const [setOperator, ...rest] = setOperators; + + if (!setOperator) { + throw new Error('Cannot pass undefined values to any set operator'); + } + + if (rest.length === 0) { + return this.buildSetOperationQuery({ leftSelect, setOperator }); + } + + // Some recursive magic here + return this.buildSetOperations( + this.buildSetOperationQuery({ leftSelect, setOperator }), + rest, + ); + } + + buildSetOperationQuery({ + leftSelect, + setOperator: { type, isAll, rightSelect, limit, orderBy, offset }, + }: { leftSelect: SQL; setOperator: MySqlSelectConfig['setOperators'][number] }): SQL { + const leftChunk = sql`(${leftSelect.getSQL()}) `; + const rightChunk = sql`(${rightSelect.getSQL()})`; + + let orderBySql; + if (orderBy && orderBy.length > 0) { + const orderByValues: (SQL | Name)[] = []; + + // The next bit is necessary because the sql operator replaces ${table.column} with `table`.`column` + // which is invalid MySql syntax, Table from one of the SELECTs cannot be used in global ORDER clause + for (const orderByUnit of orderBy) { + if (is(orderByUnit, MySqlColumn)) { + orderByValues.push(sql.identifier(this.casing.getColumnCasing(orderByUnit))); + } else if (is(orderByUnit, SQL)) { + for (let i = 0; i < orderByUnit.queryChunks.length; i++) { + const chunk = orderByUnit.queryChunks[i]; + + if (is(chunk, MySqlColumn)) { + orderByUnit.queryChunks[i] = sql.identifier(this.casing.getColumnCasing(chunk)); + } + } + + orderByValues.push(sql`${orderByUnit}`); + } else { + orderByValues.push(sql`${orderByUnit}`); + } + } + + orderBySql = sql` order by ${sql.join(orderByValues, sql`, `)} `; + } + + const limitSql = typeof limit === 'object' || (typeof limit === 'number' && limit >= 0) + ? sql` limit ${limit}` + : undefined; + + const operatorChunk = sql.raw(`${type} ${isAll ? 'all ' : ''}`); + + const offsetSql = offset ? sql` offset ${offset}` : undefined; + + return sql`${leftChunk}${operatorChunk}${rightChunk}${orderBySql}${limitSql}${offsetSql}`; + } + + buildInsertQuery( + { table, values: valuesOrSelect, ignore, onConflict, select }: MySqlInsertConfig, + ): { sql: SQL; generatedIds: Record[] } { + // const isSingleValue = values.length === 1; + const valuesSqlList: ((SQLChunk | SQL)[] | SQL)[] = []; + const columns: Record = table[Table.Symbol.Columns]; + const colEntries: [string, MySqlColumn][] = Object.entries(columns).filter(([_, col]) => + !col.shouldDisableInsert() + ); + + const insertOrder = colEntries.map(([, column]) => sql.identifier(this.casing.getColumnCasing(column))); + const generatedIdsResponse: Record[] = []; + + if (select) { + const select = valuesOrSelect as AnyMySqlSelectQueryBuilder | SQL; + + if (is(select, SQL)) { + valuesSqlList.push(select); + } else { + valuesSqlList.push(select.getSQL()); + } + } else { + const values = valuesOrSelect as Record[]; + valuesSqlList.push(sql.raw('values ')); + + for (const [valueIndex, value] of values.entries()) { + const generatedIds: Record = {}; + + const valueList: (SQLChunk | SQL)[] = []; + for (const [fieldName, col] of colEntries) { + const colValue = value[fieldName]; + if (colValue === undefined || (is(colValue, Param) && colValue.value === undefined)) { + // eslint-disable-next-line unicorn/no-negated-condition + if (col.defaultFn !== undefined) { + const defaultFnResult = col.defaultFn(); + generatedIds[fieldName] = defaultFnResult; + const defaultValue = is(defaultFnResult, SQL) ? defaultFnResult : sql.param(defaultFnResult, col); + valueList.push(defaultValue); + // eslint-disable-next-line unicorn/no-negated-condition + } else if (!col.default && col.onUpdateFn !== undefined) { + const onUpdateFnResult = col.onUpdateFn(); + const newValue = is(onUpdateFnResult, SQL) ? onUpdateFnResult : sql.param(onUpdateFnResult, col); + valueList.push(newValue); + } else { + valueList.push(sql`default`); + } + } else { + if (col.defaultFn && is(colValue, Param)) { + generatedIds[fieldName] = colValue.value; + } + valueList.push(colValue); + } + } + + generatedIdsResponse.push(generatedIds); + valuesSqlList.push(valueList); + if (valueIndex < values.length - 1) { + valuesSqlList.push(sql`, `); + } + } + } + + const valuesSql = sql.join(valuesSqlList); + + const ignoreSql = ignore ? sql` ignore` : undefined; + + const onConflictSql = onConflict ? sql` on duplicate key ${onConflict}` : undefined; + + return { + sql: sql`insert${ignoreSql} into ${table} ${insertOrder} ${valuesSql}${onConflictSql}`, + generatedIds: generatedIdsResponse, + }; + } + + sqlToQuery(sql: SQL, invokeSource?: 'indexes' | undefined): QueryWithTypings { + return sql.toQuery({ + casing: this.casing, + escapeName: this.escapeName, + escapeParam: this.escapeParam, + escapeString: this.escapeString, + invokeSource, + }); + } + + buildRelationalQuery({ + fullSchema, + schema, + tableNamesMap, + table, + tableConfig, + queryConfig: config, + tableAlias, + nestedQueryRelation, + joinOn, + }: { + fullSchema: Record; + schema: TablesRelationalConfig; + tableNamesMap: Record; + table: MySqlTable; + tableConfig: TableRelationalConfig; + queryConfig: true | DBQueryConfig<'many', true>; + tableAlias: string; + nestedQueryRelation?: Relation; + joinOn?: SQL; + }): BuildRelationalQueryResult { + let selection: BuildRelationalQueryResult['selection'] = []; + let limit, offset, orderBy: MySqlSelectConfig['orderBy'], where; + const joins: MySqlSelectJoinConfig[] = []; + + if (config === true) { + const selectionEntries = Object.entries(tableConfig.columns); + selection = selectionEntries.map(( + [key, value], + ) => ({ + dbKey: value.name, + tsKey: key, + field: aliasedTableColumn(value as MySqlColumn, tableAlias), + relationTableTsKey: undefined, + isJson: false, + selection: [], + })); + } else { + const aliasedColumns = Object.fromEntries( + Object.entries(tableConfig.columns).map(([key, value]) => [key, aliasedTableColumn(value, tableAlias)]), + ); + + if (config.where) { + const whereSql = typeof config.where === 'function' + ? config.where(aliasedColumns, getOperators()) + : config.where; + where = whereSql && mapColumnsInSQLToAlias(whereSql, tableAlias); + } + + const fieldsSelection: { tsKey: string; value: MySqlColumn | SQL.Aliased }[] = []; + let selectedColumns: string[] = []; + + // Figure out which columns to select + if (config.columns) { + let isIncludeMode = false; + + for (const [field, value] of Object.entries(config.columns)) { + if (value === undefined) { + continue; + } + + if (field in tableConfig.columns) { + if (!isIncludeMode && value === true) { + isIncludeMode = true; + } + selectedColumns.push(field); + } + } + + if (selectedColumns.length > 0) { + selectedColumns = isIncludeMode + ? selectedColumns.filter((c) => config.columns?.[c] === true) + : Object.keys(tableConfig.columns).filter((key) => !selectedColumns.includes(key)); + } + } else { + // Select all columns if selection is not specified + selectedColumns = Object.keys(tableConfig.columns); + } + + for (const field of selectedColumns) { + const column = tableConfig.columns[field]! as MySqlColumn; + fieldsSelection.push({ tsKey: field, value: column }); + } + + let selectedRelations: { + tsKey: string; + queryConfig: true | DBQueryConfig<'many', false>; + relation: Relation; + }[] = []; + + // Figure out which relations to select + if (config.with) { + selectedRelations = Object.entries(config.with) + .filter((entry): entry is [typeof entry[0], NonNullable] => !!entry[1]) + .map(([tsKey, queryConfig]) => ({ tsKey, queryConfig, relation: tableConfig.relations[tsKey]! })); + } + + let extras; + + // Figure out which extras to select + if (config.extras) { + extras = typeof config.extras === 'function' + ? config.extras(aliasedColumns, { sql }) + : config.extras; + for (const [tsKey, value] of Object.entries(extras)) { + fieldsSelection.push({ + tsKey, + value: mapColumnsInAliasedSQLToAlias(value, tableAlias), + }); + } + } + + // Transform `fieldsSelection` into `selection` + // `fieldsSelection` shouldn't be used after this point + for (const { tsKey, value } of fieldsSelection) { + selection.push({ + dbKey: is(value, SQL.Aliased) ? value.fieldAlias : tableConfig.columns[tsKey]!.name, + tsKey, + field: is(value, Column) ? aliasedTableColumn(value, tableAlias) : value, + relationTableTsKey: undefined, + isJson: false, + selection: [], + }); + } + + let orderByOrig = typeof config.orderBy === 'function' + ? config.orderBy(aliasedColumns, getOrderByOperators()) + : config.orderBy ?? []; + if (!Array.isArray(orderByOrig)) { + orderByOrig = [orderByOrig]; + } + orderBy = orderByOrig.map((orderByValue) => { + if (is(orderByValue, Column)) { + return aliasedTableColumn(orderByValue, tableAlias) as MySqlColumn; + } + return mapColumnsInSQLToAlias(orderByValue, tableAlias); + }); + + limit = config.limit; + offset = config.offset; + + // Process all relations + for ( + const { + tsKey: selectedRelationTsKey, + queryConfig: selectedRelationConfigValue, + relation, + } of selectedRelations + ) { + const normalizedRelation = normalizeRelation(schema, tableNamesMap, relation); + const relationTableName = getTableUniqueName(relation.referencedTable); + const relationTableTsName = tableNamesMap[relationTableName]!; + const relationTableAlias = `${tableAlias}_${selectedRelationTsKey}`; + const joinOn = and( + ...normalizedRelation.fields.map((field, i) => + eq( + aliasedTableColumn(normalizedRelation.references[i]!, relationTableAlias), + aliasedTableColumn(field, tableAlias), + ) + ), + ); + const builtRelation = this.buildRelationalQuery({ + fullSchema, + schema, + tableNamesMap, + table: fullSchema[relationTableTsName] as MySqlTable, + tableConfig: schema[relationTableTsName]!, + queryConfig: is(relation, One) + ? (selectedRelationConfigValue === true + ? { limit: 1 } + : { ...selectedRelationConfigValue, limit: 1 }) + : selectedRelationConfigValue, + tableAlias: relationTableAlias, + joinOn, + nestedQueryRelation: relation, + }); + const field = sql`${sql.identifier(relationTableAlias)}.${sql.identifier('data')}`.as(selectedRelationTsKey); + joins.push({ + on: sql`true`, + table: new Subquery(builtRelation.sql as SQL, {}, relationTableAlias), + alias: relationTableAlias, + joinType: 'left', + lateral: true, + }); + selection.push({ + dbKey: selectedRelationTsKey, + tsKey: selectedRelationTsKey, + field, + relationTableTsKey: relationTableTsName, + isJson: true, + selection: builtRelation.selection, + }); + } + } + + if (selection.length === 0) { + throw new DrizzleError({ message: `No fields selected for table "${tableConfig.tsName}" ("${tableAlias}")` }); + } + + let result; + + where = and(joinOn, where); + + if (nestedQueryRelation) { + let field = sql`json_array(${ + sql.join( + selection.map(({ field, tsKey, isJson }) => + isJson + ? sql`${sql.identifier(`${tableAlias}_${tsKey}`)}.${sql.identifier('data')}` + : is(field, SQL.Aliased) + ? field.sql + : field + ), + sql`, `, + ) + })`; + if (is(nestedQueryRelation, Many)) { + field = sql`coalesce(json_arrayagg(${field}), json_array())`; + } + const nestedSelection = [{ + dbKey: 'data', + tsKey: 'data', + field: field.as('data'), + isJson: true, + relationTableTsKey: tableConfig.tsName, + selection, + }]; + + const needsSubquery = limit !== undefined || offset !== undefined || (orderBy?.length ?? 0) > 0; + + if (needsSubquery) { + result = this.buildSelectQuery({ + table: aliasedTable(table, tableAlias), + fields: {}, + fieldsFlat: [ + { + path: [], + field: sql.raw('*'), + }, + ...(((orderBy?.length ?? 0) > 0) + ? [{ + path: [], + field: sql`row_number() over (order by ${sql.join(orderBy!, sql`, `)})`, + }] + : []), + ], + where, + limit, + offset, + setOperators: [], + }); + + where = undefined; + limit = undefined; + offset = undefined; + orderBy = undefined; + } else { + result = aliasedTable(table, tableAlias); + } + + result = this.buildSelectQuery({ + table: is(result, MySqlTable) ? result : new Subquery(result, {}, tableAlias), + fields: {}, + fieldsFlat: nestedSelection.map(({ field }) => ({ + path: [], + field: is(field, Column) ? aliasedTableColumn(field, tableAlias) : field, + })), + joins, + where, + limit, + offset, + orderBy, + setOperators: [], + }); + } else { + result = this.buildSelectQuery({ + table: aliasedTable(table, tableAlias), + fields: {}, + fieldsFlat: selection.map(({ field }) => ({ + path: [], + field: is(field, Column) ? aliasedTableColumn(field, tableAlias) : field, + })), + joins, + where, + limit, + offset, + orderBy, + setOperators: [], + }); + } + + return { + tableTsKey: tableConfig.tsName, + sql: result, + selection, + }; + } + + buildRelationalQueryWithoutLateralSubqueries({ + fullSchema, + schema, + tableNamesMap, + table, + tableConfig, + queryConfig: config, + tableAlias, + nestedQueryRelation, + joinOn, + }: { + fullSchema: Record; + schema: TablesRelationalConfig; + tableNamesMap: Record; + table: MySqlTable; + tableConfig: TableRelationalConfig; + queryConfig: true | DBQueryConfig<'many', true>; + tableAlias: string; + nestedQueryRelation?: Relation; + joinOn?: SQL; + }): BuildRelationalQueryResult { + let selection: BuildRelationalQueryResult['selection'] = []; + let limit, offset, orderBy: MySqlSelectConfig['orderBy'] = [], where; + + if (config === true) { + const selectionEntries = Object.entries(tableConfig.columns); + selection = selectionEntries.map(( + [key, value], + ) => ({ + dbKey: value.name, + tsKey: key, + field: aliasedTableColumn(value as MySqlColumn, tableAlias), + relationTableTsKey: undefined, + isJson: false, + selection: [], + })); + } else { + const aliasedColumns = Object.fromEntries( + Object.entries(tableConfig.columns).map(([key, value]) => [key, aliasedTableColumn(value, tableAlias)]), + ); + + if (config.where) { + const whereSql = typeof config.where === 'function' + ? config.where(aliasedColumns, getOperators()) + : config.where; + where = whereSql && mapColumnsInSQLToAlias(whereSql, tableAlias); + } + + const fieldsSelection: { tsKey: string; value: MySqlColumn | SQL.Aliased }[] = []; + let selectedColumns: string[] = []; + + // Figure out which columns to select + if (config.columns) { + let isIncludeMode = false; + + for (const [field, value] of Object.entries(config.columns)) { + if (value === undefined) { + continue; + } + + if (field in tableConfig.columns) { + if (!isIncludeMode && value === true) { + isIncludeMode = true; + } + selectedColumns.push(field); + } + } + + if (selectedColumns.length > 0) { + selectedColumns = isIncludeMode + ? selectedColumns.filter((c) => config.columns?.[c] === true) + : Object.keys(tableConfig.columns).filter((key) => !selectedColumns.includes(key)); + } + } else { + // Select all columns if selection is not specified + selectedColumns = Object.keys(tableConfig.columns); + } + + for (const field of selectedColumns) { + const column = tableConfig.columns[field]! as MySqlColumn; + fieldsSelection.push({ tsKey: field, value: column }); + } + + let selectedRelations: { + tsKey: string; + queryConfig: true | DBQueryConfig<'many', false>; + relation: Relation; + }[] = []; + + // Figure out which relations to select + if (config.with) { + selectedRelations = Object.entries(config.with) + .filter((entry): entry is [typeof entry[0], NonNullable] => !!entry[1]) + .map(([tsKey, queryConfig]) => ({ tsKey, queryConfig, relation: tableConfig.relations[tsKey]! })); + } + + let extras; + + // Figure out which extras to select + if (config.extras) { + extras = typeof config.extras === 'function' + ? config.extras(aliasedColumns, { sql }) + : config.extras; + for (const [tsKey, value] of Object.entries(extras)) { + fieldsSelection.push({ + tsKey, + value: mapColumnsInAliasedSQLToAlias(value, tableAlias), + }); + } + } + + // Transform `fieldsSelection` into `selection` + // `fieldsSelection` shouldn't be used after this point + for (const { tsKey, value } of fieldsSelection) { + selection.push({ + dbKey: is(value, SQL.Aliased) ? value.fieldAlias : tableConfig.columns[tsKey]!.name, + tsKey, + field: is(value, Column) ? aliasedTableColumn(value, tableAlias) : value, + relationTableTsKey: undefined, + isJson: false, + selection: [], + }); + } + + let orderByOrig = typeof config.orderBy === 'function' + ? config.orderBy(aliasedColumns, getOrderByOperators()) + : config.orderBy ?? []; + if (!Array.isArray(orderByOrig)) { + orderByOrig = [orderByOrig]; + } + orderBy = orderByOrig.map((orderByValue) => { + if (is(orderByValue, Column)) { + return aliasedTableColumn(orderByValue, tableAlias) as MySqlColumn; + } + return mapColumnsInSQLToAlias(orderByValue, tableAlias); + }); + + limit = config.limit; + offset = config.offset; + + // Process all relations + for ( + const { + tsKey: selectedRelationTsKey, + queryConfig: selectedRelationConfigValue, + relation, + } of selectedRelations + ) { + const normalizedRelation = normalizeRelation(schema, tableNamesMap, relation); + const relationTableName = getTableUniqueName(relation.referencedTable); + const relationTableTsName = tableNamesMap[relationTableName]!; + const relationTableAlias = `${tableAlias}_${selectedRelationTsKey}`; + const joinOn = and( + ...normalizedRelation.fields.map((field, i) => + eq( + aliasedTableColumn(normalizedRelation.references[i]!, relationTableAlias), + aliasedTableColumn(field, tableAlias), + ) + ), + ); + const builtRelation = this.buildRelationalQueryWithoutLateralSubqueries({ + fullSchema, + schema, + tableNamesMap, + table: fullSchema[relationTableTsName] as MySqlTable, + tableConfig: schema[relationTableTsName]!, + queryConfig: is(relation, One) + ? (selectedRelationConfigValue === true + ? { limit: 1 } + : { ...selectedRelationConfigValue, limit: 1 }) + : selectedRelationConfigValue, + tableAlias: relationTableAlias, + joinOn, + nestedQueryRelation: relation, + }); + let fieldSql = sql`(${builtRelation.sql})`; + if (is(relation, Many)) { + fieldSql = sql`coalesce(${fieldSql}, json_array())`; + } + const field = fieldSql.as(selectedRelationTsKey); + selection.push({ + dbKey: selectedRelationTsKey, + tsKey: selectedRelationTsKey, + field, + relationTableTsKey: relationTableTsName, + isJson: true, + selection: builtRelation.selection, + }); + } + } + + if (selection.length === 0) { + throw new DrizzleError({ + message: + `No fields selected for table "${tableConfig.tsName}" ("${tableAlias}"). You need to have at least one item in "columns", "with" or "extras". If you need to select all columns, omit the "columns" key or set it to undefined.`, + }); + } + + let result; + + where = and(joinOn, where); + + if (nestedQueryRelation) { + let field = sql`json_array(${ + sql.join( + selection.map(({ field }) => + is(field, MySqlColumn) + ? sql.identifier(this.casing.getColumnCasing(field)) + : is(field, SQL.Aliased) + ? field.sql + : field + ), + sql`, `, + ) + })`; + if (is(nestedQueryRelation, Many)) { + field = sql`json_arrayagg(${field})`; + } + const nestedSelection = [{ + dbKey: 'data', + tsKey: 'data', + field, + isJson: true, + relationTableTsKey: tableConfig.tsName, + selection, + }]; + + const needsSubquery = limit !== undefined || offset !== undefined || orderBy.length > 0; + + if (needsSubquery) { + result = this.buildSelectQuery({ + table: aliasedTable(table, tableAlias), + fields: {}, + fieldsFlat: [ + { + path: [], + field: sql.raw('*'), + }, + ...(orderBy.length > 0) + ? [{ + path: [], + field: sql`row_number() over (order by ${sql.join(orderBy, sql`, `)})`, + }] + : [], + ], + where, + limit, + offset, + setOperators: [], + }); + + where = undefined; + limit = undefined; + offset = undefined; + orderBy = undefined; + } else { + result = aliasedTable(table, tableAlias); + } + + result = this.buildSelectQuery({ + table: is(result, MySqlTable) ? result : new Subquery(result, {}, tableAlias), + fields: {}, + fieldsFlat: nestedSelection.map(({ field }) => ({ + path: [], + field: is(field, Column) ? aliasedTableColumn(field, tableAlias) : field, + })), + where, + limit, + offset, + orderBy, + setOperators: [], + }); + } else { + result = this.buildSelectQuery({ + table: aliasedTable(table, tableAlias), + fields: {}, + fieldsFlat: selection.map(({ field }) => ({ + path: [], + field: is(field, Column) ? aliasedTableColumn(field, tableAlias) : field, + })), + where, + limit, + offset, + orderBy, + setOperators: [], + }); + } + + return { + tableTsKey: tableConfig.tsName, + sql: result, + selection, + }; + } +} diff --git a/drizzle-orm/src/googlesql/expressions.ts b/drizzle-orm/src/googlesql/expressions.ts new file mode 100644 index 0000000000..a61f77786e --- /dev/null +++ b/drizzle-orm/src/googlesql/expressions.ts @@ -0,0 +1,25 @@ +import { bindIfParam } from '~/expressions.ts'; +import type { Placeholder, SQL, SQLChunk, SQLWrapper } from '~/sql/sql.ts'; +import { sql } from '~/sql/sql.ts'; +import type { MySqlColumn } from './columns/index.ts'; + +export * from '~/expressions.ts'; + +export function concat(column: MySqlColumn | SQL.Aliased, value: string | Placeholder | SQLWrapper): SQL { + return sql`${column} || ${bindIfParam(value, column)}`; +} + +export function substring( + column: MySqlColumn | SQL.Aliased, + { from, for: _for }: { from?: number | Placeholder | SQLWrapper; for?: number | Placeholder | SQLWrapper }, +): SQL { + const chunks: SQLChunk[] = [sql`substring(`, column]; + if (from !== undefined) { + chunks.push(sql` from `, bindIfParam(from, column)); + } + if (_for !== undefined) { + chunks.push(sql` for `, bindIfParam(_for, column)); + } + chunks.push(sql`)`); + return sql.join(chunks); +} diff --git a/drizzle-orm/src/googlesql/foreign-keys.ts b/drizzle-orm/src/googlesql/foreign-keys.ts new file mode 100644 index 0000000000..c8c34d6fd4 --- /dev/null +++ b/drizzle-orm/src/googlesql/foreign-keys.ts @@ -0,0 +1,126 @@ +import { entityKind } from '~/entity.ts'; +import { TableName } from '~/table.utils.ts'; +import type { AnyMySqlColumn, MySqlColumn } from './columns/index.ts'; +import type { MySqlTable } from './table.ts'; + +export type UpdateDeleteAction = 'cascade' | 'restrict' | 'no action' | 'set null' | 'set default'; + +export type Reference = () => { + readonly name?: string; + readonly columns: MySqlColumn[]; + readonly foreignTable: MySqlTable; + readonly foreignColumns: MySqlColumn[]; +}; + +export class ForeignKeyBuilder { + static readonly [entityKind]: string = 'MySqlForeignKeyBuilder'; + + /** @internal */ + reference: Reference; + + /** @internal */ + _onUpdate: UpdateDeleteAction | undefined; + + /** @internal */ + _onDelete: UpdateDeleteAction | undefined; + + constructor( + config: () => { + name?: string; + columns: MySqlColumn[]; + foreignColumns: MySqlColumn[]; + }, + actions?: { + onUpdate?: UpdateDeleteAction; + onDelete?: UpdateDeleteAction; + } | undefined, + ) { + this.reference = () => { + const { name, columns, foreignColumns } = config(); + return { name, columns, foreignTable: foreignColumns[0]!.table as MySqlTable, foreignColumns }; + }; + if (actions) { + this._onUpdate = actions.onUpdate; + this._onDelete = actions.onDelete; + } + } + + onUpdate(action: UpdateDeleteAction): this { + this._onUpdate = action; + return this; + } + + onDelete(action: UpdateDeleteAction): this { + this._onDelete = action; + return this; + } + + /** @internal */ + build(table: MySqlTable): ForeignKey { + return new ForeignKey(table, this); + } +} + +export type AnyForeignKeyBuilder = ForeignKeyBuilder; + +export class ForeignKey { + static readonly [entityKind]: string = 'MySqlForeignKey'; + + readonly reference: Reference; + readonly onUpdate: UpdateDeleteAction | undefined; + readonly onDelete: UpdateDeleteAction | undefined; + + constructor(readonly table: MySqlTable, builder: ForeignKeyBuilder) { + this.reference = builder.reference; + this.onUpdate = builder._onUpdate; + this.onDelete = builder._onDelete; + } + + getName(): string { + const { name, columns, foreignColumns } = this.reference(); + const columnNames = columns.map((column) => column.name); + const foreignColumnNames = foreignColumns.map((column) => column.name); + const chunks = [ + this.table[TableName], + ...columnNames, + foreignColumns[0]!.table[TableName], + ...foreignColumnNames, + ]; + return name ?? `${chunks.join('_')}_fk`; + } +} + +type ColumnsWithTable< + TTableName extends string, + TColumns extends MySqlColumn[], +> = { [Key in keyof TColumns]: AnyMySqlColumn<{ tableName: TTableName }> }; + +export type GetColumnsTable = ( + TColumns extends MySqlColumn ? TColumns + : TColumns extends MySqlColumn[] ? TColumns[number] + : never +) extends AnyMySqlColumn<{ tableName: infer TTableName extends string }> ? TTableName + : never; + +export function foreignKey< + TTableName extends string, + TForeignTableName extends string, + TColumns extends [AnyMySqlColumn<{ tableName: TTableName }>, ...AnyMySqlColumn<{ tableName: TTableName }>[]], +>( + config: { + name?: string; + columns: TColumns; + foreignColumns: ColumnsWithTable; + }, +): ForeignKeyBuilder { + function mappedConfig() { + const { name, columns, foreignColumns } = config; + return { + name, + columns, + foreignColumns, + }; + } + + return new ForeignKeyBuilder(mappedConfig); +} diff --git a/drizzle-orm/src/googlesql/index.ts b/drizzle-orm/src/googlesql/index.ts new file mode 100644 index 0000000000..204e0af3c4 --- /dev/null +++ b/drizzle-orm/src/googlesql/index.ts @@ -0,0 +1,17 @@ +export * from './alias.ts'; +export * from './checks.ts'; +export * from './columns/index.ts'; +export * from './db.ts'; +export * from './dialect.ts'; +export * from './foreign-keys.ts'; +export * from './indexes.ts'; +export * from './primary-keys.ts'; +export * from './query-builders/index.ts'; +export * from './schema.ts'; +export * from './session.ts'; +export * from './subquery.ts'; +export * from './table.ts'; +export * from './unique-constraint.ts'; +export * from './utils.ts'; +export * from './view-common.ts'; +export * from './view.ts'; diff --git a/drizzle-orm/src/googlesql/indexes.ts b/drizzle-orm/src/googlesql/indexes.ts new file mode 100644 index 0000000000..5b73b1d309 --- /dev/null +++ b/drizzle-orm/src/googlesql/indexes.ts @@ -0,0 +1,108 @@ +import { entityKind } from '~/entity.ts'; +import type { SQL } from '~/sql/sql.ts'; +import type { AnyMySqlColumn, MySqlColumn } from './columns/index.ts'; +import type { MySqlTable } from './table.ts'; + +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 ... algorythm { 'default' | 'inplace' | 'copy' }`. + */ + algorythm?: 'default' | 'inplace' | 'copy'; + + /** + * If set, adds locks to the index creation. + */ + lock?: 'default' | 'none' | 'shared' | 'exclusive'; +} + +export type IndexColumn = MySqlColumn | SQL; + +export class IndexBuilderOn { + static readonly [entityKind]: string = 'MySqlIndexBuilderOn'; + + constructor(private name: string, private unique: boolean) {} + + on(...columns: [IndexColumn, ...IndexColumn[]]): IndexBuilder { + return new IndexBuilder(this.name, columns, this.unique); + } +} + +export interface AnyIndexBuilder { + build(table: MySqlTable): Index; +} + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface IndexBuilder extends AnyIndexBuilder {} + +export class IndexBuilder implements AnyIndexBuilder { + static readonly [entityKind]: string = 'MySqlIndexBuilder'; + + /** @internal */ + config: IndexConfig; + + constructor(name: string, columns: IndexColumn[], unique: boolean) { + this.config = { + name, + columns, + unique, + }; + } + + using(using: IndexConfig['using']): this { + this.config.using = using; + return this; + } + + algorythm(algorythm: IndexConfig['algorythm']): this { + this.config.algorythm = algorythm; + return this; + } + + lock(lock: IndexConfig['lock']): this { + this.config.lock = lock; + return this; + } + + /** @internal */ + build(table: MySqlTable): Index { + return new Index(this.config, table); + } +} + +export class Index { + static readonly [entityKind]: string = 'MySqlIndex'; + + readonly config: IndexConfig & { table: MySqlTable }; + + constructor(config: IndexConfig, table: MySqlTable) { + this.config = { ...config, table }; + } +} + +export type GetColumnsTableName = TColumns extends + AnyMySqlColumn<{ tableName: infer TTableName extends string }> | AnyMySqlColumn< + { tableName: infer TTableName extends string } + >[] ? TTableName + : never; + +export function index(name: string): IndexBuilderOn { + return new IndexBuilderOn(name, false); +} + +export function uniqueIndex(name: string): IndexBuilderOn { + return new IndexBuilderOn(name, true); +} diff --git a/drizzle-orm/src/googlesql/primary-keys.ts b/drizzle-orm/src/googlesql/primary-keys.ts new file mode 100644 index 0000000000..014cbd8c0b --- /dev/null +++ b/drizzle-orm/src/googlesql/primary-keys.ts @@ -0,0 +1,63 @@ +import { entityKind } from '~/entity.ts'; +import type { AnyMySqlColumn, MySqlColumn } from './columns/index.ts'; +import { MySqlTable } from './table.ts'; + +export function primaryKey< + TTableName extends string, + TColumn extends AnyMySqlColumn<{ tableName: TTableName }>, + TColumns extends AnyMySqlColumn<{ tableName: TTableName }>[], +>(config: { name?: string; columns: [TColumn, ...TColumns] }): PrimaryKeyBuilder; +/** + * @deprecated: Please use primaryKey({ columns: [] }) instead of this function + * @param columns + */ +export function primaryKey< + TTableName extends string, + TColumns extends AnyMySqlColumn<{ tableName: TTableName }>[], +>(...columns: TColumns): PrimaryKeyBuilder; +export function primaryKey(...config: any) { + if (config[0].columns) { + return new PrimaryKeyBuilder(config[0].columns, config[0].name); + } + return new PrimaryKeyBuilder(config); +} + +export class PrimaryKeyBuilder { + static readonly [entityKind]: string = 'MySqlPrimaryKeyBuilder'; + + /** @internal */ + columns: MySqlColumn[]; + + /** @internal */ + name?: string; + + constructor( + columns: MySqlColumn[], + name?: string, + ) { + this.columns = columns; + this.name = name; + } + + /** @internal */ + build(table: MySqlTable): PrimaryKey { + return new PrimaryKey(table, this.columns, this.name); + } +} + +export class PrimaryKey { + static readonly [entityKind]: string = 'MySqlPrimaryKey'; + + readonly columns: MySqlColumn[]; + readonly name?: string; + + constructor(readonly table: MySqlTable, columns: MySqlColumn[], name?: string) { + this.columns = columns; + this.name = name; + } + + getName(): string { + return this.name + ?? `${this.table[MySqlTable.Symbol.Name]}_${this.columns.map((column) => column.name).join('_')}_pk`; + } +} diff --git a/drizzle-orm/src/googlesql/query-builders/count.ts b/drizzle-orm/src/googlesql/query-builders/count.ts new file mode 100644 index 0000000000..9a0241c70e --- /dev/null +++ b/drizzle-orm/src/googlesql/query-builders/count.ts @@ -0,0 +1,79 @@ +import { entityKind } from '~/entity.ts'; +import { SQL, sql, type SQLWrapper } from '~/sql/sql.ts'; +import type { MySqlSession } from '../session.ts'; +import type { MySqlTable } from '../table.ts'; +import type { MySqlViewBase } from '../view-base.ts'; + +export class MySqlCountBuilder< + TSession extends MySqlSession, +> extends SQL implements Promise, SQLWrapper { + private sql: SQL; + + static override readonly [entityKind] = 'MySqlCountBuilder'; + [Symbol.toStringTag] = 'MySqlCountBuilder'; + + private session: TSession; + + private static buildEmbeddedCount( + source: MySqlTable | MySqlViewBase | SQL | SQLWrapper, + filters?: SQL, + ): SQL { + return sql`(select count(*) from ${source}${sql.raw(' where ').if(filters)}${filters})`; + } + + private static buildCount( + source: MySqlTable | MySqlViewBase | SQL | SQLWrapper, + filters?: SQL, + ): SQL { + return sql`select count(*) as count from ${source}${sql.raw(' where ').if(filters)}${filters}`; + } + + constructor( + readonly params: { + source: MySqlTable | MySqlViewBase | SQL | SQLWrapper; + filters?: SQL; + session: TSession; + }, + ) { + super(MySqlCountBuilder.buildEmbeddedCount(params.source, params.filters).queryChunks); + + this.mapWith(Number); + + this.session = params.session; + + this.sql = MySqlCountBuilder.buildCount( + params.source, + params.filters, + ); + } + + then( + onfulfilled?: ((value: number) => TResult1 | PromiseLike) | null | undefined, + onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined, + ): Promise { + return Promise.resolve(this.session.count(this.sql)) + .then( + onfulfilled, + onrejected, + ); + } + + catch( + onRejected?: ((reason: any) => never | PromiseLike) | null | undefined, + ): Promise { + return this.then(undefined, onRejected); + } + + finally(onFinally?: (() => void) | null | undefined): Promise { + return this.then( + (value) => { + onFinally?.(); + return value; + }, + (reason) => { + onFinally?.(); + throw reason; + }, + ); + } +} diff --git a/drizzle-orm/src/googlesql/query-builders/delete.ts b/drizzle-orm/src/googlesql/query-builders/delete.ts new file mode 100644 index 0000000000..22a3e1be36 --- /dev/null +++ b/drizzle-orm/src/googlesql/query-builders/delete.ts @@ -0,0 +1,207 @@ +import { entityKind } from '~/entity.ts'; +import type { MySqlDialect } from '~/mysql-core/dialect.ts'; +import type { + AnyMySqlQueryResultHKT, + MySqlPreparedQueryConfig, + MySqlQueryResultHKT, + MySqlQueryResultKind, + MySqlSession, + PreparedQueryHKTBase, + PreparedQueryKind, +} from '~/mysql-core/session.ts'; +import type { MySqlTable } from '~/mysql-core/table.ts'; +import { QueryPromise } from '~/query-promise.ts'; +import { SelectionProxyHandler } from '~/selection-proxy.ts'; +import type { Placeholder, Query, SQL, SQLWrapper } from '~/sql/sql.ts'; +import type { Subquery } from '~/subquery.ts'; +import { Table } from '~/table.ts'; +import type { ValueOrArray } from '~/utils.ts'; +import type { MySqlColumn } from '../columns/common.ts'; +import type { SelectedFieldsOrdered } from './select.types.ts'; + +export type MySqlDeleteWithout< + T extends AnyMySqlDeleteBase, + TDynamic extends boolean, + K extends keyof T & string, +> = TDynamic extends true ? T + : Omit< + MySqlDeleteBase< + T['_']['table'], + T['_']['queryResult'], + T['_']['preparedQueryHKT'], + TDynamic, + T['_']['excludedMethods'] | K + >, + T['_']['excludedMethods'] | K + >; + +export type MySqlDelete< + TTable extends MySqlTable = MySqlTable, + TQueryResult extends MySqlQueryResultHKT = AnyMySqlQueryResultHKT, + TPreparedQueryHKT extends PreparedQueryHKTBase = PreparedQueryHKTBase, +> = MySqlDeleteBase; + +export interface MySqlDeleteConfig { + where?: SQL | undefined; + limit?: number | Placeholder; + orderBy?: (MySqlColumn | SQL | SQL.Aliased)[]; + table: MySqlTable; + returning?: SelectedFieldsOrdered; + withList?: Subquery[]; +} + +export type MySqlDeletePrepare = PreparedQueryKind< + T['_']['preparedQueryHKT'], + MySqlPreparedQueryConfig & { + execute: MySqlQueryResultKind; + iterator: never; + }, + true +>; + +type MySqlDeleteDynamic = MySqlDelete< + T['_']['table'], + T['_']['queryResult'], + T['_']['preparedQueryHKT'] +>; + +type AnyMySqlDeleteBase = MySqlDeleteBase; + +export interface MySqlDeleteBase< + TTable extends MySqlTable, + TQueryResult extends MySqlQueryResultHKT, + TPreparedQueryHKT extends PreparedQueryHKTBase, + TDynamic extends boolean = false, + TExcludedMethods extends string = never, +> extends QueryPromise> { + readonly _: { + readonly table: TTable; + readonly queryResult: TQueryResult; + readonly preparedQueryHKT: TPreparedQueryHKT; + readonly dynamic: TDynamic; + readonly excludedMethods: TExcludedMethods; + }; +} + +export class MySqlDeleteBase< + TTable extends MySqlTable, + TQueryResult extends MySqlQueryResultHKT, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + TPreparedQueryHKT extends PreparedQueryHKTBase, + TDynamic extends boolean = false, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + TExcludedMethods extends string = never, +> extends QueryPromise> implements SQLWrapper { + static override readonly [entityKind]: string = 'MySqlDelete'; + + private config: MySqlDeleteConfig; + + constructor( + private table: TTable, + private session: MySqlSession, + private dialect: MySqlDialect, + withList?: Subquery[], + ) { + super(); + this.config = { table, withList }; + } + + /** + * Adds a `where` clause to the query. + * + * Calling this method will delete only those rows that fulfill a specified condition. + * + * See docs: {@link https://orm.drizzle.team/docs/delete} + * + * @param where the `where` clause. + * + * @example + * You can use conditional operators and `sql function` to filter the rows to be deleted. + * + * ```ts + * // Delete all cars with green color + * db.delete(cars).where(eq(cars.color, 'green')); + * // or + * db.delete(cars).where(sql`${cars.color} = 'green'`) + * ``` + * + * You can logically combine conditional operators with `and()` and `or()` operators: + * + * ```ts + * // Delete all BMW cars with a green color + * db.delete(cars).where(and(eq(cars.color, 'green'), eq(cars.brand, 'BMW'))); + * + * // Delete all cars with the green or blue color + * db.delete(cars).where(or(eq(cars.color, 'green'), eq(cars.color, 'blue'))); + * ``` + */ + where(where: SQL | undefined): MySqlDeleteWithout { + this.config.where = where; + return this as any; + } + + orderBy( + builder: (deleteTable: TTable) => ValueOrArray, + ): MySqlDeleteWithout; + orderBy(...columns: (MySqlColumn | SQL | SQL.Aliased)[]): MySqlDeleteWithout; + orderBy( + ...columns: + | [(deleteTable: TTable) => ValueOrArray] + | (MySqlColumn | SQL | SQL.Aliased)[] + ): MySqlDeleteWithout { + if (typeof columns[0] === 'function') { + const orderBy = columns[0]( + new Proxy( + this.config.table[Table.Symbol.Columns], + new SelectionProxyHandler({ sqlAliasedBehavior: 'alias', sqlBehavior: 'sql' }), + ) as any, + ); + + const orderByArray = Array.isArray(orderBy) ? orderBy : [orderBy]; + this.config.orderBy = orderByArray; + } else { + const orderByArray = columns as (MySqlColumn | SQL | SQL.Aliased)[]; + this.config.orderBy = orderByArray; + } + return this as any; + } + + limit(limit: number | Placeholder): MySqlDeleteWithout { + this.config.limit = limit; + return this as any; + } + + /** @internal */ + getSQL(): SQL { + return this.dialect.buildDeleteQuery(this.config); + } + + toSQL(): Query { + const { typings: _typings, ...rest } = this.dialect.sqlToQuery(this.getSQL()); + return rest; + } + + prepare(): MySqlDeletePrepare { + return this.session.prepareQuery( + this.dialect.sqlToQuery(this.getSQL()), + this.config.returning, + ) as MySqlDeletePrepare; + } + + override execute: ReturnType['execute'] = (placeholderValues) => { + return this.prepare().execute(placeholderValues); + }; + + private createIterator = (): ReturnType['iterator'] => { + const self = this; + return async function*(placeholderValues) { + yield* self.prepare().iterator(placeholderValues); + }; + }; + + iterator = this.createIterator(); + + $dynamic(): MySqlDeleteDynamic { + return this as any; + } +} diff --git a/drizzle-orm/src/googlesql/query-builders/index.ts b/drizzle-orm/src/googlesql/query-builders/index.ts new file mode 100644 index 0000000000..16f0e1d4d9 --- /dev/null +++ b/drizzle-orm/src/googlesql/query-builders/index.ts @@ -0,0 +1,6 @@ +export * from './delete.ts'; +export * from './insert.ts'; +export * from './query-builder.ts'; +export * from './select.ts'; +export * from './select.types.ts'; +export * from './update.ts'; diff --git a/drizzle-orm/src/googlesql/query-builders/insert.ts b/drizzle-orm/src/googlesql/query-builders/insert.ts new file mode 100644 index 0000000000..f943d03229 --- /dev/null +++ b/drizzle-orm/src/googlesql/query-builders/insert.ts @@ -0,0 +1,330 @@ +import { entityKind, is } from '~/entity.ts'; +import type { MySqlDialect } from '~/mysql-core/dialect.ts'; +import type { + AnyMySqlQueryResultHKT, + MySqlPreparedQueryConfig, + MySqlQueryResultHKT, + MySqlQueryResultKind, + MySqlSession, + PreparedQueryHKTBase, + PreparedQueryKind, +} from '~/mysql-core/session.ts'; +import type { MySqlTable } from '~/mysql-core/table.ts'; +import type { TypedQueryBuilder } from '~/query-builders/query-builder.ts'; +import { QueryPromise } from '~/query-promise.ts'; +import type { RunnableQuery } from '~/runnable-query.ts'; +import type { Placeholder, Query, SQLWrapper } from '~/sql/sql.ts'; +import { Param, SQL, sql } from '~/sql/sql.ts'; +import type { InferModelFromColumns } from '~/table.ts'; +import { Columns, Table } from '~/table.ts'; +import { haveSameKeys, mapUpdateSet } from '~/utils.ts'; +import type { AnyMySqlColumn } from '../columns/common.ts'; +import { QueryBuilder } from './query-builder.ts'; +import type { SelectedFieldsOrdered } from './select.types.ts'; +import type { MySqlUpdateSetSource } from './update.ts'; + +export interface MySqlInsertConfig { + table: TTable; + values: Record[] | MySqlInsertSelectQueryBuilder | SQL; + ignore: boolean; + onConflict?: SQL; + returning?: SelectedFieldsOrdered; + select?: boolean; +} + +export type AnyMySqlInsertConfig = MySqlInsertConfig; + +export type MySqlInsertValue = + & { + [Key in keyof TTable['$inferInsert']]: TTable['$inferInsert'][Key] | SQL | Placeholder; + } + & {}; + +export type MySqlInsertSelectQueryBuilder = TypedQueryBuilder< + { [K in keyof TTable['$inferInsert']]: AnyMySqlColumn | SQL | SQL.Aliased | TTable['$inferInsert'][K] } +>; + +export class MySqlInsertBuilder< + TTable extends MySqlTable, + TQueryResult extends MySqlQueryResultHKT, + TPreparedQueryHKT extends PreparedQueryHKTBase, +> { + static readonly [entityKind]: string = 'MySqlInsertBuilder'; + + private shouldIgnore = false; + + constructor( + private table: TTable, + private session: MySqlSession, + private dialect: MySqlDialect, + ) {} + + ignore(): this { + this.shouldIgnore = true; + return this; + } + + values(value: MySqlInsertValue): MySqlInsertBase; + values(values: MySqlInsertValue[]): MySqlInsertBase; + values( + values: MySqlInsertValue | MySqlInsertValue[], + ): MySqlInsertBase { + values = Array.isArray(values) ? values : [values]; + if (values.length === 0) { + throw new Error('values() must be called with at least one value'); + } + const mappedValues = values.map((entry) => { + const result: Record = {}; + const cols = this.table[Table.Symbol.Columns]; + for (const colKey of Object.keys(entry)) { + const colValue = entry[colKey as keyof typeof entry]; + result[colKey] = is(colValue, SQL) ? colValue : new Param(colValue, cols[colKey]); + } + return result; + }); + + return new MySqlInsertBase(this.table, mappedValues, this.shouldIgnore, this.session, this.dialect); + } + + select( + selectQuery: (qb: QueryBuilder) => MySqlInsertSelectQueryBuilder, + ): MySqlInsertBase; + select(selectQuery: (qb: QueryBuilder) => SQL): MySqlInsertBase; + select(selectQuery: SQL): MySqlInsertBase; + select(selectQuery: MySqlInsertSelectQueryBuilder): MySqlInsertBase; + select( + selectQuery: + | SQL + | MySqlInsertSelectQueryBuilder + | ((qb: QueryBuilder) => MySqlInsertSelectQueryBuilder | SQL), + ): MySqlInsertBase { + const select = typeof selectQuery === 'function' ? selectQuery(new QueryBuilder()) : selectQuery; + + if ( + !is(select, SQL) + && !haveSameKeys(this.table[Columns], select._.selectedFields) + ) { + throw new Error( + 'Insert select error: selected fields are not the same or are in a different order compared to the table definition', + ); + } + + return new MySqlInsertBase(this.table, select, this.shouldIgnore, this.session, this.dialect, true); + } +} + +export type MySqlInsertWithout = + TDynamic extends true ? T + : Omit< + MySqlInsertBase< + T['_']['table'], + T['_']['queryResult'], + T['_']['preparedQueryHKT'], + T['_']['returning'], + TDynamic, + T['_']['excludedMethods'] | '$returning' + >, + T['_']['excludedMethods'] | K + >; + +export type MySqlInsertDynamic = MySqlInsert< + T['_']['table'], + T['_']['queryResult'], + T['_']['preparedQueryHKT'], + T['_']['returning'] +>; + +export type MySqlInsertPrepare< + T extends AnyMySqlInsert, + TReturning extends Record | undefined = undefined, +> = PreparedQueryKind< + T['_']['preparedQueryHKT'], + MySqlPreparedQueryConfig & { + execute: TReturning extends undefined ? MySqlQueryResultKind : TReturning[]; + iterator: never; + }, + true +>; + +export type MySqlInsertOnDuplicateKeyUpdateConfig = { + set: MySqlUpdateSetSource; +}; + +export type MySqlInsert< + TTable extends MySqlTable = MySqlTable, + TQueryResult extends MySqlQueryResultHKT = AnyMySqlQueryResultHKT, + TPreparedQueryHKT extends PreparedQueryHKTBase = PreparedQueryHKTBase, + TReturning extends Record | undefined = Record | undefined, +> = MySqlInsertBase; + +export type MySqlInsertReturning< + T extends AnyMySqlInsert, + TDynamic extends boolean, +> = MySqlInsertBase< + T['_']['table'], + T['_']['queryResult'], + T['_']['preparedQueryHKT'], + InferModelFromColumns>, + TDynamic, + T['_']['excludedMethods'] | '$returning' +>; + +export type AnyMySqlInsert = MySqlInsertBase; + +export interface MySqlInsertBase< + TTable extends MySqlTable, + TQueryResult extends MySqlQueryResultHKT, + TPreparedQueryHKT extends PreparedQueryHKTBase, + TReturning extends Record | undefined = undefined, + TDynamic extends boolean = false, + TExcludedMethods extends string = never, +> extends + QueryPromise : TReturning[]>, + RunnableQuery : TReturning[], 'mysql'>, + SQLWrapper +{ + readonly _: { + readonly dialect: 'mysql'; + readonly table: TTable; + readonly queryResult: TQueryResult; + readonly preparedQueryHKT: TPreparedQueryHKT; + readonly dynamic: TDynamic; + readonly excludedMethods: TExcludedMethods; + readonly returning: TReturning; + readonly result: TReturning extends undefined ? MySqlQueryResultKind : TReturning[]; + }; +} + +export type PrimaryKeyKeys> = { + [K in keyof T]: T[K]['_']['isPrimaryKey'] extends true ? T[K]['_']['isAutoincrement'] extends true ? K + : T[K]['_']['hasRuntimeDefault'] extends true ? T[K]['_']['isPrimaryKey'] extends true ? K : never + : never + : T[K]['_']['hasRuntimeDefault'] extends true ? T[K]['_']['isPrimaryKey'] extends true ? K : never + : never; +}[keyof T]; + +export type GetPrimarySerialOrDefaultKeys> = { + [K in PrimaryKeyKeys]: T[K]; +}; + +export class MySqlInsertBase< + TTable extends MySqlTable, + TQueryResult extends MySqlQueryResultHKT, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + TPreparedQueryHKT extends PreparedQueryHKTBase, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + TReturning extends Record | undefined = undefined, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + TDynamic extends boolean = false, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + TExcludedMethods extends string = never, +> extends QueryPromise : TReturning[]> + implements + RunnableQuery : TReturning[], 'mysql'>, + SQLWrapper +{ + static override readonly [entityKind]: string = 'MySqlInsert'; + + declare protected $table: TTable; + + private config: MySqlInsertConfig; + + constructor( + table: TTable, + values: MySqlInsertConfig['values'], + ignore: boolean, + private session: MySqlSession, + private dialect: MySqlDialect, + select?: boolean, + ) { + super(); + this.config = { table, values: values as any, select, ignore }; + } + + /** + * Adds an `on duplicate key update` clause to the query. + * + * Calling this method will update the row if any unique index conflicts. MySQL will automatically determine the conflict target based on the primary key and unique indexes. + * + * See docs: {@link https://orm.drizzle.team/docs/insert#on-duplicate-key-update} + * + * @param config The `set` clause + * + * @example + * ```ts + * await db.insert(cars) + * .values({ id: 1, brand: 'BMW'}) + * .onDuplicateKeyUpdate({ set: { brand: 'Porsche' }}); + * ``` + * + * While MySQL does not directly support doing nothing on conflict, you can perform a no-op by setting any column's value to itself and achieve the same effect: + * + * ```ts + * import { sql } from 'drizzle-orm'; + * + * await db.insert(cars) + * .values({ id: 1, brand: 'BMW' }) + * .onDuplicateKeyUpdate({ set: { id: sql`id` } }); + * ``` + */ + onDuplicateKeyUpdate( + config: MySqlInsertOnDuplicateKeyUpdateConfig, + ): MySqlInsertWithout { + const setSql = this.dialect.buildUpdateSet(this.config.table, mapUpdateSet(this.config.table, config.set)); + this.config.onConflict = sql`update ${setSql}`; + return this as any; + } + + $returningId(): MySqlInsertWithout< + MySqlInsertReturning, + TDynamic, + '$returningId' + > { + const returning: SelectedFieldsOrdered = []; + for (const [key, value] of Object.entries(this.config.table[Table.Symbol.Columns])) { + if (value.primary) { + returning.push({ field: value, path: [key] }); + } + } + this.config.returning = returning; + return this as any; + } + + /** @internal */ + getSQL(): SQL { + return this.dialect.buildInsertQuery(this.config).sql; + } + + toSQL(): Query { + const { typings: _typings, ...rest } = this.dialect.sqlToQuery(this.getSQL()); + return rest; + } + + prepare(): MySqlInsertPrepare { + const { sql, generatedIds } = this.dialect.buildInsertQuery(this.config); + return this.session.prepareQuery( + this.dialect.sqlToQuery(sql), + undefined, + undefined, + generatedIds, + this.config.returning, + ) as MySqlInsertPrepare; + } + + override execute: ReturnType['execute'] = (placeholderValues) => { + return this.prepare().execute(placeholderValues); + }; + + private createIterator = (): ReturnType['iterator'] => { + const self = this; + return async function*(placeholderValues) { + yield* self.prepare().iterator(placeholderValues); + }; + }; + + iterator = this.createIterator(); + + $dynamic(): MySqlInsertDynamic { + return this as any; + } +} diff --git a/drizzle-orm/src/googlesql/query-builders/query-builder.ts b/drizzle-orm/src/googlesql/query-builders/query-builder.ts new file mode 100644 index 0000000000..5c144d48fb --- /dev/null +++ b/drizzle-orm/src/googlesql/query-builders/query-builder.ts @@ -0,0 +1,116 @@ +import { entityKind, is } from '~/entity.ts'; +import type { MySqlDialectConfig } from '~/mysql-core/dialect.ts'; +import { MySqlDialect } from '~/mysql-core/dialect.ts'; +import type { WithBuilder } from '~/mysql-core/subquery.ts'; +import type { TypedQueryBuilder } from '~/query-builders/query-builder.ts'; +import { SelectionProxyHandler } from '~/selection-proxy.ts'; +import type { ColumnsSelection, SQL } from '~/sql/sql.ts'; +import { WithSubquery } from '~/subquery.ts'; +import { MySqlSelectBuilder } from './select.ts'; +import type { SelectedFields } from './select.types.ts'; + +export class QueryBuilder { + static readonly [entityKind]: string = 'MySqlQueryBuilder'; + + private dialect: MySqlDialect | undefined; + private dialectConfig: MySqlDialectConfig | undefined; + + constructor(dialect?: MySqlDialect | MySqlDialectConfig) { + this.dialect = is(dialect, MySqlDialect) ? dialect : undefined; + this.dialectConfig = is(dialect, MySqlDialect) ? undefined : dialect; + } + + $with: WithBuilder = (alias: string, selection?: ColumnsSelection) => { + const queryBuilder = this; + const as = ( + qb: + | TypedQueryBuilder + | SQL + | ((qb: QueryBuilder) => TypedQueryBuilder | SQL), + ) => { + if (typeof qb === 'function') { + qb = qb(queryBuilder); + } + + return new Proxy( + new WithSubquery( + qb.getSQL(), + selection ?? ('getSelectedFields' in qb ? qb.getSelectedFields() ?? {} : {}) as SelectedFields, + alias, + true, + ), + new SelectionProxyHandler({ alias, sqlAliasedBehavior: 'alias', sqlBehavior: 'error' }), + ) as any; + }; + return { as }; + }; + + with(...queries: WithSubquery[]) { + const self = this; + + function select(): MySqlSelectBuilder; + function select( + fields: TSelection, + ): MySqlSelectBuilder; + function select( + fields?: TSelection, + ): MySqlSelectBuilder { + return new MySqlSelectBuilder({ + fields: fields ?? undefined, + session: undefined, + dialect: self.getDialect(), + withList: queries, + }); + } + + function selectDistinct(): MySqlSelectBuilder; + function selectDistinct( + fields: TSelection, + ): MySqlSelectBuilder; + function selectDistinct( + fields?: TSelection, + ): MySqlSelectBuilder { + return new MySqlSelectBuilder({ + fields: fields ?? undefined, + session: undefined, + dialect: self.getDialect(), + withList: queries, + distinct: true, + }); + } + + return { select, selectDistinct }; + } + + select(): MySqlSelectBuilder; + select(fields: TSelection): MySqlSelectBuilder; + select( + fields?: TSelection, + ): MySqlSelectBuilder { + return new MySqlSelectBuilder({ fields: fields ?? undefined, session: undefined, dialect: this.getDialect() }); + } + + selectDistinct(): MySqlSelectBuilder; + selectDistinct( + fields: TSelection, + ): MySqlSelectBuilder; + selectDistinct( + fields?: TSelection, + ): MySqlSelectBuilder { + return new MySqlSelectBuilder({ + fields: fields ?? undefined, + session: undefined, + dialect: this.getDialect(), + distinct: true, + }); + } + + // Lazy load dialect to avoid circular dependency + private getDialect() { + if (!this.dialect) { + this.dialect = new MySqlDialect(this.dialectConfig); + } + + return this.dialect; + } +} diff --git a/drizzle-orm/src/googlesql/query-builders/query.ts b/drizzle-orm/src/googlesql/query-builders/query.ts new file mode 100644 index 0000000000..16d2945981 --- /dev/null +++ b/drizzle-orm/src/googlesql/query-builders/query.ts @@ -0,0 +1,157 @@ +import { entityKind } from '~/entity.ts'; +import { QueryPromise } from '~/query-promise.ts'; +import { + type BuildQueryResult, + type BuildRelationalQueryResult, + type DBQueryConfig, + mapRelationalRow, + type TableRelationalConfig, + type TablesRelationalConfig, +} from '~/relations.ts'; +import type { Query, QueryWithTypings, SQL } from '~/sql/sql.ts'; +import type { KnownKeysOnly } from '~/utils.ts'; +import type { MySqlDialect } from '../dialect.ts'; +import type { + Mode, + MySqlPreparedQueryConfig, + MySqlSession, + PreparedQueryHKTBase, + PreparedQueryKind, +} from '../session.ts'; +import type { MySqlTable } from '../table.ts'; + +export class RelationalQueryBuilder< + TPreparedQueryHKT extends PreparedQueryHKTBase, + TSchema extends TablesRelationalConfig, + TFields extends TableRelationalConfig, +> { + static readonly [entityKind]: string = 'MySqlRelationalQueryBuilder'; + + constructor( + private fullSchema: Record, + private schema: TSchema, + private tableNamesMap: Record, + private table: MySqlTable, + private tableConfig: TableRelationalConfig, + private dialect: MySqlDialect, + private session: MySqlSession, + private mode: Mode, + ) {} + + findMany>( + config?: KnownKeysOnly>, + ): MySqlRelationalQuery[]> { + return new MySqlRelationalQuery( + this.fullSchema, + this.schema, + this.tableNamesMap, + this.table, + this.tableConfig, + this.dialect, + this.session, + config ? (config as DBQueryConfig<'many', true>) : {}, + 'many', + this.mode, + ); + } + + findFirst, 'limit'>>( + config?: KnownKeysOnly, 'limit'>>, + ): MySqlRelationalQuery | undefined> { + return new MySqlRelationalQuery( + this.fullSchema, + this.schema, + this.tableNamesMap, + this.table, + this.tableConfig, + this.dialect, + this.session, + config ? { ...(config as DBQueryConfig<'many', true> | undefined), limit: 1 } : { limit: 1 }, + 'first', + this.mode, + ); + } +} + +export class MySqlRelationalQuery< + TPreparedQueryHKT extends PreparedQueryHKTBase, + TResult, +> extends QueryPromise { + static override readonly [entityKind]: string = 'MySqlRelationalQuery'; + + declare protected $brand: 'MySqlRelationalQuery'; + + constructor( + private fullSchema: Record, + private schema: TablesRelationalConfig, + private tableNamesMap: Record, + private table: MySqlTable, + private tableConfig: TableRelationalConfig, + private dialect: MySqlDialect, + private session: MySqlSession, + private config: DBQueryConfig<'many', true> | true, + private queryMode: 'many' | 'first', + private mode?: Mode, + ) { + super(); + } + + prepare() { + const { query, builtQuery } = this._toSQL(); + return this.session.prepareQuery( + builtQuery, + undefined, + (rawRows) => { + const rows = rawRows.map((row) => mapRelationalRow(this.schema, this.tableConfig, row, query.selection)); + if (this.queryMode === 'first') { + return rows[0] as TResult; + } + return rows as TResult; + }, + ) as PreparedQueryKind; + } + + private _getQuery() { + const query = this.mode === 'planetscale' + ? this.dialect.buildRelationalQueryWithoutLateralSubqueries({ + fullSchema: this.fullSchema, + schema: this.schema, + tableNamesMap: this.tableNamesMap, + table: this.table, + tableConfig: this.tableConfig, + queryConfig: this.config, + tableAlias: this.tableConfig.tsName, + }) + : this.dialect.buildRelationalQuery({ + fullSchema: this.fullSchema, + schema: this.schema, + tableNamesMap: this.tableNamesMap, + table: this.table, + tableConfig: this.tableConfig, + queryConfig: this.config, + tableAlias: this.tableConfig.tsName, + }); + return query; + } + + private _toSQL(): { query: BuildRelationalQueryResult; builtQuery: QueryWithTypings } { + const query = this._getQuery(); + + const builtQuery = this.dialect.sqlToQuery(query.sql as SQL); + + return { builtQuery, query }; + } + + /** @internal */ + getSQL(): SQL { + return this._getQuery().sql as SQL; + } + + toSQL(): Query { + return this._toSQL().builtQuery; + } + + override execute(): Promise { + return this.prepare().execute(); + } +} diff --git a/drizzle-orm/src/googlesql/query-builders/select.ts b/drizzle-orm/src/googlesql/query-builders/select.ts new file mode 100644 index 0000000000..821199ab43 --- /dev/null +++ b/drizzle-orm/src/googlesql/query-builders/select.ts @@ -0,0 +1,1290 @@ +import { entityKind, is } from '~/entity.ts'; +import type { MySqlColumn } from '~/mysql-core/columns/index.ts'; +import type { MySqlDialect } from '~/mysql-core/dialect.ts'; +import type { MySqlPreparedQueryConfig, MySqlSession, PreparedQueryHKTBase } from '~/mysql-core/session.ts'; +import type { SubqueryWithSelection } from '~/mysql-core/subquery.ts'; +import { MySqlTable } from '~/mysql-core/table.ts'; +import { TypedQueryBuilder } from '~/query-builders/query-builder.ts'; +import type { + BuildSubquerySelection, + GetSelectTableName, + GetSelectTableSelection, + JoinNullability, + JoinType, + SelectMode, + SelectResult, + SetOperator, +} from '~/query-builders/select.types.ts'; +import { QueryPromise } from '~/query-promise.ts'; +import { SelectionProxyHandler } from '~/selection-proxy.ts'; +import type { ColumnsSelection, Placeholder, Query } from '~/sql/sql.ts'; +import { SQL, View } from '~/sql/sql.ts'; +import { Subquery } from '~/subquery.ts'; +import { Table } from '~/table.ts'; +import type { ValueOrArray } from '~/utils.ts'; +import { applyMixins, getTableColumns, getTableLikeName, haveSameKeys, orderSelectedFields } from '~/utils.ts'; +import { ViewBaseConfig } from '~/view-common.ts'; +import type { IndexBuilder } from '../indexes.ts'; +import { convertIndexToString, toArray } from '../utils.ts'; +import { MySqlViewBase } from '../view-base.ts'; +import type { + AnyMySqlSelect, + CreateMySqlSelectFromBuilderMode, + GetMySqlSetOperators, + LockConfig, + LockStrength, + MySqlCreateSetOperatorFn, + MySqlJoinFn, + MySqlSelectConfig, + MySqlSelectDynamic, + MySqlSelectHKT, + MySqlSelectHKTBase, + MySqlSelectPrepare, + MySqlSelectWithout, + MySqlSetOperatorExcludedMethods, + MySqlSetOperatorWithResult, + SelectedFields, + SetOperatorRightSelect, +} from './select.types.ts'; + +export type IndexForHint = IndexBuilder | string; + +export type IndexConfig = { + useIndex?: IndexForHint | IndexForHint[]; + forceIndex?: IndexForHint | IndexForHint[]; + ignoreIndex?: IndexForHint | IndexForHint[]; +}; + +export class MySqlSelectBuilder< + TSelection extends SelectedFields | undefined, + TPreparedQueryHKT extends PreparedQueryHKTBase, + TBuilderMode extends 'db' | 'qb' = 'db', +> { + static readonly [entityKind]: string = 'MySqlSelectBuilder'; + + private fields: TSelection; + private session: MySqlSession | undefined; + private dialect: MySqlDialect; + private withList: Subquery[] = []; + private distinct: boolean | undefined; + + constructor( + config: { + fields: TSelection; + session: MySqlSession | undefined; + dialect: MySqlDialect; + withList?: Subquery[]; + distinct?: boolean; + }, + ) { + this.fields = config.fields; + this.session = config.session; + this.dialect = config.dialect; + if (config.withList) { + this.withList = config.withList; + } + this.distinct = config.distinct; + } + + from( + source: TFrom, + onIndex?: TFrom extends MySqlTable ? IndexConfig + : 'Index hint configuration is allowed only for MySqlTable and not for subqueries or views', + ): CreateMySqlSelectFromBuilderMode< + TBuilderMode, + GetSelectTableName, + TSelection extends undefined ? GetSelectTableSelection : TSelection, + TSelection extends undefined ? 'single' : 'partial', + TPreparedQueryHKT + > { + const isPartialSelect = !!this.fields; + + let fields: SelectedFields; + if (this.fields) { + fields = this.fields; + } else if (is(source, Subquery)) { + // This is required to use the proxy handler to get the correct field values from the subquery + fields = Object.fromEntries( + Object.keys(source._.selectedFields).map(( + key, + ) => [key, source[key as unknown as keyof typeof source] as unknown as SelectedFields[string]]), + ); + } else if (is(source, MySqlViewBase)) { + fields = source[ViewBaseConfig].selectedFields as SelectedFields; + } else if (is(source, SQL)) { + fields = {}; + } else { + fields = getTableColumns(source); + } + + let useIndex: string[] = []; + let forceIndex: string[] = []; + let ignoreIndex: string[] = []; + if (is(source, MySqlTable) && onIndex && typeof onIndex !== 'string') { + if (onIndex.useIndex) { + useIndex = convertIndexToString(toArray(onIndex.useIndex)); + } + if (onIndex.forceIndex) { + forceIndex = convertIndexToString(toArray(onIndex.forceIndex)); + } + if (onIndex.ignoreIndex) { + ignoreIndex = convertIndexToString(toArray(onIndex.ignoreIndex)); + } + } + + return new MySqlSelectBase( + { + table: source, + fields, + isPartialSelect, + session: this.session, + dialect: this.dialect, + withList: this.withList, + distinct: this.distinct, + useIndex, + forceIndex, + ignoreIndex, + }, + ) as any; + } +} + +export abstract class MySqlSelectQueryBuilderBase< + THKT extends MySqlSelectHKTBase, + TTableName extends string | undefined, + TSelection extends ColumnsSelection, + TSelectMode extends SelectMode, + TPreparedQueryHKT extends PreparedQueryHKTBase, + TNullabilityMap extends Record = TTableName extends string ? Record + : {}, + TDynamic extends boolean = false, + TExcludedMethods extends string = never, + TResult extends any[] = SelectResult[], + TSelectedFields extends ColumnsSelection = BuildSubquerySelection, +> extends TypedQueryBuilder { + static override readonly [entityKind]: string = 'MySqlSelectQueryBuilder'; + + override readonly _: { + readonly hkt: THKT; + readonly tableName: TTableName; + readonly selection: TSelection; + readonly selectMode: TSelectMode; + readonly preparedQueryHKT: TPreparedQueryHKT; + readonly nullabilityMap: TNullabilityMap; + readonly dynamic: TDynamic; + readonly excludedMethods: TExcludedMethods; + readonly result: TResult; + readonly selectedFields: TSelectedFields; + }; + + protected config: MySqlSelectConfig; + protected joinsNotNullableMap: Record; + private tableName: string | undefined; + private isPartialSelect: boolean; + /** @internal */ + readonly session: MySqlSession | undefined; + protected dialect: MySqlDialect; + + constructor( + { table, fields, isPartialSelect, session, dialect, withList, distinct, useIndex, forceIndex, ignoreIndex }: { + table: MySqlSelectConfig['table']; + fields: MySqlSelectConfig['fields']; + isPartialSelect: boolean; + session: MySqlSession | undefined; + dialect: MySqlDialect; + withList: Subquery[]; + distinct: boolean | undefined; + useIndex?: string[]; + forceIndex?: string[]; + ignoreIndex?: string[]; + }, + ) { + super(); + this.config = { + withList, + table, + fields: { ...fields }, + distinct, + setOperators: [], + useIndex, + forceIndex, + ignoreIndex, + }; + this.isPartialSelect = isPartialSelect; + this.session = session; + this.dialect = dialect; + this._ = { + selectedFields: fields as TSelectedFields, + } as this['_']; + this.tableName = getTableLikeName(table); + this.joinsNotNullableMap = typeof this.tableName === 'string' ? { [this.tableName]: true } : {}; + } + + private createJoin( + joinType: TJoinType, + ): MySqlJoinFn { + return < + TJoinedTable extends MySqlTable | Subquery | MySqlViewBase | SQL, + >( + table: MySqlTable | Subquery | MySqlViewBase | SQL, + on: ((aliases: TSelection) => SQL | undefined) | SQL | undefined, + onIndex?: TJoinedTable extends MySqlTable ? IndexConfig + : 'Index hint configuration is allowed only for MySqlTable and not for subqueries or views', + ) => { + const baseTableName = this.tableName; + const tableName = getTableLikeName(table); + + if (typeof tableName === 'string' && this.config.joins?.some((join) => join.alias === tableName)) { + throw new Error(`Alias "${tableName}" is already used in this query`); + } + + if (!this.isPartialSelect) { + // If this is the first join and this is not a partial select and we're not selecting from raw SQL, "move" the fields from the main table to the nested object + if (Object.keys(this.joinsNotNullableMap).length === 1 && typeof baseTableName === 'string') { + this.config.fields = { + [baseTableName]: this.config.fields, + }; + } + if (typeof tableName === 'string' && !is(table, SQL)) { + const selection = is(table, Subquery) + ? table._.selectedFields + : is(table, View) + ? table[ViewBaseConfig].selectedFields + : table[Table.Symbol.Columns]; + this.config.fields[tableName] = selection; + } + } + + if (typeof on === 'function') { + on = on( + new Proxy( + this.config.fields, + new SelectionProxyHandler({ sqlAliasedBehavior: 'sql', sqlBehavior: 'sql' }), + ) as TSelection, + ); + } + + if (!this.config.joins) { + this.config.joins = []; + } + + let useIndex: string[] = []; + let forceIndex: string[] = []; + let ignoreIndex: string[] = []; + if (is(table, MySqlTable) && onIndex && typeof onIndex !== 'string') { + if (onIndex.useIndex) { + useIndex = convertIndexToString(toArray(onIndex.useIndex)); + } + if (onIndex.forceIndex) { + forceIndex = convertIndexToString(toArray(onIndex.forceIndex)); + } + if (onIndex.ignoreIndex) { + ignoreIndex = convertIndexToString(toArray(onIndex.ignoreIndex)); + } + } + + this.config.joins.push({ on, table, joinType, alias: tableName, useIndex, forceIndex, ignoreIndex }); + + if (typeof tableName === 'string') { + switch (joinType) { + case 'left': { + this.joinsNotNullableMap[tableName] = false; + break; + } + case 'right': { + this.joinsNotNullableMap = Object.fromEntries( + Object.entries(this.joinsNotNullableMap).map(([key]) => [key, false]), + ); + this.joinsNotNullableMap[tableName] = true; + break; + } + case 'inner': { + this.joinsNotNullableMap[tableName] = true; + break; + } + case 'full': { + this.joinsNotNullableMap = Object.fromEntries( + Object.entries(this.joinsNotNullableMap).map(([key]) => [key, false]), + ); + this.joinsNotNullableMap[tableName] = false; + break; + } + } + } + + return this as any; + }; + } + + /** + * Executes a `left join` operation by adding another table to the current query. + * + * Calling this method associates each row of the table with the corresponding row from the joined table, if a match is found. If no matching row exists, it sets all columns of the joined table to null. + * + * See docs: {@link https://orm.drizzle.team/docs/joins#left-join} + * + * @param table the table to join. + * @param on the `on` clause. + * + * @example + * + * ```ts + * // Select all users and their pets + * const usersWithPets: { user: User; pets: Pet | null }[] = await db.select() + * .from(users) + * .leftJoin(pets, eq(users.id, pets.ownerId)) + * + * // Select userId and petId + * const usersIdsAndPetIds: { userId: number; petId: number | null }[] = await db.select({ + * userId: users.id, + * petId: pets.id, + * }) + * .from(users) + * .leftJoin(pets, eq(users.id, pets.ownerId)) + * + * // Select userId and petId with use index hint + * const usersIdsAndPetIds: { userId: number; petId: number | null }[] = await db.select({ + * userId: users.id, + * petId: pets.id, + * }) + * .from(users) + * .leftJoin(pets, eq(users.id, pets.ownerId), { + * useIndex: ['pets_owner_id_index'] + * }) + * ``` + */ + leftJoin = this.createJoin('left'); + + /** + * Executes a `right join` operation by adding another table to the current query. + * + * Calling this method associates each row of the joined table with the corresponding row from the main table, if a match is found. If no matching row exists, it sets all columns of the main table to null. + * + * See docs: {@link https://orm.drizzle.team/docs/joins#right-join} + * + * @param table the table to join. + * @param on the `on` clause. + * + * @example + * + * ```ts + * // Select all users and their pets + * const usersWithPets: { user: User | null; pets: Pet }[] = await db.select() + * .from(users) + * .rightJoin(pets, eq(users.id, pets.ownerId)) + * + * // Select userId and petId + * const usersIdsAndPetIds: { userId: number | null; petId: number }[] = await db.select({ + * userId: users.id, + * petId: pets.id, + * }) + * .from(users) + * .rightJoin(pets, eq(users.id, pets.ownerId)) + * + * // Select userId and petId with use index hint + * const usersIdsAndPetIds: { userId: number; petId: number | null }[] = await db.select({ + * userId: users.id, + * petId: pets.id, + * }) + * .from(users) + * .leftJoin(pets, eq(users.id, pets.ownerId), { + * useIndex: ['pets_owner_id_index'] + * }) + * ``` + */ + rightJoin = this.createJoin('right'); + + /** + * Executes an `inner join` operation, creating a new table by combining rows from two tables that have matching values. + * + * Calling this method retrieves rows that have corresponding entries in both joined tables. Rows without matching entries in either table are excluded, resulting in a table that includes only matching pairs. + * + * See docs: {@link https://orm.drizzle.team/docs/joins#inner-join} + * + * @param table the table to join. + * @param on the `on` clause. + * + * @example + * + * ```ts + * // Select all users and their pets + * const usersWithPets: { user: User; pets: Pet }[] = await db.select() + * .from(users) + * .innerJoin(pets, eq(users.id, pets.ownerId)) + * + * // Select userId and petId + * const usersIdsAndPetIds: { userId: number; petId: number }[] = await db.select({ + * userId: users.id, + * petId: pets.id, + * }) + * .from(users) + * .innerJoin(pets, eq(users.id, pets.ownerId)) + * + * // Select userId and petId with use index hint + * const usersIdsAndPetIds: { userId: number; petId: number | null }[] = await db.select({ + * userId: users.id, + * petId: pets.id, + * }) + * .from(users) + * .leftJoin(pets, eq(users.id, pets.ownerId), { + * useIndex: ['pets_owner_id_index'] + * }) + * ``` + */ + innerJoin = this.createJoin('inner'); + + /** + * Executes a `full join` operation by combining rows from two tables into a new table. + * + * Calling this method retrieves all rows from both main and joined tables, merging rows with matching values and filling in `null` for non-matching columns. + * + * See docs: {@link https://orm.drizzle.team/docs/joins#full-join} + * + * @param table the table to join. + * @param on the `on` clause. + * + * @example + * + * ```ts + * // Select all users and their pets + * const usersWithPets: { user: User | null; pets: Pet | null }[] = await db.select() + * .from(users) + * .fullJoin(pets, eq(users.id, pets.ownerId)) + * + * // Select userId and petId + * const usersIdsAndPetIds: { userId: number | null; petId: number | null }[] = await db.select({ + * userId: users.id, + * petId: pets.id, + * }) + * .from(users) + * .fullJoin(pets, eq(users.id, pets.ownerId)) + * + * // Select userId and petId with use index hint + * const usersIdsAndPetIds: { userId: number; petId: number | null }[] = await db.select({ + * userId: users.id, + * petId: pets.id, + * }) + * .from(users) + * .leftJoin(pets, eq(users.id, pets.ownerId), { + * useIndex: ['pets_owner_id_index'] + * }) + * ``` + */ + fullJoin = this.createJoin('full'); + + private createSetOperator( + type: SetOperator, + isAll: boolean, + ): >( + rightSelection: + | ((setOperators: GetMySqlSetOperators) => SetOperatorRightSelect) + | SetOperatorRightSelect, + ) => MySqlSelectWithout< + this, + TDynamic, + MySqlSetOperatorExcludedMethods, + true + > { + return (rightSelection) => { + const rightSelect = (typeof rightSelection === 'function' + ? rightSelection(getMySqlSetOperators()) + : rightSelection) as TypedQueryBuilder< + any, + TResult + >; + + if (!haveSameKeys(this.getSelectedFields(), rightSelect.getSelectedFields())) { + throw new Error( + 'Set operator error (union / intersect / except): selected fields are not the same or are in a different order', + ); + } + + this.config.setOperators.push({ type, isAll, rightSelect }); + return this as any; + }; + } + + /** + * Adds `union` set operator to the query. + * + * Calling this method will combine the result sets of the `select` statements and remove any duplicate rows that appear across them. + * + * See docs: {@link https://orm.drizzle.team/docs/set-operations#union} + * + * @example + * + * ```ts + * // Select all unique names from customers and users tables + * await db.select({ name: users.name }) + * .from(users) + * .union( + * db.select({ name: customers.name }).from(customers) + * ); + * // or + * import { union } from 'drizzle-orm/mysql-core' + * + * await union( + * db.select({ name: users.name }).from(users), + * db.select({ name: customers.name }).from(customers) + * ); + * ``` + */ + union = this.createSetOperator('union', false); + + /** + * Adds `union all` set operator to the query. + * + * Calling this method will combine the result-set of the `select` statements and keep all duplicate rows that appear across them. + * + * See docs: {@link https://orm.drizzle.team/docs/set-operations#union-all} + * + * @example + * + * ```ts + * // Select all transaction ids from both online and in-store sales + * await db.select({ transaction: onlineSales.transactionId }) + * .from(onlineSales) + * .unionAll( + * db.select({ transaction: inStoreSales.transactionId }).from(inStoreSales) + * ); + * // or + * import { unionAll } from 'drizzle-orm/mysql-core' + * + * await unionAll( + * db.select({ transaction: onlineSales.transactionId }).from(onlineSales), + * db.select({ transaction: inStoreSales.transactionId }).from(inStoreSales) + * ); + * ``` + */ + unionAll = this.createSetOperator('union', true); + + /** + * Adds `intersect` set operator to the query. + * + * Calling this method will retain only the rows that are present in both result sets and eliminate duplicates. + * + * See docs: {@link https://orm.drizzle.team/docs/set-operations#intersect} + * + * @example + * + * ```ts + * // Select course names that are offered in both departments A and B + * await db.select({ courseName: depA.courseName }) + * .from(depA) + * .intersect( + * db.select({ courseName: depB.courseName }).from(depB) + * ); + * // or + * import { intersect } from 'drizzle-orm/mysql-core' + * + * await intersect( + * db.select({ courseName: depA.courseName }).from(depA), + * db.select({ courseName: depB.courseName }).from(depB) + * ); + * ``` + */ + intersect = this.createSetOperator('intersect', false); + + /** + * Adds `intersect all` set operator to the query. + * + * Calling this method will retain only the rows that are present in both result sets including all duplicates. + * + * See docs: {@link https://orm.drizzle.team/docs/set-operations#intersect-all} + * + * @example + * + * ```ts + * // Select all products and quantities that are ordered by both regular and VIP customers + * await db.select({ + * productId: regularCustomerOrders.productId, + * quantityOrdered: regularCustomerOrders.quantityOrdered + * }) + * .from(regularCustomerOrders) + * .intersectAll( + * db.select({ + * productId: vipCustomerOrders.productId, + * quantityOrdered: vipCustomerOrders.quantityOrdered + * }) + * .from(vipCustomerOrders) + * ); + * // or + * import { intersectAll } from 'drizzle-orm/mysql-core' + * + * await intersectAll( + * db.select({ + * productId: regularCustomerOrders.productId, + * quantityOrdered: regularCustomerOrders.quantityOrdered + * }) + * .from(regularCustomerOrders), + * db.select({ + * productId: vipCustomerOrders.productId, + * quantityOrdered: vipCustomerOrders.quantityOrdered + * }) + * .from(vipCustomerOrders) + * ); + * ``` + */ + intersectAll = this.createSetOperator('intersect', true); + + /** + * Adds `except` set operator to the query. + * + * Calling this method will retrieve all unique rows from the left query, except for the rows that are present in the result set of the right query. + * + * See docs: {@link https://orm.drizzle.team/docs/set-operations#except} + * + * @example + * + * ```ts + * // Select all courses offered in department A but not in department B + * await db.select({ courseName: depA.courseName }) + * .from(depA) + * .except( + * db.select({ courseName: depB.courseName }).from(depB) + * ); + * // or + * import { except } from 'drizzle-orm/mysql-core' + * + * await except( + * db.select({ courseName: depA.courseName }).from(depA), + * db.select({ courseName: depB.courseName }).from(depB) + * ); + * ``` + */ + except = this.createSetOperator('except', false); + + /** + * Adds `except all` set operator to the query. + * + * Calling this method will retrieve all rows from the left query, except for the rows that are present in the result set of the right query. + * + * See docs: {@link https://orm.drizzle.team/docs/set-operations#except-all} + * + * @example + * + * ```ts + * // Select all products that are ordered by regular customers but not by VIP customers + * await db.select({ + * productId: regularCustomerOrders.productId, + * quantityOrdered: regularCustomerOrders.quantityOrdered, + * }) + * .from(regularCustomerOrders) + * .exceptAll( + * db.select({ + * productId: vipCustomerOrders.productId, + * quantityOrdered: vipCustomerOrders.quantityOrdered, + * }) + * .from(vipCustomerOrders) + * ); + * // or + * import { exceptAll } from 'drizzle-orm/mysql-core' + * + * await exceptAll( + * db.select({ + * productId: regularCustomerOrders.productId, + * quantityOrdered: regularCustomerOrders.quantityOrdered + * }) + * .from(regularCustomerOrders), + * db.select({ + * productId: vipCustomerOrders.productId, + * quantityOrdered: vipCustomerOrders.quantityOrdered + * }) + * .from(vipCustomerOrders) + * ); + * ``` + */ + exceptAll = this.createSetOperator('except', true); + + /** @internal */ + addSetOperators(setOperators: MySqlSelectConfig['setOperators']): MySqlSelectWithout< + this, + TDynamic, + MySqlSetOperatorExcludedMethods, + true + > { + this.config.setOperators.push(...setOperators); + return this as any; + } + + /** + * Adds a `where` clause to the query. + * + * Calling this method will select only those rows that fulfill a specified condition. + * + * See docs: {@link https://orm.drizzle.team/docs/select#filtering} + * + * @param where the `where` clause. + * + * @example + * You can use conditional operators and `sql function` to filter the rows to be selected. + * + * ```ts + * // Select all cars with green color + * await db.select().from(cars).where(eq(cars.color, 'green')); + * // or + * await db.select().from(cars).where(sql`${cars.color} = 'green'`) + * ``` + * + * You can logically combine conditional operators with `and()` and `or()` operators: + * + * ```ts + * // Select all BMW cars with a green color + * await db.select().from(cars).where(and(eq(cars.color, 'green'), eq(cars.brand, 'BMW'))); + * + * // Select all cars with the green or blue color + * await db.select().from(cars).where(or(eq(cars.color, 'green'), eq(cars.color, 'blue'))); + * ``` + */ + where( + where: ((aliases: this['_']['selection']) => SQL | undefined) | SQL | undefined, + ): MySqlSelectWithout { + if (typeof where === 'function') { + where = where( + new Proxy( + this.config.fields, + new SelectionProxyHandler({ sqlAliasedBehavior: 'sql', sqlBehavior: 'sql' }), + ) as TSelection, + ); + } + this.config.where = where; + return this as any; + } + + /** + * Adds a `having` clause to the query. + * + * Calling this method will select only those rows that fulfill a specified condition. It is typically used with aggregate functions to filter the aggregated data based on a specified condition. + * + * See docs: {@link https://orm.drizzle.team/docs/select#aggregations} + * + * @param having the `having` clause. + * + * @example + * + * ```ts + * // Select all brands with more than one car + * await db.select({ + * brand: cars.brand, + * count: sql`cast(count(${cars.id}) as int)`, + * }) + * .from(cars) + * .groupBy(cars.brand) + * .having(({ count }) => gt(count, 1)); + * ``` + */ + having( + having: ((aliases: this['_']['selection']) => SQL | undefined) | SQL | undefined, + ): MySqlSelectWithout { + if (typeof having === 'function') { + having = having( + new Proxy( + this.config.fields, + new SelectionProxyHandler({ sqlAliasedBehavior: 'sql', sqlBehavior: 'sql' }), + ) as TSelection, + ); + } + this.config.having = having; + return this as any; + } + + /** + * Adds a `group by` clause to the query. + * + * Calling this method will group rows that have the same values into summary rows, often used for aggregation purposes. + * + * See docs: {@link https://orm.drizzle.team/docs/select#aggregations} + * + * @example + * + * ```ts + * // Group and count people by their last names + * await db.select({ + * lastName: people.lastName, + * count: sql`cast(count(*) as int)` + * }) + * .from(people) + * .groupBy(people.lastName); + * ``` + */ + groupBy( + builder: (aliases: this['_']['selection']) => ValueOrArray, + ): MySqlSelectWithout; + groupBy(...columns: (MySqlColumn | SQL | SQL.Aliased)[]): MySqlSelectWithout; + groupBy( + ...columns: + | [(aliases: this['_']['selection']) => ValueOrArray] + | (MySqlColumn | SQL | SQL.Aliased)[] + ): MySqlSelectWithout { + if (typeof columns[0] === 'function') { + const groupBy = columns[0]( + new Proxy( + this.config.fields, + new SelectionProxyHandler({ sqlAliasedBehavior: 'alias', sqlBehavior: 'sql' }), + ) as TSelection, + ); + this.config.groupBy = Array.isArray(groupBy) ? groupBy : [groupBy]; + } else { + this.config.groupBy = columns as (MySqlColumn | SQL | SQL.Aliased)[]; + } + return this as any; + } + + /** + * Adds an `order by` clause to the query. + * + * Calling this method will sort the result-set in ascending or descending order. By default, the sort order is ascending. + * + * See docs: {@link https://orm.drizzle.team/docs/select#order-by} + * + * @example + * + * ``` + * // Select cars ordered by year + * await db.select().from(cars).orderBy(cars.year); + * ``` + * + * You can specify whether results are in ascending or descending order with the `asc()` and `desc()` operators. + * + * ```ts + * // Select cars ordered by year in descending order + * await db.select().from(cars).orderBy(desc(cars.year)); + * + * // Select cars ordered by year and price + * await db.select().from(cars).orderBy(asc(cars.year), desc(cars.price)); + * ``` + */ + orderBy( + builder: (aliases: this['_']['selection']) => ValueOrArray, + ): MySqlSelectWithout; + orderBy(...columns: (MySqlColumn | SQL | SQL.Aliased)[]): MySqlSelectWithout; + orderBy( + ...columns: + | [(aliases: this['_']['selection']) => ValueOrArray] + | (MySqlColumn | SQL | SQL.Aliased)[] + ): MySqlSelectWithout { + if (typeof columns[0] === 'function') { + const orderBy = columns[0]( + new Proxy( + this.config.fields, + new SelectionProxyHandler({ sqlAliasedBehavior: 'alias', sqlBehavior: 'sql' }), + ) as TSelection, + ); + + const orderByArray = Array.isArray(orderBy) ? orderBy : [orderBy]; + + if (this.config.setOperators.length > 0) { + this.config.setOperators.at(-1)!.orderBy = orderByArray; + } else { + this.config.orderBy = orderByArray; + } + } else { + const orderByArray = columns as (MySqlColumn | SQL | SQL.Aliased)[]; + + if (this.config.setOperators.length > 0) { + this.config.setOperators.at(-1)!.orderBy = orderByArray; + } else { + this.config.orderBy = orderByArray; + } + } + return this as any; + } + + /** + * Adds a `limit` clause to the query. + * + * Calling this method will set the maximum number of rows that will be returned by this query. + * + * See docs: {@link https://orm.drizzle.team/docs/select#limit--offset} + * + * @param limit the `limit` clause. + * + * @example + * + * ```ts + * // Get the first 10 people from this query. + * await db.select().from(people).limit(10); + * ``` + */ + limit(limit: number | Placeholder): MySqlSelectWithout { + if (this.config.setOperators.length > 0) { + this.config.setOperators.at(-1)!.limit = limit; + } else { + this.config.limit = limit; + } + return this as any; + } + + /** + * Adds an `offset` clause to the query. + * + * Calling this method will skip a number of rows when returning results from this query. + * + * See docs: {@link https://orm.drizzle.team/docs/select#limit--offset} + * + * @param offset the `offset` clause. + * + * @example + * + * ```ts + * // Get the 10th-20th people from this query. + * await db.select().from(people).offset(10).limit(10); + * ``` + */ + offset(offset: number | Placeholder): MySqlSelectWithout { + if (this.config.setOperators.length > 0) { + this.config.setOperators.at(-1)!.offset = offset; + } else { + this.config.offset = offset; + } + return this as any; + } + + /** + * Adds a `for` clause to the query. + * + * Calling this method will specify a lock strength for this query that controls how strictly it acquires exclusive access to the rows being queried. + * + * See docs: {@link https://dev.mysql.com/doc/refman/8.0/en/innodb-locking-reads.html} + * + * @param strength the lock strength. + * @param config the lock configuration. + */ + for(strength: LockStrength, config: LockConfig = {}): MySqlSelectWithout { + this.config.lockingClause = { strength, config }; + return this as any; + } + + /** @internal */ + getSQL(): SQL { + return this.dialect.buildSelectQuery(this.config); + } + + toSQL(): Query { + const { typings: _typings, ...rest } = this.dialect.sqlToQuery(this.getSQL()); + return rest; + } + + as( + alias: TAlias, + ): SubqueryWithSelection { + return new Proxy( + new Subquery(this.getSQL(), this.config.fields, alias), + new SelectionProxyHandler({ alias, sqlAliasedBehavior: 'alias', sqlBehavior: 'error' }), + ) as SubqueryWithSelection; + } + + /** @internal */ + override getSelectedFields(): this['_']['selectedFields'] { + return new Proxy( + this.config.fields, + new SelectionProxyHandler({ alias: this.tableName, sqlAliasedBehavior: 'alias', sqlBehavior: 'error' }), + ) as this['_']['selectedFields']; + } + + $dynamic(): MySqlSelectDynamic { + return this as any; + } +} + +export interface MySqlSelectBase< + TTableName extends string | undefined, + TSelection extends ColumnsSelection, + TSelectMode extends SelectMode, + TPreparedQueryHKT extends PreparedQueryHKTBase, + TNullabilityMap extends Record = TTableName extends string ? Record + : {}, + TDynamic extends boolean = false, + TExcludedMethods extends string = never, + TResult extends any[] = SelectResult[], + TSelectedFields extends ColumnsSelection = BuildSubquerySelection, +> extends + MySqlSelectQueryBuilderBase< + MySqlSelectHKT, + TTableName, + TSelection, + TSelectMode, + TPreparedQueryHKT, + TNullabilityMap, + TDynamic, + TExcludedMethods, + TResult, + TSelectedFields + >, + QueryPromise +{} + +export class MySqlSelectBase< + TTableName extends string | undefined, + TSelection, + TSelectMode extends SelectMode, + TPreparedQueryHKT extends PreparedQueryHKTBase, + TNullabilityMap extends Record = TTableName extends string ? Record + : {}, + TDynamic extends boolean = false, + TExcludedMethods extends string = never, + TResult = SelectResult[], + TSelectedFields = BuildSubquerySelection, +> extends MySqlSelectQueryBuilderBase< + MySqlSelectHKT, + TTableName, + TSelection, + TSelectMode, + TPreparedQueryHKT, + TNullabilityMap, + TDynamic, + TExcludedMethods, + TResult, + TSelectedFields +> { + static override readonly [entityKind]: string = 'MySqlSelect'; + + prepare(): MySqlSelectPrepare { + if (!this.session) { + throw new Error('Cannot execute a query on a query builder. Please use a database instance instead.'); + } + const fieldsList = orderSelectedFields(this.config.fields); + const query = this.session.prepareQuery< + MySqlPreparedQueryConfig & { execute: SelectResult[] }, + TPreparedQueryHKT + >(this.dialect.sqlToQuery(this.getSQL()), fieldsList); + query.joinsNotNullableMap = this.joinsNotNullableMap; + return query as MySqlSelectPrepare; + } + + execute = ((placeholderValues) => { + return this.prepare().execute(placeholderValues); + }) as ReturnType['execute']; + + private createIterator = (): ReturnType['iterator'] => { + const self = this; + return async function*(placeholderValues) { + yield* self.prepare().iterator(placeholderValues); + }; + }; + + iterator = this.createIterator(); +} + +applyMixins(MySqlSelectBase, [QueryPromise]); + +function createSetOperator(type: SetOperator, isAll: boolean): MySqlCreateSetOperatorFn { + return (leftSelect, rightSelect, ...restSelects) => { + const setOperators = [rightSelect, ...restSelects].map((select) => ({ + type, + isAll, + rightSelect: select as AnyMySqlSelect, + })); + + for (const setOperator of setOperators) { + if (!haveSameKeys((leftSelect as any).getSelectedFields(), setOperator.rightSelect.getSelectedFields())) { + throw new Error( + 'Set operator error (union / intersect / except): selected fields are not the same or are in a different order', + ); + } + } + + return (leftSelect as AnyMySqlSelect).addSetOperators(setOperators) as any; + }; +} + +const getMySqlSetOperators = () => ({ + union, + unionAll, + intersect, + intersectAll, + except, + exceptAll, +}); + +/** + * Adds `union` set operator to the query. + * + * Calling this method will combine the result sets of the `select` statements and remove any duplicate rows that appear across them. + * + * See docs: {@link https://orm.drizzle.team/docs/set-operations#union} + * + * @example + * + * ```ts + * // Select all unique names from customers and users tables + * import { union } from 'drizzle-orm/mysql-core' + * + * await union( + * db.select({ name: users.name }).from(users), + * db.select({ name: customers.name }).from(customers) + * ); + * // or + * await db.select({ name: users.name }) + * .from(users) + * .union( + * db.select({ name: customers.name }).from(customers) + * ); + * ``` + */ +export const union = createSetOperator('union', false); + +/** + * Adds `union all` set operator to the query. + * + * Calling this method will combine the result-set of the `select` statements and keep all duplicate rows that appear across them. + * + * See docs: {@link https://orm.drizzle.team/docs/set-operations#union-all} + * + * @example + * + * ```ts + * // Select all transaction ids from both online and in-store sales + * import { unionAll } from 'drizzle-orm/mysql-core' + * + * await unionAll( + * db.select({ transaction: onlineSales.transactionId }).from(onlineSales), + * db.select({ transaction: inStoreSales.transactionId }).from(inStoreSales) + * ); + * // or + * await db.select({ transaction: onlineSales.transactionId }) + * .from(onlineSales) + * .unionAll( + * db.select({ transaction: inStoreSales.transactionId }).from(inStoreSales) + * ); + * ``` + */ +export const unionAll = createSetOperator('union', true); + +/** + * Adds `intersect` set operator to the query. + * + * Calling this method will retain only the rows that are present in both result sets and eliminate duplicates. + * + * See docs: {@link https://orm.drizzle.team/docs/set-operations#intersect} + * + * @example + * + * ```ts + * // Select course names that are offered in both departments A and B + * import { intersect } from 'drizzle-orm/mysql-core' + * + * await intersect( + * db.select({ courseName: depA.courseName }).from(depA), + * db.select({ courseName: depB.courseName }).from(depB) + * ); + * // or + * await db.select({ courseName: depA.courseName }) + * .from(depA) + * .intersect( + * db.select({ courseName: depB.courseName }).from(depB) + * ); + * ``` + */ +export const intersect = createSetOperator('intersect', false); + +/** + * Adds `intersect all` set operator to the query. + * + * Calling this method will retain only the rows that are present in both result sets including all duplicates. + * + * See docs: {@link https://orm.drizzle.team/docs/set-operations#intersect-all} + * + * @example + * + * ```ts + * // Select all products and quantities that are ordered by both regular and VIP customers + * import { intersectAll } from 'drizzle-orm/mysql-core' + * + * await intersectAll( + * db.select({ + * productId: regularCustomerOrders.productId, + * quantityOrdered: regularCustomerOrders.quantityOrdered + * }) + * .from(regularCustomerOrders), + * db.select({ + * productId: vipCustomerOrders.productId, + * quantityOrdered: vipCustomerOrders.quantityOrdered + * }) + * .from(vipCustomerOrders) + * ); + * // or + * await db.select({ + * productId: regularCustomerOrders.productId, + * quantityOrdered: regularCustomerOrders.quantityOrdered + * }) + * .from(regularCustomerOrders) + * .intersectAll( + * db.select({ + * productId: vipCustomerOrders.productId, + * quantityOrdered: vipCustomerOrders.quantityOrdered + * }) + * .from(vipCustomerOrders) + * ); + * ``` + */ +export const intersectAll = createSetOperator('intersect', true); + +/** + * Adds `except` set operator to the query. + * + * Calling this method will retrieve all unique rows from the left query, except for the rows that are present in the result set of the right query. + * + * See docs: {@link https://orm.drizzle.team/docs/set-operations#except} + * + * @example + * + * ```ts + * // Select all courses offered in department A but not in department B + * import { except } from 'drizzle-orm/mysql-core' + * + * await except( + * db.select({ courseName: depA.courseName }).from(depA), + * db.select({ courseName: depB.courseName }).from(depB) + * ); + * // or + * await db.select({ courseName: depA.courseName }) + * .from(depA) + * .except( + * db.select({ courseName: depB.courseName }).from(depB) + * ); + * ``` + */ +export const except = createSetOperator('except', false); + +/** + * Adds `except all` set operator to the query. + * + * Calling this method will retrieve all rows from the left query, except for the rows that are present in the result set of the right query. + * + * See docs: {@link https://orm.drizzle.team/docs/set-operations#except-all} + * + * @example + * + * ```ts + * // Select all products that are ordered by regular customers but not by VIP customers + * import { exceptAll } from 'drizzle-orm/mysql-core' + * + * await exceptAll( + * db.select({ + * productId: regularCustomerOrders.productId, + * quantityOrdered: regularCustomerOrders.quantityOrdered + * }) + * .from(regularCustomerOrders), + * db.select({ + * productId: vipCustomerOrders.productId, + * quantityOrdered: vipCustomerOrders.quantityOrdered + * }) + * .from(vipCustomerOrders) + * ); + * // or + * await db.select({ + * productId: regularCustomerOrders.productId, + * quantityOrdered: regularCustomerOrders.quantityOrdered, + * }) + * .from(regularCustomerOrders) + * .exceptAll( + * db.select({ + * productId: vipCustomerOrders.productId, + * quantityOrdered: vipCustomerOrders.quantityOrdered, + * }) + * .from(vipCustomerOrders) + * ); + * ``` + */ +export const exceptAll = createSetOperator('except', true); diff --git a/drizzle-orm/src/googlesql/query-builders/select.types.ts b/drizzle-orm/src/googlesql/query-builders/select.types.ts new file mode 100644 index 0000000000..4b0f97d3a1 --- /dev/null +++ b/drizzle-orm/src/googlesql/query-builders/select.types.ts @@ -0,0 +1,440 @@ +import type { MySqlColumn } from '~/mysql-core/columns/index.ts'; +import type { MySqlTable, MySqlTableWithColumns } from '~/mysql-core/table.ts'; +import type { + SelectedFields as SelectedFieldsBase, + SelectedFieldsFlat as SelectedFieldsFlatBase, + SelectedFieldsOrdered as SelectedFieldsOrderedBase, +} from '~/operations.ts'; +import type { TypedQueryBuilder } from '~/query-builders/query-builder.ts'; +import type { + AppendToNullabilityMap, + AppendToResult, + BuildSubquerySelection, + GetSelectTableName, + JoinNullability, + JoinType, + MapColumnsToTableAlias, + SelectMode, + SelectResult, + SetOperator, +} from '~/query-builders/select.types.ts'; +import type { ColumnsSelection, Placeholder, SQL, View } from '~/sql/sql.ts'; +import type { Subquery } from '~/subquery.ts'; +import type { Table, UpdateTableConfig } from '~/table.ts'; +import type { Assume, ValidateShape } from '~/utils.ts'; +import type { MySqlPreparedQueryConfig, PreparedQueryHKTBase, PreparedQueryKind } from '../session.ts'; +import type { MySqlViewBase } from '../view-base.ts'; +import type { MySqlViewWithSelection } from '../view.ts'; +import type { IndexConfig, MySqlSelectBase, MySqlSelectQueryBuilderBase } from './select.ts'; + +export interface MySqlSelectJoinConfig { + on: SQL | undefined; + table: MySqlTable | Subquery | MySqlViewBase | SQL; + alias: string | undefined; + joinType: JoinType; + lateral?: boolean; + useIndex?: string[]; + forceIndex?: string[]; + ignoreIndex?: string[]; +} + +export type BuildAliasTable = TTable extends Table + ? MySqlTableWithColumns< + UpdateTableConfig; + }> + > + : TTable extends View ? MySqlViewWithSelection< + TAlias, + TTable['_']['existing'], + MapColumnsToTableAlias + > + : never; + +export interface MySqlSelectConfig { + withList?: Subquery[]; + fields: Record; + fieldsFlat?: SelectedFieldsOrdered; + where?: SQL; + having?: SQL; + table: MySqlTable | Subquery | MySqlViewBase | SQL; + limit?: number | Placeholder; + offset?: number | Placeholder; + joins?: MySqlSelectJoinConfig[]; + orderBy?: (MySqlColumn | SQL | SQL.Aliased)[]; + groupBy?: (MySqlColumn | SQL | SQL.Aliased)[]; + lockingClause?: { + strength: LockStrength; + config: LockConfig; + }; + distinct?: boolean; + setOperators: { + rightSelect: TypedQueryBuilder; + type: SetOperator; + isAll: boolean; + orderBy?: (MySqlColumn | SQL | SQL.Aliased)[]; + limit?: number | Placeholder; + offset?: number | Placeholder; + }[]; + useIndex?: string[]; + forceIndex?: string[]; + ignoreIndex?: string[]; +} + +export type MySqlJoin< + T extends AnyMySqlSelectQueryBuilder, + TDynamic extends boolean, + TJoinType extends JoinType, + TJoinedTable extends MySqlTable | Subquery | MySqlViewBase | SQL, + TJoinedName extends GetSelectTableName = GetSelectTableName, +> = T extends any ? MySqlSelectWithout< + MySqlSelectKind< + T['_']['hkt'], + T['_']['tableName'], + AppendToResult< + T['_']['tableName'], + T['_']['selection'], + TJoinedName, + TJoinedTable extends MySqlTable ? TJoinedTable['_']['columns'] + : TJoinedTable extends Subquery | View ? Assume + : never, + T['_']['selectMode'] + >, + T['_']['selectMode'] extends 'partial' ? T['_']['selectMode'] : 'multiple', + T['_']['preparedQueryHKT'], + AppendToNullabilityMap, + TDynamic, + T['_']['excludedMethods'] + >, + TDynamic, + T['_']['excludedMethods'] + > + : never; + +export type MySqlJoinFn< + T extends AnyMySqlSelectQueryBuilder, + TDynamic extends boolean, + TJoinType extends JoinType, +> = < + TJoinedTable extends MySqlTable | Subquery | MySqlViewBase | SQL, + TJoinedName extends GetSelectTableName = GetSelectTableName, +>( + table: TJoinedTable, + on: ((aliases: T['_']['selection']) => SQL | undefined) | SQL | undefined, + onIndex?: TJoinedTable extends MySqlTable ? IndexConfig + : 'Index hint configuration is allowed only for MySqlTable and not for subqueries or views', +) => MySqlJoin; + +export type SelectedFieldsFlat = SelectedFieldsFlatBase; + +export type SelectedFields = SelectedFieldsBase; + +export type SelectedFieldsOrdered = SelectedFieldsOrderedBase; + +export type LockStrength = 'update' | 'share'; + +export type LockConfig = { + noWait: true; + skipLocked?: undefined; +} | { + noWait?: undefined; + skipLocked: true; +} | { + noWait?: undefined; + skipLocked?: undefined; +}; + +export interface MySqlSelectHKTBase { + tableName: string | undefined; + selection: unknown; + selectMode: SelectMode; + preparedQueryHKT: unknown; + nullabilityMap: unknown; + dynamic: boolean; + excludedMethods: string; + result: unknown; + selectedFields: unknown; + _type: unknown; +} + +export type MySqlSelectKind< + T extends MySqlSelectHKTBase, + TTableName extends string | undefined, + TSelection extends ColumnsSelection, + TSelectMode extends SelectMode, + TPreparedQueryHKT extends PreparedQueryHKTBase, + TNullabilityMap extends Record, + TDynamic extends boolean, + TExcludedMethods extends string, + TResult = SelectResult[], + TSelectedFields = BuildSubquerySelection, +> = (T & { + tableName: TTableName; + selection: TSelection; + selectMode: TSelectMode; + preparedQueryHKT: TPreparedQueryHKT; + nullabilityMap: TNullabilityMap; + dynamic: TDynamic; + excludedMethods: TExcludedMethods; + result: TResult; + selectedFields: TSelectedFields; +})['_type']; + +export interface MySqlSelectQueryBuilderHKT extends MySqlSelectHKTBase { + _type: MySqlSelectQueryBuilderBase< + MySqlSelectQueryBuilderHKT, + this['tableName'], + Assume, + this['selectMode'], + Assume, + Assume>, + this['dynamic'], + this['excludedMethods'], + Assume, + Assume + >; +} + +export interface MySqlSelectHKT extends MySqlSelectHKTBase { + _type: MySqlSelectBase< + this['tableName'], + Assume, + this['selectMode'], + Assume, + Assume>, + this['dynamic'], + this['excludedMethods'], + Assume, + Assume + >; +} + +export type MySqlSetOperatorExcludedMethods = + | 'where' + | 'having' + | 'groupBy' + | 'session' + | 'leftJoin' + | 'rightJoin' + | 'innerJoin' + | 'fullJoin' + | 'for'; + +export type MySqlSelectWithout< + T extends AnyMySqlSelectQueryBuilder, + TDynamic extends boolean, + K extends keyof T & string, + TResetExcluded extends boolean = false, +> = TDynamic extends true ? T : Omit< + MySqlSelectKind< + T['_']['hkt'], + T['_']['tableName'], + T['_']['selection'], + T['_']['selectMode'], + T['_']['preparedQueryHKT'], + T['_']['nullabilityMap'], + TDynamic, + TResetExcluded extends true ? K : T['_']['excludedMethods'] | K, + T['_']['result'], + T['_']['selectedFields'] + >, + TResetExcluded extends true ? K : T['_']['excludedMethods'] | K +>; + +export type MySqlSelectPrepare = PreparedQueryKind< + T['_']['preparedQueryHKT'], + MySqlPreparedQueryConfig & { + execute: T['_']['result']; + iterator: T['_']['result'][number]; + }, + true +>; + +export type MySqlSelectDynamic = MySqlSelectKind< + T['_']['hkt'], + T['_']['tableName'], + T['_']['selection'], + T['_']['selectMode'], + T['_']['preparedQueryHKT'], + T['_']['nullabilityMap'], + true, + never, + T['_']['result'], + T['_']['selectedFields'] +>; + +export type CreateMySqlSelectFromBuilderMode< + TBuilderMode extends 'db' | 'qb', + TTableName extends string | undefined, + TSelection extends ColumnsSelection, + TSelectMode extends SelectMode, + TPreparedQueryHKT extends PreparedQueryHKTBase, +> = TBuilderMode extends 'db' ? MySqlSelectBase + : MySqlSelectQueryBuilderBase; + +export type MySqlSelectQueryBuilder< + THKT extends MySqlSelectHKTBase = MySqlSelectQueryBuilderHKT, + TTableName extends string | undefined = string | undefined, + TSelection extends ColumnsSelection = ColumnsSelection, + TSelectMode extends SelectMode = SelectMode, + TPreparedQueryHKT extends PreparedQueryHKTBase = PreparedQueryHKTBase, + TNullabilityMap extends Record = Record, + TResult extends any[] = unknown[], + TSelectedFields extends ColumnsSelection = ColumnsSelection, +> = MySqlSelectQueryBuilderBase< + THKT, + TTableName, + TSelection, + TSelectMode, + TPreparedQueryHKT, + TNullabilityMap, + true, + never, + TResult, + TSelectedFields +>; + +export type AnyMySqlSelectQueryBuilder = MySqlSelectQueryBuilderBase; + +export type AnyMySqlSetOperatorInterface = MySqlSetOperatorInterface; + +export interface MySqlSetOperatorInterface< + TTableName extends string | undefined, + TSelection extends ColumnsSelection, + TSelectMode extends SelectMode, + TPreparedQueryHKT extends PreparedQueryHKTBase = PreparedQueryHKTBase, + TNullabilityMap extends Record = TTableName extends string ? Record + : {}, + TDynamic extends boolean = false, + TExcludedMethods extends string = never, + TResult extends any[] = SelectResult[], + TSelectedFields extends ColumnsSelection = BuildSubquerySelection, +> { + _: { + readonly hkt: MySqlSelectHKT; + readonly tableName: TTableName; + readonly selection: TSelection; + readonly selectMode: TSelectMode; + readonly preparedQueryHKT: TPreparedQueryHKT; + readonly nullabilityMap: TNullabilityMap; + readonly dynamic: TDynamic; + readonly excludedMethods: TExcludedMethods; + readonly result: TResult; + readonly selectedFields: TSelectedFields; + }; +} + +export type MySqlSetOperatorWithResult = MySqlSetOperatorInterface< + any, + any, + any, + any, + any, + any, + any, + TResult, + any +>; + +export type MySqlSelect< + TTableName extends string | undefined = string | undefined, + TSelection extends ColumnsSelection = Record, + TSelectMode extends SelectMode = SelectMode, + TNullabilityMap extends Record = Record, +> = MySqlSelectBase; + +export type AnyMySqlSelect = MySqlSelectBase; + +export type MySqlSetOperator< + TTableName extends string | undefined = string | undefined, + TSelection extends ColumnsSelection = Record, + TSelectMode extends SelectMode = SelectMode, + TPreparedQueryHKT extends PreparedQueryHKTBase = PreparedQueryHKTBase, + TNullabilityMap extends Record = Record, +> = MySqlSelectBase< + TTableName, + TSelection, + TSelectMode, + TPreparedQueryHKT, + TNullabilityMap, + true, + MySqlSetOperatorExcludedMethods +>; + +export type SetOperatorRightSelect< + TValue extends MySqlSetOperatorWithResult, + TResult extends any[], +> = TValue extends MySqlSetOperatorInterface + ? ValidateShape< + TValueResult[number], + TResult[number], + TypedQueryBuilder + > + : TValue; + +export type SetOperatorRestSelect< + TValue extends readonly MySqlSetOperatorWithResult[], + TResult extends any[], +> = TValue extends [infer First, ...infer Rest] + ? First extends MySqlSetOperatorInterface + ? Rest extends AnyMySqlSetOperatorInterface[] ? [ + ValidateShape>, + ...SetOperatorRestSelect, + ] + : ValidateShape[]> + : never + : TValue; + +export type MySqlCreateSetOperatorFn = < + TTableName extends string | undefined, + TSelection extends ColumnsSelection, + TSelectMode extends SelectMode, + TValue extends MySqlSetOperatorWithResult, + TRest extends MySqlSetOperatorWithResult[], + TPreparedQueryHKT extends PreparedQueryHKTBase = PreparedQueryHKTBase, + TNullabilityMap extends Record = TTableName extends string ? Record + : {}, + TDynamic extends boolean = false, + TExcludedMethods extends string = never, + TResult extends any[] = SelectResult[], + TSelectedFields extends ColumnsSelection = BuildSubquerySelection, +>( + leftSelect: MySqlSetOperatorInterface< + TTableName, + TSelection, + TSelectMode, + TPreparedQueryHKT, + TNullabilityMap, + TDynamic, + TExcludedMethods, + TResult, + TSelectedFields + >, + rightSelect: SetOperatorRightSelect, + ...restSelects: SetOperatorRestSelect +) => MySqlSelectWithout< + MySqlSelectBase< + TTableName, + TSelection, + TSelectMode, + TPreparedQueryHKT, + TNullabilityMap, + TDynamic, + TExcludedMethods, + TResult, + TSelectedFields + >, + false, + MySqlSetOperatorExcludedMethods, + true +>; + +export type GetMySqlSetOperators = { + union: MySqlCreateSetOperatorFn; + intersect: MySqlCreateSetOperatorFn; + except: MySqlCreateSetOperatorFn; + unionAll: MySqlCreateSetOperatorFn; + intersectAll: MySqlCreateSetOperatorFn; + exceptAll: MySqlCreateSetOperatorFn; +}; diff --git a/drizzle-orm/src/googlesql/query-builders/update.ts b/drizzle-orm/src/googlesql/query-builders/update.ts new file mode 100644 index 0000000000..7c6fd40abb --- /dev/null +++ b/drizzle-orm/src/googlesql/query-builders/update.ts @@ -0,0 +1,246 @@ +import type { GetColumnData } from '~/column.ts'; +import { entityKind } from '~/entity.ts'; +import type { MySqlDialect } from '~/mysql-core/dialect.ts'; +import type { + AnyMySqlQueryResultHKT, + MySqlPreparedQueryConfig, + MySqlQueryResultHKT, + MySqlQueryResultKind, + MySqlSession, + PreparedQueryHKTBase, + PreparedQueryKind, +} from '~/mysql-core/session.ts'; +import type { MySqlTable } from '~/mysql-core/table.ts'; +import { QueryPromise } from '~/query-promise.ts'; +import { SelectionProxyHandler } from '~/selection-proxy.ts'; +import type { Placeholder, Query, SQL, SQLWrapper } from '~/sql/sql.ts'; +import type { Subquery } from '~/subquery.ts'; +import { Table } from '~/table.ts'; +import { mapUpdateSet, type UpdateSet, type ValueOrArray } from '~/utils.ts'; +import type { MySqlColumn } from '../columns/common.ts'; +import type { SelectedFieldsOrdered } from './select.types.ts'; + +export interface MySqlUpdateConfig { + where?: SQL | undefined; + limit?: number | Placeholder; + orderBy?: (MySqlColumn | SQL | SQL.Aliased)[]; + set: UpdateSet; + table: MySqlTable; + returning?: SelectedFieldsOrdered; + withList?: Subquery[]; +} + +export type MySqlUpdateSetSource = + & { + [Key in keyof TTable['$inferInsert']]?: + | GetColumnData + | SQL + | undefined; + } + & {}; + +export class MySqlUpdateBuilder< + TTable extends MySqlTable, + TQueryResult extends MySqlQueryResultHKT, + TPreparedQueryHKT extends PreparedQueryHKTBase, +> { + static readonly [entityKind]: string = 'MySqlUpdateBuilder'; + + declare readonly _: { + readonly table: TTable; + }; + + constructor( + private table: TTable, + private session: MySqlSession, + private dialect: MySqlDialect, + private withList?: Subquery[], + ) {} + + set(values: MySqlUpdateSetSource): MySqlUpdateBase { + return new MySqlUpdateBase(this.table, mapUpdateSet(this.table, values), this.session, this.dialect, this.withList); + } +} + +export type MySqlUpdateWithout< + T extends AnyMySqlUpdateBase, + TDynamic extends boolean, + K extends keyof T & string, +> = TDynamic extends true ? T : Omit< + MySqlUpdateBase< + T['_']['table'], + T['_']['queryResult'], + T['_']['preparedQueryHKT'], + TDynamic, + T['_']['excludedMethods'] | K + >, + T['_']['excludedMethods'] | K +>; + +export type MySqlUpdatePrepare = PreparedQueryKind< + T['_']['preparedQueryHKT'], + MySqlPreparedQueryConfig & { + execute: MySqlQueryResultKind; + iterator: never; + }, + true +>; + +export type MySqlUpdateDynamic = MySqlUpdate< + T['_']['table'], + T['_']['queryResult'], + T['_']['preparedQueryHKT'] +>; + +export type MySqlUpdate< + TTable extends MySqlTable = MySqlTable, + TQueryResult extends MySqlQueryResultHKT = AnyMySqlQueryResultHKT, + TPreparedQueryHKT extends PreparedQueryHKTBase = PreparedQueryHKTBase, +> = MySqlUpdateBase; + +export type AnyMySqlUpdateBase = MySqlUpdateBase; + +export interface MySqlUpdateBase< + TTable extends MySqlTable, + TQueryResult extends MySqlQueryResultHKT, + TPreparedQueryHKT extends PreparedQueryHKTBase, + TDynamic extends boolean = false, + TExcludedMethods extends string = never, +> extends QueryPromise>, SQLWrapper { + readonly _: { + readonly table: TTable; + readonly queryResult: TQueryResult; + readonly preparedQueryHKT: TPreparedQueryHKT; + readonly dynamic: TDynamic; + readonly excludedMethods: TExcludedMethods; + }; +} + +export class MySqlUpdateBase< + TTable extends MySqlTable, + TQueryResult extends MySqlQueryResultHKT, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + TPreparedQueryHKT extends PreparedQueryHKTBase, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + TDynamic extends boolean = false, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + TExcludedMethods extends string = never, +> extends QueryPromise> implements SQLWrapper { + static override readonly [entityKind]: string = 'MySqlUpdate'; + + private config: MySqlUpdateConfig; + + constructor( + table: TTable, + set: UpdateSet, + private session: MySqlSession, + private dialect: MySqlDialect, + withList?: Subquery[], + ) { + super(); + this.config = { set, table, withList }; + } + + /** + * Adds a 'where' clause to the query. + * + * Calling this method will update only those rows that fulfill a specified condition. + * + * See docs: {@link https://orm.drizzle.team/docs/update} + * + * @param where the 'where' clause. + * + * @example + * You can use conditional operators and `sql function` to filter the rows to be updated. + * + * ```ts + * // Update all cars with green color + * db.update(cars).set({ color: 'red' }) + * .where(eq(cars.color, 'green')); + * // or + * db.update(cars).set({ color: 'red' }) + * .where(sql`${cars.color} = 'green'`) + * ``` + * + * You can logically combine conditional operators with `and()` and `or()` operators: + * + * ```ts + * // Update all BMW cars with a green color + * db.update(cars).set({ color: 'red' }) + * .where(and(eq(cars.color, 'green'), eq(cars.brand, 'BMW'))); + * + * // Update all cars with the green or blue color + * db.update(cars).set({ color: 'red' }) + * .where(or(eq(cars.color, 'green'), eq(cars.color, 'blue'))); + * ``` + */ + where(where: SQL | undefined): MySqlUpdateWithout { + this.config.where = where; + return this as any; + } + + orderBy( + builder: (updateTable: TTable) => ValueOrArray, + ): MySqlUpdateWithout; + orderBy(...columns: (MySqlColumn | SQL | SQL.Aliased)[]): MySqlUpdateWithout; + orderBy( + ...columns: + | [(updateTable: TTable) => ValueOrArray] + | (MySqlColumn | SQL | SQL.Aliased)[] + ): MySqlUpdateWithout { + if (typeof columns[0] === 'function') { + const orderBy = columns[0]( + new Proxy( + this.config.table[Table.Symbol.Columns], + new SelectionProxyHandler({ sqlAliasedBehavior: 'alias', sqlBehavior: 'sql' }), + ) as any, + ); + + const orderByArray = Array.isArray(orderBy) ? orderBy : [orderBy]; + this.config.orderBy = orderByArray; + } else { + const orderByArray = columns as (MySqlColumn | SQL | SQL.Aliased)[]; + this.config.orderBy = orderByArray; + } + return this as any; + } + + limit(limit: number | Placeholder): MySqlUpdateWithout { + this.config.limit = limit; + return this as any; + } + + /** @internal */ + getSQL(): SQL { + return this.dialect.buildUpdateQuery(this.config); + } + + toSQL(): Query { + const { typings: _typings, ...rest } = this.dialect.sqlToQuery(this.getSQL()); + return rest; + } + + prepare(): MySqlUpdatePrepare { + return this.session.prepareQuery( + this.dialect.sqlToQuery(this.getSQL()), + this.config.returning, + ) as MySqlUpdatePrepare; + } + + override execute: ReturnType['execute'] = (placeholderValues) => { + return this.prepare().execute(placeholderValues); + }; + + private createIterator = (): ReturnType['iterator'] => { + const self = this; + return async function*(placeholderValues) { + yield* self.prepare().iterator(placeholderValues); + }; + }; + + iterator = this.createIterator(); + + $dynamic(): MySqlUpdateDynamic { + return this as any; + } +} diff --git a/drizzle-orm/src/googlesql/schema.ts b/drizzle-orm/src/googlesql/schema.ts new file mode 100644 index 0000000000..b36531e44e --- /dev/null +++ b/drizzle-orm/src/googlesql/schema.ts @@ -0,0 +1,40 @@ +import { entityKind, is } from '~/entity.ts'; +import { type MySqlTableFn, mysqlTableWithSchema } from './table.ts'; +import { type mysqlView, mysqlViewWithSchema } from './view.ts'; + +export class MySqlSchema { + static readonly [entityKind]: string = 'MySqlSchema'; + + constructor( + public readonly schemaName: TName, + ) {} + + table: MySqlTableFn = (name, columns, extraConfig) => { + return mysqlTableWithSchema(name, columns, extraConfig, this.schemaName); + }; + + view = ((name, columns) => { + return mysqlViewWithSchema(name, columns, this.schemaName); + }) as typeof mysqlView; +} + +/** @deprecated - use `instanceof MySqlSchema` */ +export function isMySqlSchema(obj: unknown): obj is MySqlSchema { + return is(obj, MySqlSchema); +} + +/** + * Create a MySQL schema. + * https://dev.mysql.com/doc/refman/8.0/en/create-database.html + * + * @param name mysql use schema name + * @returns MySQL schema + */ +export function mysqlDatabase(name: TName) { + return new MySqlSchema(name); +} + +/** + * @see mysqlDatabase + */ +export const mysqlSchema = mysqlDatabase; diff --git a/drizzle-orm/src/googlesql/session.ts b/drizzle-orm/src/googlesql/session.ts new file mode 100644 index 0000000000..326b0ad61e --- /dev/null +++ b/drizzle-orm/src/googlesql/session.ts @@ -0,0 +1,157 @@ +import { entityKind } from '~/entity.ts'; +import { TransactionRollbackError } from '~/errors.ts'; +import type { RelationalSchemaConfig, TablesRelationalConfig } from '~/relations.ts'; +import { type Query, type SQL, sql } from '~/sql/sql.ts'; +import type { Assume, Equal } from '~/utils.ts'; +import { MySqlDatabase } from './db.ts'; +import type { MySqlDialect } from './dialect.ts'; +import type { SelectedFieldsOrdered } from './query-builders/select.types.ts'; + +export type Mode = 'default' | 'planetscale'; + +export interface MySqlQueryResultHKT { + readonly $brand: 'MySqlQueryResultHKT'; + readonly row: unknown; + readonly type: unknown; +} + +export interface AnyMySqlQueryResultHKT extends MySqlQueryResultHKT { + readonly type: any; +} + +export type MySqlQueryResultKind = (TKind & { + readonly row: TRow; +})['type']; + +export interface MySqlPreparedQueryConfig { + execute: unknown; + iterator: unknown; +} + +export interface MySqlPreparedQueryHKT { + readonly $brand: 'MySqlPreparedQueryHKT'; + readonly config: unknown; + readonly type: unknown; +} + +export type PreparedQueryKind< + TKind extends MySqlPreparedQueryHKT, + TConfig extends MySqlPreparedQueryConfig, + TAssume extends boolean = false, +> = Equal extends true + ? Assume<(TKind & { readonly config: TConfig })['type'], MySqlPreparedQuery> + : (TKind & { readonly config: TConfig })['type']; + +export abstract class MySqlPreparedQuery { + static readonly [entityKind]: string = 'MySqlPreparedQuery'; + + /** @internal */ + joinsNotNullableMap?: Record; + + abstract execute(placeholderValues?: Record): Promise; + + abstract iterator(placeholderValues?: Record): AsyncGenerator; +} + +export interface MySqlTransactionConfig { + withConsistentSnapshot?: boolean; + accessMode?: 'read only' | 'read write'; + isolationLevel: 'read uncommitted' | 'read committed' | 'repeatable read' | 'serializable'; +} + +export abstract class MySqlSession< + TQueryResult extends MySqlQueryResultHKT = MySqlQueryResultHKT, + TPreparedQueryHKT extends PreparedQueryHKTBase = PreparedQueryHKTBase, + TFullSchema extends Record = Record, + TSchema extends TablesRelationalConfig = Record, +> { + static readonly [entityKind]: string = 'MySqlSession'; + + constructor(protected dialect: MySqlDialect) {} + + abstract prepareQuery( + query: Query, + fields: SelectedFieldsOrdered | undefined, + customResultMapper?: (rows: unknown[][]) => T['execute'], + generatedIds?: Record[], + returningIds?: SelectedFieldsOrdered, + ): PreparedQueryKind; + + execute(query: SQL): Promise { + return this.prepareQuery( + this.dialect.sqlToQuery(query), + undefined, + ).execute(); + } + + abstract all(query: SQL): Promise; + + async count(sql: SQL): Promise { + const res = await this.execute<[[{ count: string }]]>(sql); + + return Number( + res[0][0]['count'], + ); + } + + abstract transaction( + transaction: (tx: MySqlTransaction) => Promise, + config?: MySqlTransactionConfig, + ): Promise; + + protected getSetTransactionSQL(config: MySqlTransactionConfig): SQL | undefined { + const parts: string[] = []; + + if (config.isolationLevel) { + parts.push(`isolation level ${config.isolationLevel}`); + } + + return parts.length ? sql`set transaction ${sql.raw(parts.join(' '))}` : undefined; + } + + protected getStartTransactionSQL(config: MySqlTransactionConfig): SQL | undefined { + const parts: string[] = []; + + if (config.withConsistentSnapshot) { + parts.push('with consistent snapshot'); + } + + if (config.accessMode) { + parts.push(config.accessMode); + } + + return parts.length ? sql`start transaction ${sql.raw(parts.join(' '))}` : undefined; + } +} + +export abstract class MySqlTransaction< + TQueryResult extends MySqlQueryResultHKT, + TPreparedQueryHKT extends PreparedQueryHKTBase, + TFullSchema extends Record = Record, + TSchema extends TablesRelationalConfig = Record, +> extends MySqlDatabase { + static override readonly [entityKind]: string = 'MySqlTransaction'; + + constructor( + dialect: MySqlDialect, + session: MySqlSession, + protected schema: RelationalSchemaConfig | undefined, + protected readonly nestedIndex: number, + mode: Mode, + ) { + super(dialect, session, schema, mode); + } + + rollback(): never { + throw new TransactionRollbackError(); + } + + /** Nested transactions (aka savepoints) only work with InnoDB engine. */ + abstract override transaction( + transaction: (tx: MySqlTransaction) => Promise, + ): Promise; +} + +export interface PreparedQueryHKTBase extends MySqlPreparedQueryHKT { + type: MySqlPreparedQuery>; +} diff --git a/drizzle-orm/src/googlesql/subquery.ts b/drizzle-orm/src/googlesql/subquery.ts new file mode 100644 index 0000000000..9838cb1943 --- /dev/null +++ b/drizzle-orm/src/googlesql/subquery.ts @@ -0,0 +1,35 @@ +import type { TypedQueryBuilder } from '~/query-builders/query-builder.ts'; +import type { AddAliasToSelection } from '~/query-builders/select.types.ts'; +import type { ColumnsSelection, SQL } from '~/sql/sql.ts'; +import type { Subquery, WithSubquery, WithSubqueryWithoutSelection } from '~/subquery.ts'; +import type { QueryBuilder } from './query-builders/query-builder.ts'; + +export type SubqueryWithSelection< + TSelection extends ColumnsSelection, + TAlias extends string, +> = + & Subquery> + & AddAliasToSelection; + +export type WithSubqueryWithSelection< + TSelection extends ColumnsSelection, + TAlias extends string, +> = + & WithSubquery> + & AddAliasToSelection; + +export interface WithBuilder { + (alias: TAlias): { + as: { + ( + qb: TypedQueryBuilder | ((qb: QueryBuilder) => TypedQueryBuilder), + ): WithSubqueryWithSelection; + ( + qb: TypedQueryBuilder | ((qb: QueryBuilder) => TypedQueryBuilder), + ): WithSubqueryWithoutSelection; + }; + }; + (alias: TAlias, selection: TSelection): { + as: (qb: SQL | ((qb: QueryBuilder) => SQL)) => WithSubqueryWithSelection; + }; +} diff --git a/drizzle-orm/src/googlesql/table.ts b/drizzle-orm/src/googlesql/table.ts new file mode 100644 index 0000000000..2616e71597 --- /dev/null +++ b/drizzle-orm/src/googlesql/table.ts @@ -0,0 +1,229 @@ +import type { BuildColumns, BuildExtraConfigColumns } from '~/column-builder.ts'; +import { entityKind } from '~/entity.ts'; +import { Table, type TableConfig as TableConfigBase, type UpdateTableConfig } from '~/table.ts'; +import type { CheckBuilder } from './checks.ts'; +import { getMySqlColumnBuilders, type MySqlColumnBuilders } from './columns/all.ts'; +import type { MySqlColumn, MySqlColumnBuilder, MySqlColumnBuilderBase } from './columns/common.ts'; +import type { ForeignKey, ForeignKeyBuilder } from './foreign-keys.ts'; +import type { AnyIndexBuilder } from './indexes.ts'; +import type { PrimaryKeyBuilder } from './primary-keys.ts'; +import type { UniqueConstraintBuilder } from './unique-constraint.ts'; + +export type MySqlTableExtraConfigValue = + | AnyIndexBuilder + | CheckBuilder + | ForeignKeyBuilder + | PrimaryKeyBuilder + | UniqueConstraintBuilder; + +export type MySqlTableExtraConfig = Record< + string, + MySqlTableExtraConfigValue +>; + +export type TableConfig = TableConfigBase; + +/** @internal */ +export const InlineForeignKeys = Symbol.for('drizzle:MySqlInlineForeignKeys'); + +export class MySqlTable extends Table { + 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; + + /** @internal */ + [InlineForeignKeys]: ForeignKey[] = []; + + /** @internal */ + override [Table.Symbol.ExtraConfigBuilder]: + | ((self: Record) => MySqlTableExtraConfig) + | undefined = undefined; +} + +export type AnyMySqlTable = {}> = MySqlTable< + UpdateTableConfig +>; + +export type MySqlTableWithColumns = + & MySqlTable + & { + [Key in keyof T['columns']]: T['columns'][Key]; + }; + +export function mysqlTableWithSchema< + TTableName extends string, + TSchemaName extends string | undefined, + TColumnsMap extends Record, +>( + name: TTableName, + columns: TColumnsMap | ((columnTypes: MySqlColumnBuilders) => TColumnsMap), + extraConfig: + | (( + self: BuildColumns, + ) => MySqlTableExtraConfig | MySqlTableExtraConfigValue[]) + | undefined, + schema: TSchemaName, + baseName = name, +): MySqlTableWithColumns<{ + name: TTableName; + schema: TSchemaName; + columns: BuildColumns; + dialect: 'mysql'; +}> { + const rawTable = new MySqlTable<{ + name: TTableName; + schema: TSchemaName; + columns: BuildColumns; + 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; + + 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, + ) => MySqlTableExtraConfig; + } + + return table; +} + +export interface MySqlTableFn { + < + TTableName extends string, + TColumnsMap extends Record, + >( + name: TTableName, + columns: TColumnsMap, + extraConfig?: ( + self: BuildColumns, + ) => MySqlTableExtraConfigValue[], + ): MySqlTableWithColumns<{ + name: TTableName; + schema: TSchemaName; + columns: BuildColumns; + dialect: 'mysql'; + }>; + + < + TTableName extends string, + TColumnsMap extends Record, + >( + name: TTableName, + columns: (columnTypes: MySqlColumnBuilders) => TColumnsMap, + extraConfig?: (self: BuildColumns) => MySqlTableExtraConfigValue[], + ): MySqlTableWithColumns<{ + name: TTableName; + schema: TSchemaName; + columns: BuildColumns; + dialect: 'mysql'; + }>; + /** + * @deprecated The third parameter of mysqlTable is changing and will only accept an array instead of an object + * + * @example + * Deprecated version: + * ```ts + * export const users = mysqlTable("users", { + * id: int(), + * }, (t) => ({ + * idx: index('custom_name').on(t.id) + * })); + * ``` + * + * New API: + * ```ts + * export const users = mysqlTable("users", { + * id: int(), + * }, (t) => [ + * index('custom_name').on(t.id) + * ]); + * ``` + */ + < + TTableName extends string, + TColumnsMap extends Record, + >( + name: TTableName, + columns: TColumnsMap, + extraConfig: (self: BuildColumns) => MySqlTableExtraConfig, + ): MySqlTableWithColumns<{ + name: TTableName; + schema: TSchemaName; + columns: BuildColumns; + dialect: 'mysql'; + }>; + + /** + * @deprecated The third parameter of mysqlTable is changing and will only accept an array instead of an object + * + * @example + * Deprecated version: + * ```ts + * export const users = mysqlTable("users", { + * id: int(), + * }, (t) => ({ + * idx: index('custom_name').on(t.id) + * })); + * ``` + * + * New API: + * ```ts + * export const users = mysqlTable("users", { + * id: int(), + * }, (t) => [ + * index('custom_name').on(t.id) + * ]); + * ``` + */ + < + TTableName extends string, + TColumnsMap extends Record, + >( + name: TTableName, + columns: (columnTypes: MySqlColumnBuilders) => TColumnsMap, + extraConfig: (self: BuildColumns) => MySqlTableExtraConfig, + ): MySqlTableWithColumns<{ + name: TTableName; + schema: TSchemaName; + columns: BuildColumns; + dialect: 'mysql'; + }>; +} + +export const mysqlTable: MySqlTableFn = (name, columns, extraConfig) => { + return mysqlTableWithSchema(name, columns, extraConfig, undefined, name); +}; + +export function mysqlTableCreator(customizeTableName: (name: string) => string): MySqlTableFn { + return (name, columns, extraConfig) => { + return mysqlTableWithSchema(customizeTableName(name) as typeof name, columns, extraConfig, undefined, name); + }; +} diff --git a/drizzle-orm/src/googlesql/unique-constraint.ts b/drizzle-orm/src/googlesql/unique-constraint.ts new file mode 100644 index 0000000000..01a3c36c28 --- /dev/null +++ b/drizzle-orm/src/googlesql/unique-constraint.ts @@ -0,0 +1,65 @@ +import { entityKind } from '~/entity.ts'; +import { TableName } from '~/table.utils.ts'; +import type { MySqlColumn } from './columns/index.ts'; +import type { MySqlTable } from './table.ts'; + +export function unique(name?: string): UniqueOnConstraintBuilder { + return new UniqueOnConstraintBuilder(name); +} + +export function uniqueKeyName(table: MySqlTable, columns: string[]) { + return `${table[TableName]}_${columns.join('_')}_unique`; +} + +export class UniqueConstraintBuilder { + static readonly [entityKind]: string = 'MySqlUniqueConstraintBuilder'; + + /** @internal */ + columns: MySqlColumn[]; + + constructor( + columns: MySqlColumn[], + private name?: string, + ) { + this.columns = columns; + } + + /** @internal */ + build(table: MySqlTable): UniqueConstraint { + return new UniqueConstraint(table, this.columns, this.name); + } +} + +export class UniqueOnConstraintBuilder { + static readonly [entityKind]: string = 'MySqlUniqueOnConstraintBuilder'; + + /** @internal */ + name?: string; + + constructor( + name?: string, + ) { + this.name = name; + } + + on(...columns: [MySqlColumn, ...MySqlColumn[]]) { + return new UniqueConstraintBuilder(columns, this.name); + } +} + +export class UniqueConstraint { + static readonly [entityKind]: string = 'MySqlUniqueConstraint'; + + readonly columns: MySqlColumn[]; + readonly name?: string; + readonly nullsNotDistinct: boolean = false; + + constructor(readonly table: MySqlTable, columns: MySqlColumn[], name?: string) { + this.columns = columns; + this.name = name ?? uniqueKeyName(this.table, this.columns.map((column) => column.name)); + } + + getName() { + return this.name; + } +} diff --git a/drizzle-orm/src/googlesql/utils.ts b/drizzle-orm/src/googlesql/utils.ts new file mode 100644 index 0000000000..b49dd00433 --- /dev/null +++ b/drizzle-orm/src/googlesql/utils.ts @@ -0,0 +1,80 @@ +import { is } from '~/entity.ts'; +import { Table } from '~/table.ts'; +import { ViewBaseConfig } from '~/view-common.ts'; +import type { Check } from './checks.ts'; +import { CheckBuilder } from './checks.ts'; +import type { ForeignKey } from './foreign-keys.ts'; +import { ForeignKeyBuilder } from './foreign-keys.ts'; +import type { Index } from './indexes.ts'; +import { IndexBuilder } from './indexes.ts'; +import type { PrimaryKey } from './primary-keys.ts'; +import { PrimaryKeyBuilder } from './primary-keys.ts'; +import type { IndexForHint } from './query-builders/select.ts'; +import { MySqlTable } from './table.ts'; +import { type UniqueConstraint, UniqueConstraintBuilder } from './unique-constraint.ts'; +import { MySqlViewConfig } from './view-common.ts'; +import type { MySqlView } from './view.ts'; + +export function getTableConfig(table: MySqlTable) { + const columns = Object.values(table[MySqlTable.Symbol.Columns]); + const indexes: Index[] = []; + const checks: Check[] = []; + const primaryKeys: PrimaryKey[] = []; + const uniqueConstraints: UniqueConstraint[] = []; + const foreignKeys: ForeignKey[] = Object.values(table[MySqlTable.Symbol.InlineForeignKeys]); + const name = table[Table.Symbol.Name]; + const schema = table[Table.Symbol.Schema]; + const baseName = table[Table.Symbol.BaseName]; + + const extraConfigBuilder = table[MySqlTable.Symbol.ExtraConfigBuilder]; + + if (extraConfigBuilder !== undefined) { + const extraConfig = extraConfigBuilder(table[MySqlTable.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, + schema, + baseName, + }; +} + +export function getViewConfig< + TName extends string = string, + TExisting extends boolean = boolean, +>(view: MySqlView) { + return { + ...view[ViewBaseConfig], + ...view[MySqlViewConfig], + }; +} + +export function convertIndexToString(indexes: IndexForHint[]) { + return indexes.map((idx) => { + return typeof idx === 'object' ? idx.config.name : idx; + }); +} + +export function toArray(value: T | T[]): T[] { + return Array.isArray(value) ? value : [value]; +} diff --git a/drizzle-orm/src/googlesql/view-base.ts b/drizzle-orm/src/googlesql/view-base.ts new file mode 100644 index 0000000000..fa8a25cfa4 --- /dev/null +++ b/drizzle-orm/src/googlesql/view-base.ts @@ -0,0 +1,15 @@ +import { entityKind } from '~/entity.ts'; +import type { ColumnsSelection } from '~/sql/sql.ts'; +import { View } from '~/sql/sql.ts'; + +export abstract class MySqlViewBase< + TName extends string = string, + TExisting extends boolean = boolean, + TSelectedFields extends ColumnsSelection = ColumnsSelection, +> extends View { + static override readonly [entityKind]: string = 'MySqlViewBase'; + + declare readonly _: View['_'] & { + readonly viewBrand: 'MySqlViewBase'; + }; +} diff --git a/drizzle-orm/src/googlesql/view-common.ts b/drizzle-orm/src/googlesql/view-common.ts new file mode 100644 index 0000000000..9bbc130c33 --- /dev/null +++ b/drizzle-orm/src/googlesql/view-common.ts @@ -0,0 +1 @@ +export const MySqlViewConfig = Symbol.for('drizzle:MySqlViewConfig'); diff --git a/drizzle-orm/src/googlesql/view.ts b/drizzle-orm/src/googlesql/view.ts new file mode 100644 index 0000000000..42d9b3af6d --- /dev/null +++ b/drizzle-orm/src/googlesql/view.ts @@ -0,0 +1,199 @@ +import type { BuildColumns } from '~/column-builder.ts'; +import { entityKind } from '~/entity.ts'; +import type { TypedQueryBuilder } from '~/query-builders/query-builder.ts'; +import type { AddAliasToSelection } from '~/query-builders/select.types.ts'; +import { SelectionProxyHandler } from '~/selection-proxy.ts'; +import type { ColumnsSelection, SQL } from '~/sql/sql.ts'; +import { getTableColumns } from '~/utils.ts'; +import type { MySqlColumn, MySqlColumnBuilderBase } from './columns/index.ts'; +import { QueryBuilder } from './query-builders/query-builder.ts'; +import { mysqlTable } from './table.ts'; +import { MySqlViewBase } from './view-base.ts'; +import { MySqlViewConfig } from './view-common.ts'; + +export interface ViewBuilderConfig { + algorithm?: 'undefined' | 'merge' | 'temptable'; + sqlSecurity?: 'definer' | 'invoker'; + withCheckOption?: 'cascaded' | 'local'; +} + +export class ViewBuilderCore { + static readonly [entityKind]: string = 'MySqlViewBuilder'; + + declare readonly _: { + readonly name: TConfig['name']; + readonly columns: TConfig['columns']; + }; + + constructor( + protected name: TConfig['name'], + protected schema: string | undefined, + ) {} + + protected config: ViewBuilderConfig = {}; + + algorithm( + algorithm: Exclude, + ): this { + this.config.algorithm = algorithm; + return this; + } + + sqlSecurity( + sqlSecurity: Exclude, + ): this { + this.config.sqlSecurity = sqlSecurity; + return this; + } + + withCheckOption( + withCheckOption?: Exclude, + ): this { + this.config.withCheckOption = withCheckOption ?? 'cascaded'; + return this; + } +} + +export class ViewBuilder extends ViewBuilderCore<{ name: TName }> { + static override readonly [entityKind]: string = 'MySqlViewBuilder'; + + as( + qb: TypedQueryBuilder | ((qb: QueryBuilder) => TypedQueryBuilder), + ): MySqlViewWithSelection> { + if (typeof qb === 'function') { + qb = qb(new QueryBuilder()); + } + const selectionProxy = new SelectionProxyHandler({ + alias: this.name, + sqlBehavior: 'error', + sqlAliasedBehavior: 'alias', + replaceOriginalName: true, + }); + const aliasedSelection = new Proxy(qb.getSelectedFields(), selectionProxy); + return new Proxy( + new MySqlView({ + mysqlConfig: this.config, + config: { + name: this.name, + schema: this.schema, + selectedFields: aliasedSelection, + query: qb.getSQL().inlineParams(), + }, + }), + selectionProxy as any, + ) as MySqlViewWithSelection>; + } +} + +export class ManualViewBuilder< + TName extends string = string, + TColumns extends Record = Record, +> extends ViewBuilderCore<{ name: TName; columns: TColumns }> { + static override readonly [entityKind]: string = 'MySqlManualViewBuilder'; + + private columns: Record; + + constructor( + name: TName, + columns: TColumns, + schema: string | undefined, + ) { + super(name, schema); + this.columns = getTableColumns(mysqlTable(name, columns)) as BuildColumns; + } + + existing(): MySqlViewWithSelection> { + return new Proxy( + new MySqlView({ + mysqlConfig: undefined, + config: { + name: this.name, + schema: this.schema, + selectedFields: this.columns, + query: undefined, + }, + }), + new SelectionProxyHandler({ + alias: this.name, + sqlBehavior: 'error', + sqlAliasedBehavior: 'alias', + replaceOriginalName: true, + }), + ) as MySqlViewWithSelection>; + } + + as(query: SQL): MySqlViewWithSelection> { + return new Proxy( + new MySqlView({ + mysqlConfig: this.config, + config: { + name: this.name, + schema: this.schema, + selectedFields: this.columns, + query: query.inlineParams(), + }, + }), + new SelectionProxyHandler({ + alias: this.name, + sqlBehavior: 'error', + sqlAliasedBehavior: 'alias', + replaceOriginalName: true, + }), + ) as MySqlViewWithSelection>; + } +} + +export class MySqlView< + TName extends string = string, + TExisting extends boolean = boolean, + TSelectedFields extends ColumnsSelection = ColumnsSelection, +> extends MySqlViewBase { + static override readonly [entityKind]: string = 'MySqlView'; + + declare protected $MySqlViewBrand: 'MySqlView'; + + [MySqlViewConfig]: ViewBuilderConfig | undefined; + + constructor({ mysqlConfig, config }: { + mysqlConfig: ViewBuilderConfig | undefined; + config: { + name: TName; + schema: string | undefined; + selectedFields: ColumnsSelection; + query: SQL | undefined; + }; + }) { + super(config); + this[MySqlViewConfig] = mysqlConfig; + } +} + +export type MySqlViewWithSelection< + TName extends string, + TExisting extends boolean, + TSelectedFields extends ColumnsSelection, +> = MySqlView & TSelectedFields; + +/** @internal */ +export function mysqlViewWithSchema( + name: string, + selection: Record | undefined, + schema: string | undefined, +): ViewBuilder | ManualViewBuilder { + if (selection) { + return new ManualViewBuilder(name, selection, schema); + } + return new ViewBuilder(name, schema); +} + +export function mysqlView(name: TName): ViewBuilder; +export function mysqlView>( + name: TName, + columns: TColumns, +): ManualViewBuilder; +export function mysqlView( + name: string, + selection?: Record, +): ViewBuilder | ManualViewBuilder { + return mysqlViewWithSchema(name, selection, undefined); +} From 2e78ca49f6d419a9d7eafdb07fd3ca6e15db3a27 Mon Sep 17 00:00:00 2001 From: Gabriel Cipriano Date: Wed, 26 Feb 2025 14:36:36 +0100 Subject: [PATCH 2/7] chore: update paths --- drizzle-orm/src/googlesql/columns/bigint.ts | 2 +- drizzle-orm/src/googlesql/columns/binary.ts | 2 +- drizzle-orm/src/googlesql/columns/boolean.ts | 2 +- drizzle-orm/src/googlesql/columns/char.ts | 2 +- drizzle-orm/src/googlesql/columns/common.ts | 6 +++--- drizzle-orm/src/googlesql/columns/custom.ts | 2 +- drizzle-orm/src/googlesql/columns/date.ts | 2 +- drizzle-orm/src/googlesql/columns/datetime.ts | 2 +- drizzle-orm/src/googlesql/columns/decimal.ts | 2 +- drizzle-orm/src/googlesql/columns/double.ts | 2 +- drizzle-orm/src/googlesql/columns/enum.ts | 2 +- drizzle-orm/src/googlesql/columns/float.ts | 2 +- drizzle-orm/src/googlesql/columns/int.ts | 2 +- drizzle-orm/src/googlesql/columns/json.ts | 2 +- drizzle-orm/src/googlesql/columns/mediumint.ts | 2 +- drizzle-orm/src/googlesql/columns/real.ts | 2 +- drizzle-orm/src/googlesql/columns/serial.ts | 2 +- drizzle-orm/src/googlesql/columns/smallint.ts | 2 +- drizzle-orm/src/googlesql/columns/text.ts | 2 +- drizzle-orm/src/googlesql/columns/time.ts | 2 +- drizzle-orm/src/googlesql/columns/timestamp.ts | 2 +- drizzle-orm/src/googlesql/columns/tinyint.ts | 2 +- drizzle-orm/src/googlesql/columns/varbinary.ts | 2 +- drizzle-orm/src/googlesql/columns/varchar.ts | 2 +- drizzle-orm/src/googlesql/columns/year.ts | 2 +- drizzle-orm/src/googlesql/query-builders/delete.ts | 6 +++--- drizzle-orm/src/googlesql/query-builders/insert.ts | 6 +++--- .../src/googlesql/query-builders/query-builder.ts | 6 +++--- drizzle-orm/src/googlesql/query-builders/select.ts | 10 +++++----- .../src/googlesql/query-builders/select.types.ts | 4 ++-- drizzle-orm/src/googlesql/query-builders/update.ts | 6 +++--- 31 files changed, 46 insertions(+), 46 deletions(-) diff --git a/drizzle-orm/src/googlesql/columns/bigint.ts b/drizzle-orm/src/googlesql/columns/bigint.ts index 0973a13461..d5b6c0bf29 100644 --- a/drizzle-orm/src/googlesql/columns/bigint.ts +++ b/drizzle-orm/src/googlesql/columns/bigint.ts @@ -1,7 +1,7 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import type { AnyMySqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig } from '~/utils.ts'; import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; diff --git a/drizzle-orm/src/googlesql/columns/binary.ts b/drizzle-orm/src/googlesql/columns/binary.ts index e670066536..849c565682 100644 --- a/drizzle-orm/src/googlesql/columns/binary.ts +++ b/drizzle-orm/src/googlesql/columns/binary.ts @@ -1,7 +1,7 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import type { AnyMySqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig } from '~/utils.ts'; import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; diff --git a/drizzle-orm/src/googlesql/columns/boolean.ts b/drizzle-orm/src/googlesql/columns/boolean.ts index 2057496b6b..042eb61ee4 100644 --- a/drizzle-orm/src/googlesql/columns/boolean.ts +++ b/drizzle-orm/src/googlesql/columns/boolean.ts @@ -1,7 +1,7 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import type { AnyMySqlTable } from '~/googlesql/table.ts'; import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; export type MySqlBooleanBuilderInitial = MySqlBooleanBuilder<{ diff --git a/drizzle-orm/src/googlesql/columns/char.ts b/drizzle-orm/src/googlesql/columns/char.ts index 55743a5d4a..8d248eae7c 100644 --- a/drizzle-orm/src/googlesql/columns/char.ts +++ b/drizzle-orm/src/googlesql/columns/char.ts @@ -1,7 +1,7 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import type { AnyMySqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig, type Writable } from '~/utils.ts'; import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; diff --git a/drizzle-orm/src/googlesql/columns/common.ts b/drizzle-orm/src/googlesql/columns/common.ts index 289c420ae7..f8172f2e74 100644 --- a/drizzle-orm/src/googlesql/columns/common.ts +++ b/drizzle-orm/src/googlesql/columns/common.ts @@ -13,9 +13,9 @@ import type { import type { ColumnBaseConfig } from '~/column.ts'; import { Column } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { ForeignKey, UpdateDeleteAction } from '~/mysql-core/foreign-keys.ts'; -import { ForeignKeyBuilder } from '~/mysql-core/foreign-keys.ts'; -import type { AnyMySqlTable, MySqlTable } from '~/mysql-core/table.ts'; +import type { ForeignKey, UpdateDeleteAction } from '~/googlesql/foreign-keys.ts'; +import { ForeignKeyBuilder } from '~/googlesql/foreign-keys.ts'; +import type { AnyMySqlTable, MySqlTable } from '~/googlesql/table.ts'; import type { SQL } from '~/sql/sql.ts'; import type { Update } from '~/utils.ts'; import { uniqueKeyName } from '../unique-constraint.ts'; diff --git a/drizzle-orm/src/googlesql/columns/custom.ts b/drizzle-orm/src/googlesql/columns/custom.ts index 50585bece1..ca0d64ae1f 100644 --- a/drizzle-orm/src/googlesql/columns/custom.ts +++ b/drizzle-orm/src/googlesql/columns/custom.ts @@ -1,7 +1,7 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import type { AnyMySqlTable } from '~/googlesql/table.ts'; import type { SQL } from '~/sql/sql.ts'; import { type Equal, getColumnNameAndConfig } from '~/utils.ts'; import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; diff --git a/drizzle-orm/src/googlesql/columns/date.ts b/drizzle-orm/src/googlesql/columns/date.ts index f3797ee6e7..935758141b 100644 --- a/drizzle-orm/src/googlesql/columns/date.ts +++ b/drizzle-orm/src/googlesql/columns/date.ts @@ -1,7 +1,7 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import type { AnyMySqlTable } from '~/googlesql/table.ts'; import { type Equal, getColumnNameAndConfig } from '~/utils.ts'; import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; diff --git a/drizzle-orm/src/googlesql/columns/datetime.ts b/drizzle-orm/src/googlesql/columns/datetime.ts index ea5b917b92..5bca606349 100644 --- a/drizzle-orm/src/googlesql/columns/datetime.ts +++ b/drizzle-orm/src/googlesql/columns/datetime.ts @@ -1,7 +1,7 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import type { AnyMySqlTable } from '~/googlesql/table.ts'; import { type Equal, getColumnNameAndConfig } from '~/utils.ts'; import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; diff --git a/drizzle-orm/src/googlesql/columns/decimal.ts b/drizzle-orm/src/googlesql/columns/decimal.ts index 76b0ba8a10..df4eb101ba 100644 --- a/drizzle-orm/src/googlesql/columns/decimal.ts +++ b/drizzle-orm/src/googlesql/columns/decimal.ts @@ -1,7 +1,7 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import type { AnyMySqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig } from '~/utils.ts'; import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; diff --git a/drizzle-orm/src/googlesql/columns/double.ts b/drizzle-orm/src/googlesql/columns/double.ts index bc23fc74c0..8a1286ffc3 100644 --- a/drizzle-orm/src/googlesql/columns/double.ts +++ b/drizzle-orm/src/googlesql/columns/double.ts @@ -1,7 +1,7 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import type { AnyMySqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig } from '~/utils.ts'; import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; diff --git a/drizzle-orm/src/googlesql/columns/enum.ts b/drizzle-orm/src/googlesql/columns/enum.ts index 384e07d170..88833dd905 100644 --- a/drizzle-orm/src/googlesql/columns/enum.ts +++ b/drizzle-orm/src/googlesql/columns/enum.ts @@ -1,7 +1,7 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import type { AnyMySqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig, type Writable } from '~/utils.ts'; import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; diff --git a/drizzle-orm/src/googlesql/columns/float.ts b/drizzle-orm/src/googlesql/columns/float.ts index e368740a0e..1d3ee5af02 100644 --- a/drizzle-orm/src/googlesql/columns/float.ts +++ b/drizzle-orm/src/googlesql/columns/float.ts @@ -1,7 +1,7 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import type { AnyMySqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig } from '~/utils.ts'; import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; diff --git a/drizzle-orm/src/googlesql/columns/int.ts b/drizzle-orm/src/googlesql/columns/int.ts index 79b93bdf75..b5b15cef47 100644 --- a/drizzle-orm/src/googlesql/columns/int.ts +++ b/drizzle-orm/src/googlesql/columns/int.ts @@ -1,7 +1,7 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import type { AnyMySqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig } from '~/utils.ts'; import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; diff --git a/drizzle-orm/src/googlesql/columns/json.ts b/drizzle-orm/src/googlesql/columns/json.ts index 12d11bd4a5..b84def318a 100644 --- a/drizzle-orm/src/googlesql/columns/json.ts +++ b/drizzle-orm/src/googlesql/columns/json.ts @@ -1,7 +1,7 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import type { AnyMySqlTable } from '~/googlesql/table.ts'; import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; export type MySqlJsonBuilderInitial = MySqlJsonBuilder<{ diff --git a/drizzle-orm/src/googlesql/columns/mediumint.ts b/drizzle-orm/src/googlesql/columns/mediumint.ts index 7ba5cc9449..4dad3568a6 100644 --- a/drizzle-orm/src/googlesql/columns/mediumint.ts +++ b/drizzle-orm/src/googlesql/columns/mediumint.ts @@ -1,7 +1,7 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import type { AnyMySqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig } from '~/utils.ts'; import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; import type { MySqlIntConfig } from './int.ts'; diff --git a/drizzle-orm/src/googlesql/columns/real.ts b/drizzle-orm/src/googlesql/columns/real.ts index c6b4473108..72e39e2525 100644 --- a/drizzle-orm/src/googlesql/columns/real.ts +++ b/drizzle-orm/src/googlesql/columns/real.ts @@ -1,7 +1,7 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import type { AnyMySqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig } from '~/utils.ts'; import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; diff --git a/drizzle-orm/src/googlesql/columns/serial.ts b/drizzle-orm/src/googlesql/columns/serial.ts index 90fd7a2e5e..4753658eaf 100644 --- a/drizzle-orm/src/googlesql/columns/serial.ts +++ b/drizzle-orm/src/googlesql/columns/serial.ts @@ -9,7 +9,7 @@ import type { } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import type { AnyMySqlTable } from '~/googlesql/table.ts'; import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; export type MySqlSerialBuilderInitial = IsAutoincrement< diff --git a/drizzle-orm/src/googlesql/columns/smallint.ts b/drizzle-orm/src/googlesql/columns/smallint.ts index 87083f0fab..97026f114f 100644 --- a/drizzle-orm/src/googlesql/columns/smallint.ts +++ b/drizzle-orm/src/googlesql/columns/smallint.ts @@ -1,7 +1,7 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import type { AnyMySqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig } from '~/utils.ts'; import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; import type { MySqlIntConfig } from './int.ts'; diff --git a/drizzle-orm/src/googlesql/columns/text.ts b/drizzle-orm/src/googlesql/columns/text.ts index 6106fd45bf..d8f578e8fc 100644 --- a/drizzle-orm/src/googlesql/columns/text.ts +++ b/drizzle-orm/src/googlesql/columns/text.ts @@ -1,7 +1,7 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import type { AnyMySqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig, type Writable } from '~/utils.ts'; import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; diff --git a/drizzle-orm/src/googlesql/columns/time.ts b/drizzle-orm/src/googlesql/columns/time.ts index 7ca5426ec5..51e9c18972 100644 --- a/drizzle-orm/src/googlesql/columns/time.ts +++ b/drizzle-orm/src/googlesql/columns/time.ts @@ -1,7 +1,7 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import type { AnyMySqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig } from '~/utils.ts'; import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; diff --git a/drizzle-orm/src/googlesql/columns/timestamp.ts b/drizzle-orm/src/googlesql/columns/timestamp.ts index 2ccc2925f4..5bdd451304 100644 --- a/drizzle-orm/src/googlesql/columns/timestamp.ts +++ b/drizzle-orm/src/googlesql/columns/timestamp.ts @@ -1,7 +1,7 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import type { AnyMySqlTable } from '~/googlesql/table.ts'; import { type Equal, getColumnNameAndConfig } from '~/utils.ts'; import { MySqlDateBaseColumn, MySqlDateColumnBaseBuilder } from './date.common.ts'; diff --git a/drizzle-orm/src/googlesql/columns/tinyint.ts b/drizzle-orm/src/googlesql/columns/tinyint.ts index 890f169bd4..a7de703e1e 100644 --- a/drizzle-orm/src/googlesql/columns/tinyint.ts +++ b/drizzle-orm/src/googlesql/columns/tinyint.ts @@ -1,7 +1,7 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import type { AnyMySqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig } from '~/utils.ts'; import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; import type { MySqlIntConfig } from './int.ts'; diff --git a/drizzle-orm/src/googlesql/columns/varbinary.ts b/drizzle-orm/src/googlesql/columns/varbinary.ts index 837de8dcbe..1dfffd3c1d 100644 --- a/drizzle-orm/src/googlesql/columns/varbinary.ts +++ b/drizzle-orm/src/googlesql/columns/varbinary.ts @@ -1,7 +1,7 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import type { AnyMySqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig } from '~/utils.ts'; import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; diff --git a/drizzle-orm/src/googlesql/columns/varchar.ts b/drizzle-orm/src/googlesql/columns/varchar.ts index 0a0bde8574..ad722fb9a9 100644 --- a/drizzle-orm/src/googlesql/columns/varchar.ts +++ b/drizzle-orm/src/googlesql/columns/varchar.ts @@ -1,7 +1,7 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import type { AnyMySqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig, type Writable } from '~/utils.ts'; import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; diff --git a/drizzle-orm/src/googlesql/columns/year.ts b/drizzle-orm/src/googlesql/columns/year.ts index 4e4ae4faf4..bac330234d 100644 --- a/drizzle-orm/src/googlesql/columns/year.ts +++ b/drizzle-orm/src/googlesql/columns/year.ts @@ -1,7 +1,7 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/mysql-core/table.ts'; +import type { AnyMySqlTable } from '~/googlesql/table.ts'; import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; export type MySqlYearBuilderInitial = MySqlYearBuilder<{ diff --git a/drizzle-orm/src/googlesql/query-builders/delete.ts b/drizzle-orm/src/googlesql/query-builders/delete.ts index 22a3e1be36..d102e3b528 100644 --- a/drizzle-orm/src/googlesql/query-builders/delete.ts +++ b/drizzle-orm/src/googlesql/query-builders/delete.ts @@ -1,5 +1,5 @@ import { entityKind } from '~/entity.ts'; -import type { MySqlDialect } from '~/mysql-core/dialect.ts'; +import type { MySqlDialect } from '~/googlesql/dialect.ts'; import type { AnyMySqlQueryResultHKT, MySqlPreparedQueryConfig, @@ -8,8 +8,8 @@ import type { MySqlSession, PreparedQueryHKTBase, PreparedQueryKind, -} from '~/mysql-core/session.ts'; -import type { MySqlTable } from '~/mysql-core/table.ts'; +} from '~/googlesql/session.ts'; +import type { MySqlTable } from '~/googlesql/table.ts'; import { QueryPromise } from '~/query-promise.ts'; import { SelectionProxyHandler } from '~/selection-proxy.ts'; import type { Placeholder, Query, SQL, SQLWrapper } from '~/sql/sql.ts'; diff --git a/drizzle-orm/src/googlesql/query-builders/insert.ts b/drizzle-orm/src/googlesql/query-builders/insert.ts index f943d03229..09a8b31e62 100644 --- a/drizzle-orm/src/googlesql/query-builders/insert.ts +++ b/drizzle-orm/src/googlesql/query-builders/insert.ts @@ -1,5 +1,5 @@ import { entityKind, is } from '~/entity.ts'; -import type { MySqlDialect } from '~/mysql-core/dialect.ts'; +import type { MySqlDialect } from '~/googlesql/dialect.ts'; import type { AnyMySqlQueryResultHKT, MySqlPreparedQueryConfig, @@ -8,8 +8,8 @@ import type { MySqlSession, PreparedQueryHKTBase, PreparedQueryKind, -} from '~/mysql-core/session.ts'; -import type { MySqlTable } from '~/mysql-core/table.ts'; +} from '~/googlesql/session.ts'; +import type { MySqlTable } from '~/googlesql/table.ts'; import type { TypedQueryBuilder } from '~/query-builders/query-builder.ts'; import { QueryPromise } from '~/query-promise.ts'; import type { RunnableQuery } from '~/runnable-query.ts'; diff --git a/drizzle-orm/src/googlesql/query-builders/query-builder.ts b/drizzle-orm/src/googlesql/query-builders/query-builder.ts index 5c144d48fb..0210215705 100644 --- a/drizzle-orm/src/googlesql/query-builders/query-builder.ts +++ b/drizzle-orm/src/googlesql/query-builders/query-builder.ts @@ -1,7 +1,7 @@ import { entityKind, is } from '~/entity.ts'; -import type { MySqlDialectConfig } from '~/mysql-core/dialect.ts'; -import { MySqlDialect } from '~/mysql-core/dialect.ts'; -import type { WithBuilder } from '~/mysql-core/subquery.ts'; +import type { MySqlDialectConfig } from '~/googlesql/dialect.ts'; +import { MySqlDialect } from '~/googlesql/dialect.ts'; +import type { WithBuilder } from '~/googlesql/subquery.ts'; import type { TypedQueryBuilder } from '~/query-builders/query-builder.ts'; import { SelectionProxyHandler } from '~/selection-proxy.ts'; import type { ColumnsSelection, SQL } from '~/sql/sql.ts'; diff --git a/drizzle-orm/src/googlesql/query-builders/select.ts b/drizzle-orm/src/googlesql/query-builders/select.ts index 821199ab43..a321b6b09f 100644 --- a/drizzle-orm/src/googlesql/query-builders/select.ts +++ b/drizzle-orm/src/googlesql/query-builders/select.ts @@ -1,9 +1,9 @@ import { entityKind, is } from '~/entity.ts'; -import type { MySqlColumn } from '~/mysql-core/columns/index.ts'; -import type { MySqlDialect } from '~/mysql-core/dialect.ts'; -import type { MySqlPreparedQueryConfig, MySqlSession, PreparedQueryHKTBase } from '~/mysql-core/session.ts'; -import type { SubqueryWithSelection } from '~/mysql-core/subquery.ts'; -import { MySqlTable } from '~/mysql-core/table.ts'; +import type { MySqlColumn } from '~/googlesql/columns/index.ts'; +import type { MySqlDialect } from '~/googlesql/dialect.ts'; +import type { MySqlPreparedQueryConfig, MySqlSession, PreparedQueryHKTBase } from '~/googlesql/session.ts'; +import type { SubqueryWithSelection } from '~/googlesql/subquery.ts'; +import { MySqlTable } from '~/googlesql/table.ts'; import { TypedQueryBuilder } from '~/query-builders/query-builder.ts'; import type { BuildSubquerySelection, diff --git a/drizzle-orm/src/googlesql/query-builders/select.types.ts b/drizzle-orm/src/googlesql/query-builders/select.types.ts index 4b0f97d3a1..55b64fe026 100644 --- a/drizzle-orm/src/googlesql/query-builders/select.types.ts +++ b/drizzle-orm/src/googlesql/query-builders/select.types.ts @@ -1,5 +1,5 @@ -import type { MySqlColumn } from '~/mysql-core/columns/index.ts'; -import type { MySqlTable, MySqlTableWithColumns } from '~/mysql-core/table.ts'; +import type { MySqlColumn } from '~/googlesql/columns/index.ts'; +import type { MySqlTable, MySqlTableWithColumns } from '~/googlesql/table.ts'; import type { SelectedFields as SelectedFieldsBase, SelectedFieldsFlat as SelectedFieldsFlatBase, diff --git a/drizzle-orm/src/googlesql/query-builders/update.ts b/drizzle-orm/src/googlesql/query-builders/update.ts index 7c6fd40abb..09ff3e33a0 100644 --- a/drizzle-orm/src/googlesql/query-builders/update.ts +++ b/drizzle-orm/src/googlesql/query-builders/update.ts @@ -1,6 +1,6 @@ import type { GetColumnData } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { MySqlDialect } from '~/mysql-core/dialect.ts'; +import type { MySqlDialect } from '~/googlesql/dialect.ts'; import type { AnyMySqlQueryResultHKT, MySqlPreparedQueryConfig, @@ -9,8 +9,8 @@ import type { MySqlSession, PreparedQueryHKTBase, PreparedQueryKind, -} from '~/mysql-core/session.ts'; -import type { MySqlTable } from '~/mysql-core/table.ts'; +} from '~/googlesql/session.ts'; +import type { MySqlTable } from '~/googlesql/table.ts'; import { QueryPromise } from '~/query-promise.ts'; import { SelectionProxyHandler } from '~/selection-proxy.ts'; import type { Placeholder, Query, SQL, SQLWrapper } from '~/sql/sql.ts'; From 73a1c46d98afdb860c9ff9b0bb9f951206d11211 Mon Sep 17 00:00:00 2001 From: Gabriel Cipriano Date: Wed, 26 Feb 2025 14:55:39 +0100 Subject: [PATCH 3/7] chore: full renaming --- drizzle-orm/src/googlesql/alias.ts | 6 +- drizzle-orm/src/googlesql/checks.ts | 12 +- drizzle-orm/src/googlesql/columns/all.ts | 8 +- drizzle-orm/src/googlesql/columns/bigint.ts | 74 +++---- drizzle-orm/src/googlesql/columns/binary.ts | 46 ++-- drizzle-orm/src/googlesql/columns/boolean.ts | 32 +-- drizzle-orm/src/googlesql/columns/char.ts | 54 ++--- drizzle-orm/src/googlesql/columns/common.ts | 52 ++--- drizzle-orm/src/googlesql/columns/custom.ts | 48 ++-- .../src/googlesql/columns/date.common.ts | 16 +- drizzle-orm/src/googlesql/columns/date.ts | 78 +++---- drizzle-orm/src/googlesql/columns/datetime.ts | 84 +++---- drizzle-orm/src/googlesql/columns/decimal.ts | 50 ++--- drizzle-orm/src/googlesql/columns/double.ts | 48 ++-- drizzle-orm/src/googlesql/columns/enum.ts | 42 ++-- drizzle-orm/src/googlesql/columns/float.ts | 48 ++-- drizzle-orm/src/googlesql/columns/int.ts | 48 ++-- drizzle-orm/src/googlesql/columns/json.ts | 30 +-- .../src/googlesql/columns/mediumint.ts | 48 ++-- drizzle-orm/src/googlesql/columns/real.ts | 50 ++--- drizzle-orm/src/googlesql/columns/serial.ts | 38 ++-- drizzle-orm/src/googlesql/columns/smallint.ts | 48 ++-- drizzle-orm/src/googlesql/columns/text.ts | 100 ++++----- drizzle-orm/src/googlesql/columns/time.ts | 36 +-- .../src/googlesql/columns/timestamp.ts | 84 +++---- drizzle-orm/src/googlesql/columns/tinyint.ts | 48 ++-- .../src/googlesql/columns/varbinary.ts | 48 ++-- drizzle-orm/src/googlesql/columns/varchar.ts | 50 ++--- drizzle-orm/src/googlesql/columns/year.ts | 34 +-- drizzle-orm/src/googlesql/db.ts | 112 +++++----- drizzle-orm/src/googlesql/dialect.ts | 116 +++++----- drizzle-orm/src/googlesql/expressions.ts | 6 +- drizzle-orm/src/googlesql/foreign-keys.ts | 38 ++-- drizzle-orm/src/googlesql/indexes.ts | 22 +- drizzle-orm/src/googlesql/primary-keys.ts | 26 +-- .../src/googlesql/query-builders/count.ts | 24 +- .../src/googlesql/query-builders/delete.ts | 94 ++++---- .../src/googlesql/query-builders/insert.ts | 156 ++++++------- .../googlesql/query-builders/query-builder.ts | 52 ++--- .../src/googlesql/query-builders/query.ts | 38 ++-- .../src/googlesql/query-builders/select.ts | 206 +++++++++--------- .../googlesql/query-builders/select.types.ts | 170 +++++++-------- .../src/googlesql/query-builders/update.ts | 112 +++++----- drizzle-orm/src/googlesql/schema.ts | 32 +-- drizzle-orm/src/googlesql/session.ts | 68 +++--- drizzle-orm/src/googlesql/subquery.ts | 8 +- drizzle-orm/src/googlesql/table.ts | 130 +++++------ .../src/googlesql/unique-constraint.ts | 24 +- drizzle-orm/src/googlesql/utils.ts | 20 +- drizzle-orm/src/googlesql/view-base.ts | 6 +- drizzle-orm/src/googlesql/view-common.ts | 2 +- drizzle-orm/src/googlesql/view.ts | 78 +++---- 52 files changed, 1450 insertions(+), 1450 deletions(-) diff --git a/drizzle-orm/src/googlesql/alias.ts b/drizzle-orm/src/googlesql/alias.ts index 8320c5533d..6807e808f5 100644 --- a/drizzle-orm/src/googlesql/alias.ts +++ b/drizzle-orm/src/googlesql/alias.ts @@ -1,9 +1,9 @@ import { TableAliasProxyHandler } from '~/alias.ts'; import type { BuildAliasTable } from './query-builders/select.types.ts'; -import type { MySqlTable } from './table.ts'; -import type { MySqlViewBase } from './view-base.ts'; +import type { GoogleSqlTable } from './table.ts'; +import type { GoogleSqlViewBase } from './view-base.ts'; -export function alias( +export function alias( table: TTable, alias: TAlias, ): BuildAliasTable { diff --git a/drizzle-orm/src/googlesql/checks.ts b/drizzle-orm/src/googlesql/checks.ts index af9a29f6ae..d96cb9564b 100644 --- a/drizzle-orm/src/googlesql/checks.ts +++ b/drizzle-orm/src/googlesql/checks.ts @@ -1,27 +1,27 @@ import { entityKind } from '~/entity.ts'; import type { SQL } from '~/sql/sql.ts'; -import type { MySqlTable } from './table.ts'; +import type { GoogleSqlTable } from './table.ts'; export class CheckBuilder { - static readonly [entityKind]: string = 'MySqlCheckBuilder'; + static readonly [entityKind]: string = 'GoogleSqlCheckBuilder'; - protected brand!: 'MySqlConstraintBuilder'; + protected brand!: 'GoogleSqlConstraintBuilder'; constructor(public name: string, public value: SQL) {} /** @internal */ - build(table: MySqlTable): Check { + build(table: GoogleSqlTable): Check { return new Check(table, this); } } export class Check { - static readonly [entityKind]: string = 'MySqlCheck'; + static readonly [entityKind]: string = 'GoogleSqlCheck'; readonly name: string; readonly value: SQL; - constructor(public table: MySqlTable, builder: CheckBuilder) { + constructor(public table: GoogleSqlTable, builder: CheckBuilder) { this.name = builder.name; this.value = builder.value; } diff --git a/drizzle-orm/src/googlesql/columns/all.ts b/drizzle-orm/src/googlesql/columns/all.ts index 44c03eff0c..cf14d2e97c 100644 --- a/drizzle-orm/src/googlesql/columns/all.ts +++ b/drizzle-orm/src/googlesql/columns/all.ts @@ -7,7 +7,7 @@ import { date } from './date.ts'; import { datetime } from './datetime.ts'; import { decimal } from './decimal.ts'; import { double } from './double.ts'; -import { mysqlEnum } from './enum.ts'; +import { googlesqlEnum } from './enum.ts'; import { float } from './float.ts'; import { int } from './int.ts'; import { json } from './json.ts'; @@ -23,7 +23,7 @@ import { varbinary } from './varbinary.ts'; import { varchar } from './varchar.ts'; import { year } from './year.ts'; -export function getMySqlColumnBuilders() { +export function getGoogleSqlColumnBuilders() { return { bigint, binary, @@ -34,7 +34,7 @@ export function getMySqlColumnBuilders() { datetime, decimal, double, - mysqlEnum, + googlesqlEnum, float, int, json, @@ -55,4 +55,4 @@ export function getMySqlColumnBuilders() { }; } -export type MySqlColumnBuilders = ReturnType; +export type GoogleSqlColumnBuilders = ReturnType; diff --git a/drizzle-orm/src/googlesql/columns/bigint.ts b/drizzle-orm/src/googlesql/columns/bigint.ts index d5b6c0bf29..8e21469ccb 100644 --- a/drizzle-orm/src/googlesql/columns/bigint.ts +++ b/drizzle-orm/src/googlesql/columns/bigint.ts @@ -1,44 +1,44 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/googlesql/table.ts'; +import type { AnyGoogleSqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig } from '~/utils.ts'; -import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; +import { GoogleSqlColumnBuilderWithAutoIncrement, GoogleSqlColumnWithAutoIncrement } from './common.ts'; -export type MySqlBigInt53BuilderInitial = MySqlBigInt53Builder<{ +export type GoogleSqlBigInt53BuilderInitial = GoogleSqlBigInt53Builder<{ name: TName; dataType: 'number'; - columnType: 'MySqlBigInt53'; + columnType: 'GoogleSqlBigInt53'; data: number; driverParam: number | string; enumValues: undefined; }>; -export class MySqlBigInt53Builder> - extends MySqlColumnBuilderWithAutoIncrement +export class GoogleSqlBigInt53Builder> + extends GoogleSqlColumnBuilderWithAutoIncrement { - static override readonly [entityKind]: string = 'MySqlBigInt53Builder'; + static override readonly [entityKind]: string = 'GoogleSqlBigInt53Builder'; constructor(name: T['name'], unsigned: boolean = false) { - super(name, 'number', 'MySqlBigInt53'); + super(name, 'number', 'GoogleSqlBigInt53'); this.config.unsigned = unsigned; } /** @internal */ override build( - table: AnyMySqlTable<{ name: TTableName }>, - ): MySqlBigInt53> { - return new MySqlBigInt53>( + table: AnyGoogleSqlTable<{ name: TTableName }>, + ): GoogleSqlBigInt53> { + return new GoogleSqlBigInt53>( table, this.config as ColumnBuilderRuntimeConfig, ); } } -export class MySqlBigInt53> - extends MySqlColumnWithAutoIncrement +export class GoogleSqlBigInt53> + extends GoogleSqlColumnWithAutoIncrement { - static override readonly [entityKind]: string = 'MySqlBigInt53'; + static override readonly [entityKind]: string = 'GoogleSqlBigInt53'; getSQLType(): string { return `bigint${this.config.unsigned ? ' unsigned' : ''}`; @@ -52,40 +52,40 @@ export class MySqlBigInt53 } } -export type MySqlBigInt64BuilderInitial = MySqlBigInt64Builder<{ +export type GoogleSqlBigInt64BuilderInitial = GoogleSqlBigInt64Builder<{ name: TName; dataType: 'bigint'; - columnType: 'MySqlBigInt64'; + columnType: 'GoogleSqlBigInt64'; data: bigint; driverParam: string; enumValues: undefined; }>; -export class MySqlBigInt64Builder> - extends MySqlColumnBuilderWithAutoIncrement +export class GoogleSqlBigInt64Builder> + extends GoogleSqlColumnBuilderWithAutoIncrement { - static override readonly [entityKind]: string = 'MySqlBigInt64Builder'; + static override readonly [entityKind]: string = 'GoogleSqlBigInt64Builder'; constructor(name: T['name'], unsigned: boolean = false) { - super(name, 'bigint', 'MySqlBigInt64'); + super(name, 'bigint', 'GoogleSqlBigInt64'); this.config.unsigned = unsigned; } /** @internal */ override build( - table: AnyMySqlTable<{ name: TTableName }>, - ): MySqlBigInt64> { - return new MySqlBigInt64>( + table: AnyGoogleSqlTable<{ name: TTableName }>, + ): GoogleSqlBigInt64> { + return new GoogleSqlBigInt64>( table, this.config as ColumnBuilderRuntimeConfig, ); } } -export class MySqlBigInt64> - extends MySqlColumnWithAutoIncrement +export class GoogleSqlBigInt64> + extends GoogleSqlColumnWithAutoIncrement { - static override readonly [entityKind]: string = 'MySqlBigInt64'; + static override readonly [entityKind]: string = 'GoogleSqlBigInt64'; getSQLType(): string { return `bigint${this.config.unsigned ? ' unsigned' : ''}`; @@ -97,22 +97,22 @@ export class MySqlBigInt64 } } -export interface MySqlBigIntConfig { +export interface GoogleSqlBigIntConfig { mode: T; unsigned?: boolean; } -export function bigint( - config: MySqlBigIntConfig, -): TMode extends 'number' ? MySqlBigInt53BuilderInitial<''> : MySqlBigInt64BuilderInitial<''>; -export function bigint( +export function bigint( + config: GoogleSqlBigIntConfig, +): TMode extends 'number' ? GoogleSqlBigInt53BuilderInitial<''> : GoogleSqlBigInt64BuilderInitial<''>; +export function bigint( name: TName, - config: MySqlBigIntConfig, -): TMode extends 'number' ? MySqlBigInt53BuilderInitial : MySqlBigInt64BuilderInitial; -export function bigint(a?: string | MySqlBigIntConfig, b?: MySqlBigIntConfig) { - const { name, config } = getColumnNameAndConfig(a, b); + config: GoogleSqlBigIntConfig, +): TMode extends 'number' ? GoogleSqlBigInt53BuilderInitial : GoogleSqlBigInt64BuilderInitial; +export function bigint(a?: string | GoogleSqlBigIntConfig, b?: GoogleSqlBigIntConfig) { + const { name, config } = getColumnNameAndConfig(a, b); if (config.mode === 'number') { - return new MySqlBigInt53Builder(name, config.unsigned); + return new GoogleSqlBigInt53Builder(name, config.unsigned); } - return new MySqlBigInt64Builder(name, config.unsigned); + return new GoogleSqlBigInt64Builder(name, config.unsigned); } diff --git a/drizzle-orm/src/googlesql/columns/binary.ts b/drizzle-orm/src/googlesql/columns/binary.ts index 849c565682..b3b3cd9979 100644 --- a/drizzle-orm/src/googlesql/columns/binary.ts +++ b/drizzle-orm/src/googlesql/columns/binary.ts @@ -1,43 +1,43 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/googlesql/table.ts'; +import type { AnyGoogleSqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig } from '~/utils.ts'; -import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; +import { GoogleSqlColumn, GoogleSqlColumnBuilder } from './common.ts'; -export type MySqlBinaryBuilderInitial = MySqlBinaryBuilder<{ +export type GoogleSqlBinaryBuilderInitial = GoogleSqlBinaryBuilder<{ name: TName; dataType: 'string'; - columnType: 'MySqlBinary'; + columnType: 'GoogleSqlBinary'; data: string; driverParam: string; enumValues: undefined; }>; -export class MySqlBinaryBuilder> extends MySqlColumnBuilder< +export class GoogleSqlBinaryBuilder> extends GoogleSqlColumnBuilder< T, - MySqlBinaryConfig + GoogleSqlBinaryConfig > { - static override readonly [entityKind]: string = 'MySqlBinaryBuilder'; + static override readonly [entityKind]: string = 'GoogleSqlBinaryBuilder'; constructor(name: T['name'], length: number | undefined) { - super(name, 'string', 'MySqlBinary'); + super(name, 'string', 'GoogleSqlBinary'); this.config.length = length; } /** @internal */ override build( - table: AnyMySqlTable<{ name: TTableName }>, - ): MySqlBinary> { - return new MySqlBinary>(table, this.config as ColumnBuilderRuntimeConfig); + table: AnyGoogleSqlTable<{ name: TTableName }>, + ): GoogleSqlBinary> { + return new GoogleSqlBinary>(table, this.config as ColumnBuilderRuntimeConfig); } } -export class MySqlBinary> extends MySqlColumn< +export class GoogleSqlBinary> extends GoogleSqlColumn< T, - MySqlBinaryConfig + GoogleSqlBinaryConfig > { - static override readonly [entityKind]: string = 'MySqlBinary'; + static override readonly [entityKind]: string = 'GoogleSqlBinary'; length: number | undefined = this.config.length; @@ -46,19 +46,19 @@ export class MySqlBinary> ex } } -export interface MySqlBinaryConfig { +export interface GoogleSqlBinaryConfig { length?: number; } -export function binary(): MySqlBinaryBuilderInitial<''>; +export function binary(): GoogleSqlBinaryBuilderInitial<''>; export function binary( - config?: MySqlBinaryConfig, -): MySqlBinaryBuilderInitial<''>; + config?: GoogleSqlBinaryConfig, +): GoogleSqlBinaryBuilderInitial<''>; export function binary( name: TName, - config?: MySqlBinaryConfig, -): MySqlBinaryBuilderInitial; -export function binary(a?: string | MySqlBinaryConfig, b: MySqlBinaryConfig = {}) { - const { name, config } = getColumnNameAndConfig(a, b); - return new MySqlBinaryBuilder(name, config.length); + config?: GoogleSqlBinaryConfig, +): GoogleSqlBinaryBuilderInitial; +export function binary(a?: string | GoogleSqlBinaryConfig, b: GoogleSqlBinaryConfig = {}) { + const { name, config } = getColumnNameAndConfig(a, b); + return new GoogleSqlBinaryBuilder(name, config.length); } diff --git a/drizzle-orm/src/googlesql/columns/boolean.ts b/drizzle-orm/src/googlesql/columns/boolean.ts index 042eb61ee4..7f75796ff9 100644 --- a/drizzle-orm/src/googlesql/columns/boolean.ts +++ b/drizzle-orm/src/googlesql/columns/boolean.ts @@ -1,40 +1,40 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/googlesql/table.ts'; -import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; +import type { AnyGoogleSqlTable } from '~/googlesql/table.ts'; +import { GoogleSqlColumn, GoogleSqlColumnBuilder } from './common.ts'; -export type MySqlBooleanBuilderInitial = MySqlBooleanBuilder<{ +export type GoogleSqlBooleanBuilderInitial = GoogleSqlBooleanBuilder<{ name: TName; dataType: 'boolean'; - columnType: 'MySqlBoolean'; + columnType: 'GoogleSqlBoolean'; data: boolean; driverParam: number | boolean; enumValues: undefined; }>; -export class MySqlBooleanBuilder> - extends MySqlColumnBuilder +export class GoogleSqlBooleanBuilder> + extends GoogleSqlColumnBuilder { - static override readonly [entityKind]: string = 'MySqlBooleanBuilder'; + static override readonly [entityKind]: string = 'GoogleSqlBooleanBuilder'; constructor(name: T['name']) { - super(name, 'boolean', 'MySqlBoolean'); + super(name, 'boolean', 'GoogleSqlBoolean'); } /** @internal */ override build( - table: AnyMySqlTable<{ name: TTableName }>, - ): MySqlBoolean> { - return new MySqlBoolean>( + table: AnyGoogleSqlTable<{ name: TTableName }>, + ): GoogleSqlBoolean> { + return new GoogleSqlBoolean>( table, this.config as ColumnBuilderRuntimeConfig, ); } } -export class MySqlBoolean> extends MySqlColumn { - static override readonly [entityKind]: string = 'MySqlBoolean'; +export class GoogleSqlBoolean> extends GoogleSqlColumn { + static override readonly [entityKind]: string = 'GoogleSqlBoolean'; getSQLType(): string { return 'boolean'; @@ -48,8 +48,8 @@ export class MySqlBoolean> } } -export function boolean(): MySqlBooleanBuilderInitial<''>; -export function boolean(name: TName): MySqlBooleanBuilderInitial; +export function boolean(): GoogleSqlBooleanBuilderInitial<''>; +export function boolean(name: TName): GoogleSqlBooleanBuilderInitial; export function boolean(name?: string) { - return new MySqlBooleanBuilder(name ?? ''); + return new GoogleSqlBooleanBuilder(name ?? ''); } diff --git a/drizzle-orm/src/googlesql/columns/char.ts b/drizzle-orm/src/googlesql/columns/char.ts index 8d248eae7c..54749c9ff6 100644 --- a/drizzle-orm/src/googlesql/columns/char.ts +++ b/drizzle-orm/src/googlesql/columns/char.ts @@ -1,54 +1,54 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/googlesql/table.ts'; +import type { AnyGoogleSqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig, type Writable } from '~/utils.ts'; -import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; +import { GoogleSqlColumn, GoogleSqlColumnBuilder } from './common.ts'; -export type MySqlCharBuilderInitial< +export type GoogleSqlCharBuilderInitial< TName extends string, TEnum extends [string, ...string[]], TLength extends number | undefined, -> = MySqlCharBuilder<{ +> = GoogleSqlCharBuilder<{ name: TName; dataType: 'string'; - columnType: 'MySqlChar'; + columnType: 'GoogleSqlChar'; data: TEnum[number]; driverParam: number | string; enumValues: TEnum; length: TLength; }>; -export class MySqlCharBuilder< - T extends ColumnBuilderBaseConfig<'string', 'MySqlChar'> & { length?: number | undefined }, -> extends MySqlColumnBuilder< +export class GoogleSqlCharBuilder< + T extends ColumnBuilderBaseConfig<'string', 'GoogleSqlChar'> & { length?: number | undefined }, +> extends GoogleSqlColumnBuilder< T, - MySqlCharConfig, + GoogleSqlCharConfig, { length: T['length'] } > { - static override readonly [entityKind]: string = 'MySqlCharBuilder'; + static override readonly [entityKind]: string = 'GoogleSqlCharBuilder'; - constructor(name: T['name'], config: MySqlCharConfig) { - super(name, 'string', 'MySqlChar'); + constructor(name: T['name'], config: GoogleSqlCharConfig) { + super(name, 'string', 'GoogleSqlChar'); this.config.length = config.length; this.config.enum = config.enum; } /** @internal */ override build( - table: AnyMySqlTable<{ name: TTableName }>, - ): MySqlChar & { length: T['length']; enumValues: T['enumValues'] }> { - return new MySqlChar & { length: T['length']; enumValues: T['enumValues'] }>( + table: AnyGoogleSqlTable<{ name: TTableName }>, + ): GoogleSqlChar & { length: T['length']; enumValues: T['enumValues'] }> { + return new GoogleSqlChar & { length: T['length']; enumValues: T['enumValues'] }>( table, this.config as ColumnBuilderRuntimeConfig, ); } } -export class MySqlChar & { length?: number | undefined }> - extends MySqlColumn, { length: T['length'] }> +export class GoogleSqlChar & { length?: number | undefined }> + extends GoogleSqlColumn, { length: T['length'] }> { - static override readonly [entityKind]: string = 'MySqlChar'; + static override readonly [entityKind]: string = 'GoogleSqlChar'; readonly length: T['length'] = this.config.length; override readonly enumValues = this.config.enum; @@ -58,7 +58,7 @@ export class MySqlChar & { len } } -export interface MySqlCharConfig< +export interface GoogleSqlCharConfig< TEnum extends readonly string[] | string[] | undefined = readonly string[] | string[] | undefined, TLength extends number | undefined = number | undefined, > { @@ -66,10 +66,10 @@ export interface MySqlCharConfig< length?: TLength; } -export function char(): MySqlCharBuilderInitial<'', [string, ...string[]], undefined>; +export function char(): GoogleSqlCharBuilderInitial<'', [string, ...string[]], undefined>; export function char, L extends number | undefined>( - config?: MySqlCharConfig, L>, -): MySqlCharBuilderInitial<'', Writable, L>; + config?: GoogleSqlCharConfig, L>, +): GoogleSqlCharBuilderInitial<'', Writable, L>; export function char< TName extends string, U extends string, @@ -77,9 +77,9 @@ export function char< L extends number | undefined, >( name: TName, - config?: MySqlCharConfig, L>, -): MySqlCharBuilderInitial, L>; -export function char(a?: string | MySqlCharConfig, b: MySqlCharConfig = {}): any { - const { name, config } = getColumnNameAndConfig(a, b); - return new MySqlCharBuilder(name, config as any); + config?: GoogleSqlCharConfig, L>, +): GoogleSqlCharBuilderInitial, L>; +export function char(a?: string | GoogleSqlCharConfig, b: GoogleSqlCharConfig = {}): any { + const { name, config } = getColumnNameAndConfig(a, b); + return new GoogleSqlCharBuilder(name, config as any); } diff --git a/drizzle-orm/src/googlesql/columns/common.ts b/drizzle-orm/src/googlesql/columns/common.ts index f8172f2e74..041660700d 100644 --- a/drizzle-orm/src/googlesql/columns/common.ts +++ b/drizzle-orm/src/googlesql/columns/common.ts @@ -15,39 +15,39 @@ import { Column } from '~/column.ts'; import { entityKind } from '~/entity.ts'; import type { ForeignKey, UpdateDeleteAction } from '~/googlesql/foreign-keys.ts'; import { ForeignKeyBuilder } from '~/googlesql/foreign-keys.ts'; -import type { AnyMySqlTable, MySqlTable } from '~/googlesql/table.ts'; +import type { AnyGoogleSqlTable, GoogleSqlTable } from '~/googlesql/table.ts'; import type { SQL } from '~/sql/sql.ts'; import type { Update } from '~/utils.ts'; import { uniqueKeyName } from '../unique-constraint.ts'; export interface ReferenceConfig { - ref: () => MySqlColumn; + ref: () => GoogleSqlColumn; actions: { onUpdate?: UpdateDeleteAction; onDelete?: UpdateDeleteAction; }; } -export interface MySqlColumnBuilderBase< +export interface GoogleSqlColumnBuilderBase< T extends ColumnBuilderBaseConfig = ColumnBuilderBaseConfig, TTypeConfig extends object = object, -> extends ColumnBuilderBase {} +> extends ColumnBuilderBase {} -export interface MySqlGeneratedColumnConfig { +export interface GoogleSqlGeneratedColumnConfig { mode?: 'virtual' | 'stored'; } -export abstract class MySqlColumnBuilder< +export abstract class GoogleSqlColumnBuilder< T extends ColumnBuilderBaseConfig = ColumnBuilderBaseConfig & { data: any; }, TRuntimeConfig extends object = object, TTypeConfig extends object = object, TExtraConfig extends ColumnBuilderExtraConfig = ColumnBuilderExtraConfig, -> extends ColumnBuilder - implements MySqlColumnBuilderBase +> extends ColumnBuilder + implements GoogleSqlColumnBuilderBase { - static override readonly [entityKind]: string = 'MySqlColumnBuilder'; + static override readonly [entityKind]: string = 'GoogleSqlColumnBuilder'; private foreignKeyConfigs: ReferenceConfig[] = []; @@ -62,7 +62,7 @@ export abstract class MySqlColumnBuilder< return this; } - generatedAlwaysAs(as: SQL | T['data'] | (() => SQL), config?: MySqlGeneratedColumnConfig): HasGenerated SQL), config?: GoogleSqlGeneratedColumnConfig): HasGenerated { this.config.generated = { @@ -74,7 +74,7 @@ export abstract class MySqlColumnBuilder< } /** @internal */ - buildForeignKeys(column: MySqlColumn, table: MySqlTable): ForeignKey[] { + buildForeignKeys(column: GoogleSqlColumn, table: GoogleSqlTable): ForeignKey[] { return this.foreignKeyConfigs.map(({ ref, actions }) => { return ((ref, actions) => { const builder = new ForeignKeyBuilder(() => { @@ -94,20 +94,20 @@ export abstract class MySqlColumnBuilder< /** @internal */ abstract build( - table: AnyMySqlTable<{ name: TTableName }>, - ): MySqlColumn>; + table: AnyGoogleSqlTable<{ name: TTableName }>, + ): GoogleSqlColumn>; } -// To understand how to use `MySqlColumn` and `AnyMySqlColumn`, see `Column` and `AnyColumn` documentation. -export abstract class MySqlColumn< +// To understand how to use `GoogleSqlColumn` and `AnyGoogleSqlColumn`, see `Column` and `AnyColumn` documentation. +export abstract class GoogleSqlColumn< T extends ColumnBaseConfig = ColumnBaseConfig, TRuntimeConfig extends object = {}, TTypeConfig extends object = {}, -> extends Column { - static override readonly [entityKind]: string = 'MySqlColumn'; +> extends Column { + static override readonly [entityKind]: string = 'GoogleSqlColumn'; constructor( - override readonly table: MySqlTable, + override readonly table: GoogleSqlTable, config: ColumnBuilderRuntimeConfig, ) { if (!config.uniqueName) { @@ -117,20 +117,20 @@ export abstract class MySqlColumn< } } -export type AnyMySqlColumn> = {}> = MySqlColumn< +export type AnyGoogleSqlColumn> = {}> = GoogleSqlColumn< Required, TPartial>> >; -export interface MySqlColumnWithAutoIncrementConfig { +export interface GoogleSqlColumnWithAutoIncrementConfig { autoIncrement: boolean; } -export abstract class MySqlColumnBuilderWithAutoIncrement< +export abstract class GoogleSqlColumnBuilderWithAutoIncrement< T extends ColumnBuilderBaseConfig = ColumnBuilderBaseConfig, TRuntimeConfig extends object = object, TExtraConfig extends ColumnBuilderExtraConfig = ColumnBuilderExtraConfig, -> extends MySqlColumnBuilder { - static override readonly [entityKind]: string = 'MySqlColumnBuilderWithAutoIncrement'; +> extends GoogleSqlColumnBuilder { + static override readonly [entityKind]: string = 'GoogleSqlColumnBuilderWithAutoIncrement'; constructor(name: NonNullable, dataType: T['dataType'], columnType: T['columnType']) { super(name, dataType, columnType); @@ -144,11 +144,11 @@ export abstract class MySqlColumnBuilderWithAutoIncrement< } } -export abstract class MySqlColumnWithAutoIncrement< +export abstract class GoogleSqlColumnWithAutoIncrement< T extends ColumnBaseConfig = ColumnBaseConfig, TRuntimeConfig extends object = object, -> extends MySqlColumn { - static override readonly [entityKind]: string = 'MySqlColumnWithAutoIncrement'; +> extends GoogleSqlColumn { + static override readonly [entityKind]: string = 'GoogleSqlColumnWithAutoIncrement'; readonly autoIncrement: boolean = this.config.autoIncrement; } diff --git a/drizzle-orm/src/googlesql/columns/custom.ts b/drizzle-orm/src/googlesql/columns/custom.ts index ca0d64ae1f..627bbcfd60 100644 --- a/drizzle-orm/src/googlesql/columns/custom.ts +++ b/drizzle-orm/src/googlesql/columns/custom.ts @@ -1,16 +1,16 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/googlesql/table.ts'; +import type { AnyGoogleSqlTable } from '~/googlesql/table.ts'; import type { SQL } from '~/sql/sql.ts'; import { type Equal, getColumnNameAndConfig } from '~/utils.ts'; -import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; +import { GoogleSqlColumn, GoogleSqlColumnBuilder } from './common.ts'; export type ConvertCustomConfig> = & { name: TName; dataType: 'custom'; - columnType: 'MySqlCustomColumn'; + columnType: 'GoogleSqlCustomColumn'; data: T['data']; driverParam: T['driverData']; enumValues: undefined; @@ -18,55 +18,55 @@ export type ConvertCustomConfig> - extends MySqlColumnBuilder< +export class GoogleSqlCustomColumnBuilder> + extends GoogleSqlColumnBuilder< T, { fieldConfig: CustomTypeValues['config']; customTypeParams: CustomTypeParams; }, { - mysqlColumnBuilderBrand: 'MySqlCustomColumnBuilderBrand'; + googlesqlColumnBuilderBrand: 'GoogleSqlCustomColumnBuilderBrand'; } > { - static override readonly [entityKind]: string = 'MySqlCustomColumnBuilder'; + static override readonly [entityKind]: string = 'GoogleSqlCustomColumnBuilder'; constructor( name: T['name'], fieldConfig: CustomTypeValues['config'], customTypeParams: CustomTypeParams, ) { - super(name, 'custom', 'MySqlCustomColumn'); + super(name, 'custom', 'GoogleSqlCustomColumn'); this.config.fieldConfig = fieldConfig; this.config.customTypeParams = customTypeParams; } /** @internal */ build( - table: AnyMySqlTable<{ name: TTableName }>, - ): MySqlCustomColumn> { - return new MySqlCustomColumn>( + table: AnyGoogleSqlTable<{ name: TTableName }>, + ): GoogleSqlCustomColumn> { + return new GoogleSqlCustomColumn>( table, this.config as ColumnBuilderRuntimeConfig, ); } } -export class MySqlCustomColumn> extends MySqlColumn { - static override readonly [entityKind]: string = 'MySqlCustomColumn'; +export class GoogleSqlCustomColumn> extends GoogleSqlColumn { + static override readonly [entityKind]: string = 'GoogleSqlCustomColumn'; private sqlName: string; private mapTo?: (value: T['data']) => T['driverParam']; private mapFrom?: (value: T['driverParam']) => T['data']; constructor( - table: AnyMySqlTable<{ name: T['tableName'] }>, - config: MySqlCustomColumnBuilder['config'], + table: AnyGoogleSqlTable<{ name: T['tableName'] }>, + config: GoogleSqlCustomColumnBuilder['config'], ) { super(table, config); this.sqlName = config.customTypeParams.dataType(config.fieldConfig); @@ -198,35 +198,35 @@ export interface CustomTypeParams { } /** - * Custom mysql database data type generator + * Custom googlesql database data type generator */ export function customType( customTypeParams: CustomTypeParams, ): Equal extends true ? { & T['config']>( fieldConfig: TConfig, - ): MySqlCustomColumnBuilder>; + ): GoogleSqlCustomColumnBuilder>; ( dbName: TName, fieldConfig: T['config'], - ): MySqlCustomColumnBuilder>; + ): GoogleSqlCustomColumnBuilder>; } : { - (): MySqlCustomColumnBuilder>; + (): GoogleSqlCustomColumnBuilder>; & T['config']>( fieldConfig?: TConfig, - ): MySqlCustomColumnBuilder>; + ): GoogleSqlCustomColumnBuilder>; ( dbName: TName, fieldConfig?: T['config'], - ): MySqlCustomColumnBuilder>; + ): GoogleSqlCustomColumnBuilder>; } { return ( a?: TName | T['config'], b?: T['config'], - ): MySqlCustomColumnBuilder> => { + ): GoogleSqlCustomColumnBuilder> => { const { name, config } = getColumnNameAndConfig(a, b); - return new MySqlCustomColumnBuilder(name as ConvertCustomConfig['name'], config, customTypeParams); + return new GoogleSqlCustomColumnBuilder(name as ConvertCustomConfig['name'], config, customTypeParams); }; } diff --git a/drizzle-orm/src/googlesql/columns/date.common.ts b/drizzle-orm/src/googlesql/columns/date.common.ts index 75faad5b85..26397bb4bd 100644 --- a/drizzle-orm/src/googlesql/columns/date.common.ts +++ b/drizzle-orm/src/googlesql/columns/date.common.ts @@ -7,18 +7,18 @@ import type { import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; import { sql } from '~/sql/sql.ts'; -import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; +import { GoogleSqlColumn, GoogleSqlColumnBuilder } from './common.ts'; -export interface MySqlDateColumnBaseConfig { +export interface GoogleSqlDateColumnBaseConfig { hasOnUpdateNow: boolean; } -export abstract class MySqlDateColumnBaseBuilder< +export abstract class GoogleSqlDateColumnBaseBuilder< T extends ColumnBuilderBaseConfig, TRuntimeConfig extends object = object, TExtraConfig extends ColumnBuilderExtraConfig = ColumnBuilderExtraConfig, -> extends MySqlColumnBuilder { - static override readonly [entityKind]: string = 'MySqlDateColumnBuilder'; +> extends GoogleSqlColumnBuilder { + static override readonly [entityKind]: string = 'GoogleSqlDateColumnBuilder'; defaultNow() { return this.default(sql`(now())`); @@ -32,11 +32,11 @@ export abstract class MySqlDateColumnBaseBuilder< } } -export abstract class MySqlDateBaseColumn< +export abstract class GoogleSqlDateBaseColumn< T extends ColumnBaseConfig, TRuntimeConfig extends object = object, -> extends MySqlColumn { - static override readonly [entityKind]: string = 'MySqlDateColumn'; +> extends GoogleSqlColumn { + static override readonly [entityKind]: string = 'GoogleSqlDateColumn'; readonly hasOnUpdateNow: boolean = this.config.hasOnUpdateNow; } diff --git a/drizzle-orm/src/googlesql/columns/date.ts b/drizzle-orm/src/googlesql/columns/date.ts index 935758141b..3e99eae8f7 100644 --- a/drizzle-orm/src/googlesql/columns/date.ts +++ b/drizzle-orm/src/googlesql/columns/date.ts @@ -1,40 +1,40 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/googlesql/table.ts'; +import type { AnyGoogleSqlTable } from '~/googlesql/table.ts'; import { type Equal, getColumnNameAndConfig } from '~/utils.ts'; -import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; +import { GoogleSqlColumn, GoogleSqlColumnBuilder } from './common.ts'; -export type MySqlDateBuilderInitial = MySqlDateBuilder<{ +export type GoogleSqlDateBuilderInitial = GoogleSqlDateBuilder<{ name: TName; dataType: 'date'; - columnType: 'MySqlDate'; + columnType: 'GoogleSqlDate'; data: Date; driverParam: string | number; enumValues: undefined; }>; -export class MySqlDateBuilder> extends MySqlColumnBuilder { - static override readonly [entityKind]: string = 'MySqlDateBuilder'; +export class GoogleSqlDateBuilder> extends GoogleSqlColumnBuilder { + static override readonly [entityKind]: string = 'GoogleSqlDateBuilder'; constructor(name: T['name']) { - super(name, 'date', 'MySqlDate'); + super(name, 'date', 'GoogleSqlDate'); } /** @internal */ override build( - table: AnyMySqlTable<{ name: TTableName }>, - ): MySqlDate> { - return new MySqlDate>(table, this.config as ColumnBuilderRuntimeConfig); + table: AnyGoogleSqlTable<{ name: TTableName }>, + ): GoogleSqlDate> { + return new GoogleSqlDate>(table, this.config as ColumnBuilderRuntimeConfig); } } -export class MySqlDate> extends MySqlColumn { - static override readonly [entityKind]: string = 'MySqlDate'; +export class GoogleSqlDate> extends GoogleSqlColumn { + static override readonly [entityKind]: string = 'GoogleSqlDate'; constructor( - table: AnyMySqlTable<{ name: T['tableName'] }>, - config: MySqlDateBuilder['config'], + table: AnyGoogleSqlTable<{ name: T['tableName'] }>, + config: GoogleSqlDateBuilder['config'], ) { super(table, config); } @@ -48,41 +48,41 @@ export class MySqlDate> extends } } -export type MySqlDateStringBuilderInitial = MySqlDateStringBuilder<{ +export type GoogleSqlDateStringBuilderInitial = GoogleSqlDateStringBuilder<{ name: TName; dataType: 'string'; - columnType: 'MySqlDateString'; + columnType: 'GoogleSqlDateString'; data: string; driverParam: string | number; enumValues: undefined; }>; -export class MySqlDateStringBuilder> - extends MySqlColumnBuilder +export class GoogleSqlDateStringBuilder> + extends GoogleSqlColumnBuilder { - static override readonly [entityKind]: string = 'MySqlDateStringBuilder'; + static override readonly [entityKind]: string = 'GoogleSqlDateStringBuilder'; constructor(name: T['name']) { - super(name, 'string', 'MySqlDateString'); + super(name, 'string', 'GoogleSqlDateString'); } /** @internal */ override build( - table: AnyMySqlTable<{ name: TTableName }>, - ): MySqlDateString> { - return new MySqlDateString>( + table: AnyGoogleSqlTable<{ name: TTableName }>, + ): GoogleSqlDateString> { + return new GoogleSqlDateString>( table, this.config as ColumnBuilderRuntimeConfig, ); } } -export class MySqlDateString> extends MySqlColumn { - static override readonly [entityKind]: string = 'MySqlDateString'; +export class GoogleSqlDateString> extends GoogleSqlColumn { + static override readonly [entityKind]: string = 'GoogleSqlDateString'; constructor( - table: AnyMySqlTable<{ name: T['tableName'] }>, - config: MySqlDateStringBuilder['config'], + table: AnyGoogleSqlTable<{ name: T['tableName'] }>, + config: GoogleSqlDateStringBuilder['config'], ) { super(table, config); } @@ -92,22 +92,22 @@ export class MySqlDateString { +export interface GoogleSqlDateConfig { mode?: TMode; } -export function date(): MySqlDateBuilderInitial<''>; -export function date( - config?: MySqlDateConfig, -): Equal extends true ? MySqlDateStringBuilderInitial<''> : MySqlDateBuilderInitial<''>; -export function date( +export function date(): GoogleSqlDateBuilderInitial<''>; +export function date( + config?: GoogleSqlDateConfig, +): Equal extends true ? GoogleSqlDateStringBuilderInitial<''> : GoogleSqlDateBuilderInitial<''>; +export function date( name: TName, - config?: MySqlDateConfig, -): Equal extends true ? MySqlDateStringBuilderInitial : MySqlDateBuilderInitial; -export function date(a?: string | MySqlDateConfig, b?: MySqlDateConfig) { - const { name, config } = getColumnNameAndConfig(a, b); + config?: GoogleSqlDateConfig, +): Equal extends true ? GoogleSqlDateStringBuilderInitial : GoogleSqlDateBuilderInitial; +export function date(a?: string | GoogleSqlDateConfig, b?: GoogleSqlDateConfig) { + const { name, config } = getColumnNameAndConfig(a, b); if (config?.mode === 'string') { - return new MySqlDateStringBuilder(name); + return new GoogleSqlDateStringBuilder(name); } - return new MySqlDateBuilder(name); + return new GoogleSqlDateBuilder(name); } diff --git a/drizzle-orm/src/googlesql/columns/datetime.ts b/drizzle-orm/src/googlesql/columns/datetime.ts index 5bca606349..f5ec1aa34f 100644 --- a/drizzle-orm/src/googlesql/columns/datetime.ts +++ b/drizzle-orm/src/googlesql/columns/datetime.ts @@ -1,48 +1,48 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/googlesql/table.ts'; +import type { AnyGoogleSqlTable } from '~/googlesql/table.ts'; import { type Equal, getColumnNameAndConfig } from '~/utils.ts'; -import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; +import { GoogleSqlColumn, GoogleSqlColumnBuilder } from './common.ts'; -export type MySqlDateTimeBuilderInitial = MySqlDateTimeBuilder<{ +export type GoogleSqlDateTimeBuilderInitial = GoogleSqlDateTimeBuilder<{ name: TName; dataType: 'date'; - columnType: 'MySqlDateTime'; + columnType: 'GoogleSqlDateTime'; data: Date; driverParam: string | number; enumValues: undefined; }>; -export class MySqlDateTimeBuilder> - extends MySqlColumnBuilder +export class GoogleSqlDateTimeBuilder> + extends GoogleSqlColumnBuilder { - static override readonly [entityKind]: string = 'MySqlDateTimeBuilder'; + static override readonly [entityKind]: string = 'GoogleSqlDateTimeBuilder'; - constructor(name: T['name'], config: MySqlDatetimeConfig | undefined) { - super(name, 'date', 'MySqlDateTime'); + constructor(name: T['name'], config: GoogleSqlDatetimeConfig | undefined) { + super(name, 'date', 'GoogleSqlDateTime'); this.config.fsp = config?.fsp; } /** @internal */ override build( - table: AnyMySqlTable<{ name: TTableName }>, - ): MySqlDateTime> { - return new MySqlDateTime>( + table: AnyGoogleSqlTable<{ name: TTableName }>, + ): GoogleSqlDateTime> { + return new GoogleSqlDateTime>( table, this.config as ColumnBuilderRuntimeConfig, ); } } -export class MySqlDateTime> extends MySqlColumn { - static override readonly [entityKind]: string = 'MySqlDateTime'; +export class GoogleSqlDateTime> extends GoogleSqlColumn { + static override readonly [entityKind]: string = 'GoogleSqlDateTime'; readonly fsp: number | undefined; constructor( - table: AnyMySqlTable<{ name: T['tableName'] }>, - config: MySqlDateTimeBuilder['config'], + table: AnyGoogleSqlTable<{ name: T['tableName'] }>, + config: GoogleSqlDateTimeBuilder['config'], ) { super(table, config); this.fsp = config.fsp; @@ -62,44 +62,44 @@ export class MySqlDateTime> } } -export type MySqlDateTimeStringBuilderInitial = MySqlDateTimeStringBuilder<{ +export type GoogleSqlDateTimeStringBuilderInitial = GoogleSqlDateTimeStringBuilder<{ name: TName; dataType: 'string'; - columnType: 'MySqlDateTimeString'; + columnType: 'GoogleSqlDateTimeString'; data: string; driverParam: string | number; enumValues: undefined; }>; -export class MySqlDateTimeStringBuilder> - extends MySqlColumnBuilder +export class GoogleSqlDateTimeStringBuilder> + extends GoogleSqlColumnBuilder { - static override readonly [entityKind]: string = 'MySqlDateTimeStringBuilder'; + static override readonly [entityKind]: string = 'GoogleSqlDateTimeStringBuilder'; - constructor(name: T['name'], config: MySqlDatetimeConfig | undefined) { - super(name, 'string', 'MySqlDateTimeString'); + constructor(name: T['name'], config: GoogleSqlDatetimeConfig | undefined) { + super(name, 'string', 'GoogleSqlDateTimeString'); this.config.fsp = config?.fsp; } /** @internal */ override build( - table: AnyMySqlTable<{ name: TTableName }>, - ): MySqlDateTimeString> { - return new MySqlDateTimeString>( + table: AnyGoogleSqlTable<{ name: TTableName }>, + ): GoogleSqlDateTimeString> { + return new GoogleSqlDateTimeString>( table, this.config as ColumnBuilderRuntimeConfig, ); } } -export class MySqlDateTimeString> extends MySqlColumn { - static override readonly [entityKind]: string = 'MySqlDateTimeString'; +export class GoogleSqlDateTimeString> extends GoogleSqlColumn { + static override readonly [entityKind]: string = 'GoogleSqlDateTimeString'; readonly fsp: number | undefined; constructor( - table: AnyMySqlTable<{ name: T['tableName'] }>, - config: MySqlDateTimeStringBuilder['config'], + table: AnyGoogleSqlTable<{ name: T['tableName'] }>, + config: GoogleSqlDateTimeStringBuilder['config'], ) { super(table, config); this.fsp = config.fsp; @@ -113,23 +113,23 @@ export class MySqlDateTimeString { +export interface GoogleSqlDatetimeConfig { mode?: TMode; fsp?: DatetimeFsp; } -export function datetime(): MySqlDateTimeBuilderInitial<''>; -export function datetime( - config?: MySqlDatetimeConfig, -): Equal extends true ? MySqlDateTimeStringBuilderInitial<''> : MySqlDateTimeBuilderInitial<''>; -export function datetime( +export function datetime(): GoogleSqlDateTimeBuilderInitial<''>; +export function datetime( + config?: GoogleSqlDatetimeConfig, +): Equal extends true ? GoogleSqlDateTimeStringBuilderInitial<''> : GoogleSqlDateTimeBuilderInitial<''>; +export function datetime( name: TName, - config?: MySqlDatetimeConfig, -): Equal extends true ? MySqlDateTimeStringBuilderInitial : MySqlDateTimeBuilderInitial; -export function datetime(a?: string | MySqlDatetimeConfig, b?: MySqlDatetimeConfig) { - const { name, config } = getColumnNameAndConfig(a, b); + config?: GoogleSqlDatetimeConfig, +): Equal extends true ? GoogleSqlDateTimeStringBuilderInitial : GoogleSqlDateTimeBuilderInitial; +export function datetime(a?: string | GoogleSqlDatetimeConfig, b?: GoogleSqlDatetimeConfig) { + const { name, config } = getColumnNameAndConfig(a, b); if (config?.mode === 'string') { - return new MySqlDateTimeStringBuilder(name, config); + return new GoogleSqlDateTimeStringBuilder(name, config); } - return new MySqlDateTimeBuilder(name, config); + return new GoogleSqlDateTimeBuilder(name, config); } diff --git a/drizzle-orm/src/googlesql/columns/decimal.ts b/drizzle-orm/src/googlesql/columns/decimal.ts index df4eb101ba..0738a3afc9 100644 --- a/drizzle-orm/src/googlesql/columns/decimal.ts +++ b/drizzle-orm/src/googlesql/columns/decimal.ts @@ -1,26 +1,26 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/googlesql/table.ts'; +import type { AnyGoogleSqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig } from '~/utils.ts'; -import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; +import { GoogleSqlColumnBuilderWithAutoIncrement, GoogleSqlColumnWithAutoIncrement } from './common.ts'; -export type MySqlDecimalBuilderInitial = MySqlDecimalBuilder<{ +export type GoogleSqlDecimalBuilderInitial = GoogleSqlDecimalBuilder<{ name: TName; dataType: 'string'; - columnType: 'MySqlDecimal'; + columnType: 'GoogleSqlDecimal'; data: string; driverParam: string; enumValues: undefined; }>; -export class MySqlDecimalBuilder< - T extends ColumnBuilderBaseConfig<'string', 'MySqlDecimal'>, -> extends MySqlColumnBuilderWithAutoIncrement { - static override readonly [entityKind]: string = 'MySqlDecimalBuilder'; +export class GoogleSqlDecimalBuilder< + T extends ColumnBuilderBaseConfig<'string', 'GoogleSqlDecimal'>, +> extends GoogleSqlColumnBuilderWithAutoIncrement { + static override readonly [entityKind]: string = 'GoogleSqlDecimalBuilder'; - constructor(name: T['name'], config: MySqlDecimalConfig | undefined) { - super(name, 'string', 'MySqlDecimal'); + constructor(name: T['name'], config: GoogleSqlDecimalConfig | undefined) { + super(name, 'string', 'GoogleSqlDecimal'); this.config.precision = config?.precision; this.config.scale = config?.scale; this.config.unsigned = config?.unsigned; @@ -28,19 +28,19 @@ export class MySqlDecimalBuilder< /** @internal */ override build( - table: AnyMySqlTable<{ name: TTableName }>, - ): MySqlDecimal> { - return new MySqlDecimal>( + table: AnyGoogleSqlTable<{ name: TTableName }>, + ): GoogleSqlDecimal> { + return new GoogleSqlDecimal>( table, this.config as ColumnBuilderRuntimeConfig, ); } } -export class MySqlDecimal> - extends MySqlColumnWithAutoIncrement +export class GoogleSqlDecimal> + extends GoogleSqlColumnWithAutoIncrement { - static override readonly [entityKind]: string = 'MySqlDecimal'; + static override readonly [entityKind]: string = 'GoogleSqlDecimal'; readonly precision: number | undefined = this.config.precision; readonly scale: number | undefined = this.config.scale; @@ -60,21 +60,21 @@ export class MySqlDecimal> } } -export interface MySqlDecimalConfig { +export interface GoogleSqlDecimalConfig { precision?: number; scale?: number; unsigned?: boolean; } -export function decimal(): MySqlDecimalBuilderInitial<''>; +export function decimal(): GoogleSqlDecimalBuilderInitial<''>; export function decimal( - config: MySqlDecimalConfig, -): MySqlDecimalBuilderInitial<''>; + config: GoogleSqlDecimalConfig, +): GoogleSqlDecimalBuilderInitial<''>; export function decimal( name: TName, - config?: MySqlDecimalConfig, -): MySqlDecimalBuilderInitial; -export function decimal(a?: string | MySqlDecimalConfig, b: MySqlDecimalConfig = {}) { - const { name, config } = getColumnNameAndConfig(a, b); - return new MySqlDecimalBuilder(name, config); + config?: GoogleSqlDecimalConfig, +): GoogleSqlDecimalBuilderInitial; +export function decimal(a?: string | GoogleSqlDecimalConfig, b: GoogleSqlDecimalConfig = {}) { + const { name, config } = getColumnNameAndConfig(a, b); + return new GoogleSqlDecimalBuilder(name, config); } diff --git a/drizzle-orm/src/googlesql/columns/double.ts b/drizzle-orm/src/googlesql/columns/double.ts index 8a1286ffc3..7e0ce9a6c1 100644 --- a/drizzle-orm/src/googlesql/columns/double.ts +++ b/drizzle-orm/src/googlesql/columns/double.ts @@ -1,26 +1,26 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/googlesql/table.ts'; +import type { AnyGoogleSqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig } from '~/utils.ts'; -import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; +import { GoogleSqlColumnBuilderWithAutoIncrement, GoogleSqlColumnWithAutoIncrement } from './common.ts'; -export type MySqlDoubleBuilderInitial = MySqlDoubleBuilder<{ +export type GoogleSqlDoubleBuilderInitial = GoogleSqlDoubleBuilder<{ name: TName; dataType: 'number'; - columnType: 'MySqlDouble'; + columnType: 'GoogleSqlDouble'; data: number; driverParam: number | string; enumValues: undefined; }>; -export class MySqlDoubleBuilder> - extends MySqlColumnBuilderWithAutoIncrement +export class GoogleSqlDoubleBuilder> + extends GoogleSqlColumnBuilderWithAutoIncrement { - static override readonly [entityKind]: string = 'MySqlDoubleBuilder'; + static override readonly [entityKind]: string = 'GoogleSqlDoubleBuilder'; - constructor(name: T['name'], config: MySqlDoubleConfig | undefined) { - super(name, 'number', 'MySqlDouble'); + constructor(name: T['name'], config: GoogleSqlDoubleConfig | undefined) { + super(name, 'number', 'GoogleSqlDouble'); this.config.precision = config?.precision; this.config.scale = config?.scale; this.config.unsigned = config?.unsigned; @@ -28,16 +28,16 @@ export class MySqlDoubleBuilder( - table: AnyMySqlTable<{ name: TTableName }>, - ): MySqlDouble> { - return new MySqlDouble>(table, this.config as ColumnBuilderRuntimeConfig); + table: AnyGoogleSqlTable<{ name: TTableName }>, + ): GoogleSqlDouble> { + return new GoogleSqlDouble>(table, this.config as ColumnBuilderRuntimeConfig); } } -export class MySqlDouble> - extends MySqlColumnWithAutoIncrement +export class GoogleSqlDouble> + extends GoogleSqlColumnWithAutoIncrement { - static override readonly [entityKind]: string = 'MySqlDouble'; + static override readonly [entityKind]: string = 'GoogleSqlDouble'; readonly precision: number | undefined = this.config.precision; readonly scale: number | undefined = this.config.scale; @@ -56,21 +56,21 @@ export class MySqlDouble> } } -export interface MySqlDoubleConfig { +export interface GoogleSqlDoubleConfig { precision?: number; scale?: number; unsigned?: boolean; } -export function double(): MySqlDoubleBuilderInitial<''>; +export function double(): GoogleSqlDoubleBuilderInitial<''>; export function double( - config?: MySqlDoubleConfig, -): MySqlDoubleBuilderInitial<''>; + config?: GoogleSqlDoubleConfig, +): GoogleSqlDoubleBuilderInitial<''>; export function double( name: TName, - config?: MySqlDoubleConfig, -): MySqlDoubleBuilderInitial; -export function double(a?: string | MySqlDoubleConfig, b?: MySqlDoubleConfig) { - const { name, config } = getColumnNameAndConfig(a, b); - return new MySqlDoubleBuilder(name, config); + config?: GoogleSqlDoubleConfig, +): GoogleSqlDoubleBuilderInitial; +export function double(a?: string | GoogleSqlDoubleConfig, b?: GoogleSqlDoubleConfig) { + const { name, config } = getColumnNameAndConfig(a, b); + return new GoogleSqlDoubleBuilder(name, config); } diff --git a/drizzle-orm/src/googlesql/columns/enum.ts b/drizzle-orm/src/googlesql/columns/enum.ts index 88833dd905..126a62fe53 100644 --- a/drizzle-orm/src/googlesql/columns/enum.ts +++ b/drizzle-orm/src/googlesql/columns/enum.ts @@ -1,45 +1,45 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/googlesql/table.ts'; +import type { AnyGoogleSqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig, type Writable } from '~/utils.ts'; -import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; +import { GoogleSqlColumn, GoogleSqlColumnBuilder } from './common.ts'; -export type MySqlEnumColumnBuilderInitial = - MySqlEnumColumnBuilder<{ +export type GoogleSqlEnumColumnBuilderInitial = + GoogleSqlEnumColumnBuilder<{ name: TName; dataType: 'string'; - columnType: 'MySqlEnumColumn'; + columnType: 'GoogleSqlEnumColumn'; data: TEnum[number]; driverParam: string; enumValues: TEnum; }>; -export class MySqlEnumColumnBuilder> - extends MySqlColumnBuilder +export class GoogleSqlEnumColumnBuilder> + extends GoogleSqlColumnBuilder { - static override readonly [entityKind]: string = 'MySqlEnumColumnBuilder'; + static override readonly [entityKind]: string = 'GoogleSqlEnumColumnBuilder'; constructor(name: T['name'], values: T['enumValues']) { - super(name, 'string', 'MySqlEnumColumn'); + super(name, 'string', 'GoogleSqlEnumColumn'); this.config.enumValues = values; } /** @internal */ override build( - table: AnyMySqlTable<{ name: TTableName }>, - ): MySqlEnumColumn & { enumValues: T['enumValues'] }> { - return new MySqlEnumColumn & { enumValues: T['enumValues'] }>( + table: AnyGoogleSqlTable<{ name: TTableName }>, + ): GoogleSqlEnumColumn & { enumValues: T['enumValues'] }> { + return new GoogleSqlEnumColumn & { enumValues: T['enumValues'] }>( table, this.config as ColumnBuilderRuntimeConfig, ); } } -export class MySqlEnumColumn> - extends MySqlColumn +export class GoogleSqlEnumColumn> + extends GoogleSqlColumn { - static override readonly [entityKind]: string = 'MySqlEnumColumn'; + static override readonly [entityKind]: string = 'GoogleSqlEnumColumn'; override readonly enumValues = this.config.enumValues; @@ -48,14 +48,14 @@ export class MySqlEnumColumn>( +export function googlesqlEnum>( values: T | Writable, -): MySqlEnumColumnBuilderInitial<'', Writable>; -export function mysqlEnum>( +): GoogleSqlEnumColumnBuilderInitial<'', Writable>; +export function googlesqlEnum>( name: TName, values: T | Writable, -): MySqlEnumColumnBuilderInitial>; -export function mysqlEnum( +): GoogleSqlEnumColumnBuilderInitial>; +export function googlesqlEnum( a?: string | readonly [string, ...string[]] | [string, ...string[]], b?: readonly [string, ...string[]] | [string, ...string[]], ): any { @@ -65,5 +65,5 @@ export function mysqlEnum( throw new Error(`You have an empty array for "${name}" enum values`); } - return new MySqlEnumColumnBuilder(name, values as any); + return new GoogleSqlEnumColumnBuilder(name, values as any); } diff --git a/drizzle-orm/src/googlesql/columns/float.ts b/drizzle-orm/src/googlesql/columns/float.ts index 1d3ee5af02..8ef3053221 100644 --- a/drizzle-orm/src/googlesql/columns/float.ts +++ b/drizzle-orm/src/googlesql/columns/float.ts @@ -1,26 +1,26 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/googlesql/table.ts'; +import type { AnyGoogleSqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig } from '~/utils.ts'; -import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; +import { GoogleSqlColumnBuilderWithAutoIncrement, GoogleSqlColumnWithAutoIncrement } from './common.ts'; -export type MySqlFloatBuilderInitial = MySqlFloatBuilder<{ +export type GoogleSqlFloatBuilderInitial = GoogleSqlFloatBuilder<{ name: TName; dataType: 'number'; - columnType: 'MySqlFloat'; + columnType: 'GoogleSqlFloat'; data: number; driverParam: number | string; enumValues: undefined; }>; -export class MySqlFloatBuilder> - extends MySqlColumnBuilderWithAutoIncrement +export class GoogleSqlFloatBuilder> + extends GoogleSqlColumnBuilderWithAutoIncrement { - static override readonly [entityKind]: string = 'MySqlFloatBuilder'; + static override readonly [entityKind]: string = 'GoogleSqlFloatBuilder'; - constructor(name: T['name'], config: MySqlFloatConfig | undefined) { - super(name, 'number', 'MySqlFloat'); + constructor(name: T['name'], config: GoogleSqlFloatConfig | undefined) { + super(name, 'number', 'GoogleSqlFloat'); this.config.precision = config?.precision; this.config.scale = config?.scale; this.config.unsigned = config?.unsigned; @@ -28,16 +28,16 @@ export class MySqlFloatBuilder( - table: AnyMySqlTable<{ name: TTableName }>, - ): MySqlFloat> { - return new MySqlFloat>(table, this.config as ColumnBuilderRuntimeConfig); + table: AnyGoogleSqlTable<{ name: TTableName }>, + ): GoogleSqlFloat> { + return new GoogleSqlFloat>(table, this.config as ColumnBuilderRuntimeConfig); } } -export class MySqlFloat> - extends MySqlColumnWithAutoIncrement +export class GoogleSqlFloat> + extends GoogleSqlColumnWithAutoIncrement { - static override readonly [entityKind]: string = 'MySqlFloat'; + static override readonly [entityKind]: string = 'GoogleSqlFloat'; readonly precision: number | undefined = this.config.precision; readonly scale: number | undefined = this.config.scale; @@ -56,21 +56,21 @@ export class MySqlFloat> } } -export interface MySqlFloatConfig { +export interface GoogleSqlFloatConfig { precision?: number; scale?: number; unsigned?: boolean; } -export function float(): MySqlFloatBuilderInitial<''>; +export function float(): GoogleSqlFloatBuilderInitial<''>; export function float( - config?: MySqlFloatConfig, -): MySqlFloatBuilderInitial<''>; + config?: GoogleSqlFloatConfig, +): GoogleSqlFloatBuilderInitial<''>; export function float( name: TName, - config?: MySqlFloatConfig, -): MySqlFloatBuilderInitial; -export function float(a?: string | MySqlFloatConfig, b?: MySqlFloatConfig) { - const { name, config } = getColumnNameAndConfig(a, b); - return new MySqlFloatBuilder(name, config); + config?: GoogleSqlFloatConfig, +): GoogleSqlFloatBuilderInitial; +export function float(a?: string | GoogleSqlFloatConfig, b?: GoogleSqlFloatConfig) { + const { name, config } = getColumnNameAndConfig(a, b); + return new GoogleSqlFloatBuilder(name, config); } diff --git a/drizzle-orm/src/googlesql/columns/int.ts b/drizzle-orm/src/googlesql/columns/int.ts index b5b15cef47..033a3805d5 100644 --- a/drizzle-orm/src/googlesql/columns/int.ts +++ b/drizzle-orm/src/googlesql/columns/int.ts @@ -1,41 +1,41 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/googlesql/table.ts'; +import type { AnyGoogleSqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig } from '~/utils.ts'; -import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; +import { GoogleSqlColumnBuilderWithAutoIncrement, GoogleSqlColumnWithAutoIncrement } from './common.ts'; -export type MySqlIntBuilderInitial = MySqlIntBuilder<{ +export type GoogleSqlIntBuilderInitial = GoogleSqlIntBuilder<{ name: TName; dataType: 'number'; - columnType: 'MySqlInt'; + columnType: 'GoogleSqlInt'; data: number; driverParam: number | string; enumValues: undefined; }>; -export class MySqlIntBuilder> - extends MySqlColumnBuilderWithAutoIncrement +export class GoogleSqlIntBuilder> + extends GoogleSqlColumnBuilderWithAutoIncrement { - static override readonly [entityKind]: string = 'MySqlIntBuilder'; + static override readonly [entityKind]: string = 'GoogleSqlIntBuilder'; - constructor(name: T['name'], config?: MySqlIntConfig) { - super(name, 'number', 'MySqlInt'); + constructor(name: T['name'], config?: GoogleSqlIntConfig) { + super(name, 'number', 'GoogleSqlInt'); this.config.unsigned = config ? config.unsigned : false; } /** @internal */ override build( - table: AnyMySqlTable<{ name: TTableName }>, - ): MySqlInt> { - return new MySqlInt>(table, this.config as ColumnBuilderRuntimeConfig); + table: AnyGoogleSqlTable<{ name: TTableName }>, + ): GoogleSqlInt> { + return new GoogleSqlInt>(table, this.config as ColumnBuilderRuntimeConfig); } } -export class MySqlInt> - extends MySqlColumnWithAutoIncrement +export class GoogleSqlInt> + extends GoogleSqlColumnWithAutoIncrement { - static override readonly [entityKind]: string = 'MySqlInt'; + static override readonly [entityKind]: string = 'GoogleSqlInt'; getSQLType(): string { return `int${this.config.unsigned ? ' unsigned' : ''}`; @@ -49,19 +49,19 @@ export class MySqlInt> } } -export interface MySqlIntConfig { +export interface GoogleSqlIntConfig { unsigned?: boolean; } -export function int(): MySqlIntBuilderInitial<''>; +export function int(): GoogleSqlIntBuilderInitial<''>; export function int( - config?: MySqlIntConfig, -): MySqlIntBuilderInitial<''>; + config?: GoogleSqlIntConfig, +): GoogleSqlIntBuilderInitial<''>; export function int( name: TName, - config?: MySqlIntConfig, -): MySqlIntBuilderInitial; -export function int(a?: string | MySqlIntConfig, b?: MySqlIntConfig) { - const { name, config } = getColumnNameAndConfig(a, b); - return new MySqlIntBuilder(name, config); + config?: GoogleSqlIntConfig, +): GoogleSqlIntBuilderInitial; +export function int(a?: string | GoogleSqlIntConfig, b?: GoogleSqlIntConfig) { + const { name, config } = getColumnNameAndConfig(a, b); + return new GoogleSqlIntBuilder(name, config); } diff --git a/drizzle-orm/src/googlesql/columns/json.ts b/drizzle-orm/src/googlesql/columns/json.ts index b84def318a..dc93048316 100644 --- a/drizzle-orm/src/googlesql/columns/json.ts +++ b/drizzle-orm/src/googlesql/columns/json.ts @@ -1,35 +1,35 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/googlesql/table.ts'; -import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; +import type { AnyGoogleSqlTable } from '~/googlesql/table.ts'; +import { GoogleSqlColumn, GoogleSqlColumnBuilder } from './common.ts'; -export type MySqlJsonBuilderInitial = MySqlJsonBuilder<{ +export type GoogleSqlJsonBuilderInitial = GoogleSqlJsonBuilder<{ name: TName; dataType: 'json'; - columnType: 'MySqlJson'; + columnType: 'GoogleSqlJson'; data: unknown; driverParam: string; enumValues: undefined; }>; -export class MySqlJsonBuilder> extends MySqlColumnBuilder { - static override readonly [entityKind]: string = 'MySqlJsonBuilder'; +export class GoogleSqlJsonBuilder> extends GoogleSqlColumnBuilder { + static override readonly [entityKind]: string = 'GoogleSqlJsonBuilder'; constructor(name: T['name']) { - super(name, 'json', 'MySqlJson'); + super(name, 'json', 'GoogleSqlJson'); } /** @internal */ override build( - table: AnyMySqlTable<{ name: TTableName }>, - ): MySqlJson> { - return new MySqlJson>(table, this.config as ColumnBuilderRuntimeConfig); + table: AnyGoogleSqlTable<{ name: TTableName }>, + ): GoogleSqlJson> { + return new GoogleSqlJson>(table, this.config as ColumnBuilderRuntimeConfig); } } -export class MySqlJson> extends MySqlColumn { - static override readonly [entityKind]: string = 'MySqlJson'; +export class GoogleSqlJson> extends GoogleSqlColumn { + static override readonly [entityKind]: string = 'GoogleSqlJson'; getSQLType(): string { return 'json'; @@ -40,8 +40,8 @@ export class MySqlJson> extends } } -export function json(): MySqlJsonBuilderInitial<''>; -export function json(name: TName): MySqlJsonBuilderInitial; +export function json(): GoogleSqlJsonBuilderInitial<''>; +export function json(name: TName): GoogleSqlJsonBuilderInitial; export function json(name?: string) { - return new MySqlJsonBuilder(name ?? ''); + return new GoogleSqlJsonBuilder(name ?? ''); } diff --git a/drizzle-orm/src/googlesql/columns/mediumint.ts b/drizzle-orm/src/googlesql/columns/mediumint.ts index 4dad3568a6..915eb47916 100644 --- a/drizzle-orm/src/googlesql/columns/mediumint.ts +++ b/drizzle-orm/src/googlesql/columns/mediumint.ts @@ -1,45 +1,45 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/googlesql/table.ts'; +import type { AnyGoogleSqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig } from '~/utils.ts'; -import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; -import type { MySqlIntConfig } from './int.ts'; +import { GoogleSqlColumnBuilderWithAutoIncrement, GoogleSqlColumnWithAutoIncrement } from './common.ts'; +import type { GoogleSqlIntConfig } from './int.ts'; -export type MySqlMediumIntBuilderInitial = MySqlMediumIntBuilder<{ +export type GoogleSqlMediumIntBuilderInitial = GoogleSqlMediumIntBuilder<{ name: TName; dataType: 'number'; - columnType: 'MySqlMediumInt'; + columnType: 'GoogleSqlMediumInt'; data: number; driverParam: number | string; enumValues: undefined; }>; -export class MySqlMediumIntBuilder> - extends MySqlColumnBuilderWithAutoIncrement +export class GoogleSqlMediumIntBuilder> + extends GoogleSqlColumnBuilderWithAutoIncrement { - static override readonly [entityKind]: string = 'MySqlMediumIntBuilder'; + static override readonly [entityKind]: string = 'GoogleSqlMediumIntBuilder'; - constructor(name: T['name'], config?: MySqlIntConfig) { - super(name, 'number', 'MySqlMediumInt'); + constructor(name: T['name'], config?: GoogleSqlIntConfig) { + super(name, 'number', 'GoogleSqlMediumInt'); this.config.unsigned = config ? config.unsigned : false; } /** @internal */ override build( - table: AnyMySqlTable<{ name: TTableName }>, - ): MySqlMediumInt> { - return new MySqlMediumInt>( + table: AnyGoogleSqlTable<{ name: TTableName }>, + ): GoogleSqlMediumInt> { + return new GoogleSqlMediumInt>( table, this.config as ColumnBuilderRuntimeConfig, ); } } -export class MySqlMediumInt> - extends MySqlColumnWithAutoIncrement +export class GoogleSqlMediumInt> + extends GoogleSqlColumnWithAutoIncrement { - static override readonly [entityKind]: string = 'MySqlMediumInt'; + static override readonly [entityKind]: string = 'GoogleSqlMediumInt'; getSQLType(): string { return `mediumint${this.config.unsigned ? ' unsigned' : ''}`; @@ -53,15 +53,15 @@ export class MySqlMediumInt; +export function mediumint(): GoogleSqlMediumIntBuilderInitial<''>; export function mediumint( - config?: MySqlIntConfig, -): MySqlMediumIntBuilderInitial<''>; + config?: GoogleSqlIntConfig, +): GoogleSqlMediumIntBuilderInitial<''>; export function mediumint( name: TName, - config?: MySqlIntConfig, -): MySqlMediumIntBuilderInitial; -export function mediumint(a?: string | MySqlIntConfig, b?: MySqlIntConfig) { - const { name, config } = getColumnNameAndConfig(a, b); - return new MySqlMediumIntBuilder(name, config); + config?: GoogleSqlIntConfig, +): GoogleSqlMediumIntBuilderInitial; +export function mediumint(a?: string | GoogleSqlIntConfig, b?: GoogleSqlIntConfig) { + const { name, config } = getColumnNameAndConfig(a, b); + return new GoogleSqlMediumIntBuilder(name, config); } diff --git a/drizzle-orm/src/googlesql/columns/real.ts b/drizzle-orm/src/googlesql/columns/real.ts index 72e39e2525..39e733a35d 100644 --- a/drizzle-orm/src/googlesql/columns/real.ts +++ b/drizzle-orm/src/googlesql/columns/real.ts @@ -1,46 +1,46 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/googlesql/table.ts'; +import type { AnyGoogleSqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig } from '~/utils.ts'; -import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; +import { GoogleSqlColumnBuilderWithAutoIncrement, GoogleSqlColumnWithAutoIncrement } from './common.ts'; -export type MySqlRealBuilderInitial = MySqlRealBuilder<{ +export type GoogleSqlRealBuilderInitial = GoogleSqlRealBuilder<{ name: TName; dataType: 'number'; - columnType: 'MySqlReal'; + columnType: 'GoogleSqlReal'; data: number; driverParam: number | string; enumValues: undefined; }>; -export class MySqlRealBuilder> - extends MySqlColumnBuilderWithAutoIncrement< +export class GoogleSqlRealBuilder> + extends GoogleSqlColumnBuilderWithAutoIncrement< T, - MySqlRealConfig + GoogleSqlRealConfig > { - static override readonly [entityKind]: string = 'MySqlRealBuilder'; + static override readonly [entityKind]: string = 'GoogleSqlRealBuilder'; - constructor(name: T['name'], config: MySqlRealConfig | undefined) { - super(name, 'number', 'MySqlReal'); + constructor(name: T['name'], config: GoogleSqlRealConfig | undefined) { + super(name, 'number', 'GoogleSqlReal'); this.config.precision = config?.precision; this.config.scale = config?.scale; } /** @internal */ override build( - table: AnyMySqlTable<{ name: TTableName }>, - ): MySqlReal> { - return new MySqlReal>(table, this.config as ColumnBuilderRuntimeConfig); + table: AnyGoogleSqlTable<{ name: TTableName }>, + ): GoogleSqlReal> { + return new GoogleSqlReal>(table, this.config as ColumnBuilderRuntimeConfig); } } -export class MySqlReal> extends MySqlColumnWithAutoIncrement< +export class GoogleSqlReal> extends GoogleSqlColumnWithAutoIncrement< T, - MySqlRealConfig + GoogleSqlRealConfig > { - static override readonly [entityKind]: string = 'MySqlReal'; + static override readonly [entityKind]: string = 'GoogleSqlReal'; precision: number | undefined = this.config.precision; scale: number | undefined = this.config.scale; @@ -56,20 +56,20 @@ export class MySqlReal> extend } } -export interface MySqlRealConfig { +export interface GoogleSqlRealConfig { precision?: number; scale?: number; } -export function real(): MySqlRealBuilderInitial<''>; +export function real(): GoogleSqlRealBuilderInitial<''>; export function real( - config?: MySqlRealConfig, -): MySqlRealBuilderInitial<''>; + config?: GoogleSqlRealConfig, +): GoogleSqlRealBuilderInitial<''>; export function real( name: TName, - config?: MySqlRealConfig, -): MySqlRealBuilderInitial; -export function real(a?: string | MySqlRealConfig, b: MySqlRealConfig = {}) { - const { name, config } = getColumnNameAndConfig(a, b); - return new MySqlRealBuilder(name, config); + config?: GoogleSqlRealConfig, +): GoogleSqlRealBuilderInitial; +export function real(a?: string | GoogleSqlRealConfig, b: GoogleSqlRealConfig = {}) { + const { name, config } = getColumnNameAndConfig(a, b); + return new GoogleSqlRealBuilder(name, config); } diff --git a/drizzle-orm/src/googlesql/columns/serial.ts b/drizzle-orm/src/googlesql/columns/serial.ts index 4753658eaf..4780196114 100644 --- a/drizzle-orm/src/googlesql/columns/serial.ts +++ b/drizzle-orm/src/googlesql/columns/serial.ts @@ -9,17 +9,17 @@ import type { } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/googlesql/table.ts'; -import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; +import type { AnyGoogleSqlTable } from '~/googlesql/table.ts'; +import { GoogleSqlColumnBuilderWithAutoIncrement, GoogleSqlColumnWithAutoIncrement } from './common.ts'; -export type MySqlSerialBuilderInitial = IsAutoincrement< +export type GoogleSqlSerialBuilderInitial = IsAutoincrement< IsPrimaryKey< NotNull< HasDefault< - MySqlSerialBuilder<{ + GoogleSqlSerialBuilder<{ name: TName; dataType: 'number'; - columnType: 'MySqlSerial'; + columnType: 'GoogleSqlSerial'; data: number; driverParam: number; enumValues: undefined; @@ -29,29 +29,29 @@ export type MySqlSerialBuilderInitial = IsAutoincrement< > >; -export class MySqlSerialBuilder> - extends MySqlColumnBuilderWithAutoIncrement +export class GoogleSqlSerialBuilder> + extends GoogleSqlColumnBuilderWithAutoIncrement { - static override readonly [entityKind]: string = 'MySqlSerialBuilder'; + static override readonly [entityKind]: string = 'GoogleSqlSerialBuilder'; constructor(name: T['name']) { - super(name, 'number', 'MySqlSerial'); + super(name, 'number', 'GoogleSqlSerial'); this.config.hasDefault = true; this.config.autoIncrement = true; } /** @internal */ override build( - table: AnyMySqlTable<{ name: TTableName }>, - ): MySqlSerial> { - return new MySqlSerial>(table, this.config as ColumnBuilderRuntimeConfig); + table: AnyGoogleSqlTable<{ name: TTableName }>, + ): GoogleSqlSerial> { + return new GoogleSqlSerial>(table, this.config as ColumnBuilderRuntimeConfig); } } -export class MySqlSerial< - T extends ColumnBaseConfig<'number', 'MySqlSerial'>, -> extends MySqlColumnWithAutoIncrement { - static override readonly [entityKind]: string = 'MySqlSerial'; +export class GoogleSqlSerial< + T extends ColumnBaseConfig<'number', 'GoogleSqlSerial'>, +> extends GoogleSqlColumnWithAutoIncrement { + static override readonly [entityKind]: string = 'GoogleSqlSerial'; getSQLType(): string { return 'serial'; @@ -65,8 +65,8 @@ export class MySqlSerial< } } -export function serial(): MySqlSerialBuilderInitial<''>; -export function serial(name: TName): MySqlSerialBuilderInitial; +export function serial(): GoogleSqlSerialBuilderInitial<''>; +export function serial(name: TName): GoogleSqlSerialBuilderInitial; export function serial(name?: string) { - return new MySqlSerialBuilder(name ?? ''); + return new GoogleSqlSerialBuilder(name ?? ''); } diff --git a/drizzle-orm/src/googlesql/columns/smallint.ts b/drizzle-orm/src/googlesql/columns/smallint.ts index 97026f114f..81516580f1 100644 --- a/drizzle-orm/src/googlesql/columns/smallint.ts +++ b/drizzle-orm/src/googlesql/columns/smallint.ts @@ -1,45 +1,45 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/googlesql/table.ts'; +import type { AnyGoogleSqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig } from '~/utils.ts'; -import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; -import type { MySqlIntConfig } from './int.ts'; +import { GoogleSqlColumnBuilderWithAutoIncrement, GoogleSqlColumnWithAutoIncrement } from './common.ts'; +import type { GoogleSqlIntConfig } from './int.ts'; -export type MySqlSmallIntBuilderInitial = MySqlSmallIntBuilder<{ +export type GoogleSqlSmallIntBuilderInitial = GoogleSqlSmallIntBuilder<{ name: TName; dataType: 'number'; - columnType: 'MySqlSmallInt'; + columnType: 'GoogleSqlSmallInt'; data: number; driverParam: number | string; enumValues: undefined; }>; -export class MySqlSmallIntBuilder> - extends MySqlColumnBuilderWithAutoIncrement +export class GoogleSqlSmallIntBuilder> + extends GoogleSqlColumnBuilderWithAutoIncrement { - static override readonly [entityKind]: string = 'MySqlSmallIntBuilder'; + static override readonly [entityKind]: string = 'GoogleSqlSmallIntBuilder'; - constructor(name: T['name'], config?: MySqlIntConfig) { - super(name, 'number', 'MySqlSmallInt'); + constructor(name: T['name'], config?: GoogleSqlIntConfig) { + super(name, 'number', 'GoogleSqlSmallInt'); this.config.unsigned = config ? config.unsigned : false; } /** @internal */ override build( - table: AnyMySqlTable<{ name: TTableName }>, - ): MySqlSmallInt> { - return new MySqlSmallInt>( + table: AnyGoogleSqlTable<{ name: TTableName }>, + ): GoogleSqlSmallInt> { + return new GoogleSqlSmallInt>( table, this.config as ColumnBuilderRuntimeConfig, ); } } -export class MySqlSmallInt> - extends MySqlColumnWithAutoIncrement +export class GoogleSqlSmallInt> + extends GoogleSqlColumnWithAutoIncrement { - static override readonly [entityKind]: string = 'MySqlSmallInt'; + static override readonly [entityKind]: string = 'GoogleSqlSmallInt'; getSQLType(): string { return `smallint${this.config.unsigned ? ' unsigned' : ''}`; @@ -53,15 +53,15 @@ export class MySqlSmallInt } } -export function smallint(): MySqlSmallIntBuilderInitial<''>; +export function smallint(): GoogleSqlSmallIntBuilderInitial<''>; export function smallint( - config?: MySqlIntConfig, -): MySqlSmallIntBuilderInitial<''>; + config?: GoogleSqlIntConfig, +): GoogleSqlSmallIntBuilderInitial<''>; export function smallint( name: TName, - config?: MySqlIntConfig, -): MySqlSmallIntBuilderInitial; -export function smallint(a?: string | MySqlIntConfig, b?: MySqlIntConfig) { - const { name, config } = getColumnNameAndConfig(a, b); - return new MySqlSmallIntBuilder(name, config); + config?: GoogleSqlIntConfig, +): GoogleSqlSmallIntBuilderInitial; +export function smallint(a?: string | GoogleSqlIntConfig, b?: GoogleSqlIntConfig) { + const { name, config } = getColumnNameAndConfig(a, b); + return new GoogleSqlSmallIntBuilder(name, config); } diff --git a/drizzle-orm/src/googlesql/columns/text.ts b/drizzle-orm/src/googlesql/columns/text.ts index d8f578e8fc..693e72b415 100644 --- a/drizzle-orm/src/googlesql/columns/text.ts +++ b/drizzle-orm/src/googlesql/columns/text.ts @@ -1,47 +1,47 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/googlesql/table.ts'; +import type { AnyGoogleSqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig, type Writable } from '~/utils.ts'; -import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; +import { GoogleSqlColumn, GoogleSqlColumnBuilder } from './common.ts'; -export type MySqlTextColumnType = 'tinytext' | 'text' | 'mediumtext' | 'longtext'; +export type GoogleSqlTextColumnType = 'tinytext' | 'text' | 'mediumtext' | 'longtext'; -export type MySqlTextBuilderInitial = MySqlTextBuilder<{ +export type GoogleSqlTextBuilderInitial = GoogleSqlTextBuilder<{ name: TName; dataType: 'string'; - columnType: 'MySqlText'; + columnType: 'GoogleSqlText'; data: TEnum[number]; driverParam: string; enumValues: TEnum; }>; -export class MySqlTextBuilder> extends MySqlColumnBuilder< +export class GoogleSqlTextBuilder> extends GoogleSqlColumnBuilder< T, - { textType: MySqlTextColumnType; enumValues: T['enumValues'] } + { textType: GoogleSqlTextColumnType; enumValues: T['enumValues'] } > { - static override readonly [entityKind]: string = 'MySqlTextBuilder'; + static override readonly [entityKind]: string = 'GoogleSqlTextBuilder'; - constructor(name: T['name'], textType: MySqlTextColumnType, config: MySqlTextConfig) { - super(name, 'string', 'MySqlText'); + constructor(name: T['name'], textType: GoogleSqlTextColumnType, config: GoogleSqlTextConfig) { + super(name, 'string', 'GoogleSqlText'); this.config.textType = textType; this.config.enumValues = config.enum; } /** @internal */ override build( - table: AnyMySqlTable<{ name: TTableName }>, - ): MySqlText> { - return new MySqlText>(table, this.config as ColumnBuilderRuntimeConfig); + table: AnyGoogleSqlTable<{ name: TTableName }>, + ): GoogleSqlText> { + return new GoogleSqlText>(table, this.config as ColumnBuilderRuntimeConfig); } } -export class MySqlText> - extends MySqlColumn +export class GoogleSqlText> + extends GoogleSqlColumn { - static override readonly [entityKind]: string = 'MySqlText'; + static override readonly [entityKind]: string = 'GoogleSqlText'; - readonly textType: MySqlTextColumnType = this.config.textType; + readonly textType: GoogleSqlTextColumnType = this.config.textType; override readonly enumValues = this.config.enumValues; @@ -50,60 +50,60 @@ export class MySqlText> } } -export interface MySqlTextConfig< +export interface GoogleSqlTextConfig< TEnum extends readonly string[] | string[] | undefined = readonly string[] | string[] | undefined, > { enum?: TEnum; } -export function text(): MySqlTextBuilderInitial<'', [string, ...string[]]>; +export function text(): GoogleSqlTextBuilderInitial<'', [string, ...string[]]>; export function text>( - config?: MySqlTextConfig>, -): MySqlTextBuilderInitial<'', Writable>; + config?: GoogleSqlTextConfig>, +): GoogleSqlTextBuilderInitial<'', Writable>; export function text>( name: TName, - config?: MySqlTextConfig>, -): MySqlTextBuilderInitial>; -export function text(a?: string | MySqlTextConfig, b: MySqlTextConfig = {}): any { - const { name, config } = getColumnNameAndConfig(a, b); - return new MySqlTextBuilder(name, 'text', config as any); + config?: GoogleSqlTextConfig>, +): GoogleSqlTextBuilderInitial>; +export function text(a?: string | GoogleSqlTextConfig, b: GoogleSqlTextConfig = {}): any { + const { name, config } = getColumnNameAndConfig(a, b); + return new GoogleSqlTextBuilder(name, 'text', config as any); } -export function tinytext(): MySqlTextBuilderInitial<'', [string, ...string[]]>; +export function tinytext(): GoogleSqlTextBuilderInitial<'', [string, ...string[]]>; export function tinytext>( - config?: MySqlTextConfig>, -): MySqlTextBuilderInitial<'', Writable>; + config?: GoogleSqlTextConfig>, +): GoogleSqlTextBuilderInitial<'', Writable>; export function tinytext>( name: TName, - config?: MySqlTextConfig>, -): MySqlTextBuilderInitial>; -export function tinytext(a?: string | MySqlTextConfig, b: MySqlTextConfig = {}): any { - const { name, config } = getColumnNameAndConfig(a, b); - return new MySqlTextBuilder(name, 'tinytext', config as any); + config?: GoogleSqlTextConfig>, +): GoogleSqlTextBuilderInitial>; +export function tinytext(a?: string | GoogleSqlTextConfig, b: GoogleSqlTextConfig = {}): any { + const { name, config } = getColumnNameAndConfig(a, b); + return new GoogleSqlTextBuilder(name, 'tinytext', config as any); } -export function mediumtext(): MySqlTextBuilderInitial<'', [string, ...string[]]>; +export function mediumtext(): GoogleSqlTextBuilderInitial<'', [string, ...string[]]>; export function mediumtext>( - config?: MySqlTextConfig>, -): MySqlTextBuilderInitial<'', Writable>; + config?: GoogleSqlTextConfig>, +): GoogleSqlTextBuilderInitial<'', Writable>; export function mediumtext>( name: TName, - config?: MySqlTextConfig>, -): MySqlTextBuilderInitial>; -export function mediumtext(a?: string | MySqlTextConfig, b: MySqlTextConfig = {}): any { - const { name, config } = getColumnNameAndConfig(a, b); - return new MySqlTextBuilder(name, 'mediumtext', config as any); + config?: GoogleSqlTextConfig>, +): GoogleSqlTextBuilderInitial>; +export function mediumtext(a?: string | GoogleSqlTextConfig, b: GoogleSqlTextConfig = {}): any { + const { name, config } = getColumnNameAndConfig(a, b); + return new GoogleSqlTextBuilder(name, 'mediumtext', config as any); } -export function longtext(): MySqlTextBuilderInitial<'', [string, ...string[]]>; +export function longtext(): GoogleSqlTextBuilderInitial<'', [string, ...string[]]>; export function longtext>( - config?: MySqlTextConfig>, -): MySqlTextBuilderInitial<'', Writable>; + config?: GoogleSqlTextConfig>, +): GoogleSqlTextBuilderInitial<'', Writable>; export function longtext>( name: TName, - config?: MySqlTextConfig>, -): MySqlTextBuilderInitial>; -export function longtext(a?: string | MySqlTextConfig, b: MySqlTextConfig = {}): any { - const { name, config } = getColumnNameAndConfig(a, b); - return new MySqlTextBuilder(name, 'longtext', config as any); + config?: GoogleSqlTextConfig>, +): GoogleSqlTextBuilderInitial>; +export function longtext(a?: string | GoogleSqlTextConfig, b: GoogleSqlTextConfig = {}): any { + const { name, config } = getColumnNameAndConfig(a, b); + return new GoogleSqlTextBuilder(name, 'longtext', config as any); } diff --git a/drizzle-orm/src/googlesql/columns/time.ts b/drizzle-orm/src/googlesql/columns/time.ts index 51e9c18972..0536a56458 100644 --- a/drizzle-orm/src/googlesql/columns/time.ts +++ b/drizzle-orm/src/googlesql/columns/time.ts @@ -1,45 +1,45 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/googlesql/table.ts'; +import type { AnyGoogleSqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig } from '~/utils.ts'; -import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; +import { GoogleSqlColumn, GoogleSqlColumnBuilder } from './common.ts'; -export type MySqlTimeBuilderInitial = MySqlTimeBuilder<{ +export type GoogleSqlTimeBuilderInitial = GoogleSqlTimeBuilder<{ name: TName; dataType: 'string'; - columnType: 'MySqlTime'; + columnType: 'GoogleSqlTime'; data: string; driverParam: string | number; enumValues: undefined; }>; -export class MySqlTimeBuilder> extends MySqlColumnBuilder< +export class GoogleSqlTimeBuilder> extends GoogleSqlColumnBuilder< T, TimeConfig > { - static override readonly [entityKind]: string = 'MySqlTimeBuilder'; + static override readonly [entityKind]: string = 'GoogleSqlTimeBuilder'; constructor( name: T['name'], config: TimeConfig | undefined, ) { - super(name, 'string', 'MySqlTime'); + super(name, 'string', 'GoogleSqlTime'); this.config.fsp = config?.fsp; } /** @internal */ override build( - table: AnyMySqlTable<{ name: TTableName }>, - ): MySqlTime> { - return new MySqlTime>(table, this.config as ColumnBuilderRuntimeConfig); + table: AnyGoogleSqlTable<{ name: TTableName }>, + ): GoogleSqlTime> { + return new GoogleSqlTime>(table, this.config as ColumnBuilderRuntimeConfig); } } -export class MySqlTime< - T extends ColumnBaseConfig<'string', 'MySqlTime'>, -> extends MySqlColumn { - static override readonly [entityKind]: string = 'MySqlTime'; +export class GoogleSqlTime< + T extends ColumnBaseConfig<'string', 'GoogleSqlTime'>, +> extends GoogleSqlColumn { + static override readonly [entityKind]: string = 'GoogleSqlTime'; readonly fsp: number | undefined = this.config.fsp; @@ -53,15 +53,15 @@ export type TimeConfig = { fsp?: 0 | 1 | 2 | 3 | 4 | 5 | 6; }; -export function time(): MySqlTimeBuilderInitial<''>; +export function time(): GoogleSqlTimeBuilderInitial<''>; export function time( config?: TimeConfig, -): MySqlTimeBuilderInitial<''>; +): GoogleSqlTimeBuilderInitial<''>; export function time( name: TName, config?: TimeConfig, -): MySqlTimeBuilderInitial; +): GoogleSqlTimeBuilderInitial; export function time(a?: string | TimeConfig, b?: TimeConfig) { const { name, config } = getColumnNameAndConfig(a, b); - return new MySqlTimeBuilder(name, config); + return new GoogleSqlTimeBuilder(name, config); } diff --git a/drizzle-orm/src/googlesql/columns/timestamp.ts b/drizzle-orm/src/googlesql/columns/timestamp.ts index 5bdd451304..e8a4795aa0 100644 --- a/drizzle-orm/src/googlesql/columns/timestamp.ts +++ b/drizzle-orm/src/googlesql/columns/timestamp.ts @@ -1,44 +1,44 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/googlesql/table.ts'; +import type { AnyGoogleSqlTable } from '~/googlesql/table.ts'; import { type Equal, getColumnNameAndConfig } from '~/utils.ts'; -import { MySqlDateBaseColumn, MySqlDateColumnBaseBuilder } from './date.common.ts'; +import { GoogleSqlDateBaseColumn, GoogleSqlDateColumnBaseBuilder } from './date.common.ts'; -export type MySqlTimestampBuilderInitial = MySqlTimestampBuilder<{ +export type GoogleSqlTimestampBuilderInitial = GoogleSqlTimestampBuilder<{ name: TName; dataType: 'date'; - columnType: 'MySqlTimestamp'; + columnType: 'GoogleSqlTimestamp'; data: Date; driverParam: string | number; enumValues: undefined; }>; -export class MySqlTimestampBuilder> - extends MySqlDateColumnBaseBuilder +export class GoogleSqlTimestampBuilder> + extends GoogleSqlDateColumnBaseBuilder { - static override readonly [entityKind]: string = 'MySqlTimestampBuilder'; + static override readonly [entityKind]: string = 'GoogleSqlTimestampBuilder'; - constructor(name: T['name'], config: MySqlTimestampConfig | undefined) { - super(name, 'date', 'MySqlTimestamp'); + constructor(name: T['name'], config: GoogleSqlTimestampConfig | undefined) { + super(name, 'date', 'GoogleSqlTimestamp'); this.config.fsp = config?.fsp; } /** @internal */ override build( - table: AnyMySqlTable<{ name: TTableName }>, - ): MySqlTimestamp> { - return new MySqlTimestamp>( + table: AnyGoogleSqlTable<{ name: TTableName }>, + ): GoogleSqlTimestamp> { + return new GoogleSqlTimestamp>( table, this.config as ColumnBuilderRuntimeConfig, ); } } -export class MySqlTimestamp> - extends MySqlDateBaseColumn +export class GoogleSqlTimestamp> + extends GoogleSqlDateBaseColumn { - static override readonly [entityKind]: string = 'MySqlTimestamp'; + static override readonly [entityKind]: string = 'GoogleSqlTimestamp'; readonly fsp: number | undefined = this.config.fsp; @@ -56,40 +56,40 @@ export class MySqlTimestamp } } -export type MySqlTimestampStringBuilderInitial = MySqlTimestampStringBuilder<{ +export type GoogleSqlTimestampStringBuilderInitial = GoogleSqlTimestampStringBuilder<{ name: TName; dataType: 'string'; - columnType: 'MySqlTimestampString'; + columnType: 'GoogleSqlTimestampString'; data: string; driverParam: string | number; enumValues: undefined; }>; -export class MySqlTimestampStringBuilder> - extends MySqlDateColumnBaseBuilder +export class GoogleSqlTimestampStringBuilder> + extends GoogleSqlDateColumnBaseBuilder { - static override readonly [entityKind]: string = 'MySqlTimestampStringBuilder'; + static override readonly [entityKind]: string = 'GoogleSqlTimestampStringBuilder'; - constructor(name: T['name'], config: MySqlTimestampConfig | undefined) { - super(name, 'string', 'MySqlTimestampString'); + constructor(name: T['name'], config: GoogleSqlTimestampConfig | undefined) { + super(name, 'string', 'GoogleSqlTimestampString'); this.config.fsp = config?.fsp; } /** @internal */ override build( - table: AnyMySqlTable<{ name: TTableName }>, - ): MySqlTimestampString> { - return new MySqlTimestampString>( + table: AnyGoogleSqlTable<{ name: TTableName }>, + ): GoogleSqlTimestampString> { + return new GoogleSqlTimestampString>( table, this.config as ColumnBuilderRuntimeConfig, ); } } -export class MySqlTimestampString> - extends MySqlDateBaseColumn +export class GoogleSqlTimestampString> + extends GoogleSqlDateBaseColumn { - static override readonly [entityKind]: string = 'MySqlTimestampString'; + static override readonly [entityKind]: string = 'GoogleSqlTimestampString'; readonly fsp: number | undefined = this.config.fsp; @@ -101,25 +101,25 @@ export class MySqlTimestampString { +export interface GoogleSqlTimestampConfig { mode?: TMode; fsp?: TimestampFsp; } -export function timestamp(): MySqlTimestampBuilderInitial<''>; -export function timestamp( - config?: MySqlTimestampConfig, -): Equal extends true ? MySqlTimestampStringBuilderInitial<''> - : MySqlTimestampBuilderInitial<''>; -export function timestamp( +export function timestamp(): GoogleSqlTimestampBuilderInitial<''>; +export function timestamp( + config?: GoogleSqlTimestampConfig, +): Equal extends true ? GoogleSqlTimestampStringBuilderInitial<''> + : GoogleSqlTimestampBuilderInitial<''>; +export function timestamp( name: TName, - config?: MySqlTimestampConfig, -): Equal extends true ? MySqlTimestampStringBuilderInitial - : MySqlTimestampBuilderInitial; -export function timestamp(a?: string | MySqlTimestampConfig, b: MySqlTimestampConfig = {}) { - const { name, config } = getColumnNameAndConfig(a, b); + config?: GoogleSqlTimestampConfig, +): Equal extends true ? GoogleSqlTimestampStringBuilderInitial + : GoogleSqlTimestampBuilderInitial; +export function timestamp(a?: string | GoogleSqlTimestampConfig, b: GoogleSqlTimestampConfig = {}) { + const { name, config } = getColumnNameAndConfig(a, b); if (config?.mode === 'string') { - return new MySqlTimestampStringBuilder(name, config); + return new GoogleSqlTimestampStringBuilder(name, config); } - return new MySqlTimestampBuilder(name, config); + return new GoogleSqlTimestampBuilder(name, config); } diff --git a/drizzle-orm/src/googlesql/columns/tinyint.ts b/drizzle-orm/src/googlesql/columns/tinyint.ts index a7de703e1e..471b5bf842 100644 --- a/drizzle-orm/src/googlesql/columns/tinyint.ts +++ b/drizzle-orm/src/googlesql/columns/tinyint.ts @@ -1,45 +1,45 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/googlesql/table.ts'; +import type { AnyGoogleSqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig } from '~/utils.ts'; -import { MySqlColumnBuilderWithAutoIncrement, MySqlColumnWithAutoIncrement } from './common.ts'; -import type { MySqlIntConfig } from './int.ts'; +import { GoogleSqlColumnBuilderWithAutoIncrement, GoogleSqlColumnWithAutoIncrement } from './common.ts'; +import type { GoogleSqlIntConfig } from './int.ts'; -export type MySqlTinyIntBuilderInitial = MySqlTinyIntBuilder<{ +export type GoogleSqlTinyIntBuilderInitial = GoogleSqlTinyIntBuilder<{ name: TName; dataType: 'number'; - columnType: 'MySqlTinyInt'; + columnType: 'GoogleSqlTinyInt'; data: number; driverParam: number | string; enumValues: undefined; }>; -export class MySqlTinyIntBuilder> - extends MySqlColumnBuilderWithAutoIncrement +export class GoogleSqlTinyIntBuilder> + extends GoogleSqlColumnBuilderWithAutoIncrement { - static override readonly [entityKind]: string = 'MySqlTinyIntBuilder'; + static override readonly [entityKind]: string = 'GoogleSqlTinyIntBuilder'; - constructor(name: T['name'], config?: MySqlIntConfig) { - super(name, 'number', 'MySqlTinyInt'); + constructor(name: T['name'], config?: GoogleSqlIntConfig) { + super(name, 'number', 'GoogleSqlTinyInt'); this.config.unsigned = config ? config.unsigned : false; } /** @internal */ override build( - table: AnyMySqlTable<{ name: TTableName }>, - ): MySqlTinyInt> { - return new MySqlTinyInt>( + table: AnyGoogleSqlTable<{ name: TTableName }>, + ): GoogleSqlTinyInt> { + return new GoogleSqlTinyInt>( table, this.config as ColumnBuilderRuntimeConfig, ); } } -export class MySqlTinyInt> - extends MySqlColumnWithAutoIncrement +export class GoogleSqlTinyInt> + extends GoogleSqlColumnWithAutoIncrement { - static override readonly [entityKind]: string = 'MySqlTinyInt'; + static override readonly [entityKind]: string = 'GoogleSqlTinyInt'; getSQLType(): string { return `tinyint${this.config.unsigned ? ' unsigned' : ''}`; @@ -53,15 +53,15 @@ export class MySqlTinyInt> } } -export function tinyint(): MySqlTinyIntBuilderInitial<''>; +export function tinyint(): GoogleSqlTinyIntBuilderInitial<''>; export function tinyint( - config?: MySqlIntConfig, -): MySqlTinyIntBuilderInitial<''>; + config?: GoogleSqlIntConfig, +): GoogleSqlTinyIntBuilderInitial<''>; export function tinyint( name: TName, - config?: MySqlIntConfig, -): MySqlTinyIntBuilderInitial; -export function tinyint(a?: string | MySqlIntConfig, b?: MySqlIntConfig) { - const { name, config } = getColumnNameAndConfig(a, b); - return new MySqlTinyIntBuilder(name, config); + config?: GoogleSqlIntConfig, +): GoogleSqlTinyIntBuilderInitial; +export function tinyint(a?: string | GoogleSqlIntConfig, b?: GoogleSqlIntConfig) { + const { name, config } = getColumnNameAndConfig(a, b); + return new GoogleSqlTinyIntBuilder(name, config); } diff --git a/drizzle-orm/src/googlesql/columns/varbinary.ts b/drizzle-orm/src/googlesql/columns/varbinary.ts index 1dfffd3c1d..03533eb6d8 100644 --- a/drizzle-orm/src/googlesql/columns/varbinary.ts +++ b/drizzle-orm/src/googlesql/columns/varbinary.ts @@ -1,45 +1,45 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/googlesql/table.ts'; +import type { AnyGoogleSqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig } from '~/utils.ts'; -import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; +import { GoogleSqlColumn, GoogleSqlColumnBuilder } from './common.ts'; -export type MySqlVarBinaryBuilderInitial = MySqlVarBinaryBuilder<{ +export type GoogleSqlVarBinaryBuilderInitial = GoogleSqlVarBinaryBuilder<{ name: TName; dataType: 'string'; - columnType: 'MySqlVarBinary'; + columnType: 'GoogleSqlVarBinary'; data: string; driverParam: string; enumValues: undefined; }>; -export class MySqlVarBinaryBuilder> - extends MySqlColumnBuilder +export class GoogleSqlVarBinaryBuilder> + extends GoogleSqlColumnBuilder { - static override readonly [entityKind]: string = 'MySqlVarBinaryBuilder'; + static override readonly [entityKind]: string = 'GoogleSqlVarBinaryBuilder'; /** @internal */ - constructor(name: T['name'], config: MySqlVarbinaryOptions) { - super(name, 'string', 'MySqlVarBinary'); + constructor(name: T['name'], config: GoogleSqlVarbinaryOptions) { + super(name, 'string', 'GoogleSqlVarBinary'); this.config.length = config?.length; } /** @internal */ override build( - table: AnyMySqlTable<{ name: TTableName }>, - ): MySqlVarBinary> { - return new MySqlVarBinary>( + table: AnyGoogleSqlTable<{ name: TTableName }>, + ): GoogleSqlVarBinary> { + return new GoogleSqlVarBinary>( table, this.config as ColumnBuilderRuntimeConfig, ); } } -export class MySqlVarBinary< - T extends ColumnBaseConfig<'string', 'MySqlVarBinary'>, -> extends MySqlColumn { - static override readonly [entityKind]: string = 'MySqlVarBinary'; +export class GoogleSqlVarBinary< + T extends ColumnBaseConfig<'string', 'GoogleSqlVarBinary'>, +> extends GoogleSqlColumn { + static override readonly [entityKind]: string = 'GoogleSqlVarBinary'; length: number | undefined = this.config.length; @@ -48,18 +48,18 @@ export class MySqlVarBinary< } } -export interface MySqlVarbinaryOptions { +export interface GoogleSqlVarbinaryOptions { length: number; } export function varbinary( - config: MySqlVarbinaryOptions, -): MySqlVarBinaryBuilderInitial<''>; + config: GoogleSqlVarbinaryOptions, +): GoogleSqlVarBinaryBuilderInitial<''>; export function varbinary( name: TName, - config: MySqlVarbinaryOptions, -): MySqlVarBinaryBuilderInitial; -export function varbinary(a?: string | MySqlVarbinaryOptions, b?: MySqlVarbinaryOptions) { - const { name, config } = getColumnNameAndConfig(a, b); - return new MySqlVarBinaryBuilder(name, config); + config: GoogleSqlVarbinaryOptions, +): GoogleSqlVarBinaryBuilderInitial; +export function varbinary(a?: string | GoogleSqlVarbinaryOptions, b?: GoogleSqlVarbinaryOptions) { + const { name, config } = getColumnNameAndConfig(a, b); + return new GoogleSqlVarBinaryBuilder(name, config); } diff --git a/drizzle-orm/src/googlesql/columns/varchar.ts b/drizzle-orm/src/googlesql/columns/varchar.ts index ad722fb9a9..8f242e1b46 100644 --- a/drizzle-orm/src/googlesql/columns/varchar.ts +++ b/drizzle-orm/src/googlesql/columns/varchar.ts @@ -1,19 +1,19 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/googlesql/table.ts'; +import type { AnyGoogleSqlTable } from '~/googlesql/table.ts'; import { getColumnNameAndConfig, type Writable } from '~/utils.ts'; -import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; +import { GoogleSqlColumn, GoogleSqlColumnBuilder } from './common.ts'; -export type MySqlVarCharBuilderInitial< +export type GoogleSqlVarCharBuilderInitial< TName extends string, TEnum extends [string, ...string[]], TLength extends number | undefined, -> = MySqlVarCharBuilder< +> = GoogleSqlVarCharBuilder< { name: TName; dataType: 'string'; - columnType: 'MySqlVarChar'; + columnType: 'GoogleSqlVarChar'; data: TEnum[number]; driverParam: number | string; enumValues: TEnum; @@ -21,33 +21,33 @@ export type MySqlVarCharBuilderInitial< } >; -export class MySqlVarCharBuilder< - T extends ColumnBuilderBaseConfig<'string', 'MySqlVarChar'> & { length?: number | undefined }, -> extends MySqlColumnBuilder> { - static override readonly [entityKind]: string = 'MySqlVarCharBuilder'; +export class GoogleSqlVarCharBuilder< + T extends ColumnBuilderBaseConfig<'string', 'GoogleSqlVarChar'> & { length?: number | undefined }, +> extends GoogleSqlColumnBuilder> { + static override readonly [entityKind]: string = 'GoogleSqlVarCharBuilder'; /** @internal */ - constructor(name: T['name'], config: MySqlVarCharConfig) { - super(name, 'string', 'MySqlVarChar'); + constructor(name: T['name'], config: GoogleSqlVarCharConfig) { + super(name, 'string', 'GoogleSqlVarChar'); this.config.length = config.length; this.config.enum = config.enum; } /** @internal */ override build( - table: AnyMySqlTable<{ name: TTableName }>, - ): MySqlVarChar & { length: T['length']; enumValues: T['enumValues'] }> { - return new MySqlVarChar & { length: T['length']; enumValues: T['enumValues'] }>( + table: AnyGoogleSqlTable<{ name: TTableName }>, + ): GoogleSqlVarChar & { length: T['length']; enumValues: T['enumValues'] }> { + return new GoogleSqlVarChar & { length: T['length']; enumValues: T['enumValues'] }>( table, this.config as ColumnBuilderRuntimeConfig, ); } } -export class MySqlVarChar & { length?: number | undefined }> - extends MySqlColumn, { length: T['length'] }> +export class GoogleSqlVarChar & { length?: number | undefined }> + extends GoogleSqlColumn, { length: T['length'] }> { - static override readonly [entityKind]: string = 'MySqlVarChar'; + static override readonly [entityKind]: string = 'GoogleSqlVarChar'; readonly length: number | undefined = this.config.length; @@ -58,7 +58,7 @@ export class MySqlVarChar & } } -export interface MySqlVarCharConfig< +export interface GoogleSqlVarCharConfig< TEnum extends string[] | readonly string[] | undefined = string[] | readonly string[] | undefined, TLength extends number | undefined = number | undefined, > { @@ -67,8 +67,8 @@ export interface MySqlVarCharConfig< } export function varchar, L extends number | undefined>( - config: MySqlVarCharConfig, L>, -): MySqlVarCharBuilderInitial<'', Writable, L>; + config: GoogleSqlVarCharConfig, L>, +): GoogleSqlVarCharBuilderInitial<'', Writable, L>; export function varchar< TName extends string, U extends string, @@ -76,9 +76,9 @@ export function varchar< L extends number | undefined, >( name: TName, - config: MySqlVarCharConfig, L>, -): MySqlVarCharBuilderInitial, L>; -export function varchar(a?: string | MySqlVarCharConfig, b?: MySqlVarCharConfig): any { - const { name, config } = getColumnNameAndConfig(a, b); - return new MySqlVarCharBuilder(name, config as any); + config: GoogleSqlVarCharConfig, L>, +): GoogleSqlVarCharBuilderInitial, L>; +export function varchar(a?: string | GoogleSqlVarCharConfig, b?: GoogleSqlVarCharConfig): any { + const { name, config } = getColumnNameAndConfig(a, b); + return new GoogleSqlVarCharBuilder(name, config as any); } diff --git a/drizzle-orm/src/googlesql/columns/year.ts b/drizzle-orm/src/googlesql/columns/year.ts index bac330234d..7f83fc69af 100644 --- a/drizzle-orm/src/googlesql/columns/year.ts +++ b/drizzle-orm/src/googlesql/columns/year.ts @@ -1,45 +1,45 @@ import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts'; import type { ColumnBaseConfig } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { AnyMySqlTable } from '~/googlesql/table.ts'; -import { MySqlColumn, MySqlColumnBuilder } from './common.ts'; +import type { AnyGoogleSqlTable } from '~/googlesql/table.ts'; +import { GoogleSqlColumn, GoogleSqlColumnBuilder } from './common.ts'; -export type MySqlYearBuilderInitial = MySqlYearBuilder<{ +export type GoogleSqlYearBuilderInitial = GoogleSqlYearBuilder<{ name: TName; dataType: 'number'; - columnType: 'MySqlYear'; + columnType: 'GoogleSqlYear'; data: number; driverParam: number; enumValues: undefined; }>; -export class MySqlYearBuilder> extends MySqlColumnBuilder { - static override readonly [entityKind]: string = 'MySqlYearBuilder'; +export class GoogleSqlYearBuilder> extends GoogleSqlColumnBuilder { + static override readonly [entityKind]: string = 'GoogleSqlYearBuilder'; constructor(name: T['name']) { - super(name, 'number', 'MySqlYear'); + super(name, 'number', 'GoogleSqlYear'); } /** @internal */ override build( - table: AnyMySqlTable<{ name: TTableName }>, - ): MySqlYear> { - return new MySqlYear>(table, this.config as ColumnBuilderRuntimeConfig); + table: AnyGoogleSqlTable<{ name: TTableName }>, + ): GoogleSqlYear> { + return new GoogleSqlYear>(table, this.config as ColumnBuilderRuntimeConfig); } } -export class MySqlYear< - T extends ColumnBaseConfig<'number', 'MySqlYear'>, -> extends MySqlColumn { - static override readonly [entityKind]: string = 'MySqlYear'; +export class GoogleSqlYear< + T extends ColumnBaseConfig<'number', 'GoogleSqlYear'>, +> extends GoogleSqlColumn { + static override readonly [entityKind]: string = 'GoogleSqlYear'; getSQLType(): string { return `year`; } } -export function year(): MySqlYearBuilderInitial<''>; -export function year(name: TName): MySqlYearBuilderInitial; +export function year(): GoogleSqlYearBuilderInitial<''>; +export function year(name: TName): GoogleSqlYearBuilderInitial; export function year(name?: string) { - return new MySqlYearBuilder(name ?? ''); + return new GoogleSqlYearBuilder(name ?? ''); } diff --git a/drizzle-orm/src/googlesql/db.ts b/drizzle-orm/src/googlesql/db.ts index 6f79488383..a35718be5a 100644 --- a/drizzle-orm/src/googlesql/db.ts +++ b/drizzle-orm/src/googlesql/db.ts @@ -6,37 +6,37 @@ import { SelectionProxyHandler } from '~/selection-proxy.ts'; import { type ColumnsSelection, type SQL, sql, type SQLWrapper } from '~/sql/sql.ts'; import { WithSubquery } from '~/subquery.ts'; import type { DrizzleTypeError } from '~/utils.ts'; -import type { MySqlDialect } from './dialect.ts'; -import { MySqlCountBuilder } from './query-builders/count.ts'; +import type { GoogleSqlDialect } from './dialect.ts'; +import { GoogleSqlCountBuilder } from './query-builders/count.ts'; import { - MySqlDeleteBase, - MySqlInsertBuilder, - MySqlSelectBuilder, - MySqlUpdateBuilder, + GoogleSqlDeleteBase, + GoogleSqlInsertBuilder, + GoogleSqlSelectBuilder, + GoogleSqlUpdateBuilder, QueryBuilder, } from './query-builders/index.ts'; import { RelationalQueryBuilder } from './query-builders/query.ts'; import type { SelectedFields } from './query-builders/select.types.ts'; import type { Mode, - MySqlQueryResultHKT, - MySqlQueryResultKind, - MySqlSession, - MySqlTransaction, - MySqlTransactionConfig, + GoogleSqlQueryResultHKT, + GoogleSqlQueryResultKind, + GoogleSqlSession, + GoogleSqlTransaction, + GoogleSqlTransactionConfig, PreparedQueryHKTBase, } from './session.ts'; import type { WithBuilder } from './subquery.ts'; -import type { MySqlTable } from './table.ts'; -import type { MySqlViewBase } from './view-base.ts'; +import type { GoogleSqlTable } from './table.ts'; +import type { GoogleSqlViewBase } from './view-base.ts'; -export class MySqlDatabase< - TQueryResult extends MySqlQueryResultHKT, +export class GoogleSqlDatabase< + TQueryResult extends GoogleSqlQueryResultHKT, TPreparedQueryHKT extends PreparedQueryHKTBase, TFullSchema extends Record = {}, TSchema extends TablesRelationalConfig = ExtractTablesWithRelations, > { - static readonly [entityKind]: string = 'MySqlDatabase'; + static readonly [entityKind]: string = 'GoogleSqlDatabase'; declare readonly _: { readonly schema: TSchema | undefined; @@ -52,9 +52,9 @@ export class MySqlDatabase< constructor( /** @internal */ - readonly dialect: MySqlDialect, + readonly dialect: GoogleSqlDialect, /** @internal */ - readonly session: MySqlSession, + readonly session: GoogleSqlSession, schema: RelationalSchemaConfig | undefined, protected readonly mode: Mode, ) { @@ -72,12 +72,12 @@ export class MySqlDatabase< this.query = {} as typeof this['query']; if (this._.schema) { for (const [tableName, columns] of Object.entries(this._.schema)) { - (this.query as MySqlDatabase>['query'])[tableName] = + (this.query as GoogleSqlDatabase>['query'])[tableName] = new RelationalQueryBuilder( schema!.fullSchema, this._.schema, this._.tableNamesMap, - schema!.fullSchema[tableName] as MySqlTable, + schema!.fullSchema[tableName] as GoogleSqlTable, columns, dialect, session, @@ -145,10 +145,10 @@ export class MySqlDatabase< }; $count( - source: MySqlTable | MySqlViewBase | SQL | SQLWrapper, + source: GoogleSqlTable | GoogleSqlViewBase | SQL | SQLWrapper, filters?: SQL, ) { - return new MySqlCountBuilder({ source, filters, session: this.session }); + return new GoogleSqlCountBuilder({ source, filters, session: this.session }); } /** @@ -209,12 +209,12 @@ export class MySqlDatabase< * .from(cars); * ``` */ - function select(): MySqlSelectBuilder; + function select(): GoogleSqlSelectBuilder; function select( fields: TSelection, - ): MySqlSelectBuilder; - function select(fields?: SelectedFields): MySqlSelectBuilder { - return new MySqlSelectBuilder({ + ): GoogleSqlSelectBuilder; + function select(fields?: SelectedFields): GoogleSqlSelectBuilder { + return new GoogleSqlSelectBuilder({ fields: fields ?? undefined, session: self.session, dialect: self.dialect, @@ -246,14 +246,14 @@ export class MySqlDatabase< * .orderBy(cars.brand); * ``` */ - function selectDistinct(): MySqlSelectBuilder; + function selectDistinct(): GoogleSqlSelectBuilder; function selectDistinct( fields: TSelection, - ): MySqlSelectBuilder; + ): GoogleSqlSelectBuilder; function selectDistinct( fields?: SelectedFields, - ): MySqlSelectBuilder { - return new MySqlSelectBuilder({ + ): GoogleSqlSelectBuilder { + return new GoogleSqlSelectBuilder({ fields: fields ?? undefined, session: self.session, dialect: self.dialect, @@ -283,10 +283,10 @@ export class MySqlDatabase< * await db.update(cars).set({ color: 'red' }).where(eq(cars.brand, 'BMW')); * ``` */ - function update( + function update( table: TTable, - ): MySqlUpdateBuilder { - return new MySqlUpdateBuilder(table, self.session, self.dialect, queries); + ): GoogleSqlUpdateBuilder { + return new GoogleSqlUpdateBuilder(table, self.session, self.dialect, queries); } /** @@ -308,10 +308,10 @@ export class MySqlDatabase< * await db.delete(cars).where(eq(cars.color, 'green')); * ``` */ - function delete_( + function delete_( table: TTable, - ): MySqlDeleteBase { - return new MySqlDeleteBase(table, self.session, self.dialect, queries); + ): GoogleSqlDeleteBase { + return new GoogleSqlDeleteBase(table, self.session, self.dialect, queries); } return { select, selectDistinct, update, delete: delete_ }; @@ -353,10 +353,10 @@ export class MySqlDatabase< * .from(cars); * ``` */ - select(): MySqlSelectBuilder; - select(fields: TSelection): MySqlSelectBuilder; - select(fields?: SelectedFields): MySqlSelectBuilder { - return new MySqlSelectBuilder({ fields: fields ?? undefined, session: this.session, dialect: this.dialect }); + select(): GoogleSqlSelectBuilder; + select(fields: TSelection): GoogleSqlSelectBuilder; + select(fields?: SelectedFields): GoogleSqlSelectBuilder { + return new GoogleSqlSelectBuilder({ fields: fields ?? undefined, session: this.session, dialect: this.dialect }); } /** @@ -383,12 +383,12 @@ export class MySqlDatabase< * .orderBy(cars.brand); * ``` */ - selectDistinct(): MySqlSelectBuilder; + selectDistinct(): GoogleSqlSelectBuilder; selectDistinct( fields: TSelection, - ): MySqlSelectBuilder; - selectDistinct(fields?: SelectedFields): MySqlSelectBuilder { - return new MySqlSelectBuilder({ + ): GoogleSqlSelectBuilder; + selectDistinct(fields?: SelectedFields): GoogleSqlSelectBuilder { + return new GoogleSqlSelectBuilder({ fields: fields ?? undefined, session: this.session, dialect: this.dialect, @@ -417,8 +417,8 @@ export class MySqlDatabase< * await db.update(cars).set({ color: 'red' }).where(eq(cars.brand, 'BMW')); * ``` */ - update(table: TTable): MySqlUpdateBuilder { - return new MySqlUpdateBuilder(table, this.session, this.dialect); + update(table: TTable): GoogleSqlUpdateBuilder { + return new GoogleSqlUpdateBuilder(table, this.session, this.dialect); } /** @@ -440,8 +440,8 @@ export class MySqlDatabase< * await db.insert(cars).values([{ brand: 'BMW' }, { brand: 'Porsche' }]); * ``` */ - insert(table: TTable): MySqlInsertBuilder { - return new MySqlInsertBuilder(table, this.session, this.dialect); + insert(table: TTable): GoogleSqlInsertBuilder { + return new GoogleSqlInsertBuilder(table, this.session, this.dialect); } /** @@ -463,22 +463,22 @@ export class MySqlDatabase< * await db.delete(cars).where(eq(cars.color, 'green')); * ``` */ - delete(table: TTable): MySqlDeleteBase { - return new MySqlDeleteBase(table, this.session, this.dialect); + delete(table: TTable): GoogleSqlDeleteBase { + return new GoogleSqlDeleteBase(table, this.session, this.dialect); } execute( query: SQLWrapper | string, - ): Promise> { + ): Promise> { return this.session.execute(typeof query === 'string' ? sql.raw(query) : query.getSQL()); } transaction( transaction: ( - tx: MySqlTransaction, - config?: MySqlTransactionConfig, + tx: GoogleSqlTransaction, + config?: GoogleSqlTransactionConfig, ) => Promise, - config?: MySqlTransactionConfig, + config?: GoogleSqlTransactionConfig, ): Promise { return this.session.transaction(transaction, config); } @@ -487,11 +487,11 @@ export class MySqlDatabase< export type MySQLWithReplicas = Q & { $primary: Q }; export const withReplicas = < - HKT extends MySqlQueryResultHKT, + HKT extends GoogleSqlQueryResultHKT, TPreparedQueryHKT extends PreparedQueryHKTBase, TFullSchema extends Record, TSchema extends TablesRelationalConfig, - Q extends MySqlDatabase< + Q extends GoogleSqlDatabase< HKT, TPreparedQueryHKT, TFullSchema, diff --git a/drizzle-orm/src/googlesql/dialect.ts b/drizzle-orm/src/googlesql/dialect.ts index 8661359ab7..bb046b7dc2 100644 --- a/drizzle-orm/src/googlesql/dialect.ts +++ b/drizzle-orm/src/googlesql/dialect.ts @@ -23,37 +23,37 @@ import { Subquery } from '~/subquery.ts'; import { getTableName, getTableUniqueName, Table } from '~/table.ts'; import { type Casing, orderSelectedFields, type UpdateSet } from '~/utils.ts'; import { ViewBaseConfig } from '~/view-common.ts'; -import { MySqlColumn } from './columns/common.ts'; -import type { MySqlDeleteConfig } from './query-builders/delete.ts'; -import type { MySqlInsertConfig } from './query-builders/insert.ts'; +import { GoogleSqlColumn } from './columns/common.ts'; +import type { GoogleSqlDeleteConfig } from './query-builders/delete.ts'; +import type { GoogleSqlInsertConfig } from './query-builders/insert.ts'; import type { - AnyMySqlSelectQueryBuilder, - MySqlSelectConfig, - MySqlSelectJoinConfig, + AnyGoogleSqlSelectQueryBuilder, + GoogleSqlSelectConfig, + GoogleSqlSelectJoinConfig, SelectedFieldsOrdered, } from './query-builders/select.types.ts'; -import type { MySqlUpdateConfig } from './query-builders/update.ts'; -import type { MySqlSession } from './session.ts'; -import { MySqlTable } from './table.ts'; -import { MySqlViewBase } from './view-base.ts'; +import type { GoogleSqlUpdateConfig } from './query-builders/update.ts'; +import type { GoogleSqlSession } from './session.ts'; +import { GoogleSqlTable } from './table.ts'; +import { GoogleSqlViewBase } from './view-base.ts'; -export interface MySqlDialectConfig { +export interface GoogleSqlDialectConfig { casing?: Casing; } -export class MySqlDialect { - static readonly [entityKind]: string = 'MySqlDialect'; +export class GoogleSqlDialect { + static readonly [entityKind]: string = 'GoogleSqlDialect'; /** @internal */ readonly casing: CasingCache; - constructor(config?: MySqlDialectConfig) { + constructor(config?: GoogleSqlDialectConfig) { this.casing = new CasingCache(config?.casing); } async migrate( migrations: MigrationMeta[], - session: MySqlSession, + session: GoogleSqlSession, config: Omit, ): Promise { const migrationsTable = config.migrationsTable ?? '__drizzle_migrations'; @@ -117,7 +117,7 @@ export class MySqlDialect { return sql.join(withSqlChunks); } - buildDeleteQuery({ table, where, returning, withList, limit, orderBy }: MySqlDeleteConfig): SQL { + buildDeleteQuery({ table, where, returning, withList, limit, orderBy }: GoogleSqlDeleteConfig): SQL { const withSql = this.buildWithCTE(withList); const returningSql = returning @@ -133,7 +133,7 @@ export class MySqlDialect { return sql`${withSql}delete from ${table}${whereSql}${orderBySql}${limitSql}${returningSql}`; } - buildUpdateSet(table: MySqlTable, set: UpdateSet): SQL { + buildUpdateSet(table: GoogleSqlTable, set: UpdateSet): SQL { const tableColumns = table[Table.Symbol.Columns]; const columnNames = Object.keys(tableColumns).filter((colName) => @@ -154,7 +154,7 @@ export class MySqlDialect { })); } - buildUpdateQuery({ table, set, where, returning, withList, limit, orderBy }: MySqlUpdateConfig): SQL { + buildUpdateQuery({ table, set, where, returning, withList, limit, orderBy }: GoogleSqlUpdateConfig): SQL { const withSql = this.buildWithCTE(withList); const setSql = this.buildUpdateSet(table, set); @@ -202,7 +202,7 @@ export class MySqlDialect { chunk.push( new SQL( query.queryChunks.map((c) => { - if (is(c, MySqlColumn)) { + if (is(c, GoogleSqlColumn)) { return sql.identifier(this.casing.getColumnCasing(c)); } return c; @@ -240,7 +240,7 @@ export class MySqlDialect { : undefined; } - private buildOrderBy(orderBy: (MySqlColumn | SQL | SQL.Aliased)[] | undefined): SQL | undefined { + private buildOrderBy(orderBy: (GoogleSqlColumn | SQL | SQL.Aliased)[] | undefined): SQL | undefined { return orderBy && orderBy.length > 0 ? sql` order by ${sql.join(orderBy, sql`, `)}` : undefined; } @@ -275,16 +275,16 @@ export class MySqlDialect { useIndex, forceIndex, ignoreIndex, - }: MySqlSelectConfig, + }: GoogleSqlSelectConfig, ): SQL { - const fieldsList = fieldsFlat ?? orderSelectedFields(fields); + const fieldsList = fieldsFlat ?? orderSelectedFields(fields); for (const f of fieldsList) { if ( is(f.field, Column) && getTableName(f.field.table) !== (is(table, Subquery) ? table._.alias - : is(table, MySqlViewBase) + : is(table, GoogleSqlViewBase) ? table[ViewBaseConfig].name : is(table, SQL) ? undefined @@ -329,10 +329,10 @@ export class MySqlDialect { const table = joinMeta.table; const lateralSql = joinMeta.lateral ? sql` lateral` : undefined; - if (is(table, MySqlTable)) { - const tableName = table[MySqlTable.Symbol.Name]; - const tableSchema = table[MySqlTable.Symbol.Schema]; - const origTableName = table[MySqlTable.Symbol.OriginalName]; + if (is(table, GoogleSqlTable)) { + const tableName = table[GoogleSqlTable.Symbol.Name]; + const tableSchema = table[GoogleSqlTable.Symbol.Schema]; + const origTableName = table[GoogleSqlTable.Symbol.OriginalName]; const alias = tableName === origTableName ? undefined : joinMeta.alias; const useIndexSql = this.buildIndex({ indexes: joinMeta.useIndex, indexFor: 'USE' }); const forceIndexSql = this.buildIndex({ indexes: joinMeta.forceIndex, indexFor: 'FORCE' }); @@ -406,7 +406,7 @@ export class MySqlDialect { return finalQuery; } - buildSetOperations(leftSelect: SQL, setOperators: MySqlSelectConfig['setOperators']): SQL { + buildSetOperations(leftSelect: SQL, setOperators: GoogleSqlSelectConfig['setOperators']): SQL { const [setOperator, ...rest] = setOperators; if (!setOperator) { @@ -427,7 +427,7 @@ export class MySqlDialect { buildSetOperationQuery({ leftSelect, setOperator: { type, isAll, rightSelect, limit, orderBy, offset }, - }: { leftSelect: SQL; setOperator: MySqlSelectConfig['setOperators'][number] }): SQL { + }: { leftSelect: SQL; setOperator: GoogleSqlSelectConfig['setOperators'][number] }): SQL { const leftChunk = sql`(${leftSelect.getSQL()}) `; const rightChunk = sql`(${rightSelect.getSQL()})`; @@ -436,15 +436,15 @@ export class MySqlDialect { const orderByValues: (SQL | Name)[] = []; // The next bit is necessary because the sql operator replaces ${table.column} with `table`.`column` - // which is invalid MySql syntax, Table from one of the SELECTs cannot be used in global ORDER clause + // which is invalid GoogleSql syntax, Table from one of the SELECTs cannot be used in global ORDER clause for (const orderByUnit of orderBy) { - if (is(orderByUnit, MySqlColumn)) { + if (is(orderByUnit, GoogleSqlColumn)) { orderByValues.push(sql.identifier(this.casing.getColumnCasing(orderByUnit))); } else if (is(orderByUnit, SQL)) { for (let i = 0; i < orderByUnit.queryChunks.length; i++) { const chunk = orderByUnit.queryChunks[i]; - if (is(chunk, MySqlColumn)) { + if (is(chunk, GoogleSqlColumn)) { orderByUnit.queryChunks[i] = sql.identifier(this.casing.getColumnCasing(chunk)); } } @@ -470,12 +470,12 @@ export class MySqlDialect { } buildInsertQuery( - { table, values: valuesOrSelect, ignore, onConflict, select }: MySqlInsertConfig, + { table, values: valuesOrSelect, ignore, onConflict, select }: GoogleSqlInsertConfig, ): { sql: SQL; generatedIds: Record[] } { // const isSingleValue = values.length === 1; const valuesSqlList: ((SQLChunk | SQL)[] | SQL)[] = []; - const columns: Record = table[Table.Symbol.Columns]; - const colEntries: [string, MySqlColumn][] = Object.entries(columns).filter(([_, col]) => + const columns: Record = table[Table.Symbol.Columns]; + const colEntries: [string, GoogleSqlColumn][] = Object.entries(columns).filter(([_, col]) => !col.shouldDisableInsert() ); @@ -483,7 +483,7 @@ export class MySqlDialect { const generatedIdsResponse: Record[] = []; if (select) { - const select = valuesOrSelect as AnyMySqlSelectQueryBuilder | SQL; + const select = valuesOrSelect as AnyGoogleSqlSelectQueryBuilder | SQL; if (is(select, SQL)) { valuesSqlList.push(select); @@ -567,16 +567,16 @@ export class MySqlDialect { fullSchema: Record; schema: TablesRelationalConfig; tableNamesMap: Record; - table: MySqlTable; + table: GoogleSqlTable; tableConfig: TableRelationalConfig; queryConfig: true | DBQueryConfig<'many', true>; tableAlias: string; nestedQueryRelation?: Relation; joinOn?: SQL; - }): BuildRelationalQueryResult { - let selection: BuildRelationalQueryResult['selection'] = []; - let limit, offset, orderBy: MySqlSelectConfig['orderBy'], where; - const joins: MySqlSelectJoinConfig[] = []; + }): BuildRelationalQueryResult { + let selection: BuildRelationalQueryResult['selection'] = []; + let limit, offset, orderBy: GoogleSqlSelectConfig['orderBy'], where; + const joins: GoogleSqlSelectJoinConfig[] = []; if (config === true) { const selectionEntries = Object.entries(tableConfig.columns); @@ -585,7 +585,7 @@ export class MySqlDialect { ) => ({ dbKey: value.name, tsKey: key, - field: aliasedTableColumn(value as MySqlColumn, tableAlias), + field: aliasedTableColumn(value as GoogleSqlColumn, tableAlias), relationTableTsKey: undefined, isJson: false, selection: [], @@ -602,7 +602,7 @@ export class MySqlDialect { where = whereSql && mapColumnsInSQLToAlias(whereSql, tableAlias); } - const fieldsSelection: { tsKey: string; value: MySqlColumn | SQL.Aliased }[] = []; + const fieldsSelection: { tsKey: string; value: GoogleSqlColumn | SQL.Aliased }[] = []; let selectedColumns: string[] = []; // Figure out which columns to select @@ -633,7 +633,7 @@ export class MySqlDialect { } for (const field of selectedColumns) { - const column = tableConfig.columns[field]! as MySqlColumn; + const column = tableConfig.columns[field]! as GoogleSqlColumn; fieldsSelection.push({ tsKey: field, value: column }); } @@ -686,7 +686,7 @@ export class MySqlDialect { } orderBy = orderByOrig.map((orderByValue) => { if (is(orderByValue, Column)) { - return aliasedTableColumn(orderByValue, tableAlias) as MySqlColumn; + return aliasedTableColumn(orderByValue, tableAlias) as GoogleSqlColumn; } return mapColumnsInSQLToAlias(orderByValue, tableAlias); }); @@ -718,7 +718,7 @@ export class MySqlDialect { fullSchema, schema, tableNamesMap, - table: fullSchema[relationTableTsName] as MySqlTable, + table: fullSchema[relationTableTsName] as GoogleSqlTable, tableConfig: schema[relationTableTsName]!, queryConfig: is(relation, One) ? (selectedRelationConfigValue === true @@ -814,7 +814,7 @@ export class MySqlDialect { } result = this.buildSelectQuery({ - table: is(result, MySqlTable) ? result : new Subquery(result, {}, tableAlias), + table: is(result, GoogleSqlTable) ? result : new Subquery(result, {}, tableAlias), fields: {}, fieldsFlat: nestedSelection.map(({ field }) => ({ path: [], @@ -865,15 +865,15 @@ export class MySqlDialect { fullSchema: Record; schema: TablesRelationalConfig; tableNamesMap: Record; - table: MySqlTable; + table: GoogleSqlTable; tableConfig: TableRelationalConfig; queryConfig: true | DBQueryConfig<'many', true>; tableAlias: string; nestedQueryRelation?: Relation; joinOn?: SQL; - }): BuildRelationalQueryResult { - let selection: BuildRelationalQueryResult['selection'] = []; - let limit, offset, orderBy: MySqlSelectConfig['orderBy'] = [], where; + }): BuildRelationalQueryResult { + let selection: BuildRelationalQueryResult['selection'] = []; + let limit, offset, orderBy: GoogleSqlSelectConfig['orderBy'] = [], where; if (config === true) { const selectionEntries = Object.entries(tableConfig.columns); @@ -882,7 +882,7 @@ export class MySqlDialect { ) => ({ dbKey: value.name, tsKey: key, - field: aliasedTableColumn(value as MySqlColumn, tableAlias), + field: aliasedTableColumn(value as GoogleSqlColumn, tableAlias), relationTableTsKey: undefined, isJson: false, selection: [], @@ -899,7 +899,7 @@ export class MySqlDialect { where = whereSql && mapColumnsInSQLToAlias(whereSql, tableAlias); } - const fieldsSelection: { tsKey: string; value: MySqlColumn | SQL.Aliased }[] = []; + const fieldsSelection: { tsKey: string; value: GoogleSqlColumn | SQL.Aliased }[] = []; let selectedColumns: string[] = []; // Figure out which columns to select @@ -930,7 +930,7 @@ export class MySqlDialect { } for (const field of selectedColumns) { - const column = tableConfig.columns[field]! as MySqlColumn; + const column = tableConfig.columns[field]! as GoogleSqlColumn; fieldsSelection.push({ tsKey: field, value: column }); } @@ -983,7 +983,7 @@ export class MySqlDialect { } orderBy = orderByOrig.map((orderByValue) => { if (is(orderByValue, Column)) { - return aliasedTableColumn(orderByValue, tableAlias) as MySqlColumn; + return aliasedTableColumn(orderByValue, tableAlias) as GoogleSqlColumn; } return mapColumnsInSQLToAlias(orderByValue, tableAlias); }); @@ -1015,7 +1015,7 @@ export class MySqlDialect { fullSchema, schema, tableNamesMap, - table: fullSchema[relationTableTsName] as MySqlTable, + table: fullSchema[relationTableTsName] as GoogleSqlTable, tableConfig: schema[relationTableTsName]!, queryConfig: is(relation, One) ? (selectedRelationConfigValue === true @@ -1057,7 +1057,7 @@ export class MySqlDialect { let field = sql`json_array(${ sql.join( selection.map(({ field }) => - is(field, MySqlColumn) + is(field, GoogleSqlColumn) ? sql.identifier(this.casing.getColumnCasing(field)) : is(field, SQL.Aliased) ? field.sql @@ -1111,7 +1111,7 @@ export class MySqlDialect { } result = this.buildSelectQuery({ - table: is(result, MySqlTable) ? result : new Subquery(result, {}, tableAlias), + table: is(result, GoogleSqlTable) ? result : new Subquery(result, {}, tableAlias), fields: {}, fieldsFlat: nestedSelection.map(({ field }) => ({ path: [], diff --git a/drizzle-orm/src/googlesql/expressions.ts b/drizzle-orm/src/googlesql/expressions.ts index a61f77786e..e6dfb85e5e 100644 --- a/drizzle-orm/src/googlesql/expressions.ts +++ b/drizzle-orm/src/googlesql/expressions.ts @@ -1,16 +1,16 @@ import { bindIfParam } from '~/expressions.ts'; import type { Placeholder, SQL, SQLChunk, SQLWrapper } from '~/sql/sql.ts'; import { sql } from '~/sql/sql.ts'; -import type { MySqlColumn } from './columns/index.ts'; +import type { GoogleSqlColumn } from './columns/index.ts'; export * from '~/expressions.ts'; -export function concat(column: MySqlColumn | SQL.Aliased, value: string | Placeholder | SQLWrapper): SQL { +export function concat(column: GoogleSqlColumn | SQL.Aliased, value: string | Placeholder | SQLWrapper): SQL { return sql`${column} || ${bindIfParam(value, column)}`; } export function substring( - column: MySqlColumn | SQL.Aliased, + column: GoogleSqlColumn | SQL.Aliased, { from, for: _for }: { from?: number | Placeholder | SQLWrapper; for?: number | Placeholder | SQLWrapper }, ): SQL { const chunks: SQLChunk[] = [sql`substring(`, column]; diff --git a/drizzle-orm/src/googlesql/foreign-keys.ts b/drizzle-orm/src/googlesql/foreign-keys.ts index c8c34d6fd4..7d39372a65 100644 --- a/drizzle-orm/src/googlesql/foreign-keys.ts +++ b/drizzle-orm/src/googlesql/foreign-keys.ts @@ -1,19 +1,19 @@ import { entityKind } from '~/entity.ts'; import { TableName } from '~/table.utils.ts'; -import type { AnyMySqlColumn, MySqlColumn } from './columns/index.ts'; -import type { MySqlTable } from './table.ts'; +import type { AnyGoogleSqlColumn, GoogleSqlColumn } from './columns/index.ts'; +import type { GoogleSqlTable } from './table.ts'; export type UpdateDeleteAction = 'cascade' | 'restrict' | 'no action' | 'set null' | 'set default'; export type Reference = () => { readonly name?: string; - readonly columns: MySqlColumn[]; - readonly foreignTable: MySqlTable; - readonly foreignColumns: MySqlColumn[]; + readonly columns: GoogleSqlColumn[]; + readonly foreignTable: GoogleSqlTable; + readonly foreignColumns: GoogleSqlColumn[]; }; export class ForeignKeyBuilder { - static readonly [entityKind]: string = 'MySqlForeignKeyBuilder'; + static readonly [entityKind]: string = 'GoogleSqlForeignKeyBuilder'; /** @internal */ reference: Reference; @@ -27,8 +27,8 @@ export class ForeignKeyBuilder { constructor( config: () => { name?: string; - columns: MySqlColumn[]; - foreignColumns: MySqlColumn[]; + columns: GoogleSqlColumn[]; + foreignColumns: GoogleSqlColumn[]; }, actions?: { onUpdate?: UpdateDeleteAction; @@ -37,7 +37,7 @@ export class ForeignKeyBuilder { ) { this.reference = () => { const { name, columns, foreignColumns } = config(); - return { name, columns, foreignTable: foreignColumns[0]!.table as MySqlTable, foreignColumns }; + return { name, columns, foreignTable: foreignColumns[0]!.table as GoogleSqlTable, foreignColumns }; }; if (actions) { this._onUpdate = actions.onUpdate; @@ -56,7 +56,7 @@ export class ForeignKeyBuilder { } /** @internal */ - build(table: MySqlTable): ForeignKey { + build(table: GoogleSqlTable): ForeignKey { return new ForeignKey(table, this); } } @@ -64,13 +64,13 @@ export class ForeignKeyBuilder { export type AnyForeignKeyBuilder = ForeignKeyBuilder; export class ForeignKey { - static readonly [entityKind]: string = 'MySqlForeignKey'; + static readonly [entityKind]: string = 'GoogleSqlForeignKey'; readonly reference: Reference; readonly onUpdate: UpdateDeleteAction | undefined; readonly onDelete: UpdateDeleteAction | undefined; - constructor(readonly table: MySqlTable, builder: ForeignKeyBuilder) { + constructor(readonly table: GoogleSqlTable, builder: ForeignKeyBuilder) { this.reference = builder.reference; this.onUpdate = builder._onUpdate; this.onDelete = builder._onDelete; @@ -92,20 +92,20 @@ export class ForeignKey { type ColumnsWithTable< TTableName extends string, - TColumns extends MySqlColumn[], -> = { [Key in keyof TColumns]: AnyMySqlColumn<{ tableName: TTableName }> }; + TColumns extends GoogleSqlColumn[], +> = { [Key in keyof TColumns]: AnyGoogleSqlColumn<{ tableName: TTableName }> }; -export type GetColumnsTable = ( - TColumns extends MySqlColumn ? TColumns - : TColumns extends MySqlColumn[] ? TColumns[number] +export type GetColumnsTable = ( + TColumns extends GoogleSqlColumn ? TColumns + : TColumns extends GoogleSqlColumn[] ? TColumns[number] : never -) extends AnyMySqlColumn<{ tableName: infer TTableName extends string }> ? TTableName +) extends AnyGoogleSqlColumn<{ tableName: infer TTableName extends string }> ? TTableName : never; export function foreignKey< TTableName extends string, TForeignTableName extends string, - TColumns extends [AnyMySqlColumn<{ tableName: TTableName }>, ...AnyMySqlColumn<{ tableName: TTableName }>[]], + TColumns extends [AnyGoogleSqlColumn<{ tableName: TTableName }>, ...AnyGoogleSqlColumn<{ tableName: TTableName }>[]], >( config: { name?: string; diff --git a/drizzle-orm/src/googlesql/indexes.ts b/drizzle-orm/src/googlesql/indexes.ts index 5b73b1d309..cb920ba814 100644 --- a/drizzle-orm/src/googlesql/indexes.ts +++ b/drizzle-orm/src/googlesql/indexes.ts @@ -1,7 +1,7 @@ import { entityKind } from '~/entity.ts'; import type { SQL } from '~/sql/sql.ts'; -import type { AnyMySqlColumn, MySqlColumn } from './columns/index.ts'; -import type { MySqlTable } from './table.ts'; +import type { AnyGoogleSqlColumn, GoogleSqlColumn } from './columns/index.ts'; +import type { GoogleSqlTable } from './table.ts'; interface IndexConfig { name: string; @@ -29,10 +29,10 @@ interface IndexConfig { lock?: 'default' | 'none' | 'shared' | 'exclusive'; } -export type IndexColumn = MySqlColumn | SQL; +export type IndexColumn = GoogleSqlColumn | SQL; export class IndexBuilderOn { - static readonly [entityKind]: string = 'MySqlIndexBuilderOn'; + static readonly [entityKind]: string = 'GoogleSqlIndexBuilderOn'; constructor(private name: string, private unique: boolean) {} @@ -42,14 +42,14 @@ export class IndexBuilderOn { } export interface AnyIndexBuilder { - build(table: MySqlTable): Index; + build(table: GoogleSqlTable): Index; } // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface IndexBuilder extends AnyIndexBuilder {} export class IndexBuilder implements AnyIndexBuilder { - static readonly [entityKind]: string = 'MySqlIndexBuilder'; + static readonly [entityKind]: string = 'GoogleSqlIndexBuilder'; /** @internal */ config: IndexConfig; @@ -78,23 +78,23 @@ export class IndexBuilder implements AnyIndexBuilder { } /** @internal */ - build(table: MySqlTable): Index { + build(table: GoogleSqlTable): Index { return new Index(this.config, table); } } export class Index { - static readonly [entityKind]: string = 'MySqlIndex'; + static readonly [entityKind]: string = 'GoogleSqlIndex'; - readonly config: IndexConfig & { table: MySqlTable }; + readonly config: IndexConfig & { table: GoogleSqlTable }; - constructor(config: IndexConfig, table: MySqlTable) { + constructor(config: IndexConfig, table: GoogleSqlTable) { this.config = { ...config, table }; } } export type GetColumnsTableName = TColumns extends - AnyMySqlColumn<{ tableName: infer TTableName extends string }> | AnyMySqlColumn< + AnyGoogleSqlColumn<{ tableName: infer TTableName extends string }> | AnyGoogleSqlColumn< { tableName: infer TTableName extends string } >[] ? TTableName : never; diff --git a/drizzle-orm/src/googlesql/primary-keys.ts b/drizzle-orm/src/googlesql/primary-keys.ts index 014cbd8c0b..fd695bb9e4 100644 --- a/drizzle-orm/src/googlesql/primary-keys.ts +++ b/drizzle-orm/src/googlesql/primary-keys.ts @@ -1,11 +1,11 @@ import { entityKind } from '~/entity.ts'; -import type { AnyMySqlColumn, MySqlColumn } from './columns/index.ts'; -import { MySqlTable } from './table.ts'; +import type { AnyGoogleSqlColumn, GoogleSqlColumn } from './columns/index.ts'; +import { GoogleSqlTable } from './table.ts'; export function primaryKey< TTableName extends string, - TColumn extends AnyMySqlColumn<{ tableName: TTableName }>, - TColumns extends AnyMySqlColumn<{ tableName: TTableName }>[], + TColumn extends AnyGoogleSqlColumn<{ tableName: TTableName }>, + TColumns extends AnyGoogleSqlColumn<{ tableName: TTableName }>[], >(config: { name?: string; columns: [TColumn, ...TColumns] }): PrimaryKeyBuilder; /** * @deprecated: Please use primaryKey({ columns: [] }) instead of this function @@ -13,7 +13,7 @@ export function primaryKey< */ export function primaryKey< TTableName extends string, - TColumns extends AnyMySqlColumn<{ tableName: TTableName }>[], + TColumns extends AnyGoogleSqlColumn<{ tableName: TTableName }>[], >(...columns: TColumns): PrimaryKeyBuilder; export function primaryKey(...config: any) { if (config[0].columns) { @@ -23,16 +23,16 @@ export function primaryKey(...config: any) { } export class PrimaryKeyBuilder { - static readonly [entityKind]: string = 'MySqlPrimaryKeyBuilder'; + static readonly [entityKind]: string = 'GoogleSqlPrimaryKeyBuilder'; /** @internal */ - columns: MySqlColumn[]; + columns: GoogleSqlColumn[]; /** @internal */ name?: string; constructor( - columns: MySqlColumn[], + columns: GoogleSqlColumn[], name?: string, ) { this.columns = columns; @@ -40,24 +40,24 @@ export class PrimaryKeyBuilder { } /** @internal */ - build(table: MySqlTable): PrimaryKey { + build(table: GoogleSqlTable): PrimaryKey { return new PrimaryKey(table, this.columns, this.name); } } export class PrimaryKey { - static readonly [entityKind]: string = 'MySqlPrimaryKey'; + static readonly [entityKind]: string = 'GoogleSqlPrimaryKey'; - readonly columns: MySqlColumn[]; + readonly columns: GoogleSqlColumn[]; readonly name?: string; - constructor(readonly table: MySqlTable, columns: MySqlColumn[], name?: string) { + constructor(readonly table: GoogleSqlTable, columns: GoogleSqlColumn[], name?: string) { this.columns = columns; this.name = name; } getName(): string { return this.name - ?? `${this.table[MySqlTable.Symbol.Name]}_${this.columns.map((column) => column.name).join('_')}_pk`; + ?? `${this.table[GoogleSqlTable.Symbol.Name]}_${this.columns.map((column) => column.name).join('_')}_pk`; } } diff --git a/drizzle-orm/src/googlesql/query-builders/count.ts b/drizzle-orm/src/googlesql/query-builders/count.ts index 9a0241c70e..9c946b8690 100644 --- a/drizzle-orm/src/googlesql/query-builders/count.ts +++ b/drizzle-orm/src/googlesql/query-builders/count.ts @@ -1,28 +1,28 @@ import { entityKind } from '~/entity.ts'; import { SQL, sql, type SQLWrapper } from '~/sql/sql.ts'; -import type { MySqlSession } from '../session.ts'; -import type { MySqlTable } from '../table.ts'; -import type { MySqlViewBase } from '../view-base.ts'; +import type { GoogleSqlSession } from '../session.ts'; +import type { GoogleSqlTable } from '../table.ts'; +import type { GoogleSqlViewBase } from '../view-base.ts'; -export class MySqlCountBuilder< - TSession extends MySqlSession, +export class GoogleSqlCountBuilder< + TSession extends GoogleSqlSession, > extends SQL implements Promise, SQLWrapper { private sql: SQL; - static override readonly [entityKind] = 'MySqlCountBuilder'; - [Symbol.toStringTag] = 'MySqlCountBuilder'; + static override readonly [entityKind] = 'GoogleSqlCountBuilder'; + [Symbol.toStringTag] = 'GoogleSqlCountBuilder'; private session: TSession; private static buildEmbeddedCount( - source: MySqlTable | MySqlViewBase | SQL | SQLWrapper, + source: GoogleSqlTable | GoogleSqlViewBase | SQL | SQLWrapper, filters?: SQL, ): SQL { return sql`(select count(*) from ${source}${sql.raw(' where ').if(filters)}${filters})`; } private static buildCount( - source: MySqlTable | MySqlViewBase | SQL | SQLWrapper, + source: GoogleSqlTable | GoogleSqlViewBase | SQL | SQLWrapper, filters?: SQL, ): SQL { return sql`select count(*) as count from ${source}${sql.raw(' where ').if(filters)}${filters}`; @@ -30,18 +30,18 @@ export class MySqlCountBuilder< constructor( readonly params: { - source: MySqlTable | MySqlViewBase | SQL | SQLWrapper; + source: GoogleSqlTable | GoogleSqlViewBase | SQL | SQLWrapper; filters?: SQL; session: TSession; }, ) { - super(MySqlCountBuilder.buildEmbeddedCount(params.source, params.filters).queryChunks); + super(GoogleSqlCountBuilder.buildEmbeddedCount(params.source, params.filters).queryChunks); this.mapWith(Number); this.session = params.session; - this.sql = MySqlCountBuilder.buildCount( + this.sql = GoogleSqlCountBuilder.buildCount( params.source, params.filters, ); diff --git a/drizzle-orm/src/googlesql/query-builders/delete.ts b/drizzle-orm/src/googlesql/query-builders/delete.ts index d102e3b528..beb6027e37 100644 --- a/drizzle-orm/src/googlesql/query-builders/delete.ts +++ b/drizzle-orm/src/googlesql/query-builders/delete.ts @@ -1,31 +1,31 @@ import { entityKind } from '~/entity.ts'; -import type { MySqlDialect } from '~/googlesql/dialect.ts'; +import type { GoogleSqlDialect } from '~/googlesql/dialect.ts'; import type { - AnyMySqlQueryResultHKT, - MySqlPreparedQueryConfig, - MySqlQueryResultHKT, - MySqlQueryResultKind, - MySqlSession, + AnyGoogleSqlQueryResultHKT, + GoogleSqlPreparedQueryConfig, + GoogleSqlQueryResultHKT, + GoogleSqlQueryResultKind, + GoogleSqlSession, PreparedQueryHKTBase, PreparedQueryKind, } from '~/googlesql/session.ts'; -import type { MySqlTable } from '~/googlesql/table.ts'; +import type { GoogleSqlTable } from '~/googlesql/table.ts'; import { QueryPromise } from '~/query-promise.ts'; import { SelectionProxyHandler } from '~/selection-proxy.ts'; import type { Placeholder, Query, SQL, SQLWrapper } from '~/sql/sql.ts'; import type { Subquery } from '~/subquery.ts'; import { Table } from '~/table.ts'; import type { ValueOrArray } from '~/utils.ts'; -import type { MySqlColumn } from '../columns/common.ts'; +import type { GoogleSqlColumn } from '../columns/common.ts'; import type { SelectedFieldsOrdered } from './select.types.ts'; -export type MySqlDeleteWithout< - T extends AnyMySqlDeleteBase, +export type GoogleSqlDeleteWithout< + T extends AnyGoogleSqlDeleteBase, TDynamic extends boolean, K extends keyof T & string, > = TDynamic extends true ? T : Omit< - MySqlDeleteBase< + GoogleSqlDeleteBase< T['_']['table'], T['_']['queryResult'], T['_']['preparedQueryHKT'], @@ -35,45 +35,45 @@ export type MySqlDeleteWithout< T['_']['excludedMethods'] | K >; -export type MySqlDelete< - TTable extends MySqlTable = MySqlTable, - TQueryResult extends MySqlQueryResultHKT = AnyMySqlQueryResultHKT, +export type GoogleSqlDelete< + TTable extends GoogleSqlTable = GoogleSqlTable, + TQueryResult extends GoogleSqlQueryResultHKT = AnyGoogleSqlQueryResultHKT, TPreparedQueryHKT extends PreparedQueryHKTBase = PreparedQueryHKTBase, -> = MySqlDeleteBase; +> = GoogleSqlDeleteBase; -export interface MySqlDeleteConfig { +export interface GoogleSqlDeleteConfig { where?: SQL | undefined; limit?: number | Placeholder; - orderBy?: (MySqlColumn | SQL | SQL.Aliased)[]; - table: MySqlTable; + orderBy?: (GoogleSqlColumn | SQL | SQL.Aliased)[]; + table: GoogleSqlTable; returning?: SelectedFieldsOrdered; withList?: Subquery[]; } -export type MySqlDeletePrepare = PreparedQueryKind< +export type GoogleSqlDeletePrepare = PreparedQueryKind< T['_']['preparedQueryHKT'], - MySqlPreparedQueryConfig & { - execute: MySqlQueryResultKind; + GoogleSqlPreparedQueryConfig & { + execute: GoogleSqlQueryResultKind; iterator: never; }, true >; -type MySqlDeleteDynamic = MySqlDelete< +type GoogleSqlDeleteDynamic = GoogleSqlDelete< T['_']['table'], T['_']['queryResult'], T['_']['preparedQueryHKT'] >; -type AnyMySqlDeleteBase = MySqlDeleteBase; +type AnyGoogleSqlDeleteBase = GoogleSqlDeleteBase; -export interface MySqlDeleteBase< - TTable extends MySqlTable, - TQueryResult extends MySqlQueryResultHKT, +export interface GoogleSqlDeleteBase< + TTable extends GoogleSqlTable, + TQueryResult extends GoogleSqlQueryResultHKT, TPreparedQueryHKT extends PreparedQueryHKTBase, TDynamic extends boolean = false, TExcludedMethods extends string = never, -> extends QueryPromise> { +> extends QueryPromise> { readonly _: { readonly table: TTable; readonly queryResult: TQueryResult; @@ -83,23 +83,23 @@ export interface MySqlDeleteBase< }; } -export class MySqlDeleteBase< - TTable extends MySqlTable, - TQueryResult extends MySqlQueryResultHKT, +export class GoogleSqlDeleteBase< + TTable extends GoogleSqlTable, + TQueryResult extends GoogleSqlQueryResultHKT, // eslint-disable-next-line @typescript-eslint/no-unused-vars TPreparedQueryHKT extends PreparedQueryHKTBase, TDynamic extends boolean = false, // eslint-disable-next-line @typescript-eslint/no-unused-vars TExcludedMethods extends string = never, -> extends QueryPromise> implements SQLWrapper { - static override readonly [entityKind]: string = 'MySqlDelete'; +> extends QueryPromise> implements SQLWrapper { + static override readonly [entityKind]: string = 'GoogleSqlDelete'; - private config: MySqlDeleteConfig; + private config: GoogleSqlDeleteConfig; constructor( private table: TTable, - private session: MySqlSession, - private dialect: MySqlDialect, + private session: GoogleSqlSession, + private dialect: GoogleSqlDialect, withList?: Subquery[], ) { super(); @@ -135,20 +135,20 @@ export class MySqlDeleteBase< * db.delete(cars).where(or(eq(cars.color, 'green'), eq(cars.color, 'blue'))); * ``` */ - where(where: SQL | undefined): MySqlDeleteWithout { + where(where: SQL | undefined): GoogleSqlDeleteWithout { this.config.where = where; return this as any; } orderBy( - builder: (deleteTable: TTable) => ValueOrArray, - ): MySqlDeleteWithout; - orderBy(...columns: (MySqlColumn | SQL | SQL.Aliased)[]): MySqlDeleteWithout; + builder: (deleteTable: TTable) => ValueOrArray, + ): GoogleSqlDeleteWithout; + orderBy(...columns: (GoogleSqlColumn | SQL | SQL.Aliased)[]): GoogleSqlDeleteWithout; orderBy( ...columns: - | [(deleteTable: TTable) => ValueOrArray] - | (MySqlColumn | SQL | SQL.Aliased)[] - ): MySqlDeleteWithout { + | [(deleteTable: TTable) => ValueOrArray] + | (GoogleSqlColumn | SQL | SQL.Aliased)[] + ): GoogleSqlDeleteWithout { if (typeof columns[0] === 'function') { const orderBy = columns[0]( new Proxy( @@ -160,13 +160,13 @@ export class MySqlDeleteBase< const orderByArray = Array.isArray(orderBy) ? orderBy : [orderBy]; this.config.orderBy = orderByArray; } else { - const orderByArray = columns as (MySqlColumn | SQL | SQL.Aliased)[]; + const orderByArray = columns as (GoogleSqlColumn | SQL | SQL.Aliased)[]; this.config.orderBy = orderByArray; } return this as any; } - limit(limit: number | Placeholder): MySqlDeleteWithout { + limit(limit: number | Placeholder): GoogleSqlDeleteWithout { this.config.limit = limit; return this as any; } @@ -181,11 +181,11 @@ export class MySqlDeleteBase< return rest; } - prepare(): MySqlDeletePrepare { + prepare(): GoogleSqlDeletePrepare { return this.session.prepareQuery( this.dialect.sqlToQuery(this.getSQL()), this.config.returning, - ) as MySqlDeletePrepare; + ) as GoogleSqlDeletePrepare; } override execute: ReturnType['execute'] = (placeholderValues) => { @@ -201,7 +201,7 @@ export class MySqlDeleteBase< iterator = this.createIterator(); - $dynamic(): MySqlDeleteDynamic { + $dynamic(): GoogleSqlDeleteDynamic { return this as any; } } diff --git a/drizzle-orm/src/googlesql/query-builders/insert.ts b/drizzle-orm/src/googlesql/query-builders/insert.ts index 09a8b31e62..85f9d3e576 100644 --- a/drizzle-orm/src/googlesql/query-builders/insert.ts +++ b/drizzle-orm/src/googlesql/query-builders/insert.ts @@ -1,15 +1,15 @@ import { entityKind, is } from '~/entity.ts'; -import type { MySqlDialect } from '~/googlesql/dialect.ts'; +import type { GoogleSqlDialect } from '~/googlesql/dialect.ts'; import type { - AnyMySqlQueryResultHKT, - MySqlPreparedQueryConfig, - MySqlQueryResultHKT, - MySqlQueryResultKind, - MySqlSession, + AnyGoogleSqlQueryResultHKT, + GoogleSqlPreparedQueryConfig, + GoogleSqlQueryResultHKT, + GoogleSqlQueryResultKind, + GoogleSqlSession, PreparedQueryHKTBase, PreparedQueryKind, } from '~/googlesql/session.ts'; -import type { MySqlTable } from '~/googlesql/table.ts'; +import type { GoogleSqlTable } from '~/googlesql/table.ts'; import type { TypedQueryBuilder } from '~/query-builders/query-builder.ts'; import { QueryPromise } from '~/query-promise.ts'; import type { RunnableQuery } from '~/runnable-query.ts'; @@ -18,45 +18,45 @@ import { Param, SQL, sql } from '~/sql/sql.ts'; import type { InferModelFromColumns } from '~/table.ts'; import { Columns, Table } from '~/table.ts'; import { haveSameKeys, mapUpdateSet } from '~/utils.ts'; -import type { AnyMySqlColumn } from '../columns/common.ts'; +import type { AnyGoogleSqlColumn } from '../columns/common.ts'; import { QueryBuilder } from './query-builder.ts'; import type { SelectedFieldsOrdered } from './select.types.ts'; -import type { MySqlUpdateSetSource } from './update.ts'; +import type { GoogleSqlUpdateSetSource } from './update.ts'; -export interface MySqlInsertConfig { +export interface GoogleSqlInsertConfig { table: TTable; - values: Record[] | MySqlInsertSelectQueryBuilder | SQL; + values: Record[] | GoogleSqlInsertSelectQueryBuilder | SQL; ignore: boolean; onConflict?: SQL; returning?: SelectedFieldsOrdered; select?: boolean; } -export type AnyMySqlInsertConfig = MySqlInsertConfig; +export type AnyGoogleSqlInsertConfig = GoogleSqlInsertConfig; -export type MySqlInsertValue = +export type GoogleSqlInsertValue = & { [Key in keyof TTable['$inferInsert']]: TTable['$inferInsert'][Key] | SQL | Placeholder; } & {}; -export type MySqlInsertSelectQueryBuilder = TypedQueryBuilder< - { [K in keyof TTable['$inferInsert']]: AnyMySqlColumn | SQL | SQL.Aliased | TTable['$inferInsert'][K] } +export type GoogleSqlInsertSelectQueryBuilder = TypedQueryBuilder< + { [K in keyof TTable['$inferInsert']]: AnyGoogleSqlColumn | SQL | SQL.Aliased | TTable['$inferInsert'][K] } >; -export class MySqlInsertBuilder< - TTable extends MySqlTable, - TQueryResult extends MySqlQueryResultHKT, +export class GoogleSqlInsertBuilder< + TTable extends GoogleSqlTable, + TQueryResult extends GoogleSqlQueryResultHKT, TPreparedQueryHKT extends PreparedQueryHKTBase, > { - static readonly [entityKind]: string = 'MySqlInsertBuilder'; + static readonly [entityKind]: string = 'GoogleSqlInsertBuilder'; private shouldIgnore = false; constructor( private table: TTable, - private session: MySqlSession, - private dialect: MySqlDialect, + private session: GoogleSqlSession, + private dialect: GoogleSqlDialect, ) {} ignore(): this { @@ -64,11 +64,11 @@ export class MySqlInsertBuilder< return this; } - values(value: MySqlInsertValue): MySqlInsertBase; - values(values: MySqlInsertValue[]): MySqlInsertBase; + values(value: GoogleSqlInsertValue): GoogleSqlInsertBase; + values(values: GoogleSqlInsertValue[]): GoogleSqlInsertBase; values( - values: MySqlInsertValue | MySqlInsertValue[], - ): MySqlInsertBase { + values: GoogleSqlInsertValue | GoogleSqlInsertValue[], + ): GoogleSqlInsertBase { values = Array.isArray(values) ? values : [values]; if (values.length === 0) { throw new Error('values() must be called with at least one value'); @@ -83,21 +83,21 @@ export class MySqlInsertBuilder< return result; }); - return new MySqlInsertBase(this.table, mappedValues, this.shouldIgnore, this.session, this.dialect); + return new GoogleSqlInsertBase(this.table, mappedValues, this.shouldIgnore, this.session, this.dialect); } select( - selectQuery: (qb: QueryBuilder) => MySqlInsertSelectQueryBuilder, - ): MySqlInsertBase; - select(selectQuery: (qb: QueryBuilder) => SQL): MySqlInsertBase; - select(selectQuery: SQL): MySqlInsertBase; - select(selectQuery: MySqlInsertSelectQueryBuilder): MySqlInsertBase; + selectQuery: (qb: QueryBuilder) => GoogleSqlInsertSelectQueryBuilder, + ): GoogleSqlInsertBase; + select(selectQuery: (qb: QueryBuilder) => SQL): GoogleSqlInsertBase; + select(selectQuery: SQL): GoogleSqlInsertBase; + select(selectQuery: GoogleSqlInsertSelectQueryBuilder): GoogleSqlInsertBase; select( selectQuery: | SQL - | MySqlInsertSelectQueryBuilder - | ((qb: QueryBuilder) => MySqlInsertSelectQueryBuilder | SQL), - ): MySqlInsertBase { + | GoogleSqlInsertSelectQueryBuilder + | ((qb: QueryBuilder) => GoogleSqlInsertSelectQueryBuilder | SQL), + ): GoogleSqlInsertBase { const select = typeof selectQuery === 'function' ? selectQuery(new QueryBuilder()) : selectQuery; if ( @@ -109,14 +109,14 @@ export class MySqlInsertBuilder< ); } - return new MySqlInsertBase(this.table, select, this.shouldIgnore, this.session, this.dialect, true); + return new GoogleSqlInsertBase(this.table, select, this.shouldIgnore, this.session, this.dialect, true); } } -export type MySqlInsertWithout = +export type GoogleSqlInsertWithout = TDynamic extends true ? T : Omit< - MySqlInsertBase< + GoogleSqlInsertBase< T['_']['table'], T['_']['queryResult'], T['_']['preparedQueryHKT'], @@ -127,40 +127,40 @@ export type MySqlInsertWithout; -export type MySqlInsertDynamic = MySqlInsert< +export type GoogleSqlInsertDynamic = GoogleSqlInsert< T['_']['table'], T['_']['queryResult'], T['_']['preparedQueryHKT'], T['_']['returning'] >; -export type MySqlInsertPrepare< - T extends AnyMySqlInsert, +export type GoogleSqlInsertPrepare< + T extends AnyGoogleSqlInsert, TReturning extends Record | undefined = undefined, > = PreparedQueryKind< T['_']['preparedQueryHKT'], - MySqlPreparedQueryConfig & { - execute: TReturning extends undefined ? MySqlQueryResultKind : TReturning[]; + GoogleSqlPreparedQueryConfig & { + execute: TReturning extends undefined ? GoogleSqlQueryResultKind : TReturning[]; iterator: never; }, true >; -export type MySqlInsertOnDuplicateKeyUpdateConfig = { - set: MySqlUpdateSetSource; +export type GoogleSqlInsertOnDuplicateKeyUpdateConfig = { + set: GoogleSqlUpdateSetSource; }; -export type MySqlInsert< - TTable extends MySqlTable = MySqlTable, - TQueryResult extends MySqlQueryResultHKT = AnyMySqlQueryResultHKT, +export type GoogleSqlInsert< + TTable extends GoogleSqlTable = GoogleSqlTable, + TQueryResult extends GoogleSqlQueryResultHKT = AnyGoogleSqlQueryResultHKT, TPreparedQueryHKT extends PreparedQueryHKTBase = PreparedQueryHKTBase, TReturning extends Record | undefined = Record | undefined, -> = MySqlInsertBase; +> = GoogleSqlInsertBase; -export type MySqlInsertReturning< - T extends AnyMySqlInsert, +export type GoogleSqlInsertReturning< + T extends AnyGoogleSqlInsert, TDynamic extends boolean, -> = MySqlInsertBase< +> = GoogleSqlInsertBase< T['_']['table'], T['_']['queryResult'], T['_']['preparedQueryHKT'], @@ -169,33 +169,33 @@ export type MySqlInsertReturning< T['_']['excludedMethods'] | '$returning' >; -export type AnyMySqlInsert = MySqlInsertBase; +export type AnyGoogleSqlInsert = GoogleSqlInsertBase; -export interface MySqlInsertBase< - TTable extends MySqlTable, - TQueryResult extends MySqlQueryResultHKT, +export interface GoogleSqlInsertBase< + TTable extends GoogleSqlTable, + TQueryResult extends GoogleSqlQueryResultHKT, TPreparedQueryHKT extends PreparedQueryHKTBase, TReturning extends Record | undefined = undefined, TDynamic extends boolean = false, TExcludedMethods extends string = never, > extends - QueryPromise : TReturning[]>, - RunnableQuery : TReturning[], 'mysql'>, + QueryPromise : TReturning[]>, + RunnableQuery : TReturning[], 'googlesql'>, SQLWrapper { readonly _: { - readonly dialect: 'mysql'; + readonly dialect: 'googlesql'; readonly table: TTable; readonly queryResult: TQueryResult; readonly preparedQueryHKT: TPreparedQueryHKT; readonly dynamic: TDynamic; readonly excludedMethods: TExcludedMethods; readonly returning: TReturning; - readonly result: TReturning extends undefined ? MySqlQueryResultKind : TReturning[]; + readonly result: TReturning extends undefined ? GoogleSqlQueryResultKind : TReturning[]; }; } -export type PrimaryKeyKeys> = { +export type PrimaryKeyKeys> = { [K in keyof T]: T[K]['_']['isPrimaryKey'] extends true ? T[K]['_']['isAutoincrement'] extends true ? K : T[K]['_']['hasRuntimeDefault'] extends true ? T[K]['_']['isPrimaryKey'] extends true ? K : never : never @@ -203,13 +203,13 @@ export type PrimaryKeyKeys> = { : never; }[keyof T]; -export type GetPrimarySerialOrDefaultKeys> = { +export type GetPrimarySerialOrDefaultKeys> = { [K in PrimaryKeyKeys]: T[K]; }; -export class MySqlInsertBase< - TTable extends MySqlTable, - TQueryResult extends MySqlQueryResultHKT, +export class GoogleSqlInsertBase< + TTable extends GoogleSqlTable, + TQueryResult extends GoogleSqlQueryResultHKT, // eslint-disable-next-line @typescript-eslint/no-unused-vars TPreparedQueryHKT extends PreparedQueryHKTBase, // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -218,23 +218,23 @@ export class MySqlInsertBase< TDynamic extends boolean = false, // eslint-disable-next-line @typescript-eslint/no-unused-vars TExcludedMethods extends string = never, -> extends QueryPromise : TReturning[]> +> extends QueryPromise : TReturning[]> implements - RunnableQuery : TReturning[], 'mysql'>, + RunnableQuery : TReturning[], 'googlesql'>, SQLWrapper { - static override readonly [entityKind]: string = 'MySqlInsert'; + static override readonly [entityKind]: string = 'GoogleSqlInsert'; declare protected $table: TTable; - private config: MySqlInsertConfig; + private config: GoogleSqlInsertConfig; constructor( table: TTable, - values: MySqlInsertConfig['values'], + values: GoogleSqlInsertConfig['values'], ignore: boolean, - private session: MySqlSession, - private dialect: MySqlDialect, + private session: GoogleSqlSession, + private dialect: GoogleSqlDialect, select?: boolean, ) { super(); @@ -268,15 +268,15 @@ export class MySqlInsertBase< * ``` */ onDuplicateKeyUpdate( - config: MySqlInsertOnDuplicateKeyUpdateConfig, - ): MySqlInsertWithout { + config: GoogleSqlInsertOnDuplicateKeyUpdateConfig, + ): GoogleSqlInsertWithout { const setSql = this.dialect.buildUpdateSet(this.config.table, mapUpdateSet(this.config.table, config.set)); this.config.onConflict = sql`update ${setSql}`; return this as any; } - $returningId(): MySqlInsertWithout< - MySqlInsertReturning, + $returningId(): GoogleSqlInsertWithout< + GoogleSqlInsertReturning, TDynamic, '$returningId' > { @@ -300,7 +300,7 @@ export class MySqlInsertBase< return rest; } - prepare(): MySqlInsertPrepare { + prepare(): GoogleSqlInsertPrepare { const { sql, generatedIds } = this.dialect.buildInsertQuery(this.config); return this.session.prepareQuery( this.dialect.sqlToQuery(sql), @@ -308,7 +308,7 @@ export class MySqlInsertBase< undefined, generatedIds, this.config.returning, - ) as MySqlInsertPrepare; + ) as GoogleSqlInsertPrepare; } override execute: ReturnType['execute'] = (placeholderValues) => { @@ -324,7 +324,7 @@ export class MySqlInsertBase< iterator = this.createIterator(); - $dynamic(): MySqlInsertDynamic { + $dynamic(): GoogleSqlInsertDynamic { return this as any; } } diff --git a/drizzle-orm/src/googlesql/query-builders/query-builder.ts b/drizzle-orm/src/googlesql/query-builders/query-builder.ts index 0210215705..83feeccd7d 100644 --- a/drizzle-orm/src/googlesql/query-builders/query-builder.ts +++ b/drizzle-orm/src/googlesql/query-builders/query-builder.ts @@ -1,23 +1,23 @@ import { entityKind, is } from '~/entity.ts'; -import type { MySqlDialectConfig } from '~/googlesql/dialect.ts'; -import { MySqlDialect } from '~/googlesql/dialect.ts'; +import type { GoogleSqlDialectConfig } from '~/googlesql/dialect.ts'; +import { GoogleSqlDialect } from '~/googlesql/dialect.ts'; import type { WithBuilder } from '~/googlesql/subquery.ts'; import type { TypedQueryBuilder } from '~/query-builders/query-builder.ts'; import { SelectionProxyHandler } from '~/selection-proxy.ts'; import type { ColumnsSelection, SQL } from '~/sql/sql.ts'; import { WithSubquery } from '~/subquery.ts'; -import { MySqlSelectBuilder } from './select.ts'; +import { GoogleSqlSelectBuilder } from './select.ts'; import type { SelectedFields } from './select.types.ts'; export class QueryBuilder { - static readonly [entityKind]: string = 'MySqlQueryBuilder'; + static readonly [entityKind]: string = 'GoogleSqlQueryBuilder'; - private dialect: MySqlDialect | undefined; - private dialectConfig: MySqlDialectConfig | undefined; + private dialect: GoogleSqlDialect | undefined; + private dialectConfig: GoogleSqlDialectConfig | undefined; - constructor(dialect?: MySqlDialect | MySqlDialectConfig) { - this.dialect = is(dialect, MySqlDialect) ? dialect : undefined; - this.dialectConfig = is(dialect, MySqlDialect) ? undefined : dialect; + constructor(dialect?: GoogleSqlDialect | GoogleSqlDialectConfig) { + this.dialect = is(dialect, GoogleSqlDialect) ? dialect : undefined; + this.dialectConfig = is(dialect, GoogleSqlDialect) ? undefined : dialect; } $with: WithBuilder = (alias: string, selection?: ColumnsSelection) => { @@ -48,14 +48,14 @@ export class QueryBuilder { with(...queries: WithSubquery[]) { const self = this; - function select(): MySqlSelectBuilder; + function select(): GoogleSqlSelectBuilder; function select( fields: TSelection, - ): MySqlSelectBuilder; + ): GoogleSqlSelectBuilder; function select( fields?: TSelection, - ): MySqlSelectBuilder { - return new MySqlSelectBuilder({ + ): GoogleSqlSelectBuilder { + return new GoogleSqlSelectBuilder({ fields: fields ?? undefined, session: undefined, dialect: self.getDialect(), @@ -63,14 +63,14 @@ export class QueryBuilder { }); } - function selectDistinct(): MySqlSelectBuilder; + function selectDistinct(): GoogleSqlSelectBuilder; function selectDistinct( fields: TSelection, - ): MySqlSelectBuilder; + ): GoogleSqlSelectBuilder; function selectDistinct( fields?: TSelection, - ): MySqlSelectBuilder { - return new MySqlSelectBuilder({ + ): GoogleSqlSelectBuilder { + return new GoogleSqlSelectBuilder({ fields: fields ?? undefined, session: undefined, dialect: self.getDialect(), @@ -82,22 +82,22 @@ export class QueryBuilder { return { select, selectDistinct }; } - select(): MySqlSelectBuilder; - select(fields: TSelection): MySqlSelectBuilder; + select(): GoogleSqlSelectBuilder; + select(fields: TSelection): GoogleSqlSelectBuilder; select( fields?: TSelection, - ): MySqlSelectBuilder { - return new MySqlSelectBuilder({ fields: fields ?? undefined, session: undefined, dialect: this.getDialect() }); + ): GoogleSqlSelectBuilder { + return new GoogleSqlSelectBuilder({ fields: fields ?? undefined, session: undefined, dialect: this.getDialect() }); } - selectDistinct(): MySqlSelectBuilder; + selectDistinct(): GoogleSqlSelectBuilder; selectDistinct( fields: TSelection, - ): MySqlSelectBuilder; + ): GoogleSqlSelectBuilder; selectDistinct( fields?: TSelection, - ): MySqlSelectBuilder { - return new MySqlSelectBuilder({ + ): GoogleSqlSelectBuilder { + return new GoogleSqlSelectBuilder({ fields: fields ?? undefined, session: undefined, dialect: this.getDialect(), @@ -108,7 +108,7 @@ export class QueryBuilder { // Lazy load dialect to avoid circular dependency private getDialect() { if (!this.dialect) { - this.dialect = new MySqlDialect(this.dialectConfig); + this.dialect = new GoogleSqlDialect(this.dialectConfig); } return this.dialect; diff --git a/drizzle-orm/src/googlesql/query-builders/query.ts b/drizzle-orm/src/googlesql/query-builders/query.ts index 16d2945981..64696097ae 100644 --- a/drizzle-orm/src/googlesql/query-builders/query.ts +++ b/drizzle-orm/src/googlesql/query-builders/query.ts @@ -10,38 +10,38 @@ import { } from '~/relations.ts'; import type { Query, QueryWithTypings, SQL } from '~/sql/sql.ts'; import type { KnownKeysOnly } from '~/utils.ts'; -import type { MySqlDialect } from '../dialect.ts'; +import type { GoogleSqlDialect } from '../dialect.ts'; import type { Mode, - MySqlPreparedQueryConfig, - MySqlSession, + GoogleSqlPreparedQueryConfig, + GoogleSqlSession, PreparedQueryHKTBase, PreparedQueryKind, } from '../session.ts'; -import type { MySqlTable } from '../table.ts'; +import type { GoogleSqlTable } from '../table.ts'; export class RelationalQueryBuilder< TPreparedQueryHKT extends PreparedQueryHKTBase, TSchema extends TablesRelationalConfig, TFields extends TableRelationalConfig, > { - static readonly [entityKind]: string = 'MySqlRelationalQueryBuilder'; + static readonly [entityKind]: string = 'GoogleSqlRelationalQueryBuilder'; constructor( private fullSchema: Record, private schema: TSchema, private tableNamesMap: Record, - private table: MySqlTable, + private table: GoogleSqlTable, private tableConfig: TableRelationalConfig, - private dialect: MySqlDialect, - private session: MySqlSession, + private dialect: GoogleSqlDialect, + private session: GoogleSqlSession, private mode: Mode, ) {} findMany>( config?: KnownKeysOnly>, - ): MySqlRelationalQuery[]> { - return new MySqlRelationalQuery( + ): GoogleSqlRelationalQuery[]> { + return new GoogleSqlRelationalQuery( this.fullSchema, this.schema, this.tableNamesMap, @@ -57,8 +57,8 @@ export class RelationalQueryBuilder< findFirst, 'limit'>>( config?: KnownKeysOnly, 'limit'>>, - ): MySqlRelationalQuery | undefined> { - return new MySqlRelationalQuery( + ): GoogleSqlRelationalQuery | undefined> { + return new GoogleSqlRelationalQuery( this.fullSchema, this.schema, this.tableNamesMap, @@ -73,22 +73,22 @@ export class RelationalQueryBuilder< } } -export class MySqlRelationalQuery< +export class GoogleSqlRelationalQuery< TPreparedQueryHKT extends PreparedQueryHKTBase, TResult, > extends QueryPromise { - static override readonly [entityKind]: string = 'MySqlRelationalQuery'; + static override readonly [entityKind]: string = 'GoogleSqlRelationalQuery'; - declare protected $brand: 'MySqlRelationalQuery'; + declare protected $brand: 'GoogleSqlRelationalQuery'; constructor( private fullSchema: Record, private schema: TablesRelationalConfig, private tableNamesMap: Record, - private table: MySqlTable, + private table: GoogleSqlTable, private tableConfig: TableRelationalConfig, - private dialect: MySqlDialect, - private session: MySqlSession, + private dialect: GoogleSqlDialect, + private session: GoogleSqlSession, private config: DBQueryConfig<'many', true> | true, private queryMode: 'many' | 'first', private mode?: Mode, @@ -108,7 +108,7 @@ export class MySqlRelationalQuery< } return rows as TResult; }, - ) as PreparedQueryKind; + ) as PreparedQueryKind; } private _getQuery() { diff --git a/drizzle-orm/src/googlesql/query-builders/select.ts b/drizzle-orm/src/googlesql/query-builders/select.ts index a321b6b09f..0f6bd96889 100644 --- a/drizzle-orm/src/googlesql/query-builders/select.ts +++ b/drizzle-orm/src/googlesql/query-builders/select.ts @@ -1,9 +1,9 @@ import { entityKind, is } from '~/entity.ts'; -import type { MySqlColumn } from '~/googlesql/columns/index.ts'; -import type { MySqlDialect } from '~/googlesql/dialect.ts'; -import type { MySqlPreparedQueryConfig, MySqlSession, PreparedQueryHKTBase } from '~/googlesql/session.ts'; +import type { GoogleSqlColumn } from '~/googlesql/columns/index.ts'; +import type { GoogleSqlDialect } from '~/googlesql/dialect.ts'; +import type { GoogleSqlPreparedQueryConfig, GoogleSqlSession, PreparedQueryHKTBase } from '~/googlesql/session.ts'; import type { SubqueryWithSelection } from '~/googlesql/subquery.ts'; -import { MySqlTable } from '~/googlesql/table.ts'; +import { GoogleSqlTable } from '~/googlesql/table.ts'; import { TypedQueryBuilder } from '~/query-builders/query-builder.ts'; import type { BuildSubquerySelection, @@ -26,23 +26,23 @@ import { applyMixins, getTableColumns, getTableLikeName, haveSameKeys, orderSele import { ViewBaseConfig } from '~/view-common.ts'; import type { IndexBuilder } from '../indexes.ts'; import { convertIndexToString, toArray } from '../utils.ts'; -import { MySqlViewBase } from '../view-base.ts'; +import { GoogleSqlViewBase } from '../view-base.ts'; import type { - AnyMySqlSelect, - CreateMySqlSelectFromBuilderMode, - GetMySqlSetOperators, + AnyGoogleSqlSelect, + CreateGoogleSqlSelectFromBuilderMode, + GetGoogleSqlSetOperators, LockConfig, LockStrength, - MySqlCreateSetOperatorFn, - MySqlJoinFn, - MySqlSelectConfig, - MySqlSelectDynamic, - MySqlSelectHKT, - MySqlSelectHKTBase, - MySqlSelectPrepare, - MySqlSelectWithout, - MySqlSetOperatorExcludedMethods, - MySqlSetOperatorWithResult, + GoogleSqlCreateSetOperatorFn, + GoogleSqlJoinFn, + GoogleSqlSelectConfig, + GoogleSqlSelectDynamic, + GoogleSqlSelectHKT, + GoogleSqlSelectHKTBase, + GoogleSqlSelectPrepare, + GoogleSqlSelectWithout, + GoogleSqlSetOperatorExcludedMethods, + GoogleSqlSetOperatorWithResult, SelectedFields, SetOperatorRightSelect, } from './select.types.ts'; @@ -55,24 +55,24 @@ export type IndexConfig = { ignoreIndex?: IndexForHint | IndexForHint[]; }; -export class MySqlSelectBuilder< +export class GoogleSqlSelectBuilder< TSelection extends SelectedFields | undefined, TPreparedQueryHKT extends PreparedQueryHKTBase, TBuilderMode extends 'db' | 'qb' = 'db', > { - static readonly [entityKind]: string = 'MySqlSelectBuilder'; + static readonly [entityKind]: string = 'GoogleSqlSelectBuilder'; private fields: TSelection; - private session: MySqlSession | undefined; - private dialect: MySqlDialect; + private session: GoogleSqlSession | undefined; + private dialect: GoogleSqlDialect; private withList: Subquery[] = []; private distinct: boolean | undefined; constructor( config: { fields: TSelection; - session: MySqlSession | undefined; - dialect: MySqlDialect; + session: GoogleSqlSession | undefined; + dialect: GoogleSqlDialect; withList?: Subquery[]; distinct?: boolean; }, @@ -86,11 +86,11 @@ export class MySqlSelectBuilder< this.distinct = config.distinct; } - from( + from( source: TFrom, - onIndex?: TFrom extends MySqlTable ? IndexConfig - : 'Index hint configuration is allowed only for MySqlTable and not for subqueries or views', - ): CreateMySqlSelectFromBuilderMode< + onIndex?: TFrom extends GoogleSqlTable ? IndexConfig + : 'Index hint configuration is allowed only for GoogleSqlTable and not for subqueries or views', + ): CreateGoogleSqlSelectFromBuilderMode< TBuilderMode, GetSelectTableName, TSelection extends undefined ? GetSelectTableSelection : TSelection, @@ -109,18 +109,18 @@ export class MySqlSelectBuilder< key, ) => [key, source[key as unknown as keyof typeof source] as unknown as SelectedFields[string]]), ); - } else if (is(source, MySqlViewBase)) { + } else if (is(source, GoogleSqlViewBase)) { fields = source[ViewBaseConfig].selectedFields as SelectedFields; } else if (is(source, SQL)) { fields = {}; } else { - fields = getTableColumns(source); + fields = getTableColumns(source); } let useIndex: string[] = []; let forceIndex: string[] = []; let ignoreIndex: string[] = []; - if (is(source, MySqlTable) && onIndex && typeof onIndex !== 'string') { + if (is(source, GoogleSqlTable) && onIndex && typeof onIndex !== 'string') { if (onIndex.useIndex) { useIndex = convertIndexToString(toArray(onIndex.useIndex)); } @@ -132,7 +132,7 @@ export class MySqlSelectBuilder< } } - return new MySqlSelectBase( + return new GoogleSqlSelectBase( { table: source, fields, @@ -149,8 +149,8 @@ export class MySqlSelectBuilder< } } -export abstract class MySqlSelectQueryBuilderBase< - THKT extends MySqlSelectHKTBase, +export abstract class GoogleSqlSelectQueryBuilderBase< + THKT extends GoogleSqlSelectHKTBase, TTableName extends string | undefined, TSelection extends ColumnsSelection, TSelectMode extends SelectMode, @@ -162,7 +162,7 @@ export abstract class MySqlSelectQueryBuilderBase< TResult extends any[] = SelectResult[], TSelectedFields extends ColumnsSelection = BuildSubquerySelection, > extends TypedQueryBuilder { - static override readonly [entityKind]: string = 'MySqlSelectQueryBuilder'; + static override readonly [entityKind]: string = 'GoogleSqlSelectQueryBuilder'; override readonly _: { readonly hkt: THKT; @@ -177,21 +177,21 @@ export abstract class MySqlSelectQueryBuilderBase< readonly selectedFields: TSelectedFields; }; - protected config: MySqlSelectConfig; + protected config: GoogleSqlSelectConfig; protected joinsNotNullableMap: Record; private tableName: string | undefined; private isPartialSelect: boolean; /** @internal */ - readonly session: MySqlSession | undefined; - protected dialect: MySqlDialect; + readonly session: GoogleSqlSession | undefined; + protected dialect: GoogleSqlDialect; constructor( { table, fields, isPartialSelect, session, dialect, withList, distinct, useIndex, forceIndex, ignoreIndex }: { - table: MySqlSelectConfig['table']; - fields: MySqlSelectConfig['fields']; + table: GoogleSqlSelectConfig['table']; + fields: GoogleSqlSelectConfig['fields']; isPartialSelect: boolean; - session: MySqlSession | undefined; - dialect: MySqlDialect; + session: GoogleSqlSession | undefined; + dialect: GoogleSqlDialect; withList: Subquery[]; distinct: boolean | undefined; useIndex?: string[]; @@ -222,14 +222,14 @@ export abstract class MySqlSelectQueryBuilderBase< private createJoin( joinType: TJoinType, - ): MySqlJoinFn { + ): GoogleSqlJoinFn { return < - TJoinedTable extends MySqlTable | Subquery | MySqlViewBase | SQL, + TJoinedTable extends GoogleSqlTable | Subquery | GoogleSqlViewBase | SQL, >( - table: MySqlTable | Subquery | MySqlViewBase | SQL, + table: GoogleSqlTable | Subquery | GoogleSqlViewBase | SQL, on: ((aliases: TSelection) => SQL | undefined) | SQL | undefined, - onIndex?: TJoinedTable extends MySqlTable ? IndexConfig - : 'Index hint configuration is allowed only for MySqlTable and not for subqueries or views', + onIndex?: TJoinedTable extends GoogleSqlTable ? IndexConfig + : 'Index hint configuration is allowed only for GoogleSqlTable and not for subqueries or views', ) => { const baseTableName = this.tableName; const tableName = getTableLikeName(table); @@ -271,7 +271,7 @@ export abstract class MySqlSelectQueryBuilderBase< let useIndex: string[] = []; let forceIndex: string[] = []; let ignoreIndex: string[] = []; - if (is(table, MySqlTable) && onIndex && typeof onIndex !== 'string') { + if (is(table, GoogleSqlTable) && onIndex && typeof onIndex !== 'string') { if (onIndex.useIndex) { useIndex = convertIndexToString(toArray(onIndex.useIndex)); } @@ -475,19 +475,19 @@ export abstract class MySqlSelectQueryBuilderBase< private createSetOperator( type: SetOperator, isAll: boolean, - ): >( + ): >( rightSelection: - | ((setOperators: GetMySqlSetOperators) => SetOperatorRightSelect) + | ((setOperators: GetGoogleSqlSetOperators) => SetOperatorRightSelect) | SetOperatorRightSelect, - ) => MySqlSelectWithout< + ) => GoogleSqlSelectWithout< this, TDynamic, - MySqlSetOperatorExcludedMethods, + GoogleSqlSetOperatorExcludedMethods, true > { return (rightSelection) => { const rightSelect = (typeof rightSelection === 'function' - ? rightSelection(getMySqlSetOperators()) + ? rightSelection(getGoogleSqlSetOperators()) : rightSelection) as TypedQueryBuilder< any, TResult @@ -521,7 +521,7 @@ export abstract class MySqlSelectQueryBuilderBase< * db.select({ name: customers.name }).from(customers) * ); * // or - * import { union } from 'drizzle-orm/mysql-core' + * import { union } from 'drizzle-orm/googlesql' * * await union( * db.select({ name: users.name }).from(users), @@ -548,7 +548,7 @@ export abstract class MySqlSelectQueryBuilderBase< * db.select({ transaction: inStoreSales.transactionId }).from(inStoreSales) * ); * // or - * import { unionAll } from 'drizzle-orm/mysql-core' + * import { unionAll } from 'drizzle-orm/googlesql' * * await unionAll( * db.select({ transaction: onlineSales.transactionId }).from(onlineSales), @@ -575,7 +575,7 @@ export abstract class MySqlSelectQueryBuilderBase< * db.select({ courseName: depB.courseName }).from(depB) * ); * // or - * import { intersect } from 'drizzle-orm/mysql-core' + * import { intersect } from 'drizzle-orm/googlesql' * * await intersect( * db.select({ courseName: depA.courseName }).from(depA), @@ -609,7 +609,7 @@ export abstract class MySqlSelectQueryBuilderBase< * .from(vipCustomerOrders) * ); * // or - * import { intersectAll } from 'drizzle-orm/mysql-core' + * import { intersectAll } from 'drizzle-orm/googlesql' * * await intersectAll( * db.select({ @@ -644,7 +644,7 @@ export abstract class MySqlSelectQueryBuilderBase< * db.select({ courseName: depB.courseName }).from(depB) * ); * // or - * import { except } from 'drizzle-orm/mysql-core' + * import { except } from 'drizzle-orm/googlesql' * * await except( * db.select({ courseName: depA.courseName }).from(depA), @@ -678,7 +678,7 @@ export abstract class MySqlSelectQueryBuilderBase< * .from(vipCustomerOrders) * ); * // or - * import { exceptAll } from 'drizzle-orm/mysql-core' + * import { exceptAll } from 'drizzle-orm/googlesql' * * await exceptAll( * db.select({ @@ -697,10 +697,10 @@ export abstract class MySqlSelectQueryBuilderBase< exceptAll = this.createSetOperator('except', true); /** @internal */ - addSetOperators(setOperators: MySqlSelectConfig['setOperators']): MySqlSelectWithout< + addSetOperators(setOperators: GoogleSqlSelectConfig['setOperators']): GoogleSqlSelectWithout< this, TDynamic, - MySqlSetOperatorExcludedMethods, + GoogleSqlSetOperatorExcludedMethods, true > { this.config.setOperators.push(...setOperators); @@ -738,7 +738,7 @@ export abstract class MySqlSelectQueryBuilderBase< */ where( where: ((aliases: this['_']['selection']) => SQL | undefined) | SQL | undefined, - ): MySqlSelectWithout { + ): GoogleSqlSelectWithout { if (typeof where === 'function') { where = where( new Proxy( @@ -775,7 +775,7 @@ export abstract class MySqlSelectQueryBuilderBase< */ having( having: ((aliases: this['_']['selection']) => SQL | undefined) | SQL | undefined, - ): MySqlSelectWithout { + ): GoogleSqlSelectWithout { if (typeof having === 'function') { having = having( new Proxy( @@ -808,14 +808,14 @@ export abstract class MySqlSelectQueryBuilderBase< * ``` */ groupBy( - builder: (aliases: this['_']['selection']) => ValueOrArray, - ): MySqlSelectWithout; - groupBy(...columns: (MySqlColumn | SQL | SQL.Aliased)[]): MySqlSelectWithout; + builder: (aliases: this['_']['selection']) => ValueOrArray, + ): GoogleSqlSelectWithout; + groupBy(...columns: (GoogleSqlColumn | SQL | SQL.Aliased)[]): GoogleSqlSelectWithout; groupBy( ...columns: - | [(aliases: this['_']['selection']) => ValueOrArray] - | (MySqlColumn | SQL | SQL.Aliased)[] - ): MySqlSelectWithout { + | [(aliases: this['_']['selection']) => ValueOrArray] + | (GoogleSqlColumn | SQL | SQL.Aliased)[] + ): GoogleSqlSelectWithout { if (typeof columns[0] === 'function') { const groupBy = columns[0]( new Proxy( @@ -825,7 +825,7 @@ export abstract class MySqlSelectQueryBuilderBase< ); this.config.groupBy = Array.isArray(groupBy) ? groupBy : [groupBy]; } else { - this.config.groupBy = columns as (MySqlColumn | SQL | SQL.Aliased)[]; + this.config.groupBy = columns as (GoogleSqlColumn | SQL | SQL.Aliased)[]; } return this as any; } @@ -855,14 +855,14 @@ export abstract class MySqlSelectQueryBuilderBase< * ``` */ orderBy( - builder: (aliases: this['_']['selection']) => ValueOrArray, - ): MySqlSelectWithout; - orderBy(...columns: (MySqlColumn | SQL | SQL.Aliased)[]): MySqlSelectWithout; + builder: (aliases: this['_']['selection']) => ValueOrArray, + ): GoogleSqlSelectWithout; + orderBy(...columns: (GoogleSqlColumn | SQL | SQL.Aliased)[]): GoogleSqlSelectWithout; orderBy( ...columns: - | [(aliases: this['_']['selection']) => ValueOrArray] - | (MySqlColumn | SQL | SQL.Aliased)[] - ): MySqlSelectWithout { + | [(aliases: this['_']['selection']) => ValueOrArray] + | (GoogleSqlColumn | SQL | SQL.Aliased)[] + ): GoogleSqlSelectWithout { if (typeof columns[0] === 'function') { const orderBy = columns[0]( new Proxy( @@ -879,7 +879,7 @@ export abstract class MySqlSelectQueryBuilderBase< this.config.orderBy = orderByArray; } } else { - const orderByArray = columns as (MySqlColumn | SQL | SQL.Aliased)[]; + const orderByArray = columns as (GoogleSqlColumn | SQL | SQL.Aliased)[]; if (this.config.setOperators.length > 0) { this.config.setOperators.at(-1)!.orderBy = orderByArray; @@ -906,7 +906,7 @@ export abstract class MySqlSelectQueryBuilderBase< * await db.select().from(people).limit(10); * ``` */ - limit(limit: number | Placeholder): MySqlSelectWithout { + limit(limit: number | Placeholder): GoogleSqlSelectWithout { if (this.config.setOperators.length > 0) { this.config.setOperators.at(-1)!.limit = limit; } else { @@ -931,7 +931,7 @@ export abstract class MySqlSelectQueryBuilderBase< * await db.select().from(people).offset(10).limit(10); * ``` */ - offset(offset: number | Placeholder): MySqlSelectWithout { + offset(offset: number | Placeholder): GoogleSqlSelectWithout { if (this.config.setOperators.length > 0) { this.config.setOperators.at(-1)!.offset = offset; } else { @@ -950,7 +950,7 @@ export abstract class MySqlSelectQueryBuilderBase< * @param strength the lock strength. * @param config the lock configuration. */ - for(strength: LockStrength, config: LockConfig = {}): MySqlSelectWithout { + for(strength: LockStrength, config: LockConfig = {}): GoogleSqlSelectWithout { this.config.lockingClause = { strength, config }; return this as any; } @@ -982,12 +982,12 @@ export abstract class MySqlSelectQueryBuilderBase< ) as this['_']['selectedFields']; } - $dynamic(): MySqlSelectDynamic { + $dynamic(): GoogleSqlSelectDynamic { return this as any; } } -export interface MySqlSelectBase< +export interface GoogleSqlSelectBase< TTableName extends string | undefined, TSelection extends ColumnsSelection, TSelectMode extends SelectMode, @@ -999,8 +999,8 @@ export interface MySqlSelectBase< TResult extends any[] = SelectResult[], TSelectedFields extends ColumnsSelection = BuildSubquerySelection, > extends - MySqlSelectQueryBuilderBase< - MySqlSelectHKT, + GoogleSqlSelectQueryBuilderBase< + GoogleSqlSelectHKT, TTableName, TSelection, TSelectMode, @@ -1014,7 +1014,7 @@ export interface MySqlSelectBase< QueryPromise {} -export class MySqlSelectBase< +export class GoogleSqlSelectBase< TTableName extends string | undefined, TSelection, TSelectMode extends SelectMode, @@ -1025,8 +1025,8 @@ export class MySqlSelectBase< TExcludedMethods extends string = never, TResult = SelectResult[], TSelectedFields = BuildSubquerySelection, -> extends MySqlSelectQueryBuilderBase< - MySqlSelectHKT, +> extends GoogleSqlSelectQueryBuilderBase< + GoogleSqlSelectHKT, TTableName, TSelection, TSelectMode, @@ -1037,19 +1037,19 @@ export class MySqlSelectBase< TResult, TSelectedFields > { - static override readonly [entityKind]: string = 'MySqlSelect'; + static override readonly [entityKind]: string = 'GoogleSqlSelect'; - prepare(): MySqlSelectPrepare { + prepare(): GoogleSqlSelectPrepare { if (!this.session) { throw new Error('Cannot execute a query on a query builder. Please use a database instance instead.'); } - const fieldsList = orderSelectedFields(this.config.fields); + const fieldsList = orderSelectedFields(this.config.fields); const query = this.session.prepareQuery< - MySqlPreparedQueryConfig & { execute: SelectResult[] }, + GoogleSqlPreparedQueryConfig & { execute: SelectResult[] }, TPreparedQueryHKT >(this.dialect.sqlToQuery(this.getSQL()), fieldsList); query.joinsNotNullableMap = this.joinsNotNullableMap; - return query as MySqlSelectPrepare; + return query as GoogleSqlSelectPrepare; } execute = ((placeholderValues) => { @@ -1066,14 +1066,14 @@ export class MySqlSelectBase< iterator = this.createIterator(); } -applyMixins(MySqlSelectBase, [QueryPromise]); +applyMixins(GoogleSqlSelectBase, [QueryPromise]); -function createSetOperator(type: SetOperator, isAll: boolean): MySqlCreateSetOperatorFn { +function createSetOperator(type: SetOperator, isAll: boolean): GoogleSqlCreateSetOperatorFn { return (leftSelect, rightSelect, ...restSelects) => { const setOperators = [rightSelect, ...restSelects].map((select) => ({ type, isAll, - rightSelect: select as AnyMySqlSelect, + rightSelect: select as AnyGoogleSqlSelect, })); for (const setOperator of setOperators) { @@ -1084,11 +1084,11 @@ function createSetOperator(type: SetOperator, isAll: boolean): MySqlCreateSetOpe } } - return (leftSelect as AnyMySqlSelect).addSetOperators(setOperators) as any; + return (leftSelect as AnyGoogleSqlSelect).addSetOperators(setOperators) as any; }; } -const getMySqlSetOperators = () => ({ +const getGoogleSqlSetOperators = () => ({ union, unionAll, intersect, @@ -1108,7 +1108,7 @@ const getMySqlSetOperators = () => ({ * * ```ts * // Select all unique names from customers and users tables - * import { union } from 'drizzle-orm/mysql-core' + * import { union } from 'drizzle-orm/googlesql' * * await union( * db.select({ name: users.name }).from(users), @@ -1135,7 +1135,7 @@ export const union = createSetOperator('union', false); * * ```ts * // Select all transaction ids from both online and in-store sales - * import { unionAll } from 'drizzle-orm/mysql-core' + * import { unionAll } from 'drizzle-orm/googlesql' * * await unionAll( * db.select({ transaction: onlineSales.transactionId }).from(onlineSales), @@ -1162,7 +1162,7 @@ export const unionAll = createSetOperator('union', true); * * ```ts * // Select course names that are offered in both departments A and B - * import { intersect } from 'drizzle-orm/mysql-core' + * import { intersect } from 'drizzle-orm/googlesql' * * await intersect( * db.select({ courseName: depA.courseName }).from(depA), @@ -1189,7 +1189,7 @@ export const intersect = createSetOperator('intersect', false); * * ```ts * // Select all products and quantities that are ordered by both regular and VIP customers - * import { intersectAll } from 'drizzle-orm/mysql-core' + * import { intersectAll } from 'drizzle-orm/googlesql' * * await intersectAll( * db.select({ @@ -1231,7 +1231,7 @@ export const intersectAll = createSetOperator('intersect', true); * * ```ts * // Select all courses offered in department A but not in department B - * import { except } from 'drizzle-orm/mysql-core' + * import { except } from 'drizzle-orm/googlesql' * * await except( * db.select({ courseName: depA.courseName }).from(depA), @@ -1258,7 +1258,7 @@ export const except = createSetOperator('except', false); * * ```ts * // Select all products that are ordered by regular customers but not by VIP customers - * import { exceptAll } from 'drizzle-orm/mysql-core' + * import { exceptAll } from 'drizzle-orm/googlesql' * * await exceptAll( * db.select({ diff --git a/drizzle-orm/src/googlesql/query-builders/select.types.ts b/drizzle-orm/src/googlesql/query-builders/select.types.ts index 55b64fe026..9300f5bb6a 100644 --- a/drizzle-orm/src/googlesql/query-builders/select.types.ts +++ b/drizzle-orm/src/googlesql/query-builders/select.types.ts @@ -1,5 +1,5 @@ -import type { MySqlColumn } from '~/googlesql/columns/index.ts'; -import type { MySqlTable, MySqlTableWithColumns } from '~/googlesql/table.ts'; +import type { GoogleSqlColumn } from '~/googlesql/columns/index.ts'; +import type { GoogleSqlTable, GoogleSqlTableWithColumns } from '~/googlesql/table.ts'; import type { SelectedFields as SelectedFieldsBase, SelectedFieldsFlat as SelectedFieldsFlatBase, @@ -22,14 +22,14 @@ import type { ColumnsSelection, Placeholder, SQL, View } from '~/sql/sql.ts'; import type { Subquery } from '~/subquery.ts'; import type { Table, UpdateTableConfig } from '~/table.ts'; import type { Assume, ValidateShape } from '~/utils.ts'; -import type { MySqlPreparedQueryConfig, PreparedQueryHKTBase, PreparedQueryKind } from '../session.ts'; -import type { MySqlViewBase } from '../view-base.ts'; -import type { MySqlViewWithSelection } from '../view.ts'; -import type { IndexConfig, MySqlSelectBase, MySqlSelectQueryBuilderBase } from './select.ts'; +import type { GoogleSqlPreparedQueryConfig, PreparedQueryHKTBase, PreparedQueryKind } from '../session.ts'; +import type { GoogleSqlViewBase } from '../view-base.ts'; +import type { GoogleSqlViewWithSelection } from '../view.ts'; +import type { IndexConfig, GoogleSqlSelectBase, GoogleSqlSelectQueryBuilderBase } from './select.ts'; -export interface MySqlSelectJoinConfig { +export interface GoogleSqlSelectJoinConfig { on: SQL | undefined; - table: MySqlTable | Subquery | MySqlViewBase | SQL; + table: GoogleSqlTable | Subquery | GoogleSqlViewBase | SQL; alias: string | undefined; joinType: JoinType; lateral?: boolean; @@ -38,32 +38,32 @@ export interface MySqlSelectJoinConfig { ignoreIndex?: string[]; } -export type BuildAliasTable = TTable extends Table - ? MySqlTableWithColumns< +export type BuildAliasTable = TTable extends Table + ? GoogleSqlTableWithColumns< UpdateTableConfig; + columns: MapColumnsToTableAlias; }> > - : TTable extends View ? MySqlViewWithSelection< + : TTable extends View ? GoogleSqlViewWithSelection< TAlias, TTable['_']['existing'], - MapColumnsToTableAlias + MapColumnsToTableAlias > : never; -export interface MySqlSelectConfig { +export interface GoogleSqlSelectConfig { withList?: Subquery[]; fields: Record; fieldsFlat?: SelectedFieldsOrdered; where?: SQL; having?: SQL; - table: MySqlTable | Subquery | MySqlViewBase | SQL; + table: GoogleSqlTable | Subquery | GoogleSqlViewBase | SQL; limit?: number | Placeholder; offset?: number | Placeholder; - joins?: MySqlSelectJoinConfig[]; - orderBy?: (MySqlColumn | SQL | SQL.Aliased)[]; - groupBy?: (MySqlColumn | SQL | SQL.Aliased)[]; + joins?: GoogleSqlSelectJoinConfig[]; + orderBy?: (GoogleSqlColumn | SQL | SQL.Aliased)[]; + groupBy?: (GoogleSqlColumn | SQL | SQL.Aliased)[]; lockingClause?: { strength: LockStrength; config: LockConfig; @@ -73,7 +73,7 @@ export interface MySqlSelectConfig { rightSelect: TypedQueryBuilder; type: SetOperator; isAll: boolean; - orderBy?: (MySqlColumn | SQL | SQL.Aliased)[]; + orderBy?: (GoogleSqlColumn | SQL | SQL.Aliased)[]; limit?: number | Placeholder; offset?: number | Placeholder; }[]; @@ -82,21 +82,21 @@ export interface MySqlSelectConfig { ignoreIndex?: string[]; } -export type MySqlJoin< - T extends AnyMySqlSelectQueryBuilder, +export type GoogleSqlJoin< + T extends AnyGoogleSqlSelectQueryBuilder, TDynamic extends boolean, TJoinType extends JoinType, - TJoinedTable extends MySqlTable | Subquery | MySqlViewBase | SQL, + TJoinedTable extends GoogleSqlTable | Subquery | GoogleSqlViewBase | SQL, TJoinedName extends GetSelectTableName = GetSelectTableName, -> = T extends any ? MySqlSelectWithout< - MySqlSelectKind< +> = T extends any ? GoogleSqlSelectWithout< + GoogleSqlSelectKind< T['_']['hkt'], T['_']['tableName'], AppendToResult< T['_']['tableName'], T['_']['selection'], TJoinedName, - TJoinedTable extends MySqlTable ? TJoinedTable['_']['columns'] + TJoinedTable extends GoogleSqlTable ? TJoinedTable['_']['columns'] : TJoinedTable extends Subquery | View ? Assume : never, T['_']['selectMode'] @@ -112,25 +112,25 @@ export type MySqlJoin< > : never; -export type MySqlJoinFn< - T extends AnyMySqlSelectQueryBuilder, +export type GoogleSqlJoinFn< + T extends AnyGoogleSqlSelectQueryBuilder, TDynamic extends boolean, TJoinType extends JoinType, > = < - TJoinedTable extends MySqlTable | Subquery | MySqlViewBase | SQL, + TJoinedTable extends GoogleSqlTable | Subquery | GoogleSqlViewBase | SQL, TJoinedName extends GetSelectTableName = GetSelectTableName, >( table: TJoinedTable, on: ((aliases: T['_']['selection']) => SQL | undefined) | SQL | undefined, - onIndex?: TJoinedTable extends MySqlTable ? IndexConfig - : 'Index hint configuration is allowed only for MySqlTable and not for subqueries or views', -) => MySqlJoin; + onIndex?: TJoinedTable extends GoogleSqlTable ? IndexConfig + : 'Index hint configuration is allowed only for GoogleSqlTable and not for subqueries or views', +) => GoogleSqlJoin; -export type SelectedFieldsFlat = SelectedFieldsFlatBase; +export type SelectedFieldsFlat = SelectedFieldsFlatBase; -export type SelectedFields = SelectedFieldsBase; +export type SelectedFields = SelectedFieldsBase; -export type SelectedFieldsOrdered = SelectedFieldsOrderedBase; +export type SelectedFieldsOrdered = SelectedFieldsOrderedBase; export type LockStrength = 'update' | 'share'; @@ -145,7 +145,7 @@ export type LockConfig = { skipLocked?: undefined; }; -export interface MySqlSelectHKTBase { +export interface GoogleSqlSelectHKTBase { tableName: string | undefined; selection: unknown; selectMode: SelectMode; @@ -158,8 +158,8 @@ export interface MySqlSelectHKTBase { _type: unknown; } -export type MySqlSelectKind< - T extends MySqlSelectHKTBase, +export type GoogleSqlSelectKind< + T extends GoogleSqlSelectHKTBase, TTableName extends string | undefined, TSelection extends ColumnsSelection, TSelectMode extends SelectMode, @@ -181,9 +181,9 @@ export type MySqlSelectKind< selectedFields: TSelectedFields; })['_type']; -export interface MySqlSelectQueryBuilderHKT extends MySqlSelectHKTBase { - _type: MySqlSelectQueryBuilderBase< - MySqlSelectQueryBuilderHKT, +export interface GoogleSqlSelectQueryBuilderHKT extends GoogleSqlSelectHKTBase { + _type: GoogleSqlSelectQueryBuilderBase< + GoogleSqlSelectQueryBuilderHKT, this['tableName'], Assume, this['selectMode'], @@ -196,8 +196,8 @@ export interface MySqlSelectQueryBuilderHKT extends MySqlSelectHKTBase { >; } -export interface MySqlSelectHKT extends MySqlSelectHKTBase { - _type: MySqlSelectBase< +export interface GoogleSqlSelectHKT extends GoogleSqlSelectHKTBase { + _type: GoogleSqlSelectBase< this['tableName'], Assume, this['selectMode'], @@ -210,7 +210,7 @@ export interface MySqlSelectHKT extends MySqlSelectHKTBase { >; } -export type MySqlSetOperatorExcludedMethods = +export type GoogleSqlSetOperatorExcludedMethods = | 'where' | 'having' | 'groupBy' @@ -221,13 +221,13 @@ export type MySqlSetOperatorExcludedMethods = | 'fullJoin' | 'for'; -export type MySqlSelectWithout< - T extends AnyMySqlSelectQueryBuilder, +export type GoogleSqlSelectWithout< + T extends AnyGoogleSqlSelectQueryBuilder, TDynamic extends boolean, K extends keyof T & string, TResetExcluded extends boolean = false, > = TDynamic extends true ? T : Omit< - MySqlSelectKind< + GoogleSqlSelectKind< T['_']['hkt'], T['_']['tableName'], T['_']['selection'], @@ -242,16 +242,16 @@ export type MySqlSelectWithout< TResetExcluded extends true ? K : T['_']['excludedMethods'] | K >; -export type MySqlSelectPrepare = PreparedQueryKind< +export type GoogleSqlSelectPrepare = PreparedQueryKind< T['_']['preparedQueryHKT'], - MySqlPreparedQueryConfig & { + GoogleSqlPreparedQueryConfig & { execute: T['_']['result']; iterator: T['_']['result'][number]; }, true >; -export type MySqlSelectDynamic = MySqlSelectKind< +export type GoogleSqlSelectDynamic = GoogleSqlSelectKind< T['_']['hkt'], T['_']['tableName'], T['_']['selection'], @@ -264,17 +264,17 @@ export type MySqlSelectDynamic = MySqlSele T['_']['selectedFields'] >; -export type CreateMySqlSelectFromBuilderMode< +export type CreateGoogleSqlSelectFromBuilderMode< TBuilderMode extends 'db' | 'qb', TTableName extends string | undefined, TSelection extends ColumnsSelection, TSelectMode extends SelectMode, TPreparedQueryHKT extends PreparedQueryHKTBase, -> = TBuilderMode extends 'db' ? MySqlSelectBase - : MySqlSelectQueryBuilderBase; +> = TBuilderMode extends 'db' ? GoogleSqlSelectBase + : GoogleSqlSelectQueryBuilderBase; -export type MySqlSelectQueryBuilder< - THKT extends MySqlSelectHKTBase = MySqlSelectQueryBuilderHKT, +export type GoogleSqlSelectQueryBuilder< + THKT extends GoogleSqlSelectHKTBase = GoogleSqlSelectQueryBuilderHKT, TTableName extends string | undefined = string | undefined, TSelection extends ColumnsSelection = ColumnsSelection, TSelectMode extends SelectMode = SelectMode, @@ -282,7 +282,7 @@ export type MySqlSelectQueryBuilder< TNullabilityMap extends Record = Record, TResult extends any[] = unknown[], TSelectedFields extends ColumnsSelection = ColumnsSelection, -> = MySqlSelectQueryBuilderBase< +> = GoogleSqlSelectQueryBuilderBase< THKT, TTableName, TSelection, @@ -295,11 +295,11 @@ export type MySqlSelectQueryBuilder< TSelectedFields >; -export type AnyMySqlSelectQueryBuilder = MySqlSelectQueryBuilderBase; +export type AnyGoogleSqlSelectQueryBuilder = GoogleSqlSelectQueryBuilderBase; -export type AnyMySqlSetOperatorInterface = MySqlSetOperatorInterface; +export type AnyGoogleSqlSetOperatorInterface = GoogleSqlSetOperatorInterface; -export interface MySqlSetOperatorInterface< +export interface GoogleSqlSetOperatorInterface< TTableName extends string | undefined, TSelection extends ColumnsSelection, TSelectMode extends SelectMode, @@ -312,7 +312,7 @@ export interface MySqlSetOperatorInterface< TSelectedFields extends ColumnsSelection = BuildSubquerySelection, > { _: { - readonly hkt: MySqlSelectHKT; + readonly hkt: GoogleSqlSelectHKT; readonly tableName: TTableName; readonly selection: TSelection; readonly selectMode: TSelectMode; @@ -325,7 +325,7 @@ export interface MySqlSetOperatorInterface< }; } -export type MySqlSetOperatorWithResult = MySqlSetOperatorInterface< +export type GoogleSqlSetOperatorWithResult = GoogleSqlSetOperatorInterface< any, any, any, @@ -337,35 +337,35 @@ export type MySqlSetOperatorWithResult = MySqlSetOperator any >; -export type MySqlSelect< +export type GoogleSqlSelect< TTableName extends string | undefined = string | undefined, TSelection extends ColumnsSelection = Record, TSelectMode extends SelectMode = SelectMode, TNullabilityMap extends Record = Record, -> = MySqlSelectBase; +> = GoogleSqlSelectBase; -export type AnyMySqlSelect = MySqlSelectBase; +export type AnyGoogleSqlSelect = GoogleSqlSelectBase; -export type MySqlSetOperator< +export type GoogleSqlSetOperator< TTableName extends string | undefined = string | undefined, TSelection extends ColumnsSelection = Record, TSelectMode extends SelectMode = SelectMode, TPreparedQueryHKT extends PreparedQueryHKTBase = PreparedQueryHKTBase, TNullabilityMap extends Record = Record, -> = MySqlSelectBase< +> = GoogleSqlSelectBase< TTableName, TSelection, TSelectMode, TPreparedQueryHKT, TNullabilityMap, true, - MySqlSetOperatorExcludedMethods + GoogleSqlSetOperatorExcludedMethods >; export type SetOperatorRightSelect< - TValue extends MySqlSetOperatorWithResult, + TValue extends GoogleSqlSetOperatorWithResult, TResult extends any[], -> = TValue extends MySqlSetOperatorInterface +> = TValue extends GoogleSqlSetOperatorInterface ? ValidateShape< TValueResult[number], TResult[number], @@ -374,11 +374,11 @@ export type SetOperatorRightSelect< : TValue; export type SetOperatorRestSelect< - TValue extends readonly MySqlSetOperatorWithResult[], + TValue extends readonly GoogleSqlSetOperatorWithResult[], TResult extends any[], > = TValue extends [infer First, ...infer Rest] - ? First extends MySqlSetOperatorInterface - ? Rest extends AnyMySqlSetOperatorInterface[] ? [ + ? First extends GoogleSqlSetOperatorInterface + ? Rest extends AnyGoogleSqlSetOperatorInterface[] ? [ ValidateShape>, ...SetOperatorRestSelect, ] @@ -386,12 +386,12 @@ export type SetOperatorRestSelect< : never : TValue; -export type MySqlCreateSetOperatorFn = < +export type GoogleSqlCreateSetOperatorFn = < TTableName extends string | undefined, TSelection extends ColumnsSelection, TSelectMode extends SelectMode, - TValue extends MySqlSetOperatorWithResult, - TRest extends MySqlSetOperatorWithResult[], + TValue extends GoogleSqlSetOperatorWithResult, + TRest extends GoogleSqlSetOperatorWithResult[], TPreparedQueryHKT extends PreparedQueryHKTBase = PreparedQueryHKTBase, TNullabilityMap extends Record = TTableName extends string ? Record : {}, @@ -400,7 +400,7 @@ export type MySqlCreateSetOperatorFn = < TResult extends any[] = SelectResult[], TSelectedFields extends ColumnsSelection = BuildSubquerySelection, >( - leftSelect: MySqlSetOperatorInterface< + leftSelect: GoogleSqlSetOperatorInterface< TTableName, TSelection, TSelectMode, @@ -413,8 +413,8 @@ export type MySqlCreateSetOperatorFn = < >, rightSelect: SetOperatorRightSelect, ...restSelects: SetOperatorRestSelect -) => MySqlSelectWithout< - MySqlSelectBase< +) => GoogleSqlSelectWithout< + GoogleSqlSelectBase< TTableName, TSelection, TSelectMode, @@ -426,15 +426,15 @@ export type MySqlCreateSetOperatorFn = < TSelectedFields >, false, - MySqlSetOperatorExcludedMethods, + GoogleSqlSetOperatorExcludedMethods, true >; -export type GetMySqlSetOperators = { - union: MySqlCreateSetOperatorFn; - intersect: MySqlCreateSetOperatorFn; - except: MySqlCreateSetOperatorFn; - unionAll: MySqlCreateSetOperatorFn; - intersectAll: MySqlCreateSetOperatorFn; - exceptAll: MySqlCreateSetOperatorFn; +export type GetGoogleSqlSetOperators = { + union: GoogleSqlCreateSetOperatorFn; + intersect: GoogleSqlCreateSetOperatorFn; + except: GoogleSqlCreateSetOperatorFn; + unionAll: GoogleSqlCreateSetOperatorFn; + intersectAll: GoogleSqlCreateSetOperatorFn; + exceptAll: GoogleSqlCreateSetOperatorFn; }; diff --git a/drizzle-orm/src/googlesql/query-builders/update.ts b/drizzle-orm/src/googlesql/query-builders/update.ts index 09ff3e33a0..b91870dc6a 100644 --- a/drizzle-orm/src/googlesql/query-builders/update.ts +++ b/drizzle-orm/src/googlesql/query-builders/update.ts @@ -1,36 +1,36 @@ import type { GetColumnData } from '~/column.ts'; import { entityKind } from '~/entity.ts'; -import type { MySqlDialect } from '~/googlesql/dialect.ts'; +import type { GoogleSqlDialect } from '~/googlesql/dialect.ts'; import type { - AnyMySqlQueryResultHKT, - MySqlPreparedQueryConfig, - MySqlQueryResultHKT, - MySqlQueryResultKind, - MySqlSession, + AnyGoogleSqlQueryResultHKT, + GoogleSqlPreparedQueryConfig, + GoogleSqlQueryResultHKT, + GoogleSqlQueryResultKind, + GoogleSqlSession, PreparedQueryHKTBase, PreparedQueryKind, } from '~/googlesql/session.ts'; -import type { MySqlTable } from '~/googlesql/table.ts'; +import type { GoogleSqlTable } from '~/googlesql/table.ts'; import { QueryPromise } from '~/query-promise.ts'; import { SelectionProxyHandler } from '~/selection-proxy.ts'; import type { Placeholder, Query, SQL, SQLWrapper } from '~/sql/sql.ts'; import type { Subquery } from '~/subquery.ts'; import { Table } from '~/table.ts'; import { mapUpdateSet, type UpdateSet, type ValueOrArray } from '~/utils.ts'; -import type { MySqlColumn } from '../columns/common.ts'; +import type { GoogleSqlColumn } from '../columns/common.ts'; import type { SelectedFieldsOrdered } from './select.types.ts'; -export interface MySqlUpdateConfig { +export interface GoogleSqlUpdateConfig { where?: SQL | undefined; limit?: number | Placeholder; - orderBy?: (MySqlColumn | SQL | SQL.Aliased)[]; + orderBy?: (GoogleSqlColumn | SQL | SQL.Aliased)[]; set: UpdateSet; - table: MySqlTable; + table: GoogleSqlTable; returning?: SelectedFieldsOrdered; withList?: Subquery[]; } -export type MySqlUpdateSetSource = +export type GoogleSqlUpdateSetSource = & { [Key in keyof TTable['$inferInsert']]?: | GetColumnData @@ -39,12 +39,12 @@ export type MySqlUpdateSetSource = } & {}; -export class MySqlUpdateBuilder< - TTable extends MySqlTable, - TQueryResult extends MySqlQueryResultHKT, +export class GoogleSqlUpdateBuilder< + TTable extends GoogleSqlTable, + TQueryResult extends GoogleSqlQueryResultHKT, TPreparedQueryHKT extends PreparedQueryHKTBase, > { - static readonly [entityKind]: string = 'MySqlUpdateBuilder'; + static readonly [entityKind]: string = 'GoogleSqlUpdateBuilder'; declare readonly _: { readonly table: TTable; @@ -52,22 +52,22 @@ export class MySqlUpdateBuilder< constructor( private table: TTable, - private session: MySqlSession, - private dialect: MySqlDialect, + private session: GoogleSqlSession, + private dialect: GoogleSqlDialect, private withList?: Subquery[], ) {} - set(values: MySqlUpdateSetSource): MySqlUpdateBase { - return new MySqlUpdateBase(this.table, mapUpdateSet(this.table, values), this.session, this.dialect, this.withList); + set(values: GoogleSqlUpdateSetSource): GoogleSqlUpdateBase { + return new GoogleSqlUpdateBase(this.table, mapUpdateSet(this.table, values), this.session, this.dialect, this.withList); } } -export type MySqlUpdateWithout< - T extends AnyMySqlUpdateBase, +export type GoogleSqlUpdateWithout< + T extends AnyGoogleSqlUpdateBase, TDynamic extends boolean, K extends keyof T & string, > = TDynamic extends true ? T : Omit< - MySqlUpdateBase< + GoogleSqlUpdateBase< T['_']['table'], T['_']['queryResult'], T['_']['preparedQueryHKT'], @@ -77,36 +77,36 @@ export type MySqlUpdateWithout< T['_']['excludedMethods'] | K >; -export type MySqlUpdatePrepare = PreparedQueryKind< +export type GoogleSqlUpdatePrepare = PreparedQueryKind< T['_']['preparedQueryHKT'], - MySqlPreparedQueryConfig & { - execute: MySqlQueryResultKind; + GoogleSqlPreparedQueryConfig & { + execute: GoogleSqlQueryResultKind; iterator: never; }, true >; -export type MySqlUpdateDynamic = MySqlUpdate< +export type GoogleSqlUpdateDynamic = GoogleSqlUpdate< T['_']['table'], T['_']['queryResult'], T['_']['preparedQueryHKT'] >; -export type MySqlUpdate< - TTable extends MySqlTable = MySqlTable, - TQueryResult extends MySqlQueryResultHKT = AnyMySqlQueryResultHKT, +export type GoogleSqlUpdate< + TTable extends GoogleSqlTable = GoogleSqlTable, + TQueryResult extends GoogleSqlQueryResultHKT = AnyGoogleSqlQueryResultHKT, TPreparedQueryHKT extends PreparedQueryHKTBase = PreparedQueryHKTBase, -> = MySqlUpdateBase; +> = GoogleSqlUpdateBase; -export type AnyMySqlUpdateBase = MySqlUpdateBase; +export type AnyGoogleSqlUpdateBase = GoogleSqlUpdateBase; -export interface MySqlUpdateBase< - TTable extends MySqlTable, - TQueryResult extends MySqlQueryResultHKT, +export interface GoogleSqlUpdateBase< + TTable extends GoogleSqlTable, + TQueryResult extends GoogleSqlQueryResultHKT, TPreparedQueryHKT extends PreparedQueryHKTBase, TDynamic extends boolean = false, TExcludedMethods extends string = never, -> extends QueryPromise>, SQLWrapper { +> extends QueryPromise>, SQLWrapper { readonly _: { readonly table: TTable; readonly queryResult: TQueryResult; @@ -116,25 +116,25 @@ export interface MySqlUpdateBase< }; } -export class MySqlUpdateBase< - TTable extends MySqlTable, - TQueryResult extends MySqlQueryResultHKT, +export class GoogleSqlUpdateBase< + TTable extends GoogleSqlTable, + TQueryResult extends GoogleSqlQueryResultHKT, // eslint-disable-next-line @typescript-eslint/no-unused-vars TPreparedQueryHKT extends PreparedQueryHKTBase, // eslint-disable-next-line @typescript-eslint/no-unused-vars TDynamic extends boolean = false, // eslint-disable-next-line @typescript-eslint/no-unused-vars TExcludedMethods extends string = never, -> extends QueryPromise> implements SQLWrapper { - static override readonly [entityKind]: string = 'MySqlUpdate'; +> extends QueryPromise> implements SQLWrapper { + static override readonly [entityKind]: string = 'GoogleSqlUpdate'; - private config: MySqlUpdateConfig; + private config: GoogleSqlUpdateConfig; constructor( table: TTable, set: UpdateSet, - private session: MySqlSession, - private dialect: MySqlDialect, + private session: GoogleSqlSession, + private dialect: GoogleSqlDialect, withList?: Subquery[], ) { super(); @@ -174,20 +174,20 @@ export class MySqlUpdateBase< * .where(or(eq(cars.color, 'green'), eq(cars.color, 'blue'))); * ``` */ - where(where: SQL | undefined): MySqlUpdateWithout { + where(where: SQL | undefined): GoogleSqlUpdateWithout { this.config.where = where; return this as any; } orderBy( - builder: (updateTable: TTable) => ValueOrArray, - ): MySqlUpdateWithout; - orderBy(...columns: (MySqlColumn | SQL | SQL.Aliased)[]): MySqlUpdateWithout; + builder: (updateTable: TTable) => ValueOrArray, + ): GoogleSqlUpdateWithout; + orderBy(...columns: (GoogleSqlColumn | SQL | SQL.Aliased)[]): GoogleSqlUpdateWithout; orderBy( ...columns: - | [(updateTable: TTable) => ValueOrArray] - | (MySqlColumn | SQL | SQL.Aliased)[] - ): MySqlUpdateWithout { + | [(updateTable: TTable) => ValueOrArray] + | (GoogleSqlColumn | SQL | SQL.Aliased)[] + ): GoogleSqlUpdateWithout { if (typeof columns[0] === 'function') { const orderBy = columns[0]( new Proxy( @@ -199,13 +199,13 @@ export class MySqlUpdateBase< const orderByArray = Array.isArray(orderBy) ? orderBy : [orderBy]; this.config.orderBy = orderByArray; } else { - const orderByArray = columns as (MySqlColumn | SQL | SQL.Aliased)[]; + const orderByArray = columns as (GoogleSqlColumn | SQL | SQL.Aliased)[]; this.config.orderBy = orderByArray; } return this as any; } - limit(limit: number | Placeholder): MySqlUpdateWithout { + limit(limit: number | Placeholder): GoogleSqlUpdateWithout { this.config.limit = limit; return this as any; } @@ -220,11 +220,11 @@ export class MySqlUpdateBase< return rest; } - prepare(): MySqlUpdatePrepare { + prepare(): GoogleSqlUpdatePrepare { return this.session.prepareQuery( this.dialect.sqlToQuery(this.getSQL()), this.config.returning, - ) as MySqlUpdatePrepare; + ) as GoogleSqlUpdatePrepare; } override execute: ReturnType['execute'] = (placeholderValues) => { @@ -240,7 +240,7 @@ export class MySqlUpdateBase< iterator = this.createIterator(); - $dynamic(): MySqlUpdateDynamic { + $dynamic(): GoogleSqlUpdateDynamic { return this as any; } } diff --git a/drizzle-orm/src/googlesql/schema.ts b/drizzle-orm/src/googlesql/schema.ts index b36531e44e..6104a2d91d 100644 --- a/drizzle-orm/src/googlesql/schema.ts +++ b/drizzle-orm/src/googlesql/schema.ts @@ -1,40 +1,40 @@ import { entityKind, is } from '~/entity.ts'; -import { type MySqlTableFn, mysqlTableWithSchema } from './table.ts'; -import { type mysqlView, mysqlViewWithSchema } from './view.ts'; +import { type GoogleSqlTableFn, googlesqlTableWithSchema } from './table.ts'; +import { type googlesqlView, googlesqlViewWithSchema } from './view.ts'; -export class MySqlSchema { - static readonly [entityKind]: string = 'MySqlSchema'; +export class GoogleSqlSchema { + static readonly [entityKind]: string = 'GoogleSqlSchema'; constructor( public readonly schemaName: TName, ) {} - table: MySqlTableFn = (name, columns, extraConfig) => { - return mysqlTableWithSchema(name, columns, extraConfig, this.schemaName); + table: GoogleSqlTableFn = (name, columns, extraConfig) => { + return googlesqlTableWithSchema(name, columns, extraConfig, this.schemaName); }; view = ((name, columns) => { - return mysqlViewWithSchema(name, columns, this.schemaName); - }) as typeof mysqlView; + return googlesqlViewWithSchema(name, columns, this.schemaName); + }) as typeof googlesqlView; } -/** @deprecated - use `instanceof MySqlSchema` */ -export function isMySqlSchema(obj: unknown): obj is MySqlSchema { - return is(obj, MySqlSchema); +/** @deprecated - use `instanceof GoogleSqlSchema` */ +export function isGoogleSqlSchema(obj: unknown): obj is GoogleSqlSchema { + return is(obj, GoogleSqlSchema); } /** * Create a MySQL schema. * https://dev.mysql.com/doc/refman/8.0/en/create-database.html * - * @param name mysql use schema name + * @param name googlesql use schema name * @returns MySQL schema */ -export function mysqlDatabase(name: TName) { - return new MySqlSchema(name); +export function googlesqlDatabase(name: TName) { + return new GoogleSqlSchema(name); } /** - * @see mysqlDatabase + * @see googlesqlDatabase */ -export const mysqlSchema = mysqlDatabase; +export const googlesqlSchema = googlesqlDatabase; diff --git a/drizzle-orm/src/googlesql/session.ts b/drizzle-orm/src/googlesql/session.ts index 326b0ad61e..443cc651f5 100644 --- a/drizzle-orm/src/googlesql/session.ts +++ b/drizzle-orm/src/googlesql/session.ts @@ -3,47 +3,47 @@ import { TransactionRollbackError } from '~/errors.ts'; import type { RelationalSchemaConfig, TablesRelationalConfig } from '~/relations.ts'; import { type Query, type SQL, sql } from '~/sql/sql.ts'; import type { Assume, Equal } from '~/utils.ts'; -import { MySqlDatabase } from './db.ts'; -import type { MySqlDialect } from './dialect.ts'; +import { GoogleSqlDatabase } from './db.ts'; +import type { GoogleSqlDialect } from './dialect.ts'; import type { SelectedFieldsOrdered } from './query-builders/select.types.ts'; export type Mode = 'default' | 'planetscale'; -export interface MySqlQueryResultHKT { - readonly $brand: 'MySqlQueryResultHKT'; +export interface GoogleSqlQueryResultHKT { + readonly $brand: 'GoogleSqlQueryResultHKT'; readonly row: unknown; readonly type: unknown; } -export interface AnyMySqlQueryResultHKT extends MySqlQueryResultHKT { +export interface AnyGoogleSqlQueryResultHKT extends GoogleSqlQueryResultHKT { readonly type: any; } -export type MySqlQueryResultKind = (TKind & { +export type GoogleSqlQueryResultKind = (TKind & { readonly row: TRow; })['type']; -export interface MySqlPreparedQueryConfig { +export interface GoogleSqlPreparedQueryConfig { execute: unknown; iterator: unknown; } -export interface MySqlPreparedQueryHKT { - readonly $brand: 'MySqlPreparedQueryHKT'; +export interface GoogleSqlPreparedQueryHKT { + readonly $brand: 'GoogleSqlPreparedQueryHKT'; readonly config: unknown; readonly type: unknown; } export type PreparedQueryKind< - TKind extends MySqlPreparedQueryHKT, - TConfig extends MySqlPreparedQueryConfig, + TKind extends GoogleSqlPreparedQueryHKT, + TConfig extends GoogleSqlPreparedQueryConfig, TAssume extends boolean = false, > = Equal extends true - ? Assume<(TKind & { readonly config: TConfig })['type'], MySqlPreparedQuery> + ? Assume<(TKind & { readonly config: TConfig })['type'], GoogleSqlPreparedQuery> : (TKind & { readonly config: TConfig })['type']; -export abstract class MySqlPreparedQuery { - static readonly [entityKind]: string = 'MySqlPreparedQuery'; +export abstract class GoogleSqlPreparedQuery { + static readonly [entityKind]: string = 'GoogleSqlPreparedQuery'; /** @internal */ joinsNotNullableMap?: Record; @@ -53,23 +53,23 @@ export abstract class MySqlPreparedQuery { abstract iterator(placeholderValues?: Record): AsyncGenerator; } -export interface MySqlTransactionConfig { +export interface GoogleSqlTransactionConfig { withConsistentSnapshot?: boolean; accessMode?: 'read only' | 'read write'; isolationLevel: 'read uncommitted' | 'read committed' | 'repeatable read' | 'serializable'; } -export abstract class MySqlSession< - TQueryResult extends MySqlQueryResultHKT = MySqlQueryResultHKT, +export abstract class GoogleSqlSession< + TQueryResult extends GoogleSqlQueryResultHKT = GoogleSqlQueryResultHKT, TPreparedQueryHKT extends PreparedQueryHKTBase = PreparedQueryHKTBase, TFullSchema extends Record = Record, TSchema extends TablesRelationalConfig = Record, > { - static readonly [entityKind]: string = 'MySqlSession'; + static readonly [entityKind]: string = 'GoogleSqlSession'; - constructor(protected dialect: MySqlDialect) {} + constructor(protected dialect: GoogleSqlDialect) {} - abstract prepareQuery( + abstract prepareQuery( query: Query, fields: SelectedFieldsOrdered | undefined, customResultMapper?: (rows: unknown[][]) => T['execute'], @@ -78,7 +78,7 @@ export abstract class MySqlSession< ): PreparedQueryKind; execute(query: SQL): Promise { - return this.prepareQuery( + return this.prepareQuery( this.dialect.sqlToQuery(query), undefined, ).execute(); @@ -95,11 +95,11 @@ export abstract class MySqlSession< } abstract transaction( - transaction: (tx: MySqlTransaction) => Promise, - config?: MySqlTransactionConfig, + transaction: (tx: GoogleSqlTransaction) => Promise, + config?: GoogleSqlTransactionConfig, ): Promise; - protected getSetTransactionSQL(config: MySqlTransactionConfig): SQL | undefined { + protected getSetTransactionSQL(config: GoogleSqlTransactionConfig): SQL | undefined { const parts: string[] = []; if (config.isolationLevel) { @@ -109,7 +109,7 @@ export abstract class MySqlSession< return parts.length ? sql`set transaction ${sql.raw(parts.join(' '))}` : undefined; } - protected getStartTransactionSQL(config: MySqlTransactionConfig): SQL | undefined { + protected getStartTransactionSQL(config: GoogleSqlTransactionConfig): SQL | undefined { const parts: string[] = []; if (config.withConsistentSnapshot) { @@ -124,17 +124,17 @@ export abstract class MySqlSession< } } -export abstract class MySqlTransaction< - TQueryResult extends MySqlQueryResultHKT, +export abstract class GoogleSqlTransaction< + TQueryResult extends GoogleSqlQueryResultHKT, TPreparedQueryHKT extends PreparedQueryHKTBase, TFullSchema extends Record = Record, TSchema extends TablesRelationalConfig = Record, -> extends MySqlDatabase { - static override readonly [entityKind]: string = 'MySqlTransaction'; +> extends GoogleSqlDatabase { + static override readonly [entityKind]: string = 'GoogleSqlTransaction'; constructor( - dialect: MySqlDialect, - session: MySqlSession, + dialect: GoogleSqlDialect, + session: GoogleSqlSession, protected schema: RelationalSchemaConfig | undefined, protected readonly nestedIndex: number, mode: Mode, @@ -148,10 +148,10 @@ export abstract class MySqlTransaction< /** Nested transactions (aka savepoints) only work with InnoDB engine. */ abstract override transaction( - transaction: (tx: MySqlTransaction) => Promise, + transaction: (tx: GoogleSqlTransaction) => Promise, ): Promise; } -export interface PreparedQueryHKTBase extends MySqlPreparedQueryHKT { - type: MySqlPreparedQuery>; +export interface PreparedQueryHKTBase extends GoogleSqlPreparedQueryHKT { + type: GoogleSqlPreparedQuery>; } diff --git a/drizzle-orm/src/googlesql/subquery.ts b/drizzle-orm/src/googlesql/subquery.ts index 9838cb1943..ca2fd2f9ce 100644 --- a/drizzle-orm/src/googlesql/subquery.ts +++ b/drizzle-orm/src/googlesql/subquery.ts @@ -8,15 +8,15 @@ export type SubqueryWithSelection< TSelection extends ColumnsSelection, TAlias extends string, > = - & Subquery> - & AddAliasToSelection; + & Subquery> + & AddAliasToSelection; export type WithSubqueryWithSelection< TSelection extends ColumnsSelection, TAlias extends string, > = - & WithSubquery> - & AddAliasToSelection; + & WithSubquery> + & AddAliasToSelection; export interface WithBuilder { (alias: TAlias): { diff --git a/drizzle-orm/src/googlesql/table.ts b/drizzle-orm/src/googlesql/table.ts index 2616e71597..6e71d2be3e 100644 --- a/drizzle-orm/src/googlesql/table.ts +++ b/drizzle-orm/src/googlesql/table.ts @@ -2,32 +2,32 @@ import type { BuildColumns, BuildExtraConfigColumns } from '~/column-builder.ts' import { entityKind } from '~/entity.ts'; import { Table, type TableConfig as TableConfigBase, type UpdateTableConfig } from '~/table.ts'; import type { CheckBuilder } from './checks.ts'; -import { getMySqlColumnBuilders, type MySqlColumnBuilders } from './columns/all.ts'; -import type { MySqlColumn, MySqlColumnBuilder, MySqlColumnBuilderBase } from './columns/common.ts'; +import { getGoogleSqlColumnBuilders, type GoogleSqlColumnBuilders } from './columns/all.ts'; +import type { GoogleSqlColumn, GoogleSqlColumnBuilder, GoogleSqlColumnBuilderBase } from './columns/common.ts'; import type { ForeignKey, ForeignKeyBuilder } from './foreign-keys.ts'; import type { AnyIndexBuilder } from './indexes.ts'; import type { PrimaryKeyBuilder } from './primary-keys.ts'; import type { UniqueConstraintBuilder } from './unique-constraint.ts'; -export type MySqlTableExtraConfigValue = +export type GoogleSqlTableExtraConfigValue = | AnyIndexBuilder | CheckBuilder | ForeignKeyBuilder | PrimaryKeyBuilder | UniqueConstraintBuilder; -export type MySqlTableExtraConfig = Record< +export type GoogleSqlTableExtraConfig = Record< string, - MySqlTableExtraConfigValue + GoogleSqlTableExtraConfigValue >; -export type TableConfig = TableConfigBase; +export type TableConfig = TableConfigBase; /** @internal */ -export const InlineForeignKeys = Symbol.for('drizzle:MySqlInlineForeignKeys'); +export const InlineForeignKeys = Symbol.for('drizzle:GoogleSqlInlineForeignKeys'); -export class MySqlTable extends Table { - static override readonly [entityKind]: string = 'MySqlTable'; +export class GoogleSqlTable extends Table { + static override readonly [entityKind]: string = 'GoogleSqlTable'; declare protected $columns: T['columns']; @@ -44,58 +44,58 @@ export class MySqlTable extends Table { /** @internal */ override [Table.Symbol.ExtraConfigBuilder]: - | ((self: Record) => MySqlTableExtraConfig) + | ((self: Record) => GoogleSqlTableExtraConfig) | undefined = undefined; } -export type AnyMySqlTable = {}> = MySqlTable< +export type AnyGoogleSqlTable = {}> = GoogleSqlTable< UpdateTableConfig >; -export type MySqlTableWithColumns = - & MySqlTable +export type GoogleSqlTableWithColumns = + & GoogleSqlTable & { [Key in keyof T['columns']]: T['columns'][Key]; }; -export function mysqlTableWithSchema< +export function googlesqlTableWithSchema< TTableName extends string, TSchemaName extends string | undefined, - TColumnsMap extends Record, + TColumnsMap extends Record, >( name: TTableName, - columns: TColumnsMap | ((columnTypes: MySqlColumnBuilders) => TColumnsMap), + columns: TColumnsMap | ((columnTypes: GoogleSqlColumnBuilders) => TColumnsMap), extraConfig: | (( - self: BuildColumns, - ) => MySqlTableExtraConfig | MySqlTableExtraConfigValue[]) + self: BuildColumns, + ) => GoogleSqlTableExtraConfig | GoogleSqlTableExtraConfigValue[]) | undefined, schema: TSchemaName, baseName = name, -): MySqlTableWithColumns<{ +): GoogleSqlTableWithColumns<{ name: TTableName; schema: TSchemaName; - columns: BuildColumns; - dialect: 'mysql'; + columns: BuildColumns; + dialect: 'googlesql'; }> { - const rawTable = new MySqlTable<{ + const rawTable = new GoogleSqlTable<{ name: TTableName; schema: TSchemaName; - columns: BuildColumns; - dialect: 'mysql'; + columns: BuildColumns; + dialect: 'googlesql'; }>(name, schema, baseName); - const parsedColumns: TColumnsMap = typeof columns === 'function' ? columns(getMySqlColumnBuilders()) : columns; + const parsedColumns: TColumnsMap = typeof columns === 'function' ? columns(getGoogleSqlColumnBuilders()) : columns; const builtColumns = Object.fromEntries( Object.entries(parsedColumns).map(([name, colBuilderBase]) => { - const colBuilder = colBuilderBase as MySqlColumnBuilder; + const colBuilder = colBuilderBase as GoogleSqlColumnBuilder; colBuilder.setName(name); const column = colBuilder.build(rawTable); rawTable[InlineForeignKeys].push(...colBuilder.buildForeignKeys(column, rawTable)); return [name, column]; }), - ) as unknown as BuildColumns; + ) as unknown as BuildColumns; const table = Object.assign(rawTable, builtColumns); @@ -103,55 +103,55 @@ export function mysqlTableWithSchema< table[Table.Symbol.ExtraConfigColumns] = builtColumns as unknown as BuildExtraConfigColumns< TTableName, TColumnsMap, - 'mysql' + 'googlesql' >; if (extraConfig) { - table[MySqlTable.Symbol.ExtraConfigBuilder] = extraConfig as unknown as ( - self: Record, - ) => MySqlTableExtraConfig; + table[GoogleSqlTable.Symbol.ExtraConfigBuilder] = extraConfig as unknown as ( + self: Record, + ) => GoogleSqlTableExtraConfig; } return table; } -export interface MySqlTableFn { +export interface GoogleSqlTableFn { < TTableName extends string, - TColumnsMap extends Record, + TColumnsMap extends Record, >( name: TTableName, columns: TColumnsMap, extraConfig?: ( - self: BuildColumns, - ) => MySqlTableExtraConfigValue[], - ): MySqlTableWithColumns<{ + self: BuildColumns, + ) => GoogleSqlTableExtraConfigValue[], + ): GoogleSqlTableWithColumns<{ name: TTableName; schema: TSchemaName; - columns: BuildColumns; - dialect: 'mysql'; + columns: BuildColumns; + dialect: 'googlesql'; }>; < TTableName extends string, - TColumnsMap extends Record, + TColumnsMap extends Record, >( name: TTableName, - columns: (columnTypes: MySqlColumnBuilders) => TColumnsMap, - extraConfig?: (self: BuildColumns) => MySqlTableExtraConfigValue[], - ): MySqlTableWithColumns<{ + columns: (columnTypes: GoogleSqlColumnBuilders) => TColumnsMap, + extraConfig?: (self: BuildColumns) => GoogleSqlTableExtraConfigValue[], + ): GoogleSqlTableWithColumns<{ name: TTableName; schema: TSchemaName; - columns: BuildColumns; - dialect: 'mysql'; + columns: BuildColumns; + dialect: 'googlesql'; }>; /** - * @deprecated The third parameter of mysqlTable is changing and will only accept an array instead of an object + * @deprecated The third parameter of googlesqlTable is changing and will only accept an array instead of an object * * @example * Deprecated version: * ```ts - * export const users = mysqlTable("users", { + * export const users = googlesqlTable("users", { * id: int(), * }, (t) => ({ * idx: index('custom_name').on(t.id) @@ -160,7 +160,7 @@ export interface MySqlTableFn [ * index('custom_name').on(t.id) @@ -169,25 +169,25 @@ export interface MySqlTableFn, + TColumnsMap extends Record, >( name: TTableName, columns: TColumnsMap, - extraConfig: (self: BuildColumns) => MySqlTableExtraConfig, - ): MySqlTableWithColumns<{ + extraConfig: (self: BuildColumns) => GoogleSqlTableExtraConfig, + ): GoogleSqlTableWithColumns<{ name: TTableName; schema: TSchemaName; - columns: BuildColumns; - dialect: 'mysql'; + columns: BuildColumns; + dialect: 'googlesql'; }>; /** - * @deprecated The third parameter of mysqlTable is changing and will only accept an array instead of an object + * @deprecated The third parameter of googlesqlTable is changing and will only accept an array instead of an object * * @example * Deprecated version: * ```ts - * export const users = mysqlTable("users", { + * export const users = googlesqlTable("users", { * id: int(), * }, (t) => ({ * idx: index('custom_name').on(t.id) @@ -196,7 +196,7 @@ export interface MySqlTableFn [ * index('custom_name').on(t.id) @@ -205,25 +205,25 @@ export interface MySqlTableFn, + TColumnsMap extends Record, >( name: TTableName, - columns: (columnTypes: MySqlColumnBuilders) => TColumnsMap, - extraConfig: (self: BuildColumns) => MySqlTableExtraConfig, - ): MySqlTableWithColumns<{ + columns: (columnTypes: GoogleSqlColumnBuilders) => TColumnsMap, + extraConfig: (self: BuildColumns) => GoogleSqlTableExtraConfig, + ): GoogleSqlTableWithColumns<{ name: TTableName; schema: TSchemaName; - columns: BuildColumns; - dialect: 'mysql'; + columns: BuildColumns; + dialect: 'googlesql'; }>; } -export const mysqlTable: MySqlTableFn = (name, columns, extraConfig) => { - return mysqlTableWithSchema(name, columns, extraConfig, undefined, name); +export const googlesqlTable: GoogleSqlTableFn = (name, columns, extraConfig) => { + return googlesqlTableWithSchema(name, columns, extraConfig, undefined, name); }; -export function mysqlTableCreator(customizeTableName: (name: string) => string): MySqlTableFn { +export function googlesqlTableCreator(customizeTableName: (name: string) => string): GoogleSqlTableFn { return (name, columns, extraConfig) => { - return mysqlTableWithSchema(customizeTableName(name) as typeof name, columns, extraConfig, undefined, name); + return googlesqlTableWithSchema(customizeTableName(name) as typeof name, columns, extraConfig, undefined, name); }; } diff --git a/drizzle-orm/src/googlesql/unique-constraint.ts b/drizzle-orm/src/googlesql/unique-constraint.ts index 01a3c36c28..1bc72b8ce5 100644 --- a/drizzle-orm/src/googlesql/unique-constraint.ts +++ b/drizzle-orm/src/googlesql/unique-constraint.ts @@ -1,37 +1,37 @@ import { entityKind } from '~/entity.ts'; import { TableName } from '~/table.utils.ts'; -import type { MySqlColumn } from './columns/index.ts'; -import type { MySqlTable } from './table.ts'; +import type { GoogleSqlColumn } from './columns/index.ts'; +import type { GoogleSqlTable } from './table.ts'; export function unique(name?: string): UniqueOnConstraintBuilder { return new UniqueOnConstraintBuilder(name); } -export function uniqueKeyName(table: MySqlTable, columns: string[]) { +export function uniqueKeyName(table: GoogleSqlTable, columns: string[]) { return `${table[TableName]}_${columns.join('_')}_unique`; } export class UniqueConstraintBuilder { - static readonly [entityKind]: string = 'MySqlUniqueConstraintBuilder'; + static readonly [entityKind]: string = 'GoogleSqlUniqueConstraintBuilder'; /** @internal */ - columns: MySqlColumn[]; + columns: GoogleSqlColumn[]; constructor( - columns: MySqlColumn[], + columns: GoogleSqlColumn[], private name?: string, ) { this.columns = columns; } /** @internal */ - build(table: MySqlTable): UniqueConstraint { + build(table: GoogleSqlTable): UniqueConstraint { return new UniqueConstraint(table, this.columns, this.name); } } export class UniqueOnConstraintBuilder { - static readonly [entityKind]: string = 'MySqlUniqueOnConstraintBuilder'; + static readonly [entityKind]: string = 'GoogleSqlUniqueOnConstraintBuilder'; /** @internal */ name?: string; @@ -42,19 +42,19 @@ export class UniqueOnConstraintBuilder { this.name = name; } - on(...columns: [MySqlColumn, ...MySqlColumn[]]) { + on(...columns: [GoogleSqlColumn, ...GoogleSqlColumn[]]) { return new UniqueConstraintBuilder(columns, this.name); } } export class UniqueConstraint { - static readonly [entityKind]: string = 'MySqlUniqueConstraint'; + static readonly [entityKind]: string = 'GoogleSqlUniqueConstraint'; - readonly columns: MySqlColumn[]; + readonly columns: GoogleSqlColumn[]; readonly name?: string; readonly nullsNotDistinct: boolean = false; - constructor(readonly table: MySqlTable, columns: MySqlColumn[], name?: string) { + constructor(readonly table: GoogleSqlTable, columns: GoogleSqlColumn[], name?: string) { this.columns = columns; this.name = name ?? uniqueKeyName(this.table, this.columns.map((column) => column.name)); } diff --git a/drizzle-orm/src/googlesql/utils.ts b/drizzle-orm/src/googlesql/utils.ts index b49dd00433..90ed0c45a1 100644 --- a/drizzle-orm/src/googlesql/utils.ts +++ b/drizzle-orm/src/googlesql/utils.ts @@ -10,26 +10,26 @@ import { IndexBuilder } from './indexes.ts'; import type { PrimaryKey } from './primary-keys.ts'; import { PrimaryKeyBuilder } from './primary-keys.ts'; import type { IndexForHint } from './query-builders/select.ts'; -import { MySqlTable } from './table.ts'; +import { GoogleSqlTable } from './table.ts'; import { type UniqueConstraint, UniqueConstraintBuilder } from './unique-constraint.ts'; -import { MySqlViewConfig } from './view-common.ts'; -import type { MySqlView } from './view.ts'; +import { GoogleSqlViewConfig } from './view-common.ts'; +import type { GoogleSqlView } from './view.ts'; -export function getTableConfig(table: MySqlTable) { - const columns = Object.values(table[MySqlTable.Symbol.Columns]); +export function getTableConfig(table: GoogleSqlTable) { + const columns = Object.values(table[GoogleSqlTable.Symbol.Columns]); const indexes: Index[] = []; const checks: Check[] = []; const primaryKeys: PrimaryKey[] = []; const uniqueConstraints: UniqueConstraint[] = []; - const foreignKeys: ForeignKey[] = Object.values(table[MySqlTable.Symbol.InlineForeignKeys]); + const foreignKeys: ForeignKey[] = Object.values(table[GoogleSqlTable.Symbol.InlineForeignKeys]); const name = table[Table.Symbol.Name]; const schema = table[Table.Symbol.Schema]; const baseName = table[Table.Symbol.BaseName]; - const extraConfigBuilder = table[MySqlTable.Symbol.ExtraConfigBuilder]; + const extraConfigBuilder = table[GoogleSqlTable.Symbol.ExtraConfigBuilder]; if (extraConfigBuilder !== undefined) { - const extraConfig = extraConfigBuilder(table[MySqlTable.Symbol.Columns]); + const extraConfig = extraConfigBuilder(table[GoogleSqlTable.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)) { @@ -62,10 +62,10 @@ export function getTableConfig(table: MySqlTable) { export function getViewConfig< TName extends string = string, TExisting extends boolean = boolean, ->(view: MySqlView) { +>(view: GoogleSqlView) { return { ...view[ViewBaseConfig], - ...view[MySqlViewConfig], + ...view[GoogleSqlViewConfig], }; } diff --git a/drizzle-orm/src/googlesql/view-base.ts b/drizzle-orm/src/googlesql/view-base.ts index fa8a25cfa4..0a836e24e9 100644 --- a/drizzle-orm/src/googlesql/view-base.ts +++ b/drizzle-orm/src/googlesql/view-base.ts @@ -2,14 +2,14 @@ import { entityKind } from '~/entity.ts'; import type { ColumnsSelection } from '~/sql/sql.ts'; import { View } from '~/sql/sql.ts'; -export abstract class MySqlViewBase< +export abstract class GoogleSqlViewBase< TName extends string = string, TExisting extends boolean = boolean, TSelectedFields extends ColumnsSelection = ColumnsSelection, > extends View { - static override readonly [entityKind]: string = 'MySqlViewBase'; + static override readonly [entityKind]: string = 'GoogleSqlViewBase'; declare readonly _: View['_'] & { - readonly viewBrand: 'MySqlViewBase'; + readonly viewBrand: 'GoogleSqlViewBase'; }; } diff --git a/drizzle-orm/src/googlesql/view-common.ts b/drizzle-orm/src/googlesql/view-common.ts index 9bbc130c33..c8060efdea 100644 --- a/drizzle-orm/src/googlesql/view-common.ts +++ b/drizzle-orm/src/googlesql/view-common.ts @@ -1 +1 @@ -export const MySqlViewConfig = Symbol.for('drizzle:MySqlViewConfig'); +export const GoogleSqlViewConfig = Symbol.for('drizzle:GoogleSqlViewConfig'); diff --git a/drizzle-orm/src/googlesql/view.ts b/drizzle-orm/src/googlesql/view.ts index 42d9b3af6d..4b69572f1c 100644 --- a/drizzle-orm/src/googlesql/view.ts +++ b/drizzle-orm/src/googlesql/view.ts @@ -5,11 +5,11 @@ import type { AddAliasToSelection } from '~/query-builders/select.types.ts'; import { SelectionProxyHandler } from '~/selection-proxy.ts'; import type { ColumnsSelection, SQL } from '~/sql/sql.ts'; import { getTableColumns } from '~/utils.ts'; -import type { MySqlColumn, MySqlColumnBuilderBase } from './columns/index.ts'; +import type { GoogleSqlColumn, GoogleSqlColumnBuilderBase } from './columns/index.ts'; import { QueryBuilder } from './query-builders/query-builder.ts'; -import { mysqlTable } from './table.ts'; -import { MySqlViewBase } from './view-base.ts'; -import { MySqlViewConfig } from './view-common.ts'; +import { googlesqlTable } from './table.ts'; +import { GoogleSqlViewBase } from './view-base.ts'; +import { GoogleSqlViewConfig } from './view-common.ts'; export interface ViewBuilderConfig { algorithm?: 'undefined' | 'merge' | 'temptable'; @@ -18,7 +18,7 @@ export interface ViewBuilderConfig { } export class ViewBuilderCore { - static readonly [entityKind]: string = 'MySqlViewBuilder'; + static readonly [entityKind]: string = 'GoogleSqlViewBuilder'; declare readonly _: { readonly name: TConfig['name']; @@ -55,11 +55,11 @@ export class ViewBuilderCore extends ViewBuilderCore<{ name: TName }> { - static override readonly [entityKind]: string = 'MySqlViewBuilder'; + static override readonly [entityKind]: string = 'GoogleSqlViewBuilder'; as( qb: TypedQueryBuilder | ((qb: QueryBuilder) => TypedQueryBuilder), - ): MySqlViewWithSelection> { + ): GoogleSqlViewWithSelection> { if (typeof qb === 'function') { qb = qb(new QueryBuilder()); } @@ -71,8 +71,8 @@ export class ViewBuilder extends ViewBuilderCore< }); const aliasedSelection = new Proxy(qb.getSelectedFields(), selectionProxy); return new Proxy( - new MySqlView({ - mysqlConfig: this.config, + new GoogleSqlView({ + googlesqlConfig: this.config, config: { name: this.name, schema: this.schema, @@ -81,17 +81,17 @@ export class ViewBuilder extends ViewBuilderCore< }, }), selectionProxy as any, - ) as MySqlViewWithSelection>; + ) as GoogleSqlViewWithSelection>; } } export class ManualViewBuilder< TName extends string = string, - TColumns extends Record = Record, + TColumns extends Record = Record, > extends ViewBuilderCore<{ name: TName; columns: TColumns }> { - static override readonly [entityKind]: string = 'MySqlManualViewBuilder'; + static override readonly [entityKind]: string = 'GoogleSqlManualViewBuilder'; - private columns: Record; + private columns: Record; constructor( name: TName, @@ -99,13 +99,13 @@ export class ManualViewBuilder< schema: string | undefined, ) { super(name, schema); - this.columns = getTableColumns(mysqlTable(name, columns)) as BuildColumns; + this.columns = getTableColumns(googlesqlTable(name, columns)) as BuildColumns; } - existing(): MySqlViewWithSelection> { + existing(): GoogleSqlViewWithSelection> { return new Proxy( - new MySqlView({ - mysqlConfig: undefined, + new GoogleSqlView({ + googlesqlConfig: undefined, config: { name: this.name, schema: this.schema, @@ -119,13 +119,13 @@ export class ManualViewBuilder< sqlAliasedBehavior: 'alias', replaceOriginalName: true, }), - ) as MySqlViewWithSelection>; + ) as GoogleSqlViewWithSelection>; } - as(query: SQL): MySqlViewWithSelection> { + as(query: SQL): GoogleSqlViewWithSelection> { return new Proxy( - new MySqlView({ - mysqlConfig: this.config, + new GoogleSqlView({ + googlesqlConfig: this.config, config: { name: this.name, schema: this.schema, @@ -139,23 +139,23 @@ export class ManualViewBuilder< sqlAliasedBehavior: 'alias', replaceOriginalName: true, }), - ) as MySqlViewWithSelection>; + ) as GoogleSqlViewWithSelection>; } } -export class MySqlView< +export class GoogleSqlView< TName extends string = string, TExisting extends boolean = boolean, TSelectedFields extends ColumnsSelection = ColumnsSelection, -> extends MySqlViewBase { - static override readonly [entityKind]: string = 'MySqlView'; +> extends GoogleSqlViewBase { + static override readonly [entityKind]: string = 'GoogleSqlView'; - declare protected $MySqlViewBrand: 'MySqlView'; + declare protected $GoogleSqlViewBrand: 'GoogleSqlView'; - [MySqlViewConfig]: ViewBuilderConfig | undefined; + [GoogleSqlViewConfig]: ViewBuilderConfig | undefined; - constructor({ mysqlConfig, config }: { - mysqlConfig: ViewBuilderConfig | undefined; + constructor({ googlesqlConfig, config }: { + googlesqlConfig: ViewBuilderConfig | undefined; config: { name: TName; schema: string | undefined; @@ -164,20 +164,20 @@ export class MySqlView< }; }) { super(config); - this[MySqlViewConfig] = mysqlConfig; + this[GoogleSqlViewConfig] = googlesqlConfig; } } -export type MySqlViewWithSelection< +export type GoogleSqlViewWithSelection< TName extends string, TExisting extends boolean, TSelectedFields extends ColumnsSelection, -> = MySqlView & TSelectedFields; +> = GoogleSqlView & TSelectedFields; /** @internal */ -export function mysqlViewWithSchema( +export function googlesqlViewWithSchema( name: string, - selection: Record | undefined, + selection: Record | undefined, schema: string | undefined, ): ViewBuilder | ManualViewBuilder { if (selection) { @@ -186,14 +186,14 @@ export function mysqlViewWithSchema( return new ViewBuilder(name, schema); } -export function mysqlView(name: TName): ViewBuilder; -export function mysqlView>( +export function googlesqlView(name: TName): ViewBuilder; +export function googlesqlView>( name: TName, columns: TColumns, ): ManualViewBuilder; -export function mysqlView( +export function googlesqlView( name: string, - selection?: Record, + selection?: Record, ): ViewBuilder | ManualViewBuilder { - return mysqlViewWithSchema(name, selection, undefined); + return googlesqlViewWithSchema(name, selection, undefined); } From 905252f72f67ea246f7bcddabaced56be5b626c5 Mon Sep 17 00:00:00 2001 From: Gabriel Cipriano Date: Wed, 26 Feb 2025 16:42:19 +0100 Subject: [PATCH 4/7] chore: add TODOs --- drizzle-kit/src/cli/commands/utils.ts | 24 ++++++++ drizzle-kit/src/cli/schema.ts | 31 ++++++++++ drizzle-kit/src/cli/validations/googlesql.ts | 65 ++++++++++++++++++++ drizzle-kit/src/cli/validations/outputs.ts | 11 +++- drizzle-kit/src/index.ts | 3 +- drizzle-kit/src/migrationPreparator.ts | 9 +++ drizzle-kit/src/schemaValidator.ts | 3 +- drizzle-kit/src/sqlgenerator.ts | 2 + drizzle-kit/src/utils.ts | 2 + drizzle-orm/src/column-builder.ts | 18 +++++- 10 files changed, 164 insertions(+), 4 deletions(-) create mode 100644 drizzle-kit/src/cli/validations/googlesql.ts diff --git a/drizzle-kit/src/cli/commands/utils.ts b/drizzle-kit/src/cli/commands/utils.ts index d0abcee72e..6c18b6901e 100644 --- a/drizzle-kit/src/cli/commands/utils.ts +++ b/drizzle-kit/src/cli/commands/utils.ts @@ -444,6 +444,8 @@ export const preparePushConfig = async ( ), ); process.exit(1); + } else if (config.dialect === 'googlesql') { + throw new Error('Not implemented'); // TODO: SPANNER } assertUnreachable(config.dialect); @@ -643,6 +645,8 @@ export const preparePullConfig = async ( prefix: config.migrations?.prefix || 'index', entities: config.entities, }; + } else if (dialect === 'googlesql') { + throw new Error('Not implemented'); // TODO: SPANNER } assertUnreachable(dialect); @@ -754,6 +758,15 @@ export const prepareStudioConfig = async (options: Record) => { ), ); process.exit(1); + } else if (dialect === 'googlesql') { + throw new Error('Not implemented'); // TODO: SPANNER - not a priority + return { + dialect, + schema, + host, + port, + credentials: null as any, + }; } assertUnreachable(dialect); @@ -866,6 +879,17 @@ export const prepareMigrateConfig = async (configPath: string | undefined) => { process.exit(1); } + if (dialect === 'googlesql') { + throw new Error('Not implemented'); // TODO: SPANNER + return { + dialect, + out, + credentials: null as any, + schema, + table, + }; + } + assertUnreachable(dialect); }; diff --git a/drizzle-kit/src/cli/schema.ts b/drizzle-kit/src/cli/schema.ts index 2f8c410f47..0b15379bfa 100644 --- a/drizzle-kit/src/cli/schema.ts +++ b/drizzle-kit/src/cli/schema.ts @@ -106,6 +106,8 @@ export const generate = command({ ), ); process.exit(1); + } else if (dialect === 'googlesql') { + throw new Error('Not implemented'); // TODO: SPANNER } else { assertUnreachable(dialect); } @@ -208,6 +210,8 @@ export const migrate = command({ ), ); process.exit(1); + } else if (dialect === 'googlesql') { + throw new Error('Not implemented'); // TODO: SPANNER } else { assertUnreachable(dialect); } @@ -393,6 +397,13 @@ export const push = command({ ), ); process.exit(1); + } else if (dialect === 'googlesql') { + console.log( + error( + `You can't use 'push' command with GoogleSql dialect`, + ), + ); + process.exit(1); } else { assertUnreachable(dialect); } @@ -464,6 +475,10 @@ export const up = command({ ); process.exit(1); } + + if (dialect === 'googlesql') { + throw new Error('Not implemented'); // TODO: SPANNER + } }, }); @@ -620,6 +635,13 @@ export const pull = command({ prefix, entities, ); + } else if (dialect === 'googlesql') { + console.log( + error( + `You can't use 'pull' command with GoogleSql dialect`, + ), + ); + process.exit(1); } else { assertUnreachable(dialect); } @@ -745,6 +767,13 @@ export const studio = command({ ), ); process.exit(1); + } else if (dialect === 'googlesql') { + console.log( + error( + `You can't use 'studio' command with GoogleSql dialect`, + ), + ); + process.exit(1); } else { assertUnreachable(dialect); } @@ -847,6 +876,8 @@ export const exportRaw = command({ ), ); process.exit(1); + } else if (dialect === 'googlesql') { + throw new Error('Not implemented'); // TODO: SPANNER - probably not a priority } else { assertUnreachable(dialect); } diff --git a/drizzle-kit/src/cli/validations/googlesql.ts b/drizzle-kit/src/cli/validations/googlesql.ts new file mode 100644 index 0000000000..a34c22264d --- /dev/null +++ b/drizzle-kit/src/cli/validations/googlesql.ts @@ -0,0 +1,65 @@ +import { boolean, coerce, object, string, TypeOf, union } from 'zod'; +import { error } from '../views'; +import { wrapParam } from './common'; +import { outputs } from './outputs'; + +// TODO: SPANNER - add proper credentials config + +export const googlesqlCredentials = union([ + object({ + host: string().min(1), + port: coerce.number().min(1).optional(), + user: string().min(1).optional(), + // password: string().min(1).optional(), + // database: string().min(1), + // ssl: union([ + // string(), + // object({ + // pfx: string().optional(), + // key: string().optional(), + // passphrase: string().optional(), + // cert: string().optional(), + // ca: union([string(), string().array()]).optional(), + // crl: union([string(), string().array()]).optional(), + // ciphers: string().optional(), + // rejectUnauthorized: boolean().optional(), + // }), + // ]).optional(), + }), + object({ + url: string().min(1), + }), +]); + +export type GoogleSqlCredentials = TypeOf; + +// TODO: SPANNER - add proper connection issues +export const printCliConnectionIssues = (options: any) => { + // const { uri, host, database } = options || {}; + + // if (!uri && (!host || !database)) { + // console.log(outputs.googlesql.connection.required()); + // } +}; + +// TODO: SPANNER - add proper connection issues +export const printConfigConnectionIssues = ( + options: Record, +) => { + // if ('url' in options) { + // let text = `Please provide required params for MySQL driver:\n`; + // console.log(error(text)); + // console.log(wrapParam('url', options.url, false, 'url')); + // process.exit(1); + // } + + // let text = `Please provide required params for MySQL driver:\n`; + // console.log(error(text)); + // console.log(wrapParam('host', options.host)); + // console.log(wrapParam('port', options.port, true)); + // console.log(wrapParam('user', options.user, true)); + // console.log(wrapParam('password', options.password, true, 'secret')); + // console.log(wrapParam('database', options.database)); + // console.log(wrapParam('ssl', options.ssl, true)); + // process.exit(1); +}; diff --git a/drizzle-kit/src/cli/validations/outputs.ts b/drizzle-kit/src/cli/validations/outputs.ts index 6e9d520dd6..d93197643a 100644 --- a/drizzle-kit/src/cli/validations/outputs.ts +++ b/drizzle-kit/src/cli/validations/outputs.ts @@ -26,7 +26,7 @@ export const outputs = { ), noDialect: () => withStyle.error( - `Please specify 'dialect' param in config, either of 'postgresql', 'mysql', 'sqlite', turso or singlestore`, + `Please specify 'dialect' param in config, either of 'postgresql', 'mysql', 'sqlite', 'googlesql', turso or singlestore`, ), }, common: { @@ -88,4 +88,13 @@ export const outputs = { ), }, }, + googlesql: { + connection: { + driver: () => withStyle.error(`Only "spanner" is available options for "--driver"`), + required: () => + withStyle.error( + `Either "url" or "host", "database" are required for database connection`, // TODO: SPANNER - write proper error message + ), + }, + }, }; diff --git a/drizzle-kit/src/index.ts b/drizzle-kit/src/index.ts index e3d3d33134..2b597c8059 100644 --- a/drizzle-kit/src/index.ts +++ b/drizzle-kit/src/index.ts @@ -252,6 +252,7 @@ export type Config = }) ); } + // TODO: SPANNER - add googlesql/spanner config ); /** @@ -261,7 +262,7 @@ export type Config = * **Config** usage: * * `dialect` - mandatory and is responsible for explicitly providing a databse dialect you are using for all the commands - * *Possible values*: `postgresql`, `mysql`, `sqlite`, `singlestore`, `gel` + * *Possible values*: `postgresql`, `mysql`, `sqlite`, `singlestore`, `gel`, `googlesql` * * See https://orm.drizzle.team/kit-docs/config-reference#dialect * diff --git a/drizzle-kit/src/migrationPreparator.ts b/drizzle-kit/src/migrationPreparator.ts index 4e67e8174b..ada4489cde 100644 --- a/drizzle-kit/src/migrationPreparator.ts +++ b/drizzle-kit/src/migrationPreparator.ts @@ -168,6 +168,15 @@ export const prepareSqliteMigrationSnapshot = async ( return { prev: prevSnapshot, cur: result, custom }; }; +// TODO: SPANNER - implement +export const prepareGoogleSqlMigrationSnapshot = async ( + migrationFolders: string[], + schemaPath: string | string[], + casing: CasingType | undefined, +): Promise<{ prev: MySqlSchema; cur: MySqlSchema; custom: MySqlSchema }> => { + throw new Error('Not implemented'); +}; + export const fillPgSnapshot = ({ serialized, id, diff --git a/drizzle-kit/src/schemaValidator.ts b/drizzle-kit/src/schemaValidator.ts index ce4b2e59c4..0c6aa30de9 100644 --- a/drizzle-kit/src/schemaValidator.ts +++ b/drizzle-kit/src/schemaValidator.ts @@ -4,7 +4,7 @@ import { pgSchema, pgSchemaSquashed } from './serializer/pgSchema'; import { singlestoreSchema, singlestoreSchemaSquashed } from './serializer/singlestoreSchema'; import { sqliteSchema, SQLiteSchemaSquashed } from './serializer/sqliteSchema'; -export const dialects = ['postgresql', 'mysql', 'sqlite', 'turso', 'singlestore', 'gel'] as const; +export const dialects = ['postgresql', 'mysql', 'sqlite', 'turso', 'singlestore', 'gel', 'googlesql'] as const; export const dialect = enumType(dialects); export type Dialect = (typeof dialects)[number]; @@ -17,6 +17,7 @@ const commonSquashedSchema = union([ singlestoreSchemaSquashed, ]); +// TODO: SPANNER SCHEMA? const commonSchema = union([pgSchema, mysqlSchema, sqliteSchema, singlestoreSchema]); export type CommonSquashedSchema = TypeOf; diff --git a/drizzle-kit/src/sqlgenerator.ts b/drizzle-kit/src/sqlgenerator.ts index 4843c6c0c1..491c1ba517 100644 --- a/drizzle-kit/src/sqlgenerator.ts +++ b/drizzle-kit/src/sqlgenerator.ts @@ -3874,6 +3874,8 @@ class SingleStoreRecreateTableConvertor extends Convertor { } } +// TODO: SPANNER - add googlesql/spanner classes + const convertors: Convertor[] = []; convertors.push(new PgCreateTableConvertor()); convertors.push(new MySqlCreateTableConvertor()); diff --git a/drizzle-kit/src/utils.ts b/drizzle-kit/src/utils.ts index 1ee5f9d9a4..a1230e2198 100644 --- a/drizzle-kit/src/utils.ts +++ b/drizzle-kit/src/utils.ts @@ -128,6 +128,8 @@ const validatorForDialect = (dialect: Dialect) => { return { validator: backwardCompatibleSingleStoreSchema, version: 1 }; case 'gel': return { validator: backwardCompatibleGelSchema, version: 1 }; + case 'googlesql': + throw new Error('Not implemented'); // TODO: SPANNER } }; diff --git a/drizzle-orm/src/column-builder.ts b/drizzle-orm/src/column-builder.ts index 1cc4c5ae1e..8a17facc63 100644 --- a/drizzle-orm/src/column-builder.ts +++ b/drizzle-orm/src/column-builder.ts @@ -1,6 +1,7 @@ import { entityKind } from '~/entity.ts'; import type { Column } from './column.ts'; import type { GelColumn, GelExtraConfigColumn } from './gel-core/index.ts'; +import type { GoogleSqlColumn } from './googlesql/index.ts'; import type { MySqlColumn } from './mysql-core/index.ts'; import type { ExtraConfigColumn, PgColumn, PgSequenceOptions } from './pg-core/index.ts'; import type { SingleStoreColumn } from './singlestore-core/index.ts'; @@ -25,7 +26,7 @@ export type ColumnDataType = | 'localDate' | 'localDateTime'; -export type Dialect = 'pg' | 'mysql' | 'sqlite' | 'singlestore' | 'common' | 'gel'; +export type Dialect = 'pg' | 'mysql' | 'sqlite' | 'singlestore' | 'common' | 'gel' | 'googlesql'; export type GeneratedStorageMode = 'virtual' | 'stored'; @@ -325,6 +326,20 @@ export type BuildColumn< {}, Simplify | 'brand' | 'dialect'>> > + : TDialect extends 'googlesql' ? GoogleSqlColumn< + MakeColumnConfig, + {}, + Simplify< + Omit< + TBuilder['_'], + | keyof MakeColumnConfig + | 'brand' + | 'dialect' + | 'primaryKeyHasDefault' + | 'googlesqlColumnBuilderBrand' + > + > + > : TDialect extends 'mysql' ? MySqlColumn< MakeColumnConfig, {}, @@ -410,6 +425,7 @@ export type BuildExtraConfigColumns< export type ChangeColumnTableName = TDialect extends 'pg' ? PgColumn> : TDialect extends 'mysql' ? MySqlColumn> + : TDialect extends 'googlesql' ? GoogleSqlColumn> : TDialect extends 'singlestore' ? SingleStoreColumn> : TDialect extends 'sqlite' ? SQLiteColumn> : TDialect extends 'gel' ? GelColumn> From 0bee8b9f26de4c1de051a65ff8d2282c6eaeb388 Mon Sep 17 00:00:00 2001 From: Gabriel Cipriano Date: Wed, 26 Feb 2025 16:42:53 +0100 Subject: [PATCH 5/7] chore: lint fix --- drizzle-orm/src/googlesql/columns/binary.ts | 15 +++++--- drizzle-orm/src/googlesql/columns/common.ts | 7 ++-- drizzle-orm/src/googlesql/columns/custom.ts | 4 ++- drizzle-orm/src/googlesql/columns/date.ts | 13 +++++-- drizzle-orm/src/googlesql/columns/datetime.ts | 10 ++++-- drizzle-orm/src/googlesql/columns/double.ts | 5 ++- drizzle-orm/src/googlesql/columns/float.ts | 5 ++- drizzle-orm/src/googlesql/columns/int.ts | 5 ++- drizzle-orm/src/googlesql/columns/json.ts | 9 +++-- drizzle-orm/src/googlesql/columns/real.ts | 15 +++++--- drizzle-orm/src/googlesql/columns/serial.ts | 5 ++- drizzle-orm/src/googlesql/columns/text.ts | 32 ++++++++++------- drizzle-orm/src/googlesql/columns/time.ts | 15 +++++--- drizzle-orm/src/googlesql/columns/varchar.ts | 6 ++-- drizzle-orm/src/googlesql/columns/year.ts | 9 +++-- drizzle-orm/src/googlesql/db.ts | 10 ++++-- .../src/googlesql/query-builders/insert.ts | 14 ++++++-- .../src/googlesql/query-builders/query.ts | 2 +- .../src/googlesql/query-builders/select.ts | 4 +-- .../googlesql/query-builders/select.types.ts | 34 ++++++++++++++++--- .../src/googlesql/query-builders/update.ts | 8 ++++- 21 files changed, 164 insertions(+), 63 deletions(-) diff --git a/drizzle-orm/src/googlesql/columns/binary.ts b/drizzle-orm/src/googlesql/columns/binary.ts index b3b3cd9979..b0f7001ea7 100644 --- a/drizzle-orm/src/googlesql/columns/binary.ts +++ b/drizzle-orm/src/googlesql/columns/binary.ts @@ -14,10 +14,12 @@ export type GoogleSqlBinaryBuilderInitial = GoogleSqlBinar enumValues: undefined; }>; -export class GoogleSqlBinaryBuilder> extends GoogleSqlColumnBuilder< - T, - GoogleSqlBinaryConfig -> { +export class GoogleSqlBinaryBuilder> + extends GoogleSqlColumnBuilder< + T, + GoogleSqlBinaryConfig + > +{ static override readonly [entityKind]: string = 'GoogleSqlBinaryBuilder'; constructor(name: T['name'], length: number | undefined) { @@ -29,7 +31,10 @@ export class GoogleSqlBinaryBuilder( table: AnyGoogleSqlTable<{ name: TTableName }>, ): GoogleSqlBinary> { - return new GoogleSqlBinary>(table, this.config as ColumnBuilderRuntimeConfig); + return new GoogleSqlBinary>( + table, + this.config as ColumnBuilderRuntimeConfig, + ); } } diff --git a/drizzle-orm/src/googlesql/columns/common.ts b/drizzle-orm/src/googlesql/columns/common.ts index 041660700d..eedcba8979 100644 --- a/drizzle-orm/src/googlesql/columns/common.ts +++ b/drizzle-orm/src/googlesql/columns/common.ts @@ -117,9 +117,10 @@ export abstract class GoogleSqlColumn< } } -export type AnyGoogleSqlColumn> = {}> = GoogleSqlColumn< - Required, TPartial>> ->; +export type AnyGoogleSqlColumn> = {}> = + GoogleSqlColumn< + Required, TPartial>> + >; export interface GoogleSqlColumnWithAutoIncrementConfig { autoIncrement: boolean; diff --git a/drizzle-orm/src/googlesql/columns/custom.ts b/drizzle-orm/src/googlesql/columns/custom.ts index 627bbcfd60..8252bc7d73 100644 --- a/drizzle-orm/src/googlesql/columns/custom.ts +++ b/drizzle-orm/src/googlesql/columns/custom.ts @@ -57,7 +57,9 @@ export class GoogleSqlCustomColumnBuilder> extends GoogleSqlColumn { +export class GoogleSqlCustomColumn> + extends GoogleSqlColumn +{ static override readonly [entityKind]: string = 'GoogleSqlCustomColumn'; private sqlName: string; diff --git a/drizzle-orm/src/googlesql/columns/date.ts b/drizzle-orm/src/googlesql/columns/date.ts index 3e99eae8f7..1bffecaeb0 100644 --- a/drizzle-orm/src/googlesql/columns/date.ts +++ b/drizzle-orm/src/googlesql/columns/date.ts @@ -14,7 +14,9 @@ export type GoogleSqlDateBuilderInitial = GoogleSqlDateBui enumValues: undefined; }>; -export class GoogleSqlDateBuilder> extends GoogleSqlColumnBuilder { +export class GoogleSqlDateBuilder> + extends GoogleSqlColumnBuilder +{ static override readonly [entityKind]: string = 'GoogleSqlDateBuilder'; constructor(name: T['name']) { @@ -25,7 +27,10 @@ export class GoogleSqlDateBuilder( table: AnyGoogleSqlTable<{ name: TTableName }>, ): GoogleSqlDate> { - return new GoogleSqlDate>(table, this.config as ColumnBuilderRuntimeConfig); + return new GoogleSqlDate>( + table, + this.config as ColumnBuilderRuntimeConfig, + ); } } @@ -77,7 +82,9 @@ export class GoogleSqlDateStringBuilder> extends GoogleSqlColumn { +export class GoogleSqlDateString> + extends GoogleSqlColumn +{ static override readonly [entityKind]: string = 'GoogleSqlDateString'; constructor( diff --git a/drizzle-orm/src/googlesql/columns/datetime.ts b/drizzle-orm/src/googlesql/columns/datetime.ts index f5ec1aa34f..81281beeee 100644 --- a/drizzle-orm/src/googlesql/columns/datetime.ts +++ b/drizzle-orm/src/googlesql/columns/datetime.ts @@ -92,7 +92,9 @@ export class GoogleSqlDateTimeStringBuilder> extends GoogleSqlColumn { +export class GoogleSqlDateTimeString> + extends GoogleSqlColumn +{ static override readonly [entityKind]: string = 'GoogleSqlDateTimeString'; readonly fsp: number | undefined; @@ -121,11 +123,13 @@ export interface GoogleSqlDatetimeConfig; export function datetime( config?: GoogleSqlDatetimeConfig, -): Equal extends true ? GoogleSqlDateTimeStringBuilderInitial<''> : GoogleSqlDateTimeBuilderInitial<''>; +): Equal extends true ? GoogleSqlDateTimeStringBuilderInitial<''> + : GoogleSqlDateTimeBuilderInitial<''>; export function datetime( name: TName, config?: GoogleSqlDatetimeConfig, -): Equal extends true ? GoogleSqlDateTimeStringBuilderInitial : GoogleSqlDateTimeBuilderInitial; +): Equal extends true ? GoogleSqlDateTimeStringBuilderInitial + : GoogleSqlDateTimeBuilderInitial; export function datetime(a?: string | GoogleSqlDatetimeConfig, b?: GoogleSqlDatetimeConfig) { const { name, config } = getColumnNameAndConfig(a, b); if (config?.mode === 'string') { diff --git a/drizzle-orm/src/googlesql/columns/double.ts b/drizzle-orm/src/googlesql/columns/double.ts index 7e0ce9a6c1..01d4f372df 100644 --- a/drizzle-orm/src/googlesql/columns/double.ts +++ b/drizzle-orm/src/googlesql/columns/double.ts @@ -30,7 +30,10 @@ export class GoogleSqlDoubleBuilder( table: AnyGoogleSqlTable<{ name: TTableName }>, ): GoogleSqlDouble> { - return new GoogleSqlDouble>(table, this.config as ColumnBuilderRuntimeConfig); + return new GoogleSqlDouble>( + table, + this.config as ColumnBuilderRuntimeConfig, + ); } } diff --git a/drizzle-orm/src/googlesql/columns/float.ts b/drizzle-orm/src/googlesql/columns/float.ts index 8ef3053221..a37e10cd0c 100644 --- a/drizzle-orm/src/googlesql/columns/float.ts +++ b/drizzle-orm/src/googlesql/columns/float.ts @@ -30,7 +30,10 @@ export class GoogleSqlFloatBuilder( table: AnyGoogleSqlTable<{ name: TTableName }>, ): GoogleSqlFloat> { - return new GoogleSqlFloat>(table, this.config as ColumnBuilderRuntimeConfig); + return new GoogleSqlFloat>( + table, + this.config as ColumnBuilderRuntimeConfig, + ); } } diff --git a/drizzle-orm/src/googlesql/columns/int.ts b/drizzle-orm/src/googlesql/columns/int.ts index 033a3805d5..fe143c8d34 100644 --- a/drizzle-orm/src/googlesql/columns/int.ts +++ b/drizzle-orm/src/googlesql/columns/int.ts @@ -28,7 +28,10 @@ export class GoogleSqlIntBuilder( table: AnyGoogleSqlTable<{ name: TTableName }>, ): GoogleSqlInt> { - return new GoogleSqlInt>(table, this.config as ColumnBuilderRuntimeConfig); + return new GoogleSqlInt>( + table, + this.config as ColumnBuilderRuntimeConfig, + ); } } diff --git a/drizzle-orm/src/googlesql/columns/json.ts b/drizzle-orm/src/googlesql/columns/json.ts index dc93048316..33af18af1f 100644 --- a/drizzle-orm/src/googlesql/columns/json.ts +++ b/drizzle-orm/src/googlesql/columns/json.ts @@ -13,7 +13,9 @@ export type GoogleSqlJsonBuilderInitial = GoogleSqlJsonBui enumValues: undefined; }>; -export class GoogleSqlJsonBuilder> extends GoogleSqlColumnBuilder { +export class GoogleSqlJsonBuilder> + extends GoogleSqlColumnBuilder +{ static override readonly [entityKind]: string = 'GoogleSqlJsonBuilder'; constructor(name: T['name']) { @@ -24,7 +26,10 @@ export class GoogleSqlJsonBuilder( table: AnyGoogleSqlTable<{ name: TTableName }>, ): GoogleSqlJson> { - return new GoogleSqlJson>(table, this.config as ColumnBuilderRuntimeConfig); + return new GoogleSqlJson>( + table, + this.config as ColumnBuilderRuntimeConfig, + ); } } diff --git a/drizzle-orm/src/googlesql/columns/real.ts b/drizzle-orm/src/googlesql/columns/real.ts index 39e733a35d..87443b07a3 100644 --- a/drizzle-orm/src/googlesql/columns/real.ts +++ b/drizzle-orm/src/googlesql/columns/real.ts @@ -32,14 +32,19 @@ export class GoogleSqlRealBuilder( table: AnyGoogleSqlTable<{ name: TTableName }>, ): GoogleSqlReal> { - return new GoogleSqlReal>(table, this.config as ColumnBuilderRuntimeConfig); + return new GoogleSqlReal>( + table, + this.config as ColumnBuilderRuntimeConfig, + ); } } -export class GoogleSqlReal> extends GoogleSqlColumnWithAutoIncrement< - T, - GoogleSqlRealConfig -> { +export class GoogleSqlReal> + extends GoogleSqlColumnWithAutoIncrement< + T, + GoogleSqlRealConfig + > +{ static override readonly [entityKind]: string = 'GoogleSqlReal'; precision: number | undefined = this.config.precision; diff --git a/drizzle-orm/src/googlesql/columns/serial.ts b/drizzle-orm/src/googlesql/columns/serial.ts index 4780196114..7371b68c56 100644 --- a/drizzle-orm/src/googlesql/columns/serial.ts +++ b/drizzle-orm/src/googlesql/columns/serial.ts @@ -44,7 +44,10 @@ export class GoogleSqlSerialBuilder( table: AnyGoogleSqlTable<{ name: TTableName }>, ): GoogleSqlSerial> { - return new GoogleSqlSerial>(table, this.config as ColumnBuilderRuntimeConfig); + return new GoogleSqlSerial>( + table, + this.config as ColumnBuilderRuntimeConfig, + ); } } diff --git a/drizzle-orm/src/googlesql/columns/text.ts b/drizzle-orm/src/googlesql/columns/text.ts index 693e72b415..bb4d83a704 100644 --- a/drizzle-orm/src/googlesql/columns/text.ts +++ b/drizzle-orm/src/googlesql/columns/text.ts @@ -7,19 +7,22 @@ import { GoogleSqlColumn, GoogleSqlColumnBuilder } from './common.ts'; export type GoogleSqlTextColumnType = 'tinytext' | 'text' | 'mediumtext' | 'longtext'; -export type GoogleSqlTextBuilderInitial = GoogleSqlTextBuilder<{ - name: TName; - dataType: 'string'; - columnType: 'GoogleSqlText'; - data: TEnum[number]; - driverParam: string; - enumValues: TEnum; -}>; +export type GoogleSqlTextBuilderInitial = + GoogleSqlTextBuilder<{ + name: TName; + dataType: 'string'; + columnType: 'GoogleSqlText'; + data: TEnum[number]; + driverParam: string; + enumValues: TEnum; + }>; -export class GoogleSqlTextBuilder> extends GoogleSqlColumnBuilder< - T, - { textType: GoogleSqlTextColumnType; enumValues: T['enumValues'] } -> { +export class GoogleSqlTextBuilder> + extends GoogleSqlColumnBuilder< + T, + { textType: GoogleSqlTextColumnType; enumValues: T['enumValues'] } + > +{ static override readonly [entityKind]: string = 'GoogleSqlTextBuilder'; constructor(name: T['name'], textType: GoogleSqlTextColumnType, config: GoogleSqlTextConfig) { @@ -32,7 +35,10 @@ export class GoogleSqlTextBuilder( table: AnyGoogleSqlTable<{ name: TTableName }>, ): GoogleSqlText> { - return new GoogleSqlText>(table, this.config as ColumnBuilderRuntimeConfig); + return new GoogleSqlText>( + table, + this.config as ColumnBuilderRuntimeConfig, + ); } } diff --git a/drizzle-orm/src/googlesql/columns/time.ts b/drizzle-orm/src/googlesql/columns/time.ts index 0536a56458..89f22e51d4 100644 --- a/drizzle-orm/src/googlesql/columns/time.ts +++ b/drizzle-orm/src/googlesql/columns/time.ts @@ -14,10 +14,12 @@ export type GoogleSqlTimeBuilderInitial = GoogleSqlTimeBui enumValues: undefined; }>; -export class GoogleSqlTimeBuilder> extends GoogleSqlColumnBuilder< - T, - TimeConfig -> { +export class GoogleSqlTimeBuilder> + extends GoogleSqlColumnBuilder< + T, + TimeConfig + > +{ static override readonly [entityKind]: string = 'GoogleSqlTimeBuilder'; constructor( @@ -32,7 +34,10 @@ export class GoogleSqlTimeBuilder( table: AnyGoogleSqlTable<{ name: TTableName }>, ): GoogleSqlTime> { - return new GoogleSqlTime>(table, this.config as ColumnBuilderRuntimeConfig); + return new GoogleSqlTime>( + table, + this.config as ColumnBuilderRuntimeConfig, + ); } } diff --git a/drizzle-orm/src/googlesql/columns/varchar.ts b/drizzle-orm/src/googlesql/columns/varchar.ts index 8f242e1b46..9fd9b0a313 100644 --- a/drizzle-orm/src/googlesql/columns/varchar.ts +++ b/drizzle-orm/src/googlesql/columns/varchar.ts @@ -44,9 +44,9 @@ export class GoogleSqlVarCharBuilder< } } -export class GoogleSqlVarChar & { length?: number | undefined }> - extends GoogleSqlColumn, { length: T['length'] }> -{ +export class GoogleSqlVarChar< + T extends ColumnBaseConfig<'string', 'GoogleSqlVarChar'> & { length?: number | undefined }, +> extends GoogleSqlColumn, { length: T['length'] }> { static override readonly [entityKind]: string = 'GoogleSqlVarChar'; readonly length: number | undefined = this.config.length; diff --git a/drizzle-orm/src/googlesql/columns/year.ts b/drizzle-orm/src/googlesql/columns/year.ts index 7f83fc69af..83d7947ba5 100644 --- a/drizzle-orm/src/googlesql/columns/year.ts +++ b/drizzle-orm/src/googlesql/columns/year.ts @@ -13,7 +13,9 @@ export type GoogleSqlYearBuilderInitial = GoogleSqlYearBui enumValues: undefined; }>; -export class GoogleSqlYearBuilder> extends GoogleSqlColumnBuilder { +export class GoogleSqlYearBuilder> + extends GoogleSqlColumnBuilder +{ static override readonly [entityKind]: string = 'GoogleSqlYearBuilder'; constructor(name: T['name']) { @@ -24,7 +26,10 @@ export class GoogleSqlYearBuilder( table: AnyGoogleSqlTable<{ name: TTableName }>, ): GoogleSqlYear> { - return new GoogleSqlYear>(table, this.config as ColumnBuilderRuntimeConfig); + return new GoogleSqlYear>( + table, + this.config as ColumnBuilderRuntimeConfig, + ); } } diff --git a/drizzle-orm/src/googlesql/db.ts b/drizzle-orm/src/googlesql/db.ts index a35718be5a..65a26a2cdc 100644 --- a/drizzle-orm/src/googlesql/db.ts +++ b/drizzle-orm/src/googlesql/db.ts @@ -18,12 +18,12 @@ import { import { RelationalQueryBuilder } from './query-builders/query.ts'; import type { SelectedFields } from './query-builders/select.types.ts'; import type { - Mode, GoogleSqlQueryResultHKT, GoogleSqlQueryResultKind, GoogleSqlSession, GoogleSqlTransaction, GoogleSqlTransactionConfig, + Mode, PreparedQueryHKTBase, } from './session.ts'; import type { WithBuilder } from './subquery.ts'; @@ -417,7 +417,9 @@ export class GoogleSqlDatabase< * await db.update(cars).set({ color: 'red' }).where(eq(cars.brand, 'BMW')); * ``` */ - update(table: TTable): GoogleSqlUpdateBuilder { + update( + table: TTable, + ): GoogleSqlUpdateBuilder { return new GoogleSqlUpdateBuilder(table, this.session, this.dialect); } @@ -440,7 +442,9 @@ export class GoogleSqlDatabase< * await db.insert(cars).values([{ brand: 'BMW' }, { brand: 'Porsche' }]); * ``` */ - insert(table: TTable): GoogleSqlInsertBuilder { + insert( + table: TTable, + ): GoogleSqlInsertBuilder { return new GoogleSqlInsertBuilder(table, this.session, this.dialect); } diff --git a/drizzle-orm/src/googlesql/query-builders/insert.ts b/drizzle-orm/src/googlesql/query-builders/insert.ts index 85f9d3e576..8bd043e717 100644 --- a/drizzle-orm/src/googlesql/query-builders/insert.ts +++ b/drizzle-orm/src/googlesql/query-builders/insert.ts @@ -91,7 +91,9 @@ export class GoogleSqlInsertBuilder< ): GoogleSqlInsertBase; select(selectQuery: (qb: QueryBuilder) => SQL): GoogleSqlInsertBase; select(selectQuery: SQL): GoogleSqlInsertBase; - select(selectQuery: GoogleSqlInsertSelectQueryBuilder): GoogleSqlInsertBase; + select( + selectQuery: GoogleSqlInsertSelectQueryBuilder, + ): GoogleSqlInsertBase; select( selectQuery: | SQL @@ -180,7 +182,10 @@ export interface GoogleSqlInsertBase< TExcludedMethods extends string = never, > extends QueryPromise : TReturning[]>, - RunnableQuery : TReturning[], 'googlesql'>, + RunnableQuery< + TReturning extends undefined ? GoogleSqlQueryResultKind : TReturning[], + 'googlesql' + >, SQLWrapper { readonly _: { @@ -220,7 +225,10 @@ export class GoogleSqlInsertBase< TExcludedMethods extends string = never, > extends QueryPromise : TReturning[]> implements - RunnableQuery : TReturning[], 'googlesql'>, + RunnableQuery< + TReturning extends undefined ? GoogleSqlQueryResultKind : TReturning[], + 'googlesql' + >, SQLWrapper { static override readonly [entityKind]: string = 'GoogleSqlInsert'; diff --git a/drizzle-orm/src/googlesql/query-builders/query.ts b/drizzle-orm/src/googlesql/query-builders/query.ts index 64696097ae..70363dd626 100644 --- a/drizzle-orm/src/googlesql/query-builders/query.ts +++ b/drizzle-orm/src/googlesql/query-builders/query.ts @@ -12,9 +12,9 @@ import type { Query, QueryWithTypings, SQL } from '~/sql/sql.ts'; import type { KnownKeysOnly } from '~/utils.ts'; import type { GoogleSqlDialect } from '../dialect.ts'; import type { - Mode, GoogleSqlPreparedQueryConfig, GoogleSqlSession, + Mode, PreparedQueryHKTBase, PreparedQueryKind, } from '../session.ts'; diff --git a/drizzle-orm/src/googlesql/query-builders/select.ts b/drizzle-orm/src/googlesql/query-builders/select.ts index 0f6bd96889..b6ef7a1934 100644 --- a/drizzle-orm/src/googlesql/query-builders/select.ts +++ b/drizzle-orm/src/googlesql/query-builders/select.ts @@ -31,8 +31,6 @@ import type { AnyGoogleSqlSelect, CreateGoogleSqlSelectFromBuilderMode, GetGoogleSqlSetOperators, - LockConfig, - LockStrength, GoogleSqlCreateSetOperatorFn, GoogleSqlJoinFn, GoogleSqlSelectConfig, @@ -43,6 +41,8 @@ import type { GoogleSqlSelectWithout, GoogleSqlSetOperatorExcludedMethods, GoogleSqlSetOperatorWithResult, + LockConfig, + LockStrength, SelectedFields, SetOperatorRightSelect, } from './select.types.ts'; diff --git a/drizzle-orm/src/googlesql/query-builders/select.types.ts b/drizzle-orm/src/googlesql/query-builders/select.types.ts index 9300f5bb6a..b25c7213c1 100644 --- a/drizzle-orm/src/googlesql/query-builders/select.types.ts +++ b/drizzle-orm/src/googlesql/query-builders/select.types.ts @@ -25,7 +25,7 @@ import type { Assume, ValidateShape } from '~/utils.ts'; import type { GoogleSqlPreparedQueryConfig, PreparedQueryHKTBase, PreparedQueryKind } from '../session.ts'; import type { GoogleSqlViewBase } from '../view-base.ts'; import type { GoogleSqlViewWithSelection } from '../view.ts'; -import type { IndexConfig, GoogleSqlSelectBase, GoogleSqlSelectQueryBuilderBase } from './select.ts'; +import type { GoogleSqlSelectBase, GoogleSqlSelectQueryBuilderBase, IndexConfig } from './select.ts'; export interface GoogleSqlSelectJoinConfig { on: SQL | undefined; @@ -271,7 +271,13 @@ export type CreateGoogleSqlSelectFromBuilderMode< TSelectMode extends SelectMode, TPreparedQueryHKT extends PreparedQueryHKTBase, > = TBuilderMode extends 'db' ? GoogleSqlSelectBase - : GoogleSqlSelectQueryBuilderBase; + : GoogleSqlSelectQueryBuilderBase< + GoogleSqlSelectQueryBuilderHKT, + TTableName, + TSelection, + TSelectMode, + TPreparedQueryHKT + >; export type GoogleSqlSelectQueryBuilder< THKT extends GoogleSqlSelectHKTBase = GoogleSqlSelectQueryBuilderHKT, @@ -295,9 +301,29 @@ export type GoogleSqlSelectQueryBuilder< TSelectedFields >; -export type AnyGoogleSqlSelectQueryBuilder = GoogleSqlSelectQueryBuilderBase; +export type AnyGoogleSqlSelectQueryBuilder = GoogleSqlSelectQueryBuilderBase< + any, + any, + any, + any, + any, + any, + any, + any, + any +>; -export type AnyGoogleSqlSetOperatorInterface = GoogleSqlSetOperatorInterface; +export type AnyGoogleSqlSetOperatorInterface = GoogleSqlSetOperatorInterface< + any, + any, + any, + any, + any, + any, + any, + any, + any +>; export interface GoogleSqlSetOperatorInterface< TTableName extends string | undefined, diff --git a/drizzle-orm/src/googlesql/query-builders/update.ts b/drizzle-orm/src/googlesql/query-builders/update.ts index b91870dc6a..7dce6470c6 100644 --- a/drizzle-orm/src/googlesql/query-builders/update.ts +++ b/drizzle-orm/src/googlesql/query-builders/update.ts @@ -58,7 +58,13 @@ export class GoogleSqlUpdateBuilder< ) {} set(values: GoogleSqlUpdateSetSource): GoogleSqlUpdateBase { - return new GoogleSqlUpdateBase(this.table, mapUpdateSet(this.table, values), this.session, this.dialect, this.withList); + return new GoogleSqlUpdateBase( + this.table, + mapUpdateSet(this.table, values), + this.session, + this.dialect, + this.withList, + ); } } From bd927cd05d559e11d0f62ef668222755676263aa Mon Sep 17 00:00:00 2001 From: Gabriel Cipriano Date: Fri, 28 Feb 2025 16:07:31 +0100 Subject: [PATCH 6/7] tests: add some drizzle-orm tests --- drizzle-kit/tests/cli-generate.test.ts | 2 + drizzle-kit/tests/cli-migrate.test.ts | 2 + .../tests/casing/googlesql-to-camel.test.ts | 245 +++++++++++++++++ .../tests/casing/googlesql-to-snake.test.ts | 247 ++++++++++++++++++ 4 files changed, 496 insertions(+) create mode 100644 drizzle-orm/tests/casing/googlesql-to-camel.test.ts create mode 100644 drizzle-orm/tests/casing/googlesql-to-snake.test.ts diff --git a/drizzle-kit/tests/cli-generate.test.ts b/drizzle-kit/tests/cli-generate.test.ts index a4adf979f2..917eadf5b3 100644 --- a/drizzle-kit/tests/cli-generate.test.ts +++ b/drizzle-kit/tests/cli-generate.test.ts @@ -2,6 +2,8 @@ import { test as brotest } from '@drizzle-team/brocli'; import { assert, expect, test } from 'vitest'; import { generate } from '../src/cli/schema'; +// TODO: SPANNER - add tests + // good: // #1 drizzle-kit generate --dialect=postgresql --schema=schema.ts // #2 drizzle-kit generate --dialect=postgresql --schema=schema.ts --out=out diff --git a/drizzle-kit/tests/cli-migrate.test.ts b/drizzle-kit/tests/cli-migrate.test.ts index 1425691f0b..644d63712e 100644 --- a/drizzle-kit/tests/cli-migrate.test.ts +++ b/drizzle-kit/tests/cli-migrate.test.ts @@ -2,6 +2,8 @@ import { test as brotest } from '@drizzle-team/brocli'; import { assert, expect, test } from 'vitest'; import { migrate } from '../src/cli/schema'; +// TODO: SPANNER - add tests + // good: // #1 drizzle-kit generate // #2 drizzle-kit generate --config=turso.config.ts diff --git a/drizzle-orm/tests/casing/googlesql-to-camel.test.ts b/drizzle-orm/tests/casing/googlesql-to-camel.test.ts new file mode 100644 index 0000000000..a417c40967 --- /dev/null +++ b/drizzle-orm/tests/casing/googlesql-to-camel.test.ts @@ -0,0 +1,245 @@ +import { beforeEach, describe, it } from 'vitest'; +import { alias, boolean, int, googlesqlSchema, googlesqlTable, serial, text, union } from '~/googlesql'; +import { drizzle as spanner } from '~/spanner'; +import { relations } from '~/relations'; +import { asc, eq, sql } from '~/sql'; +import { createPool } from 'mysql2'; + +const testSchema = googlesqlSchema('test'); +const users = googlesqlTable('users', { + id: serial().primaryKey(), + first_name: text().notNull(), + last_name: text().notNull(), + // Test that custom aliases remain + age: int('AGE'), +}); +const usersRelations = relations(users, ({ one }) => ({ + developers: one(developers), +})); +const developers = testSchema.table('developers', { + user_id: serial().primaryKey().references(() => users.id), + uses_drizzle_orm: boolean().notNull(), +}); +const developersRelations = relations(developers, ({ one }) => ({ + user: one(users, { + fields: [developers.user_id], + references: [users.id], + }), +})); +const devs = alias(developers, 'devs'); +const schema = { users, usersRelations, developers, developersRelations }; + + +const instance = createPool({ + uri: "mysql://root:password@localhost:3306/test", +}); + +const db = spanner({ client: instance, schema: schema, casing: 'camelCase', mode: "default" }); + +const usersCache = { + 'public.users.id': 'id', + 'public.users.first_name': 'firstName', + 'public.users.last_name': 'lastName', + 'public.users.AGE': 'age', +}; +const developersCache = { + 'test.developers.user_id': 'userId', + 'test.developers.uses_drizzle_orm': 'usesDrizzleOrm', +}; +const cache = { + ...usersCache, + ...developersCache, +}; + +const fullName = sql`${users.first_name} || ' ' || ${users.last_name}`.as('name'); + +describe('mysql to snake case', () => { + beforeEach(() => { + db.dialect.casing.clearCache(); + }); + + it('select', ({ expect }) => { + const query = db + .select({ name: fullName, age: users.age }) + .from(users) + .leftJoin(developers, eq(users.id, developers.user_id)) + .orderBy(asc(users.first_name)); + + expect(query.toSQL()).toEqual({ + sql: + "select `users`.`firstName` || ' ' || `users`.`lastName` as `name`, `users`.`AGE` from `users` left join `test`.`developers` on `users`.`id` = `test`.`developers`.`userId` order by `users`.`firstName` asc", + params: [], + }); + expect(db.dialect.casing.cache).toEqual(cache); + }); + + it('select (with alias)', ({ expect }) => { + const query = db + .select({ firstName: users.first_name }) + .from(users) + .leftJoin(devs, eq(users.id, devs.user_id)); + + expect(query.toSQL()).toEqual({ + sql: + 'select `users`.`firstName` from `users` left join `test`.`developers` `devs` on `users`.`id` = `devs`.`userId`', + params: [], + }); + expect(db.dialect.casing.cache).toEqual(cache); + }); + + it('with CTE', ({ expect }) => { + const cte = db.$with('cte').as(db.select({ name: fullName }).from(users)); + const query = db.with(cte).select().from(cte); + + expect(query.toSQL()).toEqual({ + sql: "with `cte` as (select `firstName` || ' ' || `lastName` as `name` from `users`) select `name` from `cte`", + params: [], + }); + expect(db.dialect.casing.cache).toEqual(usersCache); + }); + + it('with CTE (with query builder)', ({ expect }) => { + const cte = db.$with('cte').as((qb) => qb.select({ name: fullName }).from(users)); + const query = db.with(cte).select().from(cte); + + expect(query.toSQL()).toEqual({ + sql: "with `cte` as (select `firstName` || ' ' || `lastName` as `name` from `users`) select `name` from `cte`", + params: [], + }); + expect(db.dialect.casing.cache).toEqual(usersCache); + }); + + it('set operator', ({ expect }) => { + const query = db + .select({ firstName: users.first_name }) + .from(users) + .union(db.select({ firstName: users.first_name }).from(users)); + + expect(query.toSQL()).toEqual({ + sql: '(select `firstName` from `users`) union (select `firstName` from `users`)', + params: [], + }); + expect(db.dialect.casing.cache).toEqual(usersCache); + }); + + it('set operator (function)', ({ expect }) => { + const query = union( + db.select({ firstName: users.first_name }).from(users), + db.select({ firstName: users.first_name }).from(users), + ); + + expect(query.toSQL()).toEqual({ + sql: '(select `firstName` from `users`) union (select `firstName` from `users`)', + params: [], + }); + expect(db.dialect.casing.cache).toEqual(usersCache); + }); + + it('query (find first)', ({ expect }) => { + const query = db.query.users.findFirst({ + columns: { + id: true, + age: true, + }, + extras: { + fullName, + }, + where: eq(users.id, 1), + with: { + developers: { + columns: { + uses_drizzle_orm: true, + }, + }, + }, + }); + + expect(query.toSQL()).toEqual({ + sql: + "select `users`.`id`, `users`.`AGE`, `users`.`firstName` || ' ' || `users`.`lastName` as `name`, `users_developers`.`data` as `developers` from `users` left join lateral (select json_array(`users_developers`.`usesDrizzleOrm`) as `data` from (select * from `developers` `users_developers` where `users_developers`.`userId` = `users`.`id` limit ?) `users_developers`) `users_developers` on true where `users`.`id` = ? limit ?", + params: [1, 1, 1], + typings: ['none', 'none', 'none'], + }); + expect(db.dialect.casing.cache).toEqual(cache); + }); + + it('query (find many)', ({ expect }) => { + const query = db.query.users.findMany({ + columns: { + id: true, + age: true, + }, + extras: { + fullName, + }, + where: eq(users.id, 1), + with: { + developers: { + columns: { + uses_drizzle_orm: true, + }, + }, + }, + }); + + expect(query.toSQL()).toEqual({ + sql: + "select `users`.`id`, `users`.`AGE`, `users`.`firstName` || ' ' || `users`.`lastName` as `name`, `users_developers`.`data` as `developers` from `users` left join lateral (select json_array(`users_developers`.`usesDrizzleOrm`) as `data` from (select * from `developers` `users_developers` where `users_developers`.`userId` = `users`.`id` limit ?) `users_developers`) `users_developers` on true where `users`.`id` = ?", + params: [1, 1], + typings: ['none', 'none'], + }); + expect(db.dialect.casing.cache).toEqual(cache); + }); + + + it('insert', ({ expect }) => { + const query = db + .insert(users) + .values({ first_name: 'John', last_name: 'Doe', age: 30 }); + + expect(query.toSQL()).toEqual({ + sql: 'insert into `users` (`id`, `firstName`, `lastName`, `AGE`) values (default, ?, ?, ?)', + params: ['John', 'Doe', 30], + }); + expect(db.dialect.casing.cache).toEqual(usersCache); + }); + + it('insert (on duplicate key update)', ({ expect }) => { + const query = db + .insert(users) + .values({ first_name: 'John', last_name: 'Doe', age: 30 }) + .onDuplicateKeyUpdate({ set: { age: 31 } }); + + expect(query.toSQL()).toEqual({ + sql: + 'insert into `users` (`id`, `firstName`, `lastName`, `AGE`) values (default, ?, ?, ?) on duplicate key update `AGE` = ?', + params: ['John', 'Doe', 30, 31], + }); + expect(db.dialect.casing.cache).toEqual(usersCache); + }); + + it('update', ({ expect }) => { + const query = db + .update(users) + .set({ first_name: 'John', last_name: 'Doe', age: 30 }) + .where(eq(users.id, 1)); + + expect(query.toSQL()).toEqual({ + sql: 'update `users` set `firstName` = ?, `lastName` = ?, `AGE` = ? where `users`.`id` = ?', + params: ['John', 'Doe', 30, 1], + }); + expect(db.dialect.casing.cache).toEqual(usersCache); + }); + + it('delete', ({ expect }) => { + const query = db + .delete(users) + .where(eq(users.id, 1)); + + expect(query.toSQL()).toEqual({ + sql: 'delete from `users` where `users`.`id` = ?', + params: [1], + }); + expect(db.dialect.casing.cache).toEqual(usersCache); + }); +}); diff --git a/drizzle-orm/tests/casing/googlesql-to-snake.test.ts b/drizzle-orm/tests/casing/googlesql-to-snake.test.ts new file mode 100644 index 0000000000..826045f8c4 --- /dev/null +++ b/drizzle-orm/tests/casing/googlesql-to-snake.test.ts @@ -0,0 +1,247 @@ +import { createPool } from 'mysql2'; +import { beforeEach, describe, it } from 'vitest'; +import { alias, boolean, int, googlesqlSchema, googlesqlTable, serial, text, union } from '~/googlesql'; +import { drizzle as spanner } from '~/spanner'; +import { relations } from '~/relations'; +import { asc, eq, sql } from '~/sql'; + +const testSchema = googlesqlSchema('test'); +const users = googlesqlTable('users', { + id: serial().primaryKey(), + firstName: text().notNull(), + lastName: text().notNull(), + // Test that custom aliases remain + age: int('AGE'), +}); +const usersRelations = relations(users, ({ one }) => ({ + developers: one(developers), +})); +const developers = testSchema.table('developers', { + userId: serial().primaryKey().references(() => users.id), + usesDrizzleORM: boolean().notNull(), +}); +const developersRelations = relations(developers, ({ one }) => ({ + user: one(users, { + fields: [developers.userId], + references: [users.id], + }), +})); +const devs = alias(developers, 'devs'); +const schema = { users, usersRelations, developers, developersRelations }; + + + +const instance = createPool({ + uri: "googlesql://root:password@localhost:3306/test", +}); + +const db = spanner({ client: instance, schema: schema, casing: 'snake_case', mode: "default" }); + +const usersCache = { + 'public.users.id': 'id', + 'public.users.firstName': 'first_name', + 'public.users.lastName': 'last_name', + 'public.users.AGE': 'age', +}; +const developersCache = { + 'test.developers.userId': 'user_id', + 'test.developers.usesDrizzleORM': 'uses_drizzle_orm', +}; +const cache = { + ...usersCache, + ...developersCache, +}; + +const fullName = sql`${users.firstName} || ' ' || ${users.lastName}`.as('name'); + +describe('googlesql to snake case', () => { + beforeEach(() => { + db.dialect.casing.clearCache(); + }); + + it('select', ({ expect }) => { + const query = db + .select({ name: fullName, age: users.age }) + .from(users) + .leftJoin(developers, eq(users.id, developers.userId)) + .orderBy(asc(users.firstName)); + + expect(query.toSQL()).toEqual({ + sql: + "select `users`.`first_name` || ' ' || `users`.`last_name` as `name`, `users`.`AGE` from `users` left join `test`.`developers` on `users`.`id` = `test`.`developers`.`user_id` order by `users`.`first_name` asc", + params: [], + }); + expect(db.dialect.casing.cache).toEqual(cache); + }); + + it('select (with alias)', ({ expect }) => { + const query = db + .select({ firstName: users.firstName }) + .from(users) + .leftJoin(devs, eq(users.id, devs.userId)); + + expect(query.toSQL()).toEqual({ + sql: + 'select `users`.`first_name` from `users` left join `test`.`developers` `devs` on `users`.`id` = `devs`.`user_id`', + params: [], + }); + expect(db.dialect.casing.cache).toEqual(cache); + }); + + it('with CTE', ({ expect }) => { + const cte = db.$with('cte').as(db.select({ name: fullName }).from(users)); + const query = db.with(cte).select().from(cte); + + expect(query.toSQL()).toEqual({ + sql: "with `cte` as (select `first_name` || ' ' || `last_name` as `name` from `users`) select `name` from `cte`", + params: [], + }); + expect(db.dialect.casing.cache).toEqual(usersCache); + }); + + it('with CTE (with query builder)', ({ expect }) => { + const cte = db.$with('cte').as((qb) => qb.select({ name: fullName }).from(users)); + const query = db.with(cte).select().from(cte); + + expect(query.toSQL()).toEqual({ + sql: "with `cte` as (select `first_name` || ' ' || `last_name` as `name` from `users`) select `name` from `cte`", + params: [], + }); + expect(db.dialect.casing.cache).toEqual(usersCache); + }); + + it('set operator', ({ expect }) => { + const query = db + .select({ firstName: users.firstName }) + .from(users) + .union(db.select({ firstName: users.firstName }).from(users)); + + expect(query.toSQL()).toEqual({ + sql: '(select `first_name` from `users`) union (select `first_name` from `users`)', + params: [], + }); + expect(db.dialect.casing.cache).toEqual(usersCache); + }); + + it('set operator (function)', ({ expect }) => { + const query = union( + db.select({ firstName: users.firstName }).from(users), + db.select({ firstName: users.firstName }).from(users), + ); + + expect(query.toSQL()).toEqual({ + sql: '(select `first_name` from `users`) union (select `first_name` from `users`)', + params: [], + }); + expect(db.dialect.casing.cache).toEqual(usersCache); + }); + + it('query (find first)', ({ expect }) => { + const query = db.query.users.findFirst({ + columns: { + id: true, + age: true, + }, + extras: { + fullName, + }, + where: eq(users.id, 1), + with: { + developers: { + columns: { + usesDrizzleORM: true, + }, + }, + }, + }); + + expect(query.toSQL()).toEqual({ + sql: + "select `users`.`id`, `users`.`AGE`, `users`.`first_name` || ' ' || `users`.`last_name` as `name`, `users_developers`.`data` as `developers` from `users` left join lateral (select json_array(`users_developers`.`uses_drizzle_orm`) as `data` from (select * from `developers` `users_developers` where `users_developers`.`user_id` = `users`.`id` limit ?) `users_developers`) `users_developers` on true where `users`.`id` = ? limit ?", + params: [1, 1, 1], + typings: ['none', 'none', 'none'], + }); + expect(db.dialect.casing.cache).toEqual(cache); + }); + + + it('query (find many)', ({ expect }) => { + const query = db.query.users.findMany({ + columns: { + id: true, + age: true, + }, + extras: { + fullName, + }, + where: eq(users.id, 1), + with: { + developers: { + columns: { + usesDrizzleORM: true, + }, + }, + }, + }); + + expect(query.toSQL()).toEqual({ + sql: + "select `users`.`id`, `users`.`AGE`, `users`.`first_name` || ' ' || `users`.`last_name` as `name`, `users_developers`.`data` as `developers` from `users` left join lateral (select json_array(`users_developers`.`uses_drizzle_orm`) as `data` from (select * from `developers` `users_developers` where `users_developers`.`user_id` = `users`.`id` limit ?) `users_developers`) `users_developers` on true where `users`.`id` = ?", + params: [1, 1], + typings: ['none', 'none'], + }); + expect(db.dialect.casing.cache).toEqual(cache); + }); + + + it('insert', ({ expect }) => { + const query = db + .insert(users) + .values({ firstName: 'John', lastName: 'Doe', age: 30 }); + + expect(query.toSQL()).toEqual({ + sql: 'insert into `users` (`id`, `first_name`, `last_name`, `AGE`) values (default, ?, ?, ?)', + params: ['John', 'Doe', 30], + }); + expect(db.dialect.casing.cache).toEqual(usersCache); + }); + + it('insert (on duplicate key update)', ({ expect }) => { + const query = db + .insert(users) + .values({ firstName: 'John', lastName: 'Doe', age: 30 }) + .onDuplicateKeyUpdate({ set: { age: 31 } }); + + expect(query.toSQL()).toEqual({ + sql: + 'insert into `users` (`id`, `first_name`, `last_name`, `AGE`) values (default, ?, ?, ?) on duplicate key update `AGE` = ?', + params: ['John', 'Doe', 30, 31], + }); + expect(db.dialect.casing.cache).toEqual(usersCache); + }); + + it('update', ({ expect }) => { + const query = db + .update(users) + .set({ firstName: 'John', lastName: 'Doe', age: 30 }) + .where(eq(users.id, 1)); + + expect(query.toSQL()).toEqual({ + sql: 'update `users` set `first_name` = ?, `last_name` = ?, `AGE` = ? where `users`.`id` = ?', + params: ['John', 'Doe', 30, 1], + }); + expect(db.dialect.casing.cache).toEqual(usersCache); + }); + + it('delete', ({ expect }) => { + const query = db + .delete(users) + .where(eq(users.id, 1)); + + expect(query.toSQL()).toEqual({ + sql: 'delete from `users` where `users`.`id` = ?', + params: [1], + }); + expect(db.dialect.casing.cache).toEqual(usersCache); + }); +}); From 5a35e7e29ab07b6091d0c22f60d0681b21df464d Mon Sep 17 00:00:00 2001 From: Gabriel Cipriano Date: Fri, 28 Feb 2025 16:08:31 +0100 Subject: [PATCH 7/7] feat: spanner pseudo-driver --- drizzle-orm/src/spanner/driver.ts | 172 ++++++++++++++ drizzle-orm/src/spanner/index.ts | 2 + drizzle-orm/src/spanner/migrator.ts | 11 + drizzle-orm/src/spanner/session.ts | 337 ++++++++++++++++++++++++++++ 4 files changed, 522 insertions(+) create mode 100644 drizzle-orm/src/spanner/driver.ts create mode 100644 drizzle-orm/src/spanner/index.ts create mode 100644 drizzle-orm/src/spanner/migrator.ts create mode 100644 drizzle-orm/src/spanner/session.ts diff --git a/drizzle-orm/src/spanner/driver.ts b/drizzle-orm/src/spanner/driver.ts new file mode 100644 index 0000000000..6602d22046 --- /dev/null +++ b/drizzle-orm/src/spanner/driver.ts @@ -0,0 +1,172 @@ +import { type Connection as CallbackConnection, createPool, type Pool as CallbackPool, type PoolOptions } from 'mysql2'; +import type { Connection, Pool } from 'mysql2/promise'; +import { entityKind } from '~/entity.ts'; +import type { Logger } from '~/logger.ts'; +import { DefaultLogger } from '~/logger.ts'; +import { GoogleSqlDatabase } from '~/googlesql/db.ts'; +import { GoogleSqlDialect } from '~/googlesql/dialect.ts'; +import type { Mode } from '~/googlesql/session.ts'; +import { + createTableRelationsHelpers, + extractTablesRelationalConfig, + type RelationalSchemaConfig, + type TablesRelationalConfig, +} from '~/relations.ts'; +import { type DrizzleConfig, isConfig } from '~/utils.ts'; +import { DrizzleError } from '../errors.ts'; +import type { SpannerClient, SpannerPreparedQueryHKT, SpannerQueryResultHKT } from './session.ts'; +import { SpannerSession } from './session.ts'; + +export interface GoogleSqlDriverOptions { + logger?: Logger; +} + +export class SpannerDriver { + static readonly [entityKind]: string = 'SpannerDriver'; + + constructor( + private client: SpannerClient, + private dialect: GoogleSqlDialect, + private options: GoogleSqlDriverOptions = {}, + ) { + } + + createSession( + schema: RelationalSchemaConfig | undefined, + mode: Mode, + ): SpannerSession, TablesRelationalConfig> { + return new SpannerSession(this.client, this.dialect, schema, { logger: this.options.logger, mode }); + } +} + +export { GoogleSqlDatabase } from '~/googlesql/db.ts'; + +export class SpannerDatabase< + TSchema extends Record = Record, +> extends GoogleSqlDatabase { + static override readonly [entityKind]: string = 'SpannerDatabase'; +} + +export type SpannerDrizzleConfig = Record> = + & Omit, 'schema'> + & ({ schema: TSchema; mode: Mode } | { schema?: undefined; mode?: Mode }); + +function construct< + TSchema extends Record = Record, + TClient extends Pool | Connection | CallbackPool | CallbackConnection = CallbackPool, +>( + client: TClient, + config: SpannerDrizzleConfig = {}, +): SpannerDatabase & { + $client: TClient; +} { + const dialect = new GoogleSqlDialect({ casing: config.casing }); + let logger; + if (config.logger === true) { + logger = new DefaultLogger(); + } else if (config.logger !== false) { + logger = config.logger; + } + + const clientForInstance = isCallbackClient(client) ? client.promise() : client; + + let schema: RelationalSchemaConfig | undefined; + if (config.schema) { + if (config.mode === undefined) { + throw new DrizzleError({ + message: + 'You need to specify "mode": "planetscale" or "default" when providing a schema. Read more: https://orm.drizzle.team/docs/rqb#modes', + }); + } + + const tablesConfig = extractTablesRelationalConfig( + config.schema, + createTableRelationsHelpers, + ); + schema = { + fullSchema: config.schema, + schema: tablesConfig.tables, + tableNamesMap: tablesConfig.tableNamesMap, + }; + } + + const mode = config.mode ?? 'default'; + + const driver = new SpannerDriver(clientForInstance as SpannerClient, dialect, { logger }); + const session = driver.createSession(schema, mode); + const db = new SpannerDatabase(dialect, session, schema as any, mode) as SpannerDatabase; + ( db).$client = client; + + return db as any; +} + +interface CallbackClient { + promise(): SpannerClient; +} + +function isCallbackClient(client: any): client is CallbackClient { + return typeof client.promise === 'function'; +} + +export type AnySpannerConnection = Pool | Connection | CallbackPool | CallbackConnection; + +export function drizzle< + TSchema extends Record = Record, + TClient extends AnySpannerConnection = CallbackPool, +>( + ...params: [ + TClient | string, + ] | [ + TClient | string, + SpannerDrizzleConfig, + ] | [ + ( + & SpannerDrizzleConfig + & ({ + connection: string | PoolOptions; + } | { + client: TClient; + }) + ), + ] +): SpannerDatabase & { + $client: TClient; +} { + if (typeof params[0] === 'string') { + const connectionString = params[0]!; + const instance = createPool({ + uri: connectionString, + }); + + return construct(instance, params[1]) as any; + } + + if (isConfig(params[0])) { + const { connection, client, ...drizzleConfig } = params[0] as + & { connection?: PoolOptions | string; client?: TClient } + & SpannerDrizzleConfig; + + if (client) return construct(client, drizzleConfig) as any; + + const instance = typeof connection === 'string' + ? createPool({ + uri: connection, + }) + : createPool(connection!); + const db = construct(instance, drizzleConfig); + + return db as any; + } + + return construct(params[0] as TClient, params[1] as SpannerDrizzleConfig | undefined) as any; +} + +export namespace drizzle { + export function mock = Record>( + config?: SpannerDrizzleConfig, + ): SpannerDatabase & { + $client: '$client is not available on drizzle.mock()'; + } { + return construct({} as any, config) as any; + } +} diff --git a/drizzle-orm/src/spanner/index.ts b/drizzle-orm/src/spanner/index.ts new file mode 100644 index 0000000000..b1b6a52e71 --- /dev/null +++ b/drizzle-orm/src/spanner/index.ts @@ -0,0 +1,2 @@ +export * from './driver.ts'; +export * from './session.ts'; diff --git a/drizzle-orm/src/spanner/migrator.ts b/drizzle-orm/src/spanner/migrator.ts new file mode 100644 index 0000000000..65d6e9fef6 --- /dev/null +++ b/drizzle-orm/src/spanner/migrator.ts @@ -0,0 +1,11 @@ +import type { MigrationConfig } from '~/migrator.ts'; +import { readMigrationFiles } from '~/migrator.ts'; +import type { SpannerDatabase } from './driver.ts'; + +export async function migrate>( + db: SpannerDatabase, + config: MigrationConfig, +) { + const migrations = readMigrationFiles(config); + await db.dialect.migrate(migrations, db.session, config); +} diff --git a/drizzle-orm/src/spanner/session.ts b/drizzle-orm/src/spanner/session.ts new file mode 100644 index 0000000000..93c0e84dad --- /dev/null +++ b/drizzle-orm/src/spanner/session.ts @@ -0,0 +1,337 @@ +import type { Connection as CallbackConnection } from 'mysql2'; +import type { + Connection, + FieldPacket, + OkPacket, + Pool, + PoolConnection, + QueryOptions, + ResultSetHeader, + RowDataPacket, +} from 'mysql2/promise'; +import { once } from 'node:events'; +import { Column } from '~/column.ts'; +import { entityKind, is } from '~/entity.ts'; +import type { Logger } from '~/logger.ts'; +import { NoopLogger } from '~/logger.ts'; +import type { GoogleSqlDialect } from '~/googlesql/dialect.ts'; +import type { SelectedFieldsOrdered } from '~/googlesql/query-builders/select.types.ts'; +import { + type Mode, + GoogleSqlPreparedQuery, + type GoogleSqlPreparedQueryConfig, + type GoogleSqlPreparedQueryHKT, + type GoogleSqlQueryResultHKT, + GoogleSqlSession, + GoogleSqlTransaction, + type GoogleSqlTransactionConfig, + type PreparedQueryKind, +} from '~/googlesql/session.ts'; +import type { RelationalSchemaConfig, TablesRelationalConfig } from '~/relations.ts'; +import { fillPlaceholders, sql } from '~/sql/sql.ts'; +import type { Query, SQL } from '~/sql/sql.ts'; +import { type Assume, mapResultRow } from '~/utils.ts'; + +export type SpannerClient = Pool | Connection; + +export type GoogleSqlRawQueryResult = [ResultSetHeader, FieldPacket[]]; +export type GoogleSqlQueryResultType = RowDataPacket[][] | RowDataPacket[] | OkPacket | OkPacket[] | ResultSetHeader; +export type GoogleSqlQueryResult< + T = any, +> = [T extends ResultSetHeader ? T : T[], FieldPacket[]]; + +export class SpannerPreparedQuery extends GoogleSqlPreparedQuery { + static override readonly [entityKind]: string = 'SpannerPreparedQuery'; + + private rawQuery: QueryOptions; + private query: QueryOptions; + + constructor( + private client: SpannerClient, + queryString: string, + private params: unknown[], + private logger: Logger, + private fields: SelectedFieldsOrdered | undefined, + private customResultMapper?: (rows: unknown[][]) => T['execute'], + // Keys that were used in $default and the value that was generated for them + private generatedIds?: Record[], + // Keys that should be returned, it has the column with all properries + key from object + private returningIds?: SelectedFieldsOrdered, + ) { + super(); + this.rawQuery = { + sql: queryString, + // rowsAsArray: true, + typeCast: function(field: any, next: any) { + if (field.type === 'TIMESTAMP' || field.type === 'DATETIME' || field.type === 'DATE') { + return field.string(); + } + return next(); + }, + }; + this.query = { + sql: queryString, + rowsAsArray: true, + typeCast: function(field: any, next: any) { + if (field.type === 'TIMESTAMP' || field.type === 'DATETIME' || field.type === 'DATE') { + return field.string(); + } + return next(); + }, + }; + } + + async execute(placeholderValues: Record = {}): Promise { + const params = fillPlaceholders(this.params, placeholderValues); + + this.logger.logQuery(this.rawQuery.sql, params); + + const { fields, client, rawQuery, query, joinsNotNullableMap, customResultMapper, returningIds, generatedIds } = + this; + if (!fields && !customResultMapper) { + const res = await client.query(rawQuery, params); + const insertId = res[0].insertId; + const affectedRows = res[0].affectedRows; + // for each row, I need to check keys from + if (returningIds) { + const returningResponse = []; + let j = 0; + for (let i = insertId; i < insertId + affectedRows; i++) { + for (const column of returningIds) { + const key = returningIds[0]!.path[0]!; + if (is(column.field, Column)) { + // @ts-ignore + if (column.field.primary && column.field.autoIncrement) { + returningResponse.push({ [key]: i }); + } + if (column.field.defaultFn && generatedIds) { + // generatedIds[rowIdx][key] + returningResponse.push({ [key]: generatedIds[j]![key] }); + } + } + } + j++; + } + + return returningResponse; + } + return res; + } + + const result = await client.query(query, params); + const rows = result[0]; + + if (customResultMapper) { + return customResultMapper(rows); + } + + return rows.map((row) => mapResultRow(fields!, row, joinsNotNullableMap)); + } + + async *iterator( + placeholderValues: Record = {}, + ): AsyncGenerator { + const params = fillPlaceholders(this.params, placeholderValues); + const conn = ((isPool(this.client) ? await this.client.getConnection() : this.client) as {} as { + connection: CallbackConnection; + }).connection; + + const { fields, query, rawQuery, joinsNotNullableMap, client, customResultMapper } = this; + const hasRowsMapper = Boolean(fields || customResultMapper); + const driverQuery = hasRowsMapper ? conn.query(query, params) : conn.query(rawQuery, params); + + const stream = driverQuery.stream(); + + function dataListener() { + stream.pause(); + } + + stream.on('data', dataListener); + + try { + const onEnd = once(stream, 'end'); + const onError = once(stream, 'error'); + + while (true) { + stream.resume(); + const row = await Promise.race([onEnd, onError, new Promise((resolve) => stream.once('data', resolve))]); + if (row === undefined || (Array.isArray(row) && row.length === 0)) { + break; + } else if (row instanceof Error) { // eslint-disable-line no-instanceof/no-instanceof + throw row; + } else { + if (hasRowsMapper) { + if (customResultMapper) { + const mappedRow = customResultMapper([row as unknown[]]); + yield (Array.isArray(mappedRow) ? mappedRow[0] : mappedRow); + } else { + yield mapResultRow(fields!, row as unknown[], joinsNotNullableMap); + } + } else { + yield row as T['execute']; + } + } + } + } finally { + stream.off('data', dataListener); + if (isPool(client)) { + conn.end(); + } + } + } +} + +export interface SpannerSessionOptions { + logger?: Logger; + mode: Mode; +} + +export class SpannerSession< + TFullSchema extends Record, + TSchema extends TablesRelationalConfig, +> extends GoogleSqlSession { + static override readonly [entityKind]: string = 'SpannerSession'; + + private logger: Logger; + private mode: Mode; + + constructor( + private client: SpannerClient, + dialect: GoogleSqlDialect, + private schema: RelationalSchemaConfig | undefined, + private options: SpannerSessionOptions, + ) { + super(dialect); + this.logger = options.logger ?? new NoopLogger(); + this.mode = options.mode; + } + + prepareQuery( + query: Query, + fields: SelectedFieldsOrdered | undefined, + customResultMapper?: (rows: unknown[][]) => T['execute'], + generatedIds?: Record[], + returningIds?: SelectedFieldsOrdered, + ): PreparedQueryKind { + // Add returningId fields + // Each driver gets them from response from database + return new SpannerPreparedQuery( + this.client, + query.sql, + query.params, + this.logger, + fields, + customResultMapper, + generatedIds, + returningIds, + ) as PreparedQueryKind; + } + + /** + * @internal + * What is its purpose? + */ + async query(query: string, params: unknown[]): Promise { + this.logger.logQuery(query, params); + const result = await this.client.query({ + sql: query, + values: params, + rowsAsArray: true, + typeCast: function(field: any, next: any) { + if (field.type === 'TIMESTAMP' || field.type === 'DATETIME' || field.type === 'DATE') { + return field.string(); + } + return next(); + }, + }); + return result; + } + + override all(query: SQL): Promise { + const querySql = this.dialect.sqlToQuery(query); + this.logger.logQuery(querySql.sql, querySql.params); + return this.client.execute(querySql.sql, querySql.params).then((result) => result[0]) as Promise; + } + + override async transaction( + transaction: (tx: SpannerTransaction) => Promise, + config?: GoogleSqlTransactionConfig, + ): Promise { + const session = isPool(this.client) + ? new SpannerSession( + await this.client.getConnection(), + this.dialect, + this.schema, + this.options, + ) + : this; + const tx = new SpannerTransaction( + this.dialect, + session as GoogleSqlSession, + this.schema, + 0, + this.mode, + ); + if (config) { + const setTransactionConfigSql = this.getSetTransactionSQL(config); + if (setTransactionConfigSql) { + await tx.execute(setTransactionConfigSql); + } + const startTransactionSql = this.getStartTransactionSQL(config); + await (startTransactionSql ? tx.execute(startTransactionSql) : tx.execute(sql`begin`)); + } else { + await tx.execute(sql`begin`); + } + try { + const result = await transaction(tx); + await tx.execute(sql`commit`); + return result; + } catch (err) { + await tx.execute(sql`rollback`); + throw err; + } finally { + if (isPool(this.client)) { + (session.client as PoolConnection).release(); + } + } + } +} + +export class SpannerTransaction< + TFullSchema extends Record, + TSchema extends TablesRelationalConfig, +> extends GoogleSqlTransaction { + static override readonly [entityKind]: string = 'SpannerTransaction'; + + override async transaction(transaction: (tx: SpannerTransaction) => Promise): Promise { + const savepointName = `sp${this.nestedIndex + 1}`; + const tx = new SpannerTransaction( + this.dialect, + this.session, + this.schema, + this.nestedIndex + 1, + this.mode, + ); + await tx.execute(sql.raw(`savepoint ${savepointName}`)); + try { + const result = await transaction(tx); + await tx.execute(sql.raw(`release savepoint ${savepointName}`)); + return result; + } catch (err) { + await tx.execute(sql.raw(`rollback to savepoint ${savepointName}`)); + throw err; + } + } +} + +function isPool(client: SpannerClient): client is Pool { + return 'getConnection' in client; +} + +export interface SpannerQueryResultHKT extends GoogleSqlQueryResultHKT { + type: GoogleSqlRawQueryResult; +} + +export interface SpannerPreparedQueryHKT extends GoogleSqlPreparedQueryHKT { + type: SpannerPreparedQuery>; +}