You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
112 lines
3.0 KiB
112 lines
3.0 KiB
// Copyright 2016 PingCAP, Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package ddl
|
|
|
|
import (
|
|
"github.com/pingcap/errors"
|
|
"github.com/pingcap/parser/model"
|
|
"github.com/pingcap/tidb/infoschema"
|
|
"github.com/pingcap/tidb/meta"
|
|
)
|
|
|
|
func onCreateForeignKey(t *meta.Meta, job *model.Job) (ver int64, _ error) {
|
|
schemaID := job.SchemaID
|
|
tblInfo, err := getTableInfoAndCancelFaultJob(t, job, schemaID)
|
|
if err != nil {
|
|
return ver, errors.Trace(err)
|
|
}
|
|
|
|
var fkInfo model.FKInfo
|
|
err = job.DecodeArgs(&fkInfo)
|
|
if err != nil {
|
|
job.State = model.JobStateCancelled
|
|
return ver, errors.Trace(err)
|
|
}
|
|
fkInfo.ID = allocateIndexID(tblInfo)
|
|
tblInfo.ForeignKeys = append(tblInfo.ForeignKeys, &fkInfo)
|
|
|
|
originalState := fkInfo.State
|
|
switch fkInfo.State {
|
|
case model.StateNone:
|
|
// We just support record the foreign key, so we just make it public.
|
|
// none -> public
|
|
fkInfo.State = model.StatePublic
|
|
ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != fkInfo.State)
|
|
if err != nil {
|
|
return ver, errors.Trace(err)
|
|
}
|
|
// Finish this job.
|
|
job.FinishTableJob(model.JobStateDone, model.StatePublic, ver, tblInfo)
|
|
return ver, nil
|
|
default:
|
|
return ver, ErrInvalidDDLState.GenWithStack("foreign key", fkInfo.State)
|
|
}
|
|
}
|
|
|
|
func onDropForeignKey(t *meta.Meta, job *model.Job) (ver int64, _ error) {
|
|
schemaID := job.SchemaID
|
|
tblInfo, err := getTableInfoAndCancelFaultJob(t, job, schemaID)
|
|
if err != nil {
|
|
return ver, errors.Trace(err)
|
|
}
|
|
|
|
var (
|
|
fkName model.CIStr
|
|
found bool
|
|
fkInfo model.FKInfo
|
|
)
|
|
err = job.DecodeArgs(&fkName)
|
|
if err != nil {
|
|
job.State = model.JobStateCancelled
|
|
return ver, errors.Trace(err)
|
|
}
|
|
|
|
for _, fk := range tblInfo.ForeignKeys {
|
|
if fk.Name.L == fkName.L {
|
|
found = true
|
|
fkInfo = *fk
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
job.State = model.JobStateCancelled
|
|
return ver, infoschema.ErrForeignKeyNotExists.GenWithStackByArgs(fkName)
|
|
}
|
|
|
|
nfks := tblInfo.ForeignKeys[:0]
|
|
for _, fk := range tblInfo.ForeignKeys {
|
|
if fk.Name.L != fkName.L {
|
|
nfks = append(nfks, fk)
|
|
}
|
|
}
|
|
tblInfo.ForeignKeys = nfks
|
|
|
|
originalState := fkInfo.State
|
|
switch fkInfo.State {
|
|
case model.StatePublic:
|
|
// We just support record the foreign key, so we just make it none.
|
|
// public -> none
|
|
fkInfo.State = model.StateNone
|
|
ver, err = updateVersionAndTableInfo(t, job, tblInfo, originalState != fkInfo.State)
|
|
if err != nil {
|
|
return ver, errors.Trace(err)
|
|
}
|
|
// Finish this job.
|
|
job.FinishTableJob(model.JobStateDone, model.StateNone, ver, tblInfo)
|
|
return ver, nil
|
|
default:
|
|
return ver, ErrInvalidDDLState.GenWithStackByArgs("foreign key", fkInfo.State)
|
|
}
|
|
|
|
}
|
|
|