Commit f1b729d3 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-9188 Split Column_definition::check() into virtual methods in Type_handler

parent 705fc43e
......@@ -9893,11 +9893,98 @@ bool check_expression(Virtual_column_info *vcol, LEX_CSTRING *name,
}
bool Column_definition::check_length(uint mysql_errno, uint limit) const
{
if (length <= limit)
return false;
my_error(mysql_errno, MYF(0), field_name.str, static_cast<ulong>(limit));
return true;
}
bool Column_definition::fix_attributes_int(uint default_length)
{
if (length)
return check_length(ER_TOO_BIG_DISPLAYWIDTH, MAX_FIELD_CHARLENGTH);
length= default_length;
return false;
}
bool Column_definition::fix_attributes_real(uint default_length)
{
/* change FLOAT(precision) to FLOAT or DOUBLE */
if (!length && !decimals)
{
length= default_length;
decimals= NOT_FIXED_DEC;
}
if (length < decimals && decimals != NOT_FIXED_DEC)
{
my_error(ER_M_BIGGER_THAN_D, MYF(0), field_name.str);
return true;
}
if (decimals != NOT_FIXED_DEC && decimals >= FLOATING_POINT_DECIMALS)
{
my_error(ER_TOO_BIG_SCALE, MYF(0), static_cast<ulonglong>(decimals),
field_name.str, static_cast<uint>(FLOATING_POINT_DECIMALS-1));
return true;
}
return check_length(ER_TOO_BIG_DISPLAYWIDTH, MAX_FIELD_CHARLENGTH);
}
bool Column_definition::fix_attributes_decimal()
{
if (decimals >= NOT_FIXED_DEC)
{
my_error(ER_TOO_BIG_SCALE, MYF(0), static_cast<ulonglong>(decimals),
field_name.str, static_cast<uint>(NOT_FIXED_DEC - 1));
return true;
}
my_decimal_trim(&length, &decimals);
if (length > DECIMAL_MAX_PRECISION)
{
my_error(ER_TOO_BIG_PRECISION, MYF(0), length, field_name.str,
DECIMAL_MAX_PRECISION);
return true;
}
if (length < decimals)
{
my_error(ER_M_BIGGER_THAN_D, MYF(0), field_name.str);
return true;
}
length= my_decimal_precision_to_length(length, decimals,
flags & UNSIGNED_FLAG);
pack_length= my_decimal_get_binary_size(length, decimals);
return false;
}
bool Column_definition::fix_attributes_bit()
{
if (!length)
length= 1;
pack_length= (length + 7) / 8;
return check_length(ER_TOO_BIG_DISPLAYWIDTH, MAX_BIT_FIELD_LENGTH);
}
bool Column_definition::fix_attributes_temporal_with_time(uint int_part_length)
{
if (length > MAX_DATETIME_PRECISION)
{
my_error(ER_TOO_BIG_PRECISION, MYF(0), length, field_name.str,
MAX_DATETIME_PRECISION);
return true;
}
length+= int_part_length + (length ? 1 : 0);
return false;
}
bool Column_definition::check(THD *thd)
{
const uint conditional_type_modifiers= AUTO_INCREMENT_FLAG;
uint sign_len, allowed_type_modifier= 0;
ulong max_field_charlength= MAX_FIELD_CHARLENGTH;
DBUG_ENTER("Column_definition::check");
/* Initialize data for a computed field */
......@@ -9972,186 +10059,9 @@ bool Column_definition::check(THD *thd)
else if (flags & AUTO_INCREMENT_FLAG)
unireg_check= Field::NEXT_NUMBER;
sign_len= flags & UNSIGNED_FLAG ? 0 : 1;
if (type_handler()->Column_definition_fix_attributes(this))
DBUG_RETURN(true);
switch (real_field_type()) {
case MYSQL_TYPE_TINY:
if (!length)
length= MAX_TINYINT_WIDTH+sign_len;
allowed_type_modifier= AUTO_INCREMENT_FLAG;
break;
case MYSQL_TYPE_SHORT:
if (!length)
length= MAX_SMALLINT_WIDTH+sign_len;
allowed_type_modifier= AUTO_INCREMENT_FLAG;
break;
case MYSQL_TYPE_INT24:
if (!length)
length= MAX_MEDIUMINT_WIDTH+sign_len;
allowed_type_modifier= AUTO_INCREMENT_FLAG;
break;
case MYSQL_TYPE_LONG:
if (!length)
length= MAX_INT_WIDTH+sign_len;
allowed_type_modifier= AUTO_INCREMENT_FLAG;
break;
case MYSQL_TYPE_LONGLONG:
if (!length)
length= MAX_BIGINT_WIDTH;
allowed_type_modifier= AUTO_INCREMENT_FLAG;
break;
case MYSQL_TYPE_NULL:
break;
case MYSQL_TYPE_NEWDECIMAL:
if (decimals >= NOT_FIXED_DEC)
{
my_error(ER_TOO_BIG_SCALE, MYF(0), static_cast<ulonglong>(decimals),
field_name.str, static_cast<uint>(NOT_FIXED_DEC - 1));
DBUG_RETURN(TRUE);
}
my_decimal_trim(&length, &decimals);
if (length > DECIMAL_MAX_PRECISION)
{
my_error(ER_TOO_BIG_PRECISION, MYF(0), length, field_name.str,
DECIMAL_MAX_PRECISION);
DBUG_RETURN(TRUE);
}
if (length < decimals)
{
my_error(ER_M_BIGGER_THAN_D, MYF(0), field_name.str);
DBUG_RETURN(TRUE);
}
length=
my_decimal_precision_to_length(length, decimals, flags & UNSIGNED_FLAG);
pack_length=
my_decimal_get_binary_size(length, decimals);
break;
case MYSQL_TYPE_VARCHAR:
/*
Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table
if they don't have a default value
*/
max_field_charlength= MAX_FIELD_VARCHARLENGTH;
break;
case MYSQL_TYPE_STRING:
break;
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_GEOMETRY:
flags|= BLOB_FLAG;
break;
case MYSQL_TYPE_YEAR:
if (!length || length != 2)
length= 4; /* Default length */
flags|= ZEROFILL_FLAG | UNSIGNED_FLAG;
break;
case MYSQL_TYPE_FLOAT:
/* change FLOAT(precision) to FLOAT or DOUBLE */
allowed_type_modifier= AUTO_INCREMENT_FLAG;
if (!length && !decimals)
{
length= MAX_FLOAT_STR_LENGTH;
decimals= NOT_FIXED_DEC;
}
if (length < decimals &&
decimals != NOT_FIXED_DEC)
{
my_error(ER_M_BIGGER_THAN_D, MYF(0), field_name.str);
DBUG_RETURN(TRUE);
}
if (decimals != NOT_FIXED_DEC && decimals >= FLOATING_POINT_DECIMALS)
{
my_error(ER_TOO_BIG_SCALE, MYF(0), static_cast<ulonglong>(decimals),
field_name.str, static_cast<uint>(FLOATING_POINT_DECIMALS-1));
DBUG_RETURN(TRUE);
}
break;
case MYSQL_TYPE_DOUBLE:
allowed_type_modifier= AUTO_INCREMENT_FLAG;
if (!length && !decimals)
{
length= DBL_DIG+7;
decimals= NOT_FIXED_DEC;
}
if (length < decimals &&
decimals != NOT_FIXED_DEC)
{
my_error(ER_M_BIGGER_THAN_D, MYF(0), field_name.str);
DBUG_RETURN(TRUE);
}
if (decimals != NOT_FIXED_DEC && decimals >= FLOATING_POINT_DECIMALS)
{
my_error(ER_TOO_BIG_SCALE, MYF(0), static_cast<ulonglong>(decimals),
field_name.str, static_cast<uint>(FLOATING_POINT_DECIMALS-1));
DBUG_RETURN(TRUE);
}
break;
case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_TIMESTAMP2:
if (length > MAX_DATETIME_PRECISION)
{
my_error(ER_TOO_BIG_PRECISION, MYF(0), length, field_name.str,
MAX_DATETIME_PRECISION);
DBUG_RETURN(TRUE);
}
length+= MAX_DATETIME_WIDTH + (length ? 1 : 0);
flags|= UNSIGNED_FLAG;
break;
case MYSQL_TYPE_DATE:
/* We don't support creation of MYSQL_TYPE_DATE anymore */
set_handler(&type_handler_newdate);
/* fall trough */
case MYSQL_TYPE_NEWDATE:
length= MAX_DATE_WIDTH;
break;
case MYSQL_TYPE_TIME:
case MYSQL_TYPE_TIME2:
if (length > MAX_DATETIME_PRECISION)
{
my_error(ER_TOO_BIG_PRECISION, MYF(0), length, field_name.str,
MAX_DATETIME_PRECISION);
DBUG_RETURN(TRUE);
}
length+= MIN_TIME_WIDTH + (length ? 1 : 0);
break;
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_DATETIME2:
if (length > MAX_DATETIME_PRECISION)
{
my_error(ER_TOO_BIG_PRECISION, MYF(0), length, field_name.str,
MAX_DATETIME_PRECISION);
DBUG_RETURN(TRUE);
}
length+= MAX_DATETIME_WIDTH + (length ? 1 : 0);
break;
case MYSQL_TYPE_SET:
pack_length= get_set_pack_length(interval_list.elements);
break;
case MYSQL_TYPE_ENUM:
/* Should be safe. */
pack_length= get_enum_pack_length(interval_list.elements);
break;
case MYSQL_TYPE_VAR_STRING:
DBUG_ASSERT(0); /* Impossible. */
break;
case MYSQL_TYPE_BIT:
{
if (!length)
length= 1;
if (length > MAX_BIT_FIELD_LENGTH)
{
my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), field_name.str,
static_cast<ulong>(MAX_BIT_FIELD_LENGTH));
DBUG_RETURN(TRUE);
}
pack_length= (length + 7) / 8;
break;
}
case MYSQL_TYPE_DECIMAL:
DBUG_ASSERT(0); /* Was obsolete */
}
/* Remember the value of length */
char_length= length;
......@@ -10174,32 +10084,9 @@ bool Column_definition::check(THD *thd)
}
}
enum_field_types sql_type= real_field_type();
if (!(flags & BLOB_FLAG) &&
((length > max_field_charlength &&
sql_type != MYSQL_TYPE_VARCHAR) ||
(length == 0 &&
sql_type != MYSQL_TYPE_NULL /* e.g. a ROW variable */ &&
sql_type != MYSQL_TYPE_ENUM && sql_type != MYSQL_TYPE_SET &&
sql_type != MYSQL_TYPE_STRING && sql_type != MYSQL_TYPE_VARCHAR &&
sql_type != MYSQL_TYPE_GEOMETRY)))
{
my_error((sql_type == MYSQL_TYPE_VAR_STRING ||
sql_type == MYSQL_TYPE_VARCHAR ||
sql_type == MYSQL_TYPE_STRING) ? ER_TOO_BIG_FIELDLENGTH :
ER_TOO_BIG_DISPLAYWIDTH,
MYF(0),
field_name.str, max_field_charlength); /* purecov: inspected */
DBUG_RETURN(TRUE);
}
else if (length > MAX_FIELD_BLOBLENGTH)
{
my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), field_name.str,
MAX_FIELD_BLOBLENGTH);
DBUG_RETURN(1);
}
if ((~allowed_type_modifier) & flags & conditional_type_modifiers)
if ((flags & AUTO_INCREMENT_FLAG) &&
!type_handler()->type_can_have_auto_increment_attribute())
{
my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name.str);
DBUG_RETURN(TRUE);
......
......@@ -3919,6 +3919,14 @@ class Column_definition: public Sql_alloc,
bool prepare_create_field(uint *blob_columns, ulonglong table_flags);
uint sign_length() const { return flags & UNSIGNED_FLAG ? 0 : 1; }
bool check_length(uint mysql_errno, uint max_allowed_length) const;
bool fix_attributes_real(uint default_length);
bool fix_attributes_int(uint default_length);
bool fix_attributes_decimal();
bool fix_attributes_temporal_with_time(uint int_part_length);
bool fix_attributes_bit();
bool check(THD *thd);
bool stored_in_db() const { return !vcol_info || vcol_info->stored_in_db; }
......
......@@ -626,7 +626,8 @@ class sp_head :private Query_arena,
*/
bool fill_field_definition(THD *thd, Column_definition *field_def)
{
return field_def->check(thd) ||
const Type_handler *h= field_def->type_handler();
return h->Column_definition_fix_attributes(field_def) ||
field_def->sp_prepare_create_field(thd, mem_root);
}
bool row_fill_field_definitions(THD *thd, Row_definition_list *row)
......
......@@ -1380,6 +1380,165 @@ Field *Type_handler_set::make_conversion_table_field(TABLE *table,
((const Field_enum*) target)->typelib, target->charset());
}
/*************************************************************************/
bool Type_handler_null::
Column_definition_fix_attributes(Column_definition *def) const
{
return false;
}
bool Type_handler_tiny::
Column_definition_fix_attributes(Column_definition *def) const
{
return def->fix_attributes_int(MAX_TINYINT_WIDTH + def->sign_length());
}
bool Type_handler_short::
Column_definition_fix_attributes(Column_definition *def) const
{
return def->fix_attributes_int(MAX_SMALLINT_WIDTH + def->sign_length());
}
bool Type_handler_int24::
Column_definition_fix_attributes(Column_definition *def) const
{
return def->fix_attributes_int(MAX_MEDIUMINT_WIDTH + def->sign_length());
}
bool Type_handler_long::
Column_definition_fix_attributes(Column_definition *def) const
{
return def->fix_attributes_int(MAX_INT_WIDTH + def->sign_length());
}
bool Type_handler_longlong::
Column_definition_fix_attributes(Column_definition *def) const
{
return def->fix_attributes_int(MAX_BIGINT_WIDTH/*no sign_length() added*/);
}
bool Type_handler_newdecimal::
Column_definition_fix_attributes(Column_definition *def) const
{
return def->fix_attributes_decimal();
}
bool Type_handler_olddecimal::
Column_definition_fix_attributes(Column_definition *def) const
{
DBUG_ASSERT(0); // Obsolete
return true;
}
bool Type_handler_var_string::
Column_definition_fix_attributes(Column_definition *def) const
{
DBUG_ASSERT(0); // Obsolete
return true;
}
bool Type_handler_varchar::
Column_definition_fix_attributes(Column_definition *def) const
{
/*
Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table
if they don't have a default value
*/
return def->check_length(ER_TOO_BIG_DISPLAYWIDTH, MAX_FIELD_BLOBLENGTH);
}
bool Type_handler_string::
Column_definition_fix_attributes(Column_definition *def) const
{
return def->check_length(ER_TOO_BIG_FIELDLENGTH, MAX_FIELD_CHARLENGTH);
}
bool Type_handler_blob_common::
Column_definition_fix_attributes(Column_definition *def) const
{
def->flags|= BLOB_FLAG;
return def->check_length(ER_TOO_BIG_DISPLAYWIDTH, MAX_FIELD_BLOBLENGTH);
}
#ifdef HAVE_SPATIAL
bool Type_handler_geometry::
Column_definition_fix_attributes(Column_definition *def) const
{
def->flags|= BLOB_FLAG;
return false;
}
#endif
bool Type_handler_year::
Column_definition_fix_attributes(Column_definition *def) const
{
if (!def->length || def->length != 2)
def->length= 4; // Default length
def->flags|= ZEROFILL_FLAG | UNSIGNED_FLAG;
return false;
}
bool Type_handler_float::
Column_definition_fix_attributes(Column_definition *def) const
{
return def->fix_attributes_real(MAX_FLOAT_STR_LENGTH);
}
bool Type_handler_double::
Column_definition_fix_attributes(Column_definition *def) const
{
return def->fix_attributes_real(DBL_DIG + 7);
}
bool Type_handler_timestamp_common::
Column_definition_fix_attributes(Column_definition *def) const
{
def->flags|= UNSIGNED_FLAG;
return def->fix_attributes_temporal_with_time(MAX_DATETIME_WIDTH);
}
bool Type_handler_date_common::
Column_definition_fix_attributes(Column_definition *def) const
{
// We don't support creation of MYSQL_TYPE_DATE anymore
def->set_handler(&type_handler_newdate);
def->length= MAX_DATE_WIDTH;
return false;
}
bool Type_handler_time_common::
Column_definition_fix_attributes(Column_definition *def) const
{
return def->fix_attributes_temporal_with_time(MIN_TIME_WIDTH);
}
bool Type_handler_datetime_common::
Column_definition_fix_attributes(Column_definition *def) const
{
return def->fix_attributes_temporal_with_time(MAX_DATETIME_WIDTH);
}
bool Type_handler_set::
Column_definition_fix_attributes(Column_definition *def) const
{
def->pack_length= get_set_pack_length(def->interval_list.elements);
return false;
}
bool Type_handler_enum::
Column_definition_fix_attributes(Column_definition *def) const
{
def->pack_length= get_enum_pack_length(def->interval_list.elements);
return false;
}
bool Type_handler_bit::
Column_definition_fix_attributes(Column_definition *def) const
{
return def->fix_attributes_bit();
}
/*************************************************************************/
Field *Type_handler::make_and_init_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment