[FEATURE]: Default select for custom types
Author: drepkovskyCreated Aug 21, 2023Updated Sep 15, 2026
Labelsenhancementqb/crud
Describe what you want
When creating a custom type that doesn't have a straightforward select like a postgis geometry, for example.
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\((?<lng>[\d.-]+) (?<lat>[\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.
export const selectPoint = (column: string, decoder: DriverValueMapper<any, any>) => {
return sql<Point>`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:
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\((?<lng>[\d.-]+) (?<lat>[\d.-]+)\)/);
const { lat, lng } = matches?.groups ?? {};
return { lat: parseFloat(String(lat)), lng: parseFloat(String(lng)) };
},
/** this is new */
selectFromDb(column, decoder) {
return sql<Point>`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.
Source: drizzle-team/drizzle-orm