From f8e232f95e423897fa3898a8e34bab2fefffe7f8 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Jun 2003 12:56:44 +0500 Subject: [PATCH 1/9] Internal commit --- mysql-test/r/func_sapdb.result | 194 ++++++++++++ mysql-test/t/func_sapdb.test | 97 ++++++ sql/field.cc | 2 + sql/item_create.cc | 35 +++ sql/item_create.h | 7 + sql/item_timefunc.cc | 538 +++++++++++++++++++++++++++++++-- sql/item_timefunc.h | 161 +++++++++- sql/lex.h | 16 +- sql/mysql_priv.h | 1 + sql/protocol.cc | 4 + sql/sql_yacc.yy | 33 ++ sql/time.cc | 13 +- 12 files changed, 1067 insertions(+), 34 deletions(-) create mode 100644 mysql-test/r/func_sapdb.result create mode 100644 mysql-test/t/func_sapdb.test diff --git a/mysql-test/r/func_sapdb.result b/mysql-test/r/func_sapdb.result new file mode 100644 index 00000000000..5c044d00726 --- /dev/null +++ b/mysql-test/r/func_sapdb.result @@ -0,0 +1,194 @@ +drop table if exists t1, test; +select extract(DAY_MICROSECOND FROM "1999-01-02 10:11:12.000123"); +extract(DAY_MICROSECOND FROM "1999-01-02 10:11:12.000123") +2101112000123 +select extract(HOUR_MICROSECOND FROM "1999-01-02 10:11:12.000123"); +extract(HOUR_MICROSECOND FROM "1999-01-02 10:11:12.000123") +101112000123 +select extract(MINUTE_MICROSECOND FROM "1999-01-02 10:11:12.000123"); +extract(MINUTE_MICROSECOND FROM "1999-01-02 10:11:12.000123") +1112000123 +select extract(SECOND_MICROSECOND FROM "1999-01-02 10:11:12.000123"); +extract(SECOND_MICROSECOND FROM "1999-01-02 10:11:12.000123") +12000123 +select extract(MICROSECOND FROM "1999-01-02 10:11:12.000123"); +extract(MICROSECOND FROM "1999-01-02 10:11:12.000123") +123 +select date_format("1997-12-31 23:59:59.000002", "%f"); +date_format("1997-12-31 23:59:59.000002", "%f") +000002 +select date_add("1997-12-31 23:59:59.000002",INTERVAL "10000 99:99:99.999999" DAY_MICROSECOND); +date_add("1997-12-31 23:59:59.000002",INTERVAL "10000 99:99:99.999999" DAY_MICROSECOND) +2025-05-23 04:40:39.000001 +select date_add("1997-12-31 23:59:59.000002",INTERVAL "10000:99:99.999999" HOUR_MICROSECOND); +date_add("1997-12-31 23:59:59.000002",INTERVAL "10000:99:99.999999" HOUR_MICROSECOND) +1999-02-21 17:40:39.000001 +select date_add("1997-12-31 23:59:59.000002",INTERVAL "10000:99.999999" MINUTE_MICROSECOND); +date_add("1997-12-31 23:59:59.000002",INTERVAL "10000:99.999999" MINUTE_MICROSECOND) +1998-01-07 22:41:39.000001 +select date_add("1997-12-31 23:59:59.000002",INTERVAL "10000.999999" SECOND_MICROSECOND); +date_add("1997-12-31 23:59:59.000002",INTERVAL "10000.999999" SECOND_MICROSECOND) +1998-01-01 02:46:40.000001 +select date_add("1997-12-31 23:59:59.000002",INTERVAL "999999" MICROSECOND); +date_add("1997-12-31 23:59:59.000002",INTERVAL "999999" MICROSECOND) +1998-01-01 00:00:00.000001 +select date_sub("1998-01-01 00:00:00.000001",INTERVAL "1 1:1:1.000002" DAY_MICROSECOND); +date_sub("1998-01-01 00:00:00.000001",INTERVAL "1 1:1:1.000002" DAY_MICROSECOND) +1997-12-30 22:58:58.999999 +select date_sub("1998-01-01 00:00:00.000001",INTERVAL "1:1:1.000002" HOUR_MICROSECOND); +date_sub("1998-01-01 00:00:00.000001",INTERVAL "1:1:1.000002" HOUR_MICROSECOND) +1997-12-31 22:58:58.999999 +select date_sub("1998-01-01 00:00:00.000001",INTERVAL "1:1.000002" MINUTE_MICROSECOND); +date_sub("1998-01-01 00:00:00.000001",INTERVAL "1:1.000002" MINUTE_MICROSECOND) +1997-12-31 23:58:58.999999 +select date_sub("1998-01-01 00:00:00.000001",INTERVAL "1.000002" SECOND_MICROSECOND); +date_sub("1998-01-01 00:00:00.000001",INTERVAL "1.000002" SECOND_MICROSECOND) +1997-12-31 23:59:58.999999 +select date_sub("1998-01-01 00:00:00.000001",INTERVAL "000002" MICROSECOND); +date_sub("1998-01-01 00:00:00.000001",INTERVAL "000002" MICROSECOND) +1997-12-31 23:59:59.999999 +select adddate("1997-12-31 23:59:59.000001", 10); +adddate("1997-12-31 23:59:59.000001", 10) +1998-01-10 23:59:59.000001 +select subdate("1997-12-31 23:59:59.000001", 10); +subdate("1997-12-31 23:59:59.000001", 10) +1997-12-21 23:59:59.000001 +select datediff("1997-12-31 23:59:59.000001","1997-12-30"); +datediff("1997-12-31 23:59:59.000001","1997-12-30") +1 +select datediff("1997-11-31 23:59:59.000001","1997-12-31"); +datediff("1997-11-31 23:59:59.000001","1997-12-31") +-30 +select datediff("1997-11-31 23:59:59.000001",null); +datediff("1997-11-31 23:59:59.000001",null) +NULL +select weekofyear("1997-11-31 23:59:59.000001"); +weekofyear("1997-11-31 23:59:59.000001") +49 +select makedate(1997,1); +makedate(1997,1) +1997-01-01 +select makedate(1997,0); +makedate(1997,0) +NULL +select addtime("1997-12-31 23:59:59.999999", "1 1:1:1.000002"); +addtime("1997-12-31 23:59:59.999999", "1 1:1:1.000002") +1998-01-02 01:01:01.000001 +select subtime("1997-12-31 23:59:59.000001", "1 1:1:1.000002"); +subtime("1997-12-31 23:59:59.000001", "1 1:1:1.000002") +1997-12-30 22:58:57.999999 +select addtime("1997-12-31 23:59:59.999999", "1998-01-01 01:01:01.999999"); +addtime("1997-12-31 23:59:59.999999", "1998-01-01 01:01:01.999999") +NULL +select subtime("1997-12-31 23:59:59.999999", "1998-01-01 01:01:01.999999"); +subtime("1997-12-31 23:59:59.999999", "1998-01-01 01:01:01.999999") +NULL +select subtime("01:00:00.999999", "02:00:00.999998"); +subtime("01:00:00.999999", "02:00:00.999998") +-00:59:59.999999 +select subtime("02:01:01.999999", "01:01:01.999999"); +subtime("02:01:01.999999", "01:01:01.999999") +01:00:00.000000 +select timediff("1997-01-01 23:59:59.000001","1995-12-31 23:59:59.000002"); +timediff("1997-01-01 23:59:59.000001","1995-12-31 23:59:59.000002") +8807:59:59.999999 +select timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002"); +timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002") +46:58:57.999999 +select timediff("1997-12-30 23:59:59.000001","1997-12-31 23:59:59.000002"); +timediff("1997-12-30 23:59:59.000001","1997-12-31 23:59:59.000002") +-23:59:59.999999 +select timediff("1997-12-31 23:59:59.000001","23:59:59.000001"); +timediff("1997-12-31 23:59:59.000001","23:59:59.000001") +NULL +select timediff("2000:01:01 00:00:00", "2000:01:01 00:00:00.1"); +timediff("2000:01:01 00:00:00", "2000:01:01 00:00:00.1") +-00:00:00.000001 +select maketime(10,11,12); +maketime(10,11,12) +10:11:12 +select maketime(25,11,12); +maketime(25,11,12) +25:11:12 +select maketime(-25,11,12); +maketime(-25,11,12) +-25:11:12 +select timestamp("2001-12-01", "01:01:01.999999"); +timestamp("2001-12-01", "01:01:01.999999") +2001-12-01 01:01:01.999999 +select timestamp("2001-13-01", "01:01:01.000001"); +timestamp("2001-13-01", "01:01:01.000001") +NULL +select timestamp("2001-12-01", "25:01:01"); +timestamp("2001-12-01", "25:01:01") +2001-12-02 01:01:01 +select day("1997-12-31 23:59:59.000001"); +day("1997-12-31 23:59:59.000001") +31 +select date("1997-12-31 23:59:59.000001"); +date("1997-12-31 23:59:59.000001") +1997-12-31 +select date("1997-13-31 23:59:59.000001"); +date("1997-13-31 23:59:59.000001") +NULL +select time("1997-12-31 23:59:59.000001"); +time("1997-12-31 23:59:59.000001") +23:59:59.000001 +select time("1997-12-31 25:59:59.000001"); +time("1997-12-31 25:59:59.000001") +NULL +select microsecond("1997-12-31 23:59:59.000001"); +microsecond("1997-12-31 23:59:59.000001") +1 +create table t1 +select makedate(1997,1) as f1, +addtime(cast("1997-12-31 23:59:59.000001" as datetime), "1 1:1:1.000002") as f2, +addtime(cast("23:59:59.999999" as time) , "1 1:1:1.000002") as f3, +timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002") as f4, +timediff("1997-12-30 23:59:59.000001","1997-12-31 23:59:59.000002") as f5, +maketime(10,11,12) as f6, +timestamp("2001-12-01", "01:01:01") as f7, +date("1997-12-31 23:59:59.000001") as f8, +time("1997-12-31 23:59:59.000001") as f9; +describe t1; +Field Type Null Key Default Extra +f1 date 0000-00-00 +f2 datetime 0000-00-00 00:00:00 +f3 time 00:00:00 +f4 time 00:00:00 +f5 time 00:00:00 +f6 time 00:00:00 +f7 datetime 0000-00-00 00:00:00 +f8 date 0000-00-00 +f9 time 00:00:00 +select * from t1; +f1 f2 f3 f4 f5 f6 f7 f8 f9 +1997-01-01 1998-01-02 01:01:00 49:01:01 46:58:57 -23:59:59 10:11:12 2001-12-01 01:01:01 1997-12-31 23:59:59 +create table test(t1 datetime, t2 time, t3 time, t4 datetime); +insert into test values +('2001-01-01 01:01:01', '01:01:01', null, '2001-02-01 01:01:01'), +('2001-01-01 01:01:01', '-01:01:01', '-23:59:59', "1997-12-31 23:59:59.000001"), +('1997-12-31 23:59:59.000001', '-23:59:59', '-01:01:01', '2001-01-01 01:01:01'), +('2001-01-01 01:01:01', '01:01:01', '-1 01:01:01', null), +('2001-01-01 01:01:01', null, '-1 01:01:01', null), +(null, null, null, null), +('2001-01-01 01:01:01', '01:01:01', '1 01:01:01', '2001-01-01 01:01:01'); +SELECT ADDTIME(t1,t2) As ttt, ADDTIME(t2, t3) As qqq from test; +ttt qqq +2001-01-01 02:02:02 NULL +2001-01-01 00:00:00 -25:01:00 +1997-12-31 00:00:00 -25:01:00 +2001-01-01 02:02:02 -24:00:00 +NULL NULL +NULL NULL +2001-01-01 02:02:02 26:02:02 +SELECT TIMEDIFF(t1,t4) As ttt, TIMEDIFF(t2, t3) As qqq from test; +ttt qqq +-744:00:00 NULL +26305:01:02 22:58:58 +-26305:01:02 -22:58:58 +NULL 26:02:02 +NULL NULL +NULL NULL +00:00:00 -24:00:00 +drop table t1, test; diff --git a/mysql-test/t/func_sapdb.test b/mysql-test/t/func_sapdb.test new file mode 100644 index 00000000000..05e1f20fe1e --- /dev/null +++ b/mysql-test/t/func_sapdb.test @@ -0,0 +1,97 @@ +--disable_warnings +drop table if exists t1, test; +--enable_warnings + + +# +# time functions +# +select extract(DAY_MICROSECOND FROM "1999-01-02 10:11:12.000123"); +select extract(HOUR_MICROSECOND FROM "1999-01-02 10:11:12.000123"); +select extract(MINUTE_MICROSECOND FROM "1999-01-02 10:11:12.000123"); +select extract(SECOND_MICROSECOND FROM "1999-01-02 10:11:12.000123"); +select extract(MICROSECOND FROM "1999-01-02 10:11:12.000123"); +select date_format("1997-12-31 23:59:59.000002", "%f"); + +select date_add("1997-12-31 23:59:59.000002",INTERVAL "10000 99:99:99.999999" DAY_MICROSECOND); +select date_add("1997-12-31 23:59:59.000002",INTERVAL "10000:99:99.999999" HOUR_MICROSECOND); +select date_add("1997-12-31 23:59:59.000002",INTERVAL "10000:99.999999" MINUTE_MICROSECOND); +select date_add("1997-12-31 23:59:59.000002",INTERVAL "10000.999999" SECOND_MICROSECOND); +select date_add("1997-12-31 23:59:59.000002",INTERVAL "999999" MICROSECOND); + +select date_sub("1998-01-01 00:00:00.000001",INTERVAL "1 1:1:1.000002" DAY_MICROSECOND); +select date_sub("1998-01-01 00:00:00.000001",INTERVAL "1:1:1.000002" HOUR_MICROSECOND); +select date_sub("1998-01-01 00:00:00.000001",INTERVAL "1:1.000002" MINUTE_MICROSECOND); +select date_sub("1998-01-01 00:00:00.000001",INTERVAL "1.000002" SECOND_MICROSECOND); +select date_sub("1998-01-01 00:00:00.000001",INTERVAL "000002" MICROSECOND); + +#Date functions +select adddate("1997-12-31 23:59:59.000001", 10); +select subdate("1997-12-31 23:59:59.000001", 10); + +select datediff("1997-12-31 23:59:59.000001","1997-12-30"); +select datediff("1997-11-31 23:59:59.000001","1997-12-31"); +select datediff("1997-11-31 23:59:59.000001",null); + +select weekofyear("1997-11-31 23:59:59.000001"); + +select makedate(1997,1); +select makedate(1997,0); + +#Time functions + +select addtime("1997-12-31 23:59:59.999999", "1 1:1:1.000002"); +select subtime("1997-12-31 23:59:59.000001", "1 1:1:1.000002"); +select addtime("1997-12-31 23:59:59.999999", "1998-01-01 01:01:01.999999"); +select subtime("1997-12-31 23:59:59.999999", "1998-01-01 01:01:01.999999"); +select subtime("01:00:00.999999", "02:00:00.999998"); +select subtime("02:01:01.999999", "01:01:01.999999"); + +select timediff("1997-01-01 23:59:59.000001","1995-12-31 23:59:59.000002"); +select timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002"); +select timediff("1997-12-30 23:59:59.000001","1997-12-31 23:59:59.000002"); +select timediff("1997-12-31 23:59:59.000001","23:59:59.000001"); +select timediff("2000:01:01 00:00:00", "2000:01:01 00:00:00.1"); + +select maketime(10,11,12); +select maketime(25,11,12); +select maketime(-25,11,12); + +#Extraction functions +select timestamp("2001-12-01", "01:01:01.999999"); +select timestamp("2001-13-01", "01:01:01.000001"); +select timestamp("2001-12-01", "25:01:01"); +select day("1997-12-31 23:59:59.000001"); +select date("1997-12-31 23:59:59.000001"); +select date("1997-13-31 23:59:59.000001"); +select time("1997-12-31 23:59:59.000001"); +select time("1997-12-31 25:59:59.000001"); +select microsecond("1997-12-31 23:59:59.000001"); + +create table t1 +select makedate(1997,1) as f1, + addtime(cast("1997-12-31 23:59:59.000001" as datetime), "1 1:1:1.000002") as f2, + addtime(cast("23:59:59.999999" as time) , "1 1:1:1.000002") as f3, + timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002") as f4, + timediff("1997-12-30 23:59:59.000001","1997-12-31 23:59:59.000002") as f5, + maketime(10,11,12) as f6, + timestamp("2001-12-01", "01:01:01") as f7, + date("1997-12-31 23:59:59.000001") as f8, + time("1997-12-31 23:59:59.000001") as f9; +describe t1; +select * from t1; + +create table test(t1 datetime, t2 time, t3 time, t4 datetime); +insert into test values +('2001-01-01 01:01:01', '01:01:01', null, '2001-02-01 01:01:01'), +('2001-01-01 01:01:01', '-01:01:01', '-23:59:59', "1997-12-31 23:59:59.000001"), +('1997-12-31 23:59:59.000001', '-23:59:59', '-01:01:01', '2001-01-01 01:01:01'), +('2001-01-01 01:01:01', '01:01:01', '-1 01:01:01', null), +('2001-01-01 01:01:01', null, '-1 01:01:01', null), +(null, null, null, null), +('2001-01-01 01:01:01', '01:01:01', '1 01:01:01', '2001-01-01 01:01:01'); + +SELECT ADDTIME(t1,t2) As ttt, ADDTIME(t2, t3) As qqq from test; +SELECT TIMEDIFF(t1,t4) As ttt, TIMEDIFF(t2, t3) As qqq from test; + +drop table t1, test; diff --git a/sql/field.cc b/sql/field.cc index a61654ed8f4..07682e36287 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -3150,11 +3150,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 3edec7fdab0..19edcaad3f6 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -678,3 +678,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); +} + +Item *create_func_subtime(Item* a,Item* b) +{ + return new Item_func_add_time(a, b, 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 b679c639244..f905e27ea00 100644 --- a/sql/item_create.h +++ b/sql/item_create.h @@ -146,3 +146,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_timefunc.cc b/sql/item_timefunc.cc index 61c869cddba..fd2bca591a7 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -55,6 +55,70 @@ 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} +}; + + +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 +373,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 +416,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 +437,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 +461,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 +482,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 +784,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: @@ -844,6 +944,10 @@ String *Item_func_date_format::val_str(String *str) sprintf(intbuff,"%d",l_time.day); str->append(intbuff); break; + case 'f': + sprintf(intbuff,"%06ld",l_time.second_part); + str->append(intbuff); + break; case 'H': sprintf(intbuff,"%02d",l_time.hour); str->append(intbuff,2); @@ -1005,7 +1109,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*default_charset()->mbmaxlen; value.alloc(32); /* @@ -1051,27 +1155,43 @@ 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; @@ -1124,34 +1244,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(<ime,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); - } - 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; - null_date: + if (ltime.time_type == TIMESTAMP_DATE) + format= DATE_ONLY; + else if (ltime.second_part) + format= DATE_TIME_MICROSECOND; + else + format= DATE_TIME; + + if (make_datetime(str, <ime, format)) + return str; + null_value=1; return 0; } @@ -1188,6 +1295,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 +1346,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 +1374,358 @@ void Item_typecast::print(String *str) str->append(func_name()); str->append(')'); } + +/* + 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 < 3652424L) // 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.mbmaxlen; + + /* + 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_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; + long microseconds, seconds, days= 0; + int l_sign= sign; + + null_value=0; + 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); + l_time3.neg= 0; + if (is_time) + { + if ((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, DATE_TIME_MICROSECOND)) + return str; + goto null_date; + } + + l_time3.hour+= days*24; + if (make_datetime(str, &l_time3, TIME_MICROSECOND)) + 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, TIME_MICROSECOND)) + 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, <ime, TIME_ONLY)) + return str; + +null_date: + return 0; +} + +/* + TIMESTAMP(a,b) is a function ( extraction) that calculates a datetime value + comprising a date value, time value. + + a: Date_or_datetime value + b: Time value + Result: Datetime value +*/ + +String *Item_func_timestamp::val_str(String *str) +{ + TIME l_time1 ,l_time2, l_time3; + long seconds; + long microseconds; + long days; + int l_sign; + + 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; + + l_sign= l_time2.neg ? -1 : 1; + days= (calc_daynr((uint) l_time1.year,(uint) l_time1.month, + (uint) l_time1.day) + l_sign*l_time2.day); + + 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); + days+= seconds/86400L; + seconds%= 86400L; + if (microseconds < 0) + { + microseconds+= 1000000L; + seconds--; + } + if (seconds < 0) + { + days--; + seconds+= 86400L; + } + if (days < 0) + goto null_date; + + calc_time_from_sec(&l_time3, seconds, microseconds); + get_date_from_daynr(days,&l_time3.year,&l_time3.month,&l_time3.day); + make_datetime(str, &l_time3, DATE_TIME_MICROSECOND); + return str; + +null_date: + null_value=1; + return 0; +} + +/* + DATE(a) is a function ( extraction) that calculates a date value. + + a: Datetime value + Result: Date value +*/ +String *Item_func_date::val_str(String *str) +{ + TIME ltime; + + if (!get_arg0_date(<ime,1) && + make_datetime(str, <ime, DATE_ONLY)) + return str; + +null_date: + null_value=1; + return 0; +} + +/* + TIME(a) is a function ( extraction) that calculates a time value. + + a: Datetime value + Result: Time value +*/ +String *Item_func_time::val_str(String *str) +{ + TIME ltime; + + if (!get_arg0_time(<ime) && + make_datetime(str, <ime, TIME_MICROSECOND)) + return str; + + null_value=1; + 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(<ime)) + return ltime.second_part; + return 0; +} diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 87563cf9f47..ea29731fe35 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 }; @@ -592,3 +593,157 @@ 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.mbmaxlen; + } + 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 +{ + int sign; + enum_field_types cached_field_type; + +public: + Item_func_add_time(Item *a, Item *b, bool neg_arg) + :Item_str_func(a, b) { 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(); + 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.mbmaxlen; + } + 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.mbmaxlen; + } + 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_timestamp :public Item_str_func +{ +public: + Item_func_timestamp(Item *a, Item *b) :Item_str_func(a, b) {} + String *val_str(String *str); + const char *func_name() const { return "timestamp"; } + enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; } + void fix_length_and_dec() + { + decimals=0; + max_length=26*my_charset_bin.mbmaxlen; + } + Field *tmp_table_field() { return result_field; } + Field *tmp_table_field(TABLE *t_arg) + { + return (new Field_datetime(maybe_null, name, t_arg, &my_charset_bin)); + } +}; + +class Item_func_date :public Item_str_func +{ +public: + Item_func_date(Item *a) + :Item_str_func(a) {} + String *val_str(String *str); + const char *func_name() const { return "date"; } + enum_field_types field_type() const { return MYSQL_TYPE_DATE; } + void fix_length_and_dec() + { + decimals=0; + max_length=10*my_charset_bin.mbmaxlen; + } + 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_time :public Item_str_func +{ +public: + Item_func_time(Item *a) + :Item_str_func(a) {} + String *val_str(String *str); + const char *func_name() const { return "time"; } + enum_field_types field_type() const { return MYSQL_TYPE_TIME; } + void fix_length_and_dec() + { + decimals=0; + max_length=15*my_charset_bin.mbmaxlen; + } + 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 e89c9f51520..8abf96645ec 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}, @@ -258,9 +260,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}, @@ -336,6 +340,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}, @@ -425,7 +430,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)}, @@ -467,6 +473,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)}, @@ -542,6 +549,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)}, @@ -602,7 +611,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)}, @@ -617,12 +626,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}, @@ -637,6 +648,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 a59f1d4b81a..9aad06bd21d 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -844,6 +844,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); diff --git a/sql/protocol.cc b/sql/protocol.cc index 7abbf3ce85b..b214b5627d5 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -862,6 +862,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); } @@ -898,6 +900,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/sql_yacc.yy b/sql/sql_yacc.yy index 1002d06be88..53fe2d4c123 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 @@ -430,6 +431,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token VARYING %token ZEROFILL +%token ADDDATE_SYM %token AGAINST %token ATAN %token BETWEEN_SYM @@ -444,6 +446,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 @@ -466,6 +469,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 @@ -480,6 +484,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 @@ -504,7 +510,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 @@ -2255,6 +2263,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 ')' @@ -2289,6 +2301,10 @@ simple_expr: $$= new Item_func_database(); Lex->safe_to_cache_query=0; } + | DATE_SYM '(' expr ')' + { $$= new Item_func_date($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 ')' @@ -2405,6 +2421,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 ')' @@ -2466,6 +2484,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 ')' @@ -2478,6 +2500,10 @@ 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_func_time($3); } + | TIMESTAMP '(' expr ',' expr ')' + { $$= new Item_func_timestamp($3, $5); } | TRIM '(' expr ')' { $$= new Item_func_trim($3,new Item_string(" ",1,default_charset_info)); } | TRIM '(' LEADING opt_pad FROM expr ')' @@ -2892,15 +2918,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; }; @@ -4191,6 +4222,7 @@ user: keyword: ACTION {} + | ADDDATE_SYM {} | AFTER_SYM {} | AGAINST {} | AGGREGATE_SYM {} @@ -4349,6 +4381,7 @@ keyword: | STATUS_SYM {} | STOP_SYM {} | STRING_SYM {} + | SUBDATE_SYM {} | SUBJECT_SYM {} | SUPER_SYM {} | TEMPORARY {} diff --git a/sql/time.cc b/sql/time.cc index eba664a690d..81624ba7287 100644 --- a/sql/time.cc +++ b/sql/time.cc @@ -567,7 +567,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]) && @@ -590,6 +590,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) @@ -622,3 +623,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; +} From e17562b55af10d9415e9dfefe7cba0ade1e49bca Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 6 Jul 2003 19:09:57 +0300 Subject: [PATCH 2/9] Support for variables with components Added framework to create/drop and manager buffers for multiple key caches include/my_getopt.h: Fixed prototype include/my_sys.h: Added (temporary) KEY_CACHE type include/mysqld_error.h: New error messages mysql-test/r/select_safe.result: Updated test results mysql-test/r/variables.result: Updated test results mysys/my_getopt.c: Fixed bugs with GET_ASK_ADDR sql/Makefile.am: Make sql_yacc.o depend on all header files in sql directory sql/item_func.cc: Added support for variable components sql/mysql_priv.h: Added support for variable components sql/mysqld.cc: Added support for multiple key caches sql/set_var.cc: Added support for multiple key caches sql/set_var.h: Added support for multiple key caches sql/share/czech/errmsg.txt: New error messages sql/share/danish/errmsg.txt: New error messages sql/share/dutch/errmsg.txt: New error messages sql/share/english/errmsg.txt: New error messages sql/share/estonian/errmsg.txt: New error messages sql/share/french/errmsg.txt: New error messages sql/share/german/errmsg.txt: New error messages sql/share/greek/errmsg.txt: New error messages sql/share/hungarian/errmsg.txt: New error messages sql/share/italian/errmsg.txt: New error messages sql/share/japanese/errmsg.txt: New error messages sql/share/korean/errmsg.txt: New error messages sql/share/norwegian-ny/errmsg.txt: New error messages sql/share/norwegian/errmsg.txt: New error messages sql/share/polish/errmsg.txt: New error messages sql/share/portuguese/errmsg.txt: New error messages sql/share/romanian/errmsg.txt: New error messages sql/share/russian/errmsg.txt: New error messages sql/share/serbian/errmsg.txt: New error messages sql/share/slovak/errmsg.txt: New error messages sql/share/spanish/errmsg.txt: New error messages sql/share/swedish/errmsg.txt: New error messages sql/share/ukrainian/errmsg.txt: New error messages sql/sql_lex.cc: Fixes for quoting of variables. sql/sql_parse.cc: Fix after changing prototype for get_system_var sql/sql_show.cc: Fix after introducing variable components sql/sql_yacc.yy: Support for variables with components (To support multiple key caches) --- include/my_getopt.h | 2 +- include/my_sys.h | 6 + include/mysqld_error.h | 3 +- mysql-test/r/key_cache.result | 43 ++++++ mysql-test/r/select_safe.result | 2 +- mysql-test/r/variables.result | 2 +- mysql-test/t/key_cache-master.opt | 1 + mysql-test/t/key_cache.test | 42 ++++++ mysys/my_getopt.c | 61 +++++---- sql/Makefile.am | 2 +- sql/item_func.cc | 78 +++++++++-- sql/mysql_priv.h | 8 +- sql/mysqld.cc | 31 ++++- sql/set_var.cc | 218 +++++++++++++++++++++++++----- sql/set_var.h | 105 ++++++++++---- sql/share/czech/errmsg.txt | 1 + sql/share/danish/errmsg.txt | 1 + sql/share/dutch/errmsg.txt | 1 + sql/share/english/errmsg.txt | 1 + sql/share/estonian/errmsg.txt | 1 + sql/share/french/errmsg.txt | 1 + sql/share/german/errmsg.txt | 1 + sql/share/greek/errmsg.txt | 1 + sql/share/hungarian/errmsg.txt | 1 + sql/share/italian/errmsg.txt | 1 + sql/share/japanese/errmsg.txt | 1 + sql/share/korean/errmsg.txt | 1 + sql/share/norwegian-ny/errmsg.txt | 1 + sql/share/norwegian/errmsg.txt | 1 + sql/share/polish/errmsg.txt | 1 + sql/share/portuguese/errmsg.txt | 1 + sql/share/romanian/errmsg.txt | 1 + sql/share/russian/errmsg.txt | 1 + sql/share/serbian/errmsg.txt | 1 + sql/share/slovak/errmsg.txt | 1 + sql/share/spanish/errmsg.txt | 1 + sql/share/swedish/errmsg.txt | 1 + sql/share/ukrainian/errmsg.txt | 1 + sql/sql_lex.cc | 23 ++-- sql/sql_parse.cc | 11 +- sql/sql_show.cc | 5 +- sql/sql_yacc.yy | 33 ++++- 42 files changed, 572 insertions(+), 127 deletions(-) create mode 100644 mysql-test/r/key_cache.result create mode 100644 mysql-test/t/key_cache-master.opt create mode 100644 mysql-test/t/key_cache.test diff --git a/include/my_getopt.h b/include/my_getopt.h index 213c8c3570e..148238f8d1b 100644 --- a/include/my_getopt.h +++ b/include/my_getopt.h @@ -53,7 +53,7 @@ extern int handle_options (int *argc, char ***argv, char *)); extern void my_print_help(const struct my_option *options); extern void my_print_variables(const struct my_option *options); -extern void my_getopt_register_get_addr(gptr* (*func_addr)(char *, uint, +extern void my_getopt_register_get_addr(gptr* (*func_addr)(const char *, uint, const struct my_option *)); ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp); diff --git a/include/my_sys.h b/include/my_sys.h index 48ebdc22f37..7ea9f63a50f 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -501,6 +501,12 @@ my_off_t my_b_append_tell(IO_CACHE* info); #define my_b_bytes_in_cache(info) (uint) (*(info)->current_end - \ *(info)->current_pos) +/* key_cache_variables */ +typedef struct st_keycache +{ + ulonglong size; +} KEY_CACHE; + #include /* Prototypes for mysys and my_func functions */ diff --git a/include/mysqld_error.h b/include/mysqld_error.h index 565c2812c50..0468663239b 100644 --- a/include/mysqld_error.h +++ b/include/mysqld_error.h @@ -286,4 +286,5 @@ #define ER_REVOKE_GRANTS 1267 #define ER_CANT_AGGREGATE_3COLLATIONS 1268 #define ER_CANT_AGGREGATE_NCOLLATIONS 1269 -#define ER_ERROR_MESSAGES 270 +#define ER_VARIABLE_IS_NOT_STRUCT 1270 +#define ER_ERROR_MESSAGES 271 diff --git a/mysql-test/r/key_cache.result b/mysql-test/r/key_cache.result new file mode 100644 index 00000000000..8ec507b2a3f --- /dev/null +++ b/mysql-test/r/key_cache.result @@ -0,0 +1,43 @@ +SET @save_key_buffer=@@key_buffer_size; +SELECT @@key_buffer_size, @@small.key_buffer_size; +@@key_buffer_size @@small.key_buffer_size +2097152 131072 +SET @@global.key_buffer_size=16*1024*1024; +SET @@global.default.key_buffer_size=16*1024*1024; +SET @@global.default.key_buffer_size=16*1024*1024; +SET @@global.small.key_buffer_size=1*1024*1024; +SET @@global.medium.key_buffer_size=4*1024*1024; +SET @@global.medium.key_buffer_size=0; +SET @@global.medium.key_buffer_size=0; +SHOW VARIABLES like "key_buffer_size"; +Variable_name Value +key_buffer_size 16777216 +SELECT @@key_buffer_size; +@@key_buffer_size +16777216 +SELECT @@global.key_buffer_size; +@@global.key_buffer_size +16777216 +SELECT @@global.default.key_buffer_size; +@@global.default.key_buffer_size +16777216 +SELECT @@global.default.`key_buffer_size`; +@@global.default.key_buffer_size +16777216 +SELECT @@global.`default`.`key_buffer_size`; +@@global.default.key_buffer_size +16777216 +SELECT @@`default`.key_buffer_size; +@@default.key_buffer_size +16777216 +SELECT @@small.key_buffer_size; +@@small.key_buffer_size +1048576 +SELECT @@medium.key_buffer_size; +@@medium.key_buffer_size +4194304 +SET @@global.key_buffer_size=@save_key_buffer; +SELECT @@default.key_buffer_size; +ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'default.key_buffer_size' at line 1 +SELECT @@skr.table_type="test"; +ERROR HY000: Variable 'table_type' is not a variable component (Can't be used as XXXX.variable_name) diff --git a/mysql-test/r/select_safe.result b/mysql-test/r/select_safe.result index e73161996b8..0f2a781d073 100644 --- a/mysql-test/r/select_safe.result +++ b/mysql-test/r/select_safe.result @@ -37,7 +37,7 @@ delete from t1 where b="test" limit 1; delete from t1 where a+0=1 limit 2; SET MAX_JOIN_SIZE=2; SELECT @@MAX_JOIN_SIZE, @@SQL_BIG_SELECTS; -@@max_join_size @@sql_big_selects +@@MAX_JOIN_SIZE @@SQL_BIG_SELECTS 2 0 insert into t1 values (null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"); SELECT * from t1; diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index 1a773acd23e..4db791c993e 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -77,7 +77,7 @@ select last_insert_id(345); last_insert_id(345) 345 select @@IDENTITY,last_insert_id(), @@identity; -@@identity last_insert_id() @@identity +@@IDENTITY last_insert_id() @@identity 345 345 345 set big_tables=OFF, big_tables=ON, big_tables=0, big_tables=1, big_tables="OFF", big_tables="ON"; set global concurrent_insert=ON; diff --git a/mysql-test/t/key_cache-master.opt b/mysql-test/t/key_cache-master.opt new file mode 100644 index 00000000000..66e19c18a8a --- /dev/null +++ b/mysql-test/t/key_cache-master.opt @@ -0,0 +1 @@ +--key_buffer_size=2M --small.key_buffer_size=256K --small.key_buffer_size=128K diff --git a/mysql-test/t/key_cache.test b/mysql-test/t/key_cache.test new file mode 100644 index 00000000000..2da18b68624 --- /dev/null +++ b/mysql-test/t/key_cache.test @@ -0,0 +1,42 @@ +# +# Test of key cache +# + +SET @save_key_buffer=@@key_buffer_size; + +SELECT @@key_buffer_size, @@small.key_buffer_size; + +# Change default key cache size +SET @@global.key_buffer_size=16*1024*1024; +SET @@global.default.key_buffer_size=16*1024*1024; +SET @@global.default.key_buffer_size=16*1024*1024; + +SET @@global.small.key_buffer_size=1*1024*1024; +SET @@global.medium.key_buffer_size=4*1024*1024; +# Drop buffer +SET @@global.medium.key_buffer_size=0; +# Test double drop +SET @@global.medium.key_buffer_size=0; + +# Print key buffer with different syntaxes +SHOW VARIABLES like "key_buffer_size"; +SELECT @@key_buffer_size; +SELECT @@global.key_buffer_size; +SELECT @@global.default.key_buffer_size; +SELECT @@global.default.`key_buffer_size`; +SELECT @@global.`default`.`key_buffer_size`; +SELECT @@`default`.key_buffer_size; + +SELECT @@small.key_buffer_size; +SELECT @@medium.key_buffer_size; + +SET @@global.key_buffer_size=@save_key_buffer; + +# +# Errors +# + +--error 1064 +SELECT @@default.key_buffer_size; +--error 1270 +SELECT @@skr.table_type="test"; diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 83ba8b98843..d539489cf1e 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -32,7 +32,7 @@ static longlong getopt_ll(char *arg, const struct my_option *optp, int *err); static ulonglong getopt_ull(char *arg, const struct my_option *optp, int *err); static void init_variables(const struct my_option *options); -static int setval(const struct my_option *opts, char *argument, +static int setval(const struct my_option *opts, gptr *value, char *argument, my_bool set_maximum_value); static char *check_struct_option(char *cur_arg, char *key_name); @@ -68,9 +68,9 @@ my_bool my_getopt_print_errors= 1; one. Call function 'get_one_option()' once for each option. */ -static gptr* (*getopt_get_addr)(char *, uint, const struct my_option *); +static gptr* (*getopt_get_addr)(const char *, uint, const struct my_option *); -void my_getopt_register_get_addr(gptr* (*func_addr)(char *, uint, +void my_getopt_register_get_addr(gptr* (*func_addr)(const char *, uint, const struct my_option *)) { getopt_get_addr= func_addr; @@ -395,7 +395,8 @@ int handle_options(int *argc, char ***argv, /* the other loop will break, because *optend + 1 == 0 */ } } - if ((error= setval(optp, argument, set_maximum_value))) + if ((error= setval(optp, optp->value, argument, + set_maximum_value))) { fprintf(stderr, "%s: Error while setting value '%s' to '%s'\n", @@ -417,7 +418,7 @@ int handle_options(int *argc, char ***argv, (*argc)--; /* option handled (short), decrease argument count */ continue; } - if ((error= setval(optp, argument, set_maximum_value))) + if ((error= setval(optp, value, argument, set_maximum_value))) { fprintf(stderr, "%s: Error while setting value '%s' to '%s'\n", @@ -473,13 +474,13 @@ static char *check_struct_option(char *cur_arg, char *key_name) if (end - ptr > 1) { uint len= ptr - cur_arg; - strnmov(key_name, cur_arg, len); - key_name[len]= '\0'; + set_if_smaller(len, FN_REFLEN-1); + strmake(key_name, cur_arg, len); return ++ptr; } else { - key_name= 0; + key_name[0]= 0; return cur_arg; } } @@ -491,15 +492,15 @@ static char *check_struct_option(char *cur_arg, char *key_name) Will set the option value to given value */ -static int setval(const struct my_option *opts, char *argument, +static int setval(const struct my_option *opts, gptr *value, char *argument, my_bool set_maximum_value) { int err= 0; - if (opts->value && argument) + if (value && argument) { gptr *result_pos= ((set_maximum_value) ? - opts->u_max_value : opts->value); + opts->u_max_value : value); if (!result_pos) return EXIT_NO_PTR_TO_VARIABLE; @@ -692,43 +693,45 @@ static void init_variables(const struct my_option *options) { for (; options->name; options++) { - if (options->value) + gptr *value= (options->var_type & GET_ASK_ADDR ? + (*getopt_get_addr)("", 0, options) : options->value); + if (value) { switch ((options->var_type & GET_TYPE_MASK)) { case GET_BOOL: if (options->u_max_value) *((my_bool*) options->u_max_value)= (my_bool) options->max_value; - *((my_bool*) options->value)= (my_bool) options->def_value; + *((my_bool*) value)= (my_bool) options->def_value; break; case GET_INT: if (options->u_max_value) *((int*) options->u_max_value)= (int) options->max_value; - *((int*) options->value)= (int) options->def_value; + *((int*) value)= (int) options->def_value; break; case GET_UINT: if (options->u_max_value) *((uint*) options->u_max_value)= (uint) options->max_value; - *((uint*) options->value)= (uint) options->def_value; + *((uint*) value)= (uint) options->def_value; break; case GET_LONG: if (options->u_max_value) *((long*) options->u_max_value)= (long) options->max_value; - *((long*) options->value)= (long) options->def_value; + *((long*) value)= (long) options->def_value; break; case GET_ULONG: if (options->u_max_value) *((ulong*) options->u_max_value)= (ulong) options->max_value; - *((ulong*) options->value)= (ulong) options->def_value; + *((ulong*) value)= (ulong) options->def_value; break; case GET_LL: if (options->u_max_value) *((longlong*) options->u_max_value)= (longlong) options->max_value; - *((longlong*) options->value)= (longlong) options->def_value; + *((longlong*) value)= (longlong) options->def_value; break; case GET_ULL: if (options->u_max_value) *((ulonglong*) options->u_max_value)= (ulonglong) options->max_value; - *((ulonglong*) options->value)= (ulonglong) options->def_value; + *((ulonglong*) value)= (ulonglong) options->def_value; break; default: /* dummy default to avoid compiler warnings */ break; @@ -831,7 +834,9 @@ void my_print_variables(const struct my_option *options) printf("--------------------------------- -----------------------------\n"); for (optp= options; optp->id; optp++) { - if (optp->value) + gptr *value= (optp->var_type & GET_ASK_ADDR ? + (*getopt_get_addr)("", 0, optp) : optp->value); + if (value) { printf("%s", optp->name); length= strlen(optp->name); @@ -840,29 +845,29 @@ void my_print_variables(const struct my_option *options) switch ((optp->var_type & GET_TYPE_MASK)) { case GET_STR: case GET_STR_ALLOC: /* fall through */ - printf("%s\n", *((char**) optp->value) ? *((char**) optp->value) : + printf("%s\n", *((char**) value) ? *((char**) value) : "(No default value)"); break; case GET_BOOL: - printf("%s\n", *((my_bool*) optp->value) ? "TRUE" : "FALSE"); + printf("%s\n", *((my_bool*) value) ? "TRUE" : "FALSE"); break; case GET_INT: - printf("%d\n", *((int*) optp->value)); + printf("%d\n", *((int*) value)); break; case GET_UINT: - printf("%d\n", *((uint*) optp->value)); + printf("%d\n", *((uint*) value)); break; case GET_LONG: - printf("%lu\n", *((long*) optp->value)); + printf("%lu\n", *((long*) value)); break; case GET_ULONG: - printf("%lu\n", *((ulong*) optp->value)); + printf("%lu\n", *((ulong*) value)); break; case GET_LL: - printf("%s\n", llstr(*((longlong*) optp->value), buff)); + printf("%s\n", llstr(*((longlong*) value), buff)); break; case GET_ULL: - longlong2str(*((ulonglong*) optp->value), buff, 10); + longlong2str(*((ulonglong*) value), buff, 10); printf("%s\n", buff); break; default: /* dummy default to avoid compiler warnings */ 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/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 (!(var= find_sys_var(name.str, name.length))) + if (component.str) + { + base_name= &component; + component_name= &name; + } + else + { + base_name= &name; + component_name= &component; // Empty string + } + + 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/mysql_priv.h b/sql/mysql_priv.h index 5ad2cc56b8c..e54e66a236a 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -770,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 threads; +extern I_List key_caches; extern MY_BITMAP temp_pool; extern DATE_FORMAT dayord; extern String empty_string; @@ -903,9 +904,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 0a3985c3ee9..709ba036f7e 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -312,11 +312,12 @@ const char *sql_mode_str="OFF"; FILE *bootstrap_file; -I_List replicate_rewrite_db; +I_List replicate_rewrite_db; I_List replicate_do_db, replicate_ignore_db; // allow the user to tell us which db to replicate and which to ignore I_List binlog_do_db, binlog_ignore_db; I_List threads,thread_cache; +I_List key_caches; struct system_variables global_system_variables; struct system_variables max_system_variables; @@ -875,6 +876,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(); @@ -4103,7 +4105,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, @@ -4679,6 +4681,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(); @@ -5309,16 +5314,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; @@ -5366,6 +5385,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); } @@ -5580,6 +5601,6 @@ template class I_List; template class I_List_iterator; template class I_List; template class I_List; - +template class I_List; FIX_GCC_LINKING_PROBLEM #endif diff --git a/sql/set_var.cc b/sql/set_var.cc index a281fac530a..cb6c875d513 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); @@ -793,12 +791,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) { @@ -870,7 +862,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]; } @@ -906,7 +898,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); @@ -951,7 +944,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); @@ -994,7 +988,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); @@ -1021,7 +1016,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); @@ -1115,7 +1111,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)) { @@ -1131,16 +1127,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: @@ -1169,7 +1165,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 : @@ -1186,7 +1183,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. @@ -1249,6 +1247,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; @@ -1274,20 +1273,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; @@ -1295,7 +1298,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; @@ -1304,7 +1309,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; @@ -1312,6 +1318,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) @@ -1320,6 +1327,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) @@ -1328,6 +1336,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) @@ -1336,6 +1345,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) @@ -1344,6 +1354,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) @@ -1352,7 +1363,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; @@ -1360,6 +1373,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) @@ -1368,6 +1382,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) @@ -1377,7 +1392,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 : @@ -1385,6 +1402,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) @@ -1394,6 +1412,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 @@ -1429,7 +1512,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; @@ -1443,7 +1527,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; @@ -1457,7 +1542,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; } @@ -1848,7 +1934,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]; @@ -1945,6 +2032,68 @@ ulong fix_sql_mode(ulong sql_mode) } +/**************************************************************************** + Named list handling +****************************************************************************/ + +gptr find_named(I_List *list, const char *name, uint length) +{ + I_List_iterator it(*list); + NAMED_LIST *element; + while ((element= it++)) + { + if (element->cmp(name, length)) + return element->data; + } + return 0; +} + + +void delete_elements(I_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 @@ -1953,4 +2102,5 @@ ulong fix_sql_mode(ulong sql_mode) #ifdef __GNUC__ template class List; template class List_iterator_fast; +template class I_List_iterator; #endif diff --git a/sql/set_var.h b/sql/set_var.h index 5a0fbd21809..978aba3384a 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,33 @@ public: }; +/* Named lists (used for keycaches) */ + +class NAMED_LIST :public ilink +{ + const char *name; + uint name_length; +public: + gptr data; + + NAMED_LIST(I_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)); + } +}; + + /* Prototypes for helper functions */ @@ -649,6 +703,11 @@ sys_var *find_sys_var(const char *str, uint length=0); int sql_set_variables(THD *thd, List *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); +gptr find_named(I_List *list, const char *name, uint length); +void delete_elements(I_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 641b1384e9a..0bd8b70a96f 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -275,3 +275,4 @@ 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)", diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index 574d26b7c1c..64ffdea0d71 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -269,3 +269,4 @@ "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)", diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index c6c975cb141..3a506c7ef69 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -277,3 +277,4 @@ "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)", diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index f39c415fa55..83b90089701 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -271,3 +271,4 @@ "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)", diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index de22d6fd111..f4107e91d5b 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -271,3 +271,4 @@ "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)", diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 6c1187cd0e4..9549e98326c 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -266,3 +266,4 @@ "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)", diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index 78d53034a71..0c60685d520 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -275,3 +275,4 @@ "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)", diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index 347370f1ac8..873f8385462 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -266,3 +266,4 @@ "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)", diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index 313275b3cb6..93ab550b60f 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -268,3 +268,4 @@ "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)", diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index 8af7e3ba9f7..d1a5b1b301f 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -266,3 +266,4 @@ "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)", diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index 417a03978fb..b8bc6e1d761 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -268,3 +268,4 @@ "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)", diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index 22395d0fb6a..9bbcaa16076 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -266,3 +266,4 @@ "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)", diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index de6db62cdce..53b46d3f943 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -268,3 +268,4 @@ "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)", diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index 28db8caa8bc..26e6b39a77f 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -268,3 +268,4 @@ "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)", diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index fdf856c7e56..60b0779db99 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -270,3 +270,4 @@ "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)", diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index 397784dc7dd..904d7107893 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -266,3 +266,4 @@ "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)", diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 8f1cdb7b259..28bb5750d41 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -270,3 +270,4 @@ "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)", diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index ec41a6acb34..e193eac6793 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -268,3 +268,4 @@ "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)", diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt index 77d35be2fc9..3fbd7635ce9 100644 --- a/sql/share/serbian/errmsg.txt +++ b/sql/share/serbian/errmsg.txt @@ -262,3 +262,4 @@ "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)", diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 33cabdfc752..b25935131d5 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -274,3 +274,4 @@ "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)", diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 35e26f35ff7..777ef612a76 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -267,3 +267,4 @@ "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)", diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index 9cdcb20db35..2166d7fe143 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -266,3 +266,4 @@ "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)", diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index 5a614714de2..2fc14372f54 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -271,3 +271,4 @@ "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)", 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 0db6ce8a642..3593087d332 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3570,15 +3570,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_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 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_yacc.yy b/sql/sql_yacc.yy index 6072be28dca..0651672a305 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -561,7 +561,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 opt_table_alias @@ -1532,6 +1532,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); }; @@ -2276,9 +2280,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 @@ -2440,7 +2444,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; } @@ -4590,6 +4594,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: From 1be34f26b3137a28abd4c69ce73c23cbf4a3a8ee Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 7 Jul 2003 23:35:24 -0500 Subject: [PATCH 3/9] Error message edits. (Change sentence ending with period + sentence not ending with period into single sentence.) sql/share/czech/errmsg.txt: Error message edits. sql/share/danish/errmsg.txt: Error message edits. sql/share/dutch/errmsg.txt: Error message edits. sql/share/english/errmsg.txt: Error message edits. sql/share/french/errmsg.txt: Error message edits. sql/share/german/errmsg.txt: Error message edits. sql/share/italian/errmsg.txt: Error message edits. sql/share/norwegian-ny/errmsg.txt: Error message edits. sql/share/norwegian/errmsg.txt: Error message edits. sql/share/polish/errmsg.txt: Error message edits. sql/share/portuguese/errmsg.txt: Error message edits. sql/share/romanian/errmsg.txt: Error message edits. sql/share/serbian/errmsg.txt: Error message edits. sql/share/slovak/errmsg.txt: Error message edits. sql/share/spanish/errmsg.txt: Error message edits. sql/share/swedish/errmsg.txt: Error message edits. --- sql/share/czech/errmsg.txt | 2 +- sql/share/danish/errmsg.txt | 4 ++-- sql/share/dutch/errmsg.txt | 4 ++-- sql/share/english/errmsg.txt | 4 ++-- sql/share/french/errmsg.txt | 4 ++-- sql/share/german/errmsg.txt | 4 ++-- sql/share/italian/errmsg.txt | 4 ++-- sql/share/norwegian-ny/errmsg.txt | 4 ++-- sql/share/norwegian/errmsg.txt | 4 ++-- sql/share/polish/errmsg.txt | 4 ++-- sql/share/portuguese/errmsg.txt | 4 ++-- sql/share/romanian/errmsg.txt | 4 ++-- sql/share/serbian/errmsg.txt | 4 ++-- sql/share/slovak/errmsg.txt | 4 ++-- sql/share/spanish/errmsg.txt | 4 ++-- sql/share/swedish/errmsg.txt | 2 +- 16 files changed, 30 insertions(+), 30 deletions(-) diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index 641b1384e9a..f179b311c83 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)", diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index 574d26b7c1c..58466ed32f7 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)", diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index c6c975cb141..6296c39d232 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)", diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index f39c415fa55..5a9c44ef07e 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)", diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 6c1187cd0e4..e9a80c44f7f 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)", diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index 78d53034a71..00f0699445f 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)", diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index 8af7e3ba9f7..677d20a535b 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)", diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index de6db62cdce..6d9ac18be34 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)", diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index 28db8caa8bc..ba7c108f9ae 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)", diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index fdf856c7e56..04e60f5aa95 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)", diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index 397784dc7dd..64d83c20aab 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)", diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 8f1cdb7b259..e62c857553b 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)", diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt index 77d35be2fc9..62e5519475f 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)", diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 33cabdfc752..7730a4220ba 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)", diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 35e26f35ff7..8f923312969 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)", diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index 9cdcb20db35..ed60fc62387 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)", From 6a2e71229042ce17c922ff796763743653606e89 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 8 Jul 2003 02:27:21 -0700 Subject: [PATCH 4/9] implementation of mysql_stmt_reset client end include/mysql.h: add mysql_stmt_reset prototype include/mysql_com.h: add COM_STMT_RESET libmysql/libmysql.def: Add mysql_stmt_reset def sql/sql_prepare.cc: Fix selects hang after windows slowdown issue fix (send_fields) sql/sql_parse.cc: Add COM_STMT_RESET sql/mysql_priv.h: add defination of mysql_stmt_reset --- include/mysql.h | 1 + include/mysql_com.h | 1 + libmysql/libmysql.c | 23 +++++++++++++++++++++++ libmysql/libmysql.def | 1 + sql/mysql_priv.h | 1 + sql/sql_parse.cc | 5 +++++ sql/sql_prepare.cc | 2 +- 7 files changed, 33 insertions(+), 1 deletion(-) diff --git a/include/mysql.h b/include/mysql.h index bd63a10ba45..27d6b03bd0b 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -566,6 +566,7 @@ unsigned long STDCALL mysql_param_count(MYSQL_STMT * stmt); my_bool STDCALL mysql_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bnd); my_bool STDCALL mysql_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bnd); my_bool STDCALL mysql_stmt_close(MYSQL_STMT * stmt); +my_bool STDCALL mysql_stmt_reset(MYSQL_STMT * stmt); my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt); unsigned int STDCALL mysql_stmt_errno(MYSQL_STMT * stmt); const char *STDCALL mysql_stmt_error(MYSQL_STMT * stmt); diff --git a/include/mysql_com.h b/include/mysql_com.h index e87001ff27d..5eb59a1c7ab 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -44,6 +44,7 @@ enum enum_server_command COM_TIME, COM_DELAYED_INSERT, COM_CHANGE_USER, COM_BINLOG_DUMP, COM_TABLE_DUMP, COM_CONNECT_OUT, COM_REGISTER_SLAVE, COM_PREPARE, COM_EXECUTE, COM_LONG_DATA, COM_CLOSE_STMT, + COM_RESET_STMT, COM_END /* Must be last */ }; diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 771278c1dbb..1461d2fa128 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -3316,6 +3316,7 @@ mysql_stmt_data_seek(MYSQL_STMT *stmt, my_ulonglong row) } else DBUG_PRINT("exit", ("stmt doesn't contain any resultset")); + DBUG_VOID_RETURN; } @@ -3421,6 +3422,28 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt) return stmt_close(stmt, 0); } +/* + Reset the statement buffers in server +*/ + +my_bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt) +{ + char buff[MYSQL_STMT_HEADER]; + MYSQL *mysql; + DBUG_ENTER("mysql_stmt_reset"); + DBUG_ASSERT(stmt != 0); + + mysql= stmt->mysql->last_used_con; + int4store(buff, stmt->stmt_id); /* Send stmt id to server */ + if (advanced_command(mysql, COM_RESET_STMT,buff,MYSQL_STMT_HEADER,0,0,1)) + { + set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno, + mysql->net.sqlstate); + DBUG_RETURN(1); + } + DBUG_RETURN(0); +} + /* Return statement error code */ diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def index d641ca57274..51869eacc4b 100644 --- a/libmysql/libmysql.def +++ b/libmysql/libmysql.def @@ -98,6 +98,7 @@ EXPORTS mysql_stat mysql_stmt_affected_rows mysql_stmt_close + mysql_stmt_reset mysql_stmt_data_seek mysql_stmt_errno mysql_stmt_error diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 5ad2cc56b8c..6633912967e 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -557,6 +557,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 &fields, List &values, ulong counter); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 0db6ce8a642..00917e296ca 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1290,6 +1290,11 @@ restore_user: 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)) 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; From 4adf180432bba0e2f7e67ecb8fa5aa6d9ed86bdb Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 8 Jul 2003 15:06:05 +0500 Subject: [PATCH 5/9] SAPDB date/time finctions mysql-test/r/cast.result: Changes for SAPDB date/time finctions --- mysql-test/r/cast.result | 4 +- mysql-test/r/func_sapdb.result | 12 +- mysql-test/t/func_sapdb.test | 6 +- sql/item_create.cc | 4 +- sql/item_timefunc.cc | 322 +++++++++++++++++---------------- sql/item_timefunc.h | 82 ++------- sql/mysql_priv.h | 2 + sql/protocol.cc | 13 ++ sql/sql_string.cc | 17 ++ sql/sql_string.h | 2 + sql/sql_yacc.yy | 9 +- sql/time.cc | 1 + 12 files changed, 238 insertions(+), 236 deletions(-) diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result index a14ea4d61a6..5d185bee005 100644 --- a/mysql-test/r/cast.result +++ b/mysql-test/r/cast.result @@ -44,10 +44,10 @@ t1 CREATE TABLE `t1` ( drop table t1; select cast("2001-1-1" as date) = "2001-01-01"; cast("2001-1-1" as date) = "2001-01-01" -0 +1 select cast("2001-1-1" as datetime) = "2001-01-01 00:00:00"; cast("2001-1-1" as datetime) = "2001-01-01 00:00:00" -0 +1 select cast("1:2:3" as TIME) = "1:02:03"; cast("1:2:3" as TIME) = "1:02:03" 0 diff --git a/mysql-test/r/func_sapdb.result b/mysql-test/r/func_sapdb.result index 5c044d00726..e330c73727b 100644 --- a/mysql-test/r/func_sapdb.result +++ b/mysql-test/r/func_sapdb.result @@ -101,8 +101,8 @@ timediff("1997-12-30 23:59:59.000001","1997-12-31 23:59:59.000002") select timediff("1997-12-31 23:59:59.000001","23:59:59.000001"); timediff("1997-12-31 23:59:59.000001","23:59:59.000001") NULL -select timediff("2000:01:01 00:00:00", "2000:01:01 00:00:00.1"); -timediff("2000:01:01 00:00:00", "2000:01:01 00:00:00.1") +select timediff("2000:01:01 00:00:00", "2000:01:01 00:00:00.000001"); +timediff("2000:01:01 00:00:00", "2000:01:01 00:00:00.000001") -00:00:00.000001 select maketime(10,11,12); maketime(10,11,12) @@ -122,6 +122,12 @@ NULL select timestamp("2001-12-01", "25:01:01"); timestamp("2001-12-01", "25:01:01") 2001-12-02 01:01:01 +select timestamp("2001-12-01 01:01:01.000100"); +timestamp("2001-12-01 01:01:01.000100") +2001-12-01 01:01:01.000100 +select timestamp("2001-12-01"); +timestamp("2001-12-01") +2001-12-01 00:00:00 select day("1997-12-31 23:59:59.000001"); day("1997-12-31 23:59:59.000001") 31 @@ -147,7 +153,7 @@ addtime(cast("23:59:59.999999" as time) , "1 1:1:1.000002") as f3, timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002") as f4, timediff("1997-12-30 23:59:59.000001","1997-12-31 23:59:59.000002") as f5, maketime(10,11,12) as f6, -timestamp("2001-12-01", "01:01:01") as f7, +timestamp(cast("2001-12-01" as date), "01:01:01") as f7, date("1997-12-31 23:59:59.000001") as f8, time("1997-12-31 23:59:59.000001") as f9; describe t1; diff --git a/mysql-test/t/func_sapdb.test b/mysql-test/t/func_sapdb.test index 05e1f20fe1e..afd84fe9630 100644 --- a/mysql-test/t/func_sapdb.test +++ b/mysql-test/t/func_sapdb.test @@ -51,7 +51,7 @@ select timediff("1997-01-01 23:59:59.000001","1995-12-31 23:59:59.000002"); select timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002"); select timediff("1997-12-30 23:59:59.000001","1997-12-31 23:59:59.000002"); select timediff("1997-12-31 23:59:59.000001","23:59:59.000001"); -select timediff("2000:01:01 00:00:00", "2000:01:01 00:00:00.1"); +select timediff("2000:01:01 00:00:00", "2000:01:01 00:00:00.000001"); select maketime(10,11,12); select maketime(25,11,12); @@ -61,6 +61,8 @@ select maketime(-25,11,12); select timestamp("2001-12-01", "01:01:01.999999"); select timestamp("2001-13-01", "01:01:01.000001"); select timestamp("2001-12-01", "25:01:01"); +select timestamp("2001-12-01 01:01:01.000100"); +select timestamp("2001-12-01"); select day("1997-12-31 23:59:59.000001"); select date("1997-12-31 23:59:59.000001"); select date("1997-13-31 23:59:59.000001"); @@ -75,7 +77,7 @@ select makedate(1997,1) as f1, timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002") as f4, timediff("1997-12-30 23:59:59.000001","1997-12-31 23:59:59.000002") as f5, maketime(10,11,12) as f6, - timestamp("2001-12-01", "01:01:01") as f7, + timestamp(cast("2001-12-01" as date), "01:01:01") as f7, date("1997-12-31 23:59:59.000001") as f8, time("1997-12-31 23:59:59.000001") as f9; describe t1; diff --git a/sql/item_create.cc b/sql/item_create.cc index 402428d40cb..eaa27c1009d 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -709,12 +709,12 @@ Item *create_func_makedate(Item* a,Item* b) Item *create_func_addtime(Item* a,Item* b) { - return new Item_func_add_time(a, b, 0); + 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, 1); + return new Item_func_add_time(a, b, 0, 1); } Item *create_func_timediff(Item* a,Item* b) diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index fd2bca591a7..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,10 +57,14 @@ 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}; +enum date_time_format_types +{ + TIME_ONLY= 0, TIME_MICROSECOND, + DATE_ONLY, DATE_TIME, DATE_TIME_MICROSECOND +}; -typedef struct date_time_format { +typedef struct date_time_format +{ const char* format_str; uint length; }; @@ -73,6 +79,14 @@ static struct date_time_format date_time_formats[]= }; +/* + 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) { @@ -898,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 @@ -921,45 +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': - sprintf(intbuff,"%06ld",l_time.second_part); - str->append(intbuff); + 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) @@ -967,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': @@ -1020,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); @@ -1109,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=26*default_charset()->mbmaxlen; + max_length=26*MY_CHARSET_BIN_MB_MAXLEN; value.alloc(32); /* @@ -1197,13 +1220,13 @@ bool Item_date_add_interval::get_date(TIME *ltime, bool fuzzy_date) ltime->hour=sec/3600; daynr= calc_daynr(ltime->year,ltime->month,1) + days; get_date_from_daynr(daynr,<ime->year,<ime->month,<ime->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,<ime->year,<ime->month,<ime->day); break; @@ -1375,6 +1398,63 @@ void Item_typecast::print(String *str) str->append(')'); } +String *Item_datetime_typecast::val_str(String *str) +{ + TIME ltime; + + if (!get_arg0_date(<ime,1) && + make_datetime(str, <ime, 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(<ime) && + make_datetime(str, <ime, 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(<ime,1) && + make_datetime(str, <ime, 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. @@ -1392,7 +1472,7 @@ String *Item_func_makedate::val_str(String *str) goto null_date; days= calc_daynr(yearnr,1,1) + daynr - 1; - if (days > 0 || days < 3652424L) // Day number from year 0 to 9999-12-31 + 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); @@ -1410,7 +1490,7 @@ void Item_func_add_time::fix_length_and_dec() { enum_field_types arg0_field_type; decimals=0; - max_length=26*my_charset_bin.mbmaxlen; + max_length=26*MY_CHARSET_BIN_MB_MAXLEN; /* The field type for the result of an Item_func_add_time function is defined as @@ -1424,7 +1504,8 @@ void Item_func_add_time::fix_length_and_dec() cached_field_type= MYSQL_TYPE_STRING; arg0_field_type= args[0]->field_type(); - if (arg0_field_type == MYSQL_TYPE_DATETIME || + 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) @@ -1443,20 +1524,28 @@ void Item_func_add_time::fix_length_and_dec() String *Item_func_add_time::val_str(String *str) { TIME l_time1, l_time2, l_time3; - bool is_time; + bool is_time= 0; long microseconds, seconds, days= 0; int l_sign= sign; null_value=0; - 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); l_time3.neg= 0; - if (is_time) + if (is_date) // TIMESTAMP function { - if ((l_time2.neg == l_time1.neg) && l_time1.neg) + 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) @@ -1504,13 +1593,17 @@ String *Item_func_add_time::val_str(String *str) { get_date_from_daynr(days,&l_time3.year,&l_time3.month,&l_time3.day); if (l_time3.day && - make_datetime(str, &l_time3, DATE_TIME_MICROSECOND)) + 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, TIME_MICROSECOND)) + if (make_datetime(str, &l_time3, + l_time1.second_part || l_time2.second_part ? + TIME_MICROSECOND : TIME_ONLY)) return str; null_date: @@ -1578,7 +1671,9 @@ String *Item_func_timediff::val_str(String *str) l_time3.neg= l_time3.neg ? 0 : 1; calc_time_from_sec(&l_time3, seconds, microseconds); - if (make_datetime(str, &l_time3, TIME_MICROSECOND)) + if (make_datetime(str, &l_time3, + l_time1.second_part || l_time2.second_part ? + TIME_MICROSECOND : TIME_ONLY)) return str; null_date: @@ -1623,99 +1718,6 @@ null_date: return 0; } -/* - TIMESTAMP(a,b) is a function ( extraction) that calculates a datetime value - comprising a date value, time value. - - a: Date_or_datetime value - b: Time value - Result: Datetime value -*/ - -String *Item_func_timestamp::val_str(String *str) -{ - TIME l_time1 ,l_time2, l_time3; - long seconds; - long microseconds; - long days; - int l_sign; - - 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; - - l_sign= l_time2.neg ? -1 : 1; - days= (calc_daynr((uint) l_time1.year,(uint) l_time1.month, - (uint) l_time1.day) + l_sign*l_time2.day); - - 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); - days+= seconds/86400L; - seconds%= 86400L; - if (microseconds < 0) - { - microseconds+= 1000000L; - seconds--; - } - if (seconds < 0) - { - days--; - seconds+= 86400L; - } - if (days < 0) - goto null_date; - - calc_time_from_sec(&l_time3, seconds, microseconds); - get_date_from_daynr(days,&l_time3.year,&l_time3.month,&l_time3.day); - make_datetime(str, &l_time3, DATE_TIME_MICROSECOND); - return str; - -null_date: - null_value=1; - return 0; -} - -/* - DATE(a) is a function ( extraction) that calculates a date value. - - a: Datetime value - Result: Date value -*/ -String *Item_func_date::val_str(String *str) -{ - TIME ltime; - - if (!get_arg0_date(<ime,1) && - make_datetime(str, <ime, DATE_ONLY)) - return str; - -null_date: - null_value=1; - return 0; -} - -/* - TIME(a) is a function ( extraction) that calculates a time value. - - a: Datetime value - Result: Time value -*/ -String *Item_func_time::val_str(String *str) -{ - TIME ltime; - - if (!get_arg0_time(<ime) && - make_datetime(str, <ime, TIME_MICROSECOND)) - return str; - - null_value=1; - return 0; -} - /* MICROSECOND(a) is a function ( extraction) that extracts the microseconds from a. diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index ea29731fe35..20b95f8e22d 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -557,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; } @@ -571,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; } @@ -585,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; } @@ -604,7 +609,7 @@ public: void fix_length_and_dec() { decimals=0; - max_length=8*my_charset_bin.mbmaxlen; + max_length=8*MY_CHARSET_BIN_MB_MAXLEN; } Field *tmp_table_field() { return result_field; } Field *tmp_table_field(TABLE *t_arg) @@ -613,18 +618,26 @@ public: } }; + 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 neg_arg) - :Item_str_func(a, b) { sign= neg_arg ? -1 : 1; } + 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) { @@ -647,7 +660,7 @@ public: void fix_length_and_dec() { decimals=0; - max_length=17*my_charset_bin.mbmaxlen; + max_length=17*MY_CHARSET_BIN_MB_MAXLEN; } Field *tmp_table_field() { return result_field; } Field *tmp_table_field(TABLE *t_arg) @@ -667,66 +680,7 @@ public: void fix_length_and_dec() { decimals=0; - max_length=8*my_charset_bin.mbmaxlen; - } - 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_timestamp :public Item_str_func -{ -public: - Item_func_timestamp(Item *a, Item *b) :Item_str_func(a, b) {} - String *val_str(String *str); - const char *func_name() const { return "timestamp"; } - enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; } - void fix_length_and_dec() - { - decimals=0; - max_length=26*my_charset_bin.mbmaxlen; - } - Field *tmp_table_field() { return result_field; } - Field *tmp_table_field(TABLE *t_arg) - { - return (new Field_datetime(maybe_null, name, t_arg, &my_charset_bin)); - } -}; - -class Item_func_date :public Item_str_func -{ -public: - Item_func_date(Item *a) - :Item_str_func(a) {} - String *val_str(String *str); - const char *func_name() const { return "date"; } - enum_field_types field_type() const { return MYSQL_TYPE_DATE; } - void fix_length_and_dec() - { - decimals=0; - max_length=10*my_charset_bin.mbmaxlen; - } - 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_time :public Item_str_func -{ -public: - Item_func_time(Item *a) - :Item_str_func(a) {} - String *val_str(String *str); - const char *func_name() const { return "time"; } - enum_field_types field_type() const { return MYSQL_TYPE_TIME; } - void fix_length_and_dec() - { - decimals=0; - max_length=15*my_charset_bin.mbmaxlen; + max_length=8*MY_CHARSET_BIN_MB_MAXLEN; } Field *tmp_table_field() { return result_field; } Field *tmp_table_field(TABLE *t_arg) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 8aeb18dcf26..ea3c2d45333 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -224,6 +224,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 diff --git a/sql/protocol.cc b/sql/protocol.cc index 3d214e6f86d..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 @@ -863,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 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 873257116b9..4aa5b70407e 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2381,7 +2381,7 @@ simple_expr: Lex->safe_to_cache_query=0; } | DATE_SYM '(' expr ')' - { $$= new Item_func_date($3); } + { $$= new Item_date_typecast($3); } | DAY_SYM '(' expr ')' { $$= new Item_func_dayofmonth($3); } | ELT_FUNC '(' expr ',' expr_list ')' @@ -2580,9 +2580,11 @@ simple_expr: | SUBSTRING_INDEX '(' expr ',' expr ',' expr ')' { $$= new Item_func_substr_index($3,$5,$7); } | TIME_SYM '(' expr ')' - { $$= new Item_func_time($3); } + { $$= new Item_time_typecast($3); } + | TIMESTAMP '(' expr ')' + { $$= new Item_datetime_typecast($3); } | TIMESTAMP '(' expr ',' expr ')' - { $$= new Item_func_timestamp($3, $5); } + { $$= new Item_func_add_time($3, $5, 1, 0); } | TRIM '(' expr ')' { $$= new Item_func_trim($3); } | TRIM '(' LEADING expr FROM expr ')' @@ -4427,6 +4429,7 @@ keyword: | MEDIUM_SYM {} | MERGE_SYM {} | MEMORY_SYM {} + | MICROSECOND_SYM {} | MINUTE_SYM {} | MIN_ROWS {} | MODIFY_SYM {} diff --git a/sql/time.cc b/sql/time.cc index 056adf050ce..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)); } From 1846a9eb5c1e8fb65fde6c4de821d0e329d7b45f Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 10 Jul 2003 10:02:57 +0200 Subject: [PATCH 6/9] - Updated error message tests in several results of the test suite after the server error messages had been modified in errmsg.txt mysql-test/r/create.result: - Updated error message in result after errmsg.txt has been modified mysql-test/r/drop.result: - Updated error message in result after errmsg.txt has been modified mysql-test/r/rpl000009.result: - Updated error message in result after errmsg.txt has been modified mysql-test/r/symlink.result: - Updated error message in result after errmsg.txt has been modified mysql-test/r/warnings.result: - Updated error message in result after errmsg.txt has been modified --- mysql-test/r/create.result | 4 ++-- mysql-test/r/drop.result | 6 +++--- mysql-test/r/rpl000009.result | 6 +++--- mysql-test/r/symlink.result | 2 +- mysql-test/r/warnings.result | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 70814aa899e..9a0eca52b84 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -50,7 +50,7 @@ create table t1 (t1.index int); drop table t1; drop database if exists test_$1; Warnings: -Note 1008 Can't drop database 'test_$1'. Database doesn't exist +Note 1008 Can't drop database 'test_$1'; database doesn't exist create database test_$1; create table test_$1.$test1 (a$1 int, $b int, c$ int); insert into test_$1.$test1 values (1,2,3); @@ -252,7 +252,7 @@ id name drop table t2, t3; drop database if exists test_$1; Warnings: -Note 1008 Can't drop database 'test_$1'. Database doesn't exist +Note 1008 Can't drop database 'test_$1'; database doesn't exist create database test_$1; create table test_$1.t3 like t1; create temporary table t3 like test_$1.t3; diff --git a/mysql-test/r/drop.result b/mysql-test/r/drop.result index 2b878455bea..9555ea452ca 100644 --- a/mysql-test/r/drop.result +++ b/mysql-test/r/drop.result @@ -13,7 +13,7 @@ n 1 drop database if exists mysqltest; Warnings: -Note 1008 Can't drop database 'mysqltest'. Database doesn't exist +Note 1008 Can't drop database 'mysqltest'; database doesn't exist create database mysqltest; drop database if exists mysqltest; create database mysqltest; @@ -27,7 +27,7 @@ create database mysqltest; drop database mysqltest; drop database if exists mysqltest; Warnings: -Note 1008 Can't drop database 'mysqltest'. Database doesn't exist +Note 1008 Can't drop database 'mysqltest'; database doesn't exist flush tables with read lock; create database mysqltest; Got one of the listed errors @@ -48,4 +48,4 @@ Database mysql test drop database mysqltest; -ERROR HY000: Can't drop database 'mysqltest'. Database doesn't exist +ERROR HY000: Can't drop database 'mysqltest'; database doesn't exist diff --git a/mysql-test/r/rpl000009.result b/mysql-test/r/rpl000009.result index dc1d8c4872e..d0faf0435e3 100644 --- a/mysql-test/r/rpl000009.result +++ b/mysql-test/r/rpl000009.result @@ -21,7 +21,7 @@ n m drop database mysqltest; drop database if exists mysqltest2; drop database mysqltest; -ERROR HY000: Can't drop database 'mysqltest'. Database doesn't exist +ERROR HY000: Can't drop database 'mysqltest'; database doesn't exist drop database mysqltest2; set sql_log_bin = 0; create database mysqltest2; @@ -48,8 +48,8 @@ mysql test load data from master; Warnings: -Note 1008 Can't drop database 'mysqltest'. Database doesn't exist -Note 1008 Can't drop database 'mysqltest2'. Database doesn't exist +Note 1008 Can't drop database 'mysqltest'; database doesn't exist +Note 1008 Can't drop database 'mysqltest2'; database doesn't exist show databases; Database mysql diff --git a/mysql-test/r/symlink.result b/mysql-test/r/symlink.result index 3efc69d2f64..f12b98ba041 100644 --- a/mysql-test/r/symlink.result +++ b/mysql-test/r/symlink.result @@ -46,7 +46,7 @@ rename table t7 to t9; drop table t1; Got one of the listed errors Warnings: -Note 1008 Can't drop database 'test_mysqltest'. Database doesn't exist +Note 1008 Can't drop database 'test_mysqltest'; database doesn't exist Got one of the listed errors Got one of the listed errors Got one of the listed errors diff --git a/mysql-test/r/warnings.result b/mysql-test/r/warnings.result index add9051ddfb..d84c284d7b4 100644 --- a/mysql-test/r/warnings.result +++ b/mysql-test/r/warnings.result @@ -32,7 +32,7 @@ Level Code Message Note 1051 Unknown table 'not_exists_table' drop database if exists not_exists_db; Warnings: -Note 1008 Can't drop database 'not_exists_db'. Database doesn't exist +Note 1008 Can't drop database 'not_exists_db'; database doesn't exist show count(*) warnings; @@session.warning_count 1 From d1d636de8fa3438b1bff24a13bd74c6e8ca399f2 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 11 Jul 2003 16:11:17 +0500 Subject: [PATCH 7/9] field_conv.cc: Data was not converted when ALTER TABLE CHAGE changed a field character set. sql/field_conv.cc: Data was not converted when ALTER TABLE CHAGE changed a field character set. --- sql/field_conv.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/field_conv.cc b/sql/field_conv.cc index ec2488f520a..144e6d7e74a 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -489,6 +489,8 @@ void (*Copy_field::get_copy_func(Field *to,Field *from))(Copy_field*) if (!to->eq_def(from)) return do_field_string; } + else if (to->charset() != from->charset()) + return do_field_string; else if (to->real_type() == FIELD_TYPE_VAR_STRING && to_length != from_length) return do_varstring; From 19a4a84dbc5b6589cdfe9dd90f2d92daef89b549 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 12 Jul 2003 23:31:21 +0200 Subject: [PATCH 8/9] Added SHOW MASTER LOGS as synonym for SHOW BINARY LOGS. Added PURGE BINARY LOGS as synonym for PURGE MASTER LOGS. Removed PURGE LOGS (now PURGE MASTER LOGS). Added SHOW BDB LOGS as synonym for SHOW LOGS. Note: tests key_cache.test hanged, rpl_log_pos.test, rpl_rotate_logs.test failed for me. For the second and third one I guess this will disappear after merging 4.0. mysql-test/r/rpl_rotate_logs.result: result update mysql-test/t/rpl_rotate_logs.test: added test for synonym PURGE BINARY LOGS, changed PURGE LOGS to PURGE MASTER LOGS. sql/sql_yacc.yy: Added SHOW MASTER LOGS as synonym for SHOW BINARY LOGS. Added PURGE BINARY LOGS as synonym for PURGE MASTER LOGS. Removed PURGE LOGS (now PURGE MASTER LOGS). Added SHOW BDB LOGS as synonym for SHOW LOGS. --- mysql-test/r/rpl_rotate_logs.result | 7 ++++++- mysql-test/t/rpl_rotate_logs.test | 5 ++++- sql/sql_yacc.yy | 11 ++++++++--- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/rpl_rotate_logs.result b/mysql-test/r/rpl_rotate_logs.result index 66209d2b852..c3c83947578 100644 --- a/mysql-test/r/rpl_rotate_logs.result +++ b/mysql-test/r/rpl_rotate_logs.result @@ -41,11 +41,16 @@ insert into t2 values(NULL); set global sql_slave_skip_counter=1; start slave; purge master logs to 'master-bin.000002'; +show master logs; +Log_name +master-bin.000002 +master-bin.000003 +purge binary logs to 'master-bin.000002'; show binary logs; Log_name master-bin.000002 master-bin.000003 -purge logs before now(); +purge master logs before now(); show binary logs; Log_name master-bin.000003 diff --git a/mysql-test/t/rpl_rotate_logs.test b/mysql-test/t/rpl_rotate_logs.test index 8ad5109d2c6..df506c08e71 100644 --- a/mysql-test/t/rpl_rotate_logs.test +++ b/mysql-test/t/rpl_rotate_logs.test @@ -90,9 +90,12 @@ connection master; sync_slave_with_master; connection master; purge master logs to 'master-bin.000002'; +show master logs; +# we just tests if synonyms are accepted +purge binary logs to 'master-bin.000002'; show binary logs; --sleep 1; -purge logs before now(); +purge master logs before now(); show binary logs; insert into t2 values (65); sync_slave_with_master; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 3098bd18b2d..c836cb414e0 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3742,7 +3742,7 @@ show_param: Lex->mi.pos = $12; Lex->mi.server_id = $16; } - | BINARY LOGS_SYM + | master_or_binary LOGS_SYM { Lex->sql_command = SQLCOM_SHOW_BINLOGS; } @@ -3802,6 +3802,8 @@ show_param: { Lex->sql_command= SQLCOM_SHOW_CHARSETS; } | COLLATION_SYM wild { Lex->sql_command= SQLCOM_SHOW_COLLATIONS; } + | BERKELEY_DB_SYM LOGS_SYM + { Lex->sql_command= SQLCOM_SHOW_LOGS; } | LOGS_SYM { Lex->sql_command= SQLCOM_SHOW_LOGS; } | GRANTS FOR_SYM user @@ -3832,6 +3834,10 @@ show_param: Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT; }; +master_or_binary: + MASTER_SYM + | BINARY; + opt_db: /* empty */ { $$= 0; } | from_or_in ident { $$= $2.str; }; @@ -3949,8 +3955,7 @@ purge: ; purge_options: - LOGS_SYM purge_option - | MASTER_SYM LOGS_SYM purge_option + master_or_binary LOGS_SYM purge_option ; purge_option: From 768ab1e47e363dffc8ee450d48ebbf976efb3d65 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 13 Jul 2003 01:20:15 -0400 Subject: [PATCH 9/9] Removed unreferenced local variable --- sql/item_strfunc.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 2d29f76c2d7..f5cc88e2e4e 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2427,7 +2427,6 @@ String* Item_func_export_set::val_str(String* str) void Item_func_export_set::fix_length_and_dec() { - uint i; uint length=max(args[1]->max_length,args[2]->max_length); uint sep_length=(arg_count > 3 ? args[3]->max_length : 1); max_length=length*64+sep_length*63;