Skip to content

Commit 6807aff

Browse files
authored
Merge pull request #103 from nktks/fix/panic-fk-column
support FOREIGN KEY without CONSTRAINTS clause
2 parents 211cd94 + ed75ced commit 6807aff

File tree

2 files changed

+38
-19
lines changed

2 files changed

+38
-19
lines changed

server/database.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1274,20 +1274,25 @@ func (db *database) registerInformationSchemaTables(ctx context.Context, stmt *a
12741274
}
12751275
}
12761276

1277-
for _, tcnst := range stmt.TableConstraints {
1277+
for i, tcnst := range stmt.TableConstraints {
12781278
switch cnst := tcnst.Constraint.(type) {
12791279
case *ast.ForeignKey:
12801280
var onDeleteAction string
1281+
var constraintName string
12811282
switch cnst.OnDelete {
12821283
case ast.OnDeleteCascade:
12831284
onDeleteAction = `"CASCADE"`
12841285
default:
12851286
onDeleteAction = `"NO ACTION"`
12861287
}
1287-
1288+
if tcnst.Name != nil {
1289+
constraintName = tcnst.Name.Name
1290+
} else {
1291+
constraintName = fmt.Sprintf("FK_%s_%s_%d", tableName, cnst.ReferenceTable.Name, i)
1292+
}
12881293
query := fmt.Sprintf(
12891294
`INSERT INTO __INFORMATION_SCHEMA__REFERENTIAL_CONSTRAINTS VALUES("", "", %q, "", "", %q, "SIMPLE", "NO ACTION", %s, "COMMITTED")`,
1290-
tcnst.Name.Name, cnst.ReferenceTable.Name, onDeleteAction,
1295+
constraintName, cnst.ReferenceTable.Name, onDeleteAction,
12911296
)
12921297
if _, err := db.db.ExecContext(ctx, query); err != nil {
12931298
return fmt.Errorf("failed to insert into INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS for table %s: %v", tableName, err)

server/database_test.go

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,10 @@ INTERLEAVE IN PARENT ParentTableNoAction ON DELETE NO ACTION;
8787
CREATE TABLE ForeignChildCascade (
8888
Id INT64 NOT NULL,
8989
ForeignId INT64 NOT NULL,
90+
ForeignSecondId INT64 NOT NULL,
9091
Value STRING(MAX) NOT NULL,
9192
CONSTRAINT FK_Cascade FOREIGN KEY (ForeignId) REFERENCES ForeignParentCascade (Id) ON DELETE CASCADE,
93+
FOREIGN KEY (ForeignSecondId) REFERENCES ForeignParentCascade (Id) ON DELETE CASCADE,
9294
) PRIMARY KEY(Id, ForeignId);
9395
`
9496

@@ -100,8 +102,10 @@ CREATE TABLE ForeignChildCascade (
100102
CREATE TABLE ForeignChildNoAction (
101103
Id INT64 NOT NULL,
102104
ForeignId INT64 NOT NULL,
105+
ForeignSecondId INT64 NOT NULL,
103106
Value STRING(MAX) NOT NULL,
104107
CONSTRAINT FK_NoAction FOREIGN KEY (ForeignId) REFERENCES ForeignParentNoAction (Id),
108+
FOREIGN KEY (ForeignSecondId) REFERENCES ForeignParentNoAction (Id),
105109
) PRIMARY KEY(Id, ForeignId);
106110
`
107111

@@ -3982,10 +3986,12 @@ func TestInformationSchema(t *testing.T) {
39823986
{"", "", "DefaultValues", "Date", int64(8), nil, nil, "NO", "TIMESTAMP"},
39833987
{"", "", "ForeignChildCascade", "Id", int64(1), nil, nil, "NO", "INT64"},
39843988
{"", "", "ForeignChildCascade", "ForeignId", int64(2), nil, nil, "NO", "INT64"},
3985-
{"", "", "ForeignChildCascade", "Value", int64(3), nil, nil, "NO", "STRING(MAX)"},
3989+
{"", "", "ForeignChildCascade", "ForeignSecondId", int64(3), nil, nil, "NO", "INT64"},
3990+
{"", "", "ForeignChildCascade", "Value", int64(4), nil, nil, "NO", "STRING(MAX)"},
39863991
{"", "", "ForeignChildNoAction", "Id", int64(1), nil, nil, "NO", "INT64"},
39873992
{"", "", "ForeignChildNoAction", "ForeignId", int64(2), nil, nil, "NO", "INT64"},
3988-
{"", "", "ForeignChildNoAction", "Value", int64(3), nil, nil, "NO", "STRING(MAX)"},
3993+
{"", "", "ForeignChildNoAction", "ForeignSecondId", int64(3), nil, nil, "NO", "INT64"},
3994+
{"", "", "ForeignChildNoAction", "Value", int64(4), nil, nil, "NO", "STRING(MAX)"},
39893995
{"", "", "ForeignParentCascade", "Id", int64(1), nil, nil, "NO", "INT64"},
39903996
{"", "", "ForeignParentCascade", "Value", int64(2), nil, nil, "NO", "STRING(MAX)"},
39913997
{"", "", "ForeignParentNoAction", "Id", int64(1), nil, nil, "NO", "INT64"},
@@ -4240,7 +4246,9 @@ func TestInformationSchema(t *testing.T) {
42404246
sql: `SELECT CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, UNIQUE_CONSTRAINT_CATALOG, UNIQUE_CONSTRAINT_SCHEMA, UNIQUE_CONSTRAINT_NAME, MATCH_OPTION, UPDATE_RULE, DELETE_RULE, SPANNER_STATE FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS`,
42414247
expected: [][]interface{}{
42424248
{"", "", "FK_Cascade", "", "", "ForeignParentCascade", "SIMPLE", "NO ACTION", "CASCADE", "COMMITTED"},
4249+
{"", "", "FK_ForeignChildCascade_ForeignParentCascade_1", "", "", "ForeignParentCascade", "SIMPLE", "NO ACTION", "CASCADE", "COMMITTED"},
42434250
{"", "", "FK_NoAction", "", "", "ForeignParentNoAction", "SIMPLE", "NO ACTION", "NO ACTION", "COMMITTED"},
4251+
{"", "", "FK_ForeignChildNoAction_ForeignParentNoAction_1", "", "", "ForeignParentNoAction", "SIMPLE", "NO ACTION", "NO ACTION", "COMMITTED"},
42444252
},
42454253
},
42464254
}
@@ -4328,13 +4336,14 @@ func TestInsertUnderForeignConstraint(t *testing.T) {
43284336
"InsertWithoutMaster": {
43294337
child: &tableConfig{
43304338
tbl: "ForeignChildNoAction",
4331-
wcols: []string{"Id", "ForeignId", "Value"},
4339+
wcols: []string{"Id", "ForeignId", "ForeignSecondId", "Value"},
43324340
values: []*structpb.Value{
43334341
makeStringValue("100"),
43344342
makeStringValue("200"),
4343+
makeStringValue("200"),
43354344
makeStringValue("yyy"),
43364345
},
4337-
cols: []string{"Id", "ForeignId", "Value"},
4346+
cols: []string{"Id", "ForeignId", "ForeignSecondId", "Value"},
43384347
limit: 100,
43394348
expected: nil,
43404349
},
@@ -4356,16 +4365,17 @@ func TestInsertUnderForeignConstraint(t *testing.T) {
43564365
},
43574366
child: &tableConfig{
43584367
tbl: "ForeignChildNoAction",
4359-
wcols: []string{"Id", "ForeignId", "Value"},
4368+
wcols: []string{"Id", "ForeignId", "ForeignSecondId", "Value"},
43604369
values: []*structpb.Value{
43614370
makeStringValue("100"),
43624371
makeStringValue("200"),
4372+
makeStringValue("200"),
43634373
makeStringValue("yyy"),
43644374
},
4365-
cols: []string{"Id", "ForeignId", "Value"},
4375+
cols: []string{"Id", "ForeignId", "ForeignSecondId", "Value"},
43664376
limit: 100,
43674377
expected: [][]interface{}{
4368-
{int64(100), int64(200), "yyy"},
4378+
{int64(100), int64(200), int64(200), "yyy"},
43694379
},
43704380
},
43714381
expectsError: false,
@@ -4374,13 +4384,14 @@ func TestInsertUnderForeignConstraint(t *testing.T) {
43744384
"InsertWithoutMaster(Cascade)": {
43754385
child: &tableConfig{
43764386
tbl: "ForeignChildCascade",
4377-
wcols: []string{"Id", "ForeignId", "Value"},
4387+
wcols: []string{"Id", "ForeignId", "ForeignSecondId", "Value"},
43784388
values: []*structpb.Value{
43794389
makeStringValue("100"),
43804390
makeStringValue("200"),
4391+
makeStringValue("200"),
43814392
makeStringValue("yyy"),
43824393
},
4383-
cols: []string{"Id", "ForeignId", "Value"},
4394+
cols: []string{"Id", "ForeignId", "ForeignSecondId", "Value"},
43844395
limit: 100,
43854396
expected: nil,
43864397
},
@@ -4402,16 +4413,17 @@ func TestInsertUnderForeignConstraint(t *testing.T) {
44024413
},
44034414
child: &tableConfig{
44044415
tbl: "ForeignChildCascade",
4405-
wcols: []string{"Id", "ForeignId", "Value"},
4416+
wcols: []string{"Id", "ForeignId", "ForeignSecondId", "Value"},
44064417
values: []*structpb.Value{
44074418
makeStringValue("100"),
44084419
makeStringValue("200"),
4420+
makeStringValue("200"),
44094421
makeStringValue("yyy"),
44104422
},
4411-
cols: []string{"Id", "ForeignId", "Value"},
4423+
cols: []string{"Id", "ForeignId", "ForeignSecondId", "Value"},
44124424
limit: 100,
44134425
expected: [][]interface{}{
4414-
{int64(100), int64(200), "yyy"},
4426+
{int64(100), int64(200), int64(200), "yyy"},
44154427
},
44164428
},
44174429
expectsError: false,
@@ -4486,13 +4498,14 @@ func TestDeleteUnderForeignConstraint(t *testing.T) {
44864498
},
44874499
child: &tableConfig{
44884500
tbl: "ForeignChildNoAction",
4489-
wcols: []string{"Id", "ForeignId", "Value"},
4501+
wcols: []string{"Id", "ForeignId", "ForeignSecondId", "Value"},
44904502
values: []*structpb.Value{
44914503
makeStringValue("100"),
44924504
makeStringValue("200"),
4505+
makeStringValue("200"),
44934506
makeStringValue("yyy"),
44944507
},
4495-
cols: []string{"Id", "ForeignId", "Value"},
4508+
cols: []string{"Id", "ForeignId", "ForeignSecondId", "Value"},
44964509
ks: &KeySet{
44974510
Keys: []*structpb.ListValue{
44984511
makeListValue(
@@ -4521,13 +4534,14 @@ func TestDeleteUnderForeignConstraint(t *testing.T) {
45214534
},
45224535
child: &tableConfig{
45234536
tbl: "ForeignChildCascade",
4524-
wcols: []string{"Id", "ForeignId", "Value"},
4537+
wcols: []string{"Id", "ForeignId", "ForeignSecondId", "Value"},
45254538
values: []*structpb.Value{
45264539
makeStringValue("100"),
45274540
makeStringValue("200"),
4541+
makeStringValue("200"),
45284542
makeStringValue("yyy"),
45294543
},
4530-
cols: []string{"Id", "ForeignId", "Value"},
4544+
cols: []string{"Id", "ForeignId", "ForeignSecondId", "Value"},
45314545
ks: &KeySet{
45324546
Keys: []*structpb.ListValue{
45334547
makeListValue(

0 commit comments

Comments
 (0)