diff options
Diffstat (limited to 'sql/sql_class.cc')
-rw-r--r-- | sql/sql_class.cc | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/sql/sql_class.cc b/sql/sql_class.cc index fd4c2ab0853..4446cd0e83e 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -288,22 +288,41 @@ bool foreign_key_prefix(Key *a, Key *b) /* @brief Check if the foreign key options are compatible with the specification - of the columns on which the key is created + of the columns on which the key is created. + + Check self-references for self-column pointing. @retval FALSE The foreign key options are compatible with key columns @retval TRUE Otherwise */ -bool Foreign_key::validate(List<Create_field> &table_fields) +bool Foreign_key::validate(const LEX_CSTRING &db, const LEX_CSTRING &table_name, + List<Create_field> &table_fields, bool &self_ref) { Create_field *sql_field; - Key_part_spec *column; - List_iterator<Key_part_spec> cols(columns); - List_iterator<Create_field> it(table_fields); + Key_part_spec *column, *rcol; + List_iterator_fast<Key_part_spec> cols(columns); + List_iterator_fast<Key_part_spec> rcols(ref_columns); + List_iterator_fast<Create_field> it(table_fields); + // NB: self-references may have no ref_table + self_ref= !ref_table.str || ((!ref_db.str || 0 == cmp_table(db, ref_db)) && + 0 == cmp_table(table_name, ref_table)); DBUG_ENTER("Foreign_key::validate"); + const char *nam= constraint_name.str ? constraint_name.str : name.str; + if (columns.elements != ref_columns.elements) + { + my_error(ER_WRONG_FK_DEF, MYF(0), (nam ? nam : "foreign key without name")); + DBUG_RETURN(TRUE); + } while ((column= cols++)) { + rcol= rcols++; + if (self_ref && 0 == cmp_ident(column->field_name, rcol->field_name)) + { + my_error(ER_WRONG_FK_DEF, MYF(0), (nam ? nam : rcol->field_name.str)); + DBUG_RETURN(TRUE); + } it.rewind(); while ((sql_field= it++) && lex_string_cmp(system_charset_info, @@ -6201,7 +6220,7 @@ int THD::decide_logging_format(TABLE_LIST *tables) replicated_tables_count++; - if (tbl->prelocking_placeholder != TABLE_LIST::PRELOCK_FK) + if (tbl->prelocking_placeholder < TABLE_LIST::PRELOCK_FK) { if (tbl->lock_type <= TL_READ_NO_INSERT) has_read_tables= true; |