30 lines
1.4 KiB
Go
30 lines
1.4 KiB
Go
package controllers
|
|
|
|
import (
|
|
"regexp"
|
|
"testing"
|
|
)
|
|
|
|
// execSchemaWithRetry re-runs the whole batch on a concurrent-DDL conflict,
|
|
// which is only safe while the batch stays one implicit transaction: no
|
|
// statement of its own opening or closing a transaction, and nothing that
|
|
// cannot run inside a transaction block at all (CREATE INDEX CONCURRENTLY
|
|
// would fail outright with 25001, and a retry could not undo the half of the
|
|
// batch that already committed). The invariant lives in the SQL template, so
|
|
// pin it here rather than in a comment.
|
|
func TestControllerSchemaTemplate_StaysOneImplicitTransaction(t *testing.T) {
|
|
concurrently := regexp.MustCompile(`(?i)\bCONCURRENTLY\b`)
|
|
txControl := regexp.MustCompile(`(?im)^\s*(BEGIN|COMMIT|ROLLBACK|START\s+TRANSACTION)\b`)
|
|
|
|
sql := renderControllerTemplate(postgresControllerSchemaTemplate, "cf_")
|
|
if loc := concurrently.FindString(sql); loc != "" {
|
|
t.Errorf("schema template uses %q — it cannot run inside the implicit transaction execSchemaWithRetry relies on", loc)
|
|
}
|
|
// Only the DDL half is checked for transaction control: the funcs half is
|
|
// dollar-quoted PL/pgSQL, where BEGIN opens a block.
|
|
ddl, _ := splitControllerSchemaSQL(sql)
|
|
if loc := txControl.FindString(ddl); loc != "" {
|
|
t.Errorf("schema DDL contains explicit transaction control %q — the batch must be left to the server's implicit transaction", loc)
|
|
}
|
|
}
|