drizzle-team / drizzle-team/drizzle-orm

[FEATURE]: Default select for custom types

Open
#1,083 18 comments 20 reactions 0 assignees View on GitHub
enhancement qb/crud
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.