How to prepare an INSERT statement with a dynamic table name for the pq driver
Asked Answered
P

1

6

How do you use a dynamic table name for a prepared INSERT statement for the pq postgres driver? At the moment I've got a test table with id SERIAL and values TEXT columns, and this statement is failing:

stmt, err := db.Prepare("INSERT INTO $1(values) VALUES($2);")
if err != nil {
    log.Fatal(err)
}

That's failing with:

pq: syntax error at or near "$1"

If I can only use placeholders for values and not table names, is there a way around using Sprintf here? The table name contains a string from user input and although I can sanitize it it will slow down the insert a bit compared to letting Postgres return an error on an prepared statement.

Portion answered 29/3, 2018 at 15:17 Comment(4)
Taking a table name from user input, even if you deny SQL injection by using prepared statements, is still extraordinarily dangerous - they could hit any table. If you must do this, do it using Sprintf, but make sure to sanitize the table name down to only those characters allowed in table names per the database's documentation.Marten
@Marten Noted. The table names are actually composed from a strong hash function, pre-calculated and stored in a map.Portion
@AndreaM16 the question was specifically "is there a way around using Sprintf here".Marten
You can't use placeholders for identifiers (such as table and column names). Identifiers exist at a different level than values (just like variable names in Go exist at a different level from values like 6). Whitelist them and quote them (manually since there is AFAIK no "quote identifier" function in the database interface) and use Sprintf.Vast
C
4

To substitute table name variables, go sql package doesn't yet provide a standard interface (in progress).

You might be able to use a database driver specific quote function, eg: QuoteIdentifier.

See also postgres parameter quoting examples.

Creese answered 29/3, 2018 at 22:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.