Skip to content

Commit 566f4c1

Browse files
lucianolixigalklebanov
authored andcommitted
feat: Alter type builder
1 parent ca7b313 commit 566f4c1

15 files changed

Lines changed: 623 additions & 3 deletions

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,8 @@ export * from './operation-node/values-node.js'
219219
export * from './operation-node/when-node.js'
220220
export * from './operation-node/where-node.js'
221221
export * from './operation-node/with-node.js'
222+
export * from './operation-node/alter-type-node.js'
223+
export * from './operation-node/add-value-node.js'
222224

223225
export * from './util/column-type.js'
224226
export * from './util/compilable.js'
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { OperationNode } from './operation-node.js'
2+
import { freeze } from '../util/object-utils.js'
3+
import { ValueNode } from './value-node.js'
4+
5+
export type AddValueNodeProps = Omit<AddValueNode, 'kind' | 'value'>
6+
7+
export interface AddValueNode extends OperationNode {
8+
readonly kind: 'AddValueNode'
9+
readonly value: ValueNode
10+
ifNotExists?: boolean
11+
before?: ValueNode
12+
after?: ValueNode
13+
}
14+
15+
/**
16+
* @internal
17+
*/
18+
export const AddValueNode = freeze({
19+
is(node: OperationNode): node is AddValueNode {
20+
return node.kind === 'AddValueNode'
21+
},
22+
create(value: ValueNode): AddValueNode {
23+
return freeze({
24+
kind: 'AddValueNode',
25+
value,
26+
})
27+
},
28+
29+
cloneWithAddValueProps(
30+
node: AddValueNode,
31+
props: AddValueNodeProps,
32+
): AddValueNode {
33+
return freeze({
34+
...node,
35+
...props,
36+
})
37+
},
38+
})
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { OperationNode } from './operation-node.js'
2+
import { freeze } from '../util/object-utils.js'
3+
import { SchemableIdentifierNode } from './schemable-identifier-node.js'
4+
import { IdentifierNode } from './identifier-node.js'
5+
import { AddValueNode } from './add-value-node.js'
6+
import { ValueNode } from './value-node.js'
7+
8+
export type AlterTypeNodeProps = Omit<AlterTypeNode, 'kind' | 'name'>
9+
10+
export interface AlterTypeNode extends OperationNode {
11+
readonly kind: 'AlterTypeNode'
12+
readonly name: SchemableIdentifierNode
13+
renameTo?: IdentifierNode
14+
ownerTo?: IdentifierNode
15+
setSchema?: IdentifierNode
16+
addValue?: AddValueNode
17+
renameValueOldName?: ValueNode
18+
renameValueNewName?: ValueNode
19+
}
20+
21+
/**
22+
* @internal
23+
*/
24+
export const AlterTypeNode = freeze({
25+
is(node: OperationNode): node is AlterTypeNode {
26+
return node.kind === 'AlterTypeNode'
27+
},
28+
create(name: SchemableIdentifierNode): AlterTypeNode {
29+
return freeze({
30+
kind: 'AlterTypeNode',
31+
name,
32+
})
33+
},
34+
cloneWithAlterTypeProps(
35+
node: AlterTypeNode,
36+
props: AlterTypeNodeProps,
37+
): AlterTypeNode {
38+
return freeze({
39+
...node,
40+
...props,
41+
})
42+
},
43+
})

src/operation-node/operation-node-transformer.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@ import { OrActionNode } from './or-action-node.js'
9999
import { CollateNode } from './collate-node.js'
100100
import { QueryId } from '../util/query-id.js'
101101
import { RenameConstraintNode } from './rename-constraint-node.js'
102-
102+
import { AlterTypeNode } from './alter-type-node.js'
103+
import { AddValueNode } from './add-value-node.js'
103104
/**
104105
* Transforms an operation node tree into another one.
105106
*
@@ -242,6 +243,8 @@ export class OperationNodeTransformer {
242243
OutputNode: this.transformOutput.bind(this),
243244
OrActionNode: this.transformOrAction.bind(this),
244245
CollateNode: this.transformCollate.bind(this),
246+
AlterTypeNode: this.transformAlterType.bind(this),
247+
AddValueNode: this.transformAddValue.bind(this),
245248
})
246249

247250
transformNode<T extends OperationNode | undefined>(
@@ -1353,4 +1356,32 @@ export class OperationNodeTransformer {
13531356
// An Object.freezed leaf node. No need to clone.
13541357
return node
13551358
}
1359+
1360+
protected transformAlterType(
1361+
node: AlterTypeNode,
1362+
queryId?: QueryId,
1363+
): AlterTypeNode {
1364+
return requireAllProps<AlterTypeNode>({
1365+
kind: 'AlterTypeNode',
1366+
name: this.transformNode(node.name, queryId),
1367+
ownerTo: this.transformNode(node.ownerTo, queryId),
1368+
renameTo: this.transformNode(node.renameTo, queryId),
1369+
renameValueNewName: this.transformNode(node.renameValueNewName, queryId),
1370+
renameValueOldName: this.transformNode(node.renameValueOldName, queryId),
1371+
setSchema: this.transformNode(node.setSchema, queryId),
1372+
addValue: this.transformNode(node.addValue),
1373+
})
1374+
}
1375+
protected transformAddValue(
1376+
node: AddValueNode,
1377+
queryId?: QueryId,
1378+
): AddValueNode {
1379+
return requireAllProps<AddValueNode>({
1380+
kind: 'AddValueNode',
1381+
value: this.transformNode(node.value, queryId),
1382+
ifNotExists: node.ifNotExists,
1383+
before: this.transformNode(node.before, queryId),
1384+
after: this.transformNode(node.after, queryId),
1385+
})
1386+
}
13561387
}

src/operation-node/operation-node-visitor.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,8 @@ import { RefreshMaterializedViewNode } from './refresh-materialized-view-node.js
100100
import { OrActionNode } from './or-action-node.js'
101101
import { CollateNode } from './collate-node.js'
102102
import { RenameConstraintNode } from './rename-constraint-node.js'
103-
103+
import { AlterTypeNode } from './alter-type-node.js'
104+
import { AddValueNode } from './add-value-node.js'
104105
export abstract class OperationNodeVisitor {
105106
protected readonly nodeStack: OperationNode[] = []
106107

@@ -207,6 +208,8 @@ export abstract class OperationNodeVisitor {
207208
OutputNode: this.visitOutput.bind(this),
208209
OrActionNode: this.visitOrAction.bind(this),
209210
CollateNode: this.visitCollate.bind(this),
211+
AlterTypeNode: this.visitAlterType.bind(this),
212+
AddValueNode: this.visitAddValue.bind(this),
210213
})
211214

212215
protected readonly visitNode = (node: OperationNode): void => {
@@ -324,4 +327,6 @@ export abstract class OperationNodeVisitor {
324327
protected abstract visitOutput(node: OutputNode): void
325328
protected abstract visitOrAction(node: OrActionNode): void
326329
protected abstract visitCollate(node: CollateNode): void
330+
protected abstract visitAlterType(node: AlterTypeNode): void
331+
protected abstract visitAddValue(node: AddValueNode): void
327332
}

src/operation-node/operation-node.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ export type OperationNodeKind =
9696
| 'OrActionNode'
9797
| 'CollateNode'
9898
| 'RenameConstraintNode'
99+
| 'AlterTypeNode'
100+
| 'AddValueNode'
99101

100102
export interface OperationNode {
101103
readonly kind: OperationNodeKind

src/plugin/with-schema/with-schema-transformer.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const ROOT_OPERATION_NODES: Record<RootOperationNode['kind'], true> = freeze({
3737
SelectQueryNode: true,
3838
UpdateQueryNode: true,
3939
MergeQueryNode: true,
40+
AlterTypeNode: true,
4041
})
4142

4243
const SCHEMALESS_FUNCTIONS: Record<string, true> = {

src/query-compiler/default-query-compiler.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ import { logOnce } from '../util/log-once.js'
117117
import { CollateNode } from '../operation-node/collate-node.js'
118118
import { QueryId } from '../util/query-id.js'
119119
import { RenameConstraintNode } from '../operation-node/rename-constraint-node.js'
120+
import { AlterTypeNode } from '../operation-node/alter-type-node.js'
121+
import { AddValueNode } from '../operation-node/add-value-node.js'
120122

121123
const LIT_WRAP_REGEX = /'/g
122124

@@ -1431,6 +1433,55 @@ export class DefaultQueryCompiler
14311433
this.visitNode(node.name)
14321434
}
14331435

1436+
protected override visitAlterType(node: AlterTypeNode): void {
1437+
this.append('alter type ')
1438+
this.visitNode(node.name)
1439+
this.append(' ')
1440+
1441+
if (node.ownerTo) {
1442+
this.append('owner to ')
1443+
this.visitNode(node.ownerTo)
1444+
}
1445+
1446+
if (node.renameTo) {
1447+
this.append('rename to ')
1448+
this.visitNode(node.renameTo)
1449+
}
1450+
1451+
if (node.setSchema) {
1452+
this.append('set schema ')
1453+
this.visitNode(node.setSchema)
1454+
}
1455+
1456+
if (node.renameValueOldName && node.renameValueNewName) {
1457+
this.append('rename value ')
1458+
this.visitNode(node.renameValueOldName)
1459+
this.append(' ')
1460+
this.append('to ')
1461+
this.visitNode(node.renameValueNewName)
1462+
}
1463+
1464+
if (node.addValue) {
1465+
this.visitNode(node.addValue)
1466+
}
1467+
}
1468+
1469+
protected override visitAddValue(node: AddValueNode): void {
1470+
this.append('add value ')
1471+
if (node.ifNotExists) {
1472+
this.append('if not exists ')
1473+
}
1474+
this.visitNode(node.value)
1475+
if (node.before) {
1476+
this.append(' before ')
1477+
this.visitNode(node.before)
1478+
}
1479+
if (node.after) {
1480+
this.append(' after ')
1481+
this.visitNode(node.after)
1482+
}
1483+
}
1484+
14341485
protected override visitExplain(node: ExplainNode): void {
14351486
this.append('explain')
14361487

src/query-compiler/query-compiler.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { AlterTableNode } from '../operation-node/alter-table-node.js'
2+
import { AlterTypeNode } from '../operation-node/alter-type-node.js'
23
import { CreateIndexNode } from '../operation-node/create-index-node.js'
34
import { CreateSchemaNode } from '../operation-node/create-schema-node.js'
45
import { CreateTableNode } from '../operation-node/create-table-node.js'
@@ -31,6 +32,7 @@ export type RootOperationNode =
3132
| RawNode
3233
| CreateTypeNode
3334
| DropTypeNode
35+
| AlterTypeNode
3436
| MergeQueryNode
3537

3638
/**
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { OperationNodeSource } from '../operation-node/operation-node-source.js'
2+
import { AddValueNode } from '../operation-node/add-value-node.js'
3+
import { ValueNode } from '../operation-node/value-node.js'
4+
5+
export class AlterTypeAddValueBuilder implements OperationNodeSource {
6+
readonly #node: AddValueNode
7+
8+
constructor(node: AddValueNode) {
9+
this.#node = node
10+
}
11+
12+
/**
13+
* Avoids the query throwing an error if the value already exists inside the enum type.
14+
*
15+
* ### Examples
16+
*
17+
* ```ts
18+
* db.schema.alterType('species').renameValue('cat', 'dog').execute()
19+
* ```
20+
*/
21+
ifNotExists() {
22+
return new AlterTypeAddValueBuilder(
23+
AddValueNode.cloneWithAddValueProps(this.#node, {
24+
ifNotExists: true,
25+
}),
26+
)
27+
}
28+
29+
/**
30+
* Adds the new value before the specified existing value.
31+
*
32+
* ### Examples
33+
*
34+
* ```ts
35+
* db.schema.alterType('species').renameValue('cat', 'dog').execute()
36+
* ```
37+
*/
38+
before(value: string) {
39+
return new AlterTypeAddValueBuilder(
40+
AddValueNode.cloneWithAddValueProps(this.#node, {
41+
before: ValueNode.createImmediate(value),
42+
after: undefined, // before and after are mutually exclusive
43+
}),
44+
)
45+
}
46+
/**
47+
* Adds the new value after the specified existing value.
48+
*
49+
* ### Examples
50+
*
51+
* ```ts
52+
* db.schema.alterType('species').renameValue('cat', 'dog').execute()
53+
* ```
54+
*/
55+
after(value: string) {
56+
return new AlterTypeAddValueBuilder(
57+
AddValueNode.cloneWithAddValueProps(this.#node, {
58+
after: ValueNode.createImmediate(value),
59+
before: undefined, // before and after are mutually exclusive
60+
}),
61+
)
62+
}
63+
64+
toOperationNode(): AddValueNode {
65+
return this.#node
66+
}
67+
}
68+
69+
export type AlterTypeAddValueCallback = (
70+
builder: AlterTypeAddValueBuilder,
71+
) => AlterTypeAddValueBuilder

0 commit comments

Comments
 (0)