Skip to content

Commit f5da1e2

Browse files
p4cketcyrilgdn
andauthored
Drop connections before drop database (#14)
* test * testing * testing * testing * support for other psql versions * Update postgresql/resource_postgresql_database.go Co-authored-by: Cyril Gaudin <[email protected]> * Update postgresql/resource_postgresql_database.go * Update postgresql/resource_postgresql_database.go * fixup! Update postgresql/resource_postgresql_database.go Co-authored-by: Cyril Gaudin <[email protected]>
1 parent 6816fac commit f5da1e2

File tree

2 files changed

+45
-1
lines changed

2 files changed

+45
-1
lines changed

postgresql/config.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ const (
2525
featureReplication
2626
featureExtension
2727
featurePrivileges
28+
featureForceDropDatabase
29+
featurePid
2830
)
2931

3032
type dbRegistryEntry struct {
@@ -65,6 +67,14 @@ var (
6567
// We do not support postgresql_grant and postgresql_default_privileges
6668
// for Postgresql < 9.
6769
featurePrivileges: semver.MustParseRange(">=9.0.0"),
70+
71+
// DROP DATABASE WITH FORCE
72+
// for Postgresql >= 13
73+
featureForceDropDatabase: semver.MustParseRange(">=13.0.0"),
74+
75+
// Column procpid was replaced by pid in pg_stat_activity
76+
// for Postgresql >= 9.2 and above
77+
featurePid: semver.MustParseRange(">=9.2.0"),
6878
}
6979
)
7080

postgresql/resource_postgresql_database.go

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ func resourcePostgreSQLDatabaseDelete(d *schema.ResourceData, meta interface{})
233233
currentUser := c.config.getDatabaseUsername()
234234
owner := d.Get(dbOwnerAttr).(string)
235235

236+
var dropWithForce string
236237
var err error
237238
if owner != "" {
238239
// Needed in order to set the owner of the db if the connection user is not a
@@ -263,7 +264,18 @@ func resourcePostgreSQLDatabaseDelete(d *schema.ResourceData, meta interface{})
263264
return err
264265
}
265266

266-
sql := fmt.Sprintf("DROP DATABASE %s", pq.QuoteIdentifier(dbName))
267+
// Terminate all active connections and block new one
268+
if err := terminateBConnections(c, dbName); err != nil {
269+
return err
270+
}
271+
272+
// Drop with force only for psql 13+
273+
if c.featureSupported(featureForceDropDatabase) {
274+
dropWithForce = "WITH ( FORCE )"
275+
}
276+
277+
sql := fmt.Sprintf("DROP DATABASE %s %s", pq.QuoteIdentifier(dbName), dropWithForce)
278+
267279
if _, err := c.DB().Exec(sql); err != nil {
268280
return fmt.Errorf("Error dropping database: %w", err)
269281
}
@@ -548,3 +560,25 @@ func doSetDBIsTemplate(c *Client, dbName string, isTemplate bool) error {
548560

549561
return nil
550562
}
563+
564+
func terminateBConnections(c *Client, dbName string) error {
565+
var terminateSql string
566+
567+
if c.featureSupported(featureDBAllowConnections) {
568+
alterSql := fmt.Sprintf("ALTER DATABASE %s ALLOW_CONNECTIONS false", pq.QuoteIdentifier(dbName))
569+
570+
if _, err := c.DB().Exec(alterSql); err != nil {
571+
return fmt.Errorf("Error blocking connections to database: %w", err)
572+
}
573+
}
574+
pid := "procpid"
575+
if c.featureSupported(featurePid) {
576+
pid = "pid"
577+
}
578+
terminateSql = fmt.Sprintf("SELECT pg_terminate_backend(%s) FROM pg_stat_activity WHERE datname = '%s' AND %s <> pg_backend_pid()", pid, dbName, pid)
579+
if _, err := c.DB().Exec(terminateSql); err != nil {
580+
return fmt.Errorf("Error terminating database connections: %w", err)
581+
}
582+
583+
return nil
584+
}

0 commit comments

Comments
 (0)