Skip to content

Commit 8e54093

Browse files
committed
async, effect type PG delete & update builders
1 parent f0e4a3c commit 8e54093

File tree

11 files changed

+1070
-135
lines changed

11 files changed

+1070
-135
lines changed

drizzle-orm/src/pg-core/async/db.ts

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,7 @@ import type { Cache } from '~/cache/core/cache.ts';
33
import { entityKind } from '~/entity.ts';
44
import type { PgAsyncSession, PgAsyncTransaction } from '~/pg-core/async/session.ts';
55
import type { PgDialect } from '~/pg-core/dialect.ts';
6-
import {
7-
PgDeleteBase,
8-
type PgDeleteHKT,
9-
PgInsertBuilder,
10-
PgUpdateBuilder,
11-
QueryBuilder,
12-
} from '~/pg-core/query-builders/index.ts';
6+
import { PgInsertBuilder, PgUpdateBuilder, QueryBuilder } from '~/pg-core/query-builders/index.ts';
137
import type { PgQueryResultHKT, PgQueryResultKind, PgTransactionConfig } from '~/pg-core/session.ts';
148
import type { PgTable } from '~/pg-core/table.ts';
159
import type { TypedQueryBuilder } from '~/query-builders/query-builder.ts';
@@ -29,8 +23,10 @@ import type { PreparedQueryConfig } from '../session.ts';
2923
import type { WithBuilder } from '../subquery.ts';
3024
import type { PgViewBase } from '../view-base.ts';
3125
import type { PgMaterializedView } from '../view.ts';
26+
import { PgAsyncDeleteBase } from './delete.ts';
3227
import { PgAsyncInsertBase, type PgAsyncInsertHKT } from './insert.ts';
3328
import { PgAsyncSelectBase, type PgAsyncSelectInit } from './select.ts';
29+
import { PgAsyncUpdateBase, type PgAsyncUpdateHKT } from './update.ts';
3430

3531
export class PgAsyncDatabase<
3632
TQueryResult extends PgQueryResultHKT,
@@ -369,8 +365,8 @@ export class PgAsyncDatabase<
369365
* .returning();
370366
* ```
371367
*/
372-
function update<TTable extends PgTable>(table: TTable): PgUpdateBuilder<TTable, TQueryResult> {
373-
return new PgUpdateBuilder(table, self.session, self.dialect, queries);
368+
function update<TTable extends PgTable>(table: TTable): PgUpdateBuilder<TTable, TQueryResult, PgAsyncUpdateHKT> {
369+
return new PgUpdateBuilder(table, self.session, self.dialect, queries, PgAsyncUpdateBase);
374370
}
375371

376372
/**
@@ -427,8 +423,8 @@ export class PgAsyncDatabase<
427423
* .returning();
428424
* ```
429425
*/
430-
function delete_<TTable extends PgTable>(table: TTable): PgDeleteBase<PgDeleteHKT, TTable, TQueryResult> {
431-
return new PgDeleteBase(table, self.session, self.dialect, queries);
426+
function delete_<TTable extends PgTable>(table: TTable): PgAsyncDeleteBase<TTable, TQueryResult> {
427+
return new PgAsyncDeleteBase(table, self.session, self.dialect, queries);
432428
}
433429

434430
return { select, selectDistinct, selectDistinctOn, update, insert, delete: delete_ };
@@ -588,8 +584,8 @@ export class PgAsyncDatabase<
588584
* .returning();
589585
* ```
590586
*/
591-
update<TTable extends PgTable>(table: TTable): PgUpdateBuilder<TTable, TQueryResult> {
592-
return new PgUpdateBuilder(table, this.session, this.dialect);
587+
update<TTable extends PgTable>(table: TTable): PgUpdateBuilder<TTable, TQueryResult, PgAsyncUpdateHKT> {
588+
return new PgUpdateBuilder(table, this.session, this.dialect, undefined, PgAsyncUpdateBase);
593589
}
594590

595591
/**
@@ -644,8 +640,8 @@ export class PgAsyncDatabase<
644640
* .returning();
645641
* ```
646642
*/
647-
delete<TTable extends PgTable>(table: TTable): PgDeleteBase<PgDeleteHKT, TTable, TQueryResult> {
648-
return new PgDeleteBase(table, this.session, this.dialect);
643+
delete<TTable extends PgTable>(table: TTable): PgAsyncDeleteBase<TTable, TQueryResult> {
644+
return new PgAsyncDeleteBase(table, this.session, this.dialect);
649645
}
650646

651647
refreshMaterializedView<TView extends PgMaterializedView>(view: TView): PgRefreshMaterializedView<TQueryResult> {
@@ -694,7 +690,7 @@ export class PgAsyncDatabase<
694690
}
695691
}
696692

697-
export type PgWithReplicas<Q> = Q & { $primary: Q; $replicas: Q[] };
693+
export type PgAsyncWithReplicas<Q> = Q & { $primary: Q; $replicas: Q[] };
698694

699695
export const withReplicas = <
700696
HKT extends PgQueryResultHKT,
@@ -711,7 +707,7 @@ export const withReplicas = <
711707
primary: Q,
712708
replicas: [Q, ...Q[]],
713709
getReplica: (replicas: Q[]) => Q = () => replicas[Math.floor(Math.random() * replicas.length)]!,
714-
): PgWithReplicas<Q> => {
710+
): PgAsyncWithReplicas<Q> => {
715711
const select: Q['select'] = (...args: []) => getReplica(replicas).select(...args);
716712
const selectDistinct: Q['selectDistinct'] = (...args: []) => getReplica(replicas).selectDistinct(...args);
717713
const selectDistinctOn: Q['selectDistinctOn'] = (...args: [any]) => getReplica(replicas).selectDistinctOn(...args);
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import { entityKind } from '~/entity.ts';
2+
import type { PgQueryResultHKT, PgQueryResultKind, PreparedQueryConfig } from '~/pg-core/session.ts';
3+
import type { PgTable } from '~/pg-core/table.ts';
4+
import type { TypedQueryBuilder } from '~/query-builders/query-builder.ts';
5+
import { QueryPromise } from '~/query-promise.ts';
6+
import type { RunnableQuery } from '~/runnable-query.ts';
7+
import type { ColumnsSelection, SQLWrapper } from '~/sql/sql.ts';
8+
import { tracer } from '~/tracing.ts';
9+
import { applyMixins, type Assume, type NeonAuthToken } from '~/utils.ts';
10+
import type { PgAsyncPreparedQuery, PgAsyncSession } from '../async/session.ts';
11+
import { PgDeleteBase, type PgDeleteHKTBase } from '../query-builders/delete.ts';
12+
import { extractUsedTable } from '../utils.ts';
13+
14+
export type PgAsyncDelete<
15+
TTable extends PgTable = PgTable,
16+
TQueryResult extends PgQueryResultHKT = PgQueryResultHKT,
17+
TSelectedFields extends ColumnsSelection | undefined = undefined,
18+
TReturning extends Record<string, unknown> | undefined = Record<string, unknown> | undefined,
19+
> = PgAsyncDeleteBase<TTable, TQueryResult, TSelectedFields, TReturning, true, never>;
20+
21+
export type PgAsyncDeletePrepare<T extends AnyAsyncPgDelete> = PgAsyncPreparedQuery<
22+
PreparedQueryConfig & {
23+
execute: T['_']['returning'] extends undefined ? PgQueryResultKind<T['_']['queryResult'], never>
24+
: T['_']['returning'][];
25+
}
26+
>;
27+
28+
export type AnyAsyncPgDelete = PgAsyncDeleteBase<any, any, any, any, any, any>;
29+
30+
export interface PgAsyncDeleteHKT extends PgDeleteHKTBase {
31+
_type: PgAsyncDeleteBase<
32+
Assume<this['table'], PgTable>,
33+
Assume<this['queryResult'], PgQueryResultHKT>,
34+
Assume<this['selectedFields'], ColumnsSelection | undefined>,
35+
Assume<this['returning'], Record<string, unknown> | undefined>,
36+
this['dynamic'],
37+
this['excludedMethods']
38+
>;
39+
}
40+
41+
export interface PgAsyncDeleteBase<
42+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
43+
TTable extends PgTable,
44+
TQueryResult extends PgQueryResultHKT,
45+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
46+
TSelectedFields extends ColumnsSelection | undefined = undefined,
47+
TReturning extends Record<string, unknown> | undefined = undefined,
48+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
49+
TDynamic extends boolean = false,
50+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
51+
TExcludedMethods extends string = never,
52+
> extends QueryPromise<TReturning extends undefined ? PgQueryResultKind<TQueryResult, never> : TReturning[]> {}
53+
54+
export class PgAsyncDeleteBase<
55+
TTable extends PgTable,
56+
TQueryResult extends PgQueryResultHKT,
57+
TSelectedFields extends ColumnsSelection | undefined = undefined,
58+
TReturning extends Record<string, unknown> | undefined = undefined,
59+
TDynamic extends boolean = false,
60+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
61+
TExcludedMethods extends string = never,
62+
> extends PgDeleteBase<PgAsyncDeleteHKT, TTable, TQueryResult, TSelectedFields, TReturning, TDynamic, TExcludedMethods>
63+
implements
64+
TypedQueryBuilder<
65+
TSelectedFields,
66+
TReturning extends undefined ? PgQueryResultKind<TQueryResult, never> : TReturning[]
67+
>,
68+
RunnableQuery<TReturning extends undefined ? PgQueryResultKind<TQueryResult, never> : TReturning[], 'pg'>,
69+
SQLWrapper
70+
{
71+
static override readonly [entityKind]: string = 'PgAsyncDelete';
72+
73+
declare protected session: PgAsyncSession;
74+
75+
/** @internal */
76+
_prepare(name?: string): PgAsyncDeletePrepare<this> {
77+
return tracer.startActiveSpan('drizzle.prepareQuery', () => {
78+
return this.session.prepareQuery<
79+
PreparedQueryConfig & {
80+
execute: TReturning extends undefined ? PgQueryResultKind<TQueryResult, never> : TReturning[];
81+
}
82+
>(this.dialect.sqlToQuery(this.getSQL()), this.config.returning, name, true, undefined, {
83+
type: 'delete',
84+
tables: extractUsedTable(this.config.table),
85+
}, this.cacheConfig);
86+
});
87+
}
88+
89+
prepare(name: string): PgAsyncDeletePrepare<this> {
90+
return this._prepare(name);
91+
}
92+
93+
/** @internal */
94+
private authToken?: NeonAuthToken;
95+
/** @internal */
96+
setToken(token?: NeonAuthToken) {
97+
this.authToken = token;
98+
return this;
99+
}
100+
101+
execute: ReturnType<this['prepare']>['execute'] = (placeholderValues) => {
102+
return tracer.startActiveSpan('drizzle.operation', () => {
103+
return this._prepare().setToken(this.authToken).execute(placeholderValues);
104+
});
105+
};
106+
}
107+
108+
applyMixins(PgAsyncDeleteBase, [QueryPromise]);
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
export * from './count.ts';
22
export * from './db.ts';
3+
export * from './delete.ts';
4+
export * from './insert.ts';
35
export * from './select.ts';
46
export * from './session.ts';
7+
export * from './update.ts';
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import { entityKind } from '~/entity.ts';
2+
import type { PgQueryResultHKT, PgQueryResultKind, PreparedQueryConfig } from '~/pg-core/session.ts';
3+
import type { PgTable } from '~/pg-core/table.ts';
4+
import type { JoinNullability } from '~/query-builders/select.types.ts';
5+
import { QueryPromise } from '~/query-promise.ts';
6+
import type { RunnableQuery } from '~/runnable-query.ts';
7+
import type { ColumnsSelection, SQL } from '~/sql/sql.ts';
8+
import type { Subquery } from '~/subquery.ts';
9+
import { applyMixins, type Assume } from '~/utils.ts';
10+
import type { PgAsyncPreparedQuery, PgAsyncSession } from '../async/session.ts';
11+
import { type Join, PgUpdateBase } from '../query-builders/update.ts';
12+
import { extractUsedTable } from '../utils.ts';
13+
import type { PgViewBase } from '../view-base.ts';
14+
15+
export type PgAsyncUpdatePrepare<T extends AnyPgAsyncUpdate> = PgAsyncPreparedQuery<
16+
PreparedQueryConfig & {
17+
execute: T['_']['returning'] extends undefined ? PgQueryResultKind<T['_']['queryResult'], never>
18+
: T['_']['returning'][];
19+
}
20+
>;
21+
22+
export type PgAsyncUpdate<
23+
TTable extends PgTable = PgTable,
24+
TQueryResult extends PgQueryResultHKT = PgQueryResultHKT,
25+
TFrom extends PgTable | Subquery | PgViewBase | SQL | undefined = undefined,
26+
TSelectedFields extends ColumnsSelection | undefined = undefined,
27+
TReturning extends Record<string, unknown> | undefined = Record<string, unknown> | undefined,
28+
TNullabilityMap extends Record<string, JoinNullability> = Record<TTable['_']['name'], 'not-null'>,
29+
TJoins extends Join[] = [],
30+
> = PgAsyncUpdateBase<
31+
TTable,
32+
TQueryResult,
33+
TFrom,
34+
TSelectedFields,
35+
TReturning,
36+
TNullabilityMap,
37+
TJoins,
38+
true,
39+
never
40+
>;
41+
42+
export interface PgUpdateHKTBase {
43+
table: unknown;
44+
joins: unknown;
45+
nullabilityMap: unknown;
46+
queryResult: unknown;
47+
from: unknown;
48+
selectedFields: unknown;
49+
returning: unknown;
50+
dynamic: boolean;
51+
excludedMethods: string;
52+
_type: unknown;
53+
}
54+
55+
export interface PgAsyncUpdateHKT extends PgUpdateHKTBase {
56+
_type: PgAsyncUpdateBase<
57+
Assume<this['table'], PgTable>,
58+
Assume<this['queryResult'], PgQueryResultHKT>,
59+
Assume<this['from'], PgTable | Subquery | PgViewBase | SQL | undefined>,
60+
Assume<this['selectedFields'], ColumnsSelection | undefined>,
61+
Assume<this['returning'], Record<string, unknown> | undefined>,
62+
Assume<this['nullabilityMap'], Record<string, JoinNullability>>,
63+
Assume<this['joins'], Join[]>,
64+
this['dynamic'],
65+
this['excludedMethods']
66+
>;
67+
}
68+
69+
export type AnyPgAsyncUpdate = PgAsyncUpdateBase<any, any, any, any, any, any, any, any, any>;
70+
71+
export interface PgAsyncUpdateBase<
72+
TTable extends PgTable,
73+
TQueryResult extends PgQueryResultHKT,
74+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
75+
TFrom extends PgTable | Subquery | PgViewBase | SQL | undefined = undefined,
76+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
77+
TSelectedFields extends ColumnsSelection | undefined = undefined,
78+
TReturning extends Record<string, unknown> | undefined = undefined,
79+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
80+
TNullabilityMap extends Record<string, JoinNullability> = Record<TTable['_']['name'], 'not-null'>,
81+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
82+
TJoins extends Join[] = [],
83+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
84+
TDynamic extends boolean = false,
85+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
86+
TExcludedMethods extends string = never,
87+
> extends QueryPromise<TReturning extends undefined ? PgQueryResultKind<TQueryResult, never> : TReturning[]> {}
88+
89+
export class PgAsyncUpdateBase<
90+
TTable extends PgTable,
91+
TQueryResult extends PgQueryResultHKT,
92+
TFrom extends PgTable | Subquery | PgViewBase | SQL | undefined = undefined,
93+
TSelectedFields extends ColumnsSelection | undefined = undefined,
94+
TReturning extends Record<string, unknown> | undefined = undefined,
95+
TNullabilityMap extends Record<string, JoinNullability> = Record<TTable['_']['name'], 'not-null'>,
96+
TJoins extends Join[] = [],
97+
TDynamic extends boolean = false,
98+
TExcludedMethods extends string = never,
99+
> extends PgUpdateBase<
100+
PgAsyncUpdateHKT,
101+
TTable,
102+
TQueryResult,
103+
TFrom,
104+
TSelectedFields,
105+
TReturning,
106+
TNullabilityMap,
107+
TJoins,
108+
TDynamic,
109+
TExcludedMethods
110+
> implements RunnableQuery<TReturning extends undefined ? PgQueryResultKind<TQueryResult, never> : TReturning[], 'pg'> {
111+
static override readonly [entityKind]: string = 'PgAsyncUpdate';
112+
113+
declare protected session: PgAsyncSession;
114+
115+
/** @internal */
116+
_prepare(name?: string): PgAsyncUpdatePrepare<this> {
117+
const query = this.session.prepareQuery<
118+
PreparedQueryConfig & { execute: TReturning[] }
119+
>(this.dialect.sqlToQuery(this.getSQL()), this.config.returning, name, true, undefined, {
120+
type: 'insert',
121+
tables: extractUsedTable(this.config.table),
122+
}, this.cacheConfig);
123+
query.joinsNotNullableMap = this.joinsNotNullableMap;
124+
return query;
125+
}
126+
127+
prepare(name: string): PgAsyncUpdatePrepare<this> {
128+
return this._prepare(name);
129+
}
130+
131+
execute: ReturnType<this['prepare']>['execute'] = (placeholderValues: Record<string, unknown> = {}) => {
132+
return this._prepare().execute(placeholderValues);
133+
};
134+
}
135+
136+
applyMixins(PgAsyncUpdateBase, [QueryPromise]);

0 commit comments

Comments
 (0)