Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions src/operation-node/drop-type-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@ import { freeze } from '../util/object-utils.js'
import { OperationNode } from './operation-node.js'
import { SchemableIdentifierNode } from './schemable-identifier-node.js'

export type DropTypeNodeParams = Omit<Partial<DropTypeNode>, 'kind' | 'name'>
export type DropTypeNodeParams = Omit<
Partial<DropTypeNode>,
'kind' | 'name' | 'additionalNames'
>

export interface DropTypeNode extends OperationNode {
readonly kind: 'DropTypeNode'
readonly name: SchemableIdentifierNode
readonly additionalNames?: SchemableIdentifierNode[]
readonly ifExists?: boolean
readonly cascade?: boolean
}

/**
Expand All @@ -18,10 +23,17 @@ export const DropTypeNode = freeze({
return node.kind === 'DropTypeNode'
},

create(name: SchemableIdentifierNode): DropTypeNode {
create(
names: SchemableIdentifierNode | SchemableIdentifierNode[],
): DropTypeNode {
if (!Array.isArray(names)) {
names = [names]
}

return freeze({
kind: 'DropTypeNode',
name,
name: names[0],
additionalNames: names.slice(1),
})
},

Expand Down
2 changes: 2 additions & 0 deletions src/operation-node/operation-node-transformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1032,6 +1032,8 @@ export class OperationNodeTransformer {
return requireAllProps<DropTypeNode>({
kind: 'DropTypeNode',
name: this.transformNode(node.name, queryId),
additionalNames: this.transformNodeList(node.additionalNames, queryId),
cascade: node.cascade,
ifExists: node.ifExists,
})
}
Expand Down
10 changes: 10 additions & 0 deletions src/parser/identifier-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ export function parseSchemableIdentifier(id: string): SchemableIdentifierNode {
}
}

export function parseSchemableIdentifierArray(
id: string | string[],
): SchemableIdentifierNode[] {
if (!Array.isArray(id)) {
id = [id]
}

return id.map(parseSchemableIdentifier)
}

function trim(str: string): string {
return str.trim()
}
9 changes: 9 additions & 0 deletions src/query-compiler/default-query-compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1429,6 +1429,15 @@ export class DefaultQueryCompiler
}

this.visitNode(node.name)

if (node.additionalNames?.length) {
this.append(', ')
this.compileList(node.additionalNames)
}

if (node.cascade) {
this.append(' cascade')
}
}

protected override visitExplain(node: ExplainNode): void {
Expand Down
15 changes: 15 additions & 0 deletions src/schema/drop-type-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ export class DropTypeBuilder implements OperationNodeSource, Compilable {
this.#props = freeze(props)
}

/**
* Adds `if exists` to the query.
*/
ifExists(): DropTypeBuilder {
return new DropTypeBuilder({
...this.#props,
Expand All @@ -22,6 +25,18 @@ export class DropTypeBuilder implements OperationNodeSource, Compilable {
})
}

/**
* Adds `cascade` to the query.
*/
cascade(): DropTypeBuilder {
return new DropTypeBuilder({
...this.#props,
node: DropTypeNode.cloneWith(this.#props.node, {
cascade: true,
}),
})
}

/**
* Simply calls the provided function passing `this` as the only argument. `$call` returns
* what the provided function returns.
Expand Down
19 changes: 16 additions & 3 deletions src/schema/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ import { CreateTypeBuilder } from './create-type-builder.js'
import { DropTypeBuilder } from './drop-type-builder.js'
import { CreateTypeNode } from '../operation-node/create-type-node.js'
import { DropTypeNode } from '../operation-node/drop-type-node.js'
import { parseSchemableIdentifier } from '../parser/identifier-parser.js'
import {
parseSchemableIdentifier,
parseSchemableIdentifierArray,
} from '../parser/identifier-parser.js'
import { RefreshMaterializedViewBuilder } from './refresh-materialized-view-builder.js'
import { RefreshMaterializedViewNode } from '../operation-node/refresh-materialized-view-node.js'

Expand Down Expand Up @@ -311,12 +314,22 @@ export class SchemaModule {
* .ifExists()
* .execute()
* ```
*
* You can also provide multiple type names:
*
* ```ts
* await db.schema
* .dropType(['species', 'colors'])
* .ifExists()
* .cascade()
* .execute()
* ```
*/
dropType(typeName: string): DropTypeBuilder {
dropType(typeName: string | string[]): DropTypeBuilder {
return new DropTypeBuilder({
queryId: createQueryId(),
executor: this.#executor,
node: DropTypeNode.create(parseSchemableIdentifier(typeName)),
node: DropTypeNode.create(parseSchemableIdentifierArray(typeName)),
})
}

Expand Down
61 changes: 60 additions & 1 deletion test/node/src/schema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2457,6 +2457,7 @@ for (const dialect of DIALECTS) {
if (sqlSpec === 'postgres') {
it('should drop a schema cascade', async () => {
await ctx.db.schema.createSchema('pets').execute()

const builder = ctx.db.schema.dropSchema('pets').cascade()

testSql(builder, dialect, {
Expand Down Expand Up @@ -2561,10 +2562,68 @@ for (const dialect of DIALECTS) {

await builder.execute()
})

it('should drop multiple types', async () => {
await ctx.db.schema.createType('species').execute()
await ctx.db.schema.createType('colors').execute()

const builder = ctx.db.schema
.dropType(['species', 'colors'])
.ifExists()

testSql(builder, dialect, {
postgres: {
sql: `drop type if exists "species", "colors"`,
parameters: [],
},
mysql: NOT_SUPPORTED,
mssql: NOT_SUPPORTED,
sqlite: NOT_SUPPORTED,
})

await builder.execute()
})

it('should drop multiple types if exists', async () => {
await ctx.db.schema.createType('species').execute()
const builder = ctx.db.schema
.dropType(['species', 'colors'])
.ifExists()

testSql(builder, dialect, {
postgres: {
sql: `drop type if exists "species", "colors"`,
parameters: [],
},
mysql: NOT_SUPPORTED,
mssql: NOT_SUPPORTED,
sqlite: NOT_SUPPORTED,
})

await builder.execute()
})

it('should drop a type and cascade', async () => {
await ctx.db.schema.createType('species').execute()

const builder = ctx.db.schema.dropType('species').cascade()

testSql(builder, dialect, {
postgres: {
sql: `drop type "species" cascade`,
parameters: [],
},
mysql: NOT_SUPPORTED,
mssql: NOT_SUPPORTED,
sqlite: NOT_SUPPORTED,
})

await builder.execute()
})
}

async function cleanup() {
await ctx.db.schema.dropType('species').ifExists().execute()
await ctx.db.schema.dropType(['species', 'colors']).ifExists().execute()
}
})

Expand Down
Loading