postgres icon indicating copy to clipboard operation
postgres copied to clipboard

Inline parameters values into query SQL string

Open uasan opened this issue 3 years ago • 5 comments

Hello.

Many SQL commands do not support parameters in queries, for example:

COPY (SELECT * FROM t WHERE id = $1 ) TO STDOUT;
CREATE VIEW AS SELECT * FROM t WHERE id = $1;

I plan to implement my own function, serialize the values by described SQL string, and substitute them into the SQL string.

Maybe there is a better solution? Thanks.

uasan avatar Aug 03 '22 10:08 uasan

Yeah, I've been having the same issue with DO statements where the protocol parameters doesn't work because they collide with the internal parameters. Perhaps the solution should be to allow nesting sql.unsafe too, so that it'd look like this?

const safeValue = '9f7a8c42-0382-4eb9-85a7-23e88ef77bd3'
sql`COPY (SELECT * FROM t WHERE id = ${ sql.unsafe(safeValue) } ) TO STDOUT;`

porsager avatar Aug 09 '22 06:08 porsager

I also did this, but there were SQL requests that must be given to JSON in one case and to COPY to csv in another, I made such a decision:

const { types } = await sql.unsafe(queryString, values).describe();

for (let i = 0; i < types.length; i++)
  values[i] = serializers[types[i]](values[i]);

return await sql.unsafe(inlineValuesToQuery(values));

perhaps if many users need it, it is worth making a built-in helper in the sql function so that it does this

uasan avatar Aug 09 '22 08:08 uasan

I'm having a similar problem where I want to pass the table name and columns to a copy query dynamically.

const query = sql`COPY ${tableName} ${columns} FROM STDIN`;

The solution to nest unsafe would be sufficient for me.

ChristophP avatar Aug 10 '22 13:08 ChristophP

@ChristophP that is different and should be possible to do as things are currently. You should wrap your table name and columns in sql()

eg like this (not tested as i don't know what your variables contain ;) ):

const query = sql`COPY ${ sql(tableName) } ${ sql(columns) } FROM STDIN`;

porsager avatar Aug 10 '22 13:08 porsager

@porsager I tried this

sql`COPY ${ sql('users') } ${ sql(['peter', 'assi']) } FROM STDIN`

but I got "Could not infer helper mode". grafik

ChristophP avatar Aug 16 '22 14:08 ChristophP

Nesting sql.unsafe() is not something that's supported yet is it? I tried it on a copy query like this.

const cols = `(col1, col2)`;
sql`COPY some_table ${sql.unsafe(cols)} FROM STDIN`;

But my DB gave errors and it appeared that it only the first part of the query was sent to the DB. grafik

ChristophP avatar Oct 05 '22 12:10 ChristophP

What version are you seeing that with? (the screenshot error doesn't match the code you posted)

porsager avatar Oct 05 '22 19:10 porsager

sql`COPY ${ sql('users') } ${ sql(['peter', 'assi']) } FROM STDIN`

sql(['peter', 'assi']), won't work there, but I'm looking into fixing that...

porsager avatar Oct 05 '22 19:10 porsager

nesting sql.unsafe works now, so closing this :)

porsager avatar Jun 25 '23 20:06 porsager

@porsager - am trying to do the following in the Latest Master

await sql`copy (select * from events where customer_id = ${sql.unsafe(customer_id)}) to stdout`.readable()`

but it just doesnt seem to work. My customer_id is an uuid String.

My intention is to make both the tableName and condition value to be interpolated. Can you tell me how I can get this to work. Thanks

acehand avatar Jul 19 '23 01:07 acehand

You need to single quote the customer id 😉

porsager avatar Jul 19 '23 07:07 porsager

thanks @porsager . that worked.

acehand avatar Jul 26 '23 04:07 acehand