postgres icon indicating copy to clipboard operation
postgres copied to clipboard

JSONB field name incorrectly handled by `sql()`

Open JakobJingleheimer opened this issue 3 months ago • 2 comments

Take a simple query like

sql`
SELECT * FROM "Example"
  WHERE
    somejsonb->>'someField' = foo;
`

When built dynamically:

// fieldName → somejsonb->>'someField'
// val → 'foo'

sql`
SELECT * FROM "Example"
  WHERE
    ${sql(fieldName)} = ${val};
`

fieldName is incorrectly quoted as "somejsonb->>'someField'" (it should be "somejsonb"->>'someField')

Manually wrapping somejsonb in double-quotes results in an extra set of quotes: ""somejsonb"->>'someField'"

JakobJingleheimer avatar Oct 10 '25 10:10 JakobJingleheimer

I think sql(fieldName) should be recognized as 'column name', so ${sql(fieldName)} will outputed as "fieldName", wrapped using double quotes I think there are two solutions: 1: somejsonb->>${'someField'} = ${val} 2: just using unsafe but you should care about sql injection: ${sql.unsafe(fieldName)} = ${val}

emogua avatar Oct 13 '25 09:10 emogua

I think sql() should handle this (otherwise it's quite a foot-gun IMO), but there is a workaround.

There was a bigger foot-gun lurking though: the lack of join (https://github.com/porsager/postgres/pull/905).

I've sent an update to the README with these caveats and workarounds.

JakobJingleheimer avatar Oct 13 '25 21:10 JakobJingleheimer