Skip to content

Commit

Permalink
feat: drop postgres domain (#981)
Browse files Browse the repository at this point in the history
* feat: drop postgres domain

* fix(TransactionClient): adding missing methods

* fix: adapt for v6
  • Loading branch information
MaximeMRF committed Feb 15, 2024
1 parent 5ec314b commit 659b061
Show file tree
Hide file tree
Showing 12 changed files with 237 additions and 1 deletion.
23 changes: 23 additions & 0 deletions commands/db_wipe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ export default class DbWipe extends BaseCommand {
@flags.boolean({ description: 'Drop all custom types (Postgres only)' })
declare dropTypes: boolean

/**
* Drop all domains in database
*/
@flags.boolean({ description: 'Drop all domains (Postgres only)' })
declare dropDomains: boolean

/**
* Force command execution in production
*/
Expand Down Expand Up @@ -104,6 +110,22 @@ export default class DbWipe extends BaseCommand {
this.logger.success('Dropped types successfully')
}

/**
* Drop all domains (if asked for and supported)
*/
private async performDropDomains(client: QueryClientContract, schemas: string[]) {
if (!this.dropDomains) {
return
}

if (!client.dialect.supportsDomains) {
this.logger.warning(`Dropping domains is not supported by "${client.dialect.name}"`)
}

await client.dropAllDomains(schemas)
this.logger.success('Dropped domains successfully')
}

/**
* Run as a subcommand. Never close database connections or exit
* process inside this method
Expand Down Expand Up @@ -147,6 +169,7 @@ export default class DbWipe extends BaseCommand {
await this.performDropViews(connection, schemas)
await this.performDropTables(connection, schemas)
await this.performDropTypes(connection, schemas)
await this.performDropDomains(connection, schemas)
}

/**
Expand Down
10 changes: 10 additions & 0 deletions commands/migration/fresh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ export default class Refresh extends BaseCommand {
@flags.boolean({ description: 'Drop all custom types (Postgres only)' })
declare dropTypes: boolean

/**
* Drop all domains in database
*/
@flags.boolean({ description: 'Drop all domains (Postgres only)' })
declare dropDomains: boolean

/**
* Disable advisory locks
*/
Expand Down Expand Up @@ -86,6 +92,10 @@ export default class Refresh extends BaseCommand {
args.push('--drop-types')
}

if (this.dropDomains) {
args.push('--drop-domains')
}

if (this.dropViews) {
args.push('--drop-views')
}
Expand Down
15 changes: 15 additions & 0 deletions src/dialects/base_sqlite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export abstract class BaseSqliteDialect implements DialectContract {
readonly supportsAdvisoryLocks = false
readonly supportsViews = true
readonly supportsTypes = false
readonly supportsDomains = false
readonly supportsReturningStatement = false

/**
Expand Down Expand Up @@ -72,6 +73,13 @@ export abstract class BaseSqliteDialect implements DialectContract {
throw new Error("Sqlite doesn't support types")
}

/**
* Returns an array of all domains names
*/
async getAllDomains(): Promise<string[]> {
throw new Error("Sqlite doesn't support domains")
}

/**
* Truncate SQLITE tables
*/
Expand Down Expand Up @@ -112,6 +120,13 @@ export abstract class BaseSqliteDialect implements DialectContract {
throw new Error("Sqlite doesn't support types")
}

/**
* Drop all custom domains inside the database
*/
async dropAllDomains(): Promise<void> {
throw new Error("Sqlite doesn't support domains")
}

/**
* Attempts to add advisory lock to the database and
* returns it's status.
Expand Down
13 changes: 13 additions & 0 deletions src/dialects/mssql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export class MssqlDialect implements DialectContract {
readonly supportsAdvisoryLocks = false
readonly supportsViews = false
readonly supportsTypes = false
readonly supportsDomains = false
readonly supportsReturningStatement = true

/**
Expand Down Expand Up @@ -99,6 +100,12 @@ export class MssqlDialect implements DialectContract {
)
}

async getAllDomains(): Promise<string[]> {
throw new Error(
'"getAllDomains" method not implemented is not implemented for mssql. Create a PR to add the feature'
)
}

async dropAllViews(): Promise<void> {
throw new Error(
'"dropAllViews" method not implemented is not implemented for mssql. Create a PR to add the feature'
Expand All @@ -111,6 +118,12 @@ export class MssqlDialect implements DialectContract {
)
}

async dropAllDomains(): Promise<void> {
throw new Error(
'"dropAllDomains" method not implemented is not implemented for mssql. Create a PR to add the feature'
)
}

getAdvisoryLock(): Promise<boolean> {
throw new Error(
'Support for advisory locks is not implemented for mssql. Create a PR to add the feature'
Expand Down
15 changes: 15 additions & 0 deletions src/dialects/mysql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export class MysqlDialect implements DialectContract {
readonly supportsAdvisoryLocks = true
readonly supportsViews = true
readonly supportsTypes = false
readonly supportsDomains = false
readonly supportsReturningStatement = false

/**
Expand Down Expand Up @@ -96,6 +97,13 @@ export class MysqlDialect implements DialectContract {
throw new Error("MySQL doesn't support types")
}

/**
* Returns an array of all domain names
*/
async getAllDomains(): Promise<string[]> {
throw new Error("MySQL doesn't support domains")
}

/**
* Drop all tables inside the database
*/
Expand Down Expand Up @@ -149,6 +157,13 @@ export class MysqlDialect implements DialectContract {
throw new Error("MySQL doesn't support types")
}

/**
* Drop all domains inside the database
*/
async dropAllDomains(): Promise<void> {
throw new Error("MySQL doesn't support domains")
}

/**
* Attempts to add advisory lock to the database and
* returns it's status.
Expand Down
13 changes: 13 additions & 0 deletions src/dialects/oracle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export class OracleDialect implements DialectContract {
readonly supportsAdvisoryLocks = false
readonly supportsViews = false
readonly supportsTypes = false
readonly supportsDomains = false
readonly supportsReturningStatement = true

/**
Expand Down Expand Up @@ -71,6 +72,12 @@ export class OracleDialect implements DialectContract {
)
}

async getAllDomains(): Promise<string[]> {
throw new Error(
'"getAllDomains" method is not implemented for oracledb. Create a PR to add the feature.'
)
}

async dropAllViews(): Promise<void> {
throw new Error(
'"dropAllViews" method is not implemented for oracledb. Create a PR to add the feature.'
Expand All @@ -83,6 +90,12 @@ export class OracleDialect implements DialectContract {
)
}

async dropAllDomains(): Promise<void> {
throw new Error(
'"dropAllDomains" method is not implemented for oracledb. Create a PR to add the feature.'
)
}

getAdvisoryLock(): Promise<boolean> {
throw new Error(
'Support for advisory locks is not implemented for oracledb. Create a PR to add the feature'
Expand Down
37 changes: 37 additions & 0 deletions src/dialects/pg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export class PgDialect implements DialectContract {
readonly supportsAdvisoryLocks = true
readonly supportsViews = true
readonly supportsTypes = true
readonly supportsDomains = true
readonly supportsReturningStatement = true

/**
Expand Down Expand Up @@ -77,6 +78,21 @@ export class PgDialect implements DialectContract {
return types.map(({ typname }) => typname)
}

/**
* Returns an array of all domain names
*/
async getAllDomains(_schemas: string[]) {
const domains = await this.client
.query()
.select('pg_type.typname')
.distinct()
.from('pg_type')
.innerJoin('pg_namespace', 'pg_namespace.oid', 'pg_type.typnamespace')
.where('pg_type.typtype', 'd')

return domains.map(({ typname }) => typname)
}

/**
* Truncate pg table with option to cascade and restart identity
*/
Expand Down Expand Up @@ -126,6 +142,27 @@ export class PgDialect implements DialectContract {
await this.client.rawQuery(`DROP TYPE "${types.join('", "')}" CASCADE;`)
}

/**
* Drop all domains inside the database
*/
async dropAllDomains(schemas: string[]) {
const domains = await this.getAllDomains(schemas)
if (!domains.length) return

// Don't drop built-in domains
// https://www.postgresql.org/docs/current/infoschema-datatypes.html
const builtInDomains = [
'cardinal_number',
'character_data',
'sql_identifier',
'time_stamp',
'yes_or_no',
]
const domainsToDrop = domains.filter((domain) => !builtInDomains.includes(domain))

await this.client.rawQuery(`DROP DOMAIN "${domainsToDrop.join('", "')}" CASCADE;`)
}

/**
* Attempts to add advisory lock to the database and
* returns it's status.
Expand Down
41 changes: 41 additions & 0 deletions src/dialects/red_shift.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export class RedshiftDialect implements DialectContract {
readonly supportsAdvisoryLocks = false
readonly supportsViews = true
readonly supportsTypes = true
readonly supportsDomains = true
readonly supportsReturningStatement = true

/**
Expand Down Expand Up @@ -83,6 +84,23 @@ export class RedshiftDialect implements DialectContract {
return types.map(({ typname }) => typname)
}

/**
* Returns an array of all domain names
*
* NOTE: ASSUMING FEATURE PARITY WITH POSTGRESQL HERE (NOT TESTED)
*/
async getAllDomains(_schemas: string[]) {
const domains = await this.client
.query()
.select('pg_type.typname')
.distinct()
.from('pg_type')
.innerJoin('pg_namespace', 'pg_namespace.oid', 'pg_type.typnamespace')
.where('pg_type.typtype', 'd')

return domains.map(({ typname }) => typname)
}

/**
* Truncate redshift table with option to cascade and restart identity.
*
Expand Down Expand Up @@ -138,6 +156,29 @@ export class RedshiftDialect implements DialectContract {
await this.client.rawQuery(`DROP type ${types.join(',')};`)
}

/**
* Drop all domains inside the database
*
* NOTE: ASSUMING FEATURE PARITY WITH POSTGRESQL HERE (NOT TESTED)
*/
async dropAllDomains(schemas: string[]) {
const domains = await this.getAllDomains(schemas)
if (!domains.length) return

// Don't drop built-in domains
// https://www.postgresql.org/docs/current/infoschema-datatypes.html
const builtInDomains = [
'cardinal_number',
'character_data',
'sql_identifier',
'time_stamp',
'yes_or_no',
]
const domainsToDrop = domains.filter((domain) => !builtInDomains.includes(domain))

await this.client.rawQuery(`DROP DOMAIN "${domainsToDrop.join('", "')}" CASCADE;`)
}

/**
* Redshift doesn't support advisory locks. Learn more:
* https://tableplus.com/blog/2018/10/redshift-vs-postgres-database-comparison.html
Expand Down
14 changes: 14 additions & 0 deletions src/query_client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,13 @@ export class QueryClient implements QueryClientContract {
return this.dialect.getAllTypes(schemas)
}

/**
* Returns an array of all domain names
*/
async getAllDomains(schemas?: string[]): Promise<string[]> {
return this.dialect.getAllDomains(schemas)
}

/**
* Drop all tables inside database
*/
Expand All @@ -181,6 +188,13 @@ export class QueryClient implements QueryClientContract {
return this.dialect.dropAllTypes(schemas || ['public'])
}

/**
* Drop all custom domains inside the database
*/
async dropAllDomains(schemas?: string[]): Promise<void> {
return this.dialect.dropAllDomains(schemas || ['public'])
}

/**
* Returns an instance of a transaction. Each transaction will
* query and hold a single connection for all queries.
Expand Down
14 changes: 14 additions & 0 deletions src/transaction_client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,13 @@ export class TransactionClient extends EventEmitter implements TransactionClient
return this.dialect.getAllTypes(schemas)
}

/**
* Returns an array of all domains names
*/
async getAllDomains(schemas?: string[]): Promise<string[]> {
return this.dialect.getAllDomains(schemas)
}

/**
* Drop all tables inside database
*/
Expand All @@ -145,6 +152,13 @@ export class TransactionClient extends EventEmitter implements TransactionClient
return this.dialect.dropAllTypes(schemas || ['public'])
}

/**
* Drop all domains inside the database
*/
async dropAllDomains(schemas?: string[]): Promise<void> {
return this.dialect.dropAllDomains(schemas || ['public'])
}

/**
* Get a new query builder instance
*/
Expand Down

0 comments on commit 659b061

Please sign in to comment.