drizzle-team / drizzle-team/drizzle-orm
[FEATURE]: Default select for custom types
- Dominant language
- TypeScript
- Stars
- 35.8k
- Forks
- 1.6k
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 4
Description
### Describe what you want
When creating a custom type that doesn't have a straightforward select like a postgis geometry, for example.
```ts
export type Point = {
lat: number;
lng: number;
};
export const pointType = customType<{ data: Point; driverData: string }>({
dataType() {
return 'geometry(Point,4326)';
},
toDriver(value: Point): string {
return `SRID=4326;POINT(${value.lng} ${value.lat})`;
},
fromDriver(value: string) {
const matches = value.match(/POINT\((?[\d.-]+) (?[\d.-]+)\)/);
const { lat, lng } = matches?.groups ?? {};
return { lat: parseFloat(String(lat)), lng: parseFloat(String(lng)) };
},
});
```
We need to create a select function wrapper to properly select the field with this custom type.
```ts
export const selectPoint = (column: string, decoder: DriverValueMapper) => {
return sql`st_astext(${sql.identifier(column)})`.mapWith(decoder).as(column);
};
// then select it like this:
db.select({
...allOtherFields
coords: selectPoint('coords', location.coords),
}).from(location);
```
That means we always need to specify this custom select when working with this table, also we are not able to use the relational query syntax because the there is no way to provide a custom sql fragment in the columns object (only true/false boolean specifying the field inclusion)
**Proposal**:
Add a selectFromDb option to customType factory function like so:
```ts
export const pointType = customType<{ data: Point; driverData: string }>({
dataType() {
return 'geometry(Point,4326)';
},
toDriver(value: Point): string {
return `SRID=4326;POINT(${value.lng} ${value.lat})`;
},
fromDriver(value: string) {
const matches = value.match(/POINT\((?[\d.-]+) (?[\d.-]+)\)/);
const { lat, lng } = matches?.groups ?? {};
return { lat: parseFloat(String(lat)), lng: parseFloat(String(lng)) };
},
/** this is new */
selectFromDb(column, decoder) {
return sql`st_astext(${sql.identifier(column)})`.mapWith(decoder).as(column);
},
});
```
Now we when the field is being selected from db the `selectFromDb` function will be automatically called if specified for given field.
Contributor guide
Assessment
This issue has not been assessed yet.