1
0
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:
Marko Mäkelä
2024-10-03 09:31:39 +03:00
482 changed files with 4427 additions and 623 deletions

View File

@ -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);
}