Custom Type interpreted as String
Hello everyone, I am having some issues with getting Drizzle to work with PostGIS, I am trying to have support for PostGIS's Point geometry. This is what I have setup
But the data returned stays a string
This is my query
This is happening across packages in monorepo, not sure if that could cause the type inference to fail
46 Replies
at first sight you did everything right
also you should install only 1 drizzle-orm instance instead of multiple
to make it works properly
we have GH issue to handle multiple drizzle-orm instances as one in monorepo
but it's still in backlog
can you try it on empty project with single drizzle-orm instance, just to check if the reason with multiple instances
Will try it out now
Lucky to have found this thread! I tried to build a point type as well to support inserts - haven't tried yours out yet, but I wonder if this set up would support inserts as well.
I know realize I posted my thrad in the wrong channel, but there's a bit more context here: https://discord.com/channels/1043890932593987624/1056966312997429278/1104042792918990928
it should work for inserts and long as @Volks specified
toDriver
function implementation that is responsible for insert mappings
fromDriver
responsible for select mappingsOh yes, it does!
@Vicente It works for you?
Do you have a monorepo?
Do you mean whether my project uses a tool like lerna to manage a monorepo? If that is case, it doesn't.
so changing my
toDriver
to the one you showed us above, makes my insert successful. However, I'm working now on the returning()
and select()
scenarios - I'd like to parse the geometry to text at the type level instead of in my queries.
I'm still getting acquainted with the drizzle internals. For the returning()
scenario, I still don't know where to go to intercept the query builder. I'd like to add that st_astext
so the newly created records contain the parsed location instead of the binary piece representing the point. Not sure whether the current custom types API supports that either.@Andrew Sherman Can you elaborate on the 1 drizzle-orm instance? I export the drizzle instance and all of the drizzle types/ functions from my
@company/db
package and use that. Is that also not possible?Maybe it won't work for returning. I guess I'll need @Dan Kochetov for this case
it should
let me double check
oh woah, that was quick. Ty guys for chiming in. I'm struggling to see where to go. No rush, I'm still debugging/tracing things to understand how everything works first.
You just need to be sure that drizzle-orm is installed once and reused in other packages
so could you explain what your current issue is?
is the
fromDriver
function not working for your custom type?Exactly. In this case:
value
is an actual binary blob representing the geometry - it is missing the set_astext(location)
to convert it to the text representation
From my test script when outputting to stdout the contents of value.what is that second value that you are logging?
Oh, yes - so that output happens when returning from an insert like the one below. I'm outputting the value of
lonlat
as it comes from pg:
I think I know what the problem is
If this is the code you are running:
Then the
location
field won't be mapped according to your custom type logic, because Drizzle doesn't know that it's related to your custom type. To run the mapping, add the .mapWith(<column>)
to the column.
so it'll look like this
where table.column
is your custom type columnDoes the sql<Type> not tell it what to map with?
this is the expected type
types have no effect in runtime
Yeah makes sense, will try it out a bit later and report back
same thing for
returning
Thanks everyone
@Vicente I guess your problem is different though?
I think so. If I understand where to use the
sql<Point>
....mapWith(table.column)
I'm not sure how that gets picked up by the returning()
This is only for cases when you're selecting custom SQL instead of just a column
Ideally I wouldn't want to perform the
st_text
parsing when querying things - I'd like that to happen transparently for these typesCan you do the sql trick in returning as well?
location: sql<Point>
```
st_astext(active_carriers.location) as location
,
```
I can try that out yes
Yes, it might work like this, but then you'll have to specify the expected type manually every time, which is a lot of boilerplate IMO
And it won't work as nice with joins, where the columns might become nullable automatically if they are joined
Can we create an issue to track this? Might be useful?
I think adding SQL wrapping for custom types might be a good idea
Yes, I'll create an issue
That's great news! It may be a too big for a first issue, but it'd be happy to work on it with some guidance.
GitHub
Allow wrapping the column in custom SQL for custom types · Issue #5...
For example, to always select fn(column) instead of column
mapWith
works for me as well! Thanks, it's just a bit verbose. I would like to write a helper for this but I am unable to work with the string templating , as when I try to template with ${}
it is translated as $1
and the placeholder $
arguments are not allowed in selects
backend-1 | [18:26:33 UTC] INFO: Query: select "employee_id", st_astext($1) as $2 from "active_carriers" -- params: ["location", "location"]
Any ideas?wrap it in
sql.raw()
the part that you don't need escaped as a param@Dan Kochetov How can I type the
sql.raw
to properly be a number and not SQL<Unknown>
?
I guess something like this
just choose a variable you don't want to translate to $1
Won't the
sql
make the insides of the ${} parametized? Eg it will translate to something like st_astext($1) as $2
?If you use .raw it won’t
raw is for the cases you won’t translate specific value to parametrized
I now understand the usage of raw... I was misusing it, thanks for the info
Any way to get fully qualified names to use with
.raw
eg
console.log(driverShifts.id._.tableName + " " + driverShifts.id._.name)
<- something like this, so I don't have to hardcode the string table_name.column_name
The above example gives me error that I am accessing undefined field name
TypeError: Cannot read properties of undefined (reading 'tableName')
I am looking into writing utility function for this but this might be a common thing that I am missinggetTableConfig(driverShifts.id.table).name
using
._.tableName
is way better though
I think I'll make it work in the futureIt would be a great DX to be able to quickly get the fully qualified selector without having to hardcode it and lose on renames and other features
Hi folks, the above info was really useful, though it was quite difficult for me to navigate. Heres a complete example in case someone else will find it useful.
I added
SQL<Point>
as the selectPoint
return type, else selectedPlace
would not be typed correctly.
I hope this looks good, please let me know if I missed something.Since this thread helped me, I might as well share another version for anyone else taking a hit at this. Here's how I'm trying to work it out:
Where:
https://discord.com/channels/1043890932593987624/1074717449997537420/1165366348759715961
I've implemeted two custom similar, experimental (but working)
geometry
columns that support GeoJSON + PostGIS (read only for now), and which has an option to select which type you want.
1. Manually parse PostGIS hex / wkx coming from / to the database driver
- Experimental gist: https://gist.github.com/ItsWendell/38ebe96b34d00d9138ce23cc363d7009
2. Wrap the customType and SQL inject the public".ST_AsGeoJSON("${dbName}") as "${dbName} as a columnName. (This hardcodes the public schema in here though so this wouldn't work if you need this work on any other schemas too, but could be an config option in the column)
- Experimental gist: https://gist.github.com/ItsWendell/65a107c0f8de00fdd6e4f3935789ce5a
@iolyd I don't undestand how you expect the driver return text, since the default that it returns is hex, right?Please help! This is such a pain in the ass and I need to launch!
coordinateType.ts
then I use this in my schema.ts
as follows:
and trying to make a simple request in my node application:
What am I missing here? I keep getting the error:
PostgresError: could not determine data type of parameter $6\
(parameter 6 is the coordinates in my schema, but I have redacted my other columns to keep my example simple above)
I am using PostGIS on a PostgreSQL engine Aurora db. I simply ran the following command to support this newly needed column:
any ideas on this? @Dan Kochetov ?
For future readers. I solved by using sql.raw()
as I think the regular sql
template was causing trouble with how it passes values around (as part of injection protection).
I am safe architecturally. Here is the final change I made to my toDriver
definition if you need it. Above code stayed the same.