diff --git a/infoschema/infoschema.go b/infoschema/infoschema.go index 15e9005ae6263..0003b0584ef89 100644 --- a/infoschema/infoschema.go +++ b/infoschema/infoschema.go @@ -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. @@ -298,6 +300,7 @@ const ( codeBadTable = 1051 codeColumnExists = 1060 codeIndexExists = 1831 + codeMultiplePriKey = 1068 ) func init() { @@ -314,6 +317,7 @@ func init() { codeBadTable: mysql.ErrBadTable, codeColumnExists: mysql.ErrDupFieldName, codeIndexExists: mysql.ErrDupIndex, + codeMultiplePriKey: mysql.ErrMultiplePriKey, } terror.ErrClassToMySQLCodes[terror.ClassSchema] = schemaMySQLErrCodes initInfoSchemaDB() diff --git a/plan/validator.go b/plan/validator.go index 18042258512da..0393aa1e36caf 100644 --- a/plan/validator.go +++ b/plan/validator.go @@ -187,7 +187,7 @@ 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 && @@ -195,15 +195,26 @@ func (v *validator) checkCreateTableGrammar(stmt *ast.CreateTableStmt) { 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 @@ -211,7 +222,6 @@ func (v *validator) checkCreateTableGrammar(stmt *ast.CreateTableStmt) { } } } - } func isPrimary(ops []*ast.ColumnOption) int { diff --git a/plan/validator_test.go b/plan/validator_test.go index 675c61841dc6d..db39eff091b5a 100644 --- a/plan/validator_test.go +++ b/plan/validator_test.go @@ -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)