relq 1.0.39 → 1.0.41
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/dist/cjs/core/helpers/ConnectedDeleteBuilder.cjs +28 -2
- package/dist/cjs/core/helpers/ConnectedInsertBuilder.cjs +28 -2
- package/dist/cjs/core/helpers/ConnectedQueryBuilder.cjs +3 -3
- package/dist/cjs/core/helpers/ConnectedSelectBuilder.cjs +4 -7
- package/dist/cjs/core/helpers/ConnectedUpdateBuilder.cjs +28 -2
- package/dist/cjs/core/helpers/ReturningExecutor.cjs +39 -3
- package/dist/cjs/delete/delete-builder.cjs +44 -3
- package/dist/cjs/insert/insert-builder.cjs +16 -3
- package/dist/cjs/update/update-builder.cjs +45 -4
- package/dist/config.d.ts +3 -2
- package/dist/esm/core/helpers/ConnectedDeleteBuilder.js +28 -2
- package/dist/esm/core/helpers/ConnectedInsertBuilder.js +28 -2
- package/dist/esm/core/helpers/ConnectedQueryBuilder.js +3 -3
- package/dist/esm/core/helpers/ConnectedSelectBuilder.js +4 -7
- package/dist/esm/core/helpers/ConnectedUpdateBuilder.js +28 -2
- package/dist/esm/core/helpers/ReturningExecutor.js +39 -3
- package/dist/esm/delete/delete-builder.js +44 -3
- package/dist/esm/insert/insert-builder.js +16 -3
- package/dist/esm/update/update-builder.js +45 -4
- package/dist/index.d.ts +125 -12
- package/dist/schema-builder.d.ts +3 -2
- package/package.json +1 -1
|
@@ -6,9 +6,32 @@ const ReturningExecutor_1 = require("./ReturningExecutor.cjs");
|
|
|
6
6
|
class ConnectedDeleteBuilder {
|
|
7
7
|
builder;
|
|
8
8
|
relq;
|
|
9
|
-
|
|
9
|
+
tableName;
|
|
10
|
+
schemaKey;
|
|
11
|
+
constructor(builder, relq, tableName, schemaKey) {
|
|
10
12
|
this.builder = builder;
|
|
11
13
|
this.relq = relq;
|
|
14
|
+
this.tableName = tableName;
|
|
15
|
+
this.schemaKey = schemaKey;
|
|
16
|
+
this.setupColumnResolver();
|
|
17
|
+
}
|
|
18
|
+
setupColumnResolver() {
|
|
19
|
+
if (!this.tableName && !this.schemaKey) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const internal = this.relq[methods_1.INTERNAL];
|
|
23
|
+
const tableDef = internal.getTableDef(this.schemaKey || this.tableName);
|
|
24
|
+
if (!tableDef) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const tableColumns = tableDef.$columns || tableDef;
|
|
28
|
+
this.builder.setColumnResolver((column) => {
|
|
29
|
+
const columnDef = tableColumns[column];
|
|
30
|
+
if (columnDef) {
|
|
31
|
+
return columnDef.$columnName || column;
|
|
32
|
+
}
|
|
33
|
+
return column;
|
|
34
|
+
});
|
|
12
35
|
}
|
|
13
36
|
where(callback) {
|
|
14
37
|
this.builder.where(callback);
|
|
@@ -26,8 +49,11 @@ class ConnectedDeleteBuilder {
|
|
|
26
49
|
return result.metadata.rowCount ?? 0;
|
|
27
50
|
}
|
|
28
51
|
returning(columns) {
|
|
52
|
+
if (columns === null) {
|
|
53
|
+
return this;
|
|
54
|
+
}
|
|
29
55
|
this.builder.returning(columns);
|
|
30
|
-
return new ReturningExecutor_1.ReturningExecutor(this.builder, this.relq);
|
|
56
|
+
return new ReturningExecutor_1.ReturningExecutor(this.builder, this.relq, this.tableName, this.schemaKey);
|
|
31
57
|
}
|
|
32
58
|
}
|
|
33
59
|
exports.ConnectedDeleteBuilder = ConnectedDeleteBuilder;
|
|
@@ -6,9 +6,32 @@ const ReturningExecutor_1 = require("./ReturningExecutor.cjs");
|
|
|
6
6
|
class ConnectedInsertBuilder {
|
|
7
7
|
builder;
|
|
8
8
|
relq;
|
|
9
|
-
|
|
9
|
+
tableName;
|
|
10
|
+
schemaKey;
|
|
11
|
+
constructor(builder, relq, tableName, schemaKey) {
|
|
10
12
|
this.builder = builder;
|
|
11
13
|
this.relq = relq;
|
|
14
|
+
this.tableName = tableName;
|
|
15
|
+
this.schemaKey = schemaKey;
|
|
16
|
+
this.setupColumnResolver();
|
|
17
|
+
}
|
|
18
|
+
setupColumnResolver() {
|
|
19
|
+
if (!this.tableName && !this.schemaKey) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const internal = this.relq[methods_1.INTERNAL];
|
|
23
|
+
const tableDef = internal.getTableDef(this.schemaKey || this.tableName);
|
|
24
|
+
if (!tableDef) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const tableColumns = tableDef.$columns || tableDef;
|
|
28
|
+
this.builder.setColumnResolver((column) => {
|
|
29
|
+
const columnDef = tableColumns[column];
|
|
30
|
+
if (columnDef) {
|
|
31
|
+
return columnDef.$columnName || column;
|
|
32
|
+
}
|
|
33
|
+
return column;
|
|
34
|
+
});
|
|
12
35
|
}
|
|
13
36
|
addRow(row) {
|
|
14
37
|
this.builder.addRow(row);
|
|
@@ -49,8 +72,11 @@ class ConnectedInsertBuilder {
|
|
|
49
72
|
return result.metadata.rowCount ?? 0;
|
|
50
73
|
}
|
|
51
74
|
returning(columns) {
|
|
75
|
+
if (columns === null) {
|
|
76
|
+
return this;
|
|
77
|
+
}
|
|
52
78
|
this.builder.returning(columns);
|
|
53
|
-
return new ReturningExecutor_1.ReturningExecutor(this.builder, this.relq);
|
|
79
|
+
return new ReturningExecutor_1.ReturningExecutor(this.builder, this.relq, this.tableName, this.schemaKey);
|
|
54
80
|
}
|
|
55
81
|
}
|
|
56
82
|
exports.ConnectedInsertBuilder = ConnectedInsertBuilder;
|
|
@@ -49,15 +49,15 @@ class ConnectedQueryBuilder {
|
|
|
49
49
|
}
|
|
50
50
|
insert(data) {
|
|
51
51
|
const builder = new insert_builder_1.InsertBuilder(this.tableName, data);
|
|
52
|
-
return new ConnectedInsertBuilder_1.ConnectedInsertBuilder(builder, this.relq);
|
|
52
|
+
return new ConnectedInsertBuilder_1.ConnectedInsertBuilder(builder, this.relq, this.tableName, this.schemaKey);
|
|
53
53
|
}
|
|
54
54
|
update(data) {
|
|
55
55
|
const builder = new update_builder_1.UpdateBuilder(this.tableName, data);
|
|
56
|
-
return new ConnectedUpdateBuilder_1.ConnectedUpdateBuilder(builder, this.relq);
|
|
56
|
+
return new ConnectedUpdateBuilder_1.ConnectedUpdateBuilder(builder, this.relq, this.tableName, this.schemaKey);
|
|
57
57
|
}
|
|
58
58
|
delete() {
|
|
59
59
|
const builder = new delete_builder_1.DeleteBuilder(this.tableName);
|
|
60
|
-
return new ConnectedDeleteBuilder_1.ConnectedDeleteBuilder(builder, this.relq);
|
|
60
|
+
return new ConnectedDeleteBuilder_1.ConnectedDeleteBuilder(builder, this.relq, this.tableName, this.schemaKey);
|
|
61
61
|
}
|
|
62
62
|
count() {
|
|
63
63
|
const builder = new count_builder_1.CountBuilder(this.tableName);
|
|
@@ -10,9 +10,6 @@ const join_condition_builder_1 = require("../../select/join-condition-builder.cj
|
|
|
10
10
|
const join_internals_1 = require("../../select/join-internals.cjs");
|
|
11
11
|
const join_many_condition_builder_1 = require("../../select/join-many-condition-builder.cjs");
|
|
12
12
|
const table_proxy_1 = require("../../select/table-proxy.cjs");
|
|
13
|
-
function camelToSnake(str) {
|
|
14
|
-
return str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);
|
|
15
|
-
}
|
|
16
13
|
const pagination_types_1 = require("../../types/pagination-types.cjs");
|
|
17
14
|
const fk_resolver_1 = require("../../utils/fk-resolver.cjs");
|
|
18
15
|
const methods_1 = require("./methods.cjs");
|
|
@@ -40,9 +37,9 @@ class ConnectedSelectBuilder {
|
|
|
40
37
|
this.builder.setColumnResolver((column) => {
|
|
41
38
|
const columnDef = tableColumns[column];
|
|
42
39
|
if (columnDef) {
|
|
43
|
-
return columnDef.$
|
|
40
|
+
return columnDef.$columnName || column;
|
|
44
41
|
}
|
|
45
|
-
return
|
|
42
|
+
return column;
|
|
46
43
|
});
|
|
47
44
|
}
|
|
48
45
|
where(callback) {
|
|
@@ -154,7 +151,7 @@ class ConnectedSelectBuilder {
|
|
|
154
151
|
const tableColumns = tableDef?.$columns || tableDef;
|
|
155
152
|
const selectCols = selectedProps.map(prop => {
|
|
156
153
|
const columnDef = tableColumns?.[prop];
|
|
157
|
-
const sqlName = columnDef?.$
|
|
154
|
+
const sqlName = columnDef?.$columnName || prop;
|
|
158
155
|
return `"${alias}"."${sqlName}" AS "${prop}"`;
|
|
159
156
|
}).join(', ');
|
|
160
157
|
parts.push(selectCols);
|
|
@@ -224,7 +221,7 @@ class ConnectedSelectBuilder {
|
|
|
224
221
|
const rightColumns = rightTableDef?.$columns || rightTableDef;
|
|
225
222
|
selectColumns = selectedProps.map(prop => {
|
|
226
223
|
const columnDef = rightColumns?.[prop];
|
|
227
|
-
const sqlName = columnDef?.$
|
|
224
|
+
const sqlName = columnDef?.$columnName || prop;
|
|
228
225
|
return { property: prop, sqlName };
|
|
229
226
|
});
|
|
230
227
|
}
|
|
@@ -6,9 +6,32 @@ const ReturningExecutor_1 = require("./ReturningExecutor.cjs");
|
|
|
6
6
|
class ConnectedUpdateBuilder {
|
|
7
7
|
builder;
|
|
8
8
|
relq;
|
|
9
|
-
|
|
9
|
+
tableName;
|
|
10
|
+
schemaKey;
|
|
11
|
+
constructor(builder, relq, tableName, schemaKey) {
|
|
10
12
|
this.builder = builder;
|
|
11
13
|
this.relq = relq;
|
|
14
|
+
this.tableName = tableName;
|
|
15
|
+
this.schemaKey = schemaKey;
|
|
16
|
+
this.setupColumnResolver();
|
|
17
|
+
}
|
|
18
|
+
setupColumnResolver() {
|
|
19
|
+
if (!this.tableName && !this.schemaKey) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const internal = this.relq[methods_1.INTERNAL];
|
|
23
|
+
const tableDef = internal.getTableDef(this.schemaKey || this.tableName);
|
|
24
|
+
if (!tableDef) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const tableColumns = tableDef.$columns || tableDef;
|
|
28
|
+
this.builder.setColumnResolver((column) => {
|
|
29
|
+
const columnDef = tableColumns[column];
|
|
30
|
+
if (columnDef) {
|
|
31
|
+
return columnDef.$columnName || column;
|
|
32
|
+
}
|
|
33
|
+
return column;
|
|
34
|
+
});
|
|
12
35
|
}
|
|
13
36
|
where(callback) {
|
|
14
37
|
this.builder.where(callback);
|
|
@@ -27,8 +50,11 @@ class ConnectedUpdateBuilder {
|
|
|
27
50
|
return result.metadata.rowCount ?? 0;
|
|
28
51
|
}
|
|
29
52
|
returning(columns) {
|
|
53
|
+
if (columns === null) {
|
|
54
|
+
return this;
|
|
55
|
+
}
|
|
30
56
|
this.builder.returning(columns);
|
|
31
|
-
return new ReturningExecutor_1.ReturningExecutor(this.builder, this.relq);
|
|
57
|
+
return new ReturningExecutor_1.ReturningExecutor(this.builder, this.relq, this.tableName, this.schemaKey);
|
|
32
58
|
}
|
|
33
59
|
}
|
|
34
60
|
exports.ConnectedUpdateBuilder = ConnectedUpdateBuilder;
|
|
@@ -7,9 +7,44 @@ const methods_1 = require("./methods.cjs");
|
|
|
7
7
|
class ReturningExecutor {
|
|
8
8
|
builder;
|
|
9
9
|
relq;
|
|
10
|
-
|
|
10
|
+
tableName;
|
|
11
|
+
schemaKey;
|
|
12
|
+
columnMapping;
|
|
13
|
+
constructor(builder, relq, tableName, schemaKey) {
|
|
11
14
|
this.builder = builder;
|
|
12
15
|
this.relq = relq;
|
|
16
|
+
this.tableName = tableName;
|
|
17
|
+
this.schemaKey = schemaKey;
|
|
18
|
+
this.setupColumnMapping();
|
|
19
|
+
}
|
|
20
|
+
setupColumnMapping() {
|
|
21
|
+
if (!this.tableName && !this.schemaKey) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const internal = this.relq[methods_1.INTERNAL];
|
|
25
|
+
const tableDef = internal.getTableDef(this.schemaKey || this.tableName);
|
|
26
|
+
if (!tableDef) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const tableColumns = tableDef.$columns || tableDef;
|
|
30
|
+
this.columnMapping = new Map();
|
|
31
|
+
for (const [propName, columnDef] of Object.entries(tableColumns)) {
|
|
32
|
+
if (columnDef && typeof columnDef === 'object') {
|
|
33
|
+
const sqlName = columnDef.$columnName || propName;
|
|
34
|
+
this.columnMapping.set(sqlName, propName);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
transformRow(row) {
|
|
39
|
+
if (!this.columnMapping) {
|
|
40
|
+
return row;
|
|
41
|
+
}
|
|
42
|
+
const transformed = {};
|
|
43
|
+
for (const [sqlKey, value] of Object.entries(row)) {
|
|
44
|
+
const propName = this.columnMapping.get(sqlKey) || sqlKey;
|
|
45
|
+
transformed[propName] = value;
|
|
46
|
+
}
|
|
47
|
+
return transformed;
|
|
13
48
|
}
|
|
14
49
|
toString() {
|
|
15
50
|
return this.builder.toString();
|
|
@@ -25,10 +60,11 @@ class ReturningExecutor {
|
|
|
25
60
|
}
|
|
26
61
|
const sql = this.builder.toString();
|
|
27
62
|
const result = await this.relq[methods_1.INTERNAL].executeSelect(sql);
|
|
63
|
+
const transformedData = result.data.map(row => this.transformRow(row));
|
|
28
64
|
if (withMetadata) {
|
|
29
|
-
return result;
|
|
65
|
+
return { ...result, data: transformedData };
|
|
30
66
|
}
|
|
31
|
-
return
|
|
67
|
+
return transformedData;
|
|
32
68
|
}
|
|
33
69
|
}
|
|
34
70
|
exports.ReturningExecutor = ReturningExecutor;
|
|
@@ -12,9 +12,47 @@ class DeleteBuilder {
|
|
|
12
12
|
tableName;
|
|
13
13
|
whereConditions = [];
|
|
14
14
|
returningClause;
|
|
15
|
+
columnResolver;
|
|
15
16
|
constructor(tableName) {
|
|
16
17
|
this.tableName = tableName;
|
|
17
18
|
}
|
|
19
|
+
setColumnResolver(resolver) {
|
|
20
|
+
this.columnResolver = resolver;
|
|
21
|
+
return this;
|
|
22
|
+
}
|
|
23
|
+
resolveColumnName(name) {
|
|
24
|
+
if (this.columnResolver) {
|
|
25
|
+
return this.columnResolver(name);
|
|
26
|
+
}
|
|
27
|
+
return name;
|
|
28
|
+
}
|
|
29
|
+
transformConditionColumns(conditions) {
|
|
30
|
+
if (!this.columnResolver) {
|
|
31
|
+
return conditions;
|
|
32
|
+
}
|
|
33
|
+
return conditions.map(cond => {
|
|
34
|
+
if (!cond.column || cond.method === 'raw') {
|
|
35
|
+
return cond;
|
|
36
|
+
}
|
|
37
|
+
if (cond.method === 'or' || cond.method === 'and') {
|
|
38
|
+
return {
|
|
39
|
+
...cond,
|
|
40
|
+
values: this.transformConditionColumns(cond.values)
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
if (cond.column.includes('.')) {
|
|
44
|
+
const [tableRef, colName] = cond.column.split('.');
|
|
45
|
+
return {
|
|
46
|
+
...cond,
|
|
47
|
+
column: `${tableRef}.${this.columnResolver(colName)}`
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
...cond,
|
|
52
|
+
column: this.columnResolver(cond.column)
|
|
53
|
+
};
|
|
54
|
+
});
|
|
55
|
+
}
|
|
18
56
|
where(callback) {
|
|
19
57
|
const conditionBuilder = new condition_collector_1.ConditionCollector();
|
|
20
58
|
callback(conditionBuilder);
|
|
@@ -64,7 +102,8 @@ class DeleteBuilder {
|
|
|
64
102
|
toString() {
|
|
65
103
|
let query = (0, pg_format_1.default)('DELETE FROM %I', this.tableName);
|
|
66
104
|
if (this.whereConditions.length > 0) {
|
|
67
|
-
|
|
105
|
+
const transformedConditions = this.transformConditionColumns(this.whereConditions);
|
|
106
|
+
query += ' WHERE ' + (0, condition_collector_1.buildConditionsSQL)(transformedConditions);
|
|
68
107
|
}
|
|
69
108
|
if (this.returningClause) {
|
|
70
109
|
query += this.buildReturningClause();
|
|
@@ -111,8 +150,10 @@ class DeleteBuilder {
|
|
|
111
150
|
if (!this.returningClause)
|
|
112
151
|
return '';
|
|
113
152
|
switch (this.returningClause.type) {
|
|
114
|
-
case 'columns':
|
|
115
|
-
|
|
153
|
+
case 'columns': {
|
|
154
|
+
const resolvedColumns = this.returningClause.columns.map(col => col === '*' ? '*' : this.resolveColumnName(col));
|
|
155
|
+
return (0, pg_format_1.default)(' RETURNING %I', resolvedColumns);
|
|
156
|
+
}
|
|
116
157
|
case 'select': {
|
|
117
158
|
const selectSQL = this.returningClause.builder.toString();
|
|
118
159
|
return ` RETURNING (${selectSQL})`;
|
|
@@ -19,11 +19,22 @@ class InsertBuilder {
|
|
|
19
19
|
_case = 'keep-case';
|
|
20
20
|
_convertCase = '2snake';
|
|
21
21
|
originalColumns;
|
|
22
|
+
columnResolver;
|
|
22
23
|
constructor(tableName, data) {
|
|
23
24
|
this.tableName = tableName;
|
|
24
25
|
this.insertData = [data];
|
|
25
26
|
this.originalColumns = Object.keys(data).sort();
|
|
26
27
|
}
|
|
28
|
+
setColumnResolver(resolver) {
|
|
29
|
+
this.columnResolver = resolver;
|
|
30
|
+
return this;
|
|
31
|
+
}
|
|
32
|
+
resolveColumnName(name) {
|
|
33
|
+
if (this.columnResolver) {
|
|
34
|
+
return this.columnResolver(name);
|
|
35
|
+
}
|
|
36
|
+
return this.convertColumnName(name);
|
|
37
|
+
}
|
|
27
38
|
convertCase(type, conversionCase = '2snake') {
|
|
28
39
|
this._case = type;
|
|
29
40
|
this._convertCase = conversionCase;
|
|
@@ -176,7 +187,7 @@ class InsertBuilder {
|
|
|
176
187
|
throw new relq_errors_1.RelqBuilderError('Cannot generate INSERT query: no rows to insert', { builder: 'InsertBuilder', missing: 'data', hint: 'Add rows using addRow() or addRows() first' });
|
|
177
188
|
}
|
|
178
189
|
const originalColumns = Object.keys(this.insertData[0]);
|
|
179
|
-
const columns = originalColumns.map(name => this.
|
|
190
|
+
const columns = originalColumns.map(name => this.resolveColumnName(name));
|
|
180
191
|
const allValuesGroups = [];
|
|
181
192
|
for (const row of this.insertData) {
|
|
182
193
|
const { values, placeholders } = this.processRowValues(row, originalColumns);
|
|
@@ -230,8 +241,10 @@ class InsertBuilder {
|
|
|
230
241
|
if (!this.returningClause)
|
|
231
242
|
return '';
|
|
232
243
|
switch (this.returningClause.type) {
|
|
233
|
-
case 'columns':
|
|
234
|
-
|
|
244
|
+
case 'columns': {
|
|
245
|
+
const resolvedColumns = this.returningClause.columns.map(col => col === '*' ? '*' : this.resolveColumnName(col));
|
|
246
|
+
return (0, pg_format_1.default)(' RETURNING %I', resolvedColumns);
|
|
247
|
+
}
|
|
235
248
|
case 'select': {
|
|
236
249
|
const selectSQL = this.returningClause.builder.toString();
|
|
237
250
|
return ` RETURNING (${selectSQL})`;
|
|
@@ -17,10 +17,48 @@ class UpdateBuilder {
|
|
|
17
17
|
returningClause;
|
|
18
18
|
_case = 'keep-case';
|
|
19
19
|
_convertCase = '2snake';
|
|
20
|
+
columnResolver;
|
|
20
21
|
constructor(tableName, data) {
|
|
21
22
|
this.tableName = tableName;
|
|
22
23
|
this.updateData = data;
|
|
23
24
|
}
|
|
25
|
+
setColumnResolver(resolver) {
|
|
26
|
+
this.columnResolver = resolver;
|
|
27
|
+
return this;
|
|
28
|
+
}
|
|
29
|
+
resolveColumnName(name) {
|
|
30
|
+
if (this.columnResolver) {
|
|
31
|
+
return this.columnResolver(name);
|
|
32
|
+
}
|
|
33
|
+
return this.convertColumnName(name);
|
|
34
|
+
}
|
|
35
|
+
transformConditionColumns(conditions) {
|
|
36
|
+
if (!this.columnResolver) {
|
|
37
|
+
return conditions;
|
|
38
|
+
}
|
|
39
|
+
return conditions.map(cond => {
|
|
40
|
+
if (!cond.column || cond.method === 'raw') {
|
|
41
|
+
return cond;
|
|
42
|
+
}
|
|
43
|
+
if (cond.method === 'or' || cond.method === 'and') {
|
|
44
|
+
return {
|
|
45
|
+
...cond,
|
|
46
|
+
values: this.transformConditionColumns(cond.values)
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
if (cond.column.includes('.')) {
|
|
50
|
+
const [tableRef, colName] = cond.column.split('.');
|
|
51
|
+
return {
|
|
52
|
+
...cond,
|
|
53
|
+
column: `${tableRef}.${this.columnResolver(colName)}`
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
...cond,
|
|
58
|
+
column: this.columnResolver(cond.column)
|
|
59
|
+
};
|
|
60
|
+
});
|
|
61
|
+
}
|
|
24
62
|
convertCase(type, conversionCase = '2snake') {
|
|
25
63
|
this._case = type;
|
|
26
64
|
this._convertCase = conversionCase;
|
|
@@ -110,7 +148,7 @@ class UpdateBuilder {
|
|
|
110
148
|
}
|
|
111
149
|
toString() {
|
|
112
150
|
const processedPairs = Object.entries(this.updateData).map(([col, val]) => {
|
|
113
|
-
const convertedCol = this.
|
|
151
|
+
const convertedCol = this.resolveColumnName(col);
|
|
114
152
|
if (typeof val === 'function') {
|
|
115
153
|
const arrayBuilder = new array_update_builder_1.ArrayUpdateBuilder(col);
|
|
116
154
|
const result = val(arrayBuilder);
|
|
@@ -124,7 +162,8 @@ class UpdateBuilder {
|
|
|
124
162
|
});
|
|
125
163
|
let query = (0, pg_format_1.default)('UPDATE %I SET %s', this.tableName, processedPairs.join(', '));
|
|
126
164
|
if (this.whereConditions.length > 0) {
|
|
127
|
-
|
|
165
|
+
const transformedConditions = this.transformConditionColumns(this.whereConditions);
|
|
166
|
+
query += ' WHERE ' + (0, condition_collector_1.buildConditionsSQL)(transformedConditions);
|
|
128
167
|
}
|
|
129
168
|
if (this.returningClause) {
|
|
130
169
|
query += this.buildReturningClause();
|
|
@@ -171,8 +210,10 @@ class UpdateBuilder {
|
|
|
171
210
|
if (!this.returningClause)
|
|
172
211
|
return '';
|
|
173
212
|
switch (this.returningClause.type) {
|
|
174
|
-
case 'columns':
|
|
175
|
-
|
|
213
|
+
case 'columns': {
|
|
214
|
+
const resolvedColumns = this.returningClause.columns.map(col => col === '*' ? '*' : this.resolveColumnName(col));
|
|
215
|
+
return (0, pg_format_1.default)(' RETURNING %I', resolvedColumns);
|
|
216
|
+
}
|
|
176
217
|
case 'select': {
|
|
177
218
|
const selectSQL = this.returningClause.builder.toString();
|
|
178
219
|
return ` RETURNING (${selectSQL})`;
|
package/dist/config.d.ts
CHANGED
|
@@ -536,9 +536,10 @@ export type Simplify<T> = {
|
|
|
536
536
|
[K in keyof T]: T[K];
|
|
537
537
|
} & {};
|
|
538
538
|
/**
|
|
539
|
-
* Clean a column type by removing DefaultValue union members
|
|
539
|
+
* Clean a column type by removing DefaultValue union members and symbols
|
|
540
|
+
* (symbols like EMPTY_OBJECT/EMPTY_ARRAY can leak into type inference from $default)
|
|
540
541
|
*/
|
|
541
|
-
export type CleanType<T> = Exclude<T, DefaultValue | (object & DefaultValue)>;
|
|
542
|
+
export type CleanType<T> = Exclude<T, DefaultValue | (object & DefaultValue) | symbol>;
|
|
542
543
|
/**
|
|
543
544
|
* Build SELECT type with smart required/optional:
|
|
544
545
|
* - Required: NOT NULL, PRIMARY KEY, has DEFAULT/GENERATED columns
|
|
@@ -3,9 +3,32 @@ import { ReturningExecutor } from "./ReturningExecutor.js";
|
|
|
3
3
|
export class ConnectedDeleteBuilder {
|
|
4
4
|
builder;
|
|
5
5
|
relq;
|
|
6
|
-
|
|
6
|
+
tableName;
|
|
7
|
+
schemaKey;
|
|
8
|
+
constructor(builder, relq, tableName, schemaKey) {
|
|
7
9
|
this.builder = builder;
|
|
8
10
|
this.relq = relq;
|
|
11
|
+
this.tableName = tableName;
|
|
12
|
+
this.schemaKey = schemaKey;
|
|
13
|
+
this.setupColumnResolver();
|
|
14
|
+
}
|
|
15
|
+
setupColumnResolver() {
|
|
16
|
+
if (!this.tableName && !this.schemaKey) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const internal = this.relq[INTERNAL];
|
|
20
|
+
const tableDef = internal.getTableDef(this.schemaKey || this.tableName);
|
|
21
|
+
if (!tableDef) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const tableColumns = tableDef.$columns || tableDef;
|
|
25
|
+
this.builder.setColumnResolver((column) => {
|
|
26
|
+
const columnDef = tableColumns[column];
|
|
27
|
+
if (columnDef) {
|
|
28
|
+
return columnDef.$columnName || column;
|
|
29
|
+
}
|
|
30
|
+
return column;
|
|
31
|
+
});
|
|
9
32
|
}
|
|
10
33
|
where(callback) {
|
|
11
34
|
this.builder.where(callback);
|
|
@@ -23,7 +46,10 @@ export class ConnectedDeleteBuilder {
|
|
|
23
46
|
return result.metadata.rowCount ?? 0;
|
|
24
47
|
}
|
|
25
48
|
returning(columns) {
|
|
49
|
+
if (columns === null) {
|
|
50
|
+
return this;
|
|
51
|
+
}
|
|
26
52
|
this.builder.returning(columns);
|
|
27
|
-
return new ReturningExecutor(this.builder, this.relq);
|
|
53
|
+
return new ReturningExecutor(this.builder, this.relq, this.tableName, this.schemaKey);
|
|
28
54
|
}
|
|
29
55
|
}
|
|
@@ -3,9 +3,32 @@ import { ReturningExecutor } from "./ReturningExecutor.js";
|
|
|
3
3
|
export class ConnectedInsertBuilder {
|
|
4
4
|
builder;
|
|
5
5
|
relq;
|
|
6
|
-
|
|
6
|
+
tableName;
|
|
7
|
+
schemaKey;
|
|
8
|
+
constructor(builder, relq, tableName, schemaKey) {
|
|
7
9
|
this.builder = builder;
|
|
8
10
|
this.relq = relq;
|
|
11
|
+
this.tableName = tableName;
|
|
12
|
+
this.schemaKey = schemaKey;
|
|
13
|
+
this.setupColumnResolver();
|
|
14
|
+
}
|
|
15
|
+
setupColumnResolver() {
|
|
16
|
+
if (!this.tableName && !this.schemaKey) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const internal = this.relq[INTERNAL];
|
|
20
|
+
const tableDef = internal.getTableDef(this.schemaKey || this.tableName);
|
|
21
|
+
if (!tableDef) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const tableColumns = tableDef.$columns || tableDef;
|
|
25
|
+
this.builder.setColumnResolver((column) => {
|
|
26
|
+
const columnDef = tableColumns[column];
|
|
27
|
+
if (columnDef) {
|
|
28
|
+
return columnDef.$columnName || column;
|
|
29
|
+
}
|
|
30
|
+
return column;
|
|
31
|
+
});
|
|
9
32
|
}
|
|
10
33
|
addRow(row) {
|
|
11
34
|
this.builder.addRow(row);
|
|
@@ -46,7 +69,10 @@ export class ConnectedInsertBuilder {
|
|
|
46
69
|
return result.metadata.rowCount ?? 0;
|
|
47
70
|
}
|
|
48
71
|
returning(columns) {
|
|
72
|
+
if (columns === null) {
|
|
73
|
+
return this;
|
|
74
|
+
}
|
|
49
75
|
this.builder.returning(columns);
|
|
50
|
-
return new ReturningExecutor(this.builder, this.relq);
|
|
76
|
+
return new ReturningExecutor(this.builder, this.relq, this.tableName, this.schemaKey);
|
|
51
77
|
}
|
|
52
78
|
}
|
|
@@ -46,15 +46,15 @@ export class ConnectedQueryBuilder {
|
|
|
46
46
|
}
|
|
47
47
|
insert(data) {
|
|
48
48
|
const builder = new InsertBuilder(this.tableName, data);
|
|
49
|
-
return new ConnectedInsertBuilder(builder, this.relq);
|
|
49
|
+
return new ConnectedInsertBuilder(builder, this.relq, this.tableName, this.schemaKey);
|
|
50
50
|
}
|
|
51
51
|
update(data) {
|
|
52
52
|
const builder = new UpdateBuilder(this.tableName, data);
|
|
53
|
-
return new ConnectedUpdateBuilder(builder, this.relq);
|
|
53
|
+
return new ConnectedUpdateBuilder(builder, this.relq, this.tableName, this.schemaKey);
|
|
54
54
|
}
|
|
55
55
|
delete() {
|
|
56
56
|
const builder = new DeleteBuilder(this.tableName);
|
|
57
|
-
return new ConnectedDeleteBuilder(builder, this.relq);
|
|
57
|
+
return new ConnectedDeleteBuilder(builder, this.relq, this.tableName, this.schemaKey);
|
|
58
58
|
}
|
|
59
59
|
count() {
|
|
60
60
|
const builder = new CountBuilder(this.tableName);
|
|
@@ -4,9 +4,6 @@ import { JoinConditionBuilder } from "../../select/join-condition-builder.js";
|
|
|
4
4
|
import { JOIN_INTERNAL, JOIN_SETUP } from "../../select/join-internals.js";
|
|
5
5
|
import { JoinManyConditionBuilder } from "../../select/join-many-condition-builder.js";
|
|
6
6
|
import { createTableProxy } from "../../select/table-proxy.js";
|
|
7
|
-
function camelToSnake(str) {
|
|
8
|
-
return str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);
|
|
9
|
-
}
|
|
10
7
|
import { randomLimit } from "../../types/pagination-types.js";
|
|
11
8
|
import { resolveForeignKey } from "../../utils/fk-resolver.js";
|
|
12
9
|
import { INTERNAL } from "./methods.js";
|
|
@@ -34,9 +31,9 @@ export class ConnectedSelectBuilder {
|
|
|
34
31
|
this.builder.setColumnResolver((column) => {
|
|
35
32
|
const columnDef = tableColumns[column];
|
|
36
33
|
if (columnDef) {
|
|
37
|
-
return columnDef.$
|
|
34
|
+
return columnDef.$columnName || column;
|
|
38
35
|
}
|
|
39
|
-
return
|
|
36
|
+
return column;
|
|
40
37
|
});
|
|
41
38
|
}
|
|
42
39
|
where(callback) {
|
|
@@ -148,7 +145,7 @@ export class ConnectedSelectBuilder {
|
|
|
148
145
|
const tableColumns = tableDef?.$columns || tableDef;
|
|
149
146
|
const selectCols = selectedProps.map(prop => {
|
|
150
147
|
const columnDef = tableColumns?.[prop];
|
|
151
|
-
const sqlName = columnDef?.$
|
|
148
|
+
const sqlName = columnDef?.$columnName || prop;
|
|
152
149
|
return `"${alias}"."${sqlName}" AS "${prop}"`;
|
|
153
150
|
}).join(', ');
|
|
154
151
|
parts.push(selectCols);
|
|
@@ -218,7 +215,7 @@ export class ConnectedSelectBuilder {
|
|
|
218
215
|
const rightColumns = rightTableDef?.$columns || rightTableDef;
|
|
219
216
|
selectColumns = selectedProps.map(prop => {
|
|
220
217
|
const columnDef = rightColumns?.[prop];
|
|
221
|
-
const sqlName = columnDef?.$
|
|
218
|
+
const sqlName = columnDef?.$columnName || prop;
|
|
222
219
|
return { property: prop, sqlName };
|
|
223
220
|
});
|
|
224
221
|
}
|
|
@@ -3,9 +3,32 @@ import { ReturningExecutor } from "./ReturningExecutor.js";
|
|
|
3
3
|
export class ConnectedUpdateBuilder {
|
|
4
4
|
builder;
|
|
5
5
|
relq;
|
|
6
|
-
|
|
6
|
+
tableName;
|
|
7
|
+
schemaKey;
|
|
8
|
+
constructor(builder, relq, tableName, schemaKey) {
|
|
7
9
|
this.builder = builder;
|
|
8
10
|
this.relq = relq;
|
|
11
|
+
this.tableName = tableName;
|
|
12
|
+
this.schemaKey = schemaKey;
|
|
13
|
+
this.setupColumnResolver();
|
|
14
|
+
}
|
|
15
|
+
setupColumnResolver() {
|
|
16
|
+
if (!this.tableName && !this.schemaKey) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const internal = this.relq[INTERNAL];
|
|
20
|
+
const tableDef = internal.getTableDef(this.schemaKey || this.tableName);
|
|
21
|
+
if (!tableDef) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const tableColumns = tableDef.$columns || tableDef;
|
|
25
|
+
this.builder.setColumnResolver((column) => {
|
|
26
|
+
const columnDef = tableColumns[column];
|
|
27
|
+
if (columnDef) {
|
|
28
|
+
return columnDef.$columnName || column;
|
|
29
|
+
}
|
|
30
|
+
return column;
|
|
31
|
+
});
|
|
9
32
|
}
|
|
10
33
|
where(callback) {
|
|
11
34
|
this.builder.where(callback);
|
|
@@ -24,7 +47,10 @@ export class ConnectedUpdateBuilder {
|
|
|
24
47
|
return result.metadata.rowCount ?? 0;
|
|
25
48
|
}
|
|
26
49
|
returning(columns) {
|
|
50
|
+
if (columns === null) {
|
|
51
|
+
return this;
|
|
52
|
+
}
|
|
27
53
|
this.builder.returning(columns);
|
|
28
|
-
return new ReturningExecutor(this.builder, this.relq);
|
|
54
|
+
return new ReturningExecutor(this.builder, this.relq, this.tableName, this.schemaKey);
|
|
29
55
|
}
|
|
30
56
|
}
|
|
@@ -4,9 +4,44 @@ import { INTERNAL } from "./methods.js";
|
|
|
4
4
|
export class ReturningExecutor {
|
|
5
5
|
builder;
|
|
6
6
|
relq;
|
|
7
|
-
|
|
7
|
+
tableName;
|
|
8
|
+
schemaKey;
|
|
9
|
+
columnMapping;
|
|
10
|
+
constructor(builder, relq, tableName, schemaKey) {
|
|
8
11
|
this.builder = builder;
|
|
9
12
|
this.relq = relq;
|
|
13
|
+
this.tableName = tableName;
|
|
14
|
+
this.schemaKey = schemaKey;
|
|
15
|
+
this.setupColumnMapping();
|
|
16
|
+
}
|
|
17
|
+
setupColumnMapping() {
|
|
18
|
+
if (!this.tableName && !this.schemaKey) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const internal = this.relq[INTERNAL];
|
|
22
|
+
const tableDef = internal.getTableDef(this.schemaKey || this.tableName);
|
|
23
|
+
if (!tableDef) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const tableColumns = tableDef.$columns || tableDef;
|
|
27
|
+
this.columnMapping = new Map();
|
|
28
|
+
for (const [propName, columnDef] of Object.entries(tableColumns)) {
|
|
29
|
+
if (columnDef && typeof columnDef === 'object') {
|
|
30
|
+
const sqlName = columnDef.$columnName || propName;
|
|
31
|
+
this.columnMapping.set(sqlName, propName);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
transformRow(row) {
|
|
36
|
+
if (!this.columnMapping) {
|
|
37
|
+
return row;
|
|
38
|
+
}
|
|
39
|
+
const transformed = {};
|
|
40
|
+
for (const [sqlKey, value] of Object.entries(row)) {
|
|
41
|
+
const propName = this.columnMapping.get(sqlKey) || sqlKey;
|
|
42
|
+
transformed[propName] = value;
|
|
43
|
+
}
|
|
44
|
+
return transformed;
|
|
10
45
|
}
|
|
11
46
|
toString() {
|
|
12
47
|
return this.builder.toString();
|
|
@@ -22,9 +57,10 @@ export class ReturningExecutor {
|
|
|
22
57
|
}
|
|
23
58
|
const sql = this.builder.toString();
|
|
24
59
|
const result = await this.relq[INTERNAL].executeSelect(sql);
|
|
60
|
+
const transformedData = result.data.map(row => this.transformRow(row));
|
|
25
61
|
if (withMetadata) {
|
|
26
|
-
return result;
|
|
62
|
+
return { ...result, data: transformedData };
|
|
27
63
|
}
|
|
28
|
-
return
|
|
64
|
+
return transformedData;
|
|
29
65
|
}
|
|
30
66
|
}
|
|
@@ -6,9 +6,47 @@ export class DeleteBuilder {
|
|
|
6
6
|
tableName;
|
|
7
7
|
whereConditions = [];
|
|
8
8
|
returningClause;
|
|
9
|
+
columnResolver;
|
|
9
10
|
constructor(tableName) {
|
|
10
11
|
this.tableName = tableName;
|
|
11
12
|
}
|
|
13
|
+
setColumnResolver(resolver) {
|
|
14
|
+
this.columnResolver = resolver;
|
|
15
|
+
return this;
|
|
16
|
+
}
|
|
17
|
+
resolveColumnName(name) {
|
|
18
|
+
if (this.columnResolver) {
|
|
19
|
+
return this.columnResolver(name);
|
|
20
|
+
}
|
|
21
|
+
return name;
|
|
22
|
+
}
|
|
23
|
+
transformConditionColumns(conditions) {
|
|
24
|
+
if (!this.columnResolver) {
|
|
25
|
+
return conditions;
|
|
26
|
+
}
|
|
27
|
+
return conditions.map(cond => {
|
|
28
|
+
if (!cond.column || cond.method === 'raw') {
|
|
29
|
+
return cond;
|
|
30
|
+
}
|
|
31
|
+
if (cond.method === 'or' || cond.method === 'and') {
|
|
32
|
+
return {
|
|
33
|
+
...cond,
|
|
34
|
+
values: this.transformConditionColumns(cond.values)
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
if (cond.column.includes('.')) {
|
|
38
|
+
const [tableRef, colName] = cond.column.split('.');
|
|
39
|
+
return {
|
|
40
|
+
...cond,
|
|
41
|
+
column: `${tableRef}.${this.columnResolver(colName)}`
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
...cond,
|
|
46
|
+
column: this.columnResolver(cond.column)
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
}
|
|
12
50
|
where(callback) {
|
|
13
51
|
const conditionBuilder = new ConditionCollector();
|
|
14
52
|
callback(conditionBuilder);
|
|
@@ -58,7 +96,8 @@ export class DeleteBuilder {
|
|
|
58
96
|
toString() {
|
|
59
97
|
let query = format('DELETE FROM %I', this.tableName);
|
|
60
98
|
if (this.whereConditions.length > 0) {
|
|
61
|
-
|
|
99
|
+
const transformedConditions = this.transformConditionColumns(this.whereConditions);
|
|
100
|
+
query += ' WHERE ' + buildConditionsSQL(transformedConditions);
|
|
62
101
|
}
|
|
63
102
|
if (this.returningClause) {
|
|
64
103
|
query += this.buildReturningClause();
|
|
@@ -105,8 +144,10 @@ export class DeleteBuilder {
|
|
|
105
144
|
if (!this.returningClause)
|
|
106
145
|
return '';
|
|
107
146
|
switch (this.returningClause.type) {
|
|
108
|
-
case 'columns':
|
|
109
|
-
|
|
147
|
+
case 'columns': {
|
|
148
|
+
const resolvedColumns = this.returningClause.columns.map(col => col === '*' ? '*' : this.resolveColumnName(col));
|
|
149
|
+
return format(' RETURNING %I', resolvedColumns);
|
|
150
|
+
}
|
|
110
151
|
case 'select': {
|
|
111
152
|
const selectSQL = this.returningClause.builder.toString();
|
|
112
153
|
return ` RETURNING (${selectSQL})`;
|
|
@@ -13,11 +13,22 @@ export class InsertBuilder {
|
|
|
13
13
|
_case = 'keep-case';
|
|
14
14
|
_convertCase = '2snake';
|
|
15
15
|
originalColumns;
|
|
16
|
+
columnResolver;
|
|
16
17
|
constructor(tableName, data) {
|
|
17
18
|
this.tableName = tableName;
|
|
18
19
|
this.insertData = [data];
|
|
19
20
|
this.originalColumns = Object.keys(data).sort();
|
|
20
21
|
}
|
|
22
|
+
setColumnResolver(resolver) {
|
|
23
|
+
this.columnResolver = resolver;
|
|
24
|
+
return this;
|
|
25
|
+
}
|
|
26
|
+
resolveColumnName(name) {
|
|
27
|
+
if (this.columnResolver) {
|
|
28
|
+
return this.columnResolver(name);
|
|
29
|
+
}
|
|
30
|
+
return this.convertColumnName(name);
|
|
31
|
+
}
|
|
21
32
|
convertCase(type, conversionCase = '2snake') {
|
|
22
33
|
this._case = type;
|
|
23
34
|
this._convertCase = conversionCase;
|
|
@@ -170,7 +181,7 @@ export class InsertBuilder {
|
|
|
170
181
|
throw new RelqBuilderError('Cannot generate INSERT query: no rows to insert', { builder: 'InsertBuilder', missing: 'data', hint: 'Add rows using addRow() or addRows() first' });
|
|
171
182
|
}
|
|
172
183
|
const originalColumns = Object.keys(this.insertData[0]);
|
|
173
|
-
const columns = originalColumns.map(name => this.
|
|
184
|
+
const columns = originalColumns.map(name => this.resolveColumnName(name));
|
|
174
185
|
const allValuesGroups = [];
|
|
175
186
|
for (const row of this.insertData) {
|
|
176
187
|
const { values, placeholders } = this.processRowValues(row, originalColumns);
|
|
@@ -224,8 +235,10 @@ export class InsertBuilder {
|
|
|
224
235
|
if (!this.returningClause)
|
|
225
236
|
return '';
|
|
226
237
|
switch (this.returningClause.type) {
|
|
227
|
-
case 'columns':
|
|
228
|
-
|
|
238
|
+
case 'columns': {
|
|
239
|
+
const resolvedColumns = this.returningClause.columns.map(col => col === '*' ? '*' : this.resolveColumnName(col));
|
|
240
|
+
return format(' RETURNING %I', resolvedColumns);
|
|
241
|
+
}
|
|
229
242
|
case 'select': {
|
|
230
243
|
const selectSQL = this.returningClause.builder.toString();
|
|
231
244
|
return ` RETURNING (${selectSQL})`;
|
|
@@ -11,10 +11,48 @@ export class UpdateBuilder {
|
|
|
11
11
|
returningClause;
|
|
12
12
|
_case = 'keep-case';
|
|
13
13
|
_convertCase = '2snake';
|
|
14
|
+
columnResolver;
|
|
14
15
|
constructor(tableName, data) {
|
|
15
16
|
this.tableName = tableName;
|
|
16
17
|
this.updateData = data;
|
|
17
18
|
}
|
|
19
|
+
setColumnResolver(resolver) {
|
|
20
|
+
this.columnResolver = resolver;
|
|
21
|
+
return this;
|
|
22
|
+
}
|
|
23
|
+
resolveColumnName(name) {
|
|
24
|
+
if (this.columnResolver) {
|
|
25
|
+
return this.columnResolver(name);
|
|
26
|
+
}
|
|
27
|
+
return this.convertColumnName(name);
|
|
28
|
+
}
|
|
29
|
+
transformConditionColumns(conditions) {
|
|
30
|
+
if (!this.columnResolver) {
|
|
31
|
+
return conditions;
|
|
32
|
+
}
|
|
33
|
+
return conditions.map(cond => {
|
|
34
|
+
if (!cond.column || cond.method === 'raw') {
|
|
35
|
+
return cond;
|
|
36
|
+
}
|
|
37
|
+
if (cond.method === 'or' || cond.method === 'and') {
|
|
38
|
+
return {
|
|
39
|
+
...cond,
|
|
40
|
+
values: this.transformConditionColumns(cond.values)
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
if (cond.column.includes('.')) {
|
|
44
|
+
const [tableRef, colName] = cond.column.split('.');
|
|
45
|
+
return {
|
|
46
|
+
...cond,
|
|
47
|
+
column: `${tableRef}.${this.columnResolver(colName)}`
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
...cond,
|
|
52
|
+
column: this.columnResolver(cond.column)
|
|
53
|
+
};
|
|
54
|
+
});
|
|
55
|
+
}
|
|
18
56
|
convertCase(type, conversionCase = '2snake') {
|
|
19
57
|
this._case = type;
|
|
20
58
|
this._convertCase = conversionCase;
|
|
@@ -104,7 +142,7 @@ export class UpdateBuilder {
|
|
|
104
142
|
}
|
|
105
143
|
toString() {
|
|
106
144
|
const processedPairs = Object.entries(this.updateData).map(([col, val]) => {
|
|
107
|
-
const convertedCol = this.
|
|
145
|
+
const convertedCol = this.resolveColumnName(col);
|
|
108
146
|
if (typeof val === 'function') {
|
|
109
147
|
const arrayBuilder = new ArrayUpdateBuilder(col);
|
|
110
148
|
const result = val(arrayBuilder);
|
|
@@ -118,7 +156,8 @@ export class UpdateBuilder {
|
|
|
118
156
|
});
|
|
119
157
|
let query = format('UPDATE %I SET %s', this.tableName, processedPairs.join(', '));
|
|
120
158
|
if (this.whereConditions.length > 0) {
|
|
121
|
-
|
|
159
|
+
const transformedConditions = this.transformConditionColumns(this.whereConditions);
|
|
160
|
+
query += ' WHERE ' + buildConditionsSQL(transformedConditions);
|
|
122
161
|
}
|
|
123
162
|
if (this.returningClause) {
|
|
124
163
|
query += this.buildReturningClause();
|
|
@@ -165,8 +204,10 @@ export class UpdateBuilder {
|
|
|
165
204
|
if (!this.returningClause)
|
|
166
205
|
return '';
|
|
167
206
|
switch (this.returningClause.type) {
|
|
168
|
-
case 'columns':
|
|
169
|
-
|
|
207
|
+
case 'columns': {
|
|
208
|
+
const resolvedColumns = this.returningClause.columns.map(col => col === '*' ? '*' : this.resolveColumnName(col));
|
|
209
|
+
return format(' RETURNING %I', resolvedColumns);
|
|
210
|
+
}
|
|
170
211
|
case 'select': {
|
|
171
212
|
const selectSQL = this.returningClause.builder.toString();
|
|
172
213
|
return ` RETURNING (${selectSQL})`;
|
package/dist/index.d.ts
CHANGED
|
@@ -474,9 +474,10 @@ export type Simplify<T> = {
|
|
|
474
474
|
[K in keyof T]: T[K];
|
|
475
475
|
} & {};
|
|
476
476
|
/**
|
|
477
|
-
* Clean a column type by removing DefaultValue union members
|
|
477
|
+
* Clean a column type by removing DefaultValue union members and symbols
|
|
478
|
+
* (symbols like EMPTY_OBJECT/EMPTY_ARRAY can leak into type inference from $default)
|
|
478
479
|
*/
|
|
479
|
-
export type CleanType<T> = Exclude<T, DefaultValue | (object & DefaultValue)>;
|
|
480
|
+
export type CleanType<T> = Exclude<T, DefaultValue | (object & DefaultValue) | symbol>;
|
|
480
481
|
/**
|
|
481
482
|
* Build SELECT type with smart required/optional:
|
|
482
483
|
* - Required: NOT NULL, PRIMARY KEY, has DEFAULT/GENERATED columns
|
|
@@ -1671,7 +1672,18 @@ export declare class InsertBuilder {
|
|
|
1671
1672
|
private _case;
|
|
1672
1673
|
private _convertCase;
|
|
1673
1674
|
private originalColumns;
|
|
1675
|
+
private columnResolver?;
|
|
1674
1676
|
constructor(tableName: string, data: Record<string, QueryValue>);
|
|
1677
|
+
/**
|
|
1678
|
+
* Set a column resolver function to transform property names to SQL column names.
|
|
1679
|
+
* @internal Used by ConnectedInsertBuilder for schema-aware column name mapping.
|
|
1680
|
+
*/
|
|
1681
|
+
setColumnResolver(resolver: (column: string) => string): InsertBuilder;
|
|
1682
|
+
/**
|
|
1683
|
+
* Resolve a column name using the column resolver or fallback to convertColumnName.
|
|
1684
|
+
* @internal
|
|
1685
|
+
*/
|
|
1686
|
+
private resolveColumnName;
|
|
1675
1687
|
convertCase(type: "keep-case" | "to-lower" | "to-upper"): InsertBuilder;
|
|
1676
1688
|
convertCase(type: "convert-case", conversionCase: ConversionType): InsertBuilder;
|
|
1677
1689
|
private validateColumns;
|
|
@@ -1817,7 +1829,24 @@ export declare class UpdateBuilder {
|
|
|
1817
1829
|
private returningClause?;
|
|
1818
1830
|
private _case;
|
|
1819
1831
|
private _convertCase;
|
|
1832
|
+
private columnResolver?;
|
|
1820
1833
|
constructor(tableName: string, data: Record<string, UpdateValue$1>);
|
|
1834
|
+
/**
|
|
1835
|
+
* Set a column resolver function to transform property names to SQL column names.
|
|
1836
|
+
* @internal Used by ConnectedUpdateBuilder for schema-aware column name mapping.
|
|
1837
|
+
*/
|
|
1838
|
+
setColumnResolver(resolver: (column: string) => string): UpdateBuilder;
|
|
1839
|
+
/**
|
|
1840
|
+
* Resolve a column name using the column resolver or fallback to convertColumnName.
|
|
1841
|
+
* @internal
|
|
1842
|
+
*/
|
|
1843
|
+
private resolveColumnName;
|
|
1844
|
+
/**
|
|
1845
|
+
* Transform column names in conditions using the column resolver.
|
|
1846
|
+
* Recursively handles nested or/and conditions.
|
|
1847
|
+
* @internal
|
|
1848
|
+
*/
|
|
1849
|
+
private transformConditionColumns;
|
|
1821
1850
|
convertCase(type: "keep-case" | "to-lower" | "to-upper"): UpdateBuilder;
|
|
1822
1851
|
convertCase(type: "convert-case", conversionCase: ConversionType): UpdateBuilder;
|
|
1823
1852
|
where(callback: (builder: ConditionBuilder) => ConditionBuilder): UpdateBuilder;
|
|
@@ -1932,7 +1961,24 @@ export declare class DeleteBuilder {
|
|
|
1932
1961
|
private tableName;
|
|
1933
1962
|
private whereConditions;
|
|
1934
1963
|
private returningClause?;
|
|
1964
|
+
private columnResolver?;
|
|
1935
1965
|
constructor(tableName: string);
|
|
1966
|
+
/**
|
|
1967
|
+
* Set a column resolver function to transform property names to SQL column names.
|
|
1968
|
+
* @internal Used by ConnectedDeleteBuilder for schema-aware column name mapping.
|
|
1969
|
+
*/
|
|
1970
|
+
setColumnResolver(resolver: (column: string) => string): DeleteBuilder;
|
|
1971
|
+
/**
|
|
1972
|
+
* Resolve a column name using the column resolver or return as-is.
|
|
1973
|
+
* @internal
|
|
1974
|
+
*/
|
|
1975
|
+
private resolveColumnName;
|
|
1976
|
+
/**
|
|
1977
|
+
* Transform column names in conditions using the column resolver.
|
|
1978
|
+
* Recursively handles nested or/and conditions.
|
|
1979
|
+
* @internal
|
|
1980
|
+
*/
|
|
1981
|
+
private transformConditionColumns;
|
|
1936
1982
|
where(callback: (builder: ConditionBuilder) => ConditionBuilder): DeleteBuilder;
|
|
1937
1983
|
/**
|
|
1938
1984
|
* RETURNING clause with simple column list
|
|
@@ -6547,9 +6593,22 @@ declare class ConnectedCountBuilder<TTable = any, TGroups extends Record<string,
|
|
|
6547
6593
|
declare class ReturningExecutor<TResult> {
|
|
6548
6594
|
private builder;
|
|
6549
6595
|
private relq;
|
|
6596
|
+
private tableName?;
|
|
6597
|
+
private schemaKey?;
|
|
6598
|
+
private columnMapping?;
|
|
6550
6599
|
constructor(builder: {
|
|
6551
6600
|
toString(): string;
|
|
6552
|
-
}, relq: Relq);
|
|
6601
|
+
}, relq: Relq, tableName?: string | undefined, schemaKey?: string | undefined);
|
|
6602
|
+
/**
|
|
6603
|
+
* Set up reverse column mapping (SQL name → TypeScript property name)
|
|
6604
|
+
* @internal
|
|
6605
|
+
*/
|
|
6606
|
+
private setupColumnMapping;
|
|
6607
|
+
/**
|
|
6608
|
+
* Transform a row's keys from SQL column names to TypeScript property names
|
|
6609
|
+
* @internal
|
|
6610
|
+
*/
|
|
6611
|
+
private transformRow;
|
|
6553
6612
|
/**
|
|
6554
6613
|
* Get SQL string
|
|
6555
6614
|
*/
|
|
@@ -6564,7 +6623,15 @@ declare class ReturningExecutor<TResult> {
|
|
|
6564
6623
|
declare class ConnectedDeleteBuilder<TTable = any> {
|
|
6565
6624
|
private builder;
|
|
6566
6625
|
private relq;
|
|
6567
|
-
|
|
6626
|
+
private tableName?;
|
|
6627
|
+
private schemaKey?;
|
|
6628
|
+
constructor(builder: DeleteBuilder, relq: Relq, tableName?: string | undefined, schemaKey?: string | undefined);
|
|
6629
|
+
/**
|
|
6630
|
+
* Set up column resolver to transform property names to SQL column names.
|
|
6631
|
+
* Uses schema metadata ($columnName) to resolve column names.
|
|
6632
|
+
* @internal
|
|
6633
|
+
*/
|
|
6634
|
+
private setupColumnResolver;
|
|
6568
6635
|
where(callback: (builder: TypedWhereCondition<TTable>) => any): this;
|
|
6569
6636
|
/**
|
|
6570
6637
|
* Get SQL string (always available)
|
|
@@ -6579,17 +6646,35 @@ declare class ConnectedDeleteBuilder<TTable = any> {
|
|
|
6579
6646
|
/**
|
|
6580
6647
|
* Set RETURNING clause - returns executor with typed run()
|
|
6581
6648
|
* Use '*' to return all columns, or specify column names
|
|
6649
|
+
* Pass null to skip RETURNING clause (useful for conditional returning)
|
|
6582
6650
|
*/
|
|
6583
|
-
returning
|
|
6651
|
+
returning(columns: null): this;
|
|
6652
|
+
returning(columns: "*"): ReturningExecutor<TTable extends {
|
|
6653
|
+
$inferSelect: infer S;
|
|
6654
|
+
} ? S : TTable>;
|
|
6655
|
+
returning<K extends string & ColumnName<TTable>>(columns: K | K[]): ReturningExecutor<Prettify<Pick<TTable extends {
|
|
6584
6656
|
$inferSelect: infer S;
|
|
6585
6657
|
} ? S : TTable, K & keyof (TTable extends {
|
|
6586
6658
|
$inferSelect: infer S;
|
|
6587
|
-
} ? S : TTable)
|
|
6659
|
+
} ? S : TTable)>>>;
|
|
6660
|
+
returning<K extends string & ColumnName<TTable>>(columns: K[] | null): this | ReturningExecutor<Prettify<Pick<TTable extends {
|
|
6661
|
+
$inferSelect: infer S;
|
|
6662
|
+
} ? S : TTable, K & keyof (TTable extends {
|
|
6663
|
+
$inferSelect: infer S;
|
|
6664
|
+
} ? S : TTable)>>>;
|
|
6588
6665
|
}
|
|
6589
6666
|
declare class ConnectedInsertBuilder<TTable = any> {
|
|
6590
6667
|
private builder;
|
|
6591
6668
|
private relq;
|
|
6592
|
-
|
|
6669
|
+
private tableName?;
|
|
6670
|
+
private schemaKey?;
|
|
6671
|
+
constructor(builder: InsertBuilder, relq: Relq, tableName?: string | undefined, schemaKey?: string | undefined);
|
|
6672
|
+
/**
|
|
6673
|
+
* Set up column resolver to transform property names to SQL column names.
|
|
6674
|
+
* Uses schema metadata ($columnName) to resolve column names.
|
|
6675
|
+
* @internal
|
|
6676
|
+
*/
|
|
6677
|
+
private setupColumnResolver;
|
|
6593
6678
|
addRow(row: InsertData<TTable>): this;
|
|
6594
6679
|
addRows(rows: InsertData<TTable>[]): this;
|
|
6595
6680
|
clear(): this;
|
|
@@ -6623,17 +6708,35 @@ declare class ConnectedInsertBuilder<TTable = any> {
|
|
|
6623
6708
|
/**
|
|
6624
6709
|
* Set RETURNING clause - returns executor with typed run()
|
|
6625
6710
|
* Use '*' to return all columns, or specify column names
|
|
6711
|
+
* Pass null to skip RETURNING clause (useful for conditional returning)
|
|
6626
6712
|
*/
|
|
6627
|
-
returning
|
|
6713
|
+
returning(columns: null): this;
|
|
6714
|
+
returning(columns: "*"): ReturningExecutor<TTable extends {
|
|
6715
|
+
$inferSelect: infer S;
|
|
6716
|
+
} ? S : TTable>;
|
|
6717
|
+
returning<K extends string & ColumnName<TTable>>(columns: K | K[]): ReturningExecutor<Prettify<Pick<TTable extends {
|
|
6628
6718
|
$inferSelect: infer S;
|
|
6629
6719
|
} ? S : TTable, K & keyof (TTable extends {
|
|
6630
6720
|
$inferSelect: infer S;
|
|
6631
|
-
} ? S : TTable)
|
|
6721
|
+
} ? S : TTable)>>>;
|
|
6722
|
+
returning<K extends string & ColumnName<TTable>>(columns: K[] | null): this | ReturningExecutor<Prettify<Pick<TTable extends {
|
|
6723
|
+
$inferSelect: infer S;
|
|
6724
|
+
} ? S : TTable, K & keyof (TTable extends {
|
|
6725
|
+
$inferSelect: infer S;
|
|
6726
|
+
} ? S : TTable)>>>;
|
|
6632
6727
|
}
|
|
6633
6728
|
declare class ConnectedUpdateBuilder<TTable = any> {
|
|
6634
6729
|
private builder;
|
|
6635
6730
|
private relq;
|
|
6636
|
-
|
|
6731
|
+
private tableName?;
|
|
6732
|
+
private schemaKey?;
|
|
6733
|
+
constructor(builder: UpdateBuilder, relq: Relq, tableName?: string | undefined, schemaKey?: string | undefined);
|
|
6734
|
+
/**
|
|
6735
|
+
* Set up column resolver to transform property names to SQL column names.
|
|
6736
|
+
* Uses schema metadata ($columnName) to resolve column names.
|
|
6737
|
+
* @internal
|
|
6738
|
+
*/
|
|
6739
|
+
private setupColumnResolver;
|
|
6637
6740
|
where(callback: (builder: TypedWhereCondition<TTable>) => any): this;
|
|
6638
6741
|
/**
|
|
6639
6742
|
* Get SQL string (always available)
|
|
@@ -6648,12 +6751,22 @@ declare class ConnectedUpdateBuilder<TTable = any> {
|
|
|
6648
6751
|
/**
|
|
6649
6752
|
* Set RETURNING clause - returns executor with typed run()
|
|
6650
6753
|
* Use '*' to return all columns, or specify column names
|
|
6754
|
+
* Pass null to skip RETURNING clause (useful for conditional returning)
|
|
6651
6755
|
*/
|
|
6652
|
-
returning
|
|
6756
|
+
returning(columns: null): this;
|
|
6757
|
+
returning(columns: "*"): ReturningExecutor<TTable extends {
|
|
6758
|
+
$inferSelect: infer S;
|
|
6759
|
+
} ? S : TTable>;
|
|
6760
|
+
returning<K extends string & ColumnName<TTable>>(columns: K | K[]): ReturningExecutor<Prettify<Pick<TTable extends {
|
|
6761
|
+
$inferSelect: infer S;
|
|
6762
|
+
} ? S : TTable, K & keyof (TTable extends {
|
|
6763
|
+
$inferSelect: infer S;
|
|
6764
|
+
} ? S : TTable)>>>;
|
|
6765
|
+
returning<K extends string & ColumnName<TTable>>(columns: K[] | null): this | ReturningExecutor<Prettify<Pick<TTable extends {
|
|
6653
6766
|
$inferSelect: infer S;
|
|
6654
6767
|
} ? S : TTable, K & keyof (TTable extends {
|
|
6655
6768
|
$inferSelect: infer S;
|
|
6656
|
-
} ? S : TTable)
|
|
6769
|
+
} ? S : TTable)>>>;
|
|
6657
6770
|
}
|
|
6658
6771
|
declare class PaginateBuilder<TSchema, TTable, T> {
|
|
6659
6772
|
private relq;
|
package/dist/schema-builder.d.ts
CHANGED
|
@@ -2779,9 +2779,10 @@ export type Simplify<T> = {
|
|
|
2779
2779
|
[K in keyof T]: T[K];
|
|
2780
2780
|
} & {};
|
|
2781
2781
|
/**
|
|
2782
|
-
* Clean a column type by removing DefaultValue union members
|
|
2782
|
+
* Clean a column type by removing DefaultValue union members and symbols
|
|
2783
|
+
* (symbols like EMPTY_OBJECT/EMPTY_ARRAY can leak into type inference from $default)
|
|
2783
2784
|
*/
|
|
2784
|
-
export type CleanType<T> = Exclude<T, DefaultValue | (object & DefaultValue)>;
|
|
2785
|
+
export type CleanType<T> = Exclude<T, DefaultValue | (object & DefaultValue) | symbol>;
|
|
2785
2786
|
/**
|
|
2786
2787
|
* Build SELECT type with smart required/optional:
|
|
2787
2788
|
* - Required: NOT NULL, PRIMARY KEY, has DEFAULT/GENERATED columns
|