Skip to content

Commit 170ca90

Browse files
authored
Support ENFORCED/NOT ENFORCED in ForeignKey (#283)
* Implement ENFORCED/NOT ENFORCED in ForeignKey * Update testdata
1 parent 71d587f commit 170ca90

28 files changed

+544
-71
lines changed

ast/ast.go

+6-3
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ type ColumnDefaultSemantics interface {
443443
func (ColumnDefaultExpr) isColumnDefaultSemantics() {}
444444
func (GeneratedColumnExpr) isColumnDefaultSemantics() {}
445445
func (IdentityColumn) isColumnDefaultSemantics() {}
446-
func (AutoIncrement) isColumnDefaultSemantics() {}
446+
func (AutoIncrement) isColumnDefaultSemantics() {}
447447

448448
type SequenceParam interface {
449449
Node
@@ -2569,19 +2569,22 @@ type TableConstraint struct {
25692569

25702570
// ForeignKey is foreign key specifier in CREATE TABLE and ALTER TABLE.
25712571
//
2572-
// FOREIGN KEY ({{.ColumnNames | sqlJoin ","}}) REFERENCES {{.ReferenceTable}} ({{.ReferenceColumns | sqlJoin ","}}) {{.OnDelete}}
2572+
// FOREIGN KEY ({{.ColumnNames | sqlJoin ","}}) REFERENCES {{.ReferenceTable}} ({{.ReferenceColumns | sqlJoin ","}})
2573+
// {{.OnDelete}} {{.Enforcement}}
25732574
type ForeignKey struct {
25742575
// pos = Foreign
2575-
// end = OnDeleteEnd || Rparen + 1
2576+
// end = Enforced + 8 || OnDeleteEnd || Rparen + 1
25762577

25772578
Foreign token.Pos // position of "FOREIGN" keyword
25782579
Rparen token.Pos // position of ")" after reference columns
25792580
OnDeleteEnd token.Pos // end position of ON DELETE clause
2581+
Enforced token.Pos // position of "ENFORCED", optional
25802582

25812583
Columns []*Ident
25822584
ReferenceTable *Path
25832585
ReferenceColumns []*Ident // len(ReferenceColumns) > 0
25842586
OnDelete OnDeleteAction // optional
2587+
Enforcement Enforcement // optional
25852588
}
25862589

25872590
// Check is check constraint in CREATE TABLE and ALTER TABLE.

ast/ast_const.go

+7
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,13 @@ const (
130130
OnDeleteNoAction OnDeleteAction = "ON DELETE NO ACTION"
131131
)
132132

133+
type Enforcement string
134+
135+
const (
136+
Enforced Enforcement = "ENFORCED"
137+
NotEnforced Enforcement = "NOT ENFORCED"
138+
)
139+
133140
type SecurityType string
134141

135142
const (

ast/pos.go

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ast/sql.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -852,7 +852,8 @@ func (f *ForeignKey) SQL() string {
852852
return "FOREIGN KEY (" + sqlJoin(f.Columns, ", ") + ") " +
853853
"REFERENCES " + f.ReferenceTable.SQL() + " (" +
854854
sqlJoin(f.ReferenceColumns, ", ") + ")" +
855-
strOpt(f.OnDelete != "", " "+string(f.OnDelete))
855+
strOpt(f.OnDelete != "", " "+string(f.OnDelete)) +
856+
strOpt(f.Enforcement != "", " "+string(f.Enforcement))
856857
}
857858

858859
func (c *Check) SQL() string {

parser.go

+16
Original file line numberDiff line numberDiff line change
@@ -3344,14 +3344,30 @@ func (p *Parser) parseForeignKey() *ast.ForeignKey {
33443344

33453345
onDelete, onDeleteEnd := p.tryParseOnDeleteAction()
33463346

3347+
enforced := token.InvalidPos
3348+
var enforcement ast.Enforcement
3349+
switch {
3350+
case p.Token.Kind == "NOT":
3351+
p.nextToken()
3352+
enforced = p.expectKeywordLike("ENFORCED").Pos
3353+
3354+
enforcement = ast.NotEnforced
3355+
case p.Token.IsKeywordLike("ENFORCED"):
3356+
enforced = p.expectKeywordLike("ENFORCED").Pos
3357+
3358+
enforcement = ast.Enforced
3359+
}
3360+
33473361
return &ast.ForeignKey{
33483362
Foreign: pos,
33493363
Rparen: rparen,
33503364
OnDeleteEnd: onDeleteEnd,
3365+
Enforced: enforced,
33513366
Columns: columns,
33523367
ReferenceTable: refTable,
33533368
ReferenceColumns: refColumns,
33543369
OnDelete: onDelete,
3370+
Enforcement: enforcement,
33553371
}
33563372
}
33573373

Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
alter table foo add foreign key (bar) references t2 (t2key1) enforced
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
alter table foo add foreign key (bar) references t2 (t2key1) not enforced

testdata/input/ddl/create_table.sql

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ create table foo (
77
foreign key (bar) references t2 (t2key2) on delete cascade,
88
foreign key (baz) references t2 (t2key3) on delete no action,
99
constraint fkname foreign key (foo, bar) references t2 (t2key1, t2key2),
10+
constraint fkname2 foreign key (foo, bar) references t2 (t2key1, t2key2) on delete cascade enforced,
11+
constraint fkname3 foreign key (foo, bar) references t2 (t2key1, t2key2) not enforced,
1012
check (foo > 0),
1113
constraint cname check (bar > 0),
1214
quux json,

testdata/result/ddl/alter_table_add_constraint_foreign_key.sql.txt

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ alter table foo add constraint fkname foreign key (foo, bar) references t2 (t2ke
2525
Foreign: 38,
2626
Rparen: 90,
2727
OnDeleteEnd: -1,
28+
Enforced: -1,
2829
Columns: []*ast.Ident{
2930
&ast.Ident{
3031
NamePos: 51,

testdata/result/ddl/alter_table_add_constraint_foreign_key_on_delete_cascade.sql.txt

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ alter table foo add constraint fkname foreign key (foo, bar) references t2 (t2ke
2525
Foreign: 38,
2626
Rparen: 90,
2727
OnDeleteEnd: 109,
28+
Enforced: -1,
2829
Columns: []*ast.Ident{
2930
&ast.Ident{
3031
NamePos: 51,

testdata/result/ddl/alter_table_add_constraint_foreign_key_on_delete_no_action.sql.txt

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ alter table foo add constraint fkname foreign key (foo, bar) references t2 (t2ke
2525
Foreign: 38,
2626
Rparen: 90,
2727
OnDeleteEnd: 111,
28+
Enforced: -1,
2829
Columns: []*ast.Ident{
2930
&ast.Ident{
3031
NamePos: 51,

testdata/result/ddl/alter_table_add_foreign_key.sql.txt

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ alter table foo add foreign key (bar) references t2 (t2key1)
2020
Foreign: 20,
2121
Rparen: 59,
2222
OnDeleteEnd: -1,
23+
Enforced: -1,
2324
Columns: []*ast.Ident{
2425
&ast.Ident{
2526
NamePos: 33,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
--- alter_table_add_foreign_key_enforced.sql
2+
alter table foo add foreign key (bar) references t2 (t2key1) enforced
3+
4+
--- AST
5+
&ast.AlterTable{
6+
Name: &ast.Path{
7+
Idents: []*ast.Ident{
8+
&ast.Ident{
9+
NamePos: 12,
10+
NameEnd: 15,
11+
Name: "foo",
12+
},
13+
},
14+
},
15+
TableAlteration: &ast.AddTableConstraint{
16+
Add: 16,
17+
TableConstraint: &ast.TableConstraint{
18+
ConstraintPos: -1,
19+
Constraint: &ast.ForeignKey{
20+
Foreign: 20,
21+
Rparen: 59,
22+
OnDeleteEnd: -1,
23+
Enforced: 61,
24+
Columns: []*ast.Ident{
25+
&ast.Ident{
26+
NamePos: 33,
27+
NameEnd: 36,
28+
Name: "bar",
29+
},
30+
},
31+
ReferenceTable: &ast.Path{
32+
Idents: []*ast.Ident{
33+
&ast.Ident{
34+
NamePos: 49,
35+
NameEnd: 51,
36+
Name: "t2",
37+
},
38+
},
39+
},
40+
ReferenceColumns: []*ast.Ident{
41+
&ast.Ident{
42+
NamePos: 53,
43+
NameEnd: 59,
44+
Name: "t2key1",
45+
},
46+
},
47+
Enforcement: "ENFORCED",
48+
},
49+
},
50+
},
51+
}
52+
53+
--- SQL
54+
ALTER TABLE foo ADD FOREIGN KEY (bar) REFERENCES t2 (t2key1) ENFORCED
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
--- alter_table_add_foreign_key_not_enforced.sql
2+
alter table foo add foreign key (bar) references t2 (t2key1) not enforced
3+
4+
--- AST
5+
&ast.AlterTable{
6+
Name: &ast.Path{
7+
Idents: []*ast.Ident{
8+
&ast.Ident{
9+
NamePos: 12,
10+
NameEnd: 15,
11+
Name: "foo",
12+
},
13+
},
14+
},
15+
TableAlteration: &ast.AddTableConstraint{
16+
Add: 16,
17+
TableConstraint: &ast.TableConstraint{
18+
ConstraintPos: -1,
19+
Constraint: &ast.ForeignKey{
20+
Foreign: 20,
21+
Rparen: 59,
22+
OnDeleteEnd: -1,
23+
Enforced: 65,
24+
Columns: []*ast.Ident{
25+
&ast.Ident{
26+
NamePos: 33,
27+
NameEnd: 36,
28+
Name: "bar",
29+
},
30+
},
31+
ReferenceTable: &ast.Path{
32+
Idents: []*ast.Ident{
33+
&ast.Ident{
34+
NamePos: 49,
35+
NameEnd: 51,
36+
Name: "t2",
37+
},
38+
},
39+
},
40+
ReferenceColumns: []*ast.Ident{
41+
&ast.Ident{
42+
NamePos: 53,
43+
NameEnd: 59,
44+
Name: "t2key1",
45+
},
46+
},
47+
Enforcement: "NOT ENFORCED",
48+
},
49+
},
50+
},
51+
}
52+
53+
--- SQL
54+
ALTER TABLE foo ADD FOREIGN KEY (bar) REFERENCES t2 (t2key1) NOT ENFORCED

0 commit comments

Comments
 (0)