1
0
mirror of https://github.com/MariaDB/server.git synced 2025-06-13 13:01:51 +03:00

Merge bk-internal.mysql.com:/home/bk/mysql-5.0

into  mysql.com:/home/alik/Documents/AllProgs/MySQL/devel/5.0-sp-vars-merge-2
This commit is contained in:
anozdrin@mysql.com
2005-12-07 17:17:42 +03:00
41 changed files with 4485 additions and 1252 deletions

View File

@ -5770,9 +5770,10 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
buf, "TIMESTAMP");
}
if (!(new_field= new_create_field(thd, field_name, type, length, decimals,
type_modifier, default_value, on_update_value,
comment, change, interval_list, cs, uint_geom_type)))
if (!(new_field= new create_field()) ||
new_field->init(thd, field_name, type, length, decimals, type_modifier,
default_value, on_update_value, comment, change,
interval_list, cs, uint_geom_type))
DBUG_RETURN(1);
lex->create_list.push_back(new_field);
@ -5780,327 +5781,6 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
DBUG_RETURN(0);
}
/*****************************************************************************
** Create field definition for create
** Return 0 on failure, otherwise return create_field instance
******************************************************************************/
create_field *
new_create_field(THD *thd, char *field_name, enum_field_types type,
char *length, char *decimals,
uint type_modifier,
Item *default_value, Item *on_update_value,
LEX_STRING *comment,
char *change, List<String> *interval_list, CHARSET_INFO *cs,
uint uint_geom_type)
{
register create_field *new_field;
uint sign_len, allowed_type_modifier=0;
ulong max_field_charlength= MAX_FIELD_CHARLENGTH;
DBUG_ENTER("new_create_field");
if (!(new_field=new create_field()))
DBUG_RETURN(NULL);
new_field->field=0;
new_field->field_name=field_name;
new_field->def= default_value;
new_field->flags= type_modifier;
new_field->unireg_check= (type_modifier & AUTO_INCREMENT_FLAG ?
Field::NEXT_NUMBER : Field::NONE);
new_field->decimals= decimals ? (uint)atoi(decimals) : 0;
if (new_field->decimals >= NOT_FIXED_DEC)
{
my_error(ER_TOO_BIG_SCALE, MYF(0), new_field->decimals, field_name,
NOT_FIXED_DEC-1);
DBUG_RETURN(NULL);
}
new_field->sql_type=type;
new_field->length=0;
new_field->change=change;
new_field->interval=0;
new_field->pack_length= new_field->key_length= 0;
new_field->charset=cs;
new_field->geom_type= (Field::geometry_type) uint_geom_type;
new_field->comment=*comment;
/*
Set flag if this field doesn't have a default value
*/
if (!default_value && !(type_modifier & AUTO_INCREMENT_FLAG) &&
(type_modifier & NOT_NULL_FLAG) && type != FIELD_TYPE_TIMESTAMP)
new_field->flags|= NO_DEFAULT_VALUE_FLAG;
if (length && !(new_field->length= (uint) atoi(length)))
length=0; /* purecov: inspected */
sign_len=type_modifier & UNSIGNED_FLAG ? 0 : 1;
switch (type) {
case FIELD_TYPE_TINY:
if (!length) new_field->length=MAX_TINYINT_WIDTH+sign_len;
allowed_type_modifier= AUTO_INCREMENT_FLAG;
break;
case FIELD_TYPE_SHORT:
if (!length) new_field->length=MAX_SMALLINT_WIDTH+sign_len;
allowed_type_modifier= AUTO_INCREMENT_FLAG;
break;
case FIELD_TYPE_INT24:
if (!length) new_field->length=MAX_MEDIUMINT_WIDTH+sign_len;
allowed_type_modifier= AUTO_INCREMENT_FLAG;
break;
case FIELD_TYPE_LONG:
if (!length) new_field->length=MAX_INT_WIDTH+sign_len;
allowed_type_modifier= AUTO_INCREMENT_FLAG;
break;
case FIELD_TYPE_LONGLONG:
if (!length) new_field->length=MAX_BIGINT_WIDTH;
allowed_type_modifier= AUTO_INCREMENT_FLAG;
break;
case FIELD_TYPE_NULL:
break;
case FIELD_TYPE_NEWDECIMAL:
if (!length && !new_field->decimals)
new_field->length= 10;
if (new_field->length > DECIMAL_MAX_PRECISION)
{
my_error(ER_TOO_BIG_PRECISION, MYF(0), new_field->length, field_name,
DECIMAL_MAX_PRECISION);
DBUG_RETURN(NULL);
}
if (new_field->length < new_field->decimals)
{
my_error(ER_M_BIGGER_THAN_D, MYF(0), field_name);
DBUG_RETURN(NULL);
}
new_field->length=
my_decimal_precision_to_length(new_field->length, new_field->decimals,
type_modifier & UNSIGNED_FLAG);
new_field->pack_length=
my_decimal_get_binary_size(new_field->length, new_field->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 FIELD_TYPE_BLOB:
case FIELD_TYPE_TINY_BLOB:
case FIELD_TYPE_LONG_BLOB:
case FIELD_TYPE_MEDIUM_BLOB:
case FIELD_TYPE_GEOMETRY:
if (default_value) // Allow empty as default value
{
String str,*res;
res=default_value->val_str(&str);
if (res->length())
{
my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0),
field_name); /* purecov: inspected */
DBUG_RETURN(NULL);
}
new_field->def=0;
}
new_field->flags|=BLOB_FLAG;
break;
case FIELD_TYPE_YEAR:
if (!length || new_field->length != 2)
new_field->length=4; // Default length
new_field->flags|= ZEROFILL_FLAG | UNSIGNED_FLAG;
break;
case FIELD_TYPE_FLOAT:
/* change FLOAT(precision) to FLOAT or DOUBLE */
allowed_type_modifier= AUTO_INCREMENT_FLAG;
if (length && !decimals)
{
uint tmp_length=new_field->length;
if (tmp_length > PRECISION_FOR_DOUBLE)
{
my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name);
DBUG_RETURN(NULL);
}
else if (tmp_length > PRECISION_FOR_FLOAT)
{
new_field->sql_type=FIELD_TYPE_DOUBLE;
new_field->length=DBL_DIG+7; // -[digits].E+###
}
else
new_field->length=FLT_DIG+6; // -[digits].E+##
new_field->decimals= NOT_FIXED_DEC;
break;
}
if (!length && !decimals)
{
new_field->length = FLT_DIG+6;
new_field->decimals= NOT_FIXED_DEC;
}
if (new_field->length < new_field->decimals &&
new_field->decimals != NOT_FIXED_DEC)
{
my_error(ER_M_BIGGER_THAN_D, MYF(0), field_name);
DBUG_RETURN(NULL);
}
break;
case FIELD_TYPE_DOUBLE:
allowed_type_modifier= AUTO_INCREMENT_FLAG;
if (!length && !decimals)
{
new_field->length = DBL_DIG+7;
new_field->decimals=NOT_FIXED_DEC;
}
if (new_field->length < new_field->decimals &&
new_field->decimals != NOT_FIXED_DEC)
{
my_error(ER_M_BIGGER_THAN_D, MYF(0), field_name);
DBUG_RETURN(NULL);
}
break;
case FIELD_TYPE_TIMESTAMP:
if (!length)
new_field->length= 14; // Full date YYYYMMDDHHMMSS
else if (new_field->length != 19)
{
/*
We support only even TIMESTAMP lengths less or equal than 14
and 19 as length of 4.1 compatible representation.
*/
new_field->length=((new_field->length+1)/2)*2; /* purecov: inspected */
new_field->length= min(new_field->length,14); /* purecov: inspected */
}
new_field->flags|= ZEROFILL_FLAG | UNSIGNED_FLAG;
if (default_value)
{
/* Grammar allows only NOW() value for ON UPDATE clause */
if (default_value->type() == Item::FUNC_ITEM &&
((Item_func*)default_value)->functype() == Item_func::NOW_FUNC)
{
new_field->unireg_check= (on_update_value?Field::TIMESTAMP_DNUN_FIELD:
Field::TIMESTAMP_DN_FIELD);
/*
We don't need default value any longer moreover it is dangerous.
Everything handled by unireg_check further.
*/
new_field->def= 0;
}
else
new_field->unireg_check= (on_update_value?Field::TIMESTAMP_UN_FIELD:
Field::NONE);
}
else
{
/*
If we have default TIMESTAMP NOT NULL column without explicit DEFAULT
or ON UPDATE values then for the sake of compatiblity we should treat
this column as having DEFAULT NOW() ON UPDATE NOW() (when we don't
have another TIMESTAMP column with auto-set option before this one)
or DEFAULT 0 (in other cases).
So here we are setting TIMESTAMP_OLD_FIELD only temporary, and will
replace this value by TIMESTAMP_DNUN_FIELD or NONE later when
information about all TIMESTAMP fields in table will be availiable.
If we have TIMESTAMP NULL column without explicit DEFAULT value
we treat it as having DEFAULT NULL attribute.
*/
new_field->unireg_check= (on_update_value ?
Field::TIMESTAMP_UN_FIELD :
(new_field->flags & NOT_NULL_FLAG ?
Field::TIMESTAMP_OLD_FIELD:
Field::NONE));
}
break;
case FIELD_TYPE_DATE: // Old date type
if (protocol_version != PROTOCOL_VERSION-1)
new_field->sql_type=FIELD_TYPE_NEWDATE;
/* fall trough */
case FIELD_TYPE_NEWDATE:
new_field->length=10;
break;
case FIELD_TYPE_TIME:
new_field->length=10;
break;
case FIELD_TYPE_DATETIME:
new_field->length=19;
break;
case FIELD_TYPE_SET:
{
if (interval_list->elements > sizeof(longlong)*8)
{
my_error(ER_TOO_BIG_SET, MYF(0), field_name); /* purecov: inspected */
DBUG_RETURN(NULL);
}
new_field->pack_length= get_set_pack_length(interval_list->elements);
List_iterator<String> it(*interval_list);
String *tmp;
while ((tmp= it++))
new_field->interval_list.push_back(tmp);
/*
Set fake length to 1 to pass the below conditions.
Real length will be set in mysql_prepare_table()
when we know the character set of the column
*/
new_field->length= 1;
break;
}
case FIELD_TYPE_ENUM:
{
// Should be safe
new_field->pack_length= get_enum_pack_length(interval_list->elements);
List_iterator<String> it(*interval_list);
String *tmp;
while ((tmp= it++))
new_field->interval_list.push_back(tmp);
new_field->length= 1; // See comment for FIELD_TYPE_SET above.
break;
}
case MYSQL_TYPE_VAR_STRING:
DBUG_ASSERT(0); // Impossible
break;
case MYSQL_TYPE_BIT:
{
if (!length)
new_field->length= 1;
if (new_field->length > MAX_BIT_FIELD_LENGTH)
{
my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), field_name,
MAX_BIT_FIELD_LENGTH);
DBUG_RETURN(NULL);
}
new_field->pack_length= (new_field->length + 7) / 8;
break;
}
case FIELD_TYPE_DECIMAL:
DBUG_ASSERT(0); /* Was obsolete */
}
if (!(new_field->flags & BLOB_FLAG) &&
((new_field->length > max_field_charlength && type != FIELD_TYPE_SET &&
type != FIELD_TYPE_ENUM &&
(type != MYSQL_TYPE_VARCHAR || default_value)) ||
(!new_field->length &&
type != MYSQL_TYPE_STRING &&
type != MYSQL_TYPE_VARCHAR && type != FIELD_TYPE_GEOMETRY)))
{
my_error((type == MYSQL_TYPE_VAR_STRING || type == MYSQL_TYPE_VARCHAR ||
type == MYSQL_TYPE_STRING) ? ER_TOO_BIG_FIELDLENGTH :
ER_TOO_BIG_DISPLAYWIDTH,
MYF(0),
field_name, max_field_charlength); /* purecov: inspected */
DBUG_RETURN(NULL);
}
type_modifier&= AUTO_INCREMENT_FLAG;
if ((~allowed_type_modifier) & type_modifier)
{
my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name);
DBUG_RETURN(NULL);
}
DBUG_RETURN(new_field);
}
/* Store position for column in ALTER TABLE .. ADD column */