Skip to content

Commit

Permalink
plan/validator: add grammar check of constraints when create table (p…
Browse files Browse the repository at this point in the history
  • Loading branch information
XuHuaiyu authored Nov 29, 2016
1 parent 7e2f769 commit b09f97d
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 8 deletions.
4 changes: 4 additions & 0 deletions infoschema/infoschema.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ var (
ErrColumnExists = terror.ClassSchema.New(codeColumnExists, "Duplicate column name '%s'")
// ErrIndexExists returns for index already exists.
ErrIndexExists = terror.ClassSchema.New(codeIndexExists, "Duplicate Index")
// ErrMultiplePriKey returns for multiple primary keys.
ErrMultiplePriKey = terror.ClassSchema.New(codeMultiplePriKey, "Multiple primary key defined")
)

// InfoSchema is the interface used to retrieve the schema information.
Expand Down Expand Up @@ -298,6 +300,7 @@ const (
codeBadTable = 1051
codeColumnExists = 1060
codeIndexExists = 1831
codeMultiplePriKey = 1068
)

func init() {
Expand All @@ -314,6 +317,7 @@ func init() {
codeBadTable: mysql.ErrBadTable,
codeColumnExists: mysql.ErrDupFieldName,
codeIndexExists: mysql.ErrDupIndex,
codeMultiplePriKey: mysql.ErrMultiplePriKey,
}
terror.ErrClassToMySQLCodes[terror.ClassSchema] = schemaMySQLErrCodes
initInfoSchemaDB()
Expand Down
22 changes: 16 additions & 6 deletions plan/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,31 +187,41 @@ func (v *validator) checkAutoIncrement(stmt *ast.CreateTableStmt) {
}

func (v *validator) checkCreateTableGrammar(stmt *ast.CreateTableStmt) {
countPrimayKey := 0
countPrimaryKey := 0
for _, colDef := range stmt.Cols {
tp := colDef.Tp
if tp.Tp == mysql.TypeString &&
tp.Flen != types.UnspecifiedLength && tp.Flen > 255 {
v.err = errors.Errorf("Column length too big for column '%s' (max = 255); use BLOB or TEXT instead", colDef.Name.Name.O)
return
}
countPrimayKey += isPrimary(colDef.Options)
if countPrimayKey > 1 {
v.err = errors.Errorf("Multiple primary key defined")
countPrimaryKey += isPrimary(colDef.Options)
if countPrimaryKey > 1 {
v.err = infoschema.ErrMultiplePriKey
return
}
}
for _, constraint := range stmt.Constraints {
switch tp := constraint.Tp; tp {
case ast.ConstraintKey:
case ast.ConstraintKey, ast.ConstraintIndex, ast.ConstraintUniq, ast.ConstraintUniqKey, ast.ConstraintUniqIndex:
err := checkDuplicateColumnName(constraint.Keys)
if err != nil {
v.err = err
return
}
case ast.ConstraintPrimaryKey:
if countPrimaryKey > 0 {
v.err = infoschema.ErrMultiplePriKey
return
}
countPrimaryKey++
err := checkDuplicateColumnName(constraint.Keys)
if err != nil {
v.err = err
return
}
}
}

}

func isPrimary(ops []*ast.ColumnOption) int {
Expand Down
10 changes: 8 additions & 2 deletions plan/validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,15 @@ func (s *testValidatorSuite) TestValidator(c *C) {
{"create table t(id int auto_increment) ENGINE=MYISAM", true, nil},
{"create table t(a int primary key, b int, c varchar(10), d char(256));", true, errors.New("Column length too big for column 'd' (max = 255); use BLOB or TEXT instead")},
{"create index ib on t(b,a,b);", true, errors.New("[schema:1060]Duplicate column name 'b'")},
{"create table t (a int, b int, key(a, b, A))", true, errors.New("[schema:1060]Duplicate column name 'A'")},
{"create table t(c1 int not null primary key, c2 int not null primary key)", true, errors.New("Multiple primary key defined")},
{"alter table t add index idx(a, b, A)", true, errors.New("[schema:1060]Duplicate column name 'A'")},
{"create table t (a int, b int, index(a, b, A))", true, errors.New("[schema:1060]Duplicate column name 'A'")},
{"create table t (a int, b int, key(a, b, A))", true, errors.New("[schema:1060]Duplicate column name 'A'")},
{"create table t (a int, b int, unique(a, b, A))", true, errors.New("[schema:1060]Duplicate column name 'A'")},
{"create table t (a int, b int, unique key(a, b, A))", true, errors.New("[schema:1060]Duplicate column name 'A'")},
{"create table t (a int, b int, unique index(a, b, A))", true, errors.New("[schema:1060]Duplicate column name 'A'")},
{"create table t(c1 int not null primary key, c2 int not null primary key)", true, errors.New("[schema:1068]Multiple primary key defined")},
{"create table t(c1 int not null primary key, c2 int not null, primary key(c1))", true, errors.New("[schema:1068]Multiple primary key defined")},
{"create table t(c1 int not null, c2 int not null, primary key(c1), primary key(c2))", true, errors.New("[schema:1068]Multiple primary key defined")},
}
store, err := tidb.NewStore(tidb.EngineGoLevelDBMemory)
c.Assert(err, IsNil)
Expand Down

0 comments on commit b09f97d

Please sign in to comment.