Skip to content

Commit

Permalink
Merge branch 'beta' into aws-data-api-fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
dankochetov committed Apr 7, 2024
2 parents df2bd77 + ab9feb7 commit 9b8a94f
Show file tree
Hide file tree
Showing 18 changed files with 133 additions and 59 deletions.
1 change: 1 addition & 0 deletions .github/workflows/release-feature-branch.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ jobs:
PLANETSCALE_CONNECTION_STRING: ${{ secrets.PLANETSCALE_CONNECTION_STRING }}
NEON_CONNECTION_STRING: ${{ secrets.NEON_CONNECTION_STRING }}
XATA_API_KEY: ${{ secrets.XATA_API_KEY }}
XATA_BRANCH: ${{ secrets.XATA_BRANCH }}
LIBSQL_URL: file:local.db
run: |
if [[ ${{ github.event_name }} != "push" && "${{ github.event.pull_request.head.repo.full_name }}" != "${{ github.repository }}" ]]; then
Expand Down
11 changes: 11 additions & 0 deletions changelogs/drizzle-orm/0.30.8.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
- 🎉 Added custom schema support to enums in Postgres:

```ts
import { pgSchema } from 'drizzle-orm/pg-core';

const mySchema = pgSchema('mySchema');
const colors = mySchema.enum('colors', ['red', 'green', 'blue']);
```

- 🐛 Split `where` clause in Postgres `.onConflictDoUpdate` method into `setWhere` and `targetWhere` clauses, to support both `where` cases in `on conflict ...` clause (#1628, #1302)
- 🐛 Fix query generation for `where` clause in Postgres `.onConflictDoNothing` method, as it was placed in a wrong spot (#1628)
6 changes: 3 additions & 3 deletions drizzle-orm/src/mysql-core/dialect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
type TablesRelationalConfig,
} from '~/relations.ts';
import { Param, type QueryWithTypings, SQL, sql, type SQLChunk, View } from '~/sql/sql.ts';
import { Subquery, SubqueryConfig } from '~/subquery.ts';
import { Subquery } from '~/subquery.ts';
import { getTableName, Table } from '~/table.ts';
import { orderSelectedFields, type UpdateSet } from '~/utils.ts';
import { and, DrizzleError, eq, type Name, ViewBaseConfig } from '../index.ts';
Expand Down Expand Up @@ -88,7 +88,7 @@ export class MySqlDialect {

const withSqlChunks = [sql`with `];
for (const [i, w] of queries.entries()) {
withSqlChunks.push(sql`${sql.identifier(w[SubqueryConfig].alias)} as (${w[SubqueryConfig].sql})`);
withSqlChunks.push(sql`${sql.identifier(w._.alias)} as (${w._.sql})`);
if (i < queries.length - 1) {
withSqlChunks.push(sql`, `);
}
Expand Down Expand Up @@ -230,7 +230,7 @@ export class MySqlDialect {
is(f.field, Column)
&& getTableName(f.field.table)
!== (is(table, Subquery)
? table[SubqueryConfig].alias
? table._.alias
: is(table, MySqlViewBase)
? table[ViewBaseConfig].name
: is(table, SQL)
Expand Down
6 changes: 3 additions & 3 deletions drizzle-orm/src/mysql-core/query-builders/select.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { QueryPromise } from '~/query-promise.ts';
import { SelectionProxyHandler } from '~/selection-proxy.ts';
import type { ColumnsSelection, Query } from '~/sql/sql.ts';
import { SQL, View } from '~/sql/sql.ts';
import { Subquery, SubqueryConfig } from '~/subquery.ts';
import { Subquery } from '~/subquery.ts';
import { Table } from '~/table.ts';
import { applyMixins, getTableColumns, getTableLikeName, haveSameKeys, type ValueOrArray } from '~/utils.ts';
import { orderSelectedFields } from '~/utils.ts';
Expand Down Expand Up @@ -93,7 +93,7 @@ export class MySqlSelectBuilder<
} 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[SubqueryConfig].selection).map((
Object.keys(source._.selectedFields).map((
key,
) => [key, source[key as unknown as keyof typeof source] as unknown as SelectedFields[string]]),
);
Expand Down Expand Up @@ -207,7 +207,7 @@ export abstract class MySqlSelectQueryBuilderBase<
}
if (typeof tableName === 'string' && !is(table, SQL)) {
const selection = is(table, Subquery)
? table[SubqueryConfig].selection
? table._.selectedFields
: is(table, View)
? table[ViewBaseConfig].selectedFields
: table[Table.Symbol.Columns];
Expand Down
13 changes: 12 additions & 1 deletion drizzle-orm/src/pg-core/columns/enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export interface PgEnum<TValues extends [string, ...string[]]> {

readonly enumName: string;
readonly enumValues: TValues;
readonly schema: string | undefined;
/** @internal */
[isPgEnumSym]: true;
}
Expand Down Expand Up @@ -76,12 +77,22 @@ export function pgEnum<U extends string, T extends Readonly<[U, ...U[]]>>(
enumName: string,
values: T | Writable<T>,
): PgEnum<Writable<T>> {
const enumInstance = Object.assign(
return pgEnumWithSchema(enumName, values, undefined);
}

/** @internal */
export function pgEnumWithSchema<U extends string, T extends Readonly<[U, ...U[]]>>(
enumName: string,
values: T | Writable<T>,
schema?: string,
): PgEnum<Writable<T>> {
const enumInstance: PgEnum<Writable<T>> = Object.assign(
<TName extends string>(name: TName): PgEnumColumnBuilderInitial<TName, Writable<T>> =>
new PgEnumColumnBuilder(name, enumInstance),
{
enumName,
enumValues: values,
schema,
[isPgEnumSym]: true,
} as const,
);
Expand Down
6 changes: 3 additions & 3 deletions drizzle-orm/src/pg-core/dialect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ import {
sql,
type SQLChunk,
} from '~/sql/sql.ts';
import { Subquery, SubqueryConfig } from '~/subquery.ts';
import { Subquery } from '~/subquery.ts';
import { getTableName, Table } from '~/table.ts';
import { orderSelectedFields, type UpdateSet } from '~/utils.ts';
import { ViewBaseConfig } from '~/view-common.ts';
Expand Down Expand Up @@ -115,7 +115,7 @@ export class PgDialect {

const withSqlChunks = [sql`with `];
for (const [i, w] of queries.entries()) {
withSqlChunks.push(sql`${sql.identifier(w[SubqueryConfig].alias)} as (${w[SubqueryConfig].sql})`);
withSqlChunks.push(sql`${sql.identifier(w._.alias)} as (${w._.sql})`);
if (i < queries.length - 1) {
withSqlChunks.push(sql`, `);
}
Expand Down Expand Up @@ -257,7 +257,7 @@ export class PgDialect {
is(f.field, Column)
&& getTableName(f.field.table)
!== (is(table, Subquery)
? table[SubqueryConfig].alias
? table._.alias
: is(table, PgViewBase)
? table[ViewBaseConfig].name
: is(table, SQL)
Expand Down
19 changes: 16 additions & 3 deletions drizzle-orm/src/pg-core/query-builders/insert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,11 @@ export type PgInsertReturningAll<T extends AnyPgInsert, TDynamic extends boolean

export interface PgInsertOnConflictDoUpdateConfig<T extends AnyPgInsert> {
target: IndexColumn | IndexColumn[];
/** @deprecated use either `targetWhere` or `setWhere` */
where?: SQL;
// TODO: add tests for targetWhere and setWhere
targetWhere?: SQL;
setWhere?: SQL;
set: PgUpdateSetSource<T['_']['table']>;
}

Expand Down Expand Up @@ -242,7 +246,7 @@ export class PgInsertBase<
: this.dialect.escapeName(config.target.name);

const whereSql = config.where ? sql` where ${config.where}` : undefined;
this.config.onConflict = sql`(${sql.raw(targetColumn)}) do nothing${whereSql}`;
this.config.onConflict = sql`(${sql.raw(targetColumn)})${whereSql} do nothing`;
}
return this as any;
}
Expand Down Expand Up @@ -272,20 +276,29 @@ export class PgInsertBase<
* .onConflictDoUpdate({
* target: cars.id,
* set: { brand: 'newBMW' },
* where: sql`${cars.createdAt} > '2023-01-01'::date`,
* targetWhere: sql`${cars.createdAt} > '2023-01-01'::date`,
* });
* ```
*/
onConflictDoUpdate(
config: PgInsertOnConflictDoUpdateConfig<this>,
): PgInsertWithout<this, TDynamic, 'onConflictDoNothing' | 'onConflictDoUpdate'> {
if (config.where && (config.targetWhere || config.setWhere)) {
throw new Error(
'You cannot use both "where" and "targetWhere"/"setWhere" at the same time - "where" is deprecated, use "targetWhere" or "setWhere" instead.',
);
}
const whereSql = config.where ? sql` where ${config.where}` : undefined;
const targetWhereSql = config.targetWhere ? sql` where ${config.targetWhere}` : undefined;
const setWhereSql = config.setWhere ? sql` where ${config.setWhere}` : undefined;
const setSql = this.dialect.buildUpdateSet(this.config.table, mapUpdateSet(this.config.table, config.set));
let targetColumn = '';
targetColumn = Array.isArray(config.target)
? config.target.map((it) => this.dialect.escapeName(it.name)).join(',')
: this.dialect.escapeName(config.target.name);
this.config.onConflict = sql`(${sql.raw(targetColumn)}) do update set ${setSql}${whereSql}`;
this.config.onConflict = sql`(${
sql.raw(targetColumn)
})${targetWhereSql} do update set ${setSql}${whereSql}${setWhereSql}`;
return this as any;
}

Expand Down
6 changes: 3 additions & 3 deletions drizzle-orm/src/pg-core/query-builders/select.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import type { RunnableQuery } from '~/runnable-query.ts';
import { SelectionProxyHandler } from '~/selection-proxy.ts';
import { SQL, View } from '~/sql/sql.ts';
import type { ColumnsSelection, Placeholder, Query, SQLWrapper } from '~/sql/sql.ts';
import { Subquery, SubqueryConfig } from '~/subquery.ts';
import { Subquery } from '~/subquery.ts';
import { Table } from '~/table.ts';
import { tracer } from '~/tracing.ts';
import { applyMixins, getTableColumns, getTableLikeName, haveSameKeys, type ValueOrArray } from '~/utils.ts';
Expand Down Expand Up @@ -103,7 +103,7 @@ export class PgSelectBuilder<
} 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[SubqueryConfig].selection).map((
Object.keys(source._.selectedFields).map((
key,
) => [key, source[key as unknown as keyof typeof source] as unknown as SelectedFields[string]]),
);
Expand Down Expand Up @@ -215,7 +215,7 @@ export abstract class PgSelectQueryBuilderBase<
}
if (typeof tableName === 'string' && !is(table, SQL)) {
const selection = is(table, Subquery)
? table[SubqueryConfig].selection
? table._.selectedFields
: is(table, View)
? table[ViewBaseConfig].selectedFields
: table[Table.Symbol.Columns];
Expand Down
6 changes: 6 additions & 0 deletions drizzle-orm/src/pg-core/schema.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { entityKind, is } from '~/entity.ts';
import type { pgEnum } from './columns/enum.ts';
import { pgEnumWithSchema } from './columns/enum.ts';
import { type PgTableFn, pgTableWithSchema } from './table.ts';
import { type pgMaterializedView, pgMaterializedViewWithSchema, type pgView, pgViewWithSchema } from './view.ts';

Expand All @@ -19,6 +21,10 @@ export class PgSchema<TName extends string = string> {
materializedView = ((name, columns) => {
return pgMaterializedViewWithSchema(name, columns, this.schemaName);
}) as typeof pgMaterializedView;

enum: typeof pgEnum = ((name, values) => {
return pgEnumWithSchema(name, values, this.schemaName);
});
}

export function isPgSchema(obj: unknown): obj is PgSchema {
Expand Down
12 changes: 6 additions & 6 deletions drizzle-orm/src/selection-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ColumnAliasProxyHandler, TableAliasProxyHandler } from './alias.ts';
import { Column } from './column.ts';
import { entityKind, is } from './entity.ts';
import { SQL, View } from './sql/sql.ts';
import { Subquery, SubqueryConfig } from './subquery.ts';
import { Subquery } from './subquery.ts';
import { ViewBaseConfig } from './view-common.ts';

export class SelectionProxyHandler<T extends Subquery | Record<string, unknown> | View>
Expand Down Expand Up @@ -45,11 +45,11 @@ export class SelectionProxyHandler<T extends Subquery | Record<string, unknown>
}

get(subquery: T, prop: string | symbol): any {
if (prop === SubqueryConfig) {
if (prop === '_') {
return {
...subquery[SubqueryConfig as keyof typeof subquery],
selection: new Proxy(
(subquery as Subquery)[SubqueryConfig].selection,
...subquery['_' as keyof typeof subquery],
selectedFields: new Proxy(
(subquery as Subquery)._.selectedFields,
this as ProxyHandler<Record<string, unknown>>,
),
};
Expand All @@ -70,7 +70,7 @@ export class SelectionProxyHandler<T extends Subquery | Record<string, unknown>
}

const columns = is(subquery, Subquery)
? subquery[SubqueryConfig].selection
? subquery._.selectedFields
: is(subquery, View)
? subquery[ViewBaseConfig].selectedFields
: subquery;
Expand Down
21 changes: 14 additions & 7 deletions drizzle-orm/src/sql/sql.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { entityKind, is } from '~/entity.ts';
import type { SelectedFields } from '~/operations.ts';
import { Subquery, SubqueryConfig } from '~/subquery.ts';
import { isPgEnum } from '~/pg-core/columns/enum.ts';
import { Subquery } from '~/subquery.ts';
import { tracer } from '~/tracing.ts';
import { ViewBaseConfig } from '~/view-common.ts';
import type { AnyColumn } from '../column.ts';
Expand Down Expand Up @@ -62,8 +63,7 @@ export interface SQLWrapper {
}

export function isSQLWrapper(value: unknown): value is SQLWrapper {
return typeof value === 'object' && value !== null && 'getSQL' in value
&& typeof (value as any).getSQL === 'function';
return value !== null && value !== undefined && typeof (value as any).getSQL === 'function';
}

function mergeQueries(queries: QueryWithTypings[]): QueryWithTypings {
Expand Down Expand Up @@ -225,17 +225,24 @@ export class SQL<T = unknown> implements SQLWrapper {
}

if (is(chunk, Subquery)) {
if (chunk[SubqueryConfig].isWith) {
return { sql: escapeName(chunk[SubqueryConfig].alias), params: [] };
if (chunk._.isWith) {
return { sql: escapeName(chunk._.alias), params: [] };
}
return this.buildQueryFromSourceParams([
new StringChunk('('),
chunk[SubqueryConfig].sql,
chunk._.sql,
new StringChunk(') '),
new Name(chunk[SubqueryConfig].alias),
new Name(chunk._.alias),
], config);
}

if (isPgEnum(chunk)) {
if (chunk.schema) {
return { sql: escapeName(chunk.schema) + '.' + escapeName(chunk.enumName), params: [] };
}
return { sql: escapeName(chunk.enumName), params: [] };
}

if (isSQLWrapper(chunk)) {
return this.buildQueryFromSourceParams([
new StringChunk('('),
Expand Down
6 changes: 3 additions & 3 deletions drizzle-orm/src/sqlite-core/dialect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { Param, type QueryWithTypings, SQL, sql, type SQLChunk } from '~/sql/sql
import { SQLiteColumn } from '~/sqlite-core/columns/index.ts';
import type { SQLiteDeleteConfig, SQLiteInsertConfig, SQLiteUpdateConfig } from '~/sqlite-core/query-builders/index.ts';
import { SQLiteTable } from '~/sqlite-core/table.ts';
import { Subquery, SubqueryConfig } from '~/subquery.ts';
import { Subquery } from '~/subquery.ts';
import { getTableName, Table } from '~/table.ts';
import { orderSelectedFields, type UpdateSet } from '~/utils.ts';
import { ViewBaseConfig } from '~/view-common.ts';
Expand Down Expand Up @@ -54,7 +54,7 @@ export abstract class SQLiteDialect {

const withSqlChunks = [sql`with `];
for (const [i, w] of queries.entries()) {
withSqlChunks.push(sql`${sql.identifier(w[SubqueryConfig].alias)} as (${w[SubqueryConfig].sql})`);
withSqlChunks.push(sql`${sql.identifier(w._.alias)} as (${w._.sql})`);
if (i < queries.length - 1) {
withSqlChunks.push(sql`, `);
}
Expand Down Expand Up @@ -197,7 +197,7 @@ export abstract class SQLiteDialect {
is(f.field, Column)
&& getTableName(f.field.table)
!== (is(table, Subquery)
? table[SubqueryConfig].alias
? table._.alias
: is(table, SQLiteViewBase)
? table[ViewBaseConfig].name
: is(table, SQL)
Expand Down
6 changes: 3 additions & 3 deletions drizzle-orm/src/sqlite-core/query-builders/select.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import type { SQLiteDialect } from '~/sqlite-core/dialect.ts';
import type { SQLiteSession } from '~/sqlite-core/session.ts';
import type { SubqueryWithSelection } from '~/sqlite-core/subquery.ts';
import type { SQLiteTable } from '~/sqlite-core/table.ts';
import { Subquery, SubqueryConfig } from '~/subquery.ts';
import { Subquery } from '~/subquery.ts';
import { Table } from '~/table.ts';
import {
applyMixins,
Expand Down Expand Up @@ -99,7 +99,7 @@ export class SQLiteSelectBuilder<
} 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[SubqueryConfig].selection).map((
Object.keys(source._.selectedFields).map((
key,
) => [key, source[key as unknown as keyof typeof source] as unknown as SelectedFields[string]]),
);
Expand Down Expand Up @@ -214,7 +214,7 @@ export abstract class SQLiteSelectQueryBuilderBase<
}
if (typeof tableName === 'string' && !is(table, SQL)) {
const selection = is(table, Subquery)
? table[SubqueryConfig].selection
? table._.selectedFields
: is(table, View)
? table[ViewBaseConfig].selectedFields
: table[Table.Symbol.Columns];
Expand Down
Loading

0 comments on commit 9b8a94f

Please sign in to comment.