Skip to content

Commit 5f5b8b8

Browse files
committed
add support for CREATE TRIGGER
1 parent 680eb46 commit 5f5b8b8

15 files changed

+968
-5
lines changed

Diff for: src/kysely.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ export class Kysely<DB>
126126
/**
127127
* Returns the {@link SchemaModule} module for building database schema.
128128
*/
129-
get schema(): SchemaModule {
129+
get schema(): SchemaModule<DB> {
130130
return new SchemaModule(this.#props.executor)
131131
}
132132

Diff for: src/operation-node/create-trigger-node.ts

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { freeze } from '../util/object-utils.js'
2+
import { OperationNode } from './operation-node.js'
3+
import { TableNode } from './table-node.js'
4+
import { IdentifierNode } from './identifier-node.js'
5+
import { QueryNode } from './query-node.js'
6+
import { TriggerEventNode } from './trigger-event-node.js'
7+
import { TriggerOrderNode } from './trigger-order-node.js'
8+
import { FunctionNode } from './function-node.js'
9+
10+
export type TriggerTime = 'after' | 'before' | 'instead of'
11+
12+
export type CreateTriggerNodeParams = Omit<
13+
CreateTriggerNode,
14+
'kind' | 'name' | 'queries'
15+
>
16+
17+
export interface CreateTriggerNode extends OperationNode {
18+
readonly kind: 'CreateTriggerNode'
19+
readonly name: IdentifierNode
20+
readonly queries?: ReadonlyArray<QueryNode>
21+
readonly function?: FunctionNode
22+
readonly time?: TriggerTime
23+
readonly events?: ReadonlyArray<TriggerEventNode>
24+
readonly table?: TableNode
25+
readonly orReplace?: boolean
26+
readonly ifNotExists?: boolean
27+
readonly when?: OperationNode
28+
readonly temporary?: boolean
29+
readonly forEach?: 'row' | 'statement'
30+
readonly order?: TriggerOrderNode
31+
}
32+
33+
/**
34+
* @internal
35+
*/
36+
export const CreateTriggerNode = freeze({
37+
is(node: OperationNode): node is CreateTriggerNode {
38+
return node.kind === 'CreateTriggerNode'
39+
},
40+
41+
create(name: IdentifierNode): CreateTriggerNode {
42+
return freeze({
43+
kind: 'CreateTriggerNode',
44+
name,
45+
})
46+
},
47+
48+
cloneWithQuery(
49+
createTrigger: CreateTriggerNode,
50+
query: QueryNode
51+
): CreateTriggerNode {
52+
return freeze({
53+
...createTrigger,
54+
queries: freeze([...(createTrigger.queries || []), query]),
55+
})
56+
},
57+
58+
cloneWithEvent(
59+
createTrigger: CreateTriggerNode,
60+
event: TriggerEventNode
61+
): CreateTriggerNode {
62+
return freeze({
63+
...createTrigger,
64+
events: freeze([...(createTrigger.events || []), event]),
65+
})
66+
},
67+
68+
cloneWith(
69+
createTrigger: CreateTriggerNode,
70+
params: CreateTriggerNodeParams
71+
): CreateTriggerNode {
72+
return freeze({
73+
...createTrigger,
74+
...params,
75+
})
76+
},
77+
})

Diff for: src/operation-node/drop-trigger-node.ts

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { freeze } from '../util/object-utils.js'
2+
import { OperationNode } from './operation-node.js'
3+
import { SchemableIdentifierNode } from './schemable-identifier-node.js'
4+
5+
export type DropTriggerNodeParams = Omit<
6+
Partial<DropTriggerNode>,
7+
'kind' | 'name'
8+
>
9+
export interface DropTriggerNode extends OperationNode {
10+
readonly kind: 'DropTriggerNode'
11+
readonly name: SchemableIdentifierNode
12+
readonly ifExists?: boolean
13+
readonly cascade?: boolean
14+
}
15+
16+
/**
17+
* @internal
18+
*/
19+
export const DropTriggerNode = freeze({
20+
is(node: OperationNode): node is DropTriggerNode {
21+
return node.kind === 'DropTriggerNode'
22+
},
23+
24+
create(name: SchemableIdentifierNode): DropTriggerNode {
25+
return freeze({
26+
kind: 'DropTriggerNode',
27+
name,
28+
})
29+
},
30+
31+
cloneWith(
32+
dropTrigger: DropTriggerNode,
33+
params: DropTriggerNodeParams
34+
): DropTriggerNode {
35+
return freeze({
36+
...dropTrigger,
37+
...params,
38+
})
39+
},
40+
})

Diff for: src/operation-node/operation-node-transformer.ts

+51
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ import { JSONPathLegNode } from './json-path-leg-node.js'
8888
import { JSONOperatorChainNode } from './json-operator-chain-node.js'
8989
import { TupleNode } from './tuple-node.js'
9090
import { AddIndexNode } from './add-index-node.js'
91+
import { CreateTriggerNode } from './create-trigger-node.js'
92+
import { DropTriggerNode } from './drop-trigger-node.js'
93+
import { TriggerEventNode } from './trigger-event-node.js'
94+
import { TriggerOrderNode } from './trigger-order-node.js'
9195

9296
/**
9397
* Transforms an operation node tree into another one.
@@ -210,6 +214,10 @@ export class OperationNodeTransformer {
210214
JSONOperatorChainNode: this.transformJSONOperatorChain.bind(this),
211215
TupleNode: this.transformTuple.bind(this),
212216
AddIndexNode: this.transformAddIndex.bind(this),
217+
CreateTriggerNode: this.transformCreateTrigger.bind(this),
218+
TriggerEventNode: this.transformTriggerEvent.bind(this),
219+
TriggerOrderNode: this.transformTriggerOrder.bind(this),
220+
DropTriggerNode: this.transformDropTrigger.bind(this),
213221
})
214222

215223
transformNode<T extends OperationNode | undefined>(node: T): T {
@@ -417,6 +425,40 @@ export class OperationNodeTransformer {
417425
})
418426
}
419427

428+
protected transformCreateTrigger(node: CreateTriggerNode): CreateTriggerNode {
429+
return requireAllProps<CreateTriggerNode>({
430+
kind: 'CreateTriggerNode',
431+
name: this.transformNode(node.name),
432+
table: this.transformNode(node.table),
433+
ifNotExists: node.ifNotExists,
434+
time: node.time,
435+
events: this.transformNodeList(node.events),
436+
forEach: node.forEach,
437+
orReplace: node.orReplace,
438+
temporary: node.temporary,
439+
queries: this.transformNodeList(node.queries),
440+
function: this.transformNode(node.function),
441+
when: this.transformNode(node.when),
442+
order: this.transformNode(node.order),
443+
})
444+
}
445+
446+
protected transformTriggerEvent(node: TriggerEventNode): TriggerEventNode {
447+
return requireAllProps<TriggerEventNode>({
448+
kind: 'TriggerEventNode',
449+
event: node.event,
450+
columns: this.transformNodeList(node.columns),
451+
})
452+
}
453+
454+
protected transformTriggerOrder(node: TriggerOrderNode): TriggerOrderNode {
455+
return requireAllProps<TriggerOrderNode>({
456+
kind: 'TriggerOrderNode',
457+
order: node.order,
458+
otherTriggerName: this.transformNode(node.otherTriggerName),
459+
})
460+
}
461+
420462
protected transformColumnDefinition(
421463
node: ColumnDefinitionNode
422464
): ColumnDefinitionNode {
@@ -455,6 +497,15 @@ export class OperationNodeTransformer {
455497
})
456498
}
457499

500+
protected transformDropTrigger(node: DropTriggerNode): DropTriggerNode {
501+
return requireAllProps<DropTriggerNode>({
502+
kind: 'DropTriggerNode',
503+
name: this.transformNode(node.name),
504+
ifExists: node.ifExists,
505+
cascade: node.cascade,
506+
})
507+
}
508+
458509
protected transformOrderBy(node: OrderByNode): OrderByNode {
459510
return requireAllProps<OrderByNode>({
460511
kind: 'OrderByNode',

Diff for: src/operation-node/operation-node-visitor.ts

+12
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ import { JSONPathLegNode } from './json-path-leg-node.js'
9090
import { JSONOperatorChainNode } from './json-operator-chain-node.js'
9191
import { TupleNode } from './tuple-node.js'
9292
import { AddIndexNode } from './add-index-node.js'
93+
import { CreateTriggerNode } from './create-trigger-node.js'
94+
import { DropTriggerNode } from './drop-trigger-node.js'
95+
import { TriggerEventNode } from './trigger-event-node.js'
96+
import { TriggerOrderNode } from './trigger-order-node.js'
9397

9498
export abstract class OperationNodeVisitor {
9599
protected readonly nodeStack: OperationNode[] = []
@@ -187,6 +191,10 @@ export abstract class OperationNodeVisitor {
187191
JSONOperatorChainNode: this.visitJSONOperatorChain.bind(this),
188192
TupleNode: this.visitTuple.bind(this),
189193
AddIndexNode: this.visitAddIndex.bind(this),
194+
CreateTriggerNode: this.visitCreateTrigger.bind(this),
195+
TriggerEventNode: this.visitTriggerEvent.bind(this),
196+
TriggerOrderNode: this.visitTriggerOrder.bind(this),
197+
DropTriggerNode: this.visitDropTrigger.bind(this),
190198
})
191199

192200
protected readonly visitNode = (node: OperationNode): void => {
@@ -213,9 +221,13 @@ export abstract class OperationNodeVisitor {
213221
protected abstract visitDeleteQuery(node: DeleteQueryNode): void
214222
protected abstract visitReturning(node: ReturningNode): void
215223
protected abstract visitCreateTable(node: CreateTableNode): void
224+
protected abstract visitCreateTrigger(node: CreateTriggerNode): void
225+
protected abstract visitTriggerEvent(node: TriggerEventNode): void
226+
protected abstract visitTriggerOrder(node: TriggerOrderNode): void
216227
protected abstract visitAddColumn(node: AddColumnNode): void
217228
protected abstract visitColumnDefinition(node: ColumnDefinitionNode): void
218229
protected abstract visitDropTable(node: DropTableNode): void
230+
protected abstract visitDropTrigger(node: DropTriggerNode): void
219231
protected abstract visitOrderBy(node: OrderByNode): void
220232
protected abstract visitOrderByItem(node: OrderByItemNode): void
221233
protected abstract visitGroupBy(node: GroupByNode): void

Diff for: src/operation-node/operation-node.ts

+4
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ export type OperationNodeKind =
8686
| 'JSONOperatorChainNode'
8787
| 'TupleNode'
8888
| 'AddIndexNode'
89+
| 'CreateTriggerNode'
90+
| 'TriggerEventNode'
91+
| 'TriggerOrderNode'
92+
| 'DropTriggerNode'
8993

9094
export interface OperationNode {
9195
readonly kind: OperationNodeKind

Diff for: src/operation-node/trigger-event-node.ts

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { freeze } from '../util/object-utils.js'
2+
import { OperationNode } from './operation-node.js'
3+
4+
export type TriggerEvent = 'delete' | 'update' | 'insert' | 'truncate'
5+
6+
export type TriggerEventNodeParams = Omit<TriggerEventNode, 'kind'>
7+
8+
export interface TriggerEventNode extends OperationNode {
9+
readonly kind: 'TriggerEventNode'
10+
readonly event: TriggerEvent
11+
readonly columns?: ReadonlyArray<OperationNode>
12+
}
13+
14+
/**
15+
* @internal
16+
*/
17+
export const TriggerEventNode = freeze({
18+
is(node: OperationNode): node is TriggerEventNode {
19+
return node.kind === 'TriggerEventNode'
20+
},
21+
22+
create(
23+
event: TriggerEvent,
24+
columns?: ReadonlyArray<OperationNode>
25+
): TriggerEventNode {
26+
return freeze({
27+
kind: 'TriggerEventNode',
28+
event,
29+
columns,
30+
})
31+
},
32+
})

Diff for: src/operation-node/trigger-order-node.ts

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { freeze } from '../util/object-utils.js'
2+
import { IdentifierNode } from './identifier-node.js'
3+
import { OperationNode } from './operation-node.js'
4+
5+
export type TriggerOrder = 'follows' | 'precedes'
6+
7+
export type TriggerOrderNodeParams = Omit<TriggerOrderNode, 'kind'>
8+
9+
export interface TriggerOrderNode extends OperationNode {
10+
readonly kind: 'TriggerOrderNode'
11+
readonly order: TriggerOrder
12+
readonly otherTriggerName: IdentifierNode
13+
}
14+
15+
/**
16+
* @internal
17+
*/
18+
export const TriggerOrderNode = freeze({
19+
is(node: OperationNode): node is TriggerOrderNode {
20+
return node.kind === 'TriggerOrderNode'
21+
},
22+
23+
create(
24+
order: TriggerOrder,
25+
otherTriggerName: IdentifierNode
26+
): TriggerOrderNode {
27+
return freeze({
28+
kind: 'TriggerOrderNode',
29+
order,
30+
otherTriggerName,
31+
})
32+
},
33+
})

Diff for: src/plugin/with-schema/with-schema-transformer.ts

+2
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,14 @@ const ROOT_OPERATION_NODES: Record<RootOperationNode['kind'], true> = freeze({
2121
CreateTableNode: true,
2222
CreateTypeNode: true,
2323
CreateViewNode: true,
24+
CreateTriggerNode: true,
2425
DeleteQueryNode: true,
2526
DropIndexNode: true,
2627
DropSchemaNode: true,
2728
DropTableNode: true,
2829
DropTypeNode: true,
2930
DropViewNode: true,
31+
DropTriggerNode: true,
3032
InsertQueryNode: true,
3133
RawNode: true,
3234
SelectQueryNode: true,

0 commit comments

Comments
 (0)