summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <mskold@mysql.com>2004-12-02 14:25:55 +0100
committerunknown <mskold@mysql.com>2004-12-02 14:25:55 +0100
commit76d43b1eb6fd60dc0bf94915b7fb4aaaedf4fd28 (patch)
treef5b670ccef121f00aae2415cac001aa14c87b437 /sql
parent067568aadfdbf87ddeb2d919800c5541edb700ea (diff)
parent374252c6860bfeab1efcd44078c0e203d21d676d (diff)
downloadmariadb-git-76d43b1eb6fd60dc0bf94915b7fb4aaaedf4fd28.tar.gz
Merge mskold@bk-internal.mysql.com:/home/bk/mysql-4.1
into mysql.com:/usr/local/home/marty/MySQL/test/mysql-4.1
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc39
-rw-r--r--sql/field.h1
-rw-r--r--sql/item_cmpfunc.cc12
-rw-r--r--sql/mysql_priv.h3
-rw-r--r--sql/set_var.cc9
-rw-r--r--sql/sql_acl.cc2
-rw-r--r--sql/sql_lex.h1
-rw-r--r--sql/sql_parse.cc99
-rw-r--r--sql/sql_prepare.cc13
-rw-r--r--sql/sql_show.cc9
-rw-r--r--sql/sql_table.cc134
-rw-r--r--sql/sql_yacc.yy20
12 files changed, 210 insertions, 132 deletions
diff --git a/sql/field.cc b/sql/field.cc
index db4b8f352c7..90203d1935d 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -5842,25 +5842,24 @@ bool Field_num::eq_def(Field *field)
void create_field::create_length_to_internal_length(void)
{
- switch (sql_type)
- {
- case MYSQL_TYPE_TINY_BLOB:
- case MYSQL_TYPE_MEDIUM_BLOB:
- case MYSQL_TYPE_LONG_BLOB:
- case MYSQL_TYPE_BLOB:
- case MYSQL_TYPE_VAR_STRING:
- case MYSQL_TYPE_STRING:
- length*= charset->mbmaxlen;
- pack_length= calc_pack_length(sql_type == FIELD_TYPE_VAR_STRING ?
- FIELD_TYPE_STRING : sql_type, length);
- break;
- case MYSQL_TYPE_ENUM:
- case MYSQL_TYPE_SET:
- length*= charset->mbmaxlen;
- break;
- default:
- /* do nothing */
- break;
+ switch (sql_type) {
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_STRING:
+ length*= charset->mbmaxlen;
+ pack_length= calc_pack_length(sql_type == FIELD_TYPE_VAR_STRING ?
+ FIELD_TYPE_STRING : sql_type, length);
+ break;
+ case MYSQL_TYPE_ENUM:
+ case MYSQL_TYPE_SET:
+ length*= charset->mbmaxlen;
+ break;
+ default:
+ /* do nothing */
+ break;
}
}
@@ -6085,6 +6084,8 @@ create_field::create_field(Field *old_field,Field *orig_field)
}
length=(length+charset->mbmaxlen-1)/charset->mbmaxlen; // QQ: Probably not needed
break;
+ case MYSQL_TYPE_ENUM:
+ case MYSQL_TYPE_SET:
case FIELD_TYPE_STRING:
case FIELD_TYPE_VAR_STRING:
length=(length+charset->mbmaxlen-1)/charset->mbmaxlen;
diff --git a/sql/field.h b/sql/field.h
index 8887da1dc0f..bb999222381 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1198,6 +1198,7 @@ public:
uint decimals,flags,pack_length;
Field::utype unireg_check;
TYPELIB *interval; // Which interval to use
+ List<String> interval_list;
CHARSET_INFO *charset;
Field::geometry_type geom_type;
Field *field; // For alter table
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index ac43b36600d..705258847c8 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -2365,10 +2365,10 @@ Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
}
int error;
if ((error= regcomp(&preg,res->c_ptr(),
- ((cmp_collation.collation->state & MY_CS_BINSORT) ||
- (cmp_collation.collation->state & MY_CS_CSSORT)) ?
+ ((cmp_collation.collation->state &
+ (MY_CS_BINSORT | MY_CS_CSSORT)) ?
REG_EXTENDED | REG_NOSUB :
- REG_EXTENDED | REG_NOSUB | REG_ICASE,
+ REG_EXTENDED | REG_NOSUB | REG_ICASE),
cmp_collation.collation)))
{
(void) regerror(error,&preg,buff,sizeof(buff));
@@ -2417,10 +2417,10 @@ longlong Item_func_regex::val_int()
regex_compiled=0;
}
if (regcomp(&preg,res2->c_ptr(),
- ((cmp_collation.collation->state & MY_CS_BINSORT) ||
- (cmp_collation.collation->state & MY_CS_CSSORT)) ?
+ ((cmp_collation.collation->state &
+ (MY_CS_BINSORT | MY_CS_CSSORT)) ?
REG_EXTENDED | REG_NOSUB :
- REG_EXTENDED | REG_NOSUB | REG_ICASE,
+ REG_EXTENDED | REG_NOSUB | REG_ICASE),
cmp_collation.collation))
{
null_value=1;
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 3f55a88b262..3a19a903e00 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -688,7 +688,8 @@ bool add_field_to_list(THD *thd, char *field_name, enum enum_field_types type,
uint type_modifier,
Item *default_value, Item *on_update_value,
LEX_STRING *comment,
- char *change, TYPELIB *interval,CHARSET_INFO *cs,
+ char *change, List<String> *interval_list,
+ CHARSET_INFO *cs,
uint uint_geom_type);
void store_position_for_column(const char *name);
bool add_to_list(THD *thd, SQL_LIST &list,Item *group,bool asc=0);
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 2031ac15412..79be4dc1c46 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -2725,24 +2725,23 @@ sys_var *find_sys_var(const char *str, uint length)
int sql_set_variables(THD *thd, List<set_var_base> *var_list)
{
- int error= 0;
+ int error;
List_iterator_fast<set_var_base> it(*var_list);
DBUG_ENTER("sql_set_variables");
set_var_base *var;
while ((var=it++))
{
- if ((error=var->check(thd)))
+ if ((error= var->check(thd)))
goto err;
}
- if (!thd->net.report_error)
+ if (!(error= test(thd->net.report_error)))
{
it.rewind();
while ((var= it++))
error|= var->update(thd); // Returns 0, -1 or 1
}
- else
- error= 1;
+
err:
free_underlaid_joins(thd, &thd->lex->select_lex);
DBUG_RETURN(error);
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index d6f52fed1d2..f1698dcc911 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -2035,7 +2035,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
{
table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
if (table->file->index_read(table->record[0], (byte*) table->field[0]->ptr,
- table->key_info[0].key_length,
+ key_length,
HA_READ_KEY_EXACT))
goto end;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 90c020b3e93..68a5ac29254 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -592,7 +592,6 @@ typedef struct st_lex
List<set_var_base> var_list;
List<Item_param> param_list;
SQL_LIST proc_list, auxilliary_table_list, save_list;
- TYPELIB *interval;
create_field *last_field;
char *savepoint_name; // Transaction savepoint id
udf_func udf;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index e066e447345..990e52d05ce 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -4115,31 +4115,6 @@ bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length)
#endif
-/*
- Calculate interval lengths.
- Strip trailing spaces from all strings.
- After this function call:
- - ENUM uses max_length
- - SET uses tot_length.
-*/
-void calculate_interval_lengths(THD *thd, TYPELIB *interval,
- uint32 *max_length, uint32 *tot_length)
-{
- const char **pos;
- uint *len;
- CHARSET_INFO *cs= thd->variables.character_set_client;
- *max_length= *tot_length= 0;
- for (pos= interval->type_names, len= interval->type_lengths;
- *pos ; pos++, len++)
- {
- *len= (uint) strip_sp((char*) *pos);
- uint length= cs->cset->numchars(cs, *pos, *pos + *len);
- *tot_length+= length;
- set_if_bigger(*max_length, (uint32)length);
- }
-}
-
-
/*****************************************************************************
** Store field definition for create
** Return 0 if ok
@@ -4150,7 +4125,8 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
uint type_modifier,
Item *default_value, Item *on_update_value,
LEX_STRING *comment,
- char *change, TYPELIB *interval, CHARSET_INFO *cs,
+ char *change,
+ List<String> *interval_list, CHARSET_INFO *cs,
uint uint_geom_type)
{
register create_field *new_field;
@@ -4445,62 +4421,39 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
break;
case FIELD_TYPE_SET:
{
- if (interval->count > sizeof(longlong)*8)
+ if (interval_list->elements > sizeof(longlong)*8)
{
- net_printf(thd,ER_TOO_BIG_SET,field_name); /* purecov: inspected */
- DBUG_RETURN(1); /* purecov: inspected */
+ net_printf(thd,ER_TOO_BIG_SET,field_name); /* purecov: inspected */
+ DBUG_RETURN(1); /* purecov: inspected */
}
- new_field->pack_length=(interval->count+7)/8;
+ new_field->pack_length= (interval_list->elements + 7) / 8;
if (new_field->pack_length > 4)
- new_field->pack_length=8;
- new_field->interval=interval;
- uint32 dummy_max_length;
- calculate_interval_lengths(thd, interval,
- &dummy_max_length, &new_field->length);
- new_field->length+= (interval->count - 1);
- set_if_smaller(new_field->length,MAX_FIELD_WIDTH-1);
- if (default_value)
- {
- char *not_used;
- uint not_used2;
- bool not_used3;
-
- thd->cuted_fields=0;
- String str,*res;
- res=default_value->val_str(&str);
- (void) find_set(interval, res->ptr(), res->length(),
- &my_charset_bin,
- &not_used, &not_used2, &not_used3);
- if (thd->cuted_fields)
- {
- net_printf(thd,ER_INVALID_DEFAULT,field_name);
- DBUG_RETURN(1);
- }
- }
+ new_field->pack_length=8;
+
+ 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:
{
- new_field->interval=interval;
- new_field->pack_length=interval->count < 256 ? 1 : 2; // Should be safe
+ // Should be safe
+ new_field->pack_length= interval_list->elements < 256 ? 1 : 2;
- uint32 dummy_tot_length;
- calculate_interval_lengths(thd, interval,
- &new_field->length, &dummy_tot_length);
- set_if_smaller(new_field->length,MAX_FIELD_WIDTH-1);
- if (default_value)
- {
- String str,*res;
- res=default_value->val_str(&str);
- res->strip_sp();
- if (!find_type(interval, res->ptr(), res->length(), 0))
- {
- net_printf(thd,ER_INVALID_DEFAULT,field_name);
- DBUG_RETURN(1);
- }
- }
- break;
+ 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;
}
if ((new_field->length > MAX_FIELD_CHARLENGTH && type != FIELD_TYPE_SET &&
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index a790e6fe9d8..637bb48b2cf 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -427,8 +427,17 @@ static void set_param_date(Item_param *param, uchar **pos, ulong len)
#else/*!EMBEDDED_LIBRARY*/
void set_param_time(Item_param *param, uchar **pos, ulong len)
{
- MYSQL_TIME *to= (MYSQL_TIME*)*pos;
- param->set_time(to, MYSQL_TIMESTAMP_TIME,
+ MYSQL_TIME tm= *((MYSQL_TIME*)*pos);
+ tm.hour+= tm.day * 24;
+ tm.day= tm.year= tm.month= 0;
+ if (tm.hour > 838)
+ {
+ /* TODO: add warning 'Data truncated' here */
+ tm.hour= 838;
+ tm.minute= 59;
+ tm.second= 59;
+ }
+ param->set_time(&tm, MYSQL_TIMESTAMP_TIME,
MAX_TIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN);
}
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index bda490e2916..ff0d943a717 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1169,6 +1169,15 @@ append_identifier(THD *thd, String *packet, const char *name, uint length)
{
uchar chr= (uchar) *name;
length= my_mbcharlen(system_charset_info, chr);
+ /*
+ my_mbcharlen can retur 0 on a wrong multibyte
+ sequence. It is possible when upgrading from 4.0,
+ and identifier contains some accented characters.
+ The manual says it does not work. So we'll just
+ change length to 1 not to hang in the endless loop.
+ */
+ if (!length)
+ length= 1;
if (length == 1 && chr == (uchar) quote_char)
packet->append(&quote_char, 1, system_charset_info);
packet->append(name, length, packet->charset());
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index eedd9388877..71ce9102fbb 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -392,6 +392,41 @@ void check_duplicates_in_interval(const char *set_or_name,
}
}
+
+/*
+ Check TYPELIB (set or enum) max and total lengths
+
+ SYNOPSIS
+ calculate_interval_lengths()
+ cs charset+collation pair of the interval
+ typelib list of values for the column
+ max_length length of the longest item
+ tot_length sum of the item lengths
+
+ DESCRIPTION
+ After this function call:
+ - ENUM uses max_length
+ - SET uses tot_length.
+
+ RETURN VALUES
+ void
+*/
+void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
+ uint32 *max_length, uint32 *tot_length)
+{
+ const char **pos;
+ uint *len;
+ *max_length= *tot_length= 0;
+ for (pos= interval->type_names, len= interval->type_lengths;
+ *pos ; pos++, len++)
+ {
+ uint length= cs->cset->numchars(cs, *pos, *pos + *len);
+ *tot_length+= length;
+ set_if_bigger(*max_length, (uint32)length);
+ }
+}
+
+
/*
Preparation for table creation
@@ -455,6 +490,91 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
DBUG_RETURN(-1);
}
+ if ((sql_field->sql_type == FIELD_TYPE_SET ||
+ sql_field->sql_type == FIELD_TYPE_ENUM) && !sql_field->interval)
+ {
+ uint32 dummy;
+ CHARSET_INFO *cs= sql_field->charset;
+ TYPELIB *interval;
+
+ /*
+ Create typelib from interval_list, and if necessary
+ convert strings from client character set to the
+ column character set.
+ */
+
+ interval= sql_field->interval= typelib(sql_field->interval_list);
+ List_iterator<String> it(sql_field->interval_list);
+ String conv, *tmp;
+ for (uint i= 0; (tmp= it++); i++)
+ {
+ if (String::needs_conversion(tmp->length(), tmp->charset(), cs, &dummy))
+ {
+ uint cnv_errs;
+ conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
+ char *buf= (char*) sql_alloc(conv.length()+1);
+ memcpy(buf, conv.ptr(), conv.length());
+ buf[conv.length()]= '\0';
+ interval->type_names[i]= buf;
+ interval->type_lengths[i]= conv.length();
+ }
+
+ // Strip trailing spaces.
+ uint lengthsp= cs->cset->lengthsp(cs, interval->type_names[i],
+ interval->type_lengths[i]);
+ interval->type_lengths[i]= lengthsp;
+ ((uchar *)interval->type_names[i])[lengthsp]= '\0';
+ }
+ sql_field->interval_list.empty(); // Don't need interval_list anymore
+
+
+ /*
+ Convert the default value from client character
+ set into the column character set if necessary.
+ */
+ if (sql_field->def)
+ {
+ sql_field->def=
+ sql_field->def->safe_charset_converter(cs);
+ }
+
+ if (sql_field->sql_type == FIELD_TYPE_SET)
+ {
+ if (sql_field->def)
+ {
+ char *not_used;
+ uint not_used2;
+ bool not_found= 0;
+ String str, *def= sql_field->def->val_str(&str);
+ def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
+ (void) find_set(interval, def->ptr(), def->length(),
+ cs, &not_used, &not_used2, &not_found);
+ if (not_found)
+ {
+ my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
+ DBUG_RETURN(-1);
+ }
+ }
+ calculate_interval_lengths(cs, interval, &dummy, &sql_field->length);
+ sql_field->length+= (interval->count - 1);
+ }
+ else /* FIELD_TYPE_ENUM */
+ {
+ if (sql_field->def)
+ {
+ String str, *def= sql_field->def->val_str(&str);
+ def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
+ if (!find_type2(interval, def->ptr(), def->length(), cs))
+ {
+ my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
+ DBUG_RETURN(-1);
+ }
+ }
+ calculate_interval_lengths(cs, interval, &sql_field->length, &dummy);
+ }
+ set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
+ }
+
sql_field->create_length_to_internal_length();
/* Don't pack keys in old tables if the user has requested this */
@@ -814,8 +934,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
DBUG_RETURN(-1);
}
}
- else
- if (key_info->algorithm == HA_KEY_ALG_RTREE)
+ else if (key_info->algorithm == HA_KEY_ALG_RTREE)
{
#ifdef HAVE_RTREE_KEYS
if ((key_info->key_parts & 1) == 1)
@@ -839,6 +958,8 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
CHARSET_INFO *ft_key_charset=0; // for FULLTEXT
for (uint column_nr=0 ; (column=cols++) ; column_nr++)
{
+ key_part_spec *dup_column;
+
it.rewind();
field=0;
while ((sql_field=it++) &&
@@ -853,9 +974,8 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
column->field_name);
DBUG_RETURN(-1);
}
- for (uint dup_nr= 0; dup_nr < column_nr; dup_nr++)
+ while ((dup_column= cols2++) != column)
{
- key_part_spec *dup_column= cols2++;
if (!my_strcasecmp(system_charset_info,
column->field_name, dup_column->field_name))
{
@@ -866,12 +986,6 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
}
}
cols2.rewind();
- /* for fulltext keys keyseg length is 1 for blobs (it's ignored in
- ft code anyway, and 0 (set to column width later) for char's.
- it has to be correct col width for char's, as char data are not
- prefixed with length (unlike blobs, where ft code takes data length
- from a data prefix, ignoring column->length).
- */
if (key->type == Key::FULLTEXT)
{
if ((sql_field->sql_type != FIELD_TYPE_STRING &&
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 8cbfaf3f99b..49e567ab54b 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1361,7 +1361,7 @@ field_spec:
field_ident
{
LEX *lex=Lex;
- lex->length=lex->dec=0; lex->type=0; lex->interval=0;
+ lex->length=lex->dec=0; lex->type=0;
lex->default_value= lex->on_update_value= 0;
lex->comment=0;
lex->charset=NULL;
@@ -1374,7 +1374,7 @@ field_spec:
lex->length,lex->dec,lex->type,
lex->default_value, lex->on_update_value,
lex->comment,
- lex->change,lex->interval,lex->charset,
+ lex->change,&lex->interval_list,lex->charset,
lex->uint_geom_type))
YYABORT;
};
@@ -1471,17 +1471,9 @@ type:
| FIXED_SYM float_options field_options
{ $$=FIELD_TYPE_DECIMAL;}
| ENUM {Lex->interval_list.empty();} '(' string_list ')' opt_binary
- {
- LEX *lex=Lex;
- lex->interval=typelib(lex->interval_list);
- $$=FIELD_TYPE_ENUM;
- }
+ { $$=FIELD_TYPE_ENUM; }
| SET { Lex->interval_list.empty();} '(' string_list ')' opt_binary
- {
- LEX *lex=Lex;
- lex->interval=typelib(lex->interval_list);
- $$=FIELD_TYPE_SET;
- }
+ { $$=FIELD_TYPE_SET; }
| LONG_SYM opt_binary { $$=FIELD_TYPE_MEDIUM_BLOB; }
| SERIAL_SYM
{
@@ -1925,7 +1917,7 @@ alter_list_item:
| MODIFY_SYM opt_column field_ident
{
LEX *lex=Lex;
- lex->length=lex->dec=0; lex->type=0; lex->interval=0;
+ lex->length=lex->dec=0; lex->type=0;
lex->default_value= lex->on_update_value= 0;
lex->comment=0;
lex->charset= NULL;
@@ -1940,7 +1932,7 @@ alter_list_item:
lex->length,lex->dec,lex->type,
lex->default_value, lex->on_update_value,
lex->comment,
- $3.str, lex->interval, lex->charset,
+ $3.str, &lex->interval_list, lex->charset,
lex->uint_geom_type))
YYABORT;
}