linkgress-orm 0.0.3 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/entity/db-column.d.ts +38 -1
- package/dist/entity/db-column.d.ts.map +1 -1
- package/dist/entity/db-column.js.map +1 -1
- package/dist/entity/db-context.d.ts +429 -50
- package/dist/entity/db-context.d.ts.map +1 -1
- package/dist/entity/db-context.js +884 -203
- package/dist/entity/db-context.js.map +1 -1
- package/dist/entity/entity-base.d.ts +8 -0
- package/dist/entity/entity-base.d.ts.map +1 -1
- package/dist/entity/entity-base.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/query/collection-strategy.factory.d.ts.map +1 -1
- package/dist/query/collection-strategy.factory.js +7 -3
- package/dist/query/collection-strategy.factory.js.map +1 -1
- package/dist/query/collection-strategy.interface.d.ts +12 -6
- package/dist/query/collection-strategy.interface.d.ts.map +1 -1
- package/dist/query/conditions.d.ts +134 -23
- package/dist/query/conditions.d.ts.map +1 -1
- package/dist/query/conditions.js +58 -0
- package/dist/query/conditions.js.map +1 -1
- package/dist/query/cte-builder.d.ts +24 -5
- package/dist/query/cte-builder.d.ts.map +1 -1
- package/dist/query/cte-builder.js +45 -7
- package/dist/query/cte-builder.js.map +1 -1
- package/dist/query/grouped-query.d.ts +196 -8
- package/dist/query/grouped-query.d.ts.map +1 -1
- package/dist/query/grouped-query.js +586 -54
- package/dist/query/grouped-query.js.map +1 -1
- package/dist/query/join-builder.d.ts +5 -4
- package/dist/query/join-builder.d.ts.map +1 -1
- package/dist/query/join-builder.js +21 -47
- package/dist/query/join-builder.js.map +1 -1
- package/dist/query/query-builder.d.ts +118 -20
- package/dist/query/query-builder.d.ts.map +1 -1
- package/dist/query/query-builder.js +511 -280
- package/dist/query/query-builder.js.map +1 -1
- package/dist/query/query-utils.d.ts +45 -0
- package/dist/query/query-utils.d.ts.map +1 -0
- package/dist/query/query-utils.js +103 -0
- package/dist/query/query-utils.js.map +1 -0
- package/dist/query/sql-utils.d.ts +83 -0
- package/dist/query/sql-utils.d.ts.map +1 -0
- package/dist/query/sql-utils.js +218 -0
- package/dist/query/sql-utils.js.map +1 -0
- package/dist/query/strategies/cte-collection-strategy.d.ts +85 -0
- package/dist/query/strategies/cte-collection-strategy.d.ts.map +1 -0
- package/dist/query/strategies/cte-collection-strategy.js +338 -0
- package/dist/query/strategies/cte-collection-strategy.js.map +1 -0
- package/dist/query/strategies/lateral-collection-strategy.d.ts +59 -0
- package/dist/query/strategies/lateral-collection-strategy.d.ts.map +1 -0
- package/dist/query/strategies/lateral-collection-strategy.js +243 -0
- package/dist/query/strategies/lateral-collection-strategy.js.map +1 -0
- package/dist/query/strategies/temptable-collection-strategy.d.ts +21 -0
- package/dist/query/strategies/temptable-collection-strategy.d.ts.map +1 -1
- package/dist/query/strategies/temptable-collection-strategy.js +160 -38
- package/dist/query/strategies/temptable-collection-strategy.js.map +1 -1
- package/dist/query/subquery.d.ts +24 -1
- package/dist/query/subquery.d.ts.map +1 -1
- package/dist/query/subquery.js +38 -2
- package/dist/query/subquery.js.map +1 -1
- package/dist/schema/table-builder.d.ts +16 -0
- package/dist/schema/table-builder.d.ts.map +1 -1
- package/dist/schema/table-builder.js +23 -1
- package/dist/schema/table-builder.js.map +1 -1
- package/package.json +1 -1
- package/dist/query/strategies/jsonb-collection-strategy.d.ts +0 -51
- package/dist/query/strategies/jsonb-collection-strategy.d.ts.map +0 -1
- package/dist/query/strategies/jsonb-collection-strategy.js +0 -210
- package/dist/query/strategies/jsonb-collection-strategy.js.map +0 -1
|
@@ -3,15 +3,34 @@ import { TableBuilder, TableSchema, InferTableType } from '../schema/table-build
|
|
|
3
3
|
import { UnwrapDbColumns, InsertData, ExtractDbColumns } from './db-column';
|
|
4
4
|
import { DbEntity, EntityConstructor } from './entity-base';
|
|
5
5
|
import { DbModelConfig } from './model-config';
|
|
6
|
-
import { Condition, SqlFragment } from '../query/conditions';
|
|
6
|
+
import { Condition, SqlFragment, UnwrapSelection, FieldRef } from '../query/conditions';
|
|
7
7
|
import { ResolveCollectionResults, SelectQueryBuilder, QueryBuilder } from '../query/query-builder';
|
|
8
8
|
import { InferRowType } from '../schema/row-type';
|
|
9
9
|
import { DbSchemaManager } from '../migration/db-schema-manager';
|
|
10
10
|
import { DbSequence, SequenceConfig } from '../schema/sequence-builder';
|
|
11
|
+
import type { DbCte } from '../query/cte-builder';
|
|
11
12
|
/**
|
|
12
13
|
* Collection aggregation strategy type
|
|
13
14
|
*/
|
|
14
|
-
export type CollectionStrategyType = '
|
|
15
|
+
export type CollectionStrategyType = 'cte' | 'temptable' | 'lateral';
|
|
16
|
+
/**
|
|
17
|
+
* Order direction for orderBy clauses
|
|
18
|
+
*/
|
|
19
|
+
export type OrderDirection = 'ASC' | 'DESC';
|
|
20
|
+
/**
|
|
21
|
+
* A single field that can be used in orderBy.
|
|
22
|
+
* At runtime, this is analyzed to extract the column reference.
|
|
23
|
+
* The type is intentionally broad to support various usage patterns.
|
|
24
|
+
*/
|
|
25
|
+
export type OrderableField<T = unknown> = T;
|
|
26
|
+
/**
|
|
27
|
+
* Order by specification with direction - a tuple of [field, direction]
|
|
28
|
+
*/
|
|
29
|
+
export type OrderByTuple<T = unknown> = [T, OrderDirection];
|
|
30
|
+
/**
|
|
31
|
+
* Order by selector result - can be a single field, array of fields, or array of [field, direction] tuples
|
|
32
|
+
*/
|
|
33
|
+
export type OrderByResult<T = unknown> = T | T[] | Array<OrderByTuple<T>>;
|
|
15
34
|
/**
|
|
16
35
|
* Query execution options
|
|
17
36
|
*/
|
|
@@ -24,7 +43,7 @@ export interface QueryOptions {
|
|
|
24
43
|
logExecutionTime?: boolean;
|
|
25
44
|
/** Log query parameters */
|
|
26
45
|
logParameters?: boolean;
|
|
27
|
-
/** Collection aggregation strategy (default: '
|
|
46
|
+
/** Collection aggregation strategy (default: 'lateral') */
|
|
28
47
|
collectionStrategy?: CollectionStrategyType;
|
|
29
48
|
/**
|
|
30
49
|
* Disable automatic mapper transformations (fromDriver/toDriver).
|
|
@@ -125,6 +144,79 @@ export interface UpsertConfig {
|
|
|
125
144
|
*/
|
|
126
145
|
updateColumnFilter?: (columnName: string) => boolean;
|
|
127
146
|
}
|
|
147
|
+
/**
|
|
148
|
+
* Returning clause configuration
|
|
149
|
+
* - undefined: no RETURNING clause (returns void)
|
|
150
|
+
* - true: return all columns
|
|
151
|
+
* - selector function: return selected columns
|
|
152
|
+
*/
|
|
153
|
+
export type ReturningConfig<TEntity, TResult = unknown> = undefined | true | ((entity: TEntity) => TResult);
|
|
154
|
+
/**
|
|
155
|
+
* Helper type to infer the result type based on ReturningConfig
|
|
156
|
+
* Note: Uses conditional types to properly infer return types
|
|
157
|
+
*/
|
|
158
|
+
export type ReturningResult<TEntity, TReturning> = TReturning extends undefined ? void : TReturning extends true ? TEntity : TReturning extends (entity: TEntity) => infer R ? R : TReturning extends (...args: any[]) => infer R ? R : never;
|
|
159
|
+
/**
|
|
160
|
+
* Base type for returning option - used in method signatures
|
|
161
|
+
*/
|
|
162
|
+
export type ReturningOption<TEntity> = undefined | true | ((entity: TEntity) => any);
|
|
163
|
+
/**
|
|
164
|
+
* Fluent insert operation that can be awaited directly or chained with .returning()
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```typescript
|
|
168
|
+
* // No returning (default) - returns void
|
|
169
|
+
* await db.users.insert({ username: 'alice' });
|
|
170
|
+
*
|
|
171
|
+
* // With returning() - returns full entity
|
|
172
|
+
* const user = await db.users.insert({ username: 'alice' }).returning();
|
|
173
|
+
*
|
|
174
|
+
* // With returning(selector) - returns selected columns
|
|
175
|
+
* const { id } = await db.users.insert({ username: 'alice' }).returning(u => ({ id: u.id }));
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
export interface FluentInsert<TEntity extends DbEntity> extends PromiseLike<void> {
|
|
179
|
+
/** Return all columns from the inserted row */
|
|
180
|
+
returning(): PromiseLike<UnwrapDbColumns<TEntity>>;
|
|
181
|
+
/** Return selected columns from the inserted row */
|
|
182
|
+
returning<TResult>(selector: (entity: EntityQuery<TEntity>) => TResult): PromiseLike<UnwrapDbColumns<TResult>>;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Fluent insert many operation
|
|
186
|
+
*/
|
|
187
|
+
export interface FluentInsertMany<TEntity extends DbEntity> extends PromiseLike<void> {
|
|
188
|
+
/** Return all columns from the inserted rows */
|
|
189
|
+
returning(): PromiseLike<UnwrapDbColumns<TEntity>[]>;
|
|
190
|
+
/** Return selected columns from the inserted rows */
|
|
191
|
+
returning<TResult>(selector: (entity: EntityQuery<TEntity>) => TResult): PromiseLike<UnwrapDbColumns<TResult>[]>;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Fluent update operation
|
|
195
|
+
*/
|
|
196
|
+
export interface FluentUpdate<TEntity extends DbEntity> extends PromiseLike<void> {
|
|
197
|
+
/** Return all columns from the updated rows */
|
|
198
|
+
returning(): PromiseLike<UnwrapDbColumns<TEntity>[]>;
|
|
199
|
+
/** Return selected columns from the updated rows */
|
|
200
|
+
returning<TResult>(selector: (entity: EntityQuery<TEntity>) => TResult): PromiseLike<UnwrapDbColumns<TResult>[]>;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Fluent bulk update operation
|
|
204
|
+
*/
|
|
205
|
+
export interface FluentBulkUpdate<TEntity extends DbEntity> extends PromiseLike<void> {
|
|
206
|
+
/** Return all columns from the updated rows */
|
|
207
|
+
returning(): PromiseLike<UnwrapDbColumns<TEntity>[]>;
|
|
208
|
+
/** Return selected columns from the updated rows */
|
|
209
|
+
returning<TResult>(selector: (entity: EntityQuery<TEntity>) => TResult): PromiseLike<UnwrapDbColumns<TResult>[]>;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Fluent upsert operation
|
|
213
|
+
*/
|
|
214
|
+
export interface FluentUpsert<TEntity extends DbEntity> extends PromiseLike<void> {
|
|
215
|
+
/** Return all columns from the upserted rows */
|
|
216
|
+
returning(): PromiseLike<UnwrapDbColumns<TEntity>[]>;
|
|
217
|
+
/** Return selected columns from the upserted rows */
|
|
218
|
+
returning<TResult>(selector: (entity: EntityQuery<TEntity>) => TResult): PromiseLike<UnwrapDbColumns<TResult>[]>;
|
|
219
|
+
}
|
|
128
220
|
/**
|
|
129
221
|
* Insert builder for upsert operations
|
|
130
222
|
*/
|
|
@@ -141,10 +233,6 @@ export declare class InsertBuilder<TSchema extends TableSchema> {
|
|
|
141
233
|
private setWhereClause?;
|
|
142
234
|
private overridingSystemValue;
|
|
143
235
|
constructor(schema: TSchema, client: DatabaseClient, executor?: QueryExecutor | undefined);
|
|
144
|
-
/**
|
|
145
|
-
* Get qualified table name with schema prefix if specified
|
|
146
|
-
*/
|
|
147
|
-
private getQualifiedTableName;
|
|
148
236
|
/**
|
|
149
237
|
* Set the values to insert (single row or multiple rows)
|
|
150
238
|
*/
|
|
@@ -205,24 +293,29 @@ export declare class TableAccessor<TBuilder extends TableBuilder<any>> {
|
|
|
205
293
|
withQueryOptions(options: QueryOptions): TableAccessor<TBuilder>;
|
|
206
294
|
/**
|
|
207
295
|
* Start a select query with automatic type inference
|
|
296
|
+
* UnwrapSelection extracts the value types from SqlFragment<T> expressions
|
|
208
297
|
*/
|
|
209
|
-
select<TSelection>(selector: (row: InferRowType<TBuilder>) => TSelection): SelectQueryBuilder<TSelection
|
|
298
|
+
select<TSelection>(selector: (row: InferRowType<TBuilder>) => TSelection): SelectQueryBuilder<UnwrapSelection<TSelection>>;
|
|
210
299
|
/**
|
|
211
300
|
* Add WHERE condition before select
|
|
212
301
|
*/
|
|
213
302
|
where(condition: (row: InferRowType<TBuilder>) => Condition): QueryBuilder<TableSchema, InferRowType<TBuilder>>;
|
|
303
|
+
/**
|
|
304
|
+
* Add CTEs (Common Table Expressions) to the query
|
|
305
|
+
*/
|
|
306
|
+
with(...ctes: DbCte<any>[]): SelectQueryBuilder<InferRowType<TBuilder>>;
|
|
214
307
|
/**
|
|
215
308
|
* Left join with another table and selector
|
|
216
309
|
*/
|
|
217
310
|
leftJoin<TRight, TSelection>(rightTable: {
|
|
218
311
|
_getSchema: () => TableSchema;
|
|
219
|
-
} | import('../query/subquery').Subquery<TRight, 'table'>, condition: (left: InferRowType<TBuilder>, right: TRight) => Condition, selector: (left: InferRowType<TBuilder>, right: TRight) => TSelection, alias?: string): SelectQueryBuilder<TSelection
|
|
312
|
+
} | import('../query/subquery').Subquery<TRight, 'table'>, condition: (left: InferRowType<TBuilder>, right: TRight) => Condition, selector: (left: InferRowType<TBuilder>, right: TRight) => TSelection, alias?: string): SelectQueryBuilder<UnwrapSelection<TSelection>>;
|
|
220
313
|
/**
|
|
221
314
|
* Inner join with another table or subquery and selector
|
|
222
315
|
*/
|
|
223
316
|
innerJoin<TRight, TSelection>(rightTable: {
|
|
224
317
|
_getSchema: () => TableSchema;
|
|
225
|
-
} | import('../query/subquery').Subquery<TRight, 'table'>, condition: (left: InferRowType<TBuilder>, right: TRight) => Condition, selector: (left: InferRowType<TBuilder>, right: TRight) => TSelection, alias?: string): SelectQueryBuilder<TSelection
|
|
318
|
+
} | import('../query/subquery').Subquery<TRight, 'table'>, condition: (left: InferRowType<TBuilder>, right: TRight) => Condition, selector: (left: InferRowType<TBuilder>, right: TRight) => TSelection, alias?: string): SelectQueryBuilder<UnwrapSelection<TSelection>>;
|
|
226
319
|
/**
|
|
227
320
|
* Get table schema (internal use for joins)
|
|
228
321
|
*/
|
|
@@ -235,10 +328,6 @@ export declare class TableAccessor<TBuilder extends TableBuilder<any>> {
|
|
|
235
328
|
* Get table name
|
|
236
329
|
*/
|
|
237
330
|
getTableName(): string;
|
|
238
|
-
/**
|
|
239
|
-
* Get qualified table name with schema prefix if specified
|
|
240
|
-
*/
|
|
241
|
-
private getQualifiedTableName;
|
|
242
331
|
/**
|
|
243
332
|
* Insert a row
|
|
244
333
|
*/
|
|
@@ -365,11 +454,52 @@ export type EntityUpsertConfig<TEntity extends DbEntity> = {
|
|
|
365
454
|
*/
|
|
366
455
|
updateColumnFilter?: (columnName: string) => boolean;
|
|
367
456
|
};
|
|
457
|
+
/**
|
|
458
|
+
* Type helper to detect if a type is a class instance (has prototype methods)
|
|
459
|
+
* vs a plain data object. Used to prevent Date, Map, Set, etc. from being
|
|
460
|
+
* treated as DbEntity.
|
|
461
|
+
* Excludes DbColumn and SqlFragment which have valueOf but are not value types.
|
|
462
|
+
*/
|
|
463
|
+
type IsClassInstance<T> = T extends {
|
|
464
|
+
__isDbColumn: true;
|
|
465
|
+
} ? false : T extends SqlFragment<any> ? false : T extends {
|
|
466
|
+
valueOf(): infer V;
|
|
467
|
+
} ? V extends T ? true : V extends number | string | boolean | bigint | symbol ? true : false : false;
|
|
468
|
+
/**
|
|
469
|
+
* Check for types with known class method signatures
|
|
470
|
+
*/
|
|
471
|
+
type HasClassMethods<T> = T extends {
|
|
472
|
+
getTime(): number;
|
|
473
|
+
} ? true : T extends {
|
|
474
|
+
size: number;
|
|
475
|
+
has(value: any): boolean;
|
|
476
|
+
} ? true : T extends {
|
|
477
|
+
byteLength: number;
|
|
478
|
+
} ? true : T extends {
|
|
479
|
+
then(onfulfilled?: any): any;
|
|
480
|
+
} ? true : T extends {
|
|
481
|
+
message: string;
|
|
482
|
+
name: string;
|
|
483
|
+
} ? true : T extends {
|
|
484
|
+
exec(string: string): any;
|
|
485
|
+
} ? true : false;
|
|
486
|
+
/**
|
|
487
|
+
* Combined check for value types that should not be treated as DbEntity
|
|
488
|
+
*/
|
|
489
|
+
type IsValueType<T> = IsClassInstance<T> extends true ? true : HasClassMethods<T> extends true ? true : false;
|
|
490
|
+
/**
|
|
491
|
+
* Type helper to convert plain object values to FieldRefs for use in conditions
|
|
492
|
+
* This is used when TSelection is not a DbEntity but needs to be used in where/join conditions
|
|
493
|
+
*/
|
|
494
|
+
type ToFieldRefs<T> = T extends object ? IsValueType<T> extends true ? FieldRef<string, T> : {
|
|
495
|
+
[K in keyof T]: FieldRef<string, T[K]>;
|
|
496
|
+
} : FieldRef<string, T>;
|
|
368
497
|
/**
|
|
369
498
|
* Type helper to build entity query type with navigation support
|
|
499
|
+
* Preserves class instances (Date, Map, Set, etc.) as-is without recursively mapping them
|
|
370
500
|
*/
|
|
371
501
|
export type EntityQuery<TEntity extends DbEntity> = {
|
|
372
|
-
[K in keyof TEntity]: TEntity[K] extends (infer U)[] | undefined ? U extends DbEntity ? EntityCollectionQuery<U> : TEntity[K] : TEntity[K] extends DbEntity | undefined ? EntityQuery<NonNullable<TEntity[K]>> : TEntity[K];
|
|
502
|
+
[K in keyof TEntity]: TEntity[K] extends (infer U)[] | undefined ? U extends DbEntity ? EntityCollectionQuery<U> : TEntity[K] : IsValueType<NonNullable<TEntity[K]>> extends true ? TEntity[K] : TEntity[K] extends DbEntity | undefined ? EntityQuery<NonNullable<TEntity[K]>> : TEntity[K];
|
|
373
503
|
};
|
|
374
504
|
/**
|
|
375
505
|
* Collection query builder type for navigation collections
|
|
@@ -377,10 +507,10 @@ export type EntityQuery<TEntity extends DbEntity> = {
|
|
|
377
507
|
export interface EntityCollectionQuery<TEntity extends DbEntity> {
|
|
378
508
|
select<TSelection>(selector: (item: EntityQuery<TEntity>) => TSelection): EntityCollectionQueryWithSelect<TEntity, TSelection>;
|
|
379
509
|
selectDistinct<TSelection>(selector: (item: EntityQuery<TEntity>) => TSelection): EntityCollectionQueryWithSelect<TEntity, TSelection>;
|
|
380
|
-
where(condition: (item: EntityQuery<TEntity>) =>
|
|
381
|
-
orderBy(selector: (item: EntityQuery<TEntity>) =>
|
|
382
|
-
orderBy(selector: (item: EntityQuery<TEntity>) =>
|
|
383
|
-
orderBy(selector: (item: EntityQuery<TEntity>) => Array<[
|
|
510
|
+
where(condition: (item: EntityQuery<TEntity>) => Condition): this;
|
|
511
|
+
orderBy<T>(selector: (item: EntityQuery<TEntity>) => T): this;
|
|
512
|
+
orderBy<T>(selector: (item: EntityQuery<TEntity>) => T[]): this;
|
|
513
|
+
orderBy<T>(selector: (item: EntityQuery<TEntity>) => Array<[T, OrderDirection]>): this;
|
|
384
514
|
limit(count: number): this;
|
|
385
515
|
offset(count: number): this;
|
|
386
516
|
min<TSelection>(selector: (item: EntityQuery<TEntity>) => TSelection): SqlFragment<number | null>;
|
|
@@ -392,10 +522,10 @@ export interface EntityCollectionQuery<TEntity extends DbEntity> {
|
|
|
392
522
|
toList(asName: string): TEntity[];
|
|
393
523
|
}
|
|
394
524
|
export interface EntityCollectionQueryWithSelect<TEntity extends DbEntity, TSelection> {
|
|
395
|
-
where(condition: (item: EntityQuery<TEntity>) =>
|
|
396
|
-
orderBy(selector: (item: TSelection) =>
|
|
397
|
-
orderBy(selector: (item: TSelection) =>
|
|
398
|
-
orderBy(selector: (item: TSelection) => Array<[
|
|
525
|
+
where(condition: (item: EntityQuery<TEntity>) => Condition): this;
|
|
526
|
+
orderBy<T>(selector: (item: TSelection) => T): this;
|
|
527
|
+
orderBy<T>(selector: (item: TSelection) => T[]): this;
|
|
528
|
+
orderBy<T>(selector: (item: TSelection) => Array<[T, OrderDirection]>): this;
|
|
399
529
|
limit(count: number): this;
|
|
400
530
|
offset(count: number): this;
|
|
401
531
|
min(): Promise<TSelection | null>;
|
|
@@ -406,25 +536,101 @@ export interface EntityCollectionQueryWithSelect<TEntity extends DbEntity, TSele
|
|
|
406
536
|
toStringList(asName?: string): string[];
|
|
407
537
|
toList(asName: string): TSelection[];
|
|
408
538
|
}
|
|
539
|
+
/**
|
|
540
|
+
* Interface for queryable entity collections that can be filtered with .where()
|
|
541
|
+
* Use this type when you need to store a query in a variable and add more .where() conditions.
|
|
542
|
+
*
|
|
543
|
+
* @example
|
|
544
|
+
* ```typescript
|
|
545
|
+
* let query: IEntityQueryable<User> = db.users;
|
|
546
|
+
* if (onlyActive) {
|
|
547
|
+
* query = query.where(u => eq(u.isActive, true));
|
|
548
|
+
* }
|
|
549
|
+
* if (minAge) {
|
|
550
|
+
* query = query.where(u => gte(u.age, minAge));
|
|
551
|
+
* }
|
|
552
|
+
* const results = await query.toList();
|
|
553
|
+
* ```
|
|
554
|
+
*/
|
|
555
|
+
export interface IEntityQueryable<TEntity extends DbEntity> {
|
|
556
|
+
/**
|
|
557
|
+
* Add a WHERE condition. Multiple where() calls are chained with AND logic.
|
|
558
|
+
*/
|
|
559
|
+
where(condition: (entity: EntityQuery<TEntity>) => Condition): IEntityQueryable<TEntity>;
|
|
560
|
+
/**
|
|
561
|
+
* Select specific fields from the entity
|
|
562
|
+
*/
|
|
563
|
+
select<TSelection>(selector: (entity: EntityQuery<TEntity>) => TSelection): EntitySelectQueryBuilder<TEntity, UnwrapSelection<TSelection>>;
|
|
564
|
+
/**
|
|
565
|
+
* Order by field(s)
|
|
566
|
+
*/
|
|
567
|
+
orderBy<T>(selector: (row: EntityQuery<TEntity>) => T): IEntityQueryable<TEntity>;
|
|
568
|
+
orderBy<T>(selector: (row: EntityQuery<TEntity>) => T[]): IEntityQueryable<TEntity>;
|
|
569
|
+
orderBy<T>(selector: (row: EntityQuery<TEntity>) => Array<[T, OrderDirection]>): IEntityQueryable<TEntity>;
|
|
570
|
+
/**
|
|
571
|
+
* Limit results
|
|
572
|
+
*/
|
|
573
|
+
limit(count: number): IEntityQueryable<TEntity>;
|
|
574
|
+
/**
|
|
575
|
+
* Offset results
|
|
576
|
+
*/
|
|
577
|
+
offset(count: number): IEntityQueryable<TEntity>;
|
|
578
|
+
/**
|
|
579
|
+
* Add CTEs (Common Table Expressions) to the query
|
|
580
|
+
*/
|
|
581
|
+
with(...ctes: import('../query/cte-builder').DbCte<any>[]): IEntityQueryable<TEntity>;
|
|
582
|
+
/**
|
|
583
|
+
* Left join with another table, CTE, or subquery
|
|
584
|
+
*/
|
|
585
|
+
leftJoin<TRight extends DbEntity, TSelection>(rightTable: DbEntityTable<TRight>, condition: (left: EntityQuery<TEntity>, right: EntityQuery<TRight>) => Condition, selector: (left: EntityQuery<TEntity>, right: EntityQuery<TRight>) => TSelection, alias?: string): EntitySelectQueryBuilder<TEntity, UnwrapSelection<TSelection>>;
|
|
586
|
+
leftJoin<TRight extends Record<string, any>, TSelection>(rightTable: import('../query/subquery').Subquery<TRight, 'table'>, condition: (left: EntityQuery<TEntity>, right: TRight) => Condition, selector: (left: EntityQuery<TEntity>, right: TRight) => TSelection, alias: string): EntitySelectQueryBuilder<TEntity, UnwrapSelection<TSelection>>;
|
|
587
|
+
leftJoin<TRight extends Record<string, any>, TSelection>(rightTable: import('../query/cte-builder').DbCte<TRight>, condition: (left: EntityQuery<TEntity>, right: ToFieldRefs<TRight>) => Condition, selector: (left: EntityQuery<TEntity>, right: TRight) => TSelection): EntitySelectQueryBuilder<TEntity, UnwrapSelection<TSelection>>;
|
|
588
|
+
/**
|
|
589
|
+
* Inner join with another table, CTE, or subquery
|
|
590
|
+
*/
|
|
591
|
+
innerJoin<TRight extends DbEntity, TSelection>(rightTable: DbEntityTable<TRight>, condition: (left: EntityQuery<TEntity>, right: EntityQuery<TRight>) => Condition, selector: (left: EntityQuery<TEntity>, right: EntityQuery<TRight>) => TSelection, alias?: string): EntitySelectQueryBuilder<TEntity, UnwrapSelection<TSelection>>;
|
|
592
|
+
innerJoin<TRight extends Record<string, any>, TSelection>(rightTable: import('../query/subquery').Subquery<TRight, 'table'>, condition: (left: EntityQuery<TEntity>, right: TRight) => Condition, selector: (left: EntityQuery<TEntity>, right: TRight) => TSelection, alias: string): EntitySelectQueryBuilder<TEntity, UnwrapSelection<TSelection>>;
|
|
593
|
+
innerJoin<TRight extends Record<string, any>, TSelection>(rightTable: import('../query/cte-builder').DbCte<TRight>, condition: (left: EntityQuery<TEntity>, right: ToFieldRefs<TRight>) => Condition, selector: (left: EntityQuery<TEntity>, right: TRight) => TSelection): EntitySelectQueryBuilder<TEntity, UnwrapSelection<TSelection>>;
|
|
594
|
+
/**
|
|
595
|
+
* Execute query and return all results
|
|
596
|
+
*/
|
|
597
|
+
toList(): Promise<UnwrapDbColumns<TEntity>[]>;
|
|
598
|
+
/**
|
|
599
|
+
* Execute query and return first result
|
|
600
|
+
*/
|
|
601
|
+
first(): Promise<UnwrapDbColumns<TEntity>>;
|
|
602
|
+
/**
|
|
603
|
+
* Execute query and return first result or null if not found
|
|
604
|
+
*/
|
|
605
|
+
firstOrDefault(): Promise<UnwrapDbColumns<TEntity> | null>;
|
|
606
|
+
/**
|
|
607
|
+
* Count matching records
|
|
608
|
+
*/
|
|
609
|
+
count(): Promise<number>;
|
|
610
|
+
}
|
|
409
611
|
/**
|
|
410
612
|
* Strongly-typed query builder for entities
|
|
411
|
-
* Results automatically unwrap DbColumn<T> to T
|
|
613
|
+
* Results automatically unwrap DbColumn<T> to T and SqlFragment<T> to T
|
|
412
614
|
*/
|
|
413
615
|
export interface EntitySelectQueryBuilder<TEntity extends DbEntity, TSelection> {
|
|
414
|
-
select<TNewSelection>(selector: (entity: TSelection extends DbEntity ? EntityQuery<TSelection> : TSelection) => TNewSelection): EntitySelectQueryBuilder<TEntity, TNewSelection
|
|
415
|
-
selectDistinct<TNewSelection>(selector: (entity: TSelection extends DbEntity ? EntityQuery<TSelection> : TSelection) => TNewSelection): EntitySelectQueryBuilder<TEntity, TNewSelection
|
|
416
|
-
where(condition: (entity: TSelection extends DbEntity ? EntityQuery<TSelection> : TSelection) =>
|
|
417
|
-
orderBy(selector: (row: TSelection) =>
|
|
418
|
-
orderBy(selector: (row: TSelection) =>
|
|
419
|
-
orderBy(selector: (row: TSelection) => Array<[
|
|
616
|
+
select<TNewSelection>(selector: (entity: TSelection extends DbEntity ? EntityQuery<TSelection> : TSelection) => TNewSelection): EntitySelectQueryBuilder<TEntity, UnwrapSelection<TNewSelection>>;
|
|
617
|
+
selectDistinct<TNewSelection>(selector: (entity: TSelection extends DbEntity ? EntityQuery<TSelection> : TSelection) => TNewSelection): EntitySelectQueryBuilder<TEntity, UnwrapSelection<TNewSelection>>;
|
|
618
|
+
where(condition: (entity: TSelection extends DbEntity ? EntityQuery<TSelection> : ToFieldRefs<TSelection>) => Condition): EntitySelectQueryBuilder<TEntity, TSelection>;
|
|
619
|
+
orderBy<T>(selector: (row: TSelection extends DbEntity ? EntityQuery<TSelection> : TSelection) => T): EntitySelectQueryBuilder<TEntity, TSelection>;
|
|
620
|
+
orderBy<T>(selector: (row: TSelection extends DbEntity ? EntityQuery<TSelection> : TSelection) => T[]): EntitySelectQueryBuilder<TEntity, TSelection>;
|
|
621
|
+
orderBy<T>(selector: (row: TSelection extends DbEntity ? EntityQuery<TSelection> : TSelection) => Array<[T, OrderDirection]>): EntitySelectQueryBuilder<TEntity, TSelection>;
|
|
420
622
|
limit(count: number): EntitySelectQueryBuilder<TEntity, TSelection>;
|
|
421
623
|
offset(count: number): EntitySelectQueryBuilder<TEntity, TSelection>;
|
|
422
624
|
count(): Promise<number>;
|
|
423
625
|
first(): Promise<ResolveCollectionResults<TSelection>>;
|
|
424
626
|
firstOrDefault(): Promise<ResolveCollectionResults<TSelection> | null>;
|
|
425
627
|
firstOrThrow(): Promise<ResolveCollectionResults<TSelection>>;
|
|
426
|
-
leftJoin<TRight extends
|
|
427
|
-
|
|
628
|
+
leftJoin<TRight extends Record<string, any>, TNewSelection>(rightTable: import('../query/cte-builder').DbCte<TRight>, condition: (left: TSelection extends DbEntity ? EntityQuery<TSelection> : ToFieldRefs<TSelection>, right: ToFieldRefs<TRight>) => Condition, selector: (left: TSelection extends DbEntity ? EntityQuery<TSelection> : TSelection, right: TRight) => TNewSelection): EntitySelectQueryBuilder<TEntity, UnwrapSelection<TNewSelection>>;
|
|
629
|
+
leftJoin<TRight extends Record<string, any>, TNewSelection>(rightTable: import('../query/subquery').Subquery<TRight, 'table'>, condition: (left: TSelection extends DbEntity ? EntityQuery<TSelection> : ToFieldRefs<TSelection>, right: ToFieldRefs<TRight>) => Condition, selector: (left: TSelection extends DbEntity ? EntityQuery<TSelection> : TSelection, right: TRight) => TNewSelection, alias: string): EntitySelectQueryBuilder<TEntity, UnwrapSelection<TNewSelection>>;
|
|
630
|
+
leftJoin<TRight extends DbEntity, TNewSelection>(rightTable: DbEntityTable<TRight>, condition: (left: TSelection extends DbEntity ? EntityQuery<TSelection> : ToFieldRefs<TSelection>, right: EntityQuery<TRight>) => Condition, selector: (left: TSelection extends DbEntity ? EntityQuery<TSelection> : TSelection, right: EntityQuery<TRight>) => TNewSelection, alias?: string): EntitySelectQueryBuilder<TEntity, UnwrapSelection<TNewSelection>>;
|
|
631
|
+
innerJoin<TRight extends Record<string, any>, TNewSelection>(rightTable: import('../query/cte-builder').DbCte<TRight>, condition: (left: TSelection extends DbEntity ? EntityQuery<TSelection> : ToFieldRefs<TSelection>, right: ToFieldRefs<TRight>) => Condition, selector: (left: TSelection extends DbEntity ? EntityQuery<TSelection> : TSelection, right: TRight) => TNewSelection): EntitySelectQueryBuilder<TEntity, UnwrapSelection<TNewSelection>>;
|
|
632
|
+
innerJoin<TRight extends Record<string, any>, TNewSelection>(rightTable: import('../query/subquery').Subquery<TRight, 'table'>, condition: (left: TSelection extends DbEntity ? EntityQuery<TSelection> : ToFieldRefs<TSelection>, right: ToFieldRefs<TRight>) => Condition, selector: (left: TSelection extends DbEntity ? EntityQuery<TSelection> : TSelection, right: TRight) => TNewSelection, alias: string): EntitySelectQueryBuilder<TEntity, UnwrapSelection<TNewSelection>>;
|
|
633
|
+
innerJoin<TRight extends DbEntity, TNewSelection>(rightTable: DbEntityTable<TRight>, condition: (left: TSelection extends DbEntity ? EntityQuery<TSelection> : ToFieldRefs<TSelection>, right: EntityQuery<TRight>) => Condition, selector: (left: TSelection extends DbEntity ? EntityQuery<TSelection> : TSelection, right: EntityQuery<TRight>) => TNewSelection, alias?: string): EntitySelectQueryBuilder<TEntity, UnwrapSelection<TNewSelection>>;
|
|
428
634
|
groupBy<TGroupingKey>(selector: (entity: TSelection extends DbEntity ? EntityQuery<TSelection> : TSelection) => TGroupingKey): import('../query/grouped-query').GroupedQueryBuilder<TSelection extends DbEntity ? EntityQuery<TSelection> : TSelection, TGroupingKey>;
|
|
429
635
|
min<TResult = TSelection>(selector?: (entity: TSelection extends DbEntity ? EntityQuery<TSelection> : TSelection) => TResult): Promise<TResult | null>;
|
|
430
636
|
max<TResult = TSelection>(selector?: (entity: TSelection extends DbEntity ? EntityQuery<TSelection> : TSelection) => TResult): Promise<TResult | null>;
|
|
@@ -514,6 +720,15 @@ export declare class DbEntityTable<TEntity extends DbEntity> {
|
|
|
514
720
|
* Select all records - returns full entities with unwrapped DbColumns
|
|
515
721
|
*/
|
|
516
722
|
toList(): Promise<UnwrapDbColumns<TEntity>[]>;
|
|
723
|
+
/**
|
|
724
|
+
* Get first record
|
|
725
|
+
* @throws Error if no records exist
|
|
726
|
+
*/
|
|
727
|
+
first(): Promise<UnwrapDbColumns<TEntity>>;
|
|
728
|
+
/**
|
|
729
|
+
* Get first record or null if none exist
|
|
730
|
+
*/
|
|
731
|
+
firstOrDefault(): Promise<UnwrapDbColumns<TEntity> | null>;
|
|
517
732
|
/**
|
|
518
733
|
* Count all records
|
|
519
734
|
*/
|
|
@@ -521,21 +736,22 @@ export declare class DbEntityTable<TEntity extends DbEntity> {
|
|
|
521
736
|
/**
|
|
522
737
|
* Order by field(s)
|
|
523
738
|
*/
|
|
524
|
-
orderBy(selector: (row: TEntity) =>
|
|
525
|
-
orderBy(selector: (row: TEntity) =>
|
|
526
|
-
orderBy(selector: (row: TEntity) => Array<[
|
|
739
|
+
orderBy<T>(selector: (row: EntityQuery<TEntity>) => T): IEntityQueryable<TEntity>;
|
|
740
|
+
orderBy<T>(selector: (row: EntityQuery<TEntity>) => T[]): IEntityQueryable<TEntity>;
|
|
741
|
+
orderBy<T>(selector: (row: EntityQuery<TEntity>) => Array<[T, OrderDirection]>): IEntityQueryable<TEntity>;
|
|
527
742
|
/**
|
|
528
743
|
* Limit results
|
|
529
744
|
*/
|
|
530
|
-
limit(count: number):
|
|
745
|
+
limit(count: number): IEntityQueryable<TEntity>;
|
|
531
746
|
/**
|
|
532
747
|
* Offset results
|
|
533
748
|
*/
|
|
534
|
-
offset(count: number):
|
|
749
|
+
offset(count: number): IEntityQueryable<TEntity>;
|
|
535
750
|
/**
|
|
536
751
|
* Select query
|
|
752
|
+
* UnwrapSelection extracts the value types from SqlFragment<T> expressions
|
|
537
753
|
*/
|
|
538
|
-
select<TSelection>(selector: (entity: EntityQuery<TEntity>) => TSelection): EntitySelectQueryBuilder<TEntity, TSelection
|
|
754
|
+
select<TSelection>(selector: (entity: EntityQuery<TEntity>) => TSelection): EntitySelectQueryBuilder<TEntity, UnwrapSelection<TSelection>>;
|
|
539
755
|
/**
|
|
540
756
|
* Select distinct
|
|
541
757
|
*/
|
|
@@ -543,37 +759,133 @@ export declare class DbEntityTable<TEntity extends DbEntity> {
|
|
|
543
759
|
/**
|
|
544
760
|
* Where query - returns all columns by default
|
|
545
761
|
*/
|
|
546
|
-
where(condition: (entity: EntityQuery<TEntity>) =>
|
|
762
|
+
where(condition: (entity: EntityQuery<TEntity>) => Condition): IEntityQueryable<TEntity>;
|
|
547
763
|
/**
|
|
548
|
-
*
|
|
764
|
+
* Add CTEs (Common Table Expressions) to the query
|
|
549
765
|
*/
|
|
550
|
-
|
|
766
|
+
with(...ctes: DbCte<any>[]): IEntityQueryable<TEntity>;
|
|
551
767
|
/**
|
|
552
|
-
*
|
|
768
|
+
* Left join with another table (DbEntity)
|
|
769
|
+
*/
|
|
770
|
+
leftJoin<TRight extends DbEntity, TSelection>(rightTable: DbEntityTable<TRight>, condition: (left: EntityQuery<TEntity>, right: EntityQuery<TRight>) => Condition, selector: (left: EntityQuery<TEntity>, right: EntityQuery<TRight>) => TSelection, alias?: string): EntitySelectQueryBuilder<TEntity, UnwrapSelection<TSelection>>;
|
|
771
|
+
/**
|
|
772
|
+
* Left join with a subquery (plain object result, not DbEntity)
|
|
773
|
+
*/
|
|
774
|
+
leftJoin<TRight extends Record<string, any>, TSelection>(rightTable: import('../query/subquery').Subquery<TRight, 'table'>, condition: (left: EntityQuery<TEntity>, right: TRight) => Condition, selector: (left: EntityQuery<TEntity>, right: TRight) => TSelection, alias: string): EntitySelectQueryBuilder<TEntity, UnwrapSelection<TSelection>>;
|
|
775
|
+
/**
|
|
776
|
+
* Left join with a CTE
|
|
777
|
+
*/
|
|
778
|
+
leftJoin<TRight extends Record<string, any>, TSelection>(rightTable: import('../query/cte-builder').DbCte<TRight>, condition: (left: EntityQuery<TEntity>, right: ToFieldRefs<TRight>) => Condition, selector: (left: EntityQuery<TEntity>, right: TRight) => TSelection): EntitySelectQueryBuilder<TEntity, UnwrapSelection<TSelection>>;
|
|
779
|
+
/**
|
|
780
|
+
* Inner join with another table (DbEntity)
|
|
553
781
|
*/
|
|
554
|
-
innerJoin<TRight extends DbEntity, TSelection>(rightTable: DbEntityTable<TRight
|
|
782
|
+
innerJoin<TRight extends DbEntity, TSelection>(rightTable: DbEntityTable<TRight>, condition: (left: EntityQuery<TEntity>, right: EntityQuery<TRight>) => Condition, selector: (left: EntityQuery<TEntity>, right: EntityQuery<TRight>) => TSelection, alias?: string): EntitySelectQueryBuilder<TEntity, UnwrapSelection<TSelection>>;
|
|
783
|
+
/**
|
|
784
|
+
* Inner join with a subquery (plain object result, not DbEntity)
|
|
785
|
+
*/
|
|
786
|
+
innerJoin<TRight extends Record<string, any>, TSelection>(rightTable: import('../query/subquery').Subquery<TRight, 'table'>, condition: (left: EntityQuery<TEntity>, right: TRight) => Condition, selector: (left: EntityQuery<TEntity>, right: TRight) => TSelection, alias: string): EntitySelectQueryBuilder<TEntity, UnwrapSelection<TSelection>>;
|
|
787
|
+
/**
|
|
788
|
+
* Inner join with a CTE
|
|
789
|
+
*/
|
|
790
|
+
innerJoin<TRight extends Record<string, any>, TSelection>(rightTable: import('../query/cte-builder').DbCte<TRight>, condition: (left: EntityQuery<TEntity>, right: ToFieldRefs<TRight>) => Condition, selector: (left: EntityQuery<TEntity>, right: TRight) => TSelection): EntitySelectQueryBuilder<TEntity, UnwrapSelection<TSelection>>;
|
|
555
791
|
/**
|
|
556
792
|
* Insert - accepts only DbColumn properties (excludes navigation properties)
|
|
793
|
+
* Returns a fluent builder that can be awaited directly or chained with .returning()
|
|
794
|
+
*
|
|
795
|
+
* @example
|
|
796
|
+
* ```typescript
|
|
797
|
+
* // No returning (default) - returns void
|
|
798
|
+
* await db.users.insert({ username: 'alice', email: 'alice@test.com' });
|
|
799
|
+
*
|
|
800
|
+
* // With returning() - returns full entity
|
|
801
|
+
* const user = await db.users.insert({ username: 'alice' }).returning();
|
|
802
|
+
*
|
|
803
|
+
* // With returning(selector) - returns selected columns
|
|
804
|
+
* const { id } = await db.users.insert({ username: 'alice' }).returning(u => ({ id: u.id }));
|
|
805
|
+
* ```
|
|
557
806
|
*/
|
|
558
|
-
insert(data: InsertData<TEntity>):
|
|
807
|
+
insert(data: InsertData<TEntity>): FluentInsert<TEntity>;
|
|
559
808
|
/**
|
|
560
809
|
* Insert multiple records
|
|
810
|
+
* Returns a fluent builder that can be awaited directly or chained with .returning()
|
|
811
|
+
*
|
|
812
|
+
* @example
|
|
813
|
+
* ```typescript
|
|
814
|
+
* // No returning (default) - returns void
|
|
815
|
+
* await db.users.insertMany([{ username: 'alice' }, { username: 'bob' }]);
|
|
816
|
+
*
|
|
817
|
+
* // With returning() - returns full entities
|
|
818
|
+
* const users = await db.users.insertMany([{ username: 'alice' }]).returning();
|
|
819
|
+
*
|
|
820
|
+
* // With returning(selector) - returns selected columns
|
|
821
|
+
* const results = await db.users.insertMany([{ username: 'alice' }]).returning(u => ({ id: u.id }));
|
|
822
|
+
* ```
|
|
561
823
|
*/
|
|
562
|
-
insertMany(data: InsertData<TEntity>[]):
|
|
824
|
+
insertMany(data: InsertData<TEntity>[]): FluentInsertMany<TEntity>;
|
|
563
825
|
/**
|
|
564
826
|
* Upsert (insert or update on conflict)
|
|
827
|
+
* Returns a fluent builder that can be awaited directly or chained with .returning()
|
|
828
|
+
*
|
|
829
|
+
* @example
|
|
830
|
+
* ```typescript
|
|
831
|
+
* // No returning (default) - returns void
|
|
832
|
+
* await db.users.upsert([{ username: 'alice' }], { primaryKey: 'username' });
|
|
833
|
+
*
|
|
834
|
+
* // With returning() - returns full entities
|
|
835
|
+
* const users = await db.users.upsert([{ username: 'alice' }], { primaryKey: 'username' }).returning();
|
|
836
|
+
* ```
|
|
565
837
|
*/
|
|
566
|
-
upsert(data: InsertData<TEntity>[], config?: EntityUpsertConfig<TEntity>):
|
|
838
|
+
upsert(data: InsertData<TEntity>[], config?: EntityUpsertConfig<TEntity>): FluentUpsert<TEntity>;
|
|
567
839
|
/**
|
|
568
840
|
* Bulk insert with advanced configuration
|
|
569
841
|
* Supports automatic chunking for large datasets
|
|
842
|
+
* Returns a fluent builder that can be awaited directly or chained with .returning()
|
|
843
|
+
*
|
|
844
|
+
* @example
|
|
845
|
+
* ```typescript
|
|
846
|
+
* // No returning (default) - returns void
|
|
847
|
+
* await db.users.insertBulk([{ username: 'alice' }]);
|
|
848
|
+
*
|
|
849
|
+
* // With returning() - returns full entities
|
|
850
|
+
* const users = await db.users.insertBulk([{ username: 'alice' }]).returning();
|
|
851
|
+
*
|
|
852
|
+
* // With returning(selector) - returns selected columns
|
|
853
|
+
* const results = await db.users.insertBulk([{ username: 'alice' }]).returning(u => ({ id: u.id }));
|
|
854
|
+
*
|
|
855
|
+
* // With options
|
|
856
|
+
* await db.users.insertBulk([{ username: 'alice' }], { chunkSize: 100 });
|
|
857
|
+
* ```
|
|
570
858
|
*/
|
|
571
|
-
insertBulk(value: InsertData<TEntity> | InsertData<TEntity>[],
|
|
859
|
+
insertBulk(value: InsertData<TEntity> | InsertData<TEntity>[], options?: InsertConfig): FluentInsertMany<TEntity>;
|
|
860
|
+
/**
|
|
861
|
+
* Execute a single bulk insert batch
|
|
862
|
+
* @internal
|
|
863
|
+
*/
|
|
864
|
+
private insertBulkSingle;
|
|
572
865
|
/**
|
|
573
866
|
* Upsert with advanced configuration
|
|
574
867
|
* Auto-detects primary keys and supports chunking
|
|
868
|
+
* Returns a fluent builder that can be awaited directly or chained with .returning()
|
|
869
|
+
*
|
|
870
|
+
* @example
|
|
871
|
+
* ```typescript
|
|
872
|
+
* // No returning (default) - returns void
|
|
873
|
+
* await db.users.upsertBulk([{ id: 1, username: 'alice' }], { primaryKey: 'id' });
|
|
874
|
+
*
|
|
875
|
+
* // With returning() - returns full entities
|
|
876
|
+
* const users = await db.users.upsertBulk([{ id: 1, username: 'alice' }]).returning();
|
|
877
|
+
*
|
|
878
|
+
* // With returning(selector) - returns selected columns
|
|
879
|
+
* const results = await db.users.upsertBulk([{ id: 1, username: 'alice' }])
|
|
880
|
+
* .returning(u => ({ id: u.id }));
|
|
881
|
+
* ```
|
|
575
882
|
*/
|
|
576
|
-
upsertBulk(values: InsertData<TEntity>[], config?: EntityUpsertConfig<TEntity>):
|
|
883
|
+
upsertBulk(values: InsertData<TEntity>[], config?: EntityUpsertConfig<TEntity>): FluentUpsert<TEntity>;
|
|
884
|
+
/**
|
|
885
|
+
* Execute a single upsert batch
|
|
886
|
+
* @internal
|
|
887
|
+
*/
|
|
888
|
+
private upsertBulkSingle;
|
|
577
889
|
/**
|
|
578
890
|
* Map database column names back to property names
|
|
579
891
|
*/
|
|
@@ -592,9 +904,65 @@ export declare class DbEntityTable<TEntity extends DbEntity> {
|
|
|
592
904
|
values(data: InsertData<TEntity> | InsertData<TEntity>[]): EntityInsertBuilder<TEntity>;
|
|
593
905
|
/**
|
|
594
906
|
* Update records matching condition
|
|
595
|
-
*
|
|
907
|
+
* Returns a fluent builder that can be awaited directly or chained with .returning()
|
|
908
|
+
*
|
|
909
|
+
* @example
|
|
910
|
+
* ```typescript
|
|
911
|
+
* // No returning (default) - returns void
|
|
912
|
+
* await db.users.update({ age: 30 }, u => eq(u.id, 1));
|
|
913
|
+
*
|
|
914
|
+
* // With returning() - returns full entities
|
|
915
|
+
* const users = await db.users.update({ age: 30 }, u => eq(u.id, 1)).returning();
|
|
916
|
+
*
|
|
917
|
+
* // With returning(selector) - returns selected columns
|
|
918
|
+
* const results = await db.users.update({ age: 30 }, u => eq(u.id, 1))
|
|
919
|
+
* .returning(u => ({ id: u.id, age: u.age }));
|
|
920
|
+
* ```
|
|
596
921
|
*/
|
|
597
|
-
update(data: Partial<InsertData<TEntity>>, condition: (entity: EntityQuery<TEntity>) => Condition):
|
|
922
|
+
update(data: Partial<InsertData<TEntity>>, condition: (entity: EntityQuery<TEntity>) => Condition): FluentUpdate<TEntity>;
|
|
923
|
+
/**
|
|
924
|
+
* Bulk update multiple records efficiently using PostgreSQL VALUES clause
|
|
925
|
+
* Updates records matching primary key(s) with provided data
|
|
926
|
+
* Returns a fluent builder that can be awaited directly or chained with .returning()
|
|
927
|
+
*
|
|
928
|
+
* @param data Array of objects with primary key(s) and columns to update
|
|
929
|
+
* @param config Optional configuration for the bulk update
|
|
930
|
+
*
|
|
931
|
+
* @example
|
|
932
|
+
* ```typescript
|
|
933
|
+
* // No returning (default) - returns void
|
|
934
|
+
* await db.users.bulkUpdate([
|
|
935
|
+
* { id: 1, age: 30 },
|
|
936
|
+
* { id: 2, age: 25 },
|
|
937
|
+
* ]);
|
|
938
|
+
*
|
|
939
|
+
* // With returning() - returns full entities
|
|
940
|
+
* const updated = await db.users.bulkUpdate([{ id: 1, age: 30 }]).returning();
|
|
941
|
+
*
|
|
942
|
+
* // With returning(selector) - returns selected columns
|
|
943
|
+
* const results = await db.users.bulkUpdate([{ id: 1, age: 30 }])
|
|
944
|
+
* .returning(u => ({ id: u.id, age: u.age }));
|
|
945
|
+
*
|
|
946
|
+
* // With custom primary key
|
|
947
|
+
* await db.users.bulkUpdate(
|
|
948
|
+
* [{ username: 'alice', age: 31 }],
|
|
949
|
+
* { primaryKey: 'username' }
|
|
950
|
+
* );
|
|
951
|
+
* ```
|
|
952
|
+
*/
|
|
953
|
+
bulkUpdate(data: Array<Partial<InsertData<TEntity>> & Record<string, any>>, config?: {
|
|
954
|
+
/** Primary key column(s) to match records. Auto-detected if not specified */
|
|
955
|
+
primaryKey?: string | string[];
|
|
956
|
+
/** Chunk size for large batches. Auto-calculated if not specified */
|
|
957
|
+
chunkSize?: number;
|
|
958
|
+
}): FluentBulkUpdate<TEntity>;
|
|
959
|
+
/** Static type map for PostgreSQL type casting - computed once */
|
|
960
|
+
private static readonly PG_TYPE_MAP;
|
|
961
|
+
/**
|
|
962
|
+
* Execute a single bulk update batch
|
|
963
|
+
* @internal
|
|
964
|
+
*/
|
|
965
|
+
private bulkUpdateSingle;
|
|
598
966
|
/**
|
|
599
967
|
* Delete records matching condition
|
|
600
968
|
* Usage: db.users.delete(u => eq(u.id, 1))
|
|
@@ -604,6 +972,16 @@ export declare class DbEntityTable<TEntity extends DbEntity> {
|
|
|
604
972
|
* Create a mock entity for type inference in lambdas
|
|
605
973
|
*/
|
|
606
974
|
private createMockEntity;
|
|
975
|
+
/**
|
|
976
|
+
* Build RETURNING clause SQL based on config
|
|
977
|
+
* @internal
|
|
978
|
+
*/
|
|
979
|
+
private buildReturningClause;
|
|
980
|
+
/**
|
|
981
|
+
* Map row results based on returning config
|
|
982
|
+
* @internal
|
|
983
|
+
*/
|
|
984
|
+
private mapReturningResults;
|
|
607
985
|
}
|
|
608
986
|
/**
|
|
609
987
|
* Base database context with entity-first approach
|
|
@@ -680,4 +1058,5 @@ export declare abstract class DatabaseContext extends DataContext {
|
|
|
680
1058
|
*/
|
|
681
1059
|
protected table<TEntity extends DbEntity>(entityClass: EntityConstructor<TEntity>): DbEntityTable<TEntity>;
|
|
682
1060
|
}
|
|
1061
|
+
export {};
|
|
683
1062
|
//# sourceMappingURL=db-context.d.ts.map
|