Skip to content

Commit

Permalink
Drop database connection by default
Browse files Browse the repository at this point in the history
When invoke drop database API or command, by default it will kill all active
connections before dropping db.

May opt out via `dropConnections: false` or `--no-dropConnections`
  • Loading branch information
ivawzh committed Jul 29, 2020
1 parent 059b80d commit ec6d502
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 37 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export type NewDbConfig = {
export type DropDbConfig = {
databaseName: string,
errorIfNonExist?: boolean,
dropConnections?: boolean,
}

export type DbCredential = {
Expand Down Expand Up @@ -121,6 +122,7 @@ USAGE
OPTIONS
-e, --errorIfNonExist [default: false] whether throw error if DB doesn't exist
-d, --dropConnections [default: true] whether automatically drop DB connections
-h, --help show CLI help
-h, --host=host [default: localhost] DB host
-i, --initialDb=initialDb [default: postgres] Initial DB name
Expand All @@ -134,7 +136,7 @@ ALIASES
EXAMPLES
$ pg-god db-drop --databaseName=bank-db
$ pg-god db-drop --databaseName=bank-db --errorIfNonExist
$ pg-god db-drop --databaseName=bank-db --errorIfNonExist --no-dropConnections
$ pg-god db-drop --databaseName=bank-db --password=123 --port=5433 --host=a.example.com --userName=beer
```

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "pg-god",
"description": "Tiny library that helps create and kill PostgreSQL database.",
"version": "1.0.5",
"version": "1.0.6",
"author": "ivan.wang @ivawzh",
"bin": {
"pg-god": "./bin/run"
Expand Down
28 changes: 12 additions & 16 deletions src/commands/db-create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,19 @@ export default class DbCreate extends Command {
}
} = this.parse(DbCreate)

try {
cli.action.start(`😇 Start to create database '${databaseName}'`)
cli.action.start(`😇 Start to create database '${databaseName}'`)

createDatabase(
{ databaseName, errorIfExist },
{
user: userName,
database: initialDb,
port: port,
host: host,
password: password,
}
)
await createDatabase(
{ databaseName, errorIfExist },
{
user: userName,
database: initialDb,
port: port,
host: host,
password: password,
}
)

cli.action.stop()
} catch (error) {
console.error(error)
}
cli.action.stop()
}
}
36 changes: 19 additions & 17 deletions src/commands/db-drop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ export default class DbDrop extends Command {

static examples = [
`$ pg-god db-drop --databaseName=bank-db`,
`$ pg-god db-drop --databaseName=bank-db --errorIfNonExist`,
`$ pg-god db-drop --databaseName=bank-db --errorIfNonExist --no-dropConnections`,
`$ pg-god db-drop --databaseName=bank-db --password=123 --port=5433 --host=a.example.com --userName=beer`,
]

static flags = {
help: flags.help({char: 'h'}),
databaseName: flags.string({char: 'n', required: true, description: 'name of DB attempt to drop', env: 'DB_NAME'}),
errorIfNonExist: flags.boolean({char: 'e', default: false, description: "[default: false] whether throw error if DB doesn't exist", env: 'DB_ERROR_IF_NON_EXIST'}),
dropConnections: flags.boolean({char: 'd', default: true, allowNo: true, description: "[default: true] whether automatically drop DB connections"}),
userName: flags.string({char: 'u', default: 'postgres', description: 'DB user name', env: 'DB_USERNAME'}),
initialDb: flags.string({char: 'i', default: 'postgres', description: 'Initial DB name', env: 'DB_INITIAL'}),
port: flags.integer({char: 'p', default: 5432, description: 'DB port, default `5432`', env: 'DB_PORT'}),
Expand All @@ -28,6 +29,7 @@ export default class DbDrop extends Command {
flags: {
databaseName,
errorIfNonExist,
dropConnections,
userName,
initialDb,
port,
Expand All @@ -36,23 +38,23 @@ export default class DbDrop extends Command {
}
} = this.parse(DbDrop)

try {
cli.action.start(`😇 Start to drop database '${databaseName}'`)
cli.action.start(`😇 Start to drop database '${databaseName}'`)

dropDatabase(
{ databaseName, errorIfNonExist },
{
user: userName,
database: initialDb,
port: port,
host: host,
password: password,
}
)
await dropDatabase(
{
databaseName,
errorIfNonExist,
dropConnections,
},
{
user: userName,
database: initialDb,
port: port,
host: host,
password: password,
}
)

cli.action.stop()
} catch (error) {
console.error(error)
}
cli.action.stop()
}
}
20 changes: 18 additions & 2 deletions src/god-stuff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,12 @@ export async function createDatabase(newDbConfig: NewDbConfig, dbCredential: Par
export type DropDbConfig = {
databaseName: string,
errorIfNonExist?: boolean,
dropConnections?: boolean,
}
/**
* @param dropDbConfig Requires a `databaseName` you are trying to drop. `errorIfNonExist` is default to false. When `errorIfNonExist` is `true`,
* it will throw error when database doesn't exist before executing drop.
* @param dropDbConfig.databaseName Requires a `databaseName` you are trying to drop.
* @param dropDbConfig.errorIfNonExist is default to false. When `errorIfNonExist` is `true`, it will throw error when database doesn't exist before executing drop.
* @param dropDbConfig.dropConnections is default to true. When `dropConnections` is `true`, it will automatically drop all current connections to the database.
* @param dbCredential Default to localhost:5432 `postgres` database and `postgres` user with empty password.
* @throws `PgDbGodError` More details at `errorProtocol`.
*
Expand All @@ -81,10 +83,24 @@ export async function dropDatabase(dropDbConfig: DropDbConfig, dbCredential: DbC
if (existingDb.rowCount === 0 && dropDbConfig.errorIfNonExist) throw PgGodError.dbDoesNotExist()
if (existingDb.rowCount === 0 && !dropDbConfig.errorIfNonExist) return

if (dropDbConfig.dropConnections !== false) await dropDbConnections(client, dropDbConfig.databaseName)

await client.query(`DROP DATABASE "${dropDbConfig.databaseName}";`)
} catch (error) {
throw PgGodError.fromPgError(error)
} finally {
await client.end()
}
}

async function dropDbConnections(client: Client, dbName: string) {
return client.query(`
SELECT
pg_terminate_backend(pg_stat_activity.pid)
FROM
pg_stat_activity
WHERE
pg_stat_activity.datname = '${dbName}'
AND pid <> pg_backend_pid();
`)
}

0 comments on commit ec6d502

Please sign in to comment.