summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <bell@sanja.is.com.ua>2003-07-13 13:04:59 +0300
committerunknown <bell@sanja.is.com.ua>2003-07-13 13:04:59 +0300
commit6d7c4021f8312ac0e0727b73ffba671384f23af3 (patch)
tree83290d8c25451bbb1963b94a7494f9b156b9aa64
parent134cc54e80bef8e1dcd344fe332000f39018682b (diff)
parent768ab1e47e363dffc8ee450d48ebbf976efb3d65 (diff)
downloadmariadb-git-6d7c4021f8312ac0e0727b73ffba671384f23af3.tar.gz
Merge sanja.is.com.ua:/home/bell/mysql/bk/mysql-4.1
into sanja.is.com.ua:/home/bell/mysql/bk/work-top3-4.1 sql/item_func.cc: Auto merged sql/mysql_priv.h: Auto merged sql/sql_lex.cc: Auto merged sql/sql_parse.cc: Auto merged sql/sql_yacc.yy: Auto merged
-rw-r--r--include/my_getopt.h2
-rw-r--r--include/my_sys.h6
-rw-r--r--include/mysql.h1
-rw-r--r--include/mysql_com.h1
-rw-r--r--include/mysqld_error.h3
-rw-r--r--libmysql/libmysql.c23
-rw-r--r--libmysql/libmysql.def1
-rw-r--r--mysql-test/r/cast.result4
-rw-r--r--mysql-test/r/create.result4
-rw-r--r--mysql-test/r/drop.result6
-rw-r--r--mysql-test/r/func_sapdb.result200
-rw-r--r--mysql-test/r/key_cache.result43
-rw-r--r--mysql-test/r/rpl000009.result6
-rw-r--r--mysql-test/r/rpl_rotate_logs.result7
-rw-r--r--mysql-test/r/select_safe.result2
-rw-r--r--mysql-test/r/symlink.result2
-rw-r--r--mysql-test/r/variables.result2
-rw-r--r--mysql-test/r/warnings.result2
-rw-r--r--mysql-test/t/func_sapdb.test99
-rw-r--r--mysql-test/t/key_cache-master.opt1
-rw-r--r--mysql-test/t/key_cache.test42
-rw-r--r--mysql-test/t/rpl_rotate_logs.test5
-rw-r--r--mysys/my_getopt.c61
-rw-r--r--sql/Makefile.am2
-rw-r--r--sql/field.cc2
-rw-r--r--sql/field_conv.cc2
-rw-r--r--sql/item_create.cc35
-rw-r--r--sql/item_create.h7
-rw-r--r--sql/item_func.cc78
-rw-r--r--sql/item_strfunc.cc1
-rw-r--r--sql/item_timefunc.cc630
-rw-r--r--sql/item_timefunc.h115
-rw-r--r--sql/lex.h16
-rw-r--r--sql/mysql_priv.h12
-rw-r--r--sql/mysqld.cc31
-rw-r--r--sql/protocol.cc17
-rw-r--r--sql/set_var.cc218
-rw-r--r--sql/set_var.h105
-rw-r--r--sql/share/czech/errmsg.txt3
-rw-r--r--sql/share/danish/errmsg.txt5
-rw-r--r--sql/share/dutch/errmsg.txt5
-rw-r--r--sql/share/english/errmsg.txt5
-rw-r--r--sql/share/estonian/errmsg.txt1
-rw-r--r--sql/share/french/errmsg.txt5
-rw-r--r--sql/share/german/errmsg.txt5
-rw-r--r--sql/share/greek/errmsg.txt1
-rw-r--r--sql/share/hungarian/errmsg.txt1
-rw-r--r--sql/share/italian/errmsg.txt5
-rw-r--r--sql/share/japanese/errmsg.txt1
-rw-r--r--sql/share/korean/errmsg.txt1
-rw-r--r--sql/share/norwegian-ny/errmsg.txt5
-rw-r--r--sql/share/norwegian/errmsg.txt5
-rw-r--r--sql/share/polish/errmsg.txt5
-rw-r--r--sql/share/portuguese/errmsg.txt5
-rw-r--r--sql/share/romanian/errmsg.txt5
-rw-r--r--sql/share/russian/errmsg.txt1
-rw-r--r--sql/share/serbian/errmsg.txt5
-rw-r--r--sql/share/slovak/errmsg.txt5
-rw-r--r--sql/share/spanish/errmsg.txt5
-rw-r--r--sql/share/swedish/errmsg.txt3
-rw-r--r--sql/share/ukrainian/errmsg.txt1
-rw-r--r--sql/sql_lex.cc23
-rw-r--r--sql/sql_parse.cc16
-rw-r--r--sql/sql_prepare.cc2
-rw-r--r--sql/sql_show.cc5
-rw-r--r--sql/sql_string.cc17
-rw-r--r--sql/sql_string.h2
-rw-r--r--sql/sql_yacc.yy80
-rw-r--r--sql/time.cc14
69 files changed, 1781 insertions, 255 deletions
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 <my_alloc.h>
/* Prototypes for mysys and my_func functions */
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/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/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;
}
@@ -3422,6 +3423,28 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
}
/*
+ 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/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/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/func_sapdb.result b/mysql-test/r/func_sapdb.result
new file mode 100644
index 00000000000..e330c73727b
--- /dev/null
+++ b/mysql-test/r/func_sapdb.result
@@ -0,0 +1,200 @@
+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.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)
+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 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
+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(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;
+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/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/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/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/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/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/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/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
diff --git a/mysql-test/t/func_sapdb.test b/mysql-test/t/func_sapdb.test
new file mode 100644
index 00000000000..afd84fe9630
--- /dev/null
+++ b/mysql-test/t/func_sapdb.test
@@ -0,0 +1,99 @@
+--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.000001");
+
+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 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");
+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(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;
+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/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/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/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/field.cc b/sql/field.cc
index 4aa58180a69..2f89dd43c3f 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -3152,11 +3152,13 @@ bool Field_time::get_time(TIME *ltime)
ltime->neg= 1;
tmp=-tmp;
}
+ ltime->day= 0;
ltime->hour= (int) (tmp/10000);
tmp-=ltime->hour*10000;
ltime->minute= (int) tmp/100;
ltime->second= (int) tmp % 100;
ltime->second_part=0;
+ ltime->time_type= TIMESTAMP_TIME;
return 0;
}
diff --git a/sql/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;
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 90f42cee959..eaa27c1009d 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -691,3 +691,38 @@ Item *create_func_uncompressed_length(Item* a)
#endif
+Item *create_func_datediff(Item *a, Item *b)
+{
+ return new Item_func_minus(new Item_func_to_days(a),
+ new Item_func_to_days(b));
+}
+
+Item *create_func_weekofyear(Item *a)
+{
+ return new Item_func_week(a, new Item_int((char*) "0", 3, 1));
+}
+
+Item *create_func_makedate(Item* a,Item* b)
+{
+ return new Item_func_makedate(a, b);
+}
+
+Item *create_func_addtime(Item* a,Item* b)
+{
+ return new Item_func_add_time(a, b, 0, 0);
+}
+
+Item *create_func_subtime(Item* a,Item* b)
+{
+ return new Item_func_add_time(a, b, 0, 1);
+}
+
+Item *create_func_timediff(Item* a,Item* b)
+{
+ return new Item_func_timediff(a, b);
+}
+
+Item *create_func_maketime(Item* a,Item* b,Item* c)
+{
+ return new Item_func_maketime(a, b, c);
+}
diff --git a/sql/item_create.h b/sql/item_create.h
index 4151f59a87f..32e452c15dd 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_func.cc b/sql/item_func.cc
index de6bf33f03a..9832c9fd3a6 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -2699,21 +2699,61 @@ longlong Item_func_bit_xor::val_int()
System variables
****************************************************************************/
-Item *get_system_var(enum_var_type var_type, LEX_STRING name)
+/*
+ Return value of an system variable base[.name] as a constant item
+
+ SYNOPSIS
+ get_system_var()
+ thd Thread handler
+ var_type global / session
+ name Name of base or system variable
+ component Component.
+
+ NOTES
+ If component.str = 0 then the variable name is in 'name'
+
+ RETURN
+ 0 error
+ # constant item
+*/
+
+
+Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
+ LEX_STRING component)
{
- if (!my_strcasecmp(system_charset_info, name.str, "VERSION"))
+ if (component.str == 0 &&
+ !my_strcasecmp(system_charset_info, name.str, "VERSION"))
return new Item_string("@@VERSION", server_version,
(uint) strlen(server_version),
system_charset_info);
- THD *thd=current_thd;
Item *item;
sys_var *var;
- char buff[MAX_SYS_VAR_LENGTH+3+8], *pos;
+ char buff[MAX_SYS_VAR_LENGTH*2+4+8], *pos;
+ LEX_STRING *base_name, *component_name;
+
+ if (component.str)
+ {
+ base_name= &component;
+ component_name= &name;
+ }
+ else
+ {
+ base_name= &name;
+ component_name= &component; // Empty string
+ }
- if (!(var= find_sys_var(name.str, name.length)))
+ if (!(var= find_sys_var(base_name->str, base_name->length)))
return 0;
- if (!(item=var->item(thd, var_type)))
+ if (component.str)
+ {
+ if (!var->is_struct())
+ {
+ net_printf(thd, ER_VARIABLE_IS_NOT_STRUCT, base_name->str);
+ return 0;
+ }
+ }
+ if (!(item=var->item(thd, var_type, component_name)))
return 0; // Impossible
thd->lex.uncacheable();
buff[0]='@';
@@ -2723,23 +2763,37 @@ Item *get_system_var(enum_var_type var_type, LEX_STRING name)
pos=strmov(pos,"session.");
else if (var_type == OPT_GLOBAL)
pos=strmov(pos,"global.");
- memcpy(pos, var->name, var->name_length+1);
+
+ set_if_smaller(component_name->length, MAX_SYS_VAR_LENGTH);
+ set_if_smaller(base_name->length, MAX_SYS_VAR_LENGTH);
+
+ if (component_name->str)
+ {
+ memcpy(pos, component_name->str, component_name->length);
+ pos+= component_name->length;
+ *pos++= '.';
+ }
+ memcpy(pos, base_name->str, base_name->length);
+ pos+= base_name->length;
+
// set_name() will allocate the name
- item->set_name(buff,(uint) (pos-buff)+var->name_length, system_charset_info);
+ item->set_name(buff,(uint) (pos-buff), system_charset_info);
return item;
}
-Item *get_system_var(enum_var_type var_type, const char *var_name, uint length,
- const char *item_name)
+Item *get_system_var(THD *thd, enum_var_type var_type, const char *var_name,
+ uint length, const char *item_name)
{
- THD *thd=current_thd;
Item *item;
sys_var *var;
+ LEX_STRING null_lex_string;
+
+ null_lex_string.str= 0;
var= find_sys_var(var_name, length);
DBUG_ASSERT(var != 0);
- if (!(item=var->item(thd, var_type)))
+ if (!(item=var->item(thd, var_type, &null_lex_string)))
return 0; // Impossible
thd->lex.uncacheable();
item->set_name(item_name, 0, system_charset_info); // Will use original name
diff --git a/sql/item_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;
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 61c869cddba..4fdb1b13d24 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -29,6 +29,8 @@
** Todo: Move month and days to language files
*/
+#define MAX_DAY_NUMBER 3652424L
+
static String month_names[] =
{
String("January", &my_charset_latin1),
@@ -55,6 +57,82 @@ static String day_names[] =
String("Sunday", &my_charset_latin1)
};
+enum date_time_format_types
+{
+ TIME_ONLY= 0, TIME_MICROSECOND,
+ DATE_ONLY, DATE_TIME, DATE_TIME_MICROSECOND
+};
+
+typedef struct date_time_format
+{
+ const char* format_str;
+ uint length;
+};
+
+static struct date_time_format date_time_formats[]=
+{
+ {"%s%02d:%02d:%02d", 10},
+ {"%s%02d:%02d:%02d.%06d", 17},
+ {"%04d-%02d-%02d", 10},
+ {"%04d-%02d-%02d %02d:%02d:%02d", 19},
+ {"%04d-%02d-%02d %02d:%02d:%02d.%06d", 26}
+};
+
+
+/*
+ OPTIMIZATION TODO:
+ - Replace the switch with a function that should be called for each
+ date type.
+ - Remove sprintf and opencode the conversion, like we do in
+ Field_datetime.
+*/
+
+String *make_datetime(String *str, TIME *ltime,
+ enum date_time_format_types format)
+{
+ char *buff;
+ CHARSET_INFO *cs= &my_charset_bin;
+ uint length= date_time_formats[format].length + 32;
+ const char* format_str= date_time_formats[format].format_str;
+
+ if (str->alloc(length))
+ return 0;
+
+ buff= (char*) str->ptr();
+ switch (format) {
+ case TIME_ONLY:
+ length= cs->cset->snprintf(cs, buff, length, format_str, ltime->neg ? "-" : "",
+ ltime->hour, ltime->minute, ltime->second);
+ break;
+ case TIME_MICROSECOND:
+ length= cs->cset->snprintf(cs, buff, length, format_str, ltime->neg ? "-" : "",
+ ltime->hour, ltime->minute, ltime->second,
+ ltime->second_part);
+ break;
+ case DATE_ONLY:
+ length= cs->cset->snprintf(cs, buff, length, format_str,
+ ltime->year, ltime->month, ltime->day);
+ break;
+ case DATE_TIME:
+ length= cs->cset->snprintf(cs, buff, length, format_str,
+ ltime->year, ltime->month, ltime->day,
+ ltime->hour, ltime->minute, ltime->second);
+ break;
+ case DATE_TIME_MICROSECOND:
+ length= cs->cset->snprintf(cs, buff, length, format_str,
+ ltime->year, ltime->month, ltime->day,
+ ltime->hour, ltime->minute, ltime->second,
+ ltime->second_part);
+ break;
+ default:
+ return 0;
+ }
+
+ str->length(length);
+ str->set_charset(cs);
+ return str;
+}
+
/*
** Get a array of positive numbers from a string object.
** Each number is separated by 1 non digit character
@@ -309,7 +387,7 @@ static bool get_interval_value(Item *args,interval_type int_type,
CHARSET_INFO *cs=str_value->charset();
bzero((char*) t,sizeof(*t));
- if ((int) int_type <= INTERVAL_SECOND)
+ if ((int) int_type <= INTERVAL_MICROSECOND)
{
value=(long) args->val_int();
if (args->null_value)
@@ -352,6 +430,9 @@ static bool get_interval_value(Item *args,interval_type int_type,
case INTERVAL_HOUR:
t->hour=value;
break;
+ case INTERVAL_MICROSECOND:
+ t->second_part=value;
+ break;
case INTERVAL_MINUTE:
t->minute=value;
break;
@@ -370,6 +451,15 @@ static bool get_interval_value(Item *args,interval_type int_type,
t->day=array[0];
t->hour=array[1];
break;
+ case INTERVAL_DAY_MICROSECOND:
+ if (get_interval_info(str,length,cs,5,array))
+ return (1);
+ t->day=array[0];
+ t->hour=array[1];
+ t->minute=array[2];
+ t->second=array[3];
+ t->second_part=array[4];
+ break;
case INTERVAL_DAY_MINUTE:
if (get_interval_info(str,length,cs,3,array))
return (1);
@@ -385,6 +475,14 @@ static bool get_interval_value(Item *args,interval_type int_type,
t->minute=array[2];
t->second=array[3];
break;
+ case INTERVAL_HOUR_MICROSECOND:
+ if (get_interval_info(str,length,cs,4,array))
+ return (1);
+ t->hour=array[0];
+ t->minute=array[1];
+ t->second=array[2];
+ t->second_part=array[3];
+ break;
case INTERVAL_HOUR_MINUTE:
if (get_interval_info(str,length,cs,2,array))
return (1);
@@ -398,12 +496,25 @@ static bool get_interval_value(Item *args,interval_type int_type,
t->minute=array[1];
t->second=array[2];
break;
+ case INTERVAL_MINUTE_MICROSECOND:
+ if (get_interval_info(str,length,cs,3,array))
+ return (1);
+ t->minute=array[0];
+ t->second=array[1];
+ t->second_part=array[2];
+ break;
case INTERVAL_MINUTE_SECOND:
if (get_interval_info(str,length,cs,2,array))
return (1);
t->minute=array[0];
t->second=array[1];
break;
+ case INTERVAL_SECOND_MICROSECOND:
+ if (get_interval_info(str,length,cs,2,array))
+ return (1);
+ t->second=array[0];
+ t->second_part=array[1];
+ break;
}
return 0;
}
@@ -687,6 +798,9 @@ uint Item_func_date_format::format_length(const String *format)
case 'T': /* time, 24-hour (hh:mm:ss) */
size += 8;
break;
+ case 'f': /* microseconds */
+ size += 6;
+ break;
case 'w': /* day (of the week), numeric */
case '%':
default:
@@ -798,8 +912,8 @@ String *Item_func_date_format::val_str(String *str)
null_value=1;
return 0;
}
- length= my_sprintf(intbuff, (intbuff,"%d",l_time.day));
- str->append(intbuff, length);
+ length= int10_to_str(l_time.day, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 1, '0');
if (l_time.day >= 10 && l_time.day <= 19)
str->append("th");
else
@@ -821,41 +935,45 @@ String *Item_func_date_format::val_str(String *str)
}
break;
case 'Y':
- sprintf(intbuff,"%04d",l_time.year);
- str->append(intbuff,4);
+ length= int10_to_str(l_time.year, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 4, '0');
break;
case 'y':
- sprintf(intbuff,"%02d",l_time.year%100);
- str->append(intbuff,2);
+ length= int10_to_str(l_time.year%100, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'm':
- sprintf(intbuff,"%02d",l_time.month);
- str->append(intbuff,2);
+ length= int10_to_str(l_time.month, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'c':
- sprintf(intbuff,"%d",l_time.month);
- str->append(intbuff);
+ length= int10_to_str(l_time.month, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 1, '0');
break;
case 'd':
- sprintf(intbuff,"%02d",l_time.day);
- str->append(intbuff,2);
+ length= int10_to_str(l_time.day, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'e':
- sprintf(intbuff,"%d",l_time.day);
- str->append(intbuff);
+ length= int10_to_str(l_time.day, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 1, '0');
+ break;
+ case 'f':
+ length= int10_to_str(l_time.second_part, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 6, '0');
break;
case 'H':
- sprintf(intbuff,"%02d",l_time.hour);
- str->append(intbuff,2);
+ length= int10_to_str(l_time.hour, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'h':
case 'I':
- sprintf(intbuff,"%02d", (l_time.hour+11)%12+1);
- str->append(intbuff,2);
+ length= int10_to_str((l_time.hour+11)%12+1, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'i': /* minutes */
- sprintf(intbuff,"%02d",l_time.minute);
- str->append(intbuff,2);
+ length= int10_to_str(l_time.minute, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'j':
if (date_or_time)
@@ -863,52 +981,60 @@ String *Item_func_date_format::val_str(String *str)
null_value=1;
return 0;
}
- sprintf(intbuff,"%03d",
- (int) (calc_daynr(l_time.year,l_time.month,l_time.day) -
- calc_daynr(l_time.year,1,1)) + 1);
- str->append(intbuff,3);
+ length= int10_to_str(calc_daynr(l_time.year,l_time.month,l_time.day) -
+ calc_daynr(l_time.year,1,1) + 1, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 3, '0');
break;
case 'k':
- sprintf(intbuff,"%d",l_time.hour);
- str->append(intbuff);
+ length= int10_to_str(l_time.hour, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 1, '0');
break;
case 'l':
- sprintf(intbuff,"%d", (l_time.hour+11)%12+1);
- str->append(intbuff);
+ length= int10_to_str((l_time.hour+11)%12+1, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 1, '0');
break;
case 'p':
str->append(l_time.hour < 12 ? "AM" : "PM",2);
break;
case 'r':
- sprintf(intbuff,(l_time.hour < 12) ? "%02d:%02d:%02d AM" :
- "%02d:%02d:%02d PM",(l_time.hour+11)%12+1,l_time.minute,
- l_time.second);
- str->append(intbuff);
+ length= my_sprintf(intbuff,
+ (intbuff,
+ (l_time.hour < 12) ? "%02d:%02d:%02d AM" : "%02d:%02d:%02d PM",
+ (l_time.hour+11)%12+1,
+ l_time.minute,
+ l_time.second));
+ str->append(intbuff, length);
break;
case 'S':
case 's':
- sprintf(intbuff,"%02d",l_time.second);
- str->append(intbuff);
+ length= int10_to_str(l_time.second, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'T':
- sprintf(intbuff,"%02d:%02d:%02d", l_time.hour, l_time.minute,
- l_time.second);
- str->append(intbuff);
+ length= my_sprintf(intbuff,
+ (intbuff,
+ "%02d:%02d:%02d",
+ l_time.hour,
+ l_time.minute,
+ l_time.second));
+ str->append(intbuff, length);
break;
case 'U':
case 'u':
{
uint year;
- sprintf(intbuff,"%02d",calc_week(&l_time, 0, (*ptr) == 'U', &year));
- str->append(intbuff,2);
+ length= int10_to_str(calc_week(&l_time, 0, (*ptr) == 'U', &year),
+ intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
}
break;
case 'v':
case 'V':
{
uint year;
- sprintf(intbuff,"%02d",calc_week(&l_time, 1, (*ptr) == 'V', &year));
- str->append(intbuff,2);
+ length= int10_to_str(calc_week(&l_time, 1, (*ptr) == 'V', &year),
+ intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
}
break;
case 'x':
@@ -916,14 +1042,15 @@ String *Item_func_date_format::val_str(String *str)
{
uint year;
(void) calc_week(&l_time, 1, (*ptr) == 'X', &year);
- sprintf(intbuff,"%04d",year);
- str->append(intbuff,4);
+ length= int10_to_str(year, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 4, '0');
}
break;
case 'w':
weekday=calc_weekday(calc_daynr(l_time.year,l_time.month,l_time.day),1);
- sprintf(intbuff,"%d",weekday);
- str->append(intbuff,1);
+ length= int10_to_str(weekday, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 1, '0');
+
break;
default:
str->append(*ptr);
@@ -1005,7 +1132,7 @@ void Item_date_add_interval::fix_length_and_dec()
enum_field_types arg0_field_type;
set_charset(default_charset());
maybe_null=1;
- max_length=19*default_charset()->mbmaxlen;
+ max_length=26*MY_CHARSET_BIN_MB_MAXLEN;
value.alloc(32);
/*
@@ -1051,39 +1178,55 @@ bool Item_date_add_interval::get_date(TIME *ltime, bool fuzzy_date)
null_value=0;
switch (int_type) {
case INTERVAL_SECOND:
+ case INTERVAL_SECOND_MICROSECOND:
+ case INTERVAL_MICROSECOND:
case INTERVAL_MINUTE:
case INTERVAL_HOUR:
+ case INTERVAL_MINUTE_MICROSECOND:
case INTERVAL_MINUTE_SECOND:
+ case INTERVAL_HOUR_MICROSECOND:
case INTERVAL_HOUR_SECOND:
case INTERVAL_HOUR_MINUTE:
+ case INTERVAL_DAY_MICROSECOND:
case INTERVAL_DAY_SECOND:
case INTERVAL_DAY_MINUTE:
case INTERVAL_DAY_HOUR:
- long sec,days,daynr;
+ long sec,days,daynr,microseconds,extra_sec;
ltime->time_type=TIMESTAMP_FULL; // Return full date
+ microseconds= ltime->second_part + sign*interval.second_part;
+ extra_sec= microseconds/1000000L;
+ microseconds= microseconds%1000000L;
sec=((ltime->day-1)*3600*24L+ltime->hour*3600+ltime->minute*60+
ltime->second +
sign*(interval.day*3600*24L +
- interval.hour*3600+interval.minute*60+interval.second));
+ interval.hour*3600+interval.minute*60+interval.second))+
+ extra_sec;
+
+ if (microseconds < 0)
+ {
+ microseconds+= 1000000L;
+ sec--;
+ }
days=sec/(3600*24L); sec=sec-days*3600*24L;
if (sec < 0)
{
days--;
sec+=3600*24L;
}
+ ltime->second_part= microseconds;
ltime->second=sec % 60;
ltime->minute=sec/60 % 60;
ltime->hour=sec/3600;
daynr= calc_daynr(ltime->year,ltime->month,1) + days;
get_date_from_daynr(daynr,&ltime->year,&ltime->month,&ltime->day);
- if (daynr < 0 || daynr >= 3652424) // Day number from year 0 to 9999-12-31
+ if (daynr < 0 || daynr >= MAX_DAY_NUMBER) // Day number from year 0 to 9999-12-31
goto null_date;
break;
case INTERVAL_DAY:
period= calc_daynr(ltime->year,ltime->month,ltime->day) +
sign*interval.day;
- if (period < 0 || period >= 3652424) // Daynumber from year 0 to 9999-12-31
+ if (period < 0 || period >= MAX_DAY_NUMBER) // Daynumber from year 0 to 9999-12-31
goto null_date;
get_date_from_daynr((long) period,&ltime->year,&ltime->month,&ltime->day);
break;
@@ -1124,34 +1267,21 @@ bool Item_date_add_interval::get_date(TIME *ltime, bool fuzzy_date)
String *Item_date_add_interval::val_str(String *str)
{
TIME ltime;
- CHARSET_INFO *cs=default_charset();
- uint32 l;
+ enum date_time_format_types format;
if (Item_date_add_interval::get_date(&ltime,0))
return 0;
+
if (ltime.time_type == TIMESTAMP_DATE)
- {
- l=11*cs->mbmaxlen+32;
- if (str->alloc(l))
- goto null_date;
- l=cs->cset->snprintf(cs,(char*) str->ptr(),l,"%04d-%02d-%02d",
- ltime.year,ltime.month,ltime.day);
- str->length(l);
- }
+ format= DATE_ONLY;
+ else if (ltime.second_part)
+ format= DATE_TIME_MICROSECOND;
else
- {
- l=20*cs->mbmaxlen+32;
- if (str->alloc(l))
- goto null_date;
- l=cs->cset->snprintf(cs,(char*) str->ptr(),l,"%04d-%02d-%02d %02d:%02d:%02d",
- ltime.year,ltime.month,ltime.day,
- ltime.hour,ltime.minute,ltime.second);
- str->length(l);
- }
- str->set_charset(cs);
- return str;
+ format= DATE_TIME;
+
+ if (make_datetime(str, &ltime, format))
+ return str;
- null_date:
null_value=1;
return 0;
}
@@ -1188,6 +1318,11 @@ void Item_extract::fix_length_and_dec()
case INTERVAL_MINUTE: max_length=2; date_value=0; break;
case INTERVAL_MINUTE_SECOND: max_length=4; date_value=0; break;
case INTERVAL_SECOND: max_length=2; date_value=0; break;
+ case INTERVAL_MICROSECOND: max_length=2; date_value=0; break;
+ case INTERVAL_DAY_MICROSECOND: max_length=20; date_value=0; break;
+ case INTERVAL_HOUR_MICROSECOND: max_length=13; date_value=0; break;
+ case INTERVAL_MINUTE_MICROSECOND: max_length=11; date_value=0; break;
+ case INTERVAL_SECOND_MICROSECOND: max_length=9; date_value=0; break;
}
}
@@ -1234,6 +1369,21 @@ longlong Item_extract::val_int()
case INTERVAL_MINUTE: return (long) ltime.minute*neg;
case INTERVAL_MINUTE_SECOND: return (long) (ltime.minute*100+ltime.second)*neg;
case INTERVAL_SECOND: return (long) ltime.second*neg;
+ case INTERVAL_MICROSECOND: return (long) ltime.second_part*neg;
+ case INTERVAL_DAY_MICROSECOND: return (((longlong)ltime.day*1000000L +
+ (longlong)ltime.hour*10000L +
+ ltime.minute*100 +
+ ltime.second)*1000000L +
+ ltime.second_part)*neg;
+ case INTERVAL_HOUR_MICROSECOND: return (((longlong)ltime.hour*10000L +
+ ltime.minute*100 +
+ ltime.second)*1000000L +
+ ltime.second_part)*neg;
+ case INTERVAL_MINUTE_MICROSECOND: return (((longlong)(ltime.minute*100+
+ ltime.second))*1000000L+
+ ltime.second_part)*neg;
+ case INTERVAL_SECOND_MICROSECOND: return ((longlong)ltime.second*1000000L+
+ ltime.second_part)*neg;
}
return 0; // Impossible
}
@@ -1247,3 +1397,337 @@ void Item_typecast::print(String *str)
str->append(func_name());
str->append(')');
}
+
+String *Item_datetime_typecast::val_str(String *str)
+{
+ TIME ltime;
+
+ if (!get_arg0_date(&ltime,1) &&
+ make_datetime(str, &ltime, ltime.second_part ?
+ DATE_TIME_MICROSECOND : DATE_TIME))
+ return str;
+
+null_date:
+ null_value=1;
+ return 0;
+}
+
+
+bool Item_time_typecast::get_time(TIME *ltime)
+{
+ bool res= get_arg0_time(ltime);
+ ltime->time_type= TIMESTAMP_TIME;
+ return res;
+}
+
+
+String *Item_time_typecast::val_str(String *str)
+{
+ TIME ltime;
+
+ if (!get_arg0_time(&ltime) &&
+ make_datetime(str, &ltime, ltime.second_part ? TIME_MICROSECOND : TIME_ONLY))
+ return str;
+
+ null_value=1;
+ return 0;
+}
+
+
+bool Item_date_typecast::get_date(TIME *ltime, bool fuzzy_date)
+{
+ bool res= get_arg0_date(ltime,1);
+ ltime->time_type= TIMESTAMP_DATE;
+ return res;
+}
+
+
+String *Item_date_typecast::val_str(String *str)
+{
+ TIME ltime;
+
+ if (!get_arg0_date(&ltime,1) &&
+ make_datetime(str, &ltime, DATE_ONLY))
+ return str;
+
+null_date:
+ null_value=1;
+ return 0;
+}
+
+/*
+ MAKEDATE(a,b) is a date function that creates a date value
+ from a year and day value.
+*/
+
+String *Item_func_makedate::val_str(String *str)
+{
+ TIME l_time;
+ long daynr= args[1]->val_int();
+ long yearnr= args[0]->val_int();
+ long days;
+
+ if (args[0]->null_value || args[1]->null_value ||
+ yearnr < 0 || daynr <= 0)
+ goto null_date;
+
+ days= calc_daynr(yearnr,1,1) + daynr - 1;
+ if (days > 0 || days < MAX_DAY_NUMBER) // Day number from year 0 to 9999-12-31
+ {
+ null_value=0;
+ get_date_from_daynr(days,&l_time.year,&l_time.month,&l_time.day);
+ if (make_datetime(str, &l_time, DATE_ONLY))
+ return str;
+ }
+
+null_date:
+ null_value=1;
+ return 0;
+}
+
+
+void Item_func_add_time::fix_length_and_dec()
+{
+ enum_field_types arg0_field_type;
+ decimals=0;
+ max_length=26*MY_CHARSET_BIN_MB_MAXLEN;
+
+ /*
+ The field type for the result of an Item_func_add_time function is defined as
+ follows:
+
+ - If first arg is a MYSQL_TYPE_DATETIME or MYSQL_TYPE_TIMESTAMP
+ result is MYSQL_TYPE_DATETIME
+ - If first arg is a MYSQL_TYPE_TIME result is MYSQL_TYPE_TIME
+ - Otherwise the result is MYSQL_TYPE_STRING
+ */
+
+ cached_field_type= MYSQL_TYPE_STRING;
+ arg0_field_type= args[0]->field_type();
+ if (arg0_field_type == MYSQL_TYPE_DATE ||
+ arg0_field_type == MYSQL_TYPE_DATETIME ||
+ arg0_field_type == MYSQL_TYPE_TIMESTAMP)
+ cached_field_type= MYSQL_TYPE_DATETIME;
+ else if (arg0_field_type == MYSQL_TYPE_TIME)
+ cached_field_type= MYSQL_TYPE_TIME;
+}
+
+/*
+ ADDTIME(t,a) and SUBTIME(t,a) are time functions that calculate a time/datetime value
+
+ t: time_or_datetime_expression
+ a: time_expression
+
+ Result: Time value or datetime value
+*/
+
+String *Item_func_add_time::val_str(String *str)
+{
+ TIME l_time1, l_time2, l_time3;
+ bool is_time= 0;
+ long microseconds, seconds, days= 0;
+ int l_sign= sign;
+
+ null_value=0;
+ l_time3.neg= 0;
+ if (is_date) // TIMESTAMP function
+ {
+ if (get_arg0_date(&l_time1,1) ||
+ args[1]->get_time(&l_time2) ||
+ l_time1.time_type == TIMESTAMP_TIME ||
+ l_time2.time_type != TIMESTAMP_TIME)
+ goto null_date;
+ }
+ else // ADDTIME function
+ {
+ if (args[0]->get_time(&l_time1) ||
+ args[1]->get_time(&l_time2) ||
+ l_time2.time_type == TIMESTAMP_FULL)
+ goto null_date;
+ is_time= (l_time1.time_type == TIMESTAMP_TIME);
+ if (is_time && (l_time2.neg == l_time1.neg && l_time1.neg))
+ l_time3.neg= 1;
+ }
+ if (l_time1.neg != l_time2.neg)
+ l_sign= -l_sign;
+
+ microseconds= l_time1.second_part + l_sign*l_time2.second_part;
+ seconds= (l_time1.hour*3600L + l_time1.minute*60L + l_time1.second +
+ (l_time2.day*86400L + l_time2.hour*3600L +
+ l_time2.minute*60L + l_time2.second)*l_sign);
+ if (is_time)
+ seconds+= l_time1.day*86400L;
+ else
+ days+= calc_daynr((uint) l_time1.year,(uint) l_time1.month, (uint) l_time1.day);
+ seconds= seconds + microseconds/1000000L;
+ microseconds= microseconds%1000000L;
+ days+= seconds/86400L;
+ seconds= seconds%86400L;
+
+ if (microseconds < 0)
+ {
+ microseconds+= 1000000L;
+ seconds--;
+ }
+ if (seconds < 0)
+ {
+ days+= seconds/86400L - 1;
+ seconds+= 86400L;
+ }
+ if (days < 0)
+ {
+ if (!is_time)
+ goto null_date;
+ if (microseconds)
+ {
+ microseconds= 1000000L - microseconds;
+ seconds++;
+ }
+ seconds= 86400L - seconds;
+ days= -(++days);
+ l_time3.neg= 1;
+ }
+
+ calc_time_from_sec(&l_time3, seconds, microseconds);
+ if (!is_time)
+ {
+ get_date_from_daynr(days,&l_time3.year,&l_time3.month,&l_time3.day);
+ if (l_time3.day &&
+ make_datetime(str, &l_time3,
+ l_time1.second_part || l_time2.second_part ?
+ DATE_TIME_MICROSECOND : DATE_TIME))
+ return str;
+ goto null_date;
+ }
+
+ l_time3.hour+= days*24;
+ if (make_datetime(str, &l_time3,
+ l_time1.second_part || l_time2.second_part ?
+ TIME_MICROSECOND : TIME_ONLY))
+ return str;
+
+null_date:
+ null_value=1;
+ return 0;
+}
+
+/*
+ TIMEDIFF(t,s) is a time function that calculates the
+ time value between a start and end time.
+
+ t and s: time_or_datetime_expression
+ Result: Time value
+*/
+
+String *Item_func_timediff::val_str(String *str)
+{
+ longlong seconds;
+ long microseconds;
+ long days;
+ int l_sign= 1;
+ TIME l_time1 ,l_time2, l_time3;
+
+ null_value= 0;
+ if (args[0]->get_time(&l_time1) ||
+ args[1]->get_time(&l_time2) ||
+ l_time1.time_type != l_time2.time_type)
+ goto null_date;
+
+ if (l_time1.neg != l_time2.neg)
+ l_sign= -l_sign;
+
+ if (l_time1.time_type == TIMESTAMP_TIME) // Time value
+ days= l_time1.day - l_sign*l_time2.day;
+ else // DateTime value
+ days= (calc_daynr((uint) l_time1.year,
+ (uint) l_time1.month,
+ (uint) l_time1.day) -
+ l_sign*calc_daynr((uint) l_time2.year,
+ (uint) l_time2.month,
+ (uint) l_time2.day));
+
+ microseconds= l_time1.second_part - l_sign*l_time2.second_part;
+ seconds= ((longlong) days*86400L + l_time1.hour*3600L +
+ l_time1.minute*60L + l_time1.second + microseconds/1000000L -
+ (longlong)l_sign*(l_time2.hour*3600L+l_time2.minute*60L+l_time2.second));
+
+ l_time3.neg= 0;
+ if (seconds < 0)
+ {
+ seconds= -seconds;
+ l_time3.neg= 1;
+ }
+ else if (seconds == 0 && microseconds < 0)
+ {
+ microseconds= -microseconds;
+ l_time3.neg= 1;
+ }
+ if (microseconds < 0)
+ {
+ microseconds+= 1000000L;
+ seconds--;
+ }
+ if ((l_time2.neg == l_time1.neg) && l_time1.neg)
+ l_time3.neg= l_time3.neg ? 0 : 1;
+
+ calc_time_from_sec(&l_time3, seconds, microseconds);
+ if (make_datetime(str, &l_time3,
+ l_time1.second_part || l_time2.second_part ?
+ TIME_MICROSECOND : TIME_ONLY))
+ return str;
+
+null_date:
+ null_value=1;
+ return 0;
+}
+
+/*
+ MAKETIME(h,m,s) is a time function that calculates a time value
+ from the total number of hours, minutes, and seconds.
+ Result: Time value
+*/
+
+String *Item_func_maketime::val_str(String *str)
+{
+ TIME ltime;
+
+ long hour= args[0]->val_int();
+ long minute= args[1]->val_int();
+ long second= args[2]->val_int();
+
+ if ((null_value=(args[0]->null_value ||
+ args[1]->null_value ||
+ args[2]->null_value ||
+ minute > 59 || minute < 0 ||
+ second > 59 || second < 0)))
+ goto null_date;
+
+ ltime.neg= 0;
+ if (hour < 0)
+ {
+ ltime.neg= 1;
+ hour= -hour;
+ }
+ ltime.hour= (ulong)hour;
+ ltime.minute= (ulong)minute;
+ ltime.second= (ulong)second;
+ if (make_datetime(str, &ltime, TIME_ONLY))
+ return str;
+
+null_date:
+ return 0;
+}
+
+/*
+ MICROSECOND(a) is a function ( extraction) that extracts the microseconds from a.
+
+ a: Datetime or time value
+ Result: int value
+*/
+longlong Item_func_microsecond::val_int()
+{
+ TIME ltime;
+ if (!get_arg0_time(&ltime))
+ return ltime.second_part;
+ return 0;
+}
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index 87563cf9f47..20b95f8e22d 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -478,9 +478,10 @@ public:
enum interval_type
{
INTERVAL_YEAR, INTERVAL_MONTH, INTERVAL_DAY, INTERVAL_HOUR, INTERVAL_MINUTE,
- INTERVAL_SECOND, INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR, INTERVAL_DAY_MINUTE,
- INTERVAL_DAY_SECOND, INTERVAL_HOUR_MINUTE, INTERVAL_HOUR_SECOND,
- INTERVAL_MINUTE_SECOND
+ INTERVAL_SECOND, INTERVAL_MICROSECOND ,INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR,
+ INTERVAL_DAY_MINUTE, INTERVAL_DAY_SECOND, INTERVAL_HOUR_MINUTE,
+ INTERVAL_HOUR_SECOND, INTERVAL_MINUTE_SECOND, INTERVAL_DAY_MICROSECOND,
+ INTERVAL_HOUR_MICROSECOND, INTERVAL_MINUTE_MICROSECOND, INTERVAL_SECOND_MICROSECOND
};
@@ -556,6 +557,8 @@ class Item_date_typecast :public Item_typecast
{
public:
Item_date_typecast(Item *a) :Item_typecast(a) {}
+ String *val_str(String *str);
+ bool get_date(TIME *ltime, bool fuzzy_date);
const char *func_name() const { return "date"; }
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
Field *tmp_table_field() { return result_field; }
@@ -570,6 +573,8 @@ class Item_time_typecast :public Item_typecast
{
public:
Item_time_typecast(Item *a) :Item_typecast(a) {}
+ String *val_str(String *str);
+ bool get_time(TIME *ltime);
const char *func_name() const { return "time"; }
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
Field *tmp_table_field() { return result_field; }
@@ -584,6 +589,7 @@ class Item_datetime_typecast :public Item_typecast
{
public:
Item_datetime_typecast(Item *a) :Item_typecast(a) {}
+ String *val_str(String *str);
const char *func_name() const { return "datetime"; }
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
Field *tmp_table_field() { return result_field; }
@@ -592,3 +598,106 @@ public:
return (new Field_datetime(maybe_null, name, t_arg, default_charset()));
}
};
+
+class Item_func_makedate :public Item_str_func
+{
+public:
+ Item_func_makedate(Item *a,Item *b) :Item_str_func(a,b) {}
+ String *val_str(String *str);
+ const char *func_name() const { return "makedate"; }
+ enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=8*MY_CHARSET_BIN_MB_MAXLEN;
+ }
+ Field *tmp_table_field() { return result_field; }
+ Field *tmp_table_field(TABLE *t_arg)
+ {
+ return (new Field_date(maybe_null, name, t_arg, &my_charset_bin));
+ }
+};
+
+
+class Item_func_add_time :public Item_str_func
+{
+ const bool is_date;
+ int sign;
+ enum_field_types cached_field_type;
+
+public:
+ Item_func_add_time(Item *a, Item *b, bool type_arg, bool neg_arg)
+ :Item_str_func(a, b), is_date(type_arg) { sign= neg_arg ? -1 : 1; }
+ String *val_str(String *str);
+ const char *func_name() const { return "addtime"; }
+ enum_field_types field_type() const { return cached_field_type; }
+ void fix_length_and_dec();
+
+/*
+ TODO:
+ Change this when we support
+ microseconds in TIME/DATETIME
+*/
+ Field *tmp_table_field() { return result_field; }
+ Field *tmp_table_field(TABLE *t_arg)
+ {
+ if (cached_field_type == MYSQL_TYPE_TIME)
+ return (new Field_time(maybe_null, name, t_arg, &my_charset_bin));
+ else if (cached_field_type == MYSQL_TYPE_DATETIME)
+ return (new Field_datetime(maybe_null, name, t_arg, &my_charset_bin));
+ return (new Field_string(max_length, maybe_null, name, t_arg, &my_charset_bin));
+ }
+};
+
+class Item_func_timediff :public Item_str_func
+{
+public:
+ Item_func_timediff(Item *a, Item *b)
+ :Item_str_func(a, b) {}
+ String *val_str(String *str);
+ const char *func_name() const { return "timediff"; }
+ enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=17*MY_CHARSET_BIN_MB_MAXLEN;
+ }
+ Field *tmp_table_field() { return result_field; }
+ Field *tmp_table_field(TABLE *t_arg)
+ {
+ return (new Field_time(maybe_null, name, t_arg, &my_charset_bin));
+ }
+};
+
+class Item_func_maketime :public Item_str_func
+{
+public:
+ Item_func_maketime(Item *a, Item *b, Item *c)
+ :Item_str_func(a, b ,c) {}
+ String *val_str(String *str);
+ const char *func_name() const { return "maketime"; }
+ enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=8*MY_CHARSET_BIN_MB_MAXLEN;
+ }
+ Field *tmp_table_field() { return result_field; }
+ Field *tmp_table_field(TABLE *t_arg)
+ {
+ return (new Field_time(maybe_null, name, t_arg, &my_charset_bin));
+ }
+};
+
+class Item_func_microsecond :public Item_int_func
+{
+public:
+ Item_func_microsecond(Item *a) :Item_int_func(a) {}
+ longlong val_int();
+ const char *func_name() const { return "microsecond"; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ maybe_null=1;
+ }
+};
diff --git a/sql/lex.h b/sql/lex.h
index bb6e7a81ab4..a148baad07f 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -116,6 +116,7 @@ static SYMBOL symbols[] = {
{ "DATETIME", SYM(DATETIME),0,0},
{ "DAY", SYM(DAY_SYM),0,0},
{ "DAY_HOUR", SYM(DAY_HOUR_SYM),0,0},
+ { "DAY_MICROSECOND", SYM(DAY_MICROSECOND_SYM),0,0},
{ "DAY_MINUTE", SYM(DAY_MINUTE_SYM),0,0},
{ "DAY_SECOND", SYM(DAY_SECOND_SYM),0,0},
{ "DEC", SYM(DECIMAL_SYM),0,0},
@@ -186,6 +187,7 @@ static SYMBOL symbols[] = {
{ "HELP", SYM(HELP_SYM),0,0},
{ "HIGH_PRIORITY", SYM(HIGH_PRIORITY),0,0},
{ "HOUR", SYM(HOUR_SYM),0,0},
+ { "HOUR_MICROSECOND", SYM(HOUR_MICROSECOND_SYM),0,0},
{ "HOUR_MINUTE", SYM(HOUR_MINUTE_SYM),0,0},
{ "HOUR_SECOND", SYM(HOUR_SECOND_SYM),0,0},
{ "HOSTS", SYM(HOSTS_SYM),0,0},
@@ -259,9 +261,11 @@ static SYMBOL symbols[] = {
{ "MERGE", SYM(MERGE_SYM),0,0},
{ "MEDIUM", SYM(MEDIUM_SYM),0,0},
{ "MEMORY", SYM(MEMORY_SYM),0,0},
+ { "MICROSECOND", SYM(MICROSECOND_SYM),0,0},
{ "MIDDLEINT", SYM(MEDIUMINT),0,0}, /* For powerbuilder */
{ "MIN_ROWS", SYM(MIN_ROWS),0,0},
{ "MINUTE", SYM(MINUTE_SYM),0,0},
+ { "MINUTE_MICROSECOND", SYM(MINUTE_MICROSECOND_SYM),0,0},
{ "MINUTE_SECOND", SYM(MINUTE_SECOND_SYM),0,0},
{ "MOD", SYM(MOD_SYM),0,0},
{ "MODE", SYM(MODE_SYM),0,0},
@@ -337,6 +341,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},
@@ -427,7 +432,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)},
@@ -470,6 +476,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)},
@@ -545,6 +552,8 @@ static SYMBOL sql_functions[] = {
{ "LPAD", SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_lpad)},
{ "LTRIM", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ltrim)},
{ "MAKE_SET", SYM(MAKE_SET_SYM),0,0},
+ { "MAKEDATE", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_makedate)},
+ { "MAKETIME", SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_maketime)},
{ "MASTER_POS_WAIT", SYM(MASTER_POS_WAIT),0,0},
{ "MAX", SYM(MAX_SYM),0,0},
{ "MBRCONTAINS", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_contains)},
@@ -605,7 +614,7 @@ static SYMBOL sql_functions[] = {
{ "RTRIM", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_rtrim)},
{ "SEC_TO_TIME", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sec_to_time)},
{ "SESSION_USER", SYM(USER),0,0},
- { "SUBDATE", SYM(DATE_SUB_INTERVAL),0,0},
+ { "SUBDATE", SYM(SUBDATE_SYM),0,0},
{ "SIGN", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sign)},
{ "SIN", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sin)},
{ "SHA", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sha)},
@@ -620,12 +629,14 @@ static SYMBOL sql_functions[] = {
{ "STRCMP", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_strcmp)},
{ "SUBSTRING", SYM(SUBSTRING),0,0},
{ "SUBSTRING_INDEX", SYM(SUBSTRING_INDEX),0,0},
+ { "SUBTIME", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_subtime)},
{ "SUM", SYM(SUM_SYM),0,0},
{ "SYSDATE", SYM(NOW_SYM),0,0},
{ "SYSTEM_USER", SYM(USER),0,0},
{ "TAN", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_tan)},
{ "TIME_FORMAT", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_time_format)},
{ "TIME_TO_SEC", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_time_to_sec)},
+ { "TIMEDIFF", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_timediff)},
{ "TO_DAYS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_to_days)},
{ "TOUCHES", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_touches)},
{ "TRIM", SYM(TRIM),0,0},
@@ -639,6 +650,7 @@ static SYMBOL sql_functions[] = {
{ "VERSION", SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_version)},
{ "WEEK", SYM(WEEK_SYM),0,0},
{ "WEEKDAY", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekday)},
+ { "WEEKOFYEAR", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekofyear)},
{ "WITHIN", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_within)},
{ "X", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_x)},
{ "Y", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_y)},
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 2b48a7f37d8..28446ed746f 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
@@ -557,6 +559,7 @@ void free_prep_stmt(PREP_STMT *stmt, TREE_FREE mode, void *not_used);
bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length);
void mysql_stmt_execute(THD *thd, char *packet);
void mysql_stmt_free(THD *thd, char *packet);
+void mysql_stmt_reset(THD *thd, char *packet);
void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length);
int check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
List<Item> &values, ulong counter);
@@ -770,6 +773,7 @@ extern rw_lock_t LOCK_grant;
extern pthread_cond_t COND_refresh, COND_thread_count, COND_manager;
extern pthread_attr_t connection_attrib;
extern I_List<THD> threads;
+extern I_List<NAMED_LIST> key_caches;
extern MY_BITMAP temp_pool;
extern DATE_FORMAT dayord;
extern String empty_string;
@@ -851,6 +855,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);
@@ -903,9 +908,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 <i_string_pair> replicate_rewrite_db;
+I_List<i_string_pair> replicate_rewrite_db;
I_List<i_string> replicate_do_db, replicate_ignore_db;
// allow the user to tell us which db to replicate and which to ignore
I_List<i_string> binlog_do_db, binlog_ignore_db;
I_List<THD> threads,thread_cache;
+I_List<NAMED_LIST> key_caches;
struct system_variables global_system_variables;
struct system_variables max_system_variables;
@@ -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<THD>;
template class I_List_iterator<THD>;
template class I_List<i_string>;
template class I_List<i_string_pair>;
-
+template class I_List<NAMED_LIST>;
FIX_GCC_LINKING_PROBLEM
#endif
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 1a1d1f0a585..1b9256c7723 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -823,6 +823,13 @@ bool Protocol_simple::store(Field *field)
}
+/*
+ TODO:
+ Second_part format ("%06") needs to change when
+ we support 0-6 decimals for time.
+*/
+
+
bool Protocol_simple::store(TIME *tm)
{
#ifndef DEBUG_OFF
@@ -840,6 +847,8 @@ bool Protocol_simple::store(TIME *tm)
(int) tm->hour,
(int) tm->minute,
(int) tm->second));
+ if (tm->second_part)
+ length+= my_sprintf(buff+length,(buff+length, ".%06d", (int)tm->second_part));
return net_store_data((char*) buff, length);
}
@@ -861,6 +870,12 @@ bool Protocol_simple::store_date(TIME *tm)
}
+/*
+ TODO:
+ Second_part format ("%06") needs to change when
+ we support 0-6 decimals for time.
+*/
+
bool Protocol_simple::store_time(TIME *tm)
{
#ifndef DEBUG_OFF
@@ -876,6 +891,8 @@ bool Protocol_simple::store_time(TIME *tm)
(long) day*24L+(long) tm->hour,
(int) tm->minute,
(int) tm->second));
+ if (tm->second_part)
+ length+= my_sprintf(buff+length,(buff+length, ".%06d", (int)tm->second_part));
return net_store_data((char*) buff, length);
}
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 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<NAMED_LIST> *list, const char *name, uint length)
+{
+ I_List_iterator<NAMED_LIST> it(*list);
+ NAMED_LIST *element;
+ while ((element= it++))
+ {
+ if (element->cmp(name, length))
+ return element->data;
+ }
+ return 0;
+}
+
+
+void delete_elements(I_List<NAMED_LIST> *list, void (*free_element)(gptr))
+{
+ NAMED_LIST *element;
+ while ((element= list->get()))
+ {
+ (*free_element)(element->data);
+ delete element;
+ }
+}
+
+
+/* Key cache functions */
+
+static KEY_CACHE *create_key_cache(const char *name, uint length)
+{
+ KEY_CACHE *key_cache;
+ DBUG_PRINT("info",("Creating key cache: %s", name));
+ if ((key_cache= (KEY_CACHE*) my_malloc(sizeof(KEY_CACHE),
+ MYF(MY_ZEROFILL | MY_WME))))
+ {
+ if (!new NAMED_LIST(&key_caches, name, length, (gptr) key_cache))
+ {
+ my_free((char*) key_cache, MYF(0));
+ key_cache= 0;
+ }
+ }
+ return key_cache;
+}
+
+
+KEY_CACHE *get_or_create_key_cache(const char *name, uint length)
+{
+ KEY_CACHE *key_cache= (KEY_CACHE*) find_named(&key_caches, name,
+ length);
+ if (!key_cache)
+ key_cache= create_key_cache(name, length);
+ return key_cache;
+}
+
+
+void free_key_cache(gptr key_cache)
+{
+ my_free(key_cache, MYF(0));
+}
+
/****************************************************************************
Used templates
@@ -1953,4 +2102,5 @@ ulong fix_sql_mode(ulong sql_mode)
#ifdef __GNUC__
template class List<set_var_base>;
template class List_iterator_fast<set_var_base>;
+template class I_List_iterator<NAMED_LIST>;
#endif
diff --git a/sql/set_var.h b/sql/set_var.h
index 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<NAMED_LIST> *links, const char *name_arg,
+ uint name_length_arg, gptr data_arg):
+ name_length(name_length_arg), data(data_arg)
+ {
+ name=my_strdup(name_arg,MYF(MY_WME));
+ links->push_back(this);
+ }
+ inline bool cmp(const char *name_cmp, uint length)
+ {
+ return length == name_length && !memcmp(name, name_cmp, length);
+ }
+ ~NAMED_LIST()
+ {
+ my_free((char*) name, MYF(0));
+ }
+};
+
+
/*
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<set_var_base> *var_list);
void fix_delay_key_write(THD *thd, enum_var_type type);
ulong fix_sql_mode(ulong sql_mode);
-
extern sys_var_str sys_charset_system;
CHARSET_INFO *get_old_charset_by_name(const char *old_name);
+gptr find_named(I_List<NAMED_LIST> *list, const char *name, uint length);
+void delete_elements(I_List<NAMED_LIST> *list, void (*free_element)(gptr));
+
+/* key_cache functions */
+KEY_CACHE *get_or_create_key_cache(const char *name, uint length);
+void free_key_cache(gptr key_cache);
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index 641b1384e9a..30516e8dad1 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -17,7 +17,7 @@ v/*
"Nemohu vytvo-Břit soubor '%-.64s' (chybový kód: %d)",
"Nemohu vytvo-Břit tabulku '%-.64s' (chybový kód: %d)",
"Nemohu vytvo-Břit databázi '%-.64s', chyba %d",
-"Nemohu vytvo-Břit databázi '%-.64s', databáze již existuje",
+"Nemohu vytvo-Břit databázi '%-.64s'; databáze již existuje",
"Nemohu zru-Bšit databázi '%-.64s', databáze neexistuje",
"Chyba p-Bři rušení databáze (nemohu vymazat '%-.64s', chyba %d)",
"Chyba p-Bři rušení databáze (nemohu vymazat adresář '%-.64s', chyba %d)",
@@ -275,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..289f70c79ed 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -11,8 +11,8 @@
"Kan ikke oprette filen '%-.64s' (Fejlkode: %d)",
"Kan ikke oprette tabellen '%-.64s' (Fejlkode: %d)",
"Kan ikke oprette databasen '%-.64s'. Fejl %d",
-"Kan ikke oprette databasen '%-.64s'. Databasen eksisterer",
-"Kan ikke slette (droppe) '%-.64s'. Databasen eksisterer ikke",
+"Kan ikke oprette databasen '%-.64s'; databasen eksisterer",
+"Kan ikke slette (droppe) '%-.64s'; databasen eksisterer ikke",
"Fejl ved sletning (drop) af databasen (kan ikke slette '%-.64s', Fejl %d)",
"Fejl ved sletting af database (kan ikke slette folderen '%-.64s', Fejl %d)",
"Fejl ved sletning af '%-.64s' (Fejlkode: %d)",
@@ -269,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..8cf926554a4 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -19,8 +19,8 @@
"Kan file '%-.64s' niet aanmaken (Errcode: %d)",
"Kan tabel '%-.64s' niet aanmaken (Errcode: %d)",
"Kan database '%-.64s' niet aanmaken (Errcode: %d)",
-"Kan database '%-.64s' niet aanmaken. Database bestaat reeds",
-"Kan database '%-.64s' niet verwijderen. Database bestaat niet",
+"Kan database '%-.64s' niet aanmaken; database bestaat reeds",
+"Kan database '%-.64s' niet verwijderen; database bestaat niet",
"Fout bij verwijderen database (kan '%-.64s' niet verwijderen, Errcode: %d)",
"Fout bij verwijderen database (kan rmdir '%-.64s' niet uitvoeren, Errcode: %d)",
"Fout bij het verwijderen van '%-.64s' (Errcode: %d)",
@@ -277,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..6f0de413a47 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -8,8 +8,8 @@
"Can't create file '%-.64s' (errno: %d)",
"Can't create table '%-.64s' (errno: %d)",
"Can't create database '%-.64s'. (errno: %d)",
-"Can't create database '%-.64s'. Database exists",
-"Can't drop database '%-.64s'. Database doesn't exist",
+"Can't create database '%-.64s'; database exists",
+"Can't drop database '%-.64s'; database doesn't exist",
"Error dropping database (can't delete '%-.64s', errno: %d)",
"Error dropping database (can't rmdir '%-.64s', errno: %d)",
"Error on delete of '%-.64s' (errno: %d)",
@@ -271,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..5d82eebefda 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -8,8 +8,8 @@
"Ne peut créer le fichier '%-.64s' (Errcode: %d)",
"Ne peut créer la table '%-.64s' (Errcode: %d)",
"Ne peut créer la base '%-.64s'. Erreur %d",
-"Ne peut créer la base '%-.64s'. Elle existe déjŕ",
-"Ne peut effacer la base '%-.64s'. Elle n'existe pas",
+"Ne peut créer la base '%-.64s'; elle existe déjŕ",
+"Ne peut effacer la base '%-.64s'; elle n'existe pas",
"Ne peut effacer la base '%-.64s' (erreur %d)",
"Erreur en effaçant la base (rmdir '%-.64s', erreur %d)",
"Erreur en effaçant '%-.64s' (Errcode: %d)",
@@ -266,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..4512cd1e0cb 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -17,8 +17,8 @@
"Kann Datei '%-.64s' nicht erzeugen. (Fehler: %d)",
"Kann Tabelle '%-.64s' nicht erzeugen. (Fehler: %d)",
"Kann Datenbank '%-.64s' nicht erzeugen. (Fehler: %d)",
-"Kann Datenbank '%-.64s' nicht erzeugen. Datenbank '%-.64s' existiert bereits.",
-"Kann Datenbank '%-.64s' nicht löschen. Keine Datenbank '%-.64s' vorhanden.",
+"Kann Datenbank '%-.64s' nicht erzeugen; datenbank '%-.64s' existiert bereits.",
+"Kann Datenbank '%-.64s' nicht löschen; keine Datenbank '%-.64s' vorhanden.",
"Fehler beim Löschen der Datenbank. ('%-.64s' kann nicht gelöscht werden, Fehlernuumer: %d)",
"Fehler beim Löschen der Datenbank. (Verzeichnis '%-.64s' kann nicht gelöscht werden, Fehlernummer: %d)",
"Fehler beim Löschen von '%-.64s'. (Fehler: %d)",
@@ -275,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..cc21f7cf42a 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -8,8 +8,8 @@
"Impossibile creare il file '%-.64s' (errno: %d)",
"Impossibile creare la tabella '%-.64s' (errno: %d)",
"Impossibile creare il database '%-.64s'. (errno: %d)",
-"Impossibile creare il database '%-.64s'. Il database esiste",
-"Impossibile cancellare '%-.64s'. Il database non esiste",
+"Impossibile creare il database '%-.64s'; il database esiste",
+"Impossibile cancellare '%-.64s'; il database non esiste",
"Errore durante la cancellazione del database (impossibile cancellare '%-.64s', errno: %d)",
"Errore durante la cancellazione del database (impossibile rmdir '%-.64s', errno: %d)",
"Errore durante la cancellazione di '%-.64s' (errno: %d)",
@@ -266,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..f562553e40a 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -10,8 +10,8 @@
"Kan ikkje opprette fila '%-.64s' (Feilkode: %d)",
"Kan ikkje opprette tabellen '%-.64s' (Feilkode: %d)",
"Kan ikkje opprette databasen '%-.64s'. Feil %d",
-"Kan ikkje opprette databasen '%-.64s'. Databasen eksisterer",
-"Kan ikkje fjerne (drop) '%-.64s'. Databasen eksisterer ikkje",
+"Kan ikkje opprette databasen '%-.64s'; databasen eksisterer",
+"Kan ikkje fjerne (drop) '%-.64s'; databasen eksisterer ikkje",
"Feil ved fjerning (drop) av databasen (kan ikkje slette '%-.64s', feil %d)",
"Feil ved sletting av database (kan ikkje slette katalogen '%-.64s', feil %d)",
"Feil ved sletting av '%-.64s' (Feilkode: %d)",
@@ -268,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..dcb7be9a053 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -10,8 +10,8 @@
"Kan ikke opprette fila '%-.64s' (Feilkode: %d)",
"Kan ikke opprette tabellen '%-.64s' (Feilkode: %d)",
"Kan ikke opprette databasen '%-.64s'. Feil %d",
-"Kan ikke opprette databasen '%-.64s'. Databasen eksisterer",
-"Kan ikke fjerne (drop) '%-.64s'. Databasen eksisterer ikke",
+"Kan ikke opprette databasen '%-.64s'; databasen eksisterer",
+"Kan ikke fjerne (drop) '%-.64s'; databasen eksisterer ikke",
"Feil ved fjerning (drop) av databasen (kan ikke slette '%-.64s', feil %d)",
"Feil ved sletting av database (kan ikke slette katalogen '%-.64s', feil %d)",
"Feil ved sletting av '%-.64s' (Feilkode: %d)",
@@ -268,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..9cd63dfc009 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -12,8 +12,8 @@
"Nie można stworzyć pliku '%-.64s' (Kod błędu: %d)",
"Nie można stworzyć tabeli '%-.64s' (Kod błędu: %d)",
"Nie można stworzyć bazy danych '%-.64s'. Bł?d %d",
-"Nie można stworzyć bazy danych '%-.64s'. Baza danych już istnieje",
-"Nie można usun?ć bazy danych '%-.64s'. Baza danych nie istnieje",
+"Nie można stworzyć bazy danych '%-.64s'; baza danych już istnieje",
+"Nie można usun?ć bazy danych '%-.64s'; baza danych nie istnieje",
"Bł?d podczas usuwania bazy danych (nie można usun?ć '%-.64s', bł?d %d)",
"Bł?d podczas usuwania bazy danych (nie można wykonać rmdir '%-.64s', bł?d %d)",
"Bł?d podczas usuwania '%-.64s' (Kod błędu: %d)",
@@ -270,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..14a1e6763b4 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -8,8 +8,8 @@
"Năo pode criar o arquivo '%-.64s' (erro no. %d)",
"Năo pode criar a tabela '%-.64s' (erro no. %d)",
"Năo pode criar o banco de dados '%-.64s' (erro no. %d)",
-"Năo pode criar o banco de dados '%-.64s'. Este banco de dados já existe",
-"Năo pode eliminar o banco de dados '%-.64s'. Este banco de dados năo existe",
+"Năo pode criar o banco de dados '%-.64s'; este banco de dados já existe",
+"Năo pode eliminar o banco de dados '%-.64s'; este banco de dados năo existe",
"Erro ao eliminar banco de dados (năo pode eliminar '%-.64s' - erro no. %d)",
"Erro ao eliminar banco de dados (năo pode remover diretório '%-.64s' - erro no. %d)",
"Erro na remoçăo de '%-.64s' (erro no. %d)",
@@ -266,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..c5be6e5df8d 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -12,8 +12,8 @@
"Nu pot sa creez fisierul '%-.64s' (Eroare: %d)",
"Nu pot sa creez tabla '%-.64s' (Eroare: %d)",
"Nu pot sa creez baza de date '%-.64s'. (Eroare: %d)",
-"Nu pot sa creez baza de date '%-.64s'. Baza de date exista deja",
-"Nu pot sa drop baza de date '%-.64s'. Baza da date este inexistenta",
+"Nu pot sa creez baza de date '%-.64s'; baza de date exista deja",
+"Nu pot sa drop baza de date '%-.64s'; baza da date este inexistenta",
"Eroare dropuind baza de date (nu pot sa sterg '%-.64s', Eroare: %d)",
"Eroare dropuind baza de date (nu pot sa rmdir '%-.64s', Eroare: %d)",
"Eroare incercind sa delete '%-.64s' (Eroare: %d)",
@@ -270,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..e413097a997 100644
--- a/sql/share/serbian/errmsg.txt
+++ b/sql/share/serbian/errmsg.txt
@@ -14,8 +14,8 @@
"Ne mogu da kreiram file '%-.64s' (errno: %d)",
"Ne mogu da kreiram tabelu '%-.64s' (errno: %d)",
"Ne mogu da kreiram bazu '%-.64s'. (errno: %d)",
-"Ne mogu da kreiram bazu '%-.64s'. Baza već postoji.",
-"Ne mogu da izbrišem bazu '%-.64s'. Baza ne postoji.",
+"Ne mogu da kreiram bazu '%-.64s'; baza već postoji.",
+"Ne mogu da izbrišem bazu '%-.64s'; baza ne postoji.",
"Ne mogu da izbrišem bazu (ne mogu da izbrišem '%-.64s', errno: %d)",
"Ne mogu da izbrišem bazu (ne mogu da izbrišem direktorijum '%-.64s', errno: %d)",
"Greška pri brisanju '%-.64s' (errno: %d)",
@@ -262,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..a3e34b8b41a 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -16,8 +16,8 @@
"Nemôžem vytvoriť súbor '%-.64s' (chybový kód: %d)",
"Nemôžem vytvoriť tabuľku '%-.64s' (chybový kód: %d)",
"Nemôžem vytvoriť databázu '%-.64s'. (chybový kód: %d)",
-"Nemôžem vytvoriť databázu '%-.64s'. Databáza existuje",
-"Nemôžem zmazať databázu '%-.64s'. Databáza neexistuje",
+"Nemôžem vytvoriť databázu '%-.64s'; databáza existuje",
+"Nemôžem zmazať databázu '%-.64s'; databáza neexistuje",
"Chyba pri mazaní databázy (nemôžem zmazať '%-.64s', chybový kód: %d)",
"Chyba pri mazaní databázy (nemôžem vymazať adresár '%-.64s', chybový kód: %d)",
"Chyba pri mazaní '%-.64s' (chybový kód: %d)",
@@ -274,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..c1b3f19da4f 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -9,8 +9,8 @@
"No puedo crear archivo '%-.64s' (Error: %d)",
"No puedo crear tabla '%-.64s' (Error: %d)",
"No puedo crear base de datos '%-.64s'. Error %d",
-"No puedo crear base de datos '%-.64s'. La base de datos ya existe",
-"No puedo eliminar base de datos '%-.64s'. La base de datos no existe",
+"No puedo crear base de datos '%-.64s'; la base de datos ya existe",
+"No puedo eliminar base de datos '%-.64s'; la base de datos no existe",
"Error eliminando la base de datos(no puedo borrar '%-.64s', error %d)",
"Error eliminando la base de datos (No puedo borrar directorio '%-.64s', error %d)",
"Error en el borrado de '%-.64s' (Error: %d)",
@@ -267,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..b1153c83504 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -9,7 +9,7 @@
"Kan inte skapa tabellen '%-.64s' (Felkod: %d)",
"Kan inte skapa databasen '%-.64s'. (Felkod: %d)",
"Databasen '%-.64s' existerar redan",
-"Kan inte radera databasen '%-.64s'. Databasen finns inte",
+"Kan inte radera databasen '%-.64s'; databasen finns inte",
"Fel vid radering av databasen (Kan inte radera '%-.64s'. Felkod: %d)",
"Fel vid radering av databasen (Kan inte radera biblioteket '%-.64s'. Felkod: %d)",
"Kan inte radera filen '%-.64s' (Felkod: %d)",
@@ -266,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 21858e0352c..6b8fb947946 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 396e2d087ff..78adebdfff3 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))
@@ -3584,15 +3589,20 @@ mysql_new_select(LEX *lex, bool move_down)
void create_select_for_variable(const char *var_name)
{
+ THD *thd;
LEX *lex;
- LEX_STRING tmp;
+ LEX_STRING tmp, null_lex_string;
DBUG_ENTER("create_select_for_variable");
- lex= current_lex;
+
+ thd= current_thd;
+ lex= &thd->lex;
mysql_init_select(lex);
lex->sql_command= SQLCOM_SELECT;
tmp.str= (char*) var_name;
tmp.length=strlen(var_name);
- add_item_to_list(lex->thd, get_system_var(OPT_SESSION, tmp));
+ bzero((char*) &null_lex_string.str, sizeof(null_lex_string));
+ add_item_to_list(thd, get_system_var(thd, OPT_SESSION, tmp,
+ null_lex_string));
DBUG_VOID_RETURN;
}
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index c38fb44db1c..550e4bbe086 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -965,7 +965,7 @@ void mysql_stmt_reset(THD *thd, char *packet)
PREP_STMT *stmt;
DBUG_ENTER("mysql_stmt_reset");
- if (!(stmt=find_prepared_statement(thd, stmt_id, "close")))
+ if (!(stmt= find_prepared_statement(thd, stmt_id, "reset")))
{
send_error(thd);
DBUG_VOID_RETURN;
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index fae01936357..e8cb59e387e 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1527,12 +1527,14 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
char buff[1024];
List<Item> field_list;
Protocol *protocol= thd->protocol;
+ LEX_STRING null_lex_str;
DBUG_ENTER("mysqld_show");
field_list.push_back(new Item_empty_string("Variable_name",30));
field_list.push_back(new Item_empty_string("Value",256));
if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1); /* purecov: inspected */
+ null_lex_str.str= 0; // For sys_var->value_ptr()
/* pthread_mutex_lock(&THR_LOCK_keycache); */
pthread_mutex_lock(&LOCK_status);
@@ -1551,7 +1553,8 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
if (show_type == SHOW_SYS)
{
show_type= ((sys_var*) value)->type();
- value= (char*) ((sys_var*) value)->value_ptr(thd, value_type);
+ value= (char*) ((sys_var*) value)->value_ptr(thd, value_type,
+ &null_lex_str);
}
pos= end= buff;
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 0a3e8d0db9f..e7d7b08c93c 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -390,6 +390,23 @@ bool String::append(IO_CACHE* file, uint32 arg_length)
return FALSE;
}
+bool String::append_with_prefill(const char *s,uint32 arg_length,
+ uint32 full_length, char fill_char)
+{
+ int t_length= arg_length > full_length ? arg_length : full_length;
+
+ if (realloc(str_length + t_length))
+ return TRUE;
+ t_length= full_length - arg_length;
+ if (t_length > 0)
+ {
+ bfill(Ptr+str_length, t_length, fill_char);
+ str_length=str_length + t_length;
+ }
+ append(s, arg_length);
+ return FALSE;
+}
+
uint32 String::numchars()
{
return str_charset->cset->numchars(str_charset, Ptr, Ptr+str_length);
diff --git a/sql/sql_string.h b/sql/sql_string.h
index e88c9389589..d446d26298b 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -189,6 +189,8 @@ public:
bool append(const char *s,uint32 arg_length=0);
bool append(const char *s,uint32 arg_length, CHARSET_INFO *cs);
bool append(IO_CACHE* file, uint32 arg_length);
+ bool append_with_prefill(const char *s, uint32 arg_length,
+ uint32 full_length, char fill_char);
int strstr(const String &search,uint32 offset=0); // Returns offset to substring or -1
int strstr_case(const String &s,uint32 offset=0);
int strrstr(const String &search,uint32 offset=0); // Returns offset to substring or -1
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 8cdcc3b49fa..768386b1a53 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -163,6 +163,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token VARIANCE_SYM
%token STOP_SYM
%token SUM_SYM
+%token ADDDATE_SYM
%token SUPER_SYM
%token TRUNCATE_SYM
%token UNLOCK_SYM
@@ -431,6 +432,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token VARYING
%token ZEROFILL
+%token ADDDATE_SYM
%token AGAINST
%token ATAN
%token BETWEEN_SYM
@@ -445,6 +447,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token DATE_ADD_INTERVAL
%token DATE_SUB_INTERVAL
%token DAY_HOUR_SYM
+%token DAY_MICROSECOND_SYM
%token DAY_MINUTE_SYM
%token DAY_SECOND_SYM
%token DAY_SYM
@@ -467,6 +470,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token GEOMETRYCOLLECTION
%token GROUP_CONCAT_SYM
%token GROUP_UNIQUE_USERS
+%token HOUR_MICROSECOND_SYM
%token HOUR_MINUTE_SYM
%token HOUR_SECOND_SYM
%token HOUR_SYM
@@ -481,6 +485,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token LOCATE
%token MAKE_SET_SYM
%token MASTER_POS_WAIT
+%token MICROSECOND_SYM
+%token MINUTE_MICROSECOND_SYM
%token MINUTE_SECOND_SYM
%token MINUTE_SYM
%token MODE_SYM
@@ -505,7 +511,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
@@ -561,7 +569,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
IDENT TEXT_STRING REAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM LEX_HOSTNAME
ULONGLONG_NUM field_ident select_alias ident ident_or_text
UNDERSCORE_CHARSET IDENT_sys TEXT_STRING_sys TEXT_STRING_literal
- NCHAR_STRING
+ NCHAR_STRING opt_component
%type <lex_str_ptr>
opt_table_alias
@@ -1532,6 +1540,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 +2288,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
@@ -2334,6 +2346,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 ')'
@@ -2368,6 +2384,10 @@ simple_expr:
$$= new Item_func_database();
Lex->safe_to_cache_query=0;
}
+ | DATE_SYM '(' expr ')'
+ { $$= new Item_date_typecast($3); }
+ | DAY_SYM '(' expr ')'
+ { $$= new Item_func_dayofmonth($3); }
| ELT_FUNC '(' expr ',' expr_list ')'
{ $$= new Item_func_elt($3, *$5); }
| MAKE_SET_SYM '(' expr ',' expr_list ')'
@@ -2440,7 +2460,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;
}
@@ -2484,6 +2504,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 ')'
@@ -2545,6 +2567,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 ')'
@@ -2557,6 +2583,12 @@ simple_expr:
{ $$= new Item_func_substr($3,$5); }
| SUBSTRING_INDEX '(' expr ',' expr ',' expr ')'
{ $$= new Item_func_substr_index($3,$5,$7); }
+ | TIME_SYM '(' expr ')'
+ { $$= new Item_time_typecast($3); }
+ | TIMESTAMP '(' expr ')'
+ { $$= new Item_datetime_typecast($3); }
+ | TIMESTAMP '(' expr ',' expr ')'
+ { $$= new Item_func_add_time($3, $5, 1, 0); }
| TRIM '(' expr ')'
{ $$= new Item_func_trim($3); }
| TRIM '(' LEADING expr FROM expr ')'
@@ -2973,15 +3005,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; };
@@ -3705,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;
}
@@ -3765,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
@@ -3795,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; };
@@ -3912,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:
@@ -4300,6 +4342,7 @@ user:
keyword:
ACTION {}
+ | ADDDATE_SYM {}
| AFTER_SYM {}
| AGAINST {}
| AGGREGATE_SYM {}
@@ -4395,6 +4438,7 @@ keyword:
| MEDIUM_SYM {}
| MERGE_SYM {}
| MEMORY_SYM {}
+ | MICROSECOND_SYM {}
| MINUTE_SYM {}
| MIN_ROWS {}
| MODIFY_SYM {}
@@ -4460,6 +4504,7 @@ keyword:
| STATUS_SYM {}
| STOP_SYM {}
| STRING_SYM {}
+ | SUBDATE_SYM {}
| SUBJECT_SYM {}
| SUPER_SYM {}
| TEMPORARY {}
@@ -4590,6 +4635,27 @@ internal_variable_name:
YYABORT;
$$=tmp;
}
+ | ident '.' ident
+ {
+ sys_var *tmp=find_sys_var($3.str, $3.length);
+ if (!tmp)
+ YYABORT;
+ if (!tmp->is_struct())
+ net_printf(YYTHD, ER_VARIABLE_IS_NOT_STRUCT, $3.str);
+ tmp->base_name= $1;
+ $$=tmp;
+ }
+ | DEFAULT '.' ident
+ {
+ sys_var *tmp=find_sys_var($3.str, $3.length);
+ if (!tmp)
+ YYABORT;
+ if (!tmp->is_struct())
+ net_printf(YYTHD, ER_VARIABLE_IS_NOT_STRUCT, $3.str);
+ tmp->base_name.str= (char*) "default";
+ tmp->base_name.length= 7;
+ $$=tmp;
+ }
;
isolation_types:
diff --git a/sql/time.cc b/sql/time.cc
index b6ca306e523..70ae8dcd8ed 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -432,6 +432,7 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
l_time->minute=date[4];
l_time->second=date[5];
l_time->second_part=date[6];
+ l_time->neg= 0;
DBUG_RETURN(l_time->time_type=
(number_of_fields <= 3 ? TIMESTAMP_DATE : TIMESTAMP_FULL));
}
@@ -581,7 +582,7 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
/* Get fractional second part */
if ((end-str) >= 2 && *str == '.' && my_isdigit(&my_charset_latin1,str[1]))
{
- uint field_length=3;
+ uint field_length=5;
str++; value=(uint) (uchar) (*str - '0');
while (++str != end &&
my_isdigit(&my_charset_latin1,str[0]) &&
@@ -604,6 +605,7 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
l_time->minute=date[2];
l_time->second=date[3];
l_time->second_part=date[4];
+ l_time->time_type= TIMESTAMP_TIME;
/* Check if there is garbage at end of the TIME specification */
if (str != end && current_thd->count_cuted_fields)
@@ -636,3 +638,13 @@ void localtime_to_TIME(TIME *to, struct tm *from)
to->minute= (int) from->tm_min;
to->second= (int) from->tm_sec;
}
+
+void calc_time_from_sec(TIME *to, long seconds, long microseconds)
+{
+ long t_seconds;
+ to->hour= seconds/3600L;
+ t_seconds= seconds%3600L;
+ to->minute= t_seconds/60L;
+ to->second= t_seconds%60L;
+ to->second_part= microseconds;
+}