Skip to content

Commit

Permalink
add createType and dropType to schema module. Closes #112
Browse files Browse the repository at this point in the history
  • Loading branch information
koskimas committed Jul 9, 2022
1 parent e6bc605 commit e5b3a98
Show file tree
Hide file tree
Showing 13 changed files with 366 additions and 2 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "kysely",
"version": "0.19.9",
"version": "0.19.10",
"description": "Type safe SQL query builder",
"repository": {
"type": "git",
Expand Down
38 changes: 38 additions & 0 deletions src/operation-node/create-type-node.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { freeze } from '../util/object-utils.js'
import { IdentifierNode } from './identifier-node.js'
import { OperationNode } from './operation-node.js'
import { ValueListNode } from './value-list-node.js'
import { ValueNode } from './value-node.js'

export type CreateTypeNodeParams = Omit<Partial<CreateTypeNode>, 'kind'>

export interface CreateTypeNode extends OperationNode {
readonly kind: 'CreateTypeNode'
readonly name: IdentifierNode
readonly enum?: ValueListNode
}

/**
* @internal
*/
export const CreateTypeNode = freeze({
is(node: OperationNode): node is CreateTypeNode {
return node.kind === 'CreateTypeNode'
},

create(name: string): CreateTypeNode {
return freeze({
kind: 'CreateTypeNode',
name: IdentifierNode.create(name),
})
},

cloneWithEnum(createType: CreateTypeNode, values: string[]): CreateTypeNode {
return freeze({
...createType,
enum: ValueListNode.create(
values.map((value) => ValueNode.createImmediate(value))
),
})
},
})
34 changes: 34 additions & 0 deletions src/operation-node/drop-type-node.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { freeze } from '../util/object-utils.js'
import { IdentifierNode } from './identifier-node.js'
import { OperationNode } from './operation-node.js'

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

export interface DropTypeNode extends OperationNode {
readonly kind: 'DropTypeNode'
readonly name: IdentifierNode
readonly ifExists?: boolean
}

/**
* @internal
*/
export const DropTypeNode = freeze({
is(node: OperationNode): node is DropTypeNode {
return node.kind === 'DropTypeNode'
},

create(name: string): DropTypeNode {
return freeze({
kind: 'DropTypeNode',
name: IdentifierNode.create(name),
})
},

cloneWith(dropType: DropTypeNode, params: DropTypeNodeParams): DropTypeNode {
return freeze({
...dropType,
...params,
})
},
})
20 changes: 20 additions & 0 deletions src/operation-node/operation-node-transformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ import { DefaultValueNode } from './default-value-node.js'
import { OnNode } from './on-node.js'
import { ValuesNode } from './values-node.js'
import { SelectModifierNode } from './select-modifier-node.js'
import { CreateTypeNode } from './create-type-node.js'
import { DropTypeNode } from './drop-type-node.js'

/**
* Transforms an operation node tree into another one.
Expand Down Expand Up @@ -170,6 +172,8 @@ export class OperationNodeTransformer {
OnNode: this.transformOn.bind(this),
ValuesNode: this.transformValues.bind(this),
SelectModifierNode: this.transformSelectModifier.bind(this),
CreateTypeNode: this.transformCreateType.bind(this),
DropTypeNode: this.transformDropType.bind(this),
})

readonly transformNode = <
Expand Down Expand Up @@ -773,6 +777,22 @@ export class OperationNodeTransformer {
})
}

protected transformCreateType(node: CreateTypeNode): CreateTypeNode {
return requireAllProps<CreateTypeNode>({
kind: 'CreateTypeNode',
name: this.transformNode(node.name),
enum: this.transformNode(node.enum),
})
}

protected transformDropType(node: DropTypeNode): DropTypeNode {
return requireAllProps<DropTypeNode>({
kind: 'DropTypeNode',
name: this.transformNode(node.name),
ifExists: node.ifExists,
})
}

protected transformDataType(node: DataTypeNode): DataTypeNode {
// An Object.freezed leaf node. No need to clone.
return node
Expand Down
6 changes: 6 additions & 0 deletions src/operation-node/operation-node-visitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ import { freeze } from '../util/object-utils.js'
import { OnNode } from './on-node.js'
import { ValuesNode } from './values-node.js'
import { SelectModifierNode } from './select-modifier-node.js'
import { CreateTypeNode } from './create-type-node.js'
import { DropTypeNode } from './drop-type-node.js'

export abstract class OperationNodeVisitor {
protected readonly nodeStack: OperationNode[] = []
Expand Down Expand Up @@ -147,6 +149,8 @@ export abstract class OperationNodeVisitor {
OnNode: this.visitOn.bind(this),
ValuesNode: this.visitValues.bind(this),
SelectModifierNode: this.visitSelectModifier.bind(this),
CreateTypeNode: this.visitCreateType.bind(this),
DropTypeNode: this.visitDropType.bind(this),
})

protected readonly visitNode = (node: OperationNode): void => {
Expand Down Expand Up @@ -230,4 +234,6 @@ export abstract class OperationNodeVisitor {
protected abstract visitOn(node: OnNode): void
protected abstract visitValues(node: ValuesNode): void
protected abstract visitSelectModifier(node: SelectModifierNode): void
protected abstract visitCreateType(node: CreateTypeNode): void
protected abstract visitDropType(node: DropTypeNode): void
}
2 changes: 2 additions & 0 deletions src/operation-node/operation-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ export type OperationNodeKind =
| 'ValuesNode'
| 'CommonTableExpressionNameNode'
| 'SelectModifierNode'
| 'CreateTypeNode'
| 'DropTypeNode'

export interface OperationNode {
readonly kind: OperationNodeKind
Expand Down
10 changes: 10 additions & 0 deletions src/plugin/with-schema/with-schema-transformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import { AliasNode } from '../../operation-node/alias-node.js'
import { AlterTableNode } from '../../operation-node/alter-table-node.js'
import { CreateIndexNode } from '../../operation-node/create-index-node.js'
import { CreateTableNode } from '../../operation-node/create-table-node.js'
import { CreateTypeNode } from '../../operation-node/create-type-node.js'
import { CreateViewNode } from '../../operation-node/create-view-node.js'
import { DeleteQueryNode } from '../../operation-node/delete-query-node.js'
import { DropIndexNode } from '../../operation-node/drop-index-node.js'
import { DropTableNode } from '../../operation-node/drop-table-node.js'
import { DropTypeNode } from '../../operation-node/drop-type-node.js'
import { DropViewNode } from '../../operation-node/drop-view-node.js'
import { InsertQueryNode } from '../../operation-node/insert-query-node.js'
import { JoinNode } from '../../operation-node/join-node.js'
Expand Down Expand Up @@ -78,6 +80,14 @@ export class WithSchemaTransformer extends OperationNodeTransformer {
return this.#transformRoot(node, (node) => super.transformDropView(node))
}

protected override transformCreateType(node: CreateTypeNode): CreateTypeNode {
return this.#transformRoot(node, (node) => super.transformCreateType(node))
}

protected override transformDropType(node: DropTypeNode): DropTypeNode {
return this.#transformRoot(node, (node) => super.transformDropType(node))
}

protected override transformAlterTable(node: AlterTableNode): AlterTableNode {
return this.#transformRoot(node, (node) => super.transformAlterTable(node))
}
Expand Down
22 changes: 22 additions & 0 deletions src/query-compiler/default-query-compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ import {
SelectModifier,
SelectModifierNode,
} from '../operation-node/select-modifier-node.js'
import { CreateTypeNode } from '../operation-node/create-type-node.js'
import { DropTypeNode } from '../operation-node/drop-type-node.js'

export class DefaultQueryCompiler
extends OperationNodeVisitor
Expand Down Expand Up @@ -1098,6 +1100,26 @@ export class DefaultQueryCompiler
}
}

protected override visitCreateType(node: CreateTypeNode): void {
this.append('create type ')
this.visitNode(node.name)

if (node.enum) {
this.append(' as enum ')
this.visitNode(node.enum)
}
}

protected override visitDropType(node: DropTypeNode): void {
this.append('drop type ')

if (node.ifExists) {
this.append('if exists ')
}

this.visitNode(node.name)
}

protected append(str: string): void {
this.#sql += str
}
Expand Down
4 changes: 4 additions & 0 deletions src/query-compiler/query-compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import { AlterTableNode } from '../operation-node/alter-table-node.js'
import { CreateIndexNode } from '../operation-node/create-index-node.js'
import { CreateSchemaNode } from '../operation-node/create-schema-node.js'
import { CreateTableNode } from '../operation-node/create-table-node.js'
import { CreateTypeNode } from '../operation-node/create-type-node.js'
import { CreateViewNode } from '../operation-node/create-view-node.js'
import { DropIndexNode } from '../operation-node/drop-index-node.js'
import { DropSchemaNode } from '../operation-node/drop-schema-node.js'
import { DropTableNode } from '../operation-node/drop-table-node.js'
import { DropTypeNode } from '../operation-node/drop-type-node.js'
import { DropViewNode } from '../operation-node/drop-view-node.js'
import { QueryNode } from '../operation-node/query-node.js'
import { RawNode } from '../operation-node/raw-node.js'
Expand All @@ -23,6 +25,8 @@ export type RootOperationNode =
| DropViewNode
| AlterTableNode
| RawNode
| CreateTypeNode
| DropTypeNode

/**
* a `QueryCompiler` compiles a query expressed as a tree of `OperationNodes` into SQL.
Expand Down
55 changes: 55 additions & 0 deletions src/schema/create-type-builder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { OperationNodeSource } from '../operation-node/operation-node-source.js'
import { CompiledQuery } from '../query-compiler/compiled-query.js'
import { Compilable } from '../util/compilable.js'
import { preventAwait } from '../util/prevent-await.js'
import { QueryExecutor } from '../query-executor/query-executor.js'
import { QueryId } from '../util/query-id.js'
import { freeze } from '../util/object-utils.js'
import { CreateTypeNode } from '../operation-node/create-type-node.js'

export class CreateTypeBuilder implements OperationNodeSource, Compilable {
readonly #props: CreateTypeBuilderProps

constructor(props: CreateTypeBuilderProps) {
this.#props = freeze(props)
}

toOperationNode(): CreateTypeNode {
return this.#props.executor.transformQuery(
this.#props.createTypeNode,
this.#props.queryId
)
}

asEnum(values: string[]): CreateTypeBuilder {
return new CreateTypeBuilder({
...this.#props,
createTypeNode: CreateTypeNode.cloneWithEnum(
this.#props.createTypeNode,
values
),
})
}

compile(): CompiledQuery {
return this.#props.executor.compileQuery(
this.toOperationNode(),
this.#props.queryId
)
}

async execute(): Promise<void> {
await this.#props.executor.executeQuery(this.compile(), this.#props.queryId)
}
}

preventAwait(
CreateTypeBuilder,
"don't await CreateTypeBuilder instances directly. To execute the query you need to call `execute`"
)

export interface CreateTypeBuilderProps {
readonly queryId: QueryId
readonly executor: QueryExecutor
readonly createTypeNode: CreateTypeNode
}
54 changes: 54 additions & 0 deletions src/schema/drop-type-builder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { DropTypeNode } from '../operation-node/drop-type-node.js'
import { OperationNodeSource } from '../operation-node/operation-node-source.js'
import { CompiledQuery } from '../query-compiler/compiled-query.js'
import { Compilable } from '../util/compilable.js'
import { preventAwait } from '../util/prevent-await.js'
import { QueryExecutor } from '../query-executor/query-executor.js'
import { QueryId } from '../util/query-id.js'
import { freeze } from '../util/object-utils.js'

export class DropTypeBuilder implements OperationNodeSource, Compilable {
readonly #props: DropTypeBuilderProps

constructor(props: DropTypeBuilderProps) {
this.#props = freeze(props)
}

ifExists(): DropTypeBuilder {
return new DropTypeBuilder({
...this.#props,
dropTypeNode: DropTypeNode.cloneWith(this.#props.dropTypeNode, {
ifExists: true,
}),
})
}

toOperationNode(): DropTypeNode {
return this.#props.executor.transformQuery(
this.#props.dropTypeNode,
this.#props.queryId
)
}

compile(): CompiledQuery {
return this.#props.executor.compileQuery(
this.toOperationNode(),
this.#props.queryId
)
}

async execute(): Promise<void> {
await this.#props.executor.executeQuery(this.compile(), this.#props.queryId)
}
}

preventAwait(
DropTypeBuilder,
"don't await DropTypeBuilder instances directly. To execute the query you need to call `execute`"
)

export interface DropTypeBuilderProps {
readonly queryId: QueryId
readonly executor: QueryExecutor
readonly dropTypeNode: DropTypeNode
}
Loading

0 comments on commit e5b3a98

Please sign in to comment.