summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/Makefile.am2
-rw-r--r--sql/field.cc2
-rw-r--r--sql/item_create.cc35
-rw-r--r--sql/item_create.h7
-rw-r--r--sql/item_func.cc78
-rw-r--r--sql/item_timefunc.cc630
-rw-r--r--sql/item_timefunc.h115
-rw-r--r--sql/lex.h16
-rw-r--r--sql/mysql_priv.h12
-rw-r--r--sql/mysqld.cc31
-rw-r--r--sql/protocol.cc17
-rw-r--r--sql/set_var.cc218
-rw-r--r--sql/set_var.h109
-rw-r--r--sql/share/czech/errmsg.txt3
-rw-r--r--sql/share/danish/errmsg.txt5
-rw-r--r--sql/share/dutch/errmsg.txt5
-rw-r--r--sql/share/english/errmsg.txt5
-rw-r--r--sql/share/estonian/errmsg.txt1
-rw-r--r--sql/share/french/errmsg.txt5
-rw-r--r--sql/share/german/errmsg.txt5
-rw-r--r--sql/share/greek/errmsg.txt1
-rw-r--r--sql/share/hungarian/errmsg.txt1
-rw-r--r--sql/share/italian/errmsg.txt5
-rw-r--r--sql/share/japanese/errmsg.txt1
-rw-r--r--sql/share/korean/errmsg.txt1
-rw-r--r--sql/share/norwegian-ny/errmsg.txt5
-rw-r--r--sql/share/norwegian/errmsg.txt5
-rw-r--r--sql/share/polish/errmsg.txt5
-rw-r--r--sql/share/portuguese/errmsg.txt5
-rw-r--r--sql/share/romanian/errmsg.txt5
-rw-r--r--sql/share/russian/errmsg.txt1
-rw-r--r--sql/share/serbian/errmsg.txt5
-rw-r--r--sql/share/slovak/errmsg.txt5
-rw-r--r--sql/share/spanish/errmsg.txt5
-rw-r--r--sql/share/swedish/errmsg.txt3
-rw-r--r--sql/share/ukrainian/errmsg.txt1
-rw-r--r--sql/sql_lex.cc23
-rw-r--r--sql/sql_parse.cc16
-rw-r--r--sql/sql_prepare.cc2
-rw-r--r--sql/sql_show.cc5
-rw-r--r--sql/sql_string.cc17
-rw-r--r--sql/sql_string.h2
-rw-r--r--sql/sql_yacc.yy69
-rw-r--r--sql/time.cc14
44 files changed, 1297 insertions, 206 deletions
diff --git a/sql/Makefile.am b/sql/Makefile.am
index fd02cc906d7..5781b6181d2 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -117,7 +117,7 @@ gen_lex_hash.o: gen_lex_hash.cc lex.h
sql_yacc.cc: sql_yacc.yy
sql_yacc.h: sql_yacc.yy
-sql_yacc.o: sql_yacc.cc sql_yacc.h
+sql_yacc.o: sql_yacc.cc sql_yacc.h $(HEADERS)
@echo "Note: The following compile may take a long time."
@echo "If it fails, re-run configure with --with-low-memory"
$(CXXCOMPILE) $(LM_CFLAGS) -c $<
diff --git a/sql/field.cc b/sql/field.cc
index 4aa58180a69..2f89dd43c3f 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -3152,11 +3152,13 @@ bool Field_time::get_time(TIME *ltime)
ltime->neg= 1;
tmp=-tmp;
}
+ ltime->day= 0;
ltime->hour= (int) (tmp/10000);
tmp-=ltime->hour*10000;
ltime->minute= (int) tmp/100;
ltime->second= (int) tmp % 100;
ltime->second_part=0;
+ ltime->time_type= TIMESTAMP_TIME;
return 0;
}
diff --git a/sql/item_create.cc b/sql/item_create.cc
index fbb26e83dfd..67179c8d002 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -679,3 +679,38 @@ Item *create_func_uncompressed_length(Item* a)
#endif
+Item *create_func_datediff(Item *a, Item *b)
+{
+ return new Item_func_minus(new Item_func_to_days(a),
+ new Item_func_to_days(b));
+}
+
+Item *create_func_weekofyear(Item *a)
+{
+ return new Item_func_week(a, new Item_int((char*) "0", 3, 1));
+}
+
+Item *create_func_makedate(Item* a,Item* b)
+{
+ return new Item_func_makedate(a, b);
+}
+
+Item *create_func_addtime(Item* a,Item* b)
+{
+ return new Item_func_add_time(a, b, 0, 0);
+}
+
+Item *create_func_subtime(Item* a,Item* b)
+{
+ return new Item_func_add_time(a, b, 0, 1);
+}
+
+Item *create_func_timediff(Item* a,Item* b)
+{
+ return new Item_func_timediff(a, b);
+}
+
+Item *create_func_maketime(Item* a,Item* b,Item* c)
+{
+ return new Item_func_maketime(a, b, c);
+}
diff --git a/sql/item_create.h b/sql/item_create.h
index 2872451c034..434a0b134c1 100644
--- a/sql/item_create.h
+++ b/sql/item_create.h
@@ -144,3 +144,10 @@ Item *create_func_compress(Item *a);
Item *create_func_uncompress(Item *a);
Item *create_func_uncompressed_length(Item *a);
+Item *create_func_datediff(Item *a, Item *b);
+Item *create_func_weekofyear(Item *a);
+Item *create_func_makedate(Item* a,Item* b);
+Item *create_func_addtime(Item* a,Item* b);
+Item *create_func_subtime(Item* a,Item* b);
+Item *create_func_timediff(Item* a,Item* b);
+Item *create_func_maketime(Item* a,Item* b,Item* c);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index ad2bebf9efb..7264a3b5225 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -2694,21 +2694,61 @@ longlong Item_func_bit_xor::val_int()
System variables
****************************************************************************/
-Item *get_system_var(enum_var_type var_type, LEX_STRING name)
+/*
+ Return value of an system variable base[.name] as a constant item
+
+ SYNOPSIS
+ get_system_var()
+ thd Thread handler
+ var_type global / session
+ name Name of base or system variable
+ component Component.
+
+ NOTES
+ If component.str = 0 then the variable name is in 'name'
+
+ RETURN
+ 0 error
+ # constant item
+*/
+
+
+Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
+ LEX_STRING component)
{
- if (!my_strcasecmp(system_charset_info, name.str, "VERSION"))
+ if (component.str == 0 &&
+ !my_strcasecmp(system_charset_info, name.str, "VERSION"))
return new Item_string("@@VERSION", server_version,
(uint) strlen(server_version),
system_charset_info);
- THD *thd=current_thd;
Item *item;
sys_var *var;
- char buff[MAX_SYS_VAR_LENGTH+3+8], *pos;
+ char buff[MAX_SYS_VAR_LENGTH*2+4+8], *pos;
+ LEX_STRING *base_name, *component_name;
+
+ if (component.str)
+ {
+ base_name= &component;
+ component_name= &name;
+ }
+ else
+ {
+ base_name= &name;
+ component_name= &component; // Empty string
+ }
- if (!(var= find_sys_var(name.str, name.length)))
+ if (!(var= find_sys_var(base_name->str, base_name->length)))
return 0;
- if (!(item=var->item(thd, var_type)))
+ if (component.str)
+ {
+ if (!var->is_struct())
+ {
+ net_printf(thd, ER_VARIABLE_IS_NOT_STRUCT, base_name->str);
+ return 0;
+ }
+ }
+ if (!(item=var->item(thd, var_type, component_name)))
return 0; // Impossible
thd->lex.uncacheable();
buff[0]='@';
@@ -2718,23 +2758,37 @@ Item *get_system_var(enum_var_type var_type, LEX_STRING name)
pos=strmov(pos,"session.");
else if (var_type == OPT_GLOBAL)
pos=strmov(pos,"global.");
- memcpy(pos, var->name, var->name_length+1);
+
+ set_if_smaller(component_name->length, MAX_SYS_VAR_LENGTH);
+ set_if_smaller(base_name->length, MAX_SYS_VAR_LENGTH);
+
+ if (component_name->str)
+ {
+ memcpy(pos, component_name->str, component_name->length);
+ pos+= component_name->length;
+ *pos++= '.';
+ }
+ memcpy(pos, base_name->str, base_name->length);
+ pos+= base_name->length;
+
// set_name() will allocate the name
- item->set_name(buff,(uint) (pos-buff)+var->name_length, system_charset_info);
+ item->set_name(buff,(uint) (pos-buff), system_charset_info);
return item;
}
-Item *get_system_var(enum_var_type var_type, const char *var_name, uint length,
- const char *item_name)
+Item *get_system_var(THD *thd, enum_var_type var_type, const char *var_name,
+ uint length, const char *item_name)
{
- THD *thd=current_thd;
Item *item;
sys_var *var;
+ LEX_STRING null_lex_string;
+
+ null_lex_string.str= 0;
var= find_sys_var(var_name, length);
DBUG_ASSERT(var != 0);
- if (!(item=var->item(thd, var_type)))
+ if (!(item=var->item(thd, var_type, &null_lex_string)))
return 0; // Impossible
thd->lex.uncacheable();
item->set_name(item_name, 0, system_charset_info); // Will use original name
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 61c869cddba..4fdb1b13d24 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -29,6 +29,8 @@
** Todo: Move month and days to language files
*/
+#define MAX_DAY_NUMBER 3652424L
+
static String month_names[] =
{
String("January", &my_charset_latin1),
@@ -55,6 +57,82 @@ static String day_names[] =
String("Sunday", &my_charset_latin1)
};
+enum date_time_format_types
+{
+ TIME_ONLY= 0, TIME_MICROSECOND,
+ DATE_ONLY, DATE_TIME, DATE_TIME_MICROSECOND
+};
+
+typedef struct date_time_format
+{
+ const char* format_str;
+ uint length;
+};
+
+static struct date_time_format date_time_formats[]=
+{
+ {"%s%02d:%02d:%02d", 10},
+ {"%s%02d:%02d:%02d.%06d", 17},
+ {"%04d-%02d-%02d", 10},
+ {"%04d-%02d-%02d %02d:%02d:%02d", 19},
+ {"%04d-%02d-%02d %02d:%02d:%02d.%06d", 26}
+};
+
+
+/*
+ OPTIMIZATION TODO:
+ - Replace the switch with a function that should be called for each
+ date type.
+ - Remove sprintf and opencode the conversion, like we do in
+ Field_datetime.
+*/
+
+String *make_datetime(String *str, TIME *ltime,
+ enum date_time_format_types format)
+{
+ char *buff;
+ CHARSET_INFO *cs= &my_charset_bin;
+ uint length= date_time_formats[format].length + 32;
+ const char* format_str= date_time_formats[format].format_str;
+
+ if (str->alloc(length))
+ return 0;
+
+ buff= (char*) str->ptr();
+ switch (format) {
+ case TIME_ONLY:
+ length= cs->cset->snprintf(cs, buff, length, format_str, ltime->neg ? "-" : "",
+ ltime->hour, ltime->minute, ltime->second);
+ break;
+ case TIME_MICROSECOND:
+ length= cs->cset->snprintf(cs, buff, length, format_str, ltime->neg ? "-" : "",
+ ltime->hour, ltime->minute, ltime->second,
+ ltime->second_part);
+ break;
+ case DATE_ONLY:
+ length= cs->cset->snprintf(cs, buff, length, format_str,
+ ltime->year, ltime->month, ltime->day);
+ break;
+ case DATE_TIME:
+ length= cs->cset->snprintf(cs, buff, length, format_str,
+ ltime->year, ltime->month, ltime->day,
+ ltime->hour, ltime->minute, ltime->second);
+ break;
+ case DATE_TIME_MICROSECOND:
+ length= cs->cset->snprintf(cs, buff, length, format_str,
+ ltime->year, ltime->month, ltime->day,
+ ltime->hour, ltime->minute, ltime->second,
+ ltime->second_part);
+ break;
+ default:
+ return 0;
+ }
+
+ str->length(length);
+ str->set_charset(cs);
+ return str;
+}
+
/*
** Get a array of positive numbers from a string object.
** Each number is separated by 1 non digit character
@@ -309,7 +387,7 @@ static bool get_interval_value(Item *args,interval_type int_type,
CHARSET_INFO *cs=str_value->charset();
bzero((char*) t,sizeof(*t));
- if ((int) int_type <= INTERVAL_SECOND)
+ if ((int) int_type <= INTERVAL_MICROSECOND)
{
value=(long) args->val_int();
if (args->null_value)
@@ -352,6 +430,9 @@ static bool get_interval_value(Item *args,interval_type int_type,
case INTERVAL_HOUR:
t->hour=value;
break;
+ case INTERVAL_MICROSECOND:
+ t->second_part=value;
+ break;
case INTERVAL_MINUTE:
t->minute=value;
break;
@@ -370,6 +451,15 @@ static bool get_interval_value(Item *args,interval_type int_type,
t->day=array[0];
t->hour=array[1];
break;
+ case INTERVAL_DAY_MICROSECOND:
+ if (get_interval_info(str,length,cs,5,array))
+ return (1);
+ t->day=array[0];
+ t->hour=array[1];
+ t->minute=array[2];
+ t->second=array[3];
+ t->second_part=array[4];
+ break;
case INTERVAL_DAY_MINUTE:
if (get_interval_info(str,length,cs,3,array))
return (1);
@@ -385,6 +475,14 @@ static bool get_interval_value(Item *args,interval_type int_type,
t->minute=array[2];
t->second=array[3];
break;
+ case INTERVAL_HOUR_MICROSECOND:
+ if (get_interval_info(str,length,cs,4,array))
+ return (1);
+ t->hour=array[0];
+ t->minute=array[1];
+ t->second=array[2];
+ t->second_part=array[3];
+ break;
case INTERVAL_HOUR_MINUTE:
if (get_interval_info(str,length,cs,2,array))
return (1);
@@ -398,12 +496,25 @@ static bool get_interval_value(Item *args,interval_type int_type,
t->minute=array[1];
t->second=array[2];
break;
+ case INTERVAL_MINUTE_MICROSECOND:
+ if (get_interval_info(str,length,cs,3,array))
+ return (1);
+ t->minute=array[0];
+ t->second=array[1];
+ t->second_part=array[2];
+ break;
case INTERVAL_MINUTE_SECOND:
if (get_interval_info(str,length,cs,2,array))
return (1);
t->minute=array[0];
t->second=array[1];
break;
+ case INTERVAL_SECOND_MICROSECOND:
+ if (get_interval_info(str,length,cs,2,array))
+ return (1);
+ t->second=array[0];
+ t->second_part=array[1];
+ break;
}
return 0;
}
@@ -687,6 +798,9 @@ uint Item_func_date_format::format_length(const String *format)
case 'T': /* time, 24-hour (hh:mm:ss) */
size += 8;
break;
+ case 'f': /* microseconds */
+ size += 6;
+ break;
case 'w': /* day (of the week), numeric */
case '%':
default:
@@ -798,8 +912,8 @@ String *Item_func_date_format::val_str(String *str)
null_value=1;
return 0;
}
- length= my_sprintf(intbuff, (intbuff,"%d",l_time.day));
- str->append(intbuff, length);
+ length= int10_to_str(l_time.day, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 1, '0');
if (l_time.day >= 10 && l_time.day <= 19)
str->append("th");
else
@@ -821,41 +935,45 @@ String *Item_func_date_format::val_str(String *str)
}
break;
case 'Y':
- sprintf(intbuff,"%04d",l_time.year);
- str->append(intbuff,4);
+ length= int10_to_str(l_time.year, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 4, '0');
break;
case 'y':
- sprintf(intbuff,"%02d",l_time.year%100);
- str->append(intbuff,2);
+ length= int10_to_str(l_time.year%100, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'm':
- sprintf(intbuff,"%02d",l_time.month);
- str->append(intbuff,2);
+ length= int10_to_str(l_time.month, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'c':
- sprintf(intbuff,"%d",l_time.month);
- str->append(intbuff);
+ length= int10_to_str(l_time.month, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 1, '0');
break;
case 'd':
- sprintf(intbuff,"%02d",l_time.day);
- str->append(intbuff,2);
+ length= int10_to_str(l_time.day, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'e':
- sprintf(intbuff,"%d",l_time.day);
- str->append(intbuff);
+ length= int10_to_str(l_time.day, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 1, '0');
+ break;
+ case 'f':
+ length= int10_to_str(l_time.second_part, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 6, '0');
break;
case 'H':
- sprintf(intbuff,"%02d",l_time.hour);
- str->append(intbuff,2);
+ length= int10_to_str(l_time.hour, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'h':
case 'I':
- sprintf(intbuff,"%02d", (l_time.hour+11)%12+1);
- str->append(intbuff,2);
+ length= int10_to_str((l_time.hour+11)%12+1, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'i': /* minutes */
- sprintf(intbuff,"%02d",l_time.minute);
- str->append(intbuff,2);
+ length= int10_to_str(l_time.minute, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'j':
if (date_or_time)
@@ -863,52 +981,60 @@ String *Item_func_date_format::val_str(String *str)
null_value=1;
return 0;
}
- sprintf(intbuff,"%03d",
- (int) (calc_daynr(l_time.year,l_time.month,l_time.day) -
- calc_daynr(l_time.year,1,1)) + 1);
- str->append(intbuff,3);
+ length= int10_to_str(calc_daynr(l_time.year,l_time.month,l_time.day) -
+ calc_daynr(l_time.year,1,1) + 1, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 3, '0');
break;
case 'k':
- sprintf(intbuff,"%d",l_time.hour);
- str->append(intbuff);
+ length= int10_to_str(l_time.hour, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 1, '0');
break;
case 'l':
- sprintf(intbuff,"%d", (l_time.hour+11)%12+1);
- str->append(intbuff);
+ length= int10_to_str((l_time.hour+11)%12+1, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 1, '0');
break;
case 'p':
str->append(l_time.hour < 12 ? "AM" : "PM",2);
break;
case 'r':
- sprintf(intbuff,(l_time.hour < 12) ? "%02d:%02d:%02d AM" :
- "%02d:%02d:%02d PM",(l_time.hour+11)%12+1,l_time.minute,
- l_time.second);
- str->append(intbuff);
+ length= my_sprintf(intbuff,
+ (intbuff,
+ (l_time.hour < 12) ? "%02d:%02d:%02d AM" : "%02d:%02d:%02d PM",
+ (l_time.hour+11)%12+1,
+ l_time.minute,
+ l_time.second));
+ str->append(intbuff, length);
break;
case 'S':
case 's':
- sprintf(intbuff,"%02d",l_time.second);
- str->append(intbuff);
+ length= int10_to_str(l_time.second, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'T':
- sprintf(intbuff,"%02d:%02d:%02d", l_time.hour, l_time.minute,
- l_time.second);
- str->append(intbuff);
+ length= my_sprintf(intbuff,
+ (intbuff,
+ "%02d:%02d:%02d",
+ l_time.hour,
+ l_time.minute,
+ l_time.second));
+ str->append(intbuff, length);
break;
case 'U':
case 'u':
{
uint year;
- sprintf(intbuff,"%02d",calc_week(&l_time, 0, (*ptr) == 'U', &year));
- str->append(intbuff,2);
+ length= int10_to_str(calc_week(&l_time, 0, (*ptr) == 'U', &year),
+ intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
}
break;
case 'v':
case 'V':
{
uint year;
- sprintf(intbuff,"%02d",calc_week(&l_time, 1, (*ptr) == 'V', &year));
- str->append(intbuff,2);
+ length= int10_to_str(calc_week(&l_time, 1, (*ptr) == 'V', &year),
+ intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
}
break;
case 'x':
@@ -916,14 +1042,15 @@ String *Item_func_date_format::val_str(String *str)
{
uint year;
(void) calc_week(&l_time, 1, (*ptr) == 'X', &year);
- sprintf(intbuff,"%04d",year);
- str->append(intbuff,4);
+ length= int10_to_str(year, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 4, '0');
}
break;
case 'w':
weekday=calc_weekday(calc_daynr(l_time.year,l_time.month,l_time.day),1);
- sprintf(intbuff,"%d",weekday);
- str->append(intbuff,1);
+ length= int10_to_str(weekday, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 1, '0');
+
break;
default:
str->append(*ptr);
@@ -1005,7 +1132,7 @@ void Item_date_add_interval::fix_length_and_dec()
enum_field_types arg0_field_type;
set_charset(default_charset());
maybe_null=1;
- max_length=19*default_charset()->mbmaxlen;
+ max_length=26*MY_CHARSET_BIN_MB_MAXLEN;
value.alloc(32);
/*
@@ -1051,39 +1178,55 @@ bool Item_date_add_interval::get_date(TIME *ltime, bool fuzzy_date)
null_value=0;
switch (int_type) {
case INTERVAL_SECOND:
+ case INTERVAL_SECOND_MICROSECOND:
+ case INTERVAL_MICROSECOND:
case INTERVAL_MINUTE:
case INTERVAL_HOUR:
+ case INTERVAL_MINUTE_MICROSECOND:
case INTERVAL_MINUTE_SECOND:
+ case INTERVAL_HOUR_MICROSECOND:
case INTERVAL_HOUR_SECOND:
case INTERVAL_HOUR_MINUTE:
+ case INTERVAL_DAY_MICROSECOND:
case INTERVAL_DAY_SECOND:
case INTERVAL_DAY_MINUTE:
case INTERVAL_DAY_HOUR:
- long sec,days,daynr;
+ long sec,days,daynr,microseconds,extra_sec;
ltime->time_type=TIMESTAMP_FULL; // Return full date
+ microseconds= ltime->second_part + sign*interval.second_part;
+ extra_sec= microseconds/1000000L;
+ microseconds= microseconds%1000000L;
sec=((ltime->day-1)*3600*24L+ltime->hour*3600+ltime->minute*60+
ltime->second +
sign*(interval.day*3600*24L +
- interval.hour*3600+interval.minute*60+interval.second));
+ interval.hour*3600+interval.minute*60+interval.second))+
+ extra_sec;
+
+ if (microseconds < 0)
+ {
+ microseconds+= 1000000L;
+ sec--;
+ }
days=sec/(3600*24L); sec=sec-days*3600*24L;
if (sec < 0)
{
days--;
sec+=3600*24L;
}
+ ltime->second_part= microseconds;
ltime->second=sec % 60;
ltime->minute=sec/60 % 60;
ltime->hour=sec/3600;
daynr= calc_daynr(ltime->year,ltime->month,1) + days;
get_date_from_daynr(daynr,&ltime->year,&ltime->month,&ltime->day);
- if (daynr < 0 || daynr >= 3652424) // Day number from year 0 to 9999-12-31
+ if (daynr < 0 || daynr >= MAX_DAY_NUMBER) // Day number from year 0 to 9999-12-31
goto null_date;
break;
case INTERVAL_DAY:
period= calc_daynr(ltime->year,ltime->month,ltime->day) +
sign*interval.day;
- if (period < 0 || period >= 3652424) // Daynumber from year 0 to 9999-12-31
+ if (period < 0 || period >= MAX_DAY_NUMBER) // Daynumber from year 0 to 9999-12-31
goto null_date;
get_date_from_daynr((long) period,&ltime->year,&ltime->month,&ltime->day);
break;
@@ -1124,34 +1267,21 @@ bool Item_date_add_interval::get_date(TIME *ltime, bool fuzzy_date)
String *Item_date_add_interval::val_str(String *str)
{
TIME ltime;
- CHARSET_INFO *cs=default_charset();
- uint32 l;
+ enum date_time_format_types format;
if (Item_date_add_interval::get_date(&ltime,0))
return 0;
+
if (ltime.time_type == TIMESTAMP_DATE)
- {
- l=11*cs->mbmaxlen+32;
- if (str->alloc(l))
- goto null_date;
- l=cs->cset->snprintf(cs,(char*) str->ptr(),l,"%04d-%02d-%02d",
- ltime.year,ltime.month,ltime.day);
- str->length(l);
- }
+ format= DATE_ONLY;
+ else if (ltime.second_part)
+ format= DATE_TIME_MICROSECOND;
else
- {
- l=20*cs->mbmaxlen+32;
- if (str->alloc(l))
- goto null_date;
- l=cs->cset->snprintf(cs,(char*) str->ptr(),l,"%04d-%02d-%02d %02d:%02d:%02d",
- ltime.year,ltime.month,ltime.day,
- ltime.hour,ltime.minute,ltime.second);
- str->length(l);
- }
- str->set_charset(cs);
- return str;
+ format= DATE_TIME;
+
+ if (make_datetime(str, &ltime, format))
+ return str;
- null_date:
null_value=1;
return 0;
}
@@ -1188,6 +1318,11 @@ void Item_extract::fix_length_and_dec()
case INTERVAL_MINUTE: max_length=2; date_value=0; break;
case INTERVAL_MINUTE_SECOND: max_length=4; date_value=0; break;
case INTERVAL_SECOND: max_length=2; date_value=0; break;
+ case INTERVAL_MICROSECOND: max_length=2; date_value=0; break;
+ case INTERVAL_DAY_MICROSECOND: max_length=20; date_value=0; break;
+ case INTERVAL_HOUR_MICROSECOND: max_length=13; date_value=0; break;
+ case INTERVAL_MINUTE_MICROSECOND: max_length=11; date_value=0; break;
+ case INTERVAL_SECOND_MICROSECOND: max_length=9; date_value=0; break;
}
}
@@ -1234,6 +1369,21 @@ longlong Item_extract::val_int()
case INTERVAL_MINUTE: return (long) ltime.minute*neg;
case INTERVAL_MINUTE_SECOND: return (long) (ltime.minute*100+ltime.second)*neg;
case INTERVAL_SECOND: return (long) ltime.second*neg;
+ case INTERVAL_MICROSECOND: return (long) ltime.second_part*neg;
+ case INTERVAL_DAY_MICROSECOND: return (((longlong)ltime.day*1000000L +
+ (longlong)ltime.hour*10000L +
+ ltime.minute*100 +
+ ltime.second)*1000000L +
+ ltime.second_part)*neg;
+ case INTERVAL_HOUR_MICROSECOND: return (((longlong)ltime.hour*10000L +
+ ltime.minute*100 +
+ ltime.second)*1000000L +
+ ltime.second_part)*neg;
+ case INTERVAL_MINUTE_MICROSECOND: return (((longlong)(ltime.minute*100+
+ ltime.second))*1000000L+
+ ltime.second_part)*neg;
+ case INTERVAL_SECOND_MICROSECOND: return ((longlong)ltime.second*1000000L+
+ ltime.second_part)*neg;
}
return 0; // Impossible
}
@@ -1247,3 +1397,337 @@ void Item_typecast::print(String *str)
str->append(func_name());
str->append(')');
}
+
+String *Item_datetime_typecast::val_str(String *str)
+{
+ TIME ltime;
+
+ if (!get_arg0_date(&ltime,1) &&
+ make_datetime(str, &ltime, ltime.second_part ?
+ DATE_TIME_MICROSECOND : DATE_TIME))
+ return str;
+
+null_date:
+ null_value=1;
+ return 0;
+}
+
+
+bool Item_time_typecast::get_time(TIME *ltime)
+{
+ bool res= get_arg0_time(ltime);
+ ltime->time_type= TIMESTAMP_TIME;
+ return res;
+}
+
+
+String *Item_time_typecast::val_str(String *str)
+{
+ TIME ltime;
+
+ if (!get_arg0_time(&ltime) &&
+ make_datetime(str, &ltime, ltime.second_part ? TIME_MICROSECOND : TIME_ONLY))
+ return str;
+
+ null_value=1;
+ return 0;
+}
+
+
+bool Item_date_typecast::get_date(TIME *ltime, bool fuzzy_date)
+{
+ bool res= get_arg0_date(ltime,1);
+ ltime->time_type= TIMESTAMP_DATE;
+ return res;
+}
+
+
+String *Item_date_typecast::val_str(String *str)
+{
+ TIME ltime;
+
+ if (!get_arg0_date(&ltime,1) &&
+ make_datetime(str, &ltime, DATE_ONLY))
+ return str;
+
+null_date:
+ null_value=1;
+ return 0;
+}
+
+/*
+ MAKEDATE(a,b) is a date function that creates a date value
+ from a year and day value.
+*/
+
+String *Item_func_makedate::val_str(String *str)
+{
+ TIME l_time;
+ long daynr= args[1]->val_int();
+ long yearnr= args[0]->val_int();
+ long days;
+
+ if (args[0]->null_value || args[1]->null_value ||
+ yearnr < 0 || daynr <= 0)
+ goto null_date;
+
+ days= calc_daynr(yearnr,1,1) + daynr - 1;
+ if (days > 0 || days < MAX_DAY_NUMBER) // Day number from year 0 to 9999-12-31
+ {
+ null_value=0;
+ get_date_from_daynr(days,&l_time.year,&l_time.month,&l_time.day);
+ if (make_datetime(str, &l_time, DATE_ONLY))
+ return str;
+ }
+
+null_date:
+ null_value=1;
+ return 0;
+}
+
+
+void Item_func_add_time::fix_length_and_dec()
+{
+ enum_field_types arg0_field_type;
+ decimals=0;
+ max_length=26*MY_CHARSET_BIN_MB_MAXLEN;
+
+ /*
+ The field type for the result of an Item_func_add_time function is defined as
+ follows:
+
+ - If first arg is a MYSQL_TYPE_DATETIME or MYSQL_TYPE_TIMESTAMP
+ result is MYSQL_TYPE_DATETIME
+ - If first arg is a MYSQL_TYPE_TIME result is MYSQL_TYPE_TIME
+ - Otherwise the result is MYSQL_TYPE_STRING
+ */
+
+ cached_field_type= MYSQL_TYPE_STRING;
+ arg0_field_type= args[0]->field_type();
+ if (arg0_field_type == MYSQL_TYPE_DATE ||
+ arg0_field_type == MYSQL_TYPE_DATETIME ||
+ arg0_field_type == MYSQL_TYPE_TIMESTAMP)
+ cached_field_type= MYSQL_TYPE_DATETIME;
+ else if (arg0_field_type == MYSQL_TYPE_TIME)
+ cached_field_type= MYSQL_TYPE_TIME;
+}
+
+/*
+ ADDTIME(t,a) and SUBTIME(t,a) are time functions that calculate a time/datetime value
+
+ t: time_or_datetime_expression
+ a: time_expression
+
+ Result: Time value or datetime value
+*/
+
+String *Item_func_add_time::val_str(String *str)
+{
+ TIME l_time1, l_time2, l_time3;
+ bool is_time= 0;
+ long microseconds, seconds, days= 0;
+ int l_sign= sign;
+
+ null_value=0;
+ l_time3.neg= 0;
+ if (is_date) // TIMESTAMP function
+ {
+ if (get_arg0_date(&l_time1,1) ||
+ args[1]->get_time(&l_time2) ||
+ l_time1.time_type == TIMESTAMP_TIME ||
+ l_time2.time_type != TIMESTAMP_TIME)
+ goto null_date;
+ }
+ else // ADDTIME function
+ {
+ if (args[0]->get_time(&l_time1) ||
+ args[1]->get_time(&l_time2) ||
+ l_time2.time_type == TIMESTAMP_FULL)
+ goto null_date;
+ is_time= (l_time1.time_type == TIMESTAMP_TIME);
+ if (is_time && (l_time2.neg == l_time1.neg && l_time1.neg))
+ l_time3.neg= 1;
+ }
+ if (l_time1.neg != l_time2.neg)
+ l_sign= -l_sign;
+
+ microseconds= l_time1.second_part + l_sign*l_time2.second_part;
+ seconds= (l_time1.hour*3600L + l_time1.minute*60L + l_time1.second +
+ (l_time2.day*86400L + l_time2.hour*3600L +
+ l_time2.minute*60L + l_time2.second)*l_sign);
+ if (is_time)
+ seconds+= l_time1.day*86400L;
+ else
+ days+= calc_daynr((uint) l_time1.year,(uint) l_time1.month, (uint) l_time1.day);
+ seconds= seconds + microseconds/1000000L;
+ microseconds= microseconds%1000000L;
+ days+= seconds/86400L;
+ seconds= seconds%86400L;
+
+ if (microseconds < 0)
+ {
+ microseconds+= 1000000L;
+ seconds--;
+ }
+ if (seconds < 0)
+ {
+ days+= seconds/86400L - 1;
+ seconds+= 86400L;
+ }
+ if (days < 0)
+ {
+ if (!is_time)
+ goto null_date;
+ if (microseconds)
+ {
+ microseconds= 1000000L - microseconds;
+ seconds++;
+ }
+ seconds= 86400L - seconds;
+ days= -(++days);
+ l_time3.neg= 1;
+ }
+
+ calc_time_from_sec(&l_time3, seconds, microseconds);
+ if (!is_time)
+ {
+ get_date_from_daynr(days,&l_time3.year,&l_time3.month,&l_time3.day);
+ if (l_time3.day &&
+ make_datetime(str, &l_time3,
+ l_time1.second_part || l_time2.second_part ?
+ DATE_TIME_MICROSECOND : DATE_TIME))
+ return str;
+ goto null_date;
+ }
+
+ l_time3.hour+= days*24;
+ if (make_datetime(str, &l_time3,
+ l_time1.second_part || l_time2.second_part ?
+ TIME_MICROSECOND : TIME_ONLY))
+ return str;
+
+null_date:
+ null_value=1;
+ return 0;
+}
+
+/*
+ TIMEDIFF(t,s) is a time function that calculates the
+ time value between a start and end time.
+
+ t and s: time_or_datetime_expression
+ Result: Time value
+*/
+
+String *Item_func_timediff::val_str(String *str)
+{
+ longlong seconds;
+ long microseconds;
+ long days;
+ int l_sign= 1;
+ TIME l_time1 ,l_time2, l_time3;
+
+ null_value= 0;
+ if (args[0]->get_time(&l_time1) ||
+ args[1]->get_time(&l_time2) ||
+ l_time1.time_type != l_time2.time_type)
+ goto null_date;
+
+ if (l_time1.neg != l_time2.neg)
+ l_sign= -l_sign;
+
+ if (l_time1.time_type == TIMESTAMP_TIME) // Time value
+ days= l_time1.day - l_sign*l_time2.day;
+ else // DateTime value
+ days= (calc_daynr((uint) l_time1.year,
+ (uint) l_time1.month,
+ (uint) l_time1.day) -
+ l_sign*calc_daynr((uint) l_time2.year,
+ (uint) l_time2.month,
+ (uint) l_time2.day));
+
+ microseconds= l_time1.second_part - l_sign*l_time2.second_part;
+ seconds= ((longlong) days*86400L + l_time1.hour*3600L +
+ l_time1.minute*60L + l_time1.second + microseconds/1000000L -
+ (longlong)l_sign*(l_time2.hour*3600L+l_time2.minute*60L+l_time2.second));
+
+ l_time3.neg= 0;
+ if (seconds < 0)
+ {
+ seconds= -seconds;
+ l_time3.neg= 1;
+ }
+ else if (seconds == 0 && microseconds < 0)
+ {
+ microseconds= -microseconds;
+ l_time3.neg= 1;
+ }
+ if (microseconds < 0)
+ {
+ microseconds+= 1000000L;
+ seconds--;
+ }
+ if ((l_time2.neg == l_time1.neg) && l_time1.neg)
+ l_time3.neg= l_time3.neg ? 0 : 1;
+
+ calc_time_from_sec(&l_time3, seconds, microseconds);
+ if (make_datetime(str, &l_time3,
+ l_time1.second_part || l_time2.second_part ?
+ TIME_MICROSECOND : TIME_ONLY))
+ return str;
+
+null_date:
+ null_value=1;
+ return 0;
+}
+
+/*
+ MAKETIME(h,m,s) is a time function that calculates a time value
+ from the total number of hours, minutes, and seconds.
+ Result: Time value
+*/
+
+String *Item_func_maketime::val_str(String *str)
+{
+ TIME ltime;
+
+ long hour= args[0]->val_int();
+ long minute= args[1]->val_int();
+ long second= args[2]->val_int();
+
+ if ((null_value=(args[0]->null_value ||
+ args[1]->null_value ||
+ args[2]->null_value ||
+ minute > 59 || minute < 0 ||
+ second > 59 || second < 0)))
+ goto null_date;
+
+ ltime.neg= 0;
+ if (hour < 0)
+ {
+ ltime.neg= 1;
+ hour= -hour;
+ }
+ ltime.hour= (ulong)hour;
+ ltime.minute= (ulong)minute;
+ ltime.second= (ulong)second;
+ if (make_datetime(str, &ltime, TIME_ONLY))
+ return str;
+
+null_date:
+ return 0;
+}
+
+/*
+ MICROSECOND(a) is a function ( extraction) that extracts the microseconds from a.
+
+ a: Datetime or time value
+ Result: int value
+*/
+longlong Item_func_microsecond::val_int()
+{
+ TIME ltime;
+ if (!get_arg0_time(&ltime))
+ return ltime.second_part;
+ return 0;
+}
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index 87563cf9f47..20b95f8e22d 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -478,9 +478,10 @@ public:
enum interval_type
{
INTERVAL_YEAR, INTERVAL_MONTH, INTERVAL_DAY, INTERVAL_HOUR, INTERVAL_MINUTE,
- INTERVAL_SECOND, INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR, INTERVAL_DAY_MINUTE,
- INTERVAL_DAY_SECOND, INTERVAL_HOUR_MINUTE, INTERVAL_HOUR_SECOND,
- INTERVAL_MINUTE_SECOND
+ INTERVAL_SECOND, INTERVAL_MICROSECOND ,INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR,
+ INTERVAL_DAY_MINUTE, INTERVAL_DAY_SECOND, INTERVAL_HOUR_MINUTE,
+ INTERVAL_HOUR_SECOND, INTERVAL_MINUTE_SECOND, INTERVAL_DAY_MICROSECOND,
+ INTERVAL_HOUR_MICROSECOND, INTERVAL_MINUTE_MICROSECOND, INTERVAL_SECOND_MICROSECOND
};
@@ -556,6 +557,8 @@ class Item_date_typecast :public Item_typecast
{
public:
Item_date_typecast(Item *a) :Item_typecast(a) {}
+ String *val_str(String *str);
+ bool get_date(TIME *ltime, bool fuzzy_date);
const char *func_name() const { return "date"; }
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
Field *tmp_table_field() { return result_field; }
@@ -570,6 +573,8 @@ class Item_time_typecast :public Item_typecast
{
public:
Item_time_typecast(Item *a) :Item_typecast(a) {}
+ String *val_str(String *str);
+ bool get_time(TIME *ltime);
const char *func_name() const { return "time"; }
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
Field *tmp_table_field() { return result_field; }
@@ -584,6 +589,7 @@ class Item_datetime_typecast :public Item_typecast
{
public:
Item_datetime_typecast(Item *a) :Item_typecast(a) {}
+ String *val_str(String *str);
const char *func_name() const { return "datetime"; }
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
Field *tmp_table_field() { return result_field; }
@@ -592,3 +598,106 @@ public:
return (new Field_datetime(maybe_null, name, t_arg, default_charset()));
}
};
+
+class Item_func_makedate :public Item_str_func
+{
+public:
+ Item_func_makedate(Item *a,Item *b) :Item_str_func(a,b) {}
+ String *val_str(String *str);
+ const char *func_name() const { return "makedate"; }
+ enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=8*MY_CHARSET_BIN_MB_MAXLEN;
+ }
+ Field *tmp_table_field() { return result_field; }
+ Field *tmp_table_field(TABLE *t_arg)
+ {
+ return (new Field_date(maybe_null, name, t_arg, &my_charset_bin));
+ }
+};
+
+
+class Item_func_add_time :public Item_str_func
+{
+ const bool is_date;
+ int sign;
+ enum_field_types cached_field_type;
+
+public:
+ Item_func_add_time(Item *a, Item *b, bool type_arg, bool neg_arg)
+ :Item_str_func(a, b), is_date(type_arg) { sign= neg_arg ? -1 : 1; }
+ String *val_str(String *str);
+ const char *func_name() const { return "addtime"; }
+ enum_field_types field_type() const { return cached_field_type; }
+ void fix_length_and_dec();
+
+/*
+ TODO:
+ Change this when we support
+ microseconds in TIME/DATETIME
+*/
+ Field *tmp_table_field() { return result_field; }
+ Field *tmp_table_field(TABLE *t_arg)
+ {
+ if (cached_field_type == MYSQL_TYPE_TIME)
+ return (new Field_time(maybe_null, name, t_arg, &my_charset_bin));
+ else if (cached_field_type == MYSQL_TYPE_DATETIME)
+ return (new Field_datetime(maybe_null, name, t_arg, &my_charset_bin));
+ return (new Field_string(max_length, maybe_null, name, t_arg, &my_charset_bin));
+ }
+};
+
+class Item_func_timediff :public Item_str_func
+{
+public:
+ Item_func_timediff(Item *a, Item *b)
+ :Item_str_func(a, b) {}
+ String *val_str(String *str);
+ const char *func_name() const { return "timediff"; }
+ enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=17*MY_CHARSET_BIN_MB_MAXLEN;
+ }
+ Field *tmp_table_field() { return result_field; }
+ Field *tmp_table_field(TABLE *t_arg)
+ {
+ return (new Field_time(maybe_null, name, t_arg, &my_charset_bin));
+ }
+};
+
+class Item_func_maketime :public Item_str_func
+{
+public:
+ Item_func_maketime(Item *a, Item *b, Item *c)
+ :Item_str_func(a, b ,c) {}
+ String *val_str(String *str);
+ const char *func_name() const { return "maketime"; }
+ enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=8*MY_CHARSET_BIN_MB_MAXLEN;
+ }
+ Field *tmp_table_field() { return result_field; }
+ Field *tmp_table_field(TABLE *t_arg)
+ {
+ return (new Field_time(maybe_null, name, t_arg, &my_charset_bin));
+ }
+};
+
+class Item_func_microsecond :public Item_int_func
+{
+public:
+ Item_func_microsecond(Item *a) :Item_int_func(a) {}
+ longlong val_int();
+ const char *func_name() const { return "microsecond"; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ maybe_null=1;
+ }
+};
diff --git a/sql/lex.h b/sql/lex.h
index f105fd4d9c8..d177a17eae8 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -116,6 +116,7 @@ static SYMBOL symbols[] = {
{ "DATETIME", SYM(DATETIME),0,0},
{ "DAY", SYM(DAY_SYM),0,0},
{ "DAY_HOUR", SYM(DAY_HOUR_SYM),0,0},
+ { "DAY_MICROSECOND", SYM(DAY_MICROSECOND_SYM),0,0},
{ "DAY_MINUTE", SYM(DAY_MINUTE_SYM),0,0},
{ "DAY_SECOND", SYM(DAY_SECOND_SYM),0,0},
{ "DEC", SYM(DECIMAL_SYM),0,0},
@@ -186,6 +187,7 @@ static SYMBOL symbols[] = {
{ "HELP", SYM(HELP_SYM),0,0},
{ "HIGH_PRIORITY", SYM(HIGH_PRIORITY),0,0},
{ "HOUR", SYM(HOUR_SYM),0,0},
+ { "HOUR_MICROSECOND", SYM(HOUR_MICROSECOND_SYM),0,0},
{ "HOUR_MINUTE", SYM(HOUR_MINUTE_SYM),0,0},
{ "HOUR_SECOND", SYM(HOUR_SECOND_SYM),0,0},
{ "HOSTS", SYM(HOSTS_SYM),0,0},
@@ -259,9 +261,11 @@ static SYMBOL symbols[] = {
{ "MERGE", SYM(MERGE_SYM),0,0},
{ "MEDIUM", SYM(MEDIUM_SYM),0,0},
{ "MEMORY", SYM(MEMORY_SYM),0,0},
+ { "MICROSECOND", SYM(MICROSECOND_SYM),0,0},
{ "MIDDLEINT", SYM(MEDIUMINT),0,0}, /* For powerbuilder */
{ "MIN_ROWS", SYM(MIN_ROWS),0,0},
{ "MINUTE", SYM(MINUTE_SYM),0,0},
+ { "MINUTE_MICROSECOND", SYM(MINUTE_MICROSECOND_SYM),0,0},
{ "MINUTE_SECOND", SYM(MINUTE_SECOND_SYM),0,0},
{ "MOD", SYM(MOD_SYM),0,0},
{ "MODE", SYM(MODE_SYM),0,0},
@@ -338,6 +342,7 @@ static SYMBOL symbols[] = {
{ "ROWS", SYM(ROWS_SYM),0,0},
{ "RTREE", SYM(RTREE_SYM),0,0},
{ "SECOND", SYM(SECOND_SYM),0,0},
+ { "SECOND_MICROSECOND", SYM(SECOND_MICROSECOND_SYM),0,0},
{ "SEPARATOR", SYM(SEPARATOR_SYM),0,0},
{ "SELECT", SYM(SELECT_SYM),0,0},
{ "SERIAL", SYM(SERIAL_SYM),0,0},
@@ -428,7 +433,8 @@ static SYMBOL symbols[] = {
static SYMBOL sql_functions[] = {
{ "ABS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_abs)},
{ "ACOS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_acos)},
- { "ADDDATE", SYM(DATE_ADD_INTERVAL),0,0},
+ { "ADDDATE", SYM(ADDDATE_SYM),0,0},
+ { "ADDTIME", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_addtime)},
{ "AES_ENCRYPT", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_aes_encrypt)},
{ "AES_DECRYPT", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_aes_decrypt)},
{ "AREA", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_area)},
@@ -471,6 +477,7 @@ static SYMBOL sql_functions[] = {
{ "CURDATE", SYM(CURDATE),0,0},
{ "CURTIME", SYM(CURTIME),0,0},
{ "DATE_ADD", SYM(DATE_ADD_INTERVAL),0,0},
+ { "DATEDIFF", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_datediff)},
{ "DATE_FORMAT", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_date_format)},
{ "DATE_SUB", SYM(DATE_SUB_INTERVAL),0,0},
{ "DAYNAME", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_dayname)},
@@ -546,6 +553,8 @@ static SYMBOL sql_functions[] = {
{ "LPAD", SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_lpad)},
{ "LTRIM", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ltrim)},
{ "MAKE_SET", SYM(MAKE_SET_SYM),0,0},
+ { "MAKEDATE", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_makedate)},
+ { "MAKETIME", SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_maketime)},
{ "MASTER_POS_WAIT", SYM(MASTER_POS_WAIT),0,0},
{ "MAX", SYM(MAX_SYM),0,0},
{ "MBRCONTAINS", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_contains)},
@@ -605,7 +614,7 @@ static SYMBOL sql_functions[] = {
{ "RTRIM", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_rtrim)},
{ "SEC_TO_TIME", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sec_to_time)},
{ "SESSION_USER", SYM(USER),0,0},
- { "SUBDATE", SYM(DATE_SUB_INTERVAL),0,0},
+ { "SUBDATE", SYM(SUBDATE_SYM),0,0},
{ "SIGN", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sign)},
{ "SIN", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sin)},
{ "SHA", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sha)},
@@ -620,12 +629,14 @@ static SYMBOL sql_functions[] = {
{ "STRCMP", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_strcmp)},
{ "SUBSTRING", SYM(SUBSTRING),0,0},
{ "SUBSTRING_INDEX", SYM(SUBSTRING_INDEX),0,0},
+ { "SUBTIME", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_subtime)},
{ "SUM", SYM(SUM_SYM),0,0},
{ "SYSDATE", SYM(NOW_SYM),0,0},
{ "SYSTEM_USER", SYM(USER),0,0},
{ "TAN", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_tan)},
{ "TIME_FORMAT", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_time_format)},
{ "TIME_TO_SEC", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_time_to_sec)},
+ { "TIMEDIFF", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_timediff)},
{ "TO_DAYS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_to_days)},
{ "TOUCHES", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_touches)},
{ "TRIM", SYM(TRIM),0,0},
@@ -639,6 +650,7 @@ static SYMBOL sql_functions[] = {
{ "VERSION", SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_version)},
{ "WEEK", SYM(WEEK_SYM),0,0},
{ "WEEKDAY", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekday)},
+ { "WEEKOFYEAR", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekofyear)},
{ "WITHIN", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_within)},
{ "X", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_x)},
{ "Y", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_y)},
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index bd77761e2eb..90cf2a62bf6 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -221,6 +221,8 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
#define RAID_BLOCK_SIZE 1024
+#define MY_CHARSET_BIN_MB_MAXLEN 1
+
#ifdef EXTRA_DEBUG
/*
Sync points allow us to force the server to reach a certain line of code
@@ -554,6 +556,7 @@ void free_prep_stmt(PREP_STMT *stmt, TREE_FREE mode, void *not_used);
bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length);
void mysql_stmt_execute(THD *thd, char *packet);
void mysql_stmt_free(THD *thd, char *packet);
+void mysql_stmt_reset(THD *thd, char *packet);
void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length);
int check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
List<Item> &values, ulong counter);
@@ -767,6 +770,7 @@ extern rw_lock_t LOCK_grant;
extern pthread_cond_t COND_refresh, COND_thread_count, COND_manager;
extern pthread_attr_t connection_attrib;
extern I_List<THD> threads;
+extern I_List<NAMED_LIST> key_caches;
extern MY_BITMAP temp_pool;
extern DATE_FORMAT dayord;
extern String empty_string;
@@ -848,6 +852,7 @@ longlong str_to_datetime(const char *str,uint length,bool fuzzy_date);
timestamp_type str_to_TIME(const char *str, uint length, TIME *l_time,
bool fuzzy_date);
void localtime_to_TIME(TIME *to, struct tm *from);
+void calc_time_from_sec(TIME *to, long seconds, long microseconds);
int test_if_number(char *str,int *res,bool allow_wildcards);
void change_byte(byte *,uint,char,char);
@@ -900,9 +905,10 @@ extern void sql_cache_free();
extern int sql_cache_hit(THD *thd, char *inBuf, uint length);
/* item.cc */
-Item *get_system_var(enum_var_type var_type, LEX_STRING name);
-Item *get_system_var(enum_var_type var_type, const char *var_name, uint length,
- const char *item_name);
+Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
+ LEX_STRING component);
+Item *get_system_var(THD *thd, enum_var_type var_type, const char *var_name,
+ uint length, const char *item_name);
/* log.cc */
bool flush_error_log(void);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 02db7d4fd9a..cfe2605ed62 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -313,11 +313,12 @@ const char *sql_mode_str="OFF";
FILE *bootstrap_file;
-I_List <i_string_pair> replicate_rewrite_db;
+I_List<i_string_pair> replicate_rewrite_db;
I_List<i_string> replicate_do_db, replicate_ignore_db;
// allow the user to tell us which db to replicate and which to ignore
I_List<i_string> binlog_do_db, binlog_ignore_db;
I_List<THD> threads,thread_cache;
+I_List<NAMED_LIST> key_caches;
struct system_variables global_system_variables;
struct system_variables max_system_variables;
@@ -876,6 +877,7 @@ void clean_up(bool print_message)
#endif
(void) ha_panic(HA_PANIC_CLOSE); /* close all tables and logs */
end_key_cache();
+ delete_elements(&key_caches, free_key_cache);
end_thr_alarm(1); /* Free allocated memory */
#ifdef USE_RAID
end_raid();
@@ -4101,7 +4103,7 @@ replicating a LOAD DATA INFILE command.",
REQUIRED_ARG, 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ~0L, MALLOC_OVERHEAD,
IO_SIZE, 0},
{"key_buffer_size", OPT_KEY_BUFFER_SIZE,
- "The size of the buffer used for index blocks. Increase this to get better index handling (for all reads and multiple writes) to as much as you can afford; 64M on a 256M machine that mainly runs MySQL is quite common.",
+ "The size of the buffer used for index blocks for MyISAM tables. Increase this to get better index handling (for all reads and multiple writes) to as much as you can afford; 64M on a 256M machine that mainly runs MySQL is quite common.",
(gptr*) &keybuff_size, (gptr*) &keybuff_size, 0,
(enum get_opt_var_type) (GET_ULL | GET_ASK_ADDR),
REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, (long) ~0, MALLOC_OVERHEAD,
@@ -4678,6 +4680,9 @@ static void mysql_init_variables(void)
my_bind_addr = htonl(INADDR_ANY);
threads.empty();
thread_cache.empty();
+ key_caches.empty();
+ if (!get_or_create_key_cache("default", 7))
+ exit(1);
/* Initialize structures that is used when processing options */
replicate_rewrite_db.empty();
@@ -5306,16 +5311,30 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
}
return 0;
}
- /* Initiates DEBUG - but no debugging here ! */
extern "C" gptr *
-mysql_getopt_value(char *keyname, uint key_length,
+mysql_getopt_value(const char *keyname, uint key_length,
const struct my_option *option)
{
+ if (!key_length)
+ {
+ keyname= "default";
+ key_length= 7;
+ }
+ switch (option->id) {
+ case OPT_KEY_BUFFER_SIZE:
+ {
+ KEY_CACHE *key_cache;
+ if (!(key_cache= get_or_create_key_cache(keyname, key_length)))
+ exit(1);
+ return (gptr*) &key_cache->size;
+ }
+ }
return option->value;
}
+
static void get_options(int argc,char **argv)
{
int ho_error;
@@ -5363,6 +5382,8 @@ static void get_options(int argc,char **argv)
table_alias_charset= (lower_case_table_names ?
files_charset_info :
&my_charset_bin);
+ /* QQ To be deleted when we have key cache variables in a struct */
+ keybuff_size= (((KEY_CACHE *) find_named(&key_caches, "default", 7))->size);
}
@@ -5577,6 +5598,6 @@ template class I_List<THD>;
template class I_List_iterator<THD>;
template class I_List<i_string>;
template class I_List<i_string_pair>;
-
+template class I_List<NAMED_LIST>;
FIX_GCC_LINKING_PROBLEM
#endif
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 1a1d1f0a585..1b9256c7723 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -823,6 +823,13 @@ bool Protocol_simple::store(Field *field)
}
+/*
+ TODO:
+ Second_part format ("%06") needs to change when
+ we support 0-6 decimals for time.
+*/
+
+
bool Protocol_simple::store(TIME *tm)
{
#ifndef DEBUG_OFF
@@ -840,6 +847,8 @@ bool Protocol_simple::store(TIME *tm)
(int) tm->hour,
(int) tm->minute,
(int) tm->second));
+ if (tm->second_part)
+ length+= my_sprintf(buff+length,(buff+length, ".%06d", (int)tm->second_part));
return net_store_data((char*) buff, length);
}
@@ -861,6 +870,12 @@ bool Protocol_simple::store_date(TIME *tm)
}
+/*
+ TODO:
+ Second_part format ("%06") needs to change when
+ we support 0-6 decimals for time.
+*/
+
bool Protocol_simple::store_time(TIME *tm)
{
#ifndef DEBUG_OFF
@@ -876,6 +891,8 @@ bool Protocol_simple::store_time(TIME *tm)
(long) day*24L+(long) tm->hour,
(int) tm->minute,
(int) tm->second));
+ if (tm->second_part)
+ length+= my_sprintf(buff+length,(buff+length, ".%06d", (int)tm->second_part));
return net_store_data((char*) buff, length);
}
diff --git a/sql/set_var.cc b/sql/set_var.cc
index a4ecf24d09f..31706b21734 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -86,9 +86,9 @@ static void fix_net_retry_count(THD *thd, enum_var_type type);
static void fix_max_join_size(THD *thd, enum_var_type type);
static void fix_query_cache_size(THD *thd, enum_var_type type);
static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type);
-static void fix_key_buffer_size(THD *thd, enum_var_type type);
static void fix_myisam_max_extra_sort_file_size(THD *thd, enum_var_type type);
static void fix_myisam_max_sort_file_size(THD *thd, enum_var_type type);
+static KEY_CACHE *create_key_cache(const char *name, uint length);
void fix_sql_mode_var(THD *thd, enum_var_type type);
static byte *get_error_count(THD *thd);
static byte *get_warning_count(THD *thd);
@@ -136,9 +136,7 @@ sys_var_thd_ulong sys_interactive_timeout("interactive_timeout",
&SV::net_interactive_timeout);
sys_var_thd_ulong sys_join_buffer_size("join_buffer_size",
&SV::join_buff_size);
-sys_var_ulonglong_ptr sys_key_buffer_size("key_buffer_size",
- &keybuff_size,
- fix_key_buffer_size);
+sys_var_key_buffer_size sys_key_buffer_size("key_buffer_size");
sys_var_bool_ptr sys_local_infile("local_infile",
&opt_local_infile);
sys_var_thd_bool sys_log_warnings("log_warnings", &SV::log_warnings);
@@ -799,12 +797,6 @@ static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type)
#endif
-static void fix_key_buffer_size(THD *thd, enum_var_type type)
-{
- ha_resize_key_cache();
-}
-
-
void fix_delay_key_write(THD *thd, enum_var_type type)
{
switch ((enum_delay_key_write) delay_key_write_options) {
@@ -876,7 +868,7 @@ bool sys_var_enum::update(THD *thd, set_var *var)
}
-byte *sys_var_enum::value_ptr(THD *thd, enum_var_type type)
+byte *sys_var_enum::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base)
{
return (byte*) enum_names->type_names[*value];
}
@@ -912,7 +904,8 @@ void sys_var_thd_ulong::set_default(THD *thd, enum_var_type type)
}
-byte *sys_var_thd_ulong::value_ptr(THD *thd, enum_var_type type)
+byte *sys_var_thd_ulong::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
{
if (type == OPT_GLOBAL)
return (byte*) &(global_system_variables.*offset);
@@ -957,7 +950,8 @@ void sys_var_thd_ha_rows::set_default(THD *thd, enum_var_type type)
}
-byte *sys_var_thd_ha_rows::value_ptr(THD *thd, enum_var_type type)
+byte *sys_var_thd_ha_rows::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
{
if (type == OPT_GLOBAL)
return (byte*) &(global_system_variables.*offset);
@@ -1000,7 +994,8 @@ void sys_var_thd_ulonglong::set_default(THD *thd, enum_var_type type)
}
-byte *sys_var_thd_ulonglong::value_ptr(THD *thd, enum_var_type type)
+byte *sys_var_thd_ulonglong::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
{
if (type == OPT_GLOBAL)
return (byte*) &(global_system_variables.*offset);
@@ -1027,7 +1022,8 @@ void sys_var_thd_bool::set_default(THD *thd, enum_var_type type)
}
-byte *sys_var_thd_bool::value_ptr(THD *thd, enum_var_type type)
+byte *sys_var_thd_bool::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
{
if (type == OPT_GLOBAL)
return (byte*) &(global_system_variables.*offset);
@@ -1121,7 +1117,7 @@ err:
to create an item that gets the current value at fix_fields() stage.
*/
-Item *sys_var::item(THD *thd, enum_var_type var_type)
+Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base)
{
if (check_type(var_type))
{
@@ -1137,16 +1133,16 @@ Item *sys_var::item(THD *thd, enum_var_type var_type)
}
switch (type()) {
case SHOW_LONG:
- return new Item_uint((int32) *(ulong*) value_ptr(thd, var_type));
+ return new Item_uint((int32) *(ulong*) value_ptr(thd, var_type, base));
case SHOW_LONGLONG:
- return new Item_int(*(longlong*) value_ptr(thd, var_type));
+ return new Item_int(*(longlong*) value_ptr(thd, var_type, base));
case SHOW_HA_ROWS:
- return new Item_int((longlong) *(ha_rows*) value_ptr(thd, var_type));
+ return new Item_int((longlong) *(ha_rows*) value_ptr(thd, var_type, base));
case SHOW_MY_BOOL:
- return new Item_int((int32) *(my_bool*) value_ptr(thd, var_type),1);
+ return new Item_int((int32) *(my_bool*) value_ptr(thd, var_type, base),1);
case SHOW_CHAR:
{
- char *str= (char*) value_ptr(thd, var_type);
+ char *str= (char*) value_ptr(thd, var_type, base);
return new Item_string(str, strlen(str), system_charset_info);
}
default:
@@ -1175,7 +1171,8 @@ void sys_var_thd_enum::set_default(THD *thd, enum_var_type type)
}
-byte *sys_var_thd_enum::value_ptr(THD *thd, enum_var_type type)
+byte *sys_var_thd_enum::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
{
ulong tmp= ((type == OPT_GLOBAL) ?
global_system_variables.*offset :
@@ -1192,7 +1189,8 @@ bool sys_var_thd_bit::update(THD *thd, set_var *var)
}
-byte *sys_var_thd_bit::value_ptr(THD *thd, enum_var_type type)
+byte *sys_var_thd_bit::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
{
/*
If reverse is 0 (default) return 1 if bit is set.
@@ -1255,6 +1253,7 @@ bool sys_var_collation::check(THD *thd, set_var *var)
return 0;
}
+
bool sys_var_character_set::check(THD *thd, set_var *var)
{
CHARSET_INFO *tmp;
@@ -1280,20 +1279,24 @@ bool sys_var_character_set::check(THD *thd, set_var *var)
return 0;
}
+
bool sys_var_character_set::update(THD *thd, set_var *var)
{
ci_ptr(thd,var->type)[0]= var->save_result.charset;
return 0;
}
-byte *sys_var_character_set::value_ptr(THD *thd, enum_var_type type)
+
+byte *sys_var_character_set::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
{
CHARSET_INFO *cs= ci_ptr(thd,type)[0];
return cs ? (byte*) cs->csname : (byte*) "NULL";
}
-CHARSET_INFO ** sys_var_character_set_connection::ci_ptr(THD *thd, enum_var_type type)
+CHARSET_INFO ** sys_var_character_set_connection::ci_ptr(THD *thd,
+ enum_var_type type)
{
if (type == OPT_GLOBAL)
return &global_system_variables.collation_connection;
@@ -1301,7 +1304,9 @@ CHARSET_INFO ** sys_var_character_set_connection::ci_ptr(THD *thd, enum_var_type
return &thd->variables.collation_connection;
}
-void sys_var_character_set_connection::set_default(THD *thd, enum_var_type type)
+
+void sys_var_character_set_connection::set_default(THD *thd,
+ enum_var_type type)
{
if (type == OPT_GLOBAL)
global_system_variables.collation_connection= default_charset_info;
@@ -1310,7 +1315,8 @@ void sys_var_character_set_connection::set_default(THD *thd, enum_var_type type)
}
-CHARSET_INFO ** sys_var_character_set_client::ci_ptr(THD *thd, enum_var_type type)
+CHARSET_INFO ** sys_var_character_set_client::ci_ptr(THD *thd,
+ enum_var_type type)
{
if (type == OPT_GLOBAL)
return &global_system_variables.character_set_client;
@@ -1318,6 +1324,7 @@ CHARSET_INFO ** sys_var_character_set_client::ci_ptr(THD *thd, enum_var_type typ
return &thd->variables.character_set_client;
}
+
void sys_var_character_set_client::set_default(THD *thd, enum_var_type type)
{
if (type == OPT_GLOBAL)
@@ -1326,6 +1333,7 @@ void sys_var_character_set_client::set_default(THD *thd, enum_var_type type)
thd->variables.character_set_client= global_system_variables.character_set_client;
}
+
CHARSET_INFO ** sys_var_character_set_results::ci_ptr(THD *thd, enum_var_type type)
{
if (type == OPT_GLOBAL)
@@ -1334,6 +1342,7 @@ CHARSET_INFO ** sys_var_character_set_results::ci_ptr(THD *thd, enum_var_type ty
return &thd->variables.character_set_results;
}
+
void sys_var_character_set_results::set_default(THD *thd, enum_var_type type)
{
if (type == OPT_GLOBAL)
@@ -1342,6 +1351,7 @@ void sys_var_character_set_results::set_default(THD *thd, enum_var_type type)
thd->variables.character_set_results= global_system_variables.character_set_results;
}
+
CHARSET_INFO ** sys_var_character_set_server::ci_ptr(THD *thd, enum_var_type type)
{
if (type == OPT_GLOBAL)
@@ -1350,6 +1360,7 @@ CHARSET_INFO ** sys_var_character_set_server::ci_ptr(THD *thd, enum_var_type typ
return &thd->variables.character_set_server;
}
+
void sys_var_character_set_server::set_default(THD *thd, enum_var_type type)
{
if (type == OPT_GLOBAL)
@@ -1358,7 +1369,9 @@ void sys_var_character_set_server::set_default(THD *thd, enum_var_type type)
thd->variables.character_set_server= global_system_variables.character_set_server;
}
-CHARSET_INFO ** sys_var_character_set_database::ci_ptr(THD *thd, enum_var_type type)
+
+CHARSET_INFO ** sys_var_character_set_database::ci_ptr(THD *thd,
+ enum_var_type type)
{
if (type == OPT_GLOBAL)
return &global_system_variables.character_set_database;
@@ -1366,6 +1379,7 @@ CHARSET_INFO ** sys_var_character_set_database::ci_ptr(THD *thd, enum_var_type t
return &thd->variables.character_set_database;
}
+
void sys_var_character_set_database::set_default(THD *thd, enum_var_type type)
{
if (type == OPT_GLOBAL)
@@ -1374,6 +1388,7 @@ void sys_var_character_set_database::set_default(THD *thd, enum_var_type type)
thd->variables.character_set_database= thd->db_charset;
}
+
bool sys_var_collation_connection::update(THD *thd, set_var *var)
{
if (var->type == OPT_GLOBAL)
@@ -1383,7 +1398,9 @@ bool sys_var_collation_connection::update(THD *thd, set_var *var)
return 0;
}
-byte *sys_var_collation_connection::value_ptr(THD *thd, enum_var_type type)
+
+byte *sys_var_collation_connection::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
{
CHARSET_INFO *cs= ((type == OPT_GLOBAL) ?
global_system_variables.collation_connection :
@@ -1391,6 +1408,7 @@ byte *sys_var_collation_connection::value_ptr(THD *thd, enum_var_type type)
return cs ? (byte*) cs->name : (byte*) "NULL";
}
+
void sys_var_collation_connection::set_default(THD *thd, enum_var_type type)
{
if (type == OPT_GLOBAL)
@@ -1400,6 +1418,71 @@ void sys_var_collation_connection::set_default(THD *thd, enum_var_type type)
}
+bool sys_var_key_buffer_size::update(THD *thd, set_var *var)
+{
+ ulonglong tmp= var->value->val_int();
+ if (!base_name.length)
+ {
+ base_name.str= (char*) "default";
+ base_name.length= 7;
+ }
+ KEY_CACHE *key_cache= (KEY_CACHE*) find_named(&key_caches, base_name.str,
+ base_name.length);
+ if (!key_cache)
+ {
+ if (!tmp) // Tried to delete cache
+ return 0; // Ok, nothing to do
+ if (!(key_cache= create_key_cache(base_name.str,
+ base_name.length)))
+ return 1;
+ }
+ if (!tmp)
+ {
+ /* Delete not default key caches */
+ if (base_name.length != 7 || memcpy(base_name.str, "default", 7))
+ {
+ /*
+ QQ: Here we should move tables using this key cache to default
+ key cache
+ */
+ delete key_cache;
+ return 0;
+ }
+ }
+
+ key_cache->size= (ulonglong) getopt_ull_limit_value(tmp, option_limits);
+
+ /* QQ: Needs to be updated when we have multiple key caches */
+ keybuff_size= key_cache->size;
+ ha_resize_key_cache();
+ return 0;
+}
+
+static ulonglong zero=0;
+
+byte *sys_var_key_buffer_size::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
+{
+ const char *name;
+ uint length;
+
+ if (!base->str)
+ {
+ name= "default";
+ length= 7;
+ }
+ else
+ {
+ name= base->str;
+ length= base->length;
+ }
+ KEY_CACHE *key_cache= (KEY_CACHE*) find_named(&key_caches, name, length);
+ if (!key_cache)
+ return (byte*) &zero;
+ return (byte*) &key_cache->size;
+}
+
+
/*****************************************************************************
Functions to handle SET NAMES and SET CHARACTER SET
@@ -1435,7 +1518,8 @@ void sys_var_timestamp::set_default(THD *thd, enum_var_type type)
}
-byte *sys_var_timestamp::value_ptr(THD *thd, enum_var_type type)
+byte *sys_var_timestamp::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
{
thd->sys_var_tmp.long_value= (long) thd->start_time;
return (byte*) &thd->sys_var_tmp.long_value;
@@ -1449,7 +1533,8 @@ bool sys_var_last_insert_id::update(THD *thd, set_var *var)
}
-byte *sys_var_last_insert_id::value_ptr(THD *thd, enum_var_type type)
+byte *sys_var_last_insert_id::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
{
thd->sys_var_tmp.long_value= (long) thd->insert_id();
return (byte*) &thd->last_insert_id;
@@ -1463,7 +1548,8 @@ bool sys_var_insert_id::update(THD *thd, set_var *var)
}
-byte *sys_var_insert_id::value_ptr(THD *thd, enum_var_type type)
+byte *sys_var_insert_id::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
{
return (byte*) &thd->current_insert_id;
}
@@ -1854,7 +1940,8 @@ int set_var_password::update(THD *thd)
Functions to handle sql_mode
****************************************************************************/
-byte *sys_var_thd_sql_mode::value_ptr(THD *thd, enum_var_type type)
+byte *sys_var_thd_sql_mode::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
{
ulong val;
char buff[256];
@@ -1951,6 +2038,68 @@ ulong fix_sql_mode(ulong sql_mode)
}
+/****************************************************************************
+ Named list handling
+****************************************************************************/
+
+gptr find_named(I_List<NAMED_LIST> *list, const char *name, uint length)
+{
+ I_List_iterator<NAMED_LIST> it(*list);
+ NAMED_LIST *element;
+ while ((element= it++))
+ {
+ if (element->cmp(name, length))
+ return element->data;
+ }
+ return 0;
+}
+
+
+void delete_elements(I_List<NAMED_LIST> *list, void (*free_element)(gptr))
+{
+ NAMED_LIST *element;
+ while ((element= list->get()))
+ {
+ (*free_element)(element->data);
+ delete element;
+ }
+}
+
+
+/* Key cache functions */
+
+static KEY_CACHE *create_key_cache(const char *name, uint length)
+{
+ KEY_CACHE *key_cache;
+ DBUG_PRINT("info",("Creating key cache: %s", name));
+ if ((key_cache= (KEY_CACHE*) my_malloc(sizeof(KEY_CACHE),
+ MYF(MY_ZEROFILL | MY_WME))))
+ {
+ if (!new NAMED_LIST(&key_caches, name, length, (gptr) key_cache))
+ {
+ my_free((char*) key_cache, MYF(0));
+ key_cache= 0;
+ }
+ }
+ return key_cache;
+}
+
+
+KEY_CACHE *get_or_create_key_cache(const char *name, uint length)
+{
+ KEY_CACHE *key_cache= (KEY_CACHE*) find_named(&key_caches, name,
+ length);
+ if (!key_cache)
+ key_cache= create_key_cache(name, length);
+ return key_cache;
+}
+
+
+void free_key_cache(gptr key_cache)
+{
+ my_free(key_cache, MYF(0));
+}
+
/****************************************************************************
Used templates
@@ -1959,4 +2108,5 @@ ulong fix_sql_mode(ulong sql_mode)
#ifdef __GNUC__
template class List<set_var_base>;
template class List_iterator_fast<set_var_base>;
+template class I_List_iterator<NAMED_LIST>;
#endif
diff --git a/sql/set_var.h b/sql/set_var.h
index 0622e504499..8f12016bab4 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -47,12 +47,18 @@ public:
struct my_option *option_limits; /* Updated by by set_var_init() */
uint name_length; /* Updated by by set_var_init() */
const char *name;
+ LEX_STRING base_name; /* for structs */
+
sys_after_update_func after_update;
sys_var(const char *name_arg) :name(name_arg),after_update(0)
- {}
+ {
+ base_name.length=0;
+ }
sys_var(const char *name_arg,sys_after_update_func func)
:name(name_arg),after_update(func)
- {}
+ {
+ base_name.length=0;
+ }
virtual ~sys_var() {}
virtual bool check(THD *thd, set_var *var) { return 0; }
bool check_enum(THD *thd, set_var *var, TYPELIB *enum_names);
@@ -60,14 +66,16 @@ public:
virtual bool update(THD *thd, set_var *var)=0;
virtual void set_default(THD *thd, enum_var_type type) {}
virtual SHOW_TYPE type() { return SHOW_UNDEF; }
- virtual byte *value_ptr(THD *thd, enum_var_type type) { return 0; }
+ virtual byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base)
+ { return 0; }
virtual bool check_type(enum_var_type type)
{ return type != OPT_GLOBAL; } /* Error if not GLOBAL */
virtual bool check_update_type(Item_result type)
{ return type != INT_RESULT; } /* Assume INT */
virtual bool check_default(enum_var_type type)
{ return option_limits == 0; }
- Item *item(THD *thd, enum_var_type type);
+ Item *item(THD *thd, enum_var_type type, LEX_STRING *base);
+ virtual bool is_struct() { return 0; }
};
@@ -83,7 +91,8 @@ public:
bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type);
SHOW_TYPE type() { return SHOW_LONG; }
- byte *value_ptr(THD *thd, enum_var_type type) { return (byte*) value; }
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base)
+ { return (byte*) value; }
};
@@ -99,7 +108,8 @@ public:
bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type);
SHOW_TYPE type() { return SHOW_LONGLONG; }
- byte *value_ptr(THD *thd, enum_var_type type) { return (byte*) value; }
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base)
+ { return (byte*) value; }
};
@@ -117,7 +127,8 @@ public:
bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type);
SHOW_TYPE type() { return SHOW_MY_BOOL; }
- byte *value_ptr(THD *thd, enum_var_type type) { return (byte*) value; }
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base)
+ { return (byte*) value; }
bool check_update_type(Item_result type) { return 0; }
};
@@ -149,7 +160,8 @@ public:
(*set_default_func)(thd, type);
}
SHOW_TYPE type() { return SHOW_CHAR; }
- byte *value_ptr(THD *thd, enum_var_type type) { return (byte*) value; }
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base)
+ { return (byte*) value; }
bool check_update_type(Item_result type)
{
return type != STRING_RESULT; /* Only accept strings */
@@ -173,7 +185,7 @@ public:
}
bool update(THD *thd, set_var *var);
SHOW_TYPE type() { return SHOW_CHAR; }
- byte *value_ptr(THD *thd, enum_var_type type);
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
bool check_update_type(Item_result type) { return 0; }
};
@@ -209,7 +221,7 @@ public:
bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type);
SHOW_TYPE type() { return SHOW_LONG; }
- byte *value_ptr(THD *thd, enum_var_type type);
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
};
class sys_var_pseudo_thread_id :public sys_var_thd_ulong
@@ -236,7 +248,7 @@ public:
bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type);
SHOW_TYPE type() { return SHOW_HA_ROWS; }
- byte *value_ptr(THD *thd, enum_var_type type);
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
};
@@ -256,7 +268,7 @@ public:
bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type);
SHOW_TYPE type() { return SHOW_LONGLONG; }
- byte *value_ptr(THD *thd, enum_var_type type);
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
bool check_default(enum_var_type type)
{
return type == OPT_GLOBAL && !option_limits;
@@ -282,7 +294,7 @@ public:
bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type);
SHOW_TYPE type() { return SHOW_MY_BOOL; }
- byte *value_ptr(THD *thd, enum_var_type type);
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
bool check(THD *thd, set_var *var)
{
return check_enum(thd, var, &bool_typelib);
@@ -313,7 +325,7 @@ public:
bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type);
SHOW_TYPE type() { return SHOW_CHAR; }
- byte *value_ptr(THD *thd, enum_var_type type);
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
bool check_update_type(Item_result type) { return 0; }
};
@@ -332,7 +344,7 @@ public:
return check_set(thd, var, enum_names);
}
void set_default(THD *thd, enum_var_type type);
- byte *value_ptr(THD *thd, enum_var_type type);
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
};
@@ -355,7 +367,7 @@ public:
bool check_update_type(Item_result type) { return 0; }
bool check_type(enum_var_type type) { return type == OPT_GLOBAL; }
SHOW_TYPE type() { return SHOW_MY_BOOL; }
- byte *value_ptr(THD *thd, enum_var_type type);
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
};
@@ -370,7 +382,7 @@ public:
bool check_type(enum_var_type type) { return type == OPT_GLOBAL; }
bool check_default(enum_var_type type) { return 0; }
SHOW_TYPE type() { return SHOW_LONG; }
- byte *value_ptr(THD *thd, enum_var_type type);
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
};
@@ -381,7 +393,7 @@ public:
bool update(THD *thd, set_var *var);
bool check_type(enum_var_type type) { return type == OPT_GLOBAL; }
SHOW_TYPE type() { return SHOW_LONGLONG; }
- byte *value_ptr(THD *thd, enum_var_type type);
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
};
@@ -392,7 +404,7 @@ public:
bool update(THD *thd, set_var *var);
bool check_type(enum_var_type type) { return type == OPT_GLOBAL; }
SHOW_TYPE type() { return SHOW_LONGLONG; }
- byte *value_ptr(THD *thd, enum_var_type type);
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
};
@@ -456,7 +468,7 @@ SHOW_TYPE type() { return SHOW_CHAR; }
}
bool check_default(enum_var_type type) { return 0; }
bool update(THD *thd, set_var *var);
- byte *value_ptr(THD *thd, enum_var_type type);
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
virtual void set_default(THD *thd, enum_var_type type)= 0;
virtual CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type)= 0;
};
@@ -513,9 +525,24 @@ public:
sys_var_collation_connection(const char *name_arg) :sys_var_collation(name_arg) {}
bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type);
- byte *value_ptr(THD *thd, enum_var_type type);
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
+};
+
+
+class sys_var_key_buffer_size :public sys_var
+{
+public:
+ sys_var_key_buffer_size(const char *name_arg)
+ :sys_var(name_arg)
+ {}
+ bool update(THD *thd, set_var *var);
+ SHOW_TYPE type() { return SHOW_LONGLONG; }
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
+ bool check_default(enum_var_type type) { return 1; }
+ bool is_struct() { return 1; }
};
+
/* Variable that you can only read from */
class sys_var_readonly: public sys_var
@@ -534,7 +561,7 @@ public:
bool check_default(enum_var_type type) { return 1; }
bool check_type(enum_var_type type) { return type != var_type; }
bool check_update_type(Item_result type) { return 1; }
- byte *value_ptr(THD *thd, enum_var_type type)
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base)
{
return (*value_ptr_func)(thd);
}
@@ -639,6 +666,36 @@ public:
};
+/* Named lists (used for keycaches) */
+
+class NAMED_LIST :public ilink
+{
+ const char *name;
+ uint name_length;
+public:
+ gptr data;
+
+ NAMED_LIST(I_List<NAMED_LIST> *links, const char *name_arg,
+ uint name_length_arg, gptr data_arg):
+ name_length(name_length_arg), data(data_arg)
+ {
+ name=my_strdup(name_arg,MYF(MY_WME));
+ links->push_back(this);
+ }
+ inline bool cmp(const char *name_cmp, uint length)
+ {
+ return length == name_length && !memcmp(name, name_cmp, length);
+ }
+ ~NAMED_LIST()
+ {
+ my_free((char*) name, MYF(0));
+ }
+};
+
+/* updated in sql_acl.cc */
+
+extern sys_var_thd_bool sys_old_passwords;
+
/*
Prototypes for helper functions
*/
@@ -649,8 +706,12 @@ sys_var *find_sys_var(const char *str, uint length=0);
int sql_set_variables(THD *thd, List<set_var_base> *var_list);
void fix_delay_key_write(THD *thd, enum_var_type type);
ulong fix_sql_mode(ulong sql_mode);
-
extern sys_var_str sys_charset_system;
CHARSET_INFO *get_old_charset_by_name(const char *old_name);
-extern sys_var_thd_bool sys_old_passwords;
+gptr find_named(I_List<NAMED_LIST> *list, const char *name, uint length);
+void delete_elements(I_List<NAMED_LIST> *list, void (*free_element)(gptr));
+
+/* key_cache functions */
+KEY_CACHE *get_or_create_key_cache(const char *name, uint length);
+void free_key_cache(gptr key_cache);
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index 4f1836ef80a..1c555e93cf2 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -17,7 +17,7 @@ v/*
"Nemohu vytvo-Bøit soubor '%-.64s' (chybový kód: %d)",
"Nemohu vytvo-Bøit tabulku '%-.64s' (chybový kód: %d)",
"Nemohu vytvo-Bøit databázi '%-.64s', chyba %d",
-"Nemohu vytvo-Bøit databázi '%-.64s', databáze ji¾ existuje",
+"Nemohu vytvo-Bøit databázi '%-.64s'; databáze ji¾ existuje",
"Nemohu zru-B¹it databázi '%-.64s', databáze neexistuje",
"Chyba p-Bøi ru¹ení databáze (nemohu vymazat '%-.64s', chyba %d)",
"Chyba p-Bøi ru¹ení databáze (nemohu vymazat adresáø '%-.64s', chyba %d)",
@@ -275,4 +275,5 @@ v/*
"Can't revoke all privileges, grant for one or more of the requested users"
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt
index 138c8c59a39..874e0680830 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -11,8 +11,8 @@
"Kan ikke oprette filen '%-.64s' (Fejlkode: %d)",
"Kan ikke oprette tabellen '%-.64s' (Fejlkode: %d)",
"Kan ikke oprette databasen '%-.64s'. Fejl %d",
-"Kan ikke oprette databasen '%-.64s'. Databasen eksisterer",
-"Kan ikke slette (droppe) '%-.64s'. Databasen eksisterer ikke",
+"Kan ikke oprette databasen '%-.64s'; databasen eksisterer",
+"Kan ikke slette (droppe) '%-.64s'; databasen eksisterer ikke",
"Fejl ved sletning (drop) af databasen (kan ikke slette '%-.64s', Fejl %d)",
"Fejl ved sletting af database (kan ikke slette folderen '%-.64s', Fejl %d)",
"Fejl ved sletning af '%-.64s' (Fejlkode: %d)",
@@ -269,4 +269,5 @@
"Can't revoke all privileges, grant for one or more of the requested users"
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
index f7a79dfa738..8719ec37916 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -19,8 +19,8 @@
"Kan file '%-.64s' niet aanmaken (Errcode: %d)",
"Kan tabel '%-.64s' niet aanmaken (Errcode: %d)",
"Kan database '%-.64s' niet aanmaken (Errcode: %d)",
-"Kan database '%-.64s' niet aanmaken. Database bestaat reeds",
-"Kan database '%-.64s' niet verwijderen. Database bestaat niet",
+"Kan database '%-.64s' niet aanmaken; database bestaat reeds",
+"Kan database '%-.64s' niet verwijderen; database bestaat niet",
"Fout bij verwijderen database (kan '%-.64s' niet verwijderen, Errcode: %d)",
"Fout bij verwijderen database (kan rmdir '%-.64s' niet uitvoeren, Errcode: %d)",
"Fout bij het verwijderen van '%-.64s' (Errcode: %d)",
@@ -277,4 +277,5 @@
"Can't revoke all privileges, grant for one or more of the requested users"
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index c57527e2578..5a87d9fbc28 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -8,8 +8,8 @@
"Can't create file '%-.64s' (errno: %d)",
"Can't create table '%-.64s' (errno: %d)",
"Can't create database '%-.64s'. (errno: %d)",
-"Can't create database '%-.64s'. Database exists",
-"Can't drop database '%-.64s'. Database doesn't exist",
+"Can't create database '%-.64s'; database exists",
+"Can't drop database '%-.64s'; database doesn't exist",
"Error dropping database (can't delete '%-.64s', errno: %d)",
"Error dropping database (can't rmdir '%-.64s', errno: %d)",
"Error on delete of '%-.64s' (errno: %d)",
@@ -271,4 +271,5 @@
"Can't revoke all privileges, grant for one or more of the requested users"
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index e6ade1c7e3d..6239d1c309d 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -271,4 +271,5 @@
"Can't revoke all privileges, grant for one or more of the requested users"
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index 7ffd834fbcf..c2d54d4de87 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -8,8 +8,8 @@
"Ne peut créer le fichier '%-.64s' (Errcode: %d)",
"Ne peut créer la table '%-.64s' (Errcode: %d)",
"Ne peut créer la base '%-.64s'. Erreur %d",
-"Ne peut créer la base '%-.64s'. Elle existe déjà",
-"Ne peut effacer la base '%-.64s'. Elle n'existe pas",
+"Ne peut créer la base '%-.64s'; elle existe déjà",
+"Ne peut effacer la base '%-.64s'; elle n'existe pas",
"Ne peut effacer la base '%-.64s' (erreur %d)",
"Erreur en effaçant la base (rmdir '%-.64s', erreur %d)",
"Erreur en effaçant '%-.64s' (Errcode: %d)",
@@ -266,4 +266,5 @@
"Can't revoke all privileges, grant for one or more of the requested users"
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index 2c6343eeeea..5760f29e719 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -17,8 +17,8 @@
"Kann Datei '%-.64s' nicht erzeugen. (Fehler: %d)",
"Kann Tabelle '%-.64s' nicht erzeugen. (Fehler: %d)",
"Kann Datenbank '%-.64s' nicht erzeugen. (Fehler: %d)",
-"Kann Datenbank '%-.64s' nicht erzeugen. Datenbank '%-.64s' existiert bereits.",
-"Kann Datenbank '%-.64s' nicht löschen. Keine Datenbank '%-.64s' vorhanden.",
+"Kann Datenbank '%-.64s' nicht erzeugen; datenbank '%-.64s' existiert bereits.",
+"Kann Datenbank '%-.64s' nicht löschen; keine Datenbank '%-.64s' vorhanden.",
"Fehler beim Löschen der Datenbank. ('%-.64s' kann nicht gelöscht werden, Fehlernuumer: %d)",
"Fehler beim Löschen der Datenbank. (Verzeichnis '%-.64s' kann nicht gelöscht werden, Fehlernummer: %d)",
"Fehler beim Löschen von '%-.64s'. (Fehler: %d)",
@@ -275,4 +275,5 @@
"Can't revoke all privileges, grant for one or more of the requested users"
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index 228834f7937..a94a14873a9 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -266,4 +266,5 @@
"Can't revoke all privileges, grant for one or more of the requested users"
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index 620234e2321..e6e74d2d76d 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -268,4 +268,5 @@
"Can't revoke all privileges, grant for one or more of the requested users"
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index 8091d3185ba..86823dcd360 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -8,8 +8,8 @@
"Impossibile creare il file '%-.64s' (errno: %d)",
"Impossibile creare la tabella '%-.64s' (errno: %d)",
"Impossibile creare il database '%-.64s'. (errno: %d)",
-"Impossibile creare il database '%-.64s'. Il database esiste",
-"Impossibile cancellare '%-.64s'. Il database non esiste",
+"Impossibile creare il database '%-.64s'; il database esiste",
+"Impossibile cancellare '%-.64s'; il database non esiste",
"Errore durante la cancellazione del database (impossibile cancellare '%-.64s', errno: %d)",
"Errore durante la cancellazione del database (impossibile rmdir '%-.64s', errno: %d)",
"Errore durante la cancellazione di '%-.64s' (errno: %d)",
@@ -266,4 +266,5 @@
"Can't revoke all privileges, grant for one or more of the requested users"
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index 962505423b1..0a57d70205d 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -268,4 +268,5 @@
"Can't revoke all privileges, grant for one or more of the requested users"
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index aa0439fcd32..7d0fe2f6d6d 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -266,4 +266,5 @@
"Can't revoke all privileges, grant for one or more of the requested users"
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index 21dfad648b9..b6d449bb70a 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -10,8 +10,8 @@
"Kan ikkje opprette fila '%-.64s' (Feilkode: %d)",
"Kan ikkje opprette tabellen '%-.64s' (Feilkode: %d)",
"Kan ikkje opprette databasen '%-.64s'. Feil %d",
-"Kan ikkje opprette databasen '%-.64s'. Databasen eksisterer",
-"Kan ikkje fjerne (drop) '%-.64s'. Databasen eksisterer ikkje",
+"Kan ikkje opprette databasen '%-.64s'; databasen eksisterer",
+"Kan ikkje fjerne (drop) '%-.64s'; databasen eksisterer ikkje",
"Feil ved fjerning (drop) av databasen (kan ikkje slette '%-.64s', feil %d)",
"Feil ved sletting av database (kan ikkje slette katalogen '%-.64s', feil %d)",
"Feil ved sletting av '%-.64s' (Feilkode: %d)",
@@ -268,4 +268,5 @@
"Can't revoke all privileges, grant for one or more of the requested users"
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index e1d7501bca4..b46fa718d4d 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -10,8 +10,8 @@
"Kan ikke opprette fila '%-.64s' (Feilkode: %d)",
"Kan ikke opprette tabellen '%-.64s' (Feilkode: %d)",
"Kan ikke opprette databasen '%-.64s'. Feil %d",
-"Kan ikke opprette databasen '%-.64s'. Databasen eksisterer",
-"Kan ikke fjerne (drop) '%-.64s'. Databasen eksisterer ikke",
+"Kan ikke opprette databasen '%-.64s'; databasen eksisterer",
+"Kan ikke fjerne (drop) '%-.64s'; databasen eksisterer ikke",
"Feil ved fjerning (drop) av databasen (kan ikke slette '%-.64s', feil %d)",
"Feil ved sletting av database (kan ikke slette katalogen '%-.64s', feil %d)",
"Feil ved sletting av '%-.64s' (Feilkode: %d)",
@@ -268,4 +268,5 @@
"Can't revoke all privileges, grant for one or more of the requested users"
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt
index eaa2395b675..e00e99bb0a8 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -12,8 +12,8 @@
"Nie mo¿na stworzyæ pliku '%-.64s' (Kod b³êdu: %d)",
"Nie mo¿na stworzyæ tabeli '%-.64s' (Kod b³êdu: %d)",
"Nie mo¿na stworzyæ bazy danych '%-.64s'. B³?d %d",
-"Nie mo¿na stworzyæ bazy danych '%-.64s'. Baza danych ju¿ istnieje",
-"Nie mo¿na usun?æ bazy danych '%-.64s'. Baza danych nie istnieje",
+"Nie mo¿na stworzyæ bazy danych '%-.64s'; baza danych ju¿ istnieje",
+"Nie mo¿na usun?æ bazy danych '%-.64s'; baza danych nie istnieje",
"B³?d podczas usuwania bazy danych (nie mo¿na usun?æ '%-.64s', b³?d %d)",
"B³?d podczas usuwania bazy danych (nie mo¿na wykonaæ rmdir '%-.64s', b³?d %d)",
"B³?d podczas usuwania '%-.64s' (Kod b³êdu: %d)",
@@ -270,4 +270,5 @@
"Can't revoke all privileges, grant for one or more of the requested users"
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt
index 89aded8afce..d904243e2fb 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -8,8 +8,8 @@
"Não pode criar o arquivo '%-.64s' (erro no. %d)",
"Não pode criar a tabela '%-.64s' (erro no. %d)",
"Não pode criar o banco de dados '%-.64s' (erro no. %d)",
-"Não pode criar o banco de dados '%-.64s'. Este banco de dados já existe",
-"Não pode eliminar o banco de dados '%-.64s'. Este banco de dados não existe",
+"Não pode criar o banco de dados '%-.64s'; este banco de dados já existe",
+"Não pode eliminar o banco de dados '%-.64s'; este banco de dados não existe",
"Erro ao eliminar banco de dados (não pode eliminar '%-.64s' - erro no. %d)",
"Erro ao eliminar banco de dados (não pode remover diretório '%-.64s' - erro no. %d)",
"Erro na remoção de '%-.64s' (erro no. %d)",
@@ -266,4 +266,5 @@
"Can't revoke all privileges, grant for one or more of the requested users"
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index e76fd43e841..702591a89ec 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -12,8 +12,8 @@
"Nu pot sa creez fisierul '%-.64s' (Eroare: %d)",
"Nu pot sa creez tabla '%-.64s' (Eroare: %d)",
"Nu pot sa creez baza de date '%-.64s'. (Eroare: %d)",
-"Nu pot sa creez baza de date '%-.64s'. Baza de date exista deja",
-"Nu pot sa drop baza de date '%-.64s'. Baza da date este inexistenta",
+"Nu pot sa creez baza de date '%-.64s'; baza de date exista deja",
+"Nu pot sa drop baza de date '%-.64s'; baza da date este inexistenta",
"Eroare dropuind baza de date (nu pot sa sterg '%-.64s', Eroare: %d)",
"Eroare dropuind baza de date (nu pot sa rmdir '%-.64s', Eroare: %d)",
"Eroare incercind sa delete '%-.64s' (Eroare: %d)",
@@ -270,4 +270,5 @@
"Can't revoke all privileges, grant for one or more of the requested users"
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
index 23d20c1b8fe..c011de8f093 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -268,4 +268,5 @@
"Can't revoke all privileges, grant for one or more of the requested users"
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"óÅÒ×ÅÒ ÚÁÐÕÝÅÎ × ÒÅÖÉÍÅ --secure-auth (ÂÅÚÏÐÁÓÎÏÊ Á×ÔÏÒÉÚÁÃÉÉ), ÎÏ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÑ '%s@%s' ÐÁÒÏÌØ ÓÏÈÒÁÎ£Î × ÓÔÁÒÏÍ ÆÏÒÍÁÔÅ; ÎÅÏÂÈÏÄÉÍÏ ÏÂÎÏ×ÉÔØ ÆÏÒÍÁÔ ÐÁÒÏÌÑ"
diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt
index e0ba1413f5e..89672811a25 100644
--- a/sql/share/serbian/errmsg.txt
+++ b/sql/share/serbian/errmsg.txt
@@ -14,8 +14,8 @@
"Ne mogu da kreiram file '%-.64s' (errno: %d)",
"Ne mogu da kreiram tabelu '%-.64s' (errno: %d)",
"Ne mogu da kreiram bazu '%-.64s'. (errno: %d)",
-"Ne mogu da kreiram bazu '%-.64s'. Baza veæ postoji.",
-"Ne mogu da izbrišem bazu '%-.64s'. Baza ne postoji.",
+"Ne mogu da kreiram bazu '%-.64s'; baza veæ postoji.",
+"Ne mogu da izbrišem bazu '%-.64s'; baza ne postoji.",
"Ne mogu da izbrišem bazu (ne mogu da izbrišem '%-.64s', errno: %d)",
"Ne mogu da izbrišem bazu (ne mogu da izbrišem direktorijum '%-.64s', errno: %d)",
"Greška pri brisanju '%-.64s' (errno: %d)",
@@ -262,4 +262,5 @@
"Can't revoke all privileges, grant for one or more of the requested users"
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index bc8949127fd..51bcde43b91 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -16,8 +16,8 @@
"Nemô¾em vytvori» súbor '%-.64s' (chybový kód: %d)",
"Nemô¾em vytvori» tabuµku '%-.64s' (chybový kód: %d)",
"Nemô¾em vytvori» databázu '%-.64s'. (chybový kód: %d)",
-"Nemô¾em vytvori» databázu '%-.64s'. Databáza existuje",
-"Nemô¾em zmaza» databázu '%-.64s'. Databáza neexistuje",
+"Nemô¾em vytvori» databázu '%-.64s'; databáza existuje",
+"Nemô¾em zmaza» databázu '%-.64s'; databáza neexistuje",
"Chyba pri mazaní databázy (nemô¾em zmaza» '%-.64s', chybový kód: %d)",
"Chyba pri mazaní databázy (nemô¾em vymaza» adresár '%-.64s', chybový kód: %d)",
"Chyba pri mazaní '%-.64s' (chybový kód: %d)",
@@ -274,4 +274,5 @@
"Can't revoke all privileges, grant for one or more of the requested users"
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt
index 9a6dcd90a4d..c8931faeb16 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -9,8 +9,8 @@
"No puedo crear archivo '%-.64s' (Error: %d)",
"No puedo crear tabla '%-.64s' (Error: %d)",
"No puedo crear base de datos '%-.64s'. Error %d",
-"No puedo crear base de datos '%-.64s'. La base de datos ya existe",
-"No puedo eliminar base de datos '%-.64s'. La base de datos no existe",
+"No puedo crear base de datos '%-.64s'; la base de datos ya existe",
+"No puedo eliminar base de datos '%-.64s'; la base de datos no existe",
"Error eliminando la base de datos(no puedo borrar '%-.64s', error %d)",
"Error eliminando la base de datos (No puedo borrar directorio '%-.64s', error %d)",
"Error en el borrado de '%-.64s' (Error: %d)",
@@ -267,4 +267,5 @@
"Can't revoke all privileges, grant for one or more of the requested users"
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt
index 3538ba3c47e..f38f2126602 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -9,7 +9,7 @@
"Kan inte skapa tabellen '%-.64s' (Felkod: %d)",
"Kan inte skapa databasen '%-.64s'. (Felkod: %d)",
"Databasen '%-.64s' existerar redan",
-"Kan inte radera databasen '%-.64s'. Databasen finns inte",
+"Kan inte radera databasen '%-.64s'; databasen finns inte",
"Fel vid radering av databasen (Kan inte radera '%-.64s'. Felkod: %d)",
"Fel vid radering av databasen (Kan inte radera biblioteket '%-.64s'. Felkod: %d)",
"Kan inte radera filen '%-.64s' (Felkod: %d)",
@@ -266,4 +266,5 @@
"Can't revoke all privileges, grant for one or more of the requested users"
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt
index 9bc07241856..a3e2c46bed1 100644
--- a/sql/share/ukrainian/errmsg.txt
+++ b/sql/share/ukrainian/errmsg.txt
@@ -271,4 +271,5 @@
"Can't revoke all privileges, grant for one or more of the requested users"
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 2eeb57f34a7..425890ab446 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -557,10 +557,12 @@ int yylex(void *arg, void *yythd)
return(IDENT);
case MY_LEX_IDENT_SEP: // Found ident and now '.'
- lex->next_state=MY_LEX_IDENT_START;// Next is an ident (not a keyword)
yylval->lex_str.str=(char*) lex->ptr;
yylval->lex_str.length=1;
c=yyGet(); // should be '.'
+ lex->next_state= MY_LEX_IDENT_START;// Next is an ident (not a keyword)
+ if (!ident_map[yyPeek()]) // Probably ` or "
+ lex->next_state= MY_LEX_START;
return((int) c);
case MY_LEX_NUMBER_IDENT: // number or ident which num-start
@@ -601,7 +603,7 @@ int yylex(void *arg, void *yythd)
yyUnget();
}
// fall through
- case MY_LEX_IDENT_START: // Incomplete ident
+ case MY_LEX_IDENT_START: // We come here after '.'
#if defined(USE_MB) && defined(USE_MB_IDENT)
if (use_mb(cs))
{
@@ -689,6 +691,7 @@ int yylex(void *arg, void *yythd)
}
if (c == delim)
yySkip(); // Skip end `
+ lex->next_state= MY_LEX_START;
return(IDENT);
}
case MY_LEX_SIGNED_NUMBER: // Incomplete signed number
@@ -707,9 +710,9 @@ int yylex(void *arg, void *yythd)
if (c != '.')
{
if (c == '-' && my_isspace(cs,yyPeek()))
- state=MY_LEX_COMMENT;
+ state= MY_LEX_COMMENT;
else
- state = MY_LEX_CHAR; // Return sign as single char
+ state= MY_LEX_CHAR; // Return sign as single char
break;
}
yyUnget(); // Fix for next loop
@@ -868,7 +871,7 @@ int yylex(void *arg, void *yythd)
else
state=MY_LEX_CHAR; // Return '*'
break;
- case MY_LEX_SET_VAR: // Check if ':='
+ case MY_LEX_SET_VAR: // Check if ':='
if (yyPeek() != '=')
{
state=MY_LEX_CHAR; // Return ':'
@@ -904,8 +907,8 @@ int yylex(void *arg, void *yythd)
state = MY_LEX_REAL; // Real
else
{
- state = MY_LEX_CHAR; // return '.'
- lex->next_state=MY_LEX_IDENT_START;// Next is an ident (not a keyword)
+ state= MY_LEX_IDENT_SEP; // return '.'
+ yyUnget(); // Put back '.'
}
break;
case MY_LEX_USER_END: // end '@' of user@hostname
@@ -933,8 +936,11 @@ int yylex(void *arg, void *yythd)
case MY_LEX_SYSTEM_VAR:
yylval->lex_str.str=(char*) lex->ptr;
yylval->lex_str.length=1;
- lex->next_state=MY_LEX_IDENT_OR_KEYWORD;
yySkip(); // Skip '@'
+ lex->next_state= (state_map[yyPeek()] ==
+ MY_LEX_USER_VARIABLE_DELIMITER ?
+ MY_LEX_OPERATOR_OR_IDENT :
+ MY_LEX_IDENT_OR_KEYWORD);
return((int) '@');
case MY_LEX_IDENT_OR_KEYWORD:
/*
@@ -942,7 +948,6 @@ int yylex(void *arg, void *yythd)
We should now be able to handle:
[(global | local | session) .]variable_name
*/
-
while (ident_map[c=yyGet()]) ;
if (c == '.')
lex->next_state=MY_LEX_IDENT_SEP;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 31755456079..7878f2c8a29 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1232,6 +1232,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
mysql_stmt_free(thd, packet);
break;
}
+ case COM_RESET_STMT:
+ {
+ mysql_stmt_reset(thd, packet);
+ break;
+ }
case COM_QUERY:
{
if (alloc_query(thd, packet, packet_length))
@@ -3512,15 +3517,20 @@ mysql_new_select(LEX *lex, bool move_down)
void create_select_for_variable(const char *var_name)
{
+ THD *thd;
LEX *lex;
- LEX_STRING tmp;
+ LEX_STRING tmp, null_lex_string;
DBUG_ENTER("create_select_for_variable");
- lex= current_lex;
+
+ thd= current_thd;
+ lex= &thd->lex;
mysql_init_select(lex);
lex->sql_command= SQLCOM_SELECT;
tmp.str= (char*) var_name;
tmp.length=strlen(var_name);
- add_item_to_list(lex->thd, get_system_var(OPT_SESSION, tmp));
+ bzero((char*) &null_lex_string.str, sizeof(null_lex_string));
+ add_item_to_list(thd, get_system_var(thd, OPT_SESSION, tmp,
+ null_lex_string));
DBUG_VOID_RETURN;
}
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index c38fb44db1c..550e4bbe086 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -965,7 +965,7 @@ void mysql_stmt_reset(THD *thd, char *packet)
PREP_STMT *stmt;
DBUG_ENTER("mysql_stmt_reset");
- if (!(stmt=find_prepared_statement(thd, stmt_id, "close")))
+ if (!(stmt= find_prepared_statement(thd, stmt_id, "reset")))
{
send_error(thd);
DBUG_VOID_RETURN;
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index fae01936357..e8cb59e387e 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1527,12 +1527,14 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
char buff[1024];
List<Item> field_list;
Protocol *protocol= thd->protocol;
+ LEX_STRING null_lex_str;
DBUG_ENTER("mysqld_show");
field_list.push_back(new Item_empty_string("Variable_name",30));
field_list.push_back(new Item_empty_string("Value",256));
if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1); /* purecov: inspected */
+ null_lex_str.str= 0; // For sys_var->value_ptr()
/* pthread_mutex_lock(&THR_LOCK_keycache); */
pthread_mutex_lock(&LOCK_status);
@@ -1551,7 +1553,8 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
if (show_type == SHOW_SYS)
{
show_type= ((sys_var*) value)->type();
- value= (char*) ((sys_var*) value)->value_ptr(thd, value_type);
+ value= (char*) ((sys_var*) value)->value_ptr(thd, value_type,
+ &null_lex_str);
}
pos= end= buff;
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 0a3e8d0db9f..e7d7b08c93c 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -390,6 +390,23 @@ bool String::append(IO_CACHE* file, uint32 arg_length)
return FALSE;
}
+bool String::append_with_prefill(const char *s,uint32 arg_length,
+ uint32 full_length, char fill_char)
+{
+ int t_length= arg_length > full_length ? arg_length : full_length;
+
+ if (realloc(str_length + t_length))
+ return TRUE;
+ t_length= full_length - arg_length;
+ if (t_length > 0)
+ {
+ bfill(Ptr+str_length, t_length, fill_char);
+ str_length=str_length + t_length;
+ }
+ append(s, arg_length);
+ return FALSE;
+}
+
uint32 String::numchars()
{
return str_charset->cset->numchars(str_charset, Ptr, Ptr+str_length);
diff --git a/sql/sql_string.h b/sql/sql_string.h
index e88c9389589..d446d26298b 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -189,6 +189,8 @@ public:
bool append(const char *s,uint32 arg_length=0);
bool append(const char *s,uint32 arg_length, CHARSET_INFO *cs);
bool append(IO_CACHE* file, uint32 arg_length);
+ bool append_with_prefill(const char *s, uint32 arg_length,
+ uint32 full_length, char fill_char);
int strstr(const String &search,uint32 offset=0); // Returns offset to substring or -1
int strstr_case(const String &s,uint32 offset=0);
int strrstr(const String &search,uint32 offset=0); // Returns offset to substring or -1
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index b79b37aac39..807501b6ab4 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -163,6 +163,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token VARIANCE_SYM
%token STOP_SYM
%token SUM_SYM
+%token ADDDATE_SYM
%token SUPER_SYM
%token TRUNCATE_SYM
%token UNLOCK_SYM
@@ -431,6 +432,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token VARYING
%token ZEROFILL
+%token ADDDATE_SYM
%token AGAINST
%token ATAN
%token BETWEEN_SYM
@@ -445,6 +447,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token DATE_ADD_INTERVAL
%token DATE_SUB_INTERVAL
%token DAY_HOUR_SYM
+%token DAY_MICROSECOND_SYM
%token DAY_MINUTE_SYM
%token DAY_SECOND_SYM
%token DAY_SYM
@@ -467,6 +470,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token GEOMETRYCOLLECTION
%token GROUP_CONCAT_SYM
%token GROUP_UNIQUE_USERS
+%token HOUR_MICROSECOND_SYM
%token HOUR_MINUTE_SYM
%token HOUR_SECOND_SYM
%token HOUR_SYM
@@ -481,6 +485,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token LOCATE
%token MAKE_SET_SYM
%token MASTER_POS_WAIT
+%token MICROSECOND_SYM
+%token MINUTE_MICROSECOND_SYM
%token MINUTE_SECOND_SYM
%token MINUTE_SYM
%token MODE_SYM
@@ -506,7 +512,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token RIGHT
%token ROUND
%token SECOND_SYM
+%token SECOND_MICROSECOND_SYM
%token SHARE_SYM
+%token SUBDATE_SYM
%token SUBSTRING
%token SUBSTRING_INDEX
%token TRIM
@@ -562,7 +570,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
IDENT TEXT_STRING REAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM LEX_HOSTNAME
ULONGLONG_NUM field_ident select_alias ident ident_or_text
UNDERSCORE_CHARSET IDENT_sys TEXT_STRING_sys TEXT_STRING_literal
- NCHAR_STRING
+ NCHAR_STRING opt_component
%type <lex_str_ptr>
opt_table_alias
@@ -1533,6 +1541,10 @@ opt_ident:
/* empty */ { $$=(char*) 0; } /* Defaultlength */
| field_ident { $$=$1.str; };
+opt_component:
+ /* empty */ { $$.str= 0; $$.length= 0; }
+ | '.' ident { $$=$2; };
+
string_list:
text_string { Lex->interval_list.push_back($1); }
| string_list ',' text_string { Lex->interval_list.push_back($3); };
@@ -2277,9 +2289,9 @@ simple_expr:
$$= new Item_func_get_user_var($2);
Lex->uncacheable();
}
- | '@' '@' opt_var_ident_type ident_or_text
+ | '@' '@' opt_var_ident_type ident_or_text opt_component
{
- if (!($$= get_system_var((enum_var_type) $3, $4)))
+ if (!($$= get_system_var(YYTHD, (enum_var_type) $3, $4, $5)))
YYABORT;
}
| sum_expr
@@ -2335,6 +2347,10 @@ simple_expr:
{ $$= ((Item*(*)(Item*,Item*))($1.symbol->create_func))($3,$5);}
| FUNC_ARG3 '(' expr ',' expr ',' expr ')'
{ $$= ((Item*(*)(Item*,Item*,Item*))($1.symbol->create_func))($3,$5,$7);}
+ | ADDDATE_SYM '(' expr ',' expr ')'
+ { $$= new Item_date_add_interval($3, $5, INTERVAL_DAY, 0);}
+ | ADDDATE_SYM '(' expr ',' INTERVAL_SYM expr interval ')'
+ { $$= new Item_date_add_interval($3, $6, $7, 0); }
| ATAN '(' expr ')'
{ $$= new Item_func_atan($3); }
| ATAN '(' expr ',' expr ')'
@@ -2369,6 +2385,10 @@ simple_expr:
$$= new Item_func_database();
Lex->safe_to_cache_query=0;
}
+ | DATE_SYM '(' expr ')'
+ { $$= new Item_date_typecast($3); }
+ | DAY_SYM '(' expr ')'
+ { $$= new Item_func_dayofmonth($3); }
| ELT_FUNC '(' expr ',' expr_list ')'
{ $$= new Item_func_elt($3, *$5); }
| MAKE_SET_SYM '(' expr ',' expr_list ')'
@@ -2441,7 +2461,7 @@ simple_expr:
}
| LAST_INSERT_ID '(' ')'
{
- $$= get_system_var(OPT_SESSION, "last_insert_id", 14,
+ $$= get_system_var(YYTHD, OPT_SESSION, "last_insert_id", 14,
"last_insert_id()");
Lex->safe_to_cache_query= 0;
}
@@ -2485,6 +2505,8 @@ simple_expr:
$$= new Item_master_pos_wait($3, $5, $7);
Lex->safe_to_cache_query=0;
}
+ | MICROSECOND_SYM '(' expr ')'
+ { $$= new Item_func_microsecond($3); }
| MINUTE_SYM '(' expr ')'
{ $$= new Item_func_minute($3); }
| MOD_SYM '(' expr ',' expr ')'
@@ -2550,6 +2572,10 @@ simple_expr:
| ROUND '(' expr ')'
{ $$= new Item_func_round($3, new Item_int((char*)"0",0,1),0); }
| ROUND '(' expr ',' expr ')' { $$= new Item_func_round($3,$5,0); }
+ | SUBDATE_SYM '(' expr ',' expr ')'
+ { $$= new Item_date_add_interval($3, $5, INTERVAL_DAY, 1);}
+ | SUBDATE_SYM '(' expr ',' INTERVAL_SYM expr interval ')'
+ { $$= new Item_date_add_interval($3, $6, $7, 1); }
| SECOND_SYM '(' expr ')'
{ $$= new Item_func_second($3); }
| SUBSTRING '(' expr ',' expr ',' expr ')'
@@ -2562,6 +2588,12 @@ simple_expr:
{ $$= new Item_func_substr($3,$5); }
| SUBSTRING_INDEX '(' expr ',' expr ',' expr ')'
{ $$= new Item_func_substr_index($3,$5,$7); }
+ | TIME_SYM '(' expr ')'
+ { $$= new Item_time_typecast($3); }
+ | TIMESTAMP '(' expr ')'
+ { $$= new Item_datetime_typecast($3); }
+ | TIMESTAMP '(' expr ',' expr ')'
+ { $$= new Item_func_add_time($3, $5, 1, 0); }
| TRIM '(' expr ')'
{ $$= new Item_func_trim($3); }
| TRIM '(' LEADING expr FROM expr ')'
@@ -2978,15 +3010,20 @@ using_list:
interval:
DAY_HOUR_SYM { $$=INTERVAL_DAY_HOUR; }
+ | DAY_MICROSECOND_SYM { $$=INTERVAL_DAY_MICROSECOND; }
| DAY_MINUTE_SYM { $$=INTERVAL_DAY_MINUTE; }
| DAY_SECOND_SYM { $$=INTERVAL_DAY_SECOND; }
| DAY_SYM { $$=INTERVAL_DAY; }
+ | HOUR_MICROSECOND_SYM { $$=INTERVAL_HOUR_MICROSECOND; }
| HOUR_MINUTE_SYM { $$=INTERVAL_HOUR_MINUTE; }
| HOUR_SECOND_SYM { $$=INTERVAL_HOUR_SECOND; }
| HOUR_SYM { $$=INTERVAL_HOUR; }
+ | MICROSECOND_SYM { $$=INTERVAL_MICROSECOND; }
+ | MINUTE_MICROSECOND_SYM { $$=INTERVAL_MINUTE_MICROSECOND; }
| MINUTE_SECOND_SYM { $$=INTERVAL_MINUTE_SECOND; }
| MINUTE_SYM { $$=INTERVAL_MINUTE; }
| MONTH_SYM { $$=INTERVAL_MONTH; }
+ | SECOND_MICROSECOND_SYM { $$=INTERVAL_SECOND_MICROSECOND; }
| SECOND_SYM { $$=INTERVAL_SECOND; }
| YEAR_MONTH_SYM { $$=INTERVAL_YEAR_MONTH; }
| YEAR_SYM { $$=INTERVAL_YEAR; };
@@ -4305,6 +4342,7 @@ user:
keyword:
ACTION {}
+ | ADDDATE_SYM {}
| AFTER_SYM {}
| AGAINST {}
| AGGREGATE_SYM {}
@@ -4400,6 +4438,7 @@ keyword:
| MEDIUM_SYM {}
| MERGE_SYM {}
| MEMORY_SYM {}
+ | MICROSECOND_SYM {}
| MINUTE_SYM {}
| MIN_ROWS {}
| MODIFY_SYM {}
@@ -4466,6 +4505,7 @@ keyword:
| STATUS_SYM {}
| STOP_SYM {}
| STRING_SYM {}
+ | SUBDATE_SYM {}
| SUBJECT_SYM {}
| SUPER_SYM {}
| TEMPORARY {}
@@ -4596,6 +4636,27 @@ internal_variable_name:
YYABORT;
$$=tmp;
}
+ | ident '.' ident
+ {
+ sys_var *tmp=find_sys_var($3.str, $3.length);
+ if (!tmp)
+ YYABORT;
+ if (!tmp->is_struct())
+ net_printf(YYTHD, ER_VARIABLE_IS_NOT_STRUCT, $3.str);
+ tmp->base_name= $1;
+ $$=tmp;
+ }
+ | DEFAULT '.' ident
+ {
+ sys_var *tmp=find_sys_var($3.str, $3.length);
+ if (!tmp)
+ YYABORT;
+ if (!tmp->is_struct())
+ net_printf(YYTHD, ER_VARIABLE_IS_NOT_STRUCT, $3.str);
+ tmp->base_name.str= (char*) "default";
+ tmp->base_name.length= 7;
+ $$=tmp;
+ }
;
isolation_types:
diff --git a/sql/time.cc b/sql/time.cc
index b6ca306e523..70ae8dcd8ed 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -432,6 +432,7 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
l_time->minute=date[4];
l_time->second=date[5];
l_time->second_part=date[6];
+ l_time->neg= 0;
DBUG_RETURN(l_time->time_type=
(number_of_fields <= 3 ? TIMESTAMP_DATE : TIMESTAMP_FULL));
}
@@ -581,7 +582,7 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
/* Get fractional second part */
if ((end-str) >= 2 && *str == '.' && my_isdigit(&my_charset_latin1,str[1]))
{
- uint field_length=3;
+ uint field_length=5;
str++; value=(uint) (uchar) (*str - '0');
while (++str != end &&
my_isdigit(&my_charset_latin1,str[0]) &&
@@ -604,6 +605,7 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
l_time->minute=date[2];
l_time->second=date[3];
l_time->second_part=date[4];
+ l_time->time_type= TIMESTAMP_TIME;
/* Check if there is garbage at end of the TIME specification */
if (str != end && current_thd->count_cuted_fields)
@@ -636,3 +638,13 @@ void localtime_to_TIME(TIME *to, struct tm *from)
to->minute= (int) from->tm_min;
to->second= (int) from->tm_sec;
}
+
+void calc_time_from_sec(TIME *to, long seconds, long microseconds)
+{
+ long t_seconds;
+ to->hour= seconds/3600L;
+ t_seconds= seconds%3600L;
+ to->minute= t_seconds/60L;
+ to->second= t_seconds%60L;
+ to->second_part= microseconds;
+}