v0.6.0
The test-database lifecycle is no longer MySQL-only. DBLifecycle became a public extension point
with MySQL, PostgreSQL and SQLite implementations in the box, and identifier quoting moved out of
fmt.Sprintf.
WithConnectionFactory lost its executeDbCreateStmt bool parameter. The flag selected between
MySQL DDL and doing nothing, which is what tied the library to one engine.
| |
DBLifecycleandDBLifecycleBuilderare exported, so a consumer can implement create/drop for an engine puppetest does not ship.WithDatabaseLifecycle(...)selects the lifecycle. Option order does not matter: it is built after every option has run, over the root connectionWithConnectionFactoryopened.MySQLLifecyclekeeps the previousCREATE/DROP DATABASE IF [NOT] EXISTSbehaviour with backtick quoting.PostgresLifecyclecheckspg_databaseinstead of theIF NOT EXISTSPostgreSQL does not have, treats SQLSTATE42P04as success, and terminates live backends before dropping so teardown does not fail intermittently. It works on servers older than 13, which lackDROP DATABASE ... WITH (FORCE).SQLiteLifecycle(pathFor)manages the database file and its-wal/-shmsidecars, since SQLite has noCREATE DATABASE.QuoteIdentifier(name, quote)escapes an identifier by doubling the quote rune, and rejects an empty name or one holding a null byte. Database names reach a lifecycle from the caller, so this replaces interpolating them straight into a statement.
Engine.Seed hardcoded ? bind markers, which are a syntax error on PostgreSQL. The style is now
pluggable and still defaults to ?.
WithPlaceholderStyle(...)on the engine factory, withQuestionPlaceholder(default) andOrdinalPlaceholder($1,$2) shipped.bancoche.NewMapQuery(...)takesbancoche.WithPlaceholderStyle(...), since it is built from a*sql.DBand never sees the engine.NewRawQueryis unchanged; that SQL belongs to the caller.- Markers are GENERATED, never rewritten, so no SQL is parsed and no string literal or comment can be corrupted by the substitution.
WithConnectionTimeout(d) replaces the hardcoded one-second budget, which covered dial, auth and
ping with no way to change it. The default is unchanged. The budget is shared by the
ConnectionPerformer and the ping, so it could not be extended from the call site.
NewDatabasedrops the database it just created when the follow-up connection fails, instead of stranding it on the server;ConnectionPerformer.Executecloses the connection when its ping fails; the engine factory’s lazy provider store no longer races under concurrent access.
puppetest still has no third-party dependencies. PostgresLifecycle reads the duplicate-database
SQLSTATE through an interface{ SQLState() string } rather than importing a driver.
That structural read is what makes concurrent creation of the same database name safe, so the
guarantee depends on the driver: pgx’s *pgconn.PgError satisfies it, lib/pq’s *pq.Error does
not. On lib/pq, two tests racing to create one database name are not protected and one fails.
Under go test -p N that is the main path rather than an edge case.