Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

How to show the SQL which lead to a syntax error #470

Unanswered
convers39 asked this question in Q&A
Discussion options

I have some problems when trying to debug a syntax error. Since there are several nested queries, I could not see the final SQL or the arguments.

 const result = await sql`
 WITH q AS (${sql`
 SELECT *,
 ${sql(column)} col_value,
 ST_AsMVTGeom(
 ${sql(shapeColumn)},
 ${stTransform},
 4096,
 256,
 true) geom
 FROM ${sql(roadTableName)}
 WHERE ST_Intersects(shape, ${stTransform})
 ${sql`AND ${condColumn} ${inequalitySign} ${condValue}`}
 `})
 SELECT ST_AsMVT(q, 'layer', 4096, 'geom') layer
 FROM q;
 `;

If I remove the await and try to describe the query, the args just show a pending promise, and the strings are broken.

image

If I add the await it just crashed and cannot see any helpful debug info about the SQL query itself.

image

How can I debug this?

You must be logged in to vote

Replies: 1 comment 5 replies

Comment options

I have the same problem. The documentation suggests that describe does not submit the generated query to PostgreSQL, but it does.
So, how can one see what is generated as query before it is executed?

You must be logged in to vote
5 replies
Comment options

Is this still a problem with v3.3.1 ?

Comment options

Yes, I'm using the latest version, 3.3.1. Apparently, if the debug option is specified for the DB connections, the thrown exception contains the details about the query, its parameters and what not.
Sorry to hijack this, but why object and number parameters are sent as strings to the database after using their toString()? 😲

Comment options

Ah, sorry I misinterpreted your question. .describe() will send your query to the db to have it described, but it won't execute it.

The PostgreSQL over the wire protocol is either text or binary, and Postgres.js uses the text version, so that's why it's sent as strings. Using binary is only beneficial in a few corner cases, and might be implemented in the future for those cases, but it's not really a big benefit generally, which is why it's not on the roadmap currently.

If you're talking about actual types value when they reach your db and are inserted, then it's a different matter. There types are decided by PostgreSQL

For instance

sql`select ${ 1 } as x` // returns [{ x: '1' }]

But

sql`select ${ 1 }::int as x` // returns [{ x: 1 }]
Comment options

Thank you for promptness and for the answer related to describe().

I'll rephrase the other question. How can I control the type of parameters that are sent to the database along with a query like update ... from (values (1,ドル 2ドル), (3,ドル 4ドル) ...) as x(a, b) where ...
I'm using exactly what is recommended in this section and all parameters are dispatched as strings (type 25) to the PostgreSQL server, ignoring the fact that I use
${sql([ [1, {...}], [2, {...}, ...])}, namely JS numbers (type 0) and objects (type 114).

I do not have a problem with your sending values as (text) literals instead of some binary representations; I don;t get why these literals do not correspond to numbers, json or whatever else I'm giving as parameter values.

Comment options

Ah, that's because PostgreSQL can't infer the types in the query through values (...), (...). And then you get an error like operator does not : integer = text ?

If you add explicit casts, then everything works well - like this if we fix the docs sample (notice ::int):

update users set name = x.name::text, age = x.age::int
from (values ${sql(users) }) as x (id, name, age)
where users.id = x.id::int
returning *

You can also force a type from the client by doing eg: sql`select ${ sql.typed(1234, 23) }`. But that will require wrapping your values like that, or at least the first row.

You can also do it with a cte if you think it's clearer.

with xs as (
 select id::int, name::text, age::int from (values ${ sql(users) }) as x (id, name, age)
)
update users set
 name = xs.name,
 age = xs.age
from xs
where users.id = xs.id
returning *
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
None yet

AltStyle によって変換されたページ (->オリジナル) /