relq 1.0.38 → 1.0.39
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.
|
@@ -28,6 +28,22 @@ class ConnectedSelectBuilder {
|
|
|
28
28
|
this.tableName = tableName;
|
|
29
29
|
this.columns = columns;
|
|
30
30
|
this.schemaKey = schemaKey;
|
|
31
|
+
this.setupColumnResolver();
|
|
32
|
+
}
|
|
33
|
+
setupColumnResolver() {
|
|
34
|
+
const internal = this.relq[methods_1.INTERNAL];
|
|
35
|
+
const tableDef = internal.getTableDef(this.schemaKey || this.tableName);
|
|
36
|
+
if (!tableDef) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const tableColumns = tableDef.$columns || tableDef;
|
|
40
|
+
this.builder.setColumnResolver((column) => {
|
|
41
|
+
const columnDef = tableColumns[column];
|
|
42
|
+
if (columnDef) {
|
|
43
|
+
return columnDef.$sqlName || columnDef.$name || camelToSnake(column);
|
|
44
|
+
}
|
|
45
|
+
return camelToSnake(column);
|
|
46
|
+
});
|
|
31
47
|
}
|
|
32
48
|
where(callback) {
|
|
33
49
|
this.builder.where(callback);
|
|
@@ -21,12 +21,47 @@ class SelectBuilder {
|
|
|
21
21
|
distinctOnColumns = [];
|
|
22
22
|
lockingClause;
|
|
23
23
|
unionQueries = [];
|
|
24
|
+
columnResolver;
|
|
24
25
|
constructor(tableName, columns) {
|
|
25
26
|
this.tableName = tableName;
|
|
26
27
|
if (columns) {
|
|
27
28
|
this.selectColumns = Array.isArray(columns) ? columns : [columns];
|
|
28
29
|
}
|
|
29
30
|
}
|
|
31
|
+
setColumnResolver(resolver) {
|
|
32
|
+
this.columnResolver = resolver;
|
|
33
|
+
return this;
|
|
34
|
+
}
|
|
35
|
+
transformConditionColumns(conditions) {
|
|
36
|
+
if (!this.columnResolver) {
|
|
37
|
+
return conditions;
|
|
38
|
+
}
|
|
39
|
+
return conditions.map(cond => {
|
|
40
|
+
if (!cond.column) {
|
|
41
|
+
return cond;
|
|
42
|
+
}
|
|
43
|
+
if (cond.method === 'raw') {
|
|
44
|
+
return cond;
|
|
45
|
+
}
|
|
46
|
+
if (cond.method === 'or' || cond.method === 'and') {
|
|
47
|
+
return {
|
|
48
|
+
...cond,
|
|
49
|
+
values: this.transformConditionColumns(cond.values)
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
if (cond.column.includes('.')) {
|
|
53
|
+
const [tableRef, colName] = cond.column.split('.');
|
|
54
|
+
return {
|
|
55
|
+
...cond,
|
|
56
|
+
column: `${tableRef}.${this.columnResolver(colName)}`
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
...cond,
|
|
61
|
+
column: this.columnResolver(cond.column)
|
|
62
|
+
};
|
|
63
|
+
});
|
|
64
|
+
}
|
|
30
65
|
setTableAlias(alias) {
|
|
31
66
|
this.tableAlias = alias;
|
|
32
67
|
return this;
|
|
@@ -273,18 +308,20 @@ class SelectBuilder {
|
|
|
273
308
|
query += ' ' + structuredJoinSQL;
|
|
274
309
|
}
|
|
275
310
|
if (this.whereConditions.length > 0) {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
311
|
+
let conditions = this.transformConditionColumns(this.whereConditions);
|
|
312
|
+
if (hasJoins) {
|
|
313
|
+
conditions = this.qualifyWhereConditions(conditions, tableRef);
|
|
314
|
+
}
|
|
279
315
|
query += ' WHERE ' + (0, condition_collector_1.buildConditionsSQL)(conditions);
|
|
280
316
|
}
|
|
281
317
|
if (this.groupByColumns.length > 0) {
|
|
282
318
|
query += ' GROUP BY ' + this.groupByColumns.map(col => pg_format_1.default.ident(col)).join(', ');
|
|
283
319
|
}
|
|
284
320
|
if (this.havingConditions.length > 0) {
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
321
|
+
let havingConds = this.transformConditionColumns(this.havingConditions);
|
|
322
|
+
if (hasJoins) {
|
|
323
|
+
havingConds = this.qualifyWhereConditions(havingConds, tableRef);
|
|
324
|
+
}
|
|
288
325
|
query += ' HAVING ' + (0, condition_collector_1.buildConditionsSQL)(havingConds);
|
|
289
326
|
}
|
|
290
327
|
if (this.orderByColumns.length > 0) {
|
|
@@ -336,18 +373,20 @@ class SelectBuilder {
|
|
|
336
373
|
query += ' ' + structuredJoinSQL;
|
|
337
374
|
}
|
|
338
375
|
if (this.whereConditions.length > 0) {
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
376
|
+
let conditions = this.transformConditionColumns(this.whereConditions);
|
|
377
|
+
if (hasJoins) {
|
|
378
|
+
conditions = this.qualifyWhereConditions(conditions, tableRef);
|
|
379
|
+
}
|
|
342
380
|
query += ' WHERE ' + (0, condition_collector_1.buildConditionsSQL)(conditions);
|
|
343
381
|
}
|
|
344
382
|
if (this.groupByColumns.length > 0) {
|
|
345
383
|
query += ' GROUP BY ' + this.groupByColumns.map(col => pg_format_1.default.ident(col)).join(', ');
|
|
346
384
|
}
|
|
347
385
|
if (this.havingConditions.length > 0) {
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
386
|
+
let havingConds = this.transformConditionColumns(this.havingConditions);
|
|
387
|
+
if (hasJoins) {
|
|
388
|
+
havingConds = this.qualifyWhereConditions(havingConds, tableRef);
|
|
389
|
+
}
|
|
351
390
|
query += ' HAVING ' + (0, condition_collector_1.buildConditionsSQL)(havingConds);
|
|
352
391
|
}
|
|
353
392
|
return query;
|
|
@@ -22,6 +22,22 @@ export class ConnectedSelectBuilder {
|
|
|
22
22
|
this.tableName = tableName;
|
|
23
23
|
this.columns = columns;
|
|
24
24
|
this.schemaKey = schemaKey;
|
|
25
|
+
this.setupColumnResolver();
|
|
26
|
+
}
|
|
27
|
+
setupColumnResolver() {
|
|
28
|
+
const internal = this.relq[INTERNAL];
|
|
29
|
+
const tableDef = internal.getTableDef(this.schemaKey || this.tableName);
|
|
30
|
+
if (!tableDef) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const tableColumns = tableDef.$columns || tableDef;
|
|
34
|
+
this.builder.setColumnResolver((column) => {
|
|
35
|
+
const columnDef = tableColumns[column];
|
|
36
|
+
if (columnDef) {
|
|
37
|
+
return columnDef.$sqlName || columnDef.$name || camelToSnake(column);
|
|
38
|
+
}
|
|
39
|
+
return camelToSnake(column);
|
|
40
|
+
});
|
|
25
41
|
}
|
|
26
42
|
where(callback) {
|
|
27
43
|
this.builder.where(callback);
|
|
@@ -15,12 +15,47 @@ export class SelectBuilder {
|
|
|
15
15
|
distinctOnColumns = [];
|
|
16
16
|
lockingClause;
|
|
17
17
|
unionQueries = [];
|
|
18
|
+
columnResolver;
|
|
18
19
|
constructor(tableName, columns) {
|
|
19
20
|
this.tableName = tableName;
|
|
20
21
|
if (columns) {
|
|
21
22
|
this.selectColumns = Array.isArray(columns) ? columns : [columns];
|
|
22
23
|
}
|
|
23
24
|
}
|
|
25
|
+
setColumnResolver(resolver) {
|
|
26
|
+
this.columnResolver = resolver;
|
|
27
|
+
return this;
|
|
28
|
+
}
|
|
29
|
+
transformConditionColumns(conditions) {
|
|
30
|
+
if (!this.columnResolver) {
|
|
31
|
+
return conditions;
|
|
32
|
+
}
|
|
33
|
+
return conditions.map(cond => {
|
|
34
|
+
if (!cond.column) {
|
|
35
|
+
return cond;
|
|
36
|
+
}
|
|
37
|
+
if (cond.method === 'raw') {
|
|
38
|
+
return cond;
|
|
39
|
+
}
|
|
40
|
+
if (cond.method === 'or' || cond.method === 'and') {
|
|
41
|
+
return {
|
|
42
|
+
...cond,
|
|
43
|
+
values: this.transformConditionColumns(cond.values)
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
if (cond.column.includes('.')) {
|
|
47
|
+
const [tableRef, colName] = cond.column.split('.');
|
|
48
|
+
return {
|
|
49
|
+
...cond,
|
|
50
|
+
column: `${tableRef}.${this.columnResolver(colName)}`
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
...cond,
|
|
55
|
+
column: this.columnResolver(cond.column)
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
}
|
|
24
59
|
setTableAlias(alias) {
|
|
25
60
|
this.tableAlias = alias;
|
|
26
61
|
return this;
|
|
@@ -267,18 +302,20 @@ export class SelectBuilder {
|
|
|
267
302
|
query += ' ' + structuredJoinSQL;
|
|
268
303
|
}
|
|
269
304
|
if (this.whereConditions.length > 0) {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
305
|
+
let conditions = this.transformConditionColumns(this.whereConditions);
|
|
306
|
+
if (hasJoins) {
|
|
307
|
+
conditions = this.qualifyWhereConditions(conditions, tableRef);
|
|
308
|
+
}
|
|
273
309
|
query += ' WHERE ' + buildConditionsSQL(conditions);
|
|
274
310
|
}
|
|
275
311
|
if (this.groupByColumns.length > 0) {
|
|
276
312
|
query += ' GROUP BY ' + this.groupByColumns.map(col => format.ident(col)).join(', ');
|
|
277
313
|
}
|
|
278
314
|
if (this.havingConditions.length > 0) {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
315
|
+
let havingConds = this.transformConditionColumns(this.havingConditions);
|
|
316
|
+
if (hasJoins) {
|
|
317
|
+
havingConds = this.qualifyWhereConditions(havingConds, tableRef);
|
|
318
|
+
}
|
|
282
319
|
query += ' HAVING ' + buildConditionsSQL(havingConds);
|
|
283
320
|
}
|
|
284
321
|
if (this.orderByColumns.length > 0) {
|
|
@@ -330,18 +367,20 @@ export class SelectBuilder {
|
|
|
330
367
|
query += ' ' + structuredJoinSQL;
|
|
331
368
|
}
|
|
332
369
|
if (this.whereConditions.length > 0) {
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
370
|
+
let conditions = this.transformConditionColumns(this.whereConditions);
|
|
371
|
+
if (hasJoins) {
|
|
372
|
+
conditions = this.qualifyWhereConditions(conditions, tableRef);
|
|
373
|
+
}
|
|
336
374
|
query += ' WHERE ' + buildConditionsSQL(conditions);
|
|
337
375
|
}
|
|
338
376
|
if (this.groupByColumns.length > 0) {
|
|
339
377
|
query += ' GROUP BY ' + this.groupByColumns.map(col => format.ident(col)).join(', ');
|
|
340
378
|
}
|
|
341
379
|
if (this.havingConditions.length > 0) {
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
380
|
+
let havingConds = this.transformConditionColumns(this.havingConditions);
|
|
381
|
+
if (hasJoins) {
|
|
382
|
+
havingConds = this.qualifyWhereConditions(havingConds, tableRef);
|
|
383
|
+
}
|
|
345
384
|
query += ' HAVING ' + buildConditionsSQL(havingConds);
|
|
346
385
|
}
|
|
347
386
|
return query;
|
package/dist/index.d.ts
CHANGED
|
@@ -1330,10 +1330,23 @@ export declare class SelectBuilder {
|
|
|
1330
1330
|
private distinctOnColumns;
|
|
1331
1331
|
private lockingClause?;
|
|
1332
1332
|
private unionQueries;
|
|
1333
|
+
private columnResolver?;
|
|
1333
1334
|
constructor(tableName: string, columns?: string | Array<string | [
|
|
1334
1335
|
string,
|
|
1335
1336
|
string
|
|
1336
1337
|
]>);
|
|
1338
|
+
/**
|
|
1339
|
+
* Set a column resolver to transform column names (e.g., camelCase to snake_case).
|
|
1340
|
+
* Used by ConnectedSelectBuilder to map TypeScript property names to SQL column names.
|
|
1341
|
+
* @internal
|
|
1342
|
+
*/
|
|
1343
|
+
setColumnResolver(resolver: (column: string) => string): SelectBuilder;
|
|
1344
|
+
/**
|
|
1345
|
+
* Transform column names in conditions using the column resolver.
|
|
1346
|
+
* Recursively handles nested or/and conditions.
|
|
1347
|
+
* @internal
|
|
1348
|
+
*/
|
|
1349
|
+
private transformConditionColumns;
|
|
1337
1350
|
/**
|
|
1338
1351
|
* Set an alias for the main table.
|
|
1339
1352
|
* @internal Used by ConnectedSelectBuilder for self-joins
|
|
@@ -6038,6 +6051,9 @@ export interface JoinManyInternals extends JoinConditionInternals {
|
|
|
6038
6051
|
toWhereSQL(): string;
|
|
6039
6052
|
getInnerJoins(): InnerJoinSpec[];
|
|
6040
6053
|
}
|
|
6054
|
+
type Prettify$1<T> = {
|
|
6055
|
+
[K in keyof T]: T[K];
|
|
6056
|
+
} & {};
|
|
6041
6057
|
/**
|
|
6042
6058
|
* Extract only actual column names from a table type
|
|
6043
6059
|
* Uses $inferSelect if available (Drizzle tables), otherwise keyof
|
|
@@ -6048,10 +6064,11 @@ export type ColumnKeys<T> = T extends {
|
|
|
6048
6064
|
/**
|
|
6049
6065
|
* Pick columns from a table's row type
|
|
6050
6066
|
* Handles both table definitions (with $inferSelect) and plain interfaces
|
|
6067
|
+
* Uses Prettify to flatten the type for better IDE display
|
|
6051
6068
|
*/
|
|
6052
6069
|
export type PickColumns<T, K extends string> = T extends {
|
|
6053
6070
|
$inferSelect: infer TSelect;
|
|
6054
|
-
} ? Pick<TSelect, K & keyof TSelect
|
|
6071
|
+
} ? Prettify$1<Pick<TSelect, K & keyof TSelect>> : Prettify$1<Pick<T, K & keyof T>>;
|
|
6055
6072
|
type ColumnValue$1<T, K extends ColumnKeys<T>> = T extends {
|
|
6056
6073
|
$inferSelect: infer TSelect;
|
|
6057
6074
|
} ? K extends keyof TSelect ? TSelect[K] : unknown : K extends keyof T ? T[K] : unknown;
|
|
@@ -7101,7 +7118,7 @@ export type TableAccessor<TSchema, TRelq> = {
|
|
|
7101
7118
|
} & {
|
|
7102
7119
|
[K in keyof TSchema & string]: ConnectedQueryBuilder<TSchema, TSchema[K]>;
|
|
7103
7120
|
};
|
|
7104
|
-
type Prettify$
|
|
7121
|
+
type Prettify$2<T> = {
|
|
7105
7122
|
[K in keyof T]: T[K];
|
|
7106
7123
|
} & {};
|
|
7107
7124
|
/**
|
|
@@ -7109,9 +7126,9 @@ type Prettify$1<T> = {
|
|
|
7109
7126
|
*/
|
|
7110
7127
|
export type InferRowType<TTable> = TTable extends {
|
|
7111
7128
|
$inferSelect: infer TSelect;
|
|
7112
|
-
} ? Prettify$
|
|
7129
|
+
} ? Prettify$2<TSelect> : TTable extends {
|
|
7113
7130
|
$columns: infer TCols;
|
|
7114
|
-
} ? Prettify$
|
|
7131
|
+
} ? Prettify$2<{
|
|
7115
7132
|
[K in keyof TCols]: any;
|
|
7116
7133
|
}> : TTable;
|
|
7117
7134
|
/**
|
|
@@ -7146,6 +7163,12 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
|
|
|
7146
7163
|
]>) | undefined,
|
|
7147
7164
|
/** Schema key (camelCase) - used for join callback params */
|
|
7148
7165
|
schemaKey?: string | undefined);
|
|
7166
|
+
/**
|
|
7167
|
+
* Set up column resolver to transform property names to SQL column names.
|
|
7168
|
+
* Uses schema metadata to resolve column names.
|
|
7169
|
+
* @internal
|
|
7170
|
+
*/
|
|
7171
|
+
private setupColumnResolver;
|
|
7149
7172
|
where(callback: (q: TypedConditionBuilder<TTable>) => TypedConditionBuilder<TTable>): this;
|
|
7150
7173
|
orderBy(column: ColumnName<TTable>, direction?: "ASC" | "DESC"): this;
|
|
7151
7174
|
limit(count: number): this;
|
|
@@ -7430,13 +7453,13 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
|
|
|
7430
7453
|
* @param withMetadata - If true, returns { data, metadata }
|
|
7431
7454
|
* @param asRequired - If true, all fields are required (removes optional)
|
|
7432
7455
|
*/
|
|
7433
|
-
all(): Promise<Prettify$
|
|
7456
|
+
all(): Promise<Prettify$2<InferResultType<TSchema, TTable, TColumns> & TJoined>[]>;
|
|
7434
7457
|
all(withMetadata: true): Promise<{
|
|
7435
|
-
data: Prettify$
|
|
7458
|
+
data: Prettify$2<InferResultType<TSchema, TTable, TColumns> & TJoined>[];
|
|
7436
7459
|
metadata: RelqMetadata;
|
|
7437
7460
|
}>;
|
|
7438
7461
|
all<R extends boolean>(withMetadata: true, asRequired: R): Promise<{
|
|
7439
|
-
data: Prettify$
|
|
7462
|
+
data: Prettify$2<R extends true ? Required<InferResultType<TSchema, TTable, TColumns> & TJoined> : InferResultType<TSchema, TTable, TColumns> & TJoined>[];
|
|
7440
7463
|
metadata: RelqMetadata;
|
|
7441
7464
|
}>;
|
|
7442
7465
|
/**
|
|
@@ -7445,13 +7468,13 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
|
|
|
7445
7468
|
* @param withMetadata - If true, returns { data, metadata }
|
|
7446
7469
|
* @param asRequired - If true, all fields are required (removes optional)
|
|
7447
7470
|
*/
|
|
7448
|
-
get(): Promise<Prettify$
|
|
7471
|
+
get(): Promise<Prettify$2<InferResultType<TSchema, TTable, TColumns> & TJoined> | null>;
|
|
7449
7472
|
get(withMetadata: true): Promise<{
|
|
7450
|
-
data: Prettify$
|
|
7473
|
+
data: Prettify$2<InferResultType<TSchema, TTable, TColumns> & TJoined> | null;
|
|
7451
7474
|
metadata: RelqMetadata;
|
|
7452
7475
|
}>;
|
|
7453
7476
|
get<R extends boolean>(withMetadata: true, asRequired: R): Promise<{
|
|
7454
|
-
data: Prettify$
|
|
7477
|
+
data: Prettify$2<R extends true ? Required<InferResultType<TSchema, TTable, TColumns> & TJoined> : InferResultType<TSchema, TTable, TColumns> & TJoined> | null;
|
|
7455
7478
|
metadata: RelqMetadata;
|
|
7456
7479
|
}>;
|
|
7457
7480
|
/**
|