mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Merge 10.5 into 10.6
This commit is contained in:
125
sql/sql_table.cc
125
sql/sql_table.cc
@ -3762,6 +3762,33 @@ bool Column_definition::prepare_blob_field(THD *thd)
|
||||
{
|
||||
DBUG_ENTER("Column_definition::prepare_blob_field");
|
||||
|
||||
if (real_field_type() == FIELD_TYPE_STRING && length > 1024)
|
||||
{
|
||||
DBUG_ASSERT(charset->mbmaxlen > 4);
|
||||
/*
|
||||
Convert long CHAR columns to VARCHAR.
|
||||
CHAR has an octet length limit of 1024 bytes.
|
||||
The code in Binlog_type_info_fixed_string::Binlog_type_info_fixed_string
|
||||
relies on this limit. If octet length of a CHAR column is greater
|
||||
than 1024, then it cannot write its metadata to binlog properly.
|
||||
In case of the filename character set with mbmaxlen=5,
|
||||
the maximum possible character length is 1024/5=204 characters.
|
||||
Upgrade to VARCHAR if octet length is greater than 1024.
|
||||
*/
|
||||
char warn_buff[MYSQL_ERRMSG_SIZE];
|
||||
if (thd->is_strict_mode())
|
||||
{
|
||||
my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), field_name.str,
|
||||
static_cast<ulong>(1024 / charset->mbmaxlen));
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
set_handler(&type_handler_varchar);
|
||||
my_snprintf(warn_buff, sizeof(warn_buff), ER_THD(thd, ER_AUTO_CONVERT),
|
||||
field_name.str, "CHAR", "VARCHAR");
|
||||
push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, ER_AUTO_CONVERT,
|
||||
warn_buff);
|
||||
}
|
||||
|
||||
if (length > MAX_FIELD_VARCHARLENGTH && !(flags & BLOB_FLAG))
|
||||
{
|
||||
/* Convert long VARCHAR columns to TEXT or BLOB */
|
||||
@ -8943,18 +8970,20 @@ static Create_field *get_field_by_old_name(Alter_info *alter_info,
|
||||
enum fk_column_change_type
|
||||
{
|
||||
FK_COLUMN_NO_CHANGE, FK_COLUMN_DATA_CHANGE,
|
||||
FK_COLUMN_RENAMED, FK_COLUMN_DROPPED
|
||||
FK_COLUMN_RENAMED, FK_COLUMN_DROPPED, FK_COLUMN_NOT_NULL
|
||||
};
|
||||
|
||||
/**
|
||||
Check that ALTER TABLE's changes on columns of a foreign key are allowed.
|
||||
|
||||
@param[in] thd Thread context.
|
||||
@param[in] table table to be altered
|
||||
@param[in] alter_info Alter_info describing changes to be done
|
||||
by ALTER TABLE.
|
||||
@param[in] fk_columns List of columns of the foreign key to check.
|
||||
@param[in] fk Foreign key information.
|
||||
@param[out] bad_column_name Name of field on which ALTER TABLE tries to
|
||||
do prohibited operation.
|
||||
@param[in] referenced Check the referenced fields
|
||||
|
||||
@note This function takes into account value of @@foreign_key_checks
|
||||
setting.
|
||||
@ -8965,17 +8994,27 @@ enum fk_column_change_type
|
||||
change in foreign key column.
|
||||
@retval FK_COLUMN_RENAMED Foreign key column is renamed.
|
||||
@retval FK_COLUMN_DROPPED Foreign key column is dropped.
|
||||
@retval FK_COLUMN_NOT_NULL Foreign key column cannot be null
|
||||
if ON...SET NULL or ON UPDATE
|
||||
CASCADE conflicts with NOT NULL
|
||||
*/
|
||||
|
||||
static enum fk_column_change_type
|
||||
fk_check_column_changes(THD *thd, Alter_info *alter_info,
|
||||
List<LEX_CSTRING> &fk_columns,
|
||||
const char **bad_column_name)
|
||||
fk_check_column_changes(THD *thd, const TABLE *table,
|
||||
Alter_info *alter_info,
|
||||
FOREIGN_KEY_INFO *fk,
|
||||
const char **bad_column_name,
|
||||
bool referenced=false)
|
||||
{
|
||||
List<LEX_CSTRING> &fk_columns= referenced
|
||||
? fk->referenced_fields
|
||||
: fk->foreign_fields;
|
||||
List_iterator_fast<LEX_CSTRING> column_it(fk_columns);
|
||||
LEX_CSTRING *column;
|
||||
int n_col= 0;
|
||||
|
||||
*bad_column_name= NULL;
|
||||
enum fk_column_change_type result= FK_COLUMN_NO_CHANGE;
|
||||
|
||||
while ((column= column_it++))
|
||||
{
|
||||
@ -8994,8 +9033,8 @@ fk_check_column_changes(THD *thd, Alter_info *alter_info,
|
||||
SE that foreign keys should be updated to use new name of column
|
||||
like it happens in case of in-place algorithm.
|
||||
*/
|
||||
*bad_column_name= column->str;
|
||||
return FK_COLUMN_RENAMED;
|
||||
result= FK_COLUMN_RENAMED;
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -9008,17 +9047,55 @@ fk_check_column_changes(THD *thd, Alter_info *alter_info,
|
||||
new_field->flags&= ~AUTO_INCREMENT_FLAG;
|
||||
const bool equal_result= old_field->is_equal(*new_field);
|
||||
new_field->flags= flags;
|
||||
const bool old_field_not_null= old_field->flags & NOT_NULL_FLAG;
|
||||
const bool new_field_not_null= new_field->flags & NOT_NULL_FLAG;
|
||||
|
||||
if ((equal_result == IS_EQUAL_NO) ||
|
||||
((new_field->flags & NOT_NULL_FLAG) &&
|
||||
!(old_field->flags & NOT_NULL_FLAG)))
|
||||
if ((equal_result == IS_EQUAL_NO))
|
||||
{
|
||||
/*
|
||||
Column in a FK has changed significantly and it
|
||||
may break referential intergrity.
|
||||
*/
|
||||
*bad_column_name= column->str;
|
||||
return FK_COLUMN_DATA_CHANGE;
|
||||
result= FK_COLUMN_DATA_CHANGE;
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
if (old_field_not_null != new_field_not_null)
|
||||
{
|
||||
if (referenced && !new_field_not_null)
|
||||
{
|
||||
/*
|
||||
Don't allow referenced column to change from
|
||||
NOT NULL to NULL when foreign key relation is
|
||||
ON UPDATE CASCADE and the referencing column
|
||||
is declared as NOT NULL
|
||||
*/
|
||||
if (fk->update_method == FK_OPTION_CASCADE &&
|
||||
!fk->is_nullable(false, n_col))
|
||||
{
|
||||
result= FK_COLUMN_DATA_CHANGE;
|
||||
goto func_exit;
|
||||
}
|
||||
}
|
||||
else if (!referenced && new_field_not_null)
|
||||
{
|
||||
/*
|
||||
Don't allow the foreign column to change
|
||||
from NULL to NOT NULL when foreign key type is
|
||||
1) UPDATE SET NULL
|
||||
2) DELETE SET NULL
|
||||
3) UPDATE CASCADE and referenced column is declared as NULL
|
||||
*/
|
||||
if (fk->update_method == FK_OPTION_SET_NULL ||
|
||||
fk->delete_method == FK_OPTION_SET_NULL ||
|
||||
(fk->update_method == FK_OPTION_CASCADE &&
|
||||
fk->referenced_key_name &&
|
||||
fk->is_nullable(true, n_col)))
|
||||
{
|
||||
result= FK_COLUMN_NOT_NULL;
|
||||
goto func_exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -9032,12 +9109,15 @@ fk_check_column_changes(THD *thd, Alter_info *alter_info,
|
||||
field being dropped since it is easy to break referential
|
||||
integrity in this case.
|
||||
*/
|
||||
*bad_column_name= column->str;
|
||||
return FK_COLUMN_DROPPED;
|
||||
result= FK_COLUMN_DROPPED;
|
||||
goto func_exit;
|
||||
}
|
||||
n_col++;
|
||||
}
|
||||
|
||||
return FK_COLUMN_NO_CHANGE;
|
||||
func_exit:
|
||||
*bad_column_name= column->str;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -9129,9 +9209,8 @@ static bool fk_prepare_copy_alter_table(THD *thd, TABLE *table,
|
||||
enum fk_column_change_type changes;
|
||||
const char *bad_column_name;
|
||||
|
||||
changes= fk_check_column_changes(thd, alter_info,
|
||||
f_key->referenced_fields,
|
||||
&bad_column_name);
|
||||
changes= fk_check_column_changes(thd, table, alter_info, f_key,
|
||||
&bad_column_name, true);
|
||||
|
||||
switch(changes)
|
||||
{
|
||||
@ -9165,6 +9244,9 @@ static bool fk_prepare_copy_alter_table(THD *thd, TABLE *table,
|
||||
f_key->foreign_id->str, buff.c_ptr());
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
/* FK_COLUMN_NOT_NULL error happens only when changing
|
||||
the foreign key column from NULL to NOT NULL */
|
||||
case FK_COLUMN_NOT_NULL:
|
||||
default:
|
||||
DBUG_ASSERT(0);
|
||||
}
|
||||
@ -9203,8 +9285,7 @@ static bool fk_prepare_copy_alter_table(THD *thd, TABLE *table,
|
||||
enum fk_column_change_type changes;
|
||||
const char *bad_column_name;
|
||||
|
||||
changes= fk_check_column_changes(thd, alter_info,
|
||||
f_key->foreign_fields,
|
||||
changes= fk_check_column_changes(thd, table, alter_info, f_key,
|
||||
&bad_column_name);
|
||||
|
||||
switch(changes)
|
||||
@ -9226,6 +9307,10 @@ static bool fk_prepare_copy_alter_table(THD *thd, TABLE *table,
|
||||
my_error(ER_FK_COLUMN_CANNOT_DROP, MYF(0), bad_column_name,
|
||||
f_key->foreign_id->str);
|
||||
DBUG_RETURN(true);
|
||||
case FK_COLUMN_NOT_NULL:
|
||||
my_error(ER_FK_COLUMN_NOT_NULL, MYF(0), bad_column_name,
|
||||
f_key->foreign_id->str);
|
||||
DBUG_RETURN(true);
|
||||
default:
|
||||
DBUG_ASSERT(0);
|
||||
}
|
||||
|
Reference in New Issue
Block a user