drizzle-orm 1.0.0-beta.1-7946562 → 1.0.0-beta.1-5e64efc
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/gel-core/columns/common.cjs +8 -0
- package/gel-core/columns/common.cjs.map +1 -1
- package/gel-core/columns/common.d.cts +2 -0
- package/gel-core/columns/common.d.ts +2 -0
- package/gel-core/columns/common.js +8 -0
- package/gel-core/columns/common.js.map +1 -1
- package/gel-core/columns/custom.cjs +12 -0
- package/gel-core/columns/custom.cjs.map +1 -1
- package/gel-core/columns/custom.d.cts +117 -6
- package/gel-core/columns/custom.d.ts +117 -6
- package/gel-core/columns/custom.js +12 -0
- package/gel-core/columns/custom.js.map +1 -1
- package/gel-core/dialect.cjs +21 -2
- package/gel-core/dialect.cjs.map +1 -1
- package/gel-core/dialect.js +22 -3
- package/gel-core/dialect.js.map +1 -1
- package/mysql-core/columns/custom.cjs +28 -0
- package/mysql-core/columns/custom.cjs.map +1 -1
- package/mysql-core/columns/custom.d.cts +119 -6
- package/mysql-core/columns/custom.d.ts +119 -6
- package/mysql-core/columns/custom.js +28 -0
- package/mysql-core/columns/custom.js.map +1 -1
- package/mysql-core/dialect.cjs +3 -0
- package/mysql-core/dialect.cjs.map +1 -1
- package/mysql-core/dialect.js +3 -0
- package/mysql-core/dialect.js.map +1 -1
- package/package.json +145 -145
- package/pg-core/columns/common.cjs +8 -0
- package/pg-core/columns/common.cjs.map +1 -1
- package/pg-core/columns/common.d.cts +1 -0
- package/pg-core/columns/common.d.ts +1 -0
- package/pg-core/columns/common.js +8 -0
- package/pg-core/columns/common.js.map +1 -1
- package/pg-core/columns/custom.cjs +27 -0
- package/pg-core/columns/custom.cjs.map +1 -1
- package/pg-core/columns/custom.d.cts +119 -6
- package/pg-core/columns/custom.d.ts +119 -6
- package/pg-core/columns/custom.js +27 -0
- package/pg-core/columns/custom.js.map +1 -1
- package/pg-core/dialect.cjs +7 -3
- package/pg-core/dialect.cjs.map +1 -1
- package/pg-core/dialect.js +7 -3
- package/pg-core/dialect.js.map +1 -1
- package/relations.cjs +1 -1
- package/relations.cjs.map +1 -1
- package/relations.js +1 -1
- package/relations.js.map +1 -1
- package/singlestore-core/columns/custom.cjs +28 -0
- package/singlestore-core/columns/custom.cjs.map +1 -1
- package/singlestore-core/columns/custom.d.cts +119 -6
- package/singlestore-core/columns/custom.d.ts +119 -6
- package/singlestore-core/columns/custom.js +28 -0
- package/singlestore-core/columns/custom.js.map +1 -1
- package/sql/sql.cjs.map +1 -1
- package/sql/sql.d.cts +1 -0
- package/sql/sql.d.ts +1 -0
- package/sql/sql.js.map +1 -1
- package/sqlite-core/columns/custom.cjs +27 -0
- package/sqlite-core/columns/custom.cjs.map +1 -1
- package/sqlite-core/columns/custom.d.cts +119 -6
- package/sqlite-core/columns/custom.d.ts +119 -6
- package/sqlite-core/columns/custom.js +27 -0
- package/sqlite-core/columns/custom.js.map +1 -1
- package/sqlite-core/dialect.cjs +3 -0
- package/sqlite-core/dialect.cjs.map +1 -1
- package/sqlite-core/dialect.js +3 -0
- package/sqlite-core/dialect.js.map +1 -1
- package/version.cjs +1 -1
- package/version.d.cts +1 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
|
@@ -2,7 +2,7 @@ import type { ColumnBuilderBaseConfig } from "../../column-builder.cjs";
|
|
|
2
2
|
import type { ColumnBaseConfig } from "../../column.cjs";
|
|
3
3
|
import { entityKind } from "../../entity.cjs";
|
|
4
4
|
import type { AnyPgTable } from "../table.cjs";
|
|
5
|
-
import type { SQL } from "../../sql/sql.cjs";
|
|
5
|
+
import type { SQL, SQLGenerator } from "../../sql/sql.cjs";
|
|
6
6
|
import { type Equal } from "../../utils.cjs";
|
|
7
7
|
import { PgColumn, PgColumnBuilder } from "./common.cjs";
|
|
8
8
|
export type ConvertCustomConfig<TName extends string, T extends Partial<CustomTypeValues>> = {
|
|
@@ -34,14 +34,18 @@ export declare class PgCustomColumn<T extends ColumnBaseConfig<'custom', 'PgCust
|
|
|
34
34
|
private sqlName;
|
|
35
35
|
private mapTo?;
|
|
36
36
|
private mapFrom?;
|
|
37
|
+
private mapJson?;
|
|
38
|
+
private forJsonSelect?;
|
|
37
39
|
constructor(table: AnyPgTable<{
|
|
38
40
|
name: T['tableName'];
|
|
39
41
|
}>, config: PgCustomColumnBuilder<T>['config']);
|
|
40
42
|
getSQLType(): string;
|
|
41
43
|
mapFromDriverValue(value: T['driverParam']): T['data'];
|
|
44
|
+
mapFromJsonValue(value: unknown): T['data'];
|
|
45
|
+
jsonSelectIdentifier(identifier: SQL, sql: SQLGenerator, arrayDimensions?: number): SQL;
|
|
42
46
|
mapToDriverValue(value: T['data']): T['driverParam'];
|
|
43
47
|
}
|
|
44
|
-
export
|
|
48
|
+
export interface CustomTypeValues {
|
|
45
49
|
/**
|
|
46
50
|
* Required type for custom column, that will infer proper type model
|
|
47
51
|
*
|
|
@@ -56,6 +60,18 @@ export type CustomTypeValues = {
|
|
|
56
60
|
* Type helper, that represents what type database driver is accepting for specific database data type
|
|
57
61
|
*/
|
|
58
62
|
driverData?: unknown;
|
|
63
|
+
/**
|
|
64
|
+
* Type helper, that represents what type database driver is returning for specific database data type
|
|
65
|
+
*
|
|
66
|
+
* Needed only in case driver's output and input for type differ
|
|
67
|
+
*
|
|
68
|
+
* Defaults to {@link driverData}
|
|
69
|
+
*/
|
|
70
|
+
driverOutput?: unknown;
|
|
71
|
+
/**
|
|
72
|
+
* Type helper, that represents what type field returns after being aggregated to JSON
|
|
73
|
+
*/
|
|
74
|
+
jsonData?: unknown;
|
|
59
75
|
/**
|
|
60
76
|
* What config type should be used for {@link CustomTypeParams} `dataType` generation
|
|
61
77
|
*/
|
|
@@ -87,7 +103,7 @@ export type CustomTypeValues = {
|
|
|
87
103
|
* });
|
|
88
104
|
*/
|
|
89
105
|
default?: boolean;
|
|
90
|
-
}
|
|
106
|
+
}
|
|
91
107
|
export interface CustomTypeParams<T extends CustomTypeValues> {
|
|
92
108
|
/**
|
|
93
109
|
* Database data type string representation, that is used for migrations
|
|
@@ -120,7 +136,7 @@ export interface CustomTypeParams<T extends CustomTypeValues> {
|
|
|
120
136
|
*/
|
|
121
137
|
dataType: (config: T['config'] | (Equal<T['configRequired'], true> extends true ? never : undefined)) => string;
|
|
122
138
|
/**
|
|
123
|
-
* Optional mapping function,
|
|
139
|
+
* Optional mapping function, that is used to transform inputs from desired to be used in code format to one suitable for driver
|
|
124
140
|
* @example
|
|
125
141
|
* For example, when using jsonb we need to map JS/TS object to string before writing to database
|
|
126
142
|
* ```
|
|
@@ -131,16 +147,113 @@ export interface CustomTypeParams<T extends CustomTypeValues> {
|
|
|
131
147
|
*/
|
|
132
148
|
toDriver?: (value: T['data']) => T['driverData'] | SQL;
|
|
133
149
|
/**
|
|
134
|
-
* Optional mapping function, that is
|
|
150
|
+
* Optional mapping function, that is used for transforming data returned by driver to desired column's output format
|
|
135
151
|
* @example
|
|
136
152
|
* For example, when using timestamp we need to map string Date representation to JS Date
|
|
137
153
|
* ```
|
|
138
154
|
* fromDriver(value: string): Date {
|
|
139
155
|
* return new Date(value);
|
|
156
|
+
* }
|
|
157
|
+
* ```
|
|
158
|
+
*
|
|
159
|
+
* It'll cause the returned data to change from:
|
|
160
|
+
* ```
|
|
161
|
+
* {
|
|
162
|
+
* customField: "2025-04-07T03:25:16.635Z";
|
|
163
|
+
* }
|
|
164
|
+
* ```
|
|
165
|
+
* to:
|
|
166
|
+
* ```
|
|
167
|
+
* {
|
|
168
|
+
* customField: new Date("2025-04-07T03:25:16.635Z");
|
|
169
|
+
* }
|
|
170
|
+
* ```
|
|
171
|
+
*/
|
|
172
|
+
fromDriver?: (value: 'driverOutput' extends keyof T ? T['driverOutput'] : T['driverData']) => T['data'];
|
|
173
|
+
/**
|
|
174
|
+
* Optional mapping function, that is used for transforming data returned by transofmed to JSON in database data to desired format
|
|
175
|
+
*
|
|
176
|
+
* Used by [relational queries](https://orm.drizzle.team/docs/rqb-v2)
|
|
177
|
+
*
|
|
178
|
+
* Defaults to {@link fromDriver} function
|
|
179
|
+
* @example
|
|
180
|
+
* For example, when querying bigint column via [RQB](https://orm.drizzle.team/docs/rqb-v2) or [JSON functions](https://orm.drizzle.team/docs/json-functions), the result field will be returned as it's string representation, as opposed to bigint from regular query
|
|
181
|
+
* To handle that, we need a separate function to handle such field's mapping:
|
|
182
|
+
* ```
|
|
183
|
+
* fromJson(value: string): bigint {
|
|
184
|
+
* return BigInt(value);
|
|
140
185
|
* },
|
|
141
186
|
* ```
|
|
187
|
+
*
|
|
188
|
+
* It'll cause the returned data to change from:
|
|
189
|
+
* ```
|
|
190
|
+
* {
|
|
191
|
+
* customField: "5044565289845416380";
|
|
192
|
+
* }
|
|
193
|
+
* ```
|
|
194
|
+
* to:
|
|
195
|
+
* ```
|
|
196
|
+
* {
|
|
197
|
+
* customField: 5044565289845416380n;
|
|
198
|
+
* }
|
|
199
|
+
* ```
|
|
200
|
+
*/
|
|
201
|
+
fromJson?: (value: T['jsonData']) => T['data'];
|
|
202
|
+
/**
|
|
203
|
+
* Optional selection modifier function, that is used for modifying selection of column inside [JSON functions](https://orm.drizzle.team/docs/json-functions)
|
|
204
|
+
*
|
|
205
|
+
* Additional mapping that could be required for such scenarios can be handled using {@link fromJson} function
|
|
206
|
+
*
|
|
207
|
+
* Used by [relational queries](https://orm.drizzle.team/docs/rqb-v2)
|
|
208
|
+
*
|
|
209
|
+
* Following types are being casted to text by default: `bytea`, `geometry`, `timestamp`, `numeric`, `bigint`
|
|
210
|
+
* @example
|
|
211
|
+
* For example, when using bigint we need to cast field to text to preserve data integrity
|
|
212
|
+
* ```
|
|
213
|
+
* forJsonSelect(identifier: SQL, sql: SQLGenerator, arrayDimensions?: number): SQL {
|
|
214
|
+
* return sql`${identifier}::text`
|
|
215
|
+
* },
|
|
216
|
+
* ```
|
|
217
|
+
*
|
|
218
|
+
* This will change query from:
|
|
219
|
+
* ```
|
|
220
|
+
* SELECT
|
|
221
|
+
* row_to_json("t".*)
|
|
222
|
+
* FROM
|
|
223
|
+
* (
|
|
224
|
+
* SELECT
|
|
225
|
+
* "table"."custom_bigint" AS "bigint"
|
|
226
|
+
* FROM
|
|
227
|
+
* "table"
|
|
228
|
+
* ) AS "t"
|
|
229
|
+
* ```
|
|
230
|
+
* to:
|
|
231
|
+
* ```
|
|
232
|
+
* SELECT
|
|
233
|
+
* row_to_json("t".*)
|
|
234
|
+
* FROM
|
|
235
|
+
* (
|
|
236
|
+
* SELECT
|
|
237
|
+
* "table"."custom_bigint"::text AS "bigint"
|
|
238
|
+
* FROM
|
|
239
|
+
* "table"
|
|
240
|
+
* ) AS "t"
|
|
241
|
+
* ```
|
|
242
|
+
*
|
|
243
|
+
* Returned by query object will change from:
|
|
244
|
+
* ```
|
|
245
|
+
* {
|
|
246
|
+
* bigint: 5044565289845416000; // Partial data loss due to direct conversion to JSON format
|
|
247
|
+
* }
|
|
248
|
+
* ```
|
|
249
|
+
* to:
|
|
250
|
+
* ```
|
|
251
|
+
* {
|
|
252
|
+
* bigint: "5044565289845416380"; // Data is preserved due to conversion of field to text before JSON-ification
|
|
253
|
+
* }
|
|
254
|
+
* ```
|
|
142
255
|
*/
|
|
143
|
-
|
|
256
|
+
forJsonSelect?: (identifier: SQL, sql: SQLGenerator, arrayDimensions?: number) => SQL;
|
|
144
257
|
}
|
|
145
258
|
/**
|
|
146
259
|
* Custom pg database data type generator
|
|
@@ -2,7 +2,7 @@ import type { ColumnBuilderBaseConfig } from "../../column-builder.js";
|
|
|
2
2
|
import type { ColumnBaseConfig } from "../../column.js";
|
|
3
3
|
import { entityKind } from "../../entity.js";
|
|
4
4
|
import type { AnyPgTable } from "../table.js";
|
|
5
|
-
import type { SQL } from "../../sql/sql.js";
|
|
5
|
+
import type { SQL, SQLGenerator } from "../../sql/sql.js";
|
|
6
6
|
import { type Equal } from "../../utils.js";
|
|
7
7
|
import { PgColumn, PgColumnBuilder } from "./common.js";
|
|
8
8
|
export type ConvertCustomConfig<TName extends string, T extends Partial<CustomTypeValues>> = {
|
|
@@ -34,14 +34,18 @@ export declare class PgCustomColumn<T extends ColumnBaseConfig<'custom', 'PgCust
|
|
|
34
34
|
private sqlName;
|
|
35
35
|
private mapTo?;
|
|
36
36
|
private mapFrom?;
|
|
37
|
+
private mapJson?;
|
|
38
|
+
private forJsonSelect?;
|
|
37
39
|
constructor(table: AnyPgTable<{
|
|
38
40
|
name: T['tableName'];
|
|
39
41
|
}>, config: PgCustomColumnBuilder<T>['config']);
|
|
40
42
|
getSQLType(): string;
|
|
41
43
|
mapFromDriverValue(value: T['driverParam']): T['data'];
|
|
44
|
+
mapFromJsonValue(value: unknown): T['data'];
|
|
45
|
+
jsonSelectIdentifier(identifier: SQL, sql: SQLGenerator, arrayDimensions?: number): SQL;
|
|
42
46
|
mapToDriverValue(value: T['data']): T['driverParam'];
|
|
43
47
|
}
|
|
44
|
-
export
|
|
48
|
+
export interface CustomTypeValues {
|
|
45
49
|
/**
|
|
46
50
|
* Required type for custom column, that will infer proper type model
|
|
47
51
|
*
|
|
@@ -56,6 +60,18 @@ export type CustomTypeValues = {
|
|
|
56
60
|
* Type helper, that represents what type database driver is accepting for specific database data type
|
|
57
61
|
*/
|
|
58
62
|
driverData?: unknown;
|
|
63
|
+
/**
|
|
64
|
+
* Type helper, that represents what type database driver is returning for specific database data type
|
|
65
|
+
*
|
|
66
|
+
* Needed only in case driver's output and input for type differ
|
|
67
|
+
*
|
|
68
|
+
* Defaults to {@link driverData}
|
|
69
|
+
*/
|
|
70
|
+
driverOutput?: unknown;
|
|
71
|
+
/**
|
|
72
|
+
* Type helper, that represents what type field returns after being aggregated to JSON
|
|
73
|
+
*/
|
|
74
|
+
jsonData?: unknown;
|
|
59
75
|
/**
|
|
60
76
|
* What config type should be used for {@link CustomTypeParams} `dataType` generation
|
|
61
77
|
*/
|
|
@@ -87,7 +103,7 @@ export type CustomTypeValues = {
|
|
|
87
103
|
* });
|
|
88
104
|
*/
|
|
89
105
|
default?: boolean;
|
|
90
|
-
}
|
|
106
|
+
}
|
|
91
107
|
export interface CustomTypeParams<T extends CustomTypeValues> {
|
|
92
108
|
/**
|
|
93
109
|
* Database data type string representation, that is used for migrations
|
|
@@ -120,7 +136,7 @@ export interface CustomTypeParams<T extends CustomTypeValues> {
|
|
|
120
136
|
*/
|
|
121
137
|
dataType: (config: T['config'] | (Equal<T['configRequired'], true> extends true ? never : undefined)) => string;
|
|
122
138
|
/**
|
|
123
|
-
* Optional mapping function,
|
|
139
|
+
* Optional mapping function, that is used to transform inputs from desired to be used in code format to one suitable for driver
|
|
124
140
|
* @example
|
|
125
141
|
* For example, when using jsonb we need to map JS/TS object to string before writing to database
|
|
126
142
|
* ```
|
|
@@ -131,16 +147,113 @@ export interface CustomTypeParams<T extends CustomTypeValues> {
|
|
|
131
147
|
*/
|
|
132
148
|
toDriver?: (value: T['data']) => T['driverData'] | SQL;
|
|
133
149
|
/**
|
|
134
|
-
* Optional mapping function, that is
|
|
150
|
+
* Optional mapping function, that is used for transforming data returned by driver to desired column's output format
|
|
135
151
|
* @example
|
|
136
152
|
* For example, when using timestamp we need to map string Date representation to JS Date
|
|
137
153
|
* ```
|
|
138
154
|
* fromDriver(value: string): Date {
|
|
139
155
|
* return new Date(value);
|
|
156
|
+
* }
|
|
157
|
+
* ```
|
|
158
|
+
*
|
|
159
|
+
* It'll cause the returned data to change from:
|
|
160
|
+
* ```
|
|
161
|
+
* {
|
|
162
|
+
* customField: "2025-04-07T03:25:16.635Z";
|
|
163
|
+
* }
|
|
164
|
+
* ```
|
|
165
|
+
* to:
|
|
166
|
+
* ```
|
|
167
|
+
* {
|
|
168
|
+
* customField: new Date("2025-04-07T03:25:16.635Z");
|
|
169
|
+
* }
|
|
170
|
+
* ```
|
|
171
|
+
*/
|
|
172
|
+
fromDriver?: (value: 'driverOutput' extends keyof T ? T['driverOutput'] : T['driverData']) => T['data'];
|
|
173
|
+
/**
|
|
174
|
+
* Optional mapping function, that is used for transforming data returned by transofmed to JSON in database data to desired format
|
|
175
|
+
*
|
|
176
|
+
* Used by [relational queries](https://orm.drizzle.team/docs/rqb-v2)
|
|
177
|
+
*
|
|
178
|
+
* Defaults to {@link fromDriver} function
|
|
179
|
+
* @example
|
|
180
|
+
* For example, when querying bigint column via [RQB](https://orm.drizzle.team/docs/rqb-v2) or [JSON functions](https://orm.drizzle.team/docs/json-functions), the result field will be returned as it's string representation, as opposed to bigint from regular query
|
|
181
|
+
* To handle that, we need a separate function to handle such field's mapping:
|
|
182
|
+
* ```
|
|
183
|
+
* fromJson(value: string): bigint {
|
|
184
|
+
* return BigInt(value);
|
|
140
185
|
* },
|
|
141
186
|
* ```
|
|
187
|
+
*
|
|
188
|
+
* It'll cause the returned data to change from:
|
|
189
|
+
* ```
|
|
190
|
+
* {
|
|
191
|
+
* customField: "5044565289845416380";
|
|
192
|
+
* }
|
|
193
|
+
* ```
|
|
194
|
+
* to:
|
|
195
|
+
* ```
|
|
196
|
+
* {
|
|
197
|
+
* customField: 5044565289845416380n;
|
|
198
|
+
* }
|
|
199
|
+
* ```
|
|
200
|
+
*/
|
|
201
|
+
fromJson?: (value: T['jsonData']) => T['data'];
|
|
202
|
+
/**
|
|
203
|
+
* Optional selection modifier function, that is used for modifying selection of column inside [JSON functions](https://orm.drizzle.team/docs/json-functions)
|
|
204
|
+
*
|
|
205
|
+
* Additional mapping that could be required for such scenarios can be handled using {@link fromJson} function
|
|
206
|
+
*
|
|
207
|
+
* Used by [relational queries](https://orm.drizzle.team/docs/rqb-v2)
|
|
208
|
+
*
|
|
209
|
+
* Following types are being casted to text by default: `bytea`, `geometry`, `timestamp`, `numeric`, `bigint`
|
|
210
|
+
* @example
|
|
211
|
+
* For example, when using bigint we need to cast field to text to preserve data integrity
|
|
212
|
+
* ```
|
|
213
|
+
* forJsonSelect(identifier: SQL, sql: SQLGenerator, arrayDimensions?: number): SQL {
|
|
214
|
+
* return sql`${identifier}::text`
|
|
215
|
+
* },
|
|
216
|
+
* ```
|
|
217
|
+
*
|
|
218
|
+
* This will change query from:
|
|
219
|
+
* ```
|
|
220
|
+
* SELECT
|
|
221
|
+
* row_to_json("t".*)
|
|
222
|
+
* FROM
|
|
223
|
+
* (
|
|
224
|
+
* SELECT
|
|
225
|
+
* "table"."custom_bigint" AS "bigint"
|
|
226
|
+
* FROM
|
|
227
|
+
* "table"
|
|
228
|
+
* ) AS "t"
|
|
229
|
+
* ```
|
|
230
|
+
* to:
|
|
231
|
+
* ```
|
|
232
|
+
* SELECT
|
|
233
|
+
* row_to_json("t".*)
|
|
234
|
+
* FROM
|
|
235
|
+
* (
|
|
236
|
+
* SELECT
|
|
237
|
+
* "table"."custom_bigint"::text AS "bigint"
|
|
238
|
+
* FROM
|
|
239
|
+
* "table"
|
|
240
|
+
* ) AS "t"
|
|
241
|
+
* ```
|
|
242
|
+
*
|
|
243
|
+
* Returned by query object will change from:
|
|
244
|
+
* ```
|
|
245
|
+
* {
|
|
246
|
+
* bigint: 5044565289845416000; // Partial data loss due to direct conversion to JSON format
|
|
247
|
+
* }
|
|
248
|
+
* ```
|
|
249
|
+
* to:
|
|
250
|
+
* ```
|
|
251
|
+
* {
|
|
252
|
+
* bigint: "5044565289845416380"; // Data is preserved due to conversion of field to text before JSON-ification
|
|
253
|
+
* }
|
|
254
|
+
* ```
|
|
142
255
|
*/
|
|
143
|
-
|
|
256
|
+
forJsonSelect?: (identifier: SQL, sql: SQLGenerator, arrayDimensions?: number) => SQL;
|
|
144
257
|
}
|
|
145
258
|
/**
|
|
146
259
|
* Custom pg database data type generator
|
|
@@ -21,11 +21,15 @@ class PgCustomColumn extends PgColumn {
|
|
|
21
21
|
sqlName;
|
|
22
22
|
mapTo;
|
|
23
23
|
mapFrom;
|
|
24
|
+
mapJson;
|
|
25
|
+
forJsonSelect;
|
|
24
26
|
constructor(table, config) {
|
|
25
27
|
super(table, config);
|
|
26
28
|
this.sqlName = config.customTypeParams.dataType(config.fieldConfig);
|
|
27
29
|
this.mapTo = config.customTypeParams.toDriver;
|
|
28
30
|
this.mapFrom = config.customTypeParams.fromDriver;
|
|
31
|
+
this.mapJson = config.customTypeParams.fromJson;
|
|
32
|
+
this.forJsonSelect = config.customTypeParams.forJsonSelect;
|
|
29
33
|
}
|
|
30
34
|
getSQLType() {
|
|
31
35
|
return this.sqlName;
|
|
@@ -33,6 +37,29 @@ class PgCustomColumn extends PgColumn {
|
|
|
33
37
|
mapFromDriverValue(value) {
|
|
34
38
|
return typeof this.mapFrom === "function" ? this.mapFrom(value) : value;
|
|
35
39
|
}
|
|
40
|
+
mapFromJsonValue(value) {
|
|
41
|
+
return typeof this.mapJson === "function" ? this.mapJson(value) : this.mapFromDriverValue(value);
|
|
42
|
+
}
|
|
43
|
+
jsonSelectIdentifier(identifier, sql, arrayDimensions) {
|
|
44
|
+
if (typeof this.forJsonSelect === "function")
|
|
45
|
+
return this.forJsonSelect(identifier, sql, arrayDimensions);
|
|
46
|
+
const rawType = this.getSQLType().toLowerCase();
|
|
47
|
+
const parenPos = rawType.indexOf("(");
|
|
48
|
+
const type = parenPos + 1 ? rawType.slice(0, parenPos) : rawType;
|
|
49
|
+
switch (type) {
|
|
50
|
+
case "bytea":
|
|
51
|
+
case "geometry":
|
|
52
|
+
case "timestamp":
|
|
53
|
+
case "numeric":
|
|
54
|
+
case "bigint": {
|
|
55
|
+
const arrVal = "[]".repeat(arrayDimensions ?? 0);
|
|
56
|
+
return sql`${identifier}::text${sql.raw(arrVal).if(arrayDimensions)}`;
|
|
57
|
+
}
|
|
58
|
+
default: {
|
|
59
|
+
return identifier;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
36
63
|
mapToDriverValue(value) {
|
|
37
64
|
return typeof this.mapTo === "function" ? this.mapTo(value) : value;
|
|
38
65
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/pg-core/columns/custom.ts"],"sourcesContent":["import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts';\nimport type { ColumnBaseConfig } from '~/column.ts';\nimport { entityKind } from '~/entity.ts';\nimport type { AnyPgTable } from '~/pg-core/table.ts';\nimport type { SQL } from '~/sql/sql.ts';\nimport { type Equal, getColumnNameAndConfig } from '~/utils.ts';\nimport { PgColumn, PgColumnBuilder } from './common.ts';\n\nexport type ConvertCustomConfig<TName extends string, T extends Partial<CustomTypeValues>> =\n\t& {\n\t\tname: TName;\n\t\tdataType: 'custom';\n\t\tcolumnType: 'PgCustomColumn';\n\t\tdata: T['data'];\n\t\tdriverParam: T['driverData'];\n\t\tenumValues: undefined;\n\t}\n\t& (T['notNull'] extends true ? { notNull: true } : {})\n\t& (T['default'] extends true ? { hasDefault: true } : {});\n\nexport interface PgCustomColumnInnerConfig {\n\tcustomTypeValues: CustomTypeValues;\n}\n\nexport class PgCustomColumnBuilder<T extends ColumnBuilderBaseConfig<'custom', 'PgCustomColumn'>>\n\textends PgColumnBuilder<\n\t\tT,\n\t\t{\n\t\t\tfieldConfig: CustomTypeValues['config'];\n\t\t\tcustomTypeParams: CustomTypeParams<any>;\n\t\t},\n\t\t{\n\t\t\tpgColumnBuilderBrand: 'PgCustomColumnBuilderBrand';\n\t\t}\n\t>\n{\n\tstatic override readonly [entityKind]: string = 'PgCustomColumnBuilder';\n\n\tconstructor(\n\t\tname: T['name'],\n\t\tfieldConfig: CustomTypeValues['config'],\n\t\tcustomTypeParams: CustomTypeParams<any>,\n\t) {\n\t\tsuper(name, 'custom', 'PgCustomColumn');\n\t\tthis.config.fieldConfig = fieldConfig;\n\t\tthis.config.customTypeParams = customTypeParams;\n\t}\n\n\t/** @internal */\n\tbuild<TTableName extends string>(\n\t\ttable: AnyPgTable<{ name: TTableName }>,\n\t): PgCustomColumn<MakeColumnConfig<T, TTableName>> {\n\t\treturn new PgCustomColumn<MakeColumnConfig<T, TTableName>>(\n\t\t\ttable,\n\t\t\tthis.config as ColumnBuilderRuntimeConfig<any, any>,\n\t\t);\n\t}\n}\n\nexport class PgCustomColumn<T extends ColumnBaseConfig<'custom', 'PgCustomColumn'>> extends PgColumn<T> {\n\tstatic override readonly [entityKind]: string = 'PgCustomColumn';\n\n\tprivate sqlName: string;\n\tprivate mapTo?: (value: T['data']) => T['driverParam'];\n\tprivate mapFrom?: (value: T['driverParam']) => T['data'];\n\n\tconstructor(\n\t\ttable: AnyPgTable<{ name: T['tableName'] }>,\n\t\tconfig: PgCustomColumnBuilder<T>['config'],\n\t) {\n\t\tsuper(table, config);\n\t\tthis.sqlName = config.customTypeParams.dataType(config.fieldConfig);\n\t\tthis.mapTo = config.customTypeParams.toDriver;\n\t\tthis.mapFrom = config.customTypeParams.fromDriver;\n\t}\n\n\tgetSQLType(): string {\n\t\treturn this.sqlName;\n\t}\n\n\toverride mapFromDriverValue(value: T['driverParam']): T['data'] {\n\t\treturn typeof this.mapFrom === 'function' ? this.mapFrom(value) : value as T['data'];\n\t}\n\n\toverride mapToDriverValue(value: T['data']): T['driverParam'] {\n\t\treturn typeof this.mapTo === 'function' ? this.mapTo(value) : value as T['data'];\n\t}\n}\n\nexport type CustomTypeValues = {\n\t/**\n\t * Required type for custom column, that will infer proper type model\n\t *\n\t * Examples:\n\t *\n\t * If you want your column to be `string` type after selecting/or on inserting - use `data: string`. Like `text`, `varchar`\n\t *\n\t * If you want your column to be `number` type after selecting/or on inserting - use `data: number`. Like `integer`\n\t */\n\tdata: unknown;\n\n\t/**\n\t * Type helper, that represents what type database driver is accepting for specific database data type\n\t */\n\tdriverData?: unknown;\n\n\t/**\n\t * What config type should be used for {@link CustomTypeParams} `dataType` generation\n\t */\n\tconfig?: Record<string, any>;\n\n\t/**\n\t * Whether the config argument should be required or not\n\t * @default false\n\t */\n\tconfigRequired?: boolean;\n\n\t/**\n\t * If your custom data type should be notNull by default you can use `notNull: true`\n\t *\n\t * @example\n\t * const customSerial = customType<{ data: number, notNull: true, default: true }>({\n\t * \t dataType() {\n\t * \t return 'serial';\n\t * },\n\t * });\n\t */\n\tnotNull?: boolean;\n\n\t/**\n\t * If your custom data type has default you can use `default: true`\n\t *\n\t * @example\n\t * const customSerial = customType<{ data: number, notNull: true, default: true }>({\n\t * \t dataType() {\n\t * \t return 'serial';\n\t * },\n\t * });\n\t */\n\tdefault?: boolean;\n};\n\nexport interface CustomTypeParams<T extends CustomTypeValues> {\n\t/**\n\t * Database data type string representation, that is used for migrations\n\t * @example\n\t * ```\n\t * `jsonb`, `text`\n\t * ```\n\t *\n\t * If database data type needs additional params you can use them from `config` param\n\t * @example\n\t * ```\n\t * `varchar(256)`, `numeric(2,3)`\n\t * ```\n\t *\n\t * To make `config` be of specific type please use config generic in {@link CustomTypeValues}\n\t *\n\t * @example\n\t * Usage example\n\t * ```\n\t * dataType() {\n\t * return 'boolean';\n\t * },\n\t * ```\n\t * Or\n\t * ```\n\t * dataType(config) {\n\t * \t return typeof config.length !== 'undefined' ? `varchar(${config.length})` : `varchar`;\n\t * \t }\n\t * ```\n\t */\n\tdataType: (config: T['config'] | (Equal<T['configRequired'], true> extends true ? never : undefined)) => string;\n\n\t/**\n\t * Optional mapping function, between user input and driver\n\t * @example\n\t * For example, when using jsonb we need to map JS/TS object to string before writing to database\n\t * ```\n\t * toDriver(value: TData): string {\n\t * \t return JSON.stringify(value);\n\t * }\n\t * ```\n\t */\n\ttoDriver?: (value: T['data']) => T['driverData'] | SQL;\n\n\t/**\n\t * Optional mapping function, that is responsible for data mapping from database to JS/TS code\n\t * @example\n\t * For example, when using timestamp we need to map string Date representation to JS Date\n\t * ```\n\t * fromDriver(value: string): Date {\n\t * \treturn new Date(value);\n\t * },\n\t * ```\n\t */\n\tfromDriver?: (value: T['driverData']) => T['data'];\n}\n\n/**\n * Custom pg database data type generator\n */\nexport function customType<T extends CustomTypeValues = CustomTypeValues>(\n\tcustomTypeParams: CustomTypeParams<T>,\n): Equal<T['configRequired'], true> extends true ? {\n\t\t<TConfig extends Record<string, any> & T['config']>(\n\t\t\tfieldConfig: TConfig,\n\t\t): PgCustomColumnBuilder<ConvertCustomConfig<'', T>>;\n\t\t<TName extends string>(\n\t\t\tdbName: TName,\n\t\t\tfieldConfig: T['config'],\n\t\t): PgCustomColumnBuilder<ConvertCustomConfig<TName, T>>;\n\t}\n\t: {\n\t\t(): PgCustomColumnBuilder<ConvertCustomConfig<'', T>>;\n\t\t<TConfig extends Record<string, any> & T['config']>(\n\t\t\tfieldConfig?: TConfig,\n\t\t): PgCustomColumnBuilder<ConvertCustomConfig<'', T>>;\n\t\t<TName extends string>(\n\t\t\tdbName: TName,\n\t\t\tfieldConfig?: T['config'],\n\t\t): PgCustomColumnBuilder<ConvertCustomConfig<TName, T>>;\n\t}\n{\n\treturn <TName extends string>(\n\t\ta?: TName | T['config'],\n\t\tb?: T['config'],\n\t): PgCustomColumnBuilder<ConvertCustomConfig<TName, T>> => {\n\t\tconst { name, config } = getColumnNameAndConfig<T['config']>(a, b);\n\t\treturn new PgCustomColumnBuilder(name as ConvertCustomConfig<TName, T>['name'], config, customTypeParams);\n\t};\n}\n"],"mappings":"AAEA,SAAS,kBAAkB;AAG3B,SAAqB,8BAA8B;AACnD,SAAS,UAAU,uBAAuB;AAkBnC,MAAM,8BACJ,gBAUT;AAAA,EACC,QAA0B,UAAU,IAAY;AAAA,EAEhD,YACC,MACA,aACA,kBACC;AACD,UAAM,MAAM,UAAU,gBAAgB;AACtC,SAAK,OAAO,cAAc;AAC1B,SAAK,OAAO,mBAAmB;AAAA,EAChC;AAAA;AAAA,EAGA,MACC,OACkD;AAClD,WAAO,IAAI;AAAA,MACV;AAAA,MACA,KAAK;AAAA,IACN;AAAA,EACD;AACD;AAEO,MAAM,uBAA+E,SAAY;AAAA,EACvG,QAA0B,UAAU,IAAY;AAAA,EAExC;AAAA,EACA;AAAA,EACA;AAAA,EAER,YACC,OACA,QACC;AACD,UAAM,OAAO,MAAM;AACnB,SAAK,UAAU,OAAO,iBAAiB,SAAS,OAAO,WAAW;AAClE,SAAK,QAAQ,OAAO,iBAAiB;AACrC,SAAK,UAAU,OAAO,iBAAiB;AAAA,EACxC;AAAA,EAEA,aAAqB;AACpB,WAAO,KAAK;AAAA,EACb;AAAA,EAES,mBAAmB,OAAoC;AAC/D,WAAO,OAAO,KAAK,YAAY,aAAa,KAAK,QAAQ,KAAK,IAAI;AAAA,EACnE;AAAA,EAES,iBAAiB,OAAoC;AAC7D,WAAO,OAAO,KAAK,UAAU,aAAa,KAAK,MAAM,KAAK,IAAI;AAAA,EAC/D;AACD;AAmHO,SAAS,WACf,kBAoBD;AACC,SAAO,CACN,GACA,MAC0D;AAC1D,UAAM,EAAE,MAAM,OAAO,IAAI,uBAAoC,GAAG,CAAC;AACjE,WAAO,IAAI,sBAAsB,MAA+C,QAAQ,gBAAgB;AAAA,EACzG;AACD;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/pg-core/columns/custom.ts"],"sourcesContent":["import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts';\nimport type { ColumnBaseConfig } from '~/column.ts';\nimport { entityKind } from '~/entity.ts';\nimport type { AnyPgTable } from '~/pg-core/table.ts';\nimport type { SQL, SQLGenerator } from '~/sql/sql.ts';\nimport { type Equal, getColumnNameAndConfig } from '~/utils.ts';\nimport { PgColumn, PgColumnBuilder } from './common.ts';\n\nexport type ConvertCustomConfig<TName extends string, T extends Partial<CustomTypeValues>> =\n\t& {\n\t\tname: TName;\n\t\tdataType: 'custom';\n\t\tcolumnType: 'PgCustomColumn';\n\t\tdata: T['data'];\n\t\tdriverParam: T['driverData'];\n\t\tenumValues: undefined;\n\t}\n\t& (T['notNull'] extends true ? { notNull: true } : {})\n\t& (T['default'] extends true ? { hasDefault: true } : {});\n\nexport interface PgCustomColumnInnerConfig {\n\tcustomTypeValues: CustomTypeValues;\n}\n\nexport class PgCustomColumnBuilder<T extends ColumnBuilderBaseConfig<'custom', 'PgCustomColumn'>>\n\textends PgColumnBuilder<\n\t\tT,\n\t\t{\n\t\t\tfieldConfig: CustomTypeValues['config'];\n\t\t\tcustomTypeParams: CustomTypeParams<any>;\n\t\t},\n\t\t{\n\t\t\tpgColumnBuilderBrand: 'PgCustomColumnBuilderBrand';\n\t\t}\n\t>\n{\n\tstatic override readonly [entityKind]: string = 'PgCustomColumnBuilder';\n\n\tconstructor(\n\t\tname: T['name'],\n\t\tfieldConfig: CustomTypeValues['config'],\n\t\tcustomTypeParams: CustomTypeParams<any>,\n\t) {\n\t\tsuper(name, 'custom', 'PgCustomColumn');\n\t\tthis.config.fieldConfig = fieldConfig;\n\t\tthis.config.customTypeParams = customTypeParams;\n\t}\n\n\t/** @internal */\n\tbuild<TTableName extends string>(\n\t\ttable: AnyPgTable<{ name: TTableName }>,\n\t): PgCustomColumn<MakeColumnConfig<T, TTableName>> {\n\t\treturn new PgCustomColumn<MakeColumnConfig<T, TTableName>>(\n\t\t\ttable,\n\t\t\tthis.config as ColumnBuilderRuntimeConfig<any, any>,\n\t\t);\n\t}\n}\n\nexport class PgCustomColumn<T extends ColumnBaseConfig<'custom', 'PgCustomColumn'>> extends PgColumn<T> {\n\tstatic override readonly [entityKind]: string = 'PgCustomColumn';\n\n\tprivate sqlName: string;\n\tprivate mapTo?: (value: T['data']) => T['driverParam'];\n\tprivate mapFrom?: (value: T['driverParam']) => T['data'];\n\tprivate mapJson?: (value: unknown) => T['data'];\n\tprivate forJsonSelect?: (identifier: SQL, sql: SQLGenerator, arrayDimensions?: number) => SQL;\n\n\tconstructor(\n\t\ttable: AnyPgTable<{ name: T['tableName'] }>,\n\t\tconfig: PgCustomColumnBuilder<T>['config'],\n\t) {\n\t\tsuper(table, config);\n\t\tthis.sqlName = config.customTypeParams.dataType(config.fieldConfig);\n\t\tthis.mapTo = config.customTypeParams.toDriver;\n\t\tthis.mapFrom = config.customTypeParams.fromDriver;\n\t\tthis.mapJson = config.customTypeParams.fromJson;\n\t\tthis.forJsonSelect = config.customTypeParams.forJsonSelect;\n\t}\n\n\tgetSQLType(): string {\n\t\treturn this.sqlName;\n\t}\n\n\toverride mapFromDriverValue(value: T['driverParam']): T['data'] {\n\t\treturn typeof this.mapFrom === 'function' ? this.mapFrom(value) : value as T['data'];\n\t}\n\n\tmapFromJsonValue(value: unknown): T['data'] {\n\t\treturn typeof this.mapJson === 'function' ? this.mapJson(value) : this.mapFromDriverValue(value) as T['data'];\n\t}\n\n\tjsonSelectIdentifier(identifier: SQL, sql: SQLGenerator, arrayDimensions?: number): SQL {\n\t\tif (typeof this.forJsonSelect === 'function') return this.forJsonSelect(identifier, sql, arrayDimensions);\n\n\t\tconst rawType = this.getSQLType().toLowerCase();\n\t\tconst parenPos = rawType.indexOf('(');\n\t\tconst type = (parenPos + 1) ? rawType.slice(0, parenPos) : rawType;\n\n\t\tswitch (type) {\n\t\t\tcase 'bytea':\n\t\t\tcase 'geometry':\n\t\t\tcase 'timestamp':\n\t\t\tcase 'numeric':\n\t\t\tcase 'bigint': {\n\t\t\t\tconst arrVal = '[]'.repeat(arrayDimensions ?? 0);\n\n\t\t\t\treturn sql`${identifier}::text${sql.raw(arrVal).if(arrayDimensions)}`;\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\treturn identifier;\n\t\t\t}\n\t\t}\n\t}\n\n\toverride mapToDriverValue(value: T['data']): T['driverParam'] {\n\t\treturn typeof this.mapTo === 'function' ? this.mapTo(value) : value as T['data'];\n\t}\n}\n\nexport interface CustomTypeValues {\n\t/**\n\t * Required type for custom column, that will infer proper type model\n\t *\n\t * Examples:\n\t *\n\t * If you want your column to be `string` type after selecting/or on inserting - use `data: string`. Like `text`, `varchar`\n\t *\n\t * If you want your column to be `number` type after selecting/or on inserting - use `data: number`. Like `integer`\n\t */\n\tdata: unknown;\n\n\t/**\n\t * Type helper, that represents what type database driver is accepting for specific database data type\n\t */\n\tdriverData?: unknown;\n\n\t/**\n\t * Type helper, that represents what type database driver is returning for specific database data type\n\t *\n\t * Needed only in case driver's output and input for type differ\n\t *\n\t * Defaults to {@link driverData}\n\t */\n\tdriverOutput?: unknown;\n\n\t/**\n\t * Type helper, that represents what type field returns after being aggregated to JSON\n\t */\n\tjsonData?: unknown;\n\n\t/**\n\t * What config type should be used for {@link CustomTypeParams} `dataType` generation\n\t */\n\tconfig?: Record<string, any>;\n\n\t/**\n\t * Whether the config argument should be required or not\n\t * @default false\n\t */\n\tconfigRequired?: boolean;\n\n\t/**\n\t * If your custom data type should be notNull by default you can use `notNull: true`\n\t *\n\t * @example\n\t * const customSerial = customType<{ data: number, notNull: true, default: true }>({\n\t * \t dataType() {\n\t * \t return 'serial';\n\t * },\n\t * });\n\t */\n\tnotNull?: boolean;\n\n\t/**\n\t * If your custom data type has default you can use `default: true`\n\t *\n\t * @example\n\t * const customSerial = customType<{ data: number, notNull: true, default: true }>({\n\t * \t dataType() {\n\t * \t return 'serial';\n\t * },\n\t * });\n\t */\n\tdefault?: boolean;\n}\n\nexport interface CustomTypeParams<T extends CustomTypeValues> {\n\t/**\n\t * Database data type string representation, that is used for migrations\n\t * @example\n\t * ```\n\t * `jsonb`, `text`\n\t * ```\n\t *\n\t * If database data type needs additional params you can use them from `config` param\n\t * @example\n\t * ```\n\t * `varchar(256)`, `numeric(2,3)`\n\t * ```\n\t *\n\t * To make `config` be of specific type please use config generic in {@link CustomTypeValues}\n\t *\n\t * @example\n\t * Usage example\n\t * ```\n\t * dataType() {\n\t * return 'boolean';\n\t * },\n\t * ```\n\t * Or\n\t * ```\n\t * dataType(config) {\n\t * \t return typeof config.length !== 'undefined' ? `varchar(${config.length})` : `varchar`;\n\t * \t }\n\t * ```\n\t */\n\tdataType: (config: T['config'] | (Equal<T['configRequired'], true> extends true ? never : undefined)) => string;\n\n\t/**\n\t * Optional mapping function, that is used to transform inputs from desired to be used in code format to one suitable for driver\n\t * @example\n\t * For example, when using jsonb we need to map JS/TS object to string before writing to database\n\t * ```\n\t * toDriver(value: TData): string {\n\t * \t return JSON.stringify(value);\n\t * }\n\t * ```\n\t */\n\ttoDriver?: (value: T['data']) => T['driverData'] | SQL;\n\n\t/**\n\t * Optional mapping function, that is used for transforming data returned by driver to desired column's output format\n\t * @example\n\t * For example, when using timestamp we need to map string Date representation to JS Date\n\t * ```\n\t * fromDriver(value: string): Date {\n\t * \treturn new Date(value);\n\t * }\n\t * ```\n\t *\n\t * It'll cause the returned data to change from:\n\t * ```\n\t * {\n\t * \tcustomField: \"2025-04-07T03:25:16.635Z\";\n\t * }\n\t * ```\n\t * to:\n\t * ```\n\t * {\n\t * \tcustomField: new Date(\"2025-04-07T03:25:16.635Z\");\n\t * }\n\t * ```\n\t */\n\tfromDriver?: (value: 'driverOutput' extends keyof T ? T['driverOutput'] : T['driverData']) => T['data'];\n\n\t/**\n\t * Optional mapping function, that is used for transforming data returned by transofmed to JSON in database data to desired format\n\t *\n\t * Used by [relational queries](https://orm.drizzle.team/docs/rqb-v2)\n\t *\n\t * Defaults to {@link fromDriver} function\n\t * @example\n\t * For example, when querying bigint column via [RQB](https://orm.drizzle.team/docs/rqb-v2) or [JSON functions](https://orm.drizzle.team/docs/json-functions), the result field will be returned as it's string representation, as opposed to bigint from regular query\n\t * To handle that, we need a separate function to handle such field's mapping:\n\t * ```\n\t * fromJson(value: string): bigint {\n\t * \treturn BigInt(value);\n\t * },\n\t * ```\n\t *\n\t * It'll cause the returned data to change from:\n\t * ```\n\t * {\n\t * \tcustomField: \"5044565289845416380\";\n\t * }\n\t * ```\n\t * to:\n\t * ```\n\t * {\n\t * \tcustomField: 5044565289845416380n;\n\t * }\n\t * ```\n\t */\n\tfromJson?: (value: T['jsonData']) => T['data'];\n\n\t/**\n\t * Optional selection modifier function, that is used for modifying selection of column inside [JSON functions](https://orm.drizzle.team/docs/json-functions)\n\t *\n\t * Additional mapping that could be required for such scenarios can be handled using {@link fromJson} function\n\t *\n\t * Used by [relational queries](https://orm.drizzle.team/docs/rqb-v2)\n\t *\n\t * Following types are being casted to text by default: `bytea`, `geometry`, `timestamp`, `numeric`, `bigint`\n\t * @example\n\t * For example, when using bigint we need to cast field to text to preserve data integrity\n\t * ```\n\t * forJsonSelect(identifier: SQL, sql: SQLGenerator, arrayDimensions?: number): SQL {\n\t * \treturn sql`${identifier}::text`\n\t * },\n\t * ```\n\t *\n\t * This will change query from:\n\t * ```\n\t * SELECT\n\t * \trow_to_json(\"t\".*)\n\t * \tFROM\n\t * \t(\n\t * \t\tSELECT\n\t * \t\t\"table\".\"custom_bigint\" AS \"bigint\"\n\t * \t\tFROM\n\t * \t\t\"table\"\n\t * \t) AS \"t\"\n\t * ```\n\t * to:\n\t * ```\n\t * SELECT\n\t * \trow_to_json(\"t\".*)\n\t * \tFROM\n\t * \t(\n\t * \t\tSELECT\n\t * \t\t\"table\".\"custom_bigint\"::text AS \"bigint\"\n\t * \t\tFROM\n\t * \t\t\"table\"\n\t * \t) AS \"t\"\n\t * ```\n\t *\n\t * Returned by query object will change from:\n\t * ```\n\t * {\n\t * \tbigint: 5044565289845416000; // Partial data loss due to direct conversion to JSON format\n\t * }\n\t * ```\n\t * to:\n\t * ```\n\t * {\n\t * \tbigint: \"5044565289845416380\"; // Data is preserved due to conversion of field to text before JSON-ification\n\t * }\n\t * ```\n\t */\n\tforJsonSelect?: (identifier: SQL, sql: SQLGenerator, arrayDimensions?: number) => SQL;\n}\n\n/**\n * Custom pg database data type generator\n */\nexport function customType<T extends CustomTypeValues = CustomTypeValues>(\n\tcustomTypeParams: CustomTypeParams<T>,\n): Equal<T['configRequired'], true> extends true ? {\n\t\t<TConfig extends Record<string, any> & T['config']>(\n\t\t\tfieldConfig: TConfig,\n\t\t): PgCustomColumnBuilder<ConvertCustomConfig<'', T>>;\n\t\t<TName extends string>(\n\t\t\tdbName: TName,\n\t\t\tfieldConfig: T['config'],\n\t\t): PgCustomColumnBuilder<ConvertCustomConfig<TName, T>>;\n\t}\n\t: {\n\t\t(): PgCustomColumnBuilder<ConvertCustomConfig<'', T>>;\n\t\t<TConfig extends Record<string, any> & T['config']>(\n\t\t\tfieldConfig?: TConfig,\n\t\t): PgCustomColumnBuilder<ConvertCustomConfig<'', T>>;\n\t\t<TName extends string>(\n\t\t\tdbName: TName,\n\t\t\tfieldConfig?: T['config'],\n\t\t): PgCustomColumnBuilder<ConvertCustomConfig<TName, T>>;\n\t}\n{\n\treturn <TName extends string>(\n\t\ta?: TName | T['config'],\n\t\tb?: T['config'],\n\t): PgCustomColumnBuilder<ConvertCustomConfig<TName, T>> => {\n\t\tconst { name, config } = getColumnNameAndConfig<T['config']>(a, b);\n\t\treturn new PgCustomColumnBuilder(name as ConvertCustomConfig<TName, T>['name'], config, customTypeParams);\n\t};\n}\n"],"mappings":"AAEA,SAAS,kBAAkB;AAG3B,SAAqB,8BAA8B;AACnD,SAAS,UAAU,uBAAuB;AAkBnC,MAAM,8BACJ,gBAUT;AAAA,EACC,QAA0B,UAAU,IAAY;AAAA,EAEhD,YACC,MACA,aACA,kBACC;AACD,UAAM,MAAM,UAAU,gBAAgB;AACtC,SAAK,OAAO,cAAc;AAC1B,SAAK,OAAO,mBAAmB;AAAA,EAChC;AAAA;AAAA,EAGA,MACC,OACkD;AAClD,WAAO,IAAI;AAAA,MACV;AAAA,MACA,KAAK;AAAA,IACN;AAAA,EACD;AACD;AAEO,MAAM,uBAA+E,SAAY;AAAA,EACvG,QAA0B,UAAU,IAAY;AAAA,EAExC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,YACC,OACA,QACC;AACD,UAAM,OAAO,MAAM;AACnB,SAAK,UAAU,OAAO,iBAAiB,SAAS,OAAO,WAAW;AAClE,SAAK,QAAQ,OAAO,iBAAiB;AACrC,SAAK,UAAU,OAAO,iBAAiB;AACvC,SAAK,UAAU,OAAO,iBAAiB;AACvC,SAAK,gBAAgB,OAAO,iBAAiB;AAAA,EAC9C;AAAA,EAEA,aAAqB;AACpB,WAAO,KAAK;AAAA,EACb;AAAA,EAES,mBAAmB,OAAoC;AAC/D,WAAO,OAAO,KAAK,YAAY,aAAa,KAAK,QAAQ,KAAK,IAAI;AAAA,EACnE;AAAA,EAEA,iBAAiB,OAA2B;AAC3C,WAAO,OAAO,KAAK,YAAY,aAAa,KAAK,QAAQ,KAAK,IAAI,KAAK,mBAAmB,KAAK;AAAA,EAChG;AAAA,EAEA,qBAAqB,YAAiB,KAAmB,iBAA+B;AACvF,QAAI,OAAO,KAAK,kBAAkB;AAAY,aAAO,KAAK,cAAc,YAAY,KAAK,eAAe;AAExG,UAAM,UAAU,KAAK,WAAW,EAAE,YAAY;AAC9C,UAAM,WAAW,QAAQ,QAAQ,GAAG;AACpC,UAAM,OAAQ,WAAW,IAAK,QAAQ,MAAM,GAAG,QAAQ,IAAI;AAE3D,YAAQ,MAAM;AAAA,MACb,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK,UAAU;AACd,cAAM,SAAS,KAAK,OAAO,mBAAmB,CAAC;AAE/C,eAAO,MAAM,UAAU,SAAS,IAAI,IAAI,MAAM,EAAE,GAAG,eAAe,CAAC;AAAA,MACpE;AAAA,MACA,SAAS;AACR,eAAO;AAAA,MACR;AAAA,IACD;AAAA,EACD;AAAA,EAES,iBAAiB,OAAoC;AAC7D,WAAO,OAAO,KAAK,UAAU,aAAa,KAAK,MAAM,KAAK,IAAI;AAAA,EAC/D;AACD;AAoOO,SAAS,WACf,kBAoBD;AACC,SAAO,CACN,GACA,MAC0D;AAC1D,UAAM,EAAE,MAAM,OAAO,IAAI,uBAAoC,GAAG,CAAC;AACjE,WAAO,IAAI,sBAAsB,MAA+C,QAAQ,gBAAgB;AAAA,EACzG;AACD;","names":[]}
|
package/pg-core/dialect.cjs
CHANGED
|
@@ -668,11 +668,11 @@ class PgDialect {
|
|
|
668
668
|
const name = import_sql2.sql`${table}.${import_sql2.sql.identifier(this.casing.getColumnCasing(column))}`;
|
|
669
669
|
let targetType = column.columnType;
|
|
670
670
|
let col = column;
|
|
671
|
-
let
|
|
671
|
+
let dimensionCnt = 0;
|
|
672
672
|
while ((0, import_entity.is)(col, import_columns.PgArray)) {
|
|
673
|
-
col =
|
|
673
|
+
col = col.baseColumn;
|
|
674
674
|
targetType = col.columnType;
|
|
675
|
-
|
|
675
|
+
++dimensionCnt;
|
|
676
676
|
}
|
|
677
677
|
switch (targetType) {
|
|
678
678
|
case "PgNumeric":
|
|
@@ -684,8 +684,12 @@ class PgDialect {
|
|
|
684
684
|
case "PgGeometry":
|
|
685
685
|
case "PgGeometryObject":
|
|
686
686
|
case "PgBytea": {
|
|
687
|
+
const arrVal = "[]".repeat(dimensionCnt);
|
|
687
688
|
return import_sql2.sql`${name}::text${import_sql2.sql.raw(arrVal).if(arrVal)} as ${import_sql2.sql.identifier(key)}`;
|
|
688
689
|
}
|
|
690
|
+
case "PgCustomColumn": {
|
|
691
|
+
return import_sql2.sql`${col.jsonSelectIdentifier(name, import_sql2.sql, dimensionCnt > 0 ? dimensionCnt : void 0)} as ${import_sql2.sql.identifier(key)}`;
|
|
692
|
+
}
|
|
689
693
|
default: {
|
|
690
694
|
return import_sql2.sql`${name} as ${import_sql2.sql.identifier(key)}`;
|
|
691
695
|
}
|