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.
@@ -6,9 +6,32 @@ const ReturningExecutor_1 = require("./ReturningExecutor.cjs");
6
6
  class ConnectedDeleteBuilder {
7
7
  builder;
8
8
  relq;
9
- constructor(builder, relq) {
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
- constructor(builder, relq) {
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.$sqlName || columnDef.$name || camelToSnake(column);
40
+ return columnDef.$columnName || column;
44
41
  }
45
- return camelToSnake(column);
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?.$sqlName || columnDef?.$name || camelToSnake(prop);
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?.$sqlName || columnDef?.$name || camelToSnake(prop);
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
- constructor(builder, relq) {
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
- constructor(builder, relq) {
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 result.data;
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
- query += ' WHERE ' + (0, condition_collector_1.buildConditionsSQL)(this.whereConditions);
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
- return (0, pg_format_1.default)(' RETURNING %I', this.returningClause.columns);
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.convertColumnName(name));
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
- return (0, pg_format_1.default)(' RETURNING %I', this.returningClause.columns);
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.convertColumnName(col);
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
- query += ' WHERE ' + (0, condition_collector_1.buildConditionsSQL)(this.whereConditions);
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
- return (0, pg_format_1.default)(' RETURNING %I', this.returningClause.columns);
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
- constructor(builder, relq) {
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
- constructor(builder, relq) {
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.$sqlName || columnDef.$name || camelToSnake(column);
34
+ return columnDef.$columnName || column;
38
35
  }
39
- return camelToSnake(column);
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?.$sqlName || columnDef?.$name || camelToSnake(prop);
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?.$sqlName || columnDef?.$name || camelToSnake(prop);
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
- constructor(builder, relq) {
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
- constructor(builder, relq) {
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 result.data;
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
- query += ' WHERE ' + buildConditionsSQL(this.whereConditions);
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
- return format(' RETURNING %I', this.returningClause.columns);
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.convertColumnName(name));
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
- return format(' RETURNING %I', this.returningClause.columns);
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.convertColumnName(col);
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
- query += ' WHERE ' + buildConditionsSQL(this.whereConditions);
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
- return format(' RETURNING %I', this.returningClause.columns);
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
- constructor(builder: DeleteBuilder, relq: Relq);
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<K extends string & ColumnName<TTable>>(columns: "*" | K | K[]): ReturningExecutor<Pick<TTable extends {
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
- constructor(builder: InsertBuilder, relq: Relq);
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<K extends string & ColumnName<TTable>>(columns: "*" | K | K[]): ReturningExecutor<Pick<TTable extends {
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
- constructor(builder: UpdateBuilder, relq: Relq);
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<K extends string & ColumnName<TTable>>(columns: "*" | K | K[]): ReturningExecutor<Pick<TTable extends {
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;
@@ -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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "relq",
3
- "version": "1.0.39",
3
+ "version": "1.0.41",
4
4
  "description": "The Fully-Typed PostgreSQL ORM for TypeScript",
5
5
  "author": "Olajide Mathew O. <olajide.mathew@yuniq.solutions>",
6
6
  "license": "MIT",