Groundwork for PostgreSQL, with no PostgreSQL in it yet: the store still opens SQLite and behaves exactly as it did. One set of queries rather than one per database. The SQL here is almost entirely portable — ON CONFLICT upserts work in both, and the only construct that genuinely differs is the placeholder — so two copies of every query would buy nothing and drift, one query at a time, discovered in production. The rewrite is a wrapper around the handle rather than a change at each call site. There are sixty of those and sixty chances to forget one; this way the only route to the driver goes through the rewrite. Making it a wrapper found six places that reached past it, including all three manual transactions and two prepared statements — every one of which would have worked on SQLite and failed on PostgreSQL, on a path nobody exercises before deploying. The rewriter skips quoted sections. No query here contains a question mark in a literal today; this is so that adding one is a test failure rather than a statement that silently binds the wrong argument. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
45 lines
1.4 KiB
Go
45 lines
1.4 KiB
Go
package store
|
|
|
|
import "testing"
|
|
|
|
func TestSQLiteKeepsItsPlaceholders(t *testing.T) {
|
|
q := "SELECT a FROM t WHERE b = ? AND c = ?"
|
|
if got := SQLiteDialect.rebind(q); got != q {
|
|
t.Errorf("sqlite query was rewritten: %s", got)
|
|
}
|
|
}
|
|
|
|
func TestPostgresGetsNumberedPlaceholders(t *testing.T) {
|
|
got := PostgresDialect.rebind("SELECT a FROM t WHERE b = ? AND c = ?")
|
|
want := "SELECT a FROM t WHERE b = $1 AND c = $2"
|
|
if got != want {
|
|
t.Errorf("rebind = %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestAQuestionMarkInsideALiteralIsLeftAlone(t *testing.T) {
|
|
// No query here contains one today. This exists so that adding one is a
|
|
// test failure rather than a query that silently reads the wrong argument
|
|
// — or, worse, one that still parses and returns the wrong rows.
|
|
got := PostgresDialect.rebind(`SELECT a FROM t WHERE name = 'why?' AND b = ?`)
|
|
want := `SELECT a FROM t WHERE name = 'why?' AND b = $1`
|
|
if got != want {
|
|
t.Errorf("rebind = %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestDoubleQuotedIdentifiersAreAlsoSkipped(t *testing.T) {
|
|
got := PostgresDialect.rebind(`SELECT "odd?name" FROM t WHERE b = ?`)
|
|
want := `SELECT "odd?name" FROM t WHERE b = $1`
|
|
if got != want {
|
|
t.Errorf("rebind = %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestAQueryWithNoPlaceholdersIsUntouched(t *testing.T) {
|
|
q := "DELETE FROM t"
|
|
if got := PostgresDialect.rebind(q); got != q {
|
|
t.Errorf("rebind = %q", got)
|
|
}
|
|
}
|