summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bzrignore1
-rw-r--r--client/client_priv.h2
-rw-r--r--configure.in2
-rw-r--r--include/m_ctype.h12
-rw-r--r--include/my_base.h32
-rw-r--r--include/mysql.h3
-rw-r--r--include/mysqld_error.h5
-rw-r--r--include/queues.h1
-rw-r--r--include/sql_state.h1
-rw-r--r--include/thr_alarm.h4
-rw-r--r--innobase/include/os0thread.h11
-rw-r--r--innobase/include/srv0srv.h2
-rw-r--r--innobase/srv/srv0srv.c13
-rw-r--r--innobase/srv/srv0start.c26
-rw-r--r--innobase/thr/thr0loc.c1
-rw-r--r--libmysql/client_settings.h6
-rw-r--r--libmysql/libmysql.c6
-rw-r--r--libmysql/libmysql.def2
-rw-r--r--myisam/myisamchk.c2
-rw-r--r--mysql-test/r/create.result52
-rw-r--r--mysql-test/r/ctype_mb.result5
-rw-r--r--mysql-test/r/date_formats.result157
-rw-r--r--mysql-test/r/derived.result15
-rw-r--r--mysql-test/r/null.result2
-rw-r--r--mysql-test/r/select_found.result2
-rw-r--r--mysql-test/r/sql_mode.result4
-rw-r--r--mysql-test/r/subselect.result2
-rw-r--r--mysql-test/r/type_float.result6
-rw-r--r--mysql-test/r/variables.result34
-rw-r--r--mysql-test/r/warnings.result2
-rw-r--r--mysql-test/t/create.test77
-rw-r--r--mysql-test/t/ctype_mb.test7
-rw-r--r--mysql-test/t/date_formats-master.opt1
-rw-r--r--mysql-test/t/date_formats.test82
-rw-r--r--mysql-test/t/derived.test10
-rw-r--r--mysql-test/t/myisam.test2
-rw-r--r--mysql-test/t/mysqlbinlog.test16
-rw-r--r--mysql-test/t/select_found.test2
-rw-r--r--mysql-test/t/sql_mode.test2
-rw-r--r--mysql-test/t/subselect.test2
-rw-r--r--mysql-test/t/type_float.test9
-rw-r--r--mysql-test/t/variables.test14
-rw-r--r--mysys/my_chsize.c13
-rw-r--r--mysys/queues.c45
-rw-r--r--mysys/thr_alarm.c14
-rwxr-xr-xnetware/BUILD/apply-patch41
-rwxr-xr-xnetware/BUILD/save-patch56
-rw-r--r--scripts/Makefile.am4
-rw-r--r--scripts/fill_help_tables.sh3
-rw-r--r--scripts/make_sharedlib_distribution.sh117
-rw-r--r--scripts/mysql_config.sh2
-rw-r--r--scripts/mysqld_safe.sh22
-rw-r--r--sql-common/client.c4
-rw-r--r--sql/field.cc73
-rw-r--r--sql/field_conv.cc4
-rw-r--r--sql/ha_berkeley.cc3
-rw-r--r--sql/handler.h4
-rw-r--r--sql/item.cc54
-rw-r--r--sql/item.h12
-rw-r--r--sql/item_create.cc5
-rw-r--r--sql/item_create.h1
-rw-r--r--sql/item_func.cc9
-rw-r--r--sql/item_strfunc.cc2
-rw-r--r--sql/item_timefunc.cc1119
-rw-r--r--sql/item_timefunc.h43
-rw-r--r--sql/lex.h2
-rw-r--r--sql/mysql_priv.h43
-rw-r--r--sql/mysqld.cc105
-rw-r--r--sql/opt_ft.cc8
-rw-r--r--sql/opt_ft.h7
-rw-r--r--sql/opt_range.cc103
-rw-r--r--sql/opt_range.h13
-rw-r--r--sql/protocol.cc45
-rw-r--r--sql/set_var.cc129
-rw-r--r--sql/set_var.h52
-rw-r--r--sql/share/czech/errmsg.txt2
-rw-r--r--sql/share/danish/errmsg.txt2
-rw-r--r--sql/share/dutch/errmsg.txt2
-rw-r--r--sql/share/english/errmsg.txt2
-rw-r--r--sql/share/estonian/errmsg.txt2
-rw-r--r--sql/share/french/errmsg.txt2
-rw-r--r--sql/share/german/errmsg.txt2
-rw-r--r--sql/share/greek/errmsg.txt2
-rw-r--r--sql/share/hungarian/errmsg.txt2
-rw-r--r--sql/share/italian/errmsg.txt2
-rw-r--r--sql/share/japanese/errmsg.txt2
-rw-r--r--sql/share/korean/errmsg.txt2
-rw-r--r--sql/share/norwegian-ny/errmsg.txt2
-rw-r--r--sql/share/norwegian/errmsg.txt2
-rw-r--r--sql/share/polish/errmsg.txt2
-rw-r--r--sql/share/portuguese/errmsg.txt2
-rw-r--r--sql/share/romanian/errmsg.txt2
-rw-r--r--sql/share/russian/errmsg.txt2
-rw-r--r--sql/share/serbian/errmsg.txt2
-rw-r--r--sql/share/slovak/errmsg.txt2
-rw-r--r--sql/share/spanish/errmsg.txt2
-rw-r--r--sql/share/swedish/errmsg.txt2
-rw-r--r--sql/share/ukrainian/errmsg.txt2
-rw-r--r--sql/slave.cc7
-rw-r--r--sql/sql_acl.cc4
-rw-r--r--sql/sql_class.cc14
-rw-r--r--sql/sql_class.h17
-rw-r--r--sql/sql_delete.cc2
-rw-r--r--sql/sql_derived.cc2
-rw-r--r--sql/sql_handler.cc15
-rw-r--r--sql/sql_help.cc4
-rw-r--r--sql/sql_insert.cc32
-rw-r--r--sql/sql_lex.cc35
-rw-r--r--sql/sql_lex.h1
-rw-r--r--sql/sql_load.cc4
-rw-r--r--sql/sql_parse.cc2
-rw-r--r--sql/sql_prepare.cc18
-rw-r--r--sql/sql_select.cc26
-rw-r--r--sql/sql_show.cc2
-rw-r--r--sql/sql_table.cc27
-rw-r--r--sql/sql_test.cc31
-rw-r--r--sql/sql_udf.cc2
-rw-r--r--sql/sql_update.cc10
-rw-r--r--sql/sql_yacc.yy13
-rw-r--r--sql/structs.h9
-rw-r--r--sql/table.cc2
-rw-r--r--sql/time.cc328
-rw-r--r--strings/ctype-bin.c16
-rw-r--r--strings/ctype-mb.c22
-rw-r--r--strings/ctype-simple.c14
125 files changed, 2707 insertions, 792 deletions
diff --git a/.bzrignore b/.bzrignore
index 339dc8f33ee..920522c7592 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -515,6 +515,7 @@ scripts/fill_func_tables.sql
scripts/fill_help_tables
scripts/fill_help_tables.sql
scripts/make_binary_distribution
+scripts/make_sharedlib_distribution
scripts/make_win_src_distribution
scripts/msql2mysql
scripts/mysql_config
diff --git a/client/client_priv.h b/client/client_priv.h
index eede1a0a39d..d655619516d 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -26,7 +26,7 @@
/* We have to define 'enum options' identical in all files to keep OS2 happy */
-enum options { OPT_CHARSETS_DIR=256, OPT_DEFAULT_CHARSET,
+enum options_client { OPT_CHARSETS_DIR=256, OPT_DEFAULT_CHARSET,
OPT_PAGER, OPT_NOPAGER, OPT_TEE, OPT_NOTEE,
OPT_LOW_PRIORITY, OPT_AUTO_REPAIR, OPT_COMPRESS,
OPT_DROP, OPT_LOCKS, OPT_KEYWORDS, OPT_DELAYED, OPT_OPTIMIZE,
diff --git a/configure.in b/configure.in
index f098a3d39a8..207404a89c5 100644
--- a/configure.in
+++ b/configure.in
@@ -1821,7 +1821,7 @@ AC_CHECK_FUNCS(alarm bmove \
cuserid fcntl fconvert poll \
getrusage getpwuid getcwd getrlimit getwd index stpcpy locking longjmp \
perror pread realpath readlink rename \
- socket strnlen madvise mkstemp \
+ socket strnlen madvise mallinfo mkstemp \
strtol strtoul strtoll strtoull snprintf tempnam thr_setconcurrency \
gethostbyaddr_r gethostbyname_r getpwnam \
bfill bzero bcmp strstr strpbrk strerror \
diff --git a/include/m_ctype.h b/include/m_ctype.h
index f39cbf8b659..a896afe750a 100644
--- a/include/m_ctype.h
+++ b/include/m_ctype.h
@@ -123,8 +123,8 @@ typedef struct my_collation_handler_st
int (*strcasecmp)(struct charset_info_st *, const char *, const char *);
uint (*instr)(struct charset_info_st *,
- const char *big, uint b_length,
- const char *small, uint s_length,
+ const char *b, uint b_length,
+ const char *s, uint s_length,
my_match_t *match, uint nmatch);
/* Hash calculation */
@@ -257,8 +257,8 @@ extern void my_hash_sort_simple(CHARSET_INFO *cs,
extern uint my_lengthsp_8bit(CHARSET_INFO *cs, const char *ptr, uint length);
extern uint my_instr_simple(struct charset_info_st *,
- const char *big, uint b_length,
- const char *small, uint s_length,
+ const char *b, uint b_length,
+ const char *s, uint s_length,
my_match_t *match, uint nmatch);
@@ -327,8 +327,8 @@ int my_wildcmp_mb(CHARSET_INFO *,
uint my_numchars_mb(CHARSET_INFO *, const char *b, const char *e);
uint my_charpos_mb(CHARSET_INFO *, const char *b, const char *e, uint pos);
uint my_instr_mb(struct charset_info_st *,
- const char *big, uint b_length,
- const char *small, uint s_length,
+ const char *b, uint b_length,
+ const char *s, uint s_length,
my_match_t *match, uint nmatch);
diff --git a/include/my_base.h b/include/my_base.h
index e36f73afe75..5af8a968cd0 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -49,20 +49,24 @@
/* The following is parameter to ha_rkey() how to use key */
-/* We define a complete-field prefix of a key value as a prefix where the
-last included field in the prefix contains the full field, not just some bytes
-from the start of the field. A partial-field prefix is allowed to
-contain only a few first bytes from the last included field.
-
-Below HA_READ_KEY_EXACT, ..., HA_READ_BEFORE_KEY can take a
-complete-field prefix of a key value as the search key. HA_READ_PREFIX
-and HA_READ_PREFIX_LAST could also take a partial-field prefix, but
-currently (4.0.10) they are only used with complete-field prefixes. MySQL uses
-a padding trick to implement LIKE 'abc%' queries.
-
-NOTE that in InnoDB HA_READ_PREFIX_LAST will NOT work with a partial-field
-prefix because InnoDB currently strips spaces from the end of varchar
-fields! */
+/*
+ We define a complete-field prefix of a key value as a prefix where
+ the last included field in the prefix contains the full field, not
+ just some bytes from the start of the field. A partial-field prefix
+ is allowed to contain only a few first bytes from the last included
+ field.
+
+ Below HA_READ_KEY_EXACT, ..., HA_READ_BEFORE_KEY can take a
+ complete-field prefix of a key value as the search
+ key. HA_READ_PREFIX and HA_READ_PREFIX_LAST could also take a
+ partial-field prefix, but currently (4.0.10) they are only used with
+ complete-field prefixes. MySQL uses a padding trick to implement
+ LIKE 'abc%' queries.
+
+ NOTE that in InnoDB HA_READ_PREFIX_LAST will NOT work with a
+ partial-field prefix because InnoDB currently strips spaces from the
+ end of varchar fields!
+*/
enum ha_rkey_function {
HA_READ_KEY_EXACT, /* Find first record else error */
diff --git a/include/mysql.h b/include/mysql.h
index a8ced90f414..f44d515478c 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -66,6 +66,9 @@ typedef int my_socket;
extern unsigned int mysql_port;
extern char *mysql_unix_port;
+#define CLIENT_NET_READ_TIMEOUT 365*24*3600 /* Timeout on read */
+#define CLIENT_NET_WRITE_TIMEOUT 365*24*3600 /* Timeout on write */
+
#ifdef __NETWARE__
#pragma pack(push, 8) /* 8 byte alignment */
#endif
diff --git a/include/mysqld_error.h b/include/mysqld_error.h
index 8a75ccffe8c..34184f5ba97 100644
--- a/include/mysqld_error.h
+++ b/include/mysqld_error.h
@@ -295,5 +295,6 @@
#define ER_BAD_SLAVE_UNTIL_COND 1276
#define ER_MISSING_SKIP_SLAVE 1277
#define ER_UNTIL_COND_IGNORED 1278
-#define ER_BAD_FT_COLUMN 1279
-#define ER_ERROR_MESSAGES 280
+#define ER_WRONG_INDEX_NAME 1279
+#define ER_BAD_FT_COLUMN 1280
+#define ER_ERROR_MESSAGES 281
diff --git a/include/queues.h b/include/queues.h
index 699705d0869..ac15b09719b 100644
--- a/include/queues.h
+++ b/include/queues.h
@@ -49,6 +49,7 @@ int init_queue(QUEUE *queue,uint max_elements,uint offset_to_key,
int reinit_queue(QUEUE *queue,uint max_elements,uint offset_to_key,
pbool max_at_top, queue_compare compare,
void *first_cmp_arg);
+int resize_queue(QUEUE *queue, uint max_elements);
void delete_queue(QUEUE *queue);
void queue_insert(QUEUE *queue,byte *element);
byte *queue_remove(QUEUE *queue,uint idx);
diff --git a/include/sql_state.h b/include/sql_state.h
index c0b7cf97ea5..222636d3bec 100644
--- a/include/sql_state.h
+++ b/include/sql_state.h
@@ -159,3 +159,4 @@ ER_WARN_TOO_MANY_RECORDS, "01000", "",
ER_WARN_NULL_TO_NOTNULL, "01000", "",
ER_WARN_DATA_OUT_OF_RANGE, "01000", "",
ER_WARN_DATA_TRUNCATED, "01000", "",
+ER_WRONG_INDEX_NAME, "42000", "",
diff --git a/include/thr_alarm.h b/include/thr_alarm.h
index 8ff4472f700..0dbb700b4fc 100644
--- a/include/thr_alarm.h
+++ b/include/thr_alarm.h
@@ -60,9 +60,10 @@ typedef my_bool ALARM;
#define thr_end_alarm(A)
#define thr_alarm(A,B,C) ((*(A)=1)-1)
/* The following should maybe be (*(A)) */
-#define thr_got_alarm(A) 0
+#define thr_got_alarm(A) 0
#define init_thr_alarm(A)
#define thr_alarm_kill(A)
+#define resize_thr_alarm(N)
#define end_thr_alarm()
#else
@@ -100,6 +101,7 @@ typedef struct st_alarm {
#define thr_alarm_init(A) (*(A))=0
#define thr_alarm_in_use(A) (*(A)!= 0)
void init_thr_alarm(uint max_alarm);
+void resize_thr_alarm(uint max_alarms);
my_bool thr_alarm(thr_alarm_t *alarmed, uint sec, ALARM *buff);
void thr_alarm_kill(pthread_t thread_id);
void thr_end_alarm(thr_alarm_t *alarmed);
diff --git a/innobase/include/os0thread.h b/innobase/include/os0thread.h
index 491d8866af4..554ca0563e4 100644
--- a/innobase/include/os0thread.h
+++ b/innobase/include/os0thread.h
@@ -15,14 +15,9 @@ Created 9/8/1995 Heikki Tuuri
/* Maximum number of threads which can be created in the program;
this is also the size of the wait slot array for MySQL threads which
can wait inside InnoDB */
-#if defined(__WIN__) || defined(__NETWARE__)
-/* Create less event semaphores because Win 98/ME had difficult creating
-40000 event semaphores */
-/* TODO: these just take a lot of memory on NetWare. should netware move up? */
-#define OS_THREAD_MAX_N 1000
-#else
-#define OS_THREAD_MAX_N 10000
-#endif
+
+#define OS_THREAD_MAX_N srv_max_n_threads
+
/* Possible fixed priorities for threads */
#define OS_THREAD_PRIORITY_NONE 100
diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h
index 094b95e68d3..6e47c468d26 100644
--- a/innobase/include/srv0srv.h
+++ b/innobase/include/srv0srv.h
@@ -87,6 +87,8 @@ extern ulint srv_max_dirty_pages_pct;
extern ulint srv_force_recovery;
extern ulint srv_thread_concurrency;
+extern ulint srv_max_n_threads;
+
extern lint srv_conc_n_threads;
extern ibool srv_fast_shutdown;
diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
index e16073c171c..2f3502f99ad 100644
--- a/innobase/srv/srv0srv.c
+++ b/innobase/srv/srv0srv.c
@@ -180,6 +180,12 @@ the user from forgetting the innodb_force_recovery keyword to my.cnf */
ulint srv_force_recovery = 0;
/*-----------------------*/
+/* We are prepared for a situation that we have this many threads waiting for
+a semaphore inside InnoDB. innobase_start_or_create_for_mysql() sets the
+value. */
+
+ulint srv_max_n_threads = 0;
+
/* The following controls how many threads we let inside InnoDB concurrently:
threads waiting for locks are not counted into the number because otherwise
we could get a deadlock. MySQL creates a thread for each user session, and
@@ -219,7 +225,7 @@ struct srv_conc_slot_struct{
UT_LIST_BASE_NODE_T(srv_conc_slot_t) srv_conc_queue; /* queue of threads
waiting to get in */
-srv_conc_slot_t srv_conc_slots[OS_THREAD_MAX_N]; /* array of wait
+srv_conc_slot_t* srv_conc_slots; /* array of wait
slots */
/* Number of times a thread is allowed to enter InnoDB within the same
@@ -1712,6 +1718,8 @@ srv_init(void)
UT_LIST_INIT(srv_conc_queue);
+ srv_conc_slots = mem_alloc(OS_THREAD_MAX_N * sizeof(srv_conc_slot_t));
+
for (i = 0; i < OS_THREAD_MAX_N; i++) {
conc_slot = srv_conc_slots + i;
conc_slot->reserved = FALSE;
@@ -1758,7 +1766,7 @@ srv_conc_enter_innodb(
thread */
{
ibool has_slept = FALSE;
- srv_conc_slot_t* slot;
+ srv_conc_slot_t* slot = NULL;
ulint i;
char err_buf[1000];
@@ -1835,6 +1843,7 @@ retry:
slot = srv_conc_slots + i;
if (!slot->reserved) {
+
break;
}
}
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index 5de87038bde..83cde6e6589 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -1138,10 +1138,32 @@ innobase_start_or_create_for_mysql(void)
srv_file_flush_method_str);
return(DB_ERROR);
}
-
+
+ /* Set the maximum number of threads which can wait for a semaphore
+ inside InnoDB */
+#if defined(__WIN__) || defined(__NETWARE__)
+
+/* Create less event semaphores because Win 98/ME had difficulty creating
+40000 event semaphores.
+Comment from Novell, Inc.: also, these just take a lot of memory on
+NetWare. */
+ srv_max_n_threads = 1000;
+#else
+ if (srv_pool_size >= 8 * 1024) {
+ /* Here we still have srv_pool_size counted
+ in kilobytes, srv_boot converts the value to
+ pages; if buffer pool is less than 8 MB,
+ assume fewer threads. */
+ srv_max_n_threads = 10000;
+ } else {
+ srv_max_n_threads = 1000; /* saves several MB of memory,
+ especially in 64-bit
+ computers */
+ }
+#endif
/* Note that the call srv_boot() also changes the values of
srv_pool_size etc. to the units used by InnoDB internally */
-
+
err = srv_boot();
if (err != DB_SUCCESS) {
diff --git a/innobase/thr/thr0loc.c b/innobase/thr/thr0loc.c
index fbf3e3a1dad..839cb024f25 100644
--- a/innobase/thr/thr0loc.c
+++ b/innobase/thr/thr0loc.c
@@ -14,6 +14,7 @@ Created 10/5/1995 Heikki Tuuri
#include "sync0sync.h"
#include "hash0hash.h"
#include "mem0mem.h"
+#include "srv0srv.h"
/*
IMPLEMENTATION OF THREAD LOCAL STORAGE
diff --git a/libmysql/client_settings.h b/libmysql/client_settings.h
index b9c47c1dd55..582f9613ee0 100644
--- a/libmysql/client_settings.h
+++ b/libmysql/client_settings.h
@@ -52,9 +52,9 @@ void STDCALL cli_mysql_close(MYSQL *mysql);
MYSQL_FIELD * STDCALL cli_list_fields(MYSQL *mysql);
my_bool STDCALL cli_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt);
-MYSQL_DATA *cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
- uint fields);
+MYSQL_DATA * STDCALL cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
+ uint fields);
int STDCALL cli_stmt_execute(MYSQL_STMT *stmt);
-MYSQL_DATA *cli_read_binary_rows(MYSQL_STMT *stmt);
+MYSQL_DATA * STDCALL cli_read_binary_rows(MYSQL_STMT *stmt);
int STDCALL cli_unbuffered_fetch(MYSQL *mysql, char **row);
const char * STDCALL cli_read_statistic(MYSQL *mysql);
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index 08ea9deb11e..1cad02948e1 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -65,8 +65,8 @@
ulong net_buffer_length=8192;
ulong max_allowed_packet= 1024L*1024L*1024L;
-ulong net_read_timeout= NET_READ_TIMEOUT;
-ulong net_write_timeout= NET_WRITE_TIMEOUT;
+ulong net_read_timeout= CLIENT_NET_READ_TIMEOUT;
+ulong net_write_timeout= CLIENT_NET_WRITE_TIMEOUT;
#ifdef EMBEDDED_LIBRARY
@@ -3098,7 +3098,7 @@ no_data:
Read all rows of data from server (binary format)
*/
-MYSQL_DATA *cli_read_binary_rows(MYSQL_STMT *stmt)
+MYSQL_DATA * STDCALL cli_read_binary_rows(MYSQL_STMT *stmt)
{
ulong pkt_len;
uchar *cp;
diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def
index 1abc924e9c0..787aa645017 100644
--- a/libmysql/libmysql.def
+++ b/libmysql/libmysql.def
@@ -81,7 +81,7 @@ EXPORTS
mysql_param_result
mysql_ping
mysql_prepare
- mysql_prepare_result
+ mysql_get_metadata
mysql_query
mysql_read_query_result
mysql_real_connect
diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c
index b2fdb2ccf3f..76d3205dc01 100644
--- a/myisam/myisamchk.c
+++ b/myisam/myisamchk.c
@@ -146,7 +146,7 @@ int main(int argc, char **argv)
#endif
} /* main */
-enum options {
+enum options_mc {
OPT_CHARSETS_DIR=256, OPT_SET_CHARSET,OPT_START_CHECK_POS,
OPT_CORRECT_CHECKSUM, OPT_KEY_BUFFER_SIZE, OPT_MYISAM_BLOCK_SIZE,
OPT_READ_BUFFER_SIZE, OPT_WRITE_BUFFER_SIZE, OPT_SORT_BUFFER_SIZE,
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result
index 277ae9e0b8d..d61614180b3 100644
--- a/mysql-test/r/create.result
+++ b/mysql-test/r/create.result
@@ -16,6 +16,8 @@ b
drop table t1;
+create table t1 (a int not null auto_increment,primary key (a)) type=heap;
+drop table t1;
create table t2 type=heap select * from t1;
ERROR 42S02: Table 'test.t1' doesn't exist
create table t2 select auto+1 from t1;
@@ -26,10 +28,11 @@ Note 1051 Unknown table 't1'
Note 1051 Unknown table 't2'
create table t1 (b char(0) not null, index(b));
ERROR 42000: The used storage engine can't index column 'b'
-create table t1 (a int not null auto_increment,primary key (a)) type=heap;
create table t1 (a int not null,b text) type=heap;
ERROR 42000: The used table type doesn't support BLOB/TEXT columns
drop table if exists t1;
+Warnings:
+Note 1051 Unknown table 't1'
create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) type=heap;
ERROR 42000: Incorrect table definition; There can only be one auto column and it must be defined as a key
create table not_existing_database.test (a int);
@@ -66,9 +69,8 @@ drop table if exists ``;
ERROR 42000: Incorrect table name ''
create table t1 (`` int);
ERROR 42000: Incorrect column name ''
-drop table if exists t1;
-Warnings:
-Note 1051 Unknown table 't1'
+create table t1 (i int, index `` (i));
+ERROR 42000: Incorrect index name ''
create table t1 (a int auto_increment not null primary key, B CHAR(20));
insert into t1 (b) values ("hello"),("my"),("world");
create table t2 (key (b)) select * from t1;
@@ -220,6 +222,46 @@ ERROR 23000: Column 'k1' cannot be null
insert into t1 values (NULL, NULL);
ERROR 23000: Column 'k1' cannot be null
drop table t1;
+create table t1 select x'4132';
+drop table t1;
+create table t1 select 1,2,3;
+create table if not exists t1 select 1,2;
+create table if not exists t1 select 1,2,3,4;
+ERROR 21S01: Column count doesn't match value count at row 1
+create table if not exists t1 select 1;
+select * from t1;
+1 2 3
+1 2 3
+0 1 2
+0 0 1
+drop table t1;
+create table t1 select 1,2,3;
+create table if not exists t1 select 1,2;
+create table if not exists t1 select 1,2,3,4;
+ERROR 21S01: Column count doesn't match value count at row 1
+create table if not exists t1 select 1;
+select * from t1;
+1 2 3
+1 2 3
+0 1 2
+0 0 1
+drop table t1;
+create table t1 (a int not null, b int, primary key (a));
+insert into t1 values (1,1);
+create table if not exists t1 select 2;
+select * from t1;
+a b
+1 1
+0 2
+create table if not exists t1 select 3 as 'a',4 as 'b';
+create table if not exists t1 select 3 as 'a',3 as 'b';
+ERROR 23000: Duplicate entry '3' for key 1
+select * from t1;
+a b
+1 1
+0 2
+3 4
+drop table t1;
create table t1 (a int, key(a));
create table t2 (b int, foreign key(b) references t1(a), key(b));
drop table if exists t1,t2;
@@ -320,8 +362,6 @@ t1 CREATE TABLE `t1` (
) TYPE=MyISAM CHARSET=latin1
SET SESSION table_type=default;
drop table t1;
-create table t1 select x'4132';
-drop table t1;
create table t1(a int,b int,c int unsigned,d date,e char,f datetime,g time,h blob);
insert into t1(a)values(1);
insert into t1(a,b,c,d,e,f,g,h)
diff --git a/mysql-test/r/ctype_mb.result b/mysql-test/r/ctype_mb.result
index 298e774186d..ce4a4f98b42 100644
--- a/mysql-test/r/ctype_mb.result
+++ b/mysql-test/r/ctype_mb.result
@@ -1,3 +1,4 @@
+drop table if exists t1;
CREATE TABLE t1 SELECT _utf8'test' as c1, _utf8'теÑÑ‚' as c2;
SHOW CREATE TABLE t1;
Table Create Table
@@ -15,6 +16,10 @@ t1 CREATE TABLE `t1` (
`c3` char(4) character set utf8 default NULL
) TYPE=MyISAM CHARSET=latin1
INSERT INTO t1 VALUES ('aaaabbbbccccdddd','aaaabbbbccccdddd','aaaabbbbccccdddd');
+Warnings:
+Warning 1264 Data truncated for column 'c1' at row 1
+Warning 1264 Data truncated for column 'c2' at row 1
+Warning 1264 Data truncated for column 'c3' at row 1
SELECT * FROM t1;
c1 c2 c3
aaaabbbbcccc aaaabbbbcccc aaaabbbbcccc
diff --git a/mysql-test/r/date_formats.result b/mysql-test/r/date_formats.result
new file mode 100644
index 00000000000..590a1d6904b
--- /dev/null
+++ b/mysql-test/r/date_formats.result
@@ -0,0 +1,157 @@
+SHOW GLOBAL VARIABLES LIKE "%_format%";
+Variable_name Value
+date_format %d.%m.%Y
+datetime_format %Y/%d/%m-%H:%i:%s
+default_week_format 0
+time_format %H.%i.%s
+SHOW SESSION VARIABLES LIKE "%_format%";
+Variable_name Value
+date_format %d.%m.%Y
+datetime_format %Y/%d/%m-%H:%i:%s
+default_week_format 0
+time_format %H.%i.%s
+SET date_format="%d.%m.%Y";
+select CAST("01.01.2001" as DATE) as a;
+a
+01.01.2001
+SET datetime_format="%d.%m.%Y %H.%i.%s";
+select CAST("01.01.2001 05.12.06" as DATETIME) as a;
+a
+01.01.2001 05.12.06
+SET time_format="%H.%i.%s";
+select CAST("05.12.06" as TIME) as a;
+a
+05.12.06
+SET datetime_format="%d.%m.%Y %h:%i:%s %p";
+select CAST("01.01.2001 05:12:06AM" as DATETIME) as a;
+a
+01.01.2001 05:12:06 AM
+select CAST("01.01.2001 05:12:06 PM" as DATETIME) as a;
+a
+01.01.2001 05:12:06 PM
+SET time_format="%h:%i:%s %p";
+select CAST("05:12:06 AM" as TIME) as a;
+a
+05:12:06 AM
+select CAST("05:12:06.1234PM" as TIME) as a;
+a
+05:12:06.001234 PM
+SET time_format="%h.%i.%s %p";
+SET date_format='%d.%m.%y';
+SET datetime_format="%d.%m.%y %h.%i.%s %p";
+select CAST("12-12-06" as DATE) as a;
+a
+12.12.06
+select adddate("01.01.97 11.59.59.000001 PM", 10);
+adddate("01.01.97 11.59.59.000001 PM", 10)
+11.01.97 11.59.59.000001 PM
+select datediff("31.12.97 11.59:59.000001 PM","01.01.98");
+datediff("31.12.97 11.59:59.000001 PM","01.01.98")
+-1
+select weekofyear("31.11.97 11:59:59.000001 PM");
+weekofyear("31.11.97 11:59:59.000001 PM")
+49
+select makedate(1997,1);
+makedate(1997,1)
+01.01.97
+select addtime("31.12.97 11.59.59.999999 PM", "1 1.1.1.000002");
+addtime("31.12.97 11.59.59.999999 PM", "1 1.1.1.000002")
+02.01.98 01.01.01.000001 AM
+select maketime(23,11,12);
+maketime(23,11,12)
+11.11.12 PM
+select timediff("01.01.97 11:59:59.000001 PM","31.12.95 11:59:59.000002 PM");
+timediff("01.01.97 11:59:59.000001 PM","31.12.95 11:59:59.000002 PM")
+8795.59.59.999999 PM
+SET time_format="%H%i%s";
+SET time_format="%h%i%s";
+ERROR HY000: Unknown error
+SET date_format='%d.%m.%d';
+ERROR HY000: Unknown error
+SET datetime_format="%d.%m.%y %h.%i.%s";
+ERROR HY000: Unknown error
+SET GLOBAL date_format=default;
+SHOW GLOBAL VARIABLES LIKE "date_format%";
+Variable_name Value
+date_format %d.%m.%Y
+SET GLOBAL time_format=default;
+SHOW GLOBAL VARIABLES LIKE "time_format%";
+Variable_name Value
+time_format %H.%i.%s
+SET GLOBAL datetime_format=default;
+SHOW GLOBAL VARIABLES LIKE "datetime_format%";
+Variable_name Value
+datetime_format %Y/%d/%m-%H:%i:%s
+SET date_format=default;
+SHOW SESSION VARIABLES LIKE "date_format%";
+Variable_name Value
+date_format %d.%m.%Y
+SET time_format=default;
+SHOW SESSION VARIABLES LIKE "time_format%";
+Variable_name Value
+time_format %H.%i.%s
+SET datetime_format=default;
+SHOW SESSION VARIABLES LIKE "datetime_format%";
+Variable_name Value
+datetime_format %Y/%d/%m-%H:%i:%s
+SET time_format='%i:%s:%H';
+select cast(str_to_date("15-01-2001 12:59:59", "%d-%m-%Y %H:%i:%S") as TIME);
+cast(str_to_date("15-01-2001 12:59:59", "%d-%m-%Y %H:%i:%S") as TIME)
+59:59:12
+SET GLOBAL date_format='%Y-%m-%d';
+SET GLOBAL time_format='%H:%i:%s';
+SET GLOBAL datetime_format='%Y-%m-%d %H:%i:%s';
+SET date_format='%Y-%m-%d';
+SET time_format='%H:%i:%s';
+SET datetime_format='%Y-%m-%d %H:%i:%s';
+select str_to_date("15-01-2001 12:59:59", "%d-%m-%Y %H:%i:%S");
+str_to_date("15-01-2001 12:59:59", "%d-%m-%Y %H:%i:%S")
+2001-01-15 12:59:59
+select str_to_date("15 September 2001", "%d %M %Y");
+str_to_date("15 September 2001", "%d %M %Y")
+2001-09-15 00:00:00
+select str_to_date("15 Septembeb 2001", "%d %M %Y");
+str_to_date("15 Septembeb 2001", "%d %M %Y")
+NULL
+select str_to_date("15 MAY 2001", "%d %b %Y");
+str_to_date("15 MAY 2001", "%d %b %Y")
+2001-05-15 00:00:00
+select str_to_date("Sunday 15 MAY 2001", "%W %d %b %Y");
+str_to_date("Sunday 15 MAY 2001", "%W %d %b %Y")
+2001-05-15 00:00:00
+select str_to_date("Sundai 15 MAY 2001", "%W %d %b %Y");
+str_to_date("Sundai 15 MAY 2001", "%W %d %b %Y")
+NULL
+select str_to_date("Sundai 15 MA", "%W %d %b %Y");
+str_to_date("Sundai 15 MA", "%W %d %b %Y")
+NULL
+select str_to_date("Tuesday 52 2001", "%W %V %X");
+str_to_date("Tuesday 52 2001", "%W %V %X")
+NULL
+select str_to_date("Sunday 01 2001", "%W %V %X");
+str_to_date("Sunday 01 2001", "%W %V %X")
+NULL
+select str_to_date("Tuesday 00 2002", "%W %U %Y");
+str_to_date("Tuesday 00 2002", "%W %U %Y")
+2002-01-01 00:00:00
+select str_to_date("Thursday 53 1998", "%W %u %Y");
+str_to_date("Thursday 53 1998", "%W %u %Y")
+1998-12-31 00:00:00
+select str_to_date("15-01-2001", "%d-%m-%Y %H:%i:%S");
+str_to_date("15-01-2001", "%d-%m-%Y %H:%i:%S")
+2001-01-15 00:00:00
+select str_to_date("15-01-20", "%d-%m-%Y");
+str_to_date("15-01-20", "%d-%m-%Y")
+NULL
+select str_to_date("15-2001-1", "%d-%Y-%c");
+str_to_date("15-2001-1", "%d-%Y-%c")
+2001-01-15 00:00:00
+select get_format(DATE, 'USA') as a;
+a
+%m.%d.%Y
+select get_format(TIME, 'internal') as a;
+a
+%H%i%s
+select get_format(DATETIME, 'eur') as a;
+a
+%Y-%m-%d-%H.%i.%s
diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result
index d24ac5e898a..12d8bbaf8ae 100644
--- a/mysql-test/r/derived.result
+++ b/mysql-test/r/derived.result
@@ -215,3 +215,18 @@ ERROR 42000: You have an error in your SQL syntax. Check the manual that corres
insert into (select * from t1) values (5);
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 '(select * from t1) values (5)' at line 1
drop table t1;
+create table t1 (E1 INTEGER UNSIGNED NOT NULL, E2 INTEGER UNSIGNED NOT NULL, E3 INTEGER UNSIGNED NOT NULL, PRIMARY KEY(E1)
+);
+insert into t1 VALUES(1,1,1), (2,2,1);
+select count(*) from t1 INNER JOIN (SELECT A.E1, A.E2, A.E3 FROM t1 AS A WHERE A.E3 = (SELECT MAX(B.E3) FROM t1 AS B WHERE A.E2 = B.E2)) AS THEMAX ON t1.E1 = THEMAX.E2 AND t1.E1 = t1.E2;
+count(*)
+2
+explain select count(*) from t1 INNER JOIN (SELECT A.E1, A.E2, A.E3 FROM t1 AS A WHERE A.E3 = (SELECT MAX(B.E3) FROM t1 AS B WHERE A.E2 = B.E2)) AS THEMAX ON t1.E1 = THEMAX.E2 AND t1.E1 = t1.E2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
+1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 THEMAX.E2 1 Using where
+2 DERIVED t1 ALL NULL NULL NULL NULL 2 Using where
+3 DEPENDENT SUBQUERY B ALL NULL NULL NULL NULL 2 Using where
+Warnings:
+Note 1275 Field or reference 'A.E2' of SELECT #3 was resolved in SELECT #2
+drop table t1;
diff --git a/mysql-test/r/null.result b/mysql-test/r/null.result
index 479a7f049d9..2ef1f0c86f9 100644
--- a/mysql-test/r/null.result
+++ b/mysql-test/r/null.result
@@ -75,6 +75,8 @@ NULL this is null
drop table t1;
CREATE TABLE t1 (a varchar(16) NOT NULL, b smallint(6) NOT NULL, c datetime NOT NULL, d smallint(6) NOT NULL);
INSERT INTO t1 SET a = "", d= "2003-01-14 03:54:55";
+Warnings:
+Warning 1264 Data truncated for column 'd' at row 1
UPDATE t1 SET d=1/NULL;
Warnings:
Warning 1264 Data truncated for column 'd' at row 1
diff --git a/mysql-test/r/select_found.result b/mysql-test/r/select_found.result
index c8991696b5e..d79f45a9334 100644
--- a/mysql-test/r/select_found.result
+++ b/mysql-test/r/select_found.result
@@ -136,7 +136,7 @@ email104
email105
email106
email107
-INSERT INTO `t1` (`id`, `kid`) VALUES ('', '150');
+INSERT INTO `t1` (`id`, `kid`) VALUES ('0', '150');
SELECT SQL_CALC_FOUND_ROWS DISTINCT email FROM t2 LEFT JOIN t1 ON kid = t2.id WHERE t1.id IS NULL LIMIT 10;
email
email1
diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result
index 9b80b965d10..06451b8ac34 100644
--- a/mysql-test/r/sql_mode.result
+++ b/mysql-test/r/sql_mode.result
@@ -71,10 +71,10 @@ t1 CREATE TABLE `t1` (
PRIMARY KEY (`a`),
UNIQUE KEY `email` (`email`)
) TYPE=HEAP ROW_FORMAT=DYNAMIC
-set sql_mode="postgresql,oracle,mssql,db2,sapdb";
+set sql_mode="postgresql,oracle,mssql,db2,maxdb";
select @@sql_mode;
@@sql_mode
-PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,POSTGRESQL,ORACLE,MSSQL,DB2,SAPDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS
+PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS
show create table t1;
Table Create Table
t1 CREATE TABLE "t1" (
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index 6e35b6e78c1..14a132531ca 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -1438,4 +1438,4 @@ explain select * from t3 where a > all (select max(b) from t2 group by a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 4 Using temporary; Using filesort
-drop table if exists t2, t3;
+drop table t2, t3;
diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result
index 987fa9d5685..2a461942853 100644
--- a/mysql-test/r/type_float.result
+++ b/mysql-test/r/type_float.result
@@ -70,6 +70,12 @@ select min(a) from t1;
min(a)
-0.010
drop table t1;
+create table t1 (a float);
+insert into t1 values (1);
+select max(a),min(a),avg(a) from t1;
+max(a) min(a) avg(a)
+1 1 1
+drop table t1;
create table t1 (f float, f2 float(24), f3 float(6,2), d double, d2 float(53), d3 double(10,3), de decimal, de2 decimal(6), de3 decimal(5,2), n numeric, n2 numeric(8), n3 numeric(5,6));
show full columns from t1;
Field Type Collation Null Key Default Extra Privileges Comment
diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result
index ead09cc6ed7..d65b44e7846 100644
--- a/mysql-test/r/variables.result
+++ b/mysql-test/r/variables.result
@@ -163,6 +163,38 @@ set @@rand_seed1=10000000,@@rand_seed2=1000000;
select ROUND(RAND(),5);
ROUND(RAND(),5)
0.02887
+show variables like '%alloc%';
+Variable_name Value
+query_alloc_block_size 8192
+query_prealloc_size 8192
+range_alloc_block_size 2048
+transaction_alloc_block_size 8192
+transaction_prealloc_size 4096
+set @@range_alloc_block_size=1024*16;
+set @@query_alloc_block_size=1024*17+2;
+set @@query_prealloc_size=1024*18;
+set @@transaction_alloc_block_size=1024*20-1;
+set @@transaction_prealloc_size=1024*21-1;
+select @@query_alloc_block_size;
+@@query_alloc_block_size
+17408
+show variables like '%alloc%';
+Variable_name Value
+query_alloc_block_size 17408
+query_prealloc_size 18432
+range_alloc_block_size 16384
+transaction_alloc_block_size 19456
+transaction_prealloc_size 20480
+set @@range_alloc_block_size=default;
+set @@query_alloc_block_size=default, @@query_prealloc_size=default;
+set transaction_alloc_block_size=default, @@transaction_prealloc_size=default;
+show variables like '%alloc%';
+Variable_name Value
+query_alloc_block_size 8192
+query_prealloc_size 8192
+range_alloc_block_size 2048
+transaction_alloc_block_size 8192
+transaction_prealloc_size 4096
set big_tables=OFFF;
ERROR 42000: Variable 'big_tables' can't be set to the value of 'OFFF'
set big_tables="OFFF";
@@ -202,6 +234,8 @@ set myisam_max_sort_file_size=100;
ERROR HY000: Variable 'myisam_max_sort_file_size' is a GLOBAL variable and should be set with SET GLOBAL
set myisam_max_extra_sort_file_size=100;
ERROR HY000: Variable 'myisam_max_extra_sort_file_size' is a GLOBAL variable and should be set with SET GLOBAL
+set @@SQL_WARNINGS=NULL;
+ERROR 42000: Variable 'sql_warnings' can't be set to the value of 'NULL'
set autocommit=1;
set big_tables=1;
select @@autocommit, @@big_tables;
diff --git a/mysql-test/r/warnings.result b/mysql-test/r/warnings.result
index 9d4710ff729..26353785733 100644
--- a/mysql-test/r/warnings.result
+++ b/mysql-test/r/warnings.result
@@ -92,6 +92,8 @@ Warning 1264 Data truncated for column 'b' at row 3
Warning 1262 Data truncated, NULL supplied to NOT NULL column 'a' at row 4
Warning 1264 Data truncated for column 'b' at row 4
insert into t2(b) values('mysqlab');
+Warnings:
+Warning 1264 Data truncated for column 'b' at row 1
set sql_warnings=1;
insert into t2(b) values('mysqlab');
Warnings:
diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test
index d57fd3bb193..059808161a3 100644
--- a/mysql-test/t/create.test
+++ b/mysql-test/t/create.test
@@ -17,25 +17,35 @@ insert into t1 values (""),(null);
select * from t1;
drop table t1;
+create table t1 (a int not null auto_increment,primary key (a)) type=heap;
+drop table t1;
+
#
# Test of some CREATE TABLE'S that should fail
#
-!$1146 create table t2 type=heap select * from t1;
-!$1146 create table t2 select auto+1 from t1;
+--error 1146
+create table t2 type=heap select * from t1;
+--error 1146
+create table t2 select auto+1 from t1;
drop table if exists t1,t2;
-!$1167 create table t1 (b char(0) not null, index(b));
-create table t1 (a int not null auto_increment,primary key (a)) type=heap;
-!$1163 create table t1 (a int not null,b text) type=heap;
+--error 1167
+create table t1 (b char(0) not null, index(b));
+--error 1163
+create table t1 (a int not null,b text) type=heap;
drop table if exists t1;
-!$1075 create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) type=heap;
+--error 1075
+create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) type=heap;
-- error 1044,1
create table not_existing_database.test (a int);
-!$1103 create table `a/a` (a int);
-!$1103 create table `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa int);
-!$1059 create table a (`aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` int);
+--error 1103
+create table `a/a` (a int);
+--error 1103
+create table `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa int);
+--error 1059
+create table a (`aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` int);
#
# test of dummy table names
@@ -62,7 +72,8 @@ create table `` (a int);
drop table if exists ``;
--error 1166
create table t1 (`` int);
-drop table if exists t1;
+--error 1279
+create table t1 (i int, index `` (i));
#
# Test of CREATE ... SELECT with indexes
@@ -167,6 +178,46 @@ insert into t1 values (NULL, NULL);
drop table t1;
#
+# Bug # 801
+#
+
+create table t1 select x'4132';
+drop table t1;
+
+#
+# bug #1434
+#
+
+create table t1 select 1,2,3;
+create table if not exists t1 select 1,2;
+--error 1136
+create table if not exists t1 select 1,2,3,4;
+create table if not exists t1 select 1;
+select * from t1;
+drop table t1;
+create table t1 select 1,2,3;
+create table if not exists t1 select 1,2;
+--error 1136
+create table if not exists t1 select 1,2,3,4;
+create table if not exists t1 select 1;
+select * from t1;
+drop table t1;
+
+#
+# Test create table if not exists with duplicate key error
+#
+
+create table t1 (a int not null, b int, primary key (a));
+insert into t1 values (1,1);
+create table if not exists t1 select 2;
+select * from t1;
+create table if not exists t1 select 3 as 'a',4 as 'b';
+--error 1062
+create table if not exists t1 select 3 as 'a',3 as 'b';
+select * from t1;
+drop table t1;
+
+#
# Test create with foreign keys
#
@@ -230,12 +281,6 @@ SET SESSION table_type=default;
drop table t1;
#
-# Bug # 801
-#
-create table t1 select x'4132';
-drop table t1;
-
-#
# Test types of data for create select with functions
#
diff --git a/mysql-test/t/ctype_mb.test b/mysql-test/t/ctype_mb.test
index 96bb634deb3..b0ccab8e345 100644
--- a/mysql-test/t/ctype_mb.test
+++ b/mysql-test/t/ctype_mb.test
@@ -1,3 +1,10 @@
+#
+# Test of alter table
+#
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
CREATE TABLE t1 SELECT _utf8'test' as c1, _utf8'теÑÑ‚' as c2;
SHOW CREATE TABLE t1;
DELETE FROM t1;
diff --git a/mysql-test/t/date_formats-master.opt b/mysql-test/t/date_formats-master.opt
new file mode 100644
index 00000000000..7977a601dd7
--- /dev/null
+++ b/mysql-test/t/date_formats-master.opt
@@ -0,0 +1 @@
+--date_format=%d.%m.%Y --time_format=%H.%i.%s --datetime_format=%Y/%d/%m-%H:%i:%s
diff --git a/mysql-test/t/date_formats.test b/mysql-test/t/date_formats.test
new file mode 100644
index 00000000000..9551efaa648
--- /dev/null
+++ b/mysql-test/t/date_formats.test
@@ -0,0 +1,82 @@
+SHOW GLOBAL VARIABLES LIKE "%_format%";
+SHOW SESSION VARIABLES LIKE "%_format%";
+
+SET date_format="%d.%m.%Y";
+select CAST("01.01.2001" as DATE) as a;
+SET datetime_format="%d.%m.%Y %H.%i.%s";
+select CAST("01.01.2001 05.12.06" as DATETIME) as a;
+SET time_format="%H.%i.%s";
+select CAST("05.12.06" as TIME) as a;
+
+SET datetime_format="%d.%m.%Y %h:%i:%s %p";
+select CAST("01.01.2001 05:12:06AM" as DATETIME) as a;
+select CAST("01.01.2001 05:12:06 PM" as DATETIME) as a;
+
+SET time_format="%h:%i:%s %p";
+select CAST("05:12:06 AM" as TIME) as a;
+select CAST("05:12:06.1234PM" as TIME) as a;
+
+SET time_format="%h.%i.%s %p";
+SET date_format='%d.%m.%y';
+SET datetime_format="%d.%m.%y %h.%i.%s %p";
+select CAST("12-12-06" as DATE) as a;
+
+select adddate("01.01.97 11.59.59.000001 PM", 10);
+select datediff("31.12.97 11.59:59.000001 PM","01.01.98");
+select weekofyear("31.11.97 11:59:59.000001 PM");
+select makedate(1997,1);
+select addtime("31.12.97 11.59.59.999999 PM", "1 1.1.1.000002");
+select maketime(23,11,12);
+select timediff("01.01.97 11:59:59.000001 PM","31.12.95 11:59:59.000002 PM");
+
+SET time_format="%H%i%s";
+--error 1105
+SET time_format="%h%i%s";
+--error 1105
+SET date_format='%d.%m.%d';
+--error 1105
+SET datetime_format="%d.%m.%y %h.%i.%s";
+
+SET GLOBAL date_format=default;
+SHOW GLOBAL VARIABLES LIKE "date_format%";
+SET GLOBAL time_format=default;
+SHOW GLOBAL VARIABLES LIKE "time_format%";
+SET GLOBAL datetime_format=default;
+SHOW GLOBAL VARIABLES LIKE "datetime_format%";
+
+SET date_format=default;
+SHOW SESSION VARIABLES LIKE "date_format%";
+SET time_format=default;
+SHOW SESSION VARIABLES LIKE "time_format%";
+SET datetime_format=default;
+SHOW SESSION VARIABLES LIKE "datetime_format%";
+
+SET time_format='%i:%s:%H';
+select cast(str_to_date("15-01-2001 12:59:59", "%d-%m-%Y %H:%i:%S") as TIME);
+
+SET GLOBAL date_format='%Y-%m-%d';
+SET GLOBAL time_format='%H:%i:%s';
+SET GLOBAL datetime_format='%Y-%m-%d %H:%i:%s';
+SET date_format='%Y-%m-%d';
+SET time_format='%H:%i:%s';
+SET datetime_format='%Y-%m-%d %H:%i:%s';
+
+select str_to_date("15-01-2001 12:59:59", "%d-%m-%Y %H:%i:%S");
+select str_to_date("15 September 2001", "%d %M %Y");
+select str_to_date("15 Septembeb 2001", "%d %M %Y");
+select str_to_date("15 MAY 2001", "%d %b %Y");
+select str_to_date("Sunday 15 MAY 2001", "%W %d %b %Y");
+select str_to_date("Sundai 15 MAY 2001", "%W %d %b %Y");
+select str_to_date("Sundai 15 MA", "%W %d %b %Y");
+select str_to_date("Tuesday 52 2001", "%W %V %X");
+select str_to_date("Sunday 01 2001", "%W %V %X");
+select str_to_date("Tuesday 00 2002", "%W %U %Y");
+select str_to_date("Thursday 53 1998", "%W %u %Y");
+select str_to_date("15-01-2001", "%d-%m-%Y %H:%i:%S");
+select str_to_date("15-01-20", "%d-%m-%Y");
+select str_to_date("15-2001-1", "%d-%Y-%c");
+
+select get_format(DATE, 'USA') as a;
+select get_format(TIME, 'internal') as a;
+select get_format(DATETIME, 'eur') as a;
+
diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test
index a8583aa5ea3..80b131ac6fe 100644
--- a/mysql-test/t/derived.test
+++ b/mysql-test/t/derived.test
@@ -122,3 +122,13 @@ delete from (select * from t1);
-- error 1064
insert into (select * from t1) values (5);
drop table t1;
+
+#
+# deived tables with subquery inside all by one table
+#
+create table t1 (E1 INTEGER UNSIGNED NOT NULL, E2 INTEGER UNSIGNED NOT NULL, E3 INTEGER UNSIGNED NOT NULL, PRIMARY KEY(E1)
+);
+insert into t1 VALUES(1,1,1), (2,2,1);
+select count(*) from t1 INNER JOIN (SELECT A.E1, A.E2, A.E3 FROM t1 AS A WHERE A.E3 = (SELECT MAX(B.E3) FROM t1 AS B WHERE A.E2 = B.E2)) AS THEMAX ON t1.E1 = THEMAX.E2 AND t1.E1 = t1.E2;
+explain select count(*) from t1 INNER JOIN (SELECT A.E1, A.E2, A.E3 FROM t1 AS A WHERE A.E3 = (SELECT MAX(B.E3) FROM t1 AS B WHERE A.E2 = B.E2)) AS THEMAX ON t1.E1 = THEMAX.E2 AND t1.E1 = t1.E2;
+drop table t1;
diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test
index 8c43ce1937f..5dceb2b4598 100644
--- a/mysql-test/t/myisam.test
+++ b/mysql-test/t/myisam.test
@@ -34,6 +34,7 @@ create table t1 (a tinyint not null auto_increment, b blob not null, primary key
let $1=100;
disable_query_log;
+--disable_warnings
SET SQL_WARNINGS=0;
while ($1)
{
@@ -41,6 +42,7 @@ while ($1)
dec $1;
}
SET SQL_WARNINGS=1;
+--enable_warnings
enable_query_log;
check table t1;
repair table t1;
diff --git a/mysql-test/t/mysqlbinlog.test b/mysql-test/t/mysqlbinlog.test
index 956afb3e7ca..c71ffb21354 100644
--- a/mysql-test/t/mysqlbinlog.test
+++ b/mysql-test/t/mysqlbinlog.test
@@ -39,28 +39,28 @@ select "--- Local --" as "";
#
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
---exec $MYSQL_BINLOG --short-form $MYSQL_TEST_DIR/var/log/master-bin.000001
+--exec $MYSQL_BINLOG --short-form --local-load=$MYSQL_TEST_DIR/var/tmp/ $MYSQL_TEST_DIR/var/log/master-bin.000001
# this should not fail but shouldn't produce any working statements
--disable_query_log
select "--- Broken LOAD DATA --" as "";
--enable_query_log
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
---exec $MYSQL_BINLOG --short-form $MYSQL_TEST_DIR/var/log/master-bin.000002
+--exec $MYSQL_BINLOG --short-form --local-load=$MYSQL_TEST_DIR/var/tmp/ $MYSQL_TEST_DIR/var/log/master-bin.000002
# this should show almost nothing
--disable_query_log
select "--- --database --" as "";
--enable_query_log
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
---exec $MYSQL_BINLOG --short-form --database=nottest $MYSQL_TEST_DIR/var/log/master-bin.000001
+--exec $MYSQL_BINLOG --short-form --local-load=$MYSQL_TEST_DIR/var/tmp/ --database=nottest $MYSQL_TEST_DIR/var/log/master-bin.000001
# this test for position option
--disable_query_log
select "--- --position --" as "";
--enable_query_log
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
---exec $MYSQL_BINLOG --short-form --position=27 $MYSQL_TEST_DIR/var/log/master-bin.000002
+--exec $MYSQL_BINLOG --short-form --local-load=$MYSQL_TEST_DIR/var/tmp/ --position=27 $MYSQL_TEST_DIR/var/log/master-bin.000002
# These are tests for remote binlog.
# They should return the same as previous test.
@@ -76,28 +76,28 @@ select "--- Remote --" as "";
# This is broken now
# By the way it seems that remote version fetches all events with name >= master-bin.000001
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
---exec $MYSQL_BINLOG --short-form --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
+--exec $MYSQL_BINLOG --short-form --local-load=$MYSQL_TEST_DIR/var/tmp/ --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
# This is broken too
--disable_query_log
select "--- Broken LOAD DATA --" as "";
--enable_query_log
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
---exec $MYSQL_BINLOG --short-form --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002
+--exec $MYSQL_BINLOG --short-form --local-load=$MYSQL_TEST_DIR/var/tmp/ --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002
# And this too ! (altough it is documented)
--disable_query_log
select "--- --database --" as "";
--enable_query_log
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
---exec $MYSQL_BINLOG --short-form --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT --database=nottest master-bin.000001
+--exec $MYSQL_BINLOG --short-form --local-load=$MYSQL_TEST_DIR/var/tmp/ --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT --database=nottest master-bin.000001
# Strangely but this works
--disable_query_log
select "--- --position --" as "";
--enable_query_log
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
---exec $MYSQL_BINLOG --short-form --read-from-remote-server --position=27 --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002
+--exec $MYSQL_BINLOG --short-form --local-load=$MYSQL_TEST_DIR/var/tmp/ --read-from-remote-server --position=27 --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002
# clean up
drop table t1;
diff --git a/mysql-test/t/select_found.test b/mysql-test/t/select_found.test
index 06624d50a43..e8be902606c 100644
--- a/mysql-test/t/select_found.test
+++ b/mysql-test/t/select_found.test
@@ -64,7 +64,7 @@ SELECT FOUND_ROWS();
SELECT DISTINCT email FROM t2 LEFT JOIN t1 ON kid = t2.id WHERE t1.id IS NULL LIMIT 10;
SELECT DISTINCT email FROM t2 LEFT JOIN t1 ON kid = t2.id WHERE t1.id IS NULL ORDER BY email LIMIT 10;
-INSERT INTO `t1` (`id`, `kid`) VALUES ('', '150');
+INSERT INTO `t1` (`id`, `kid`) VALUES ('0', '150');
SELECT SQL_CALC_FOUND_ROWS DISTINCT email FROM t2 LEFT JOIN t1 ON kid = t2.id WHERE t1.id IS NULL LIMIT 10;
SELECT FOUND_ROWS();
diff --git a/mysql-test/t/sql_mode.test b/mysql-test/t/sql_mode.test
index d3531f0c440..d96fd030207 100644
--- a/mysql-test/t/sql_mode.test
+++ b/mysql-test/t/sql_mode.test
@@ -24,7 +24,7 @@ show create table t1;
set @@sql_mode="no_field_options,mysql323,mysql40";
show variables like 'sql_mode';
show create table t1;
-set sql_mode="postgresql,oracle,mssql,db2,sapdb";
+set sql_mode="postgresql,oracle,mssql,db2,maxdb";
select @@sql_mode;
show create table t1;
drop table t1;
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 9ba91c7e0a6..8c0b3fb3919 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -964,4 +964,4 @@ explain select * from t3 where a >= all (select b from t2);
insert into t2 values (2,2), (2,1), (3,3), (3,1);
select * from t3 where a > all (select max(b) from t2 group by a);
explain select * from t3 where a > all (select max(b) from t2 group by a);
-drop table if exists t2, t3;
+drop table t2, t3;
diff --git a/mysql-test/t/type_float.test b/mysql-test/t/type_float.test
index f6281ca6c21..caccf31b32a 100644
--- a/mysql-test/t/type_float.test
+++ b/mysql-test/t/type_float.test
@@ -31,6 +31,15 @@ select a from t1 order by a;
select min(a) from t1;
drop table t1;
+# Bug #1022: When a table contains a 'float' field,
+# and one of the functions MAX, MIN, or AVG is used on that field,
+# the system crashes.
+
+create table t1 (a float);
+insert into t1 values (1);
+select max(a),min(a),avg(a) from t1;
+drop table t1;
+
#
# FLOAT/DOUBLE/DECIMAL handling
#
diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test
index 22f8406cba5..396fb3ac722 100644
--- a/mysql-test/t/variables.test
+++ b/mysql-test/t/variables.test
@@ -98,6 +98,18 @@ select @@timestamp>0;
set @@rand_seed1=10000000,@@rand_seed2=1000000;
select ROUND(RAND(),5);
+show variables like '%alloc%';
+set @@range_alloc_block_size=1024*16;
+set @@query_alloc_block_size=1024*17+2;
+set @@query_prealloc_size=1024*18;
+set @@transaction_alloc_block_size=1024*20-1;
+set @@transaction_prealloc_size=1024*21-1;
+select @@query_alloc_block_size;
+show variables like '%alloc%';
+set @@range_alloc_block_size=default;
+set @@query_alloc_block_size=default, @@query_prealloc_size=default;
+set transaction_alloc_block_size=default, @@transaction_prealloc_size=default;
+show variables like '%alloc%';
# The following should give errors
@@ -138,6 +150,8 @@ select @@global.sql_auto_is_null;
set myisam_max_sort_file_size=100;
--error 1229
set myisam_max_extra_sort_file_size=100;
+--error 1231
+set @@SQL_WARNINGS=NULL;
# Test setting all variables
diff --git a/mysys/my_chsize.c b/mysys/my_chsize.c
index 8e46b0808c0..653ea569172 100644
--- a/mysys/my_chsize.c
+++ b/mysys/my_chsize.c
@@ -51,16 +51,17 @@ int my_chsize(File fd, my_off_t newlength, int filler, myf MyFlags)
#if defined(HAVE_SETFILEPOINTER)
/* This is for the moment only true on windows */
{
+ long is_success;
HANDLE win_file= (HANDLE) _get_osfhandle(fd);
long length_low, length_high;
length_low= (long) (ulong) newlength;
length_high= (long) ((ulonglong) newlength >> 32);
- if (SetFilePointer(win_file, length_low, &length_high, FILE_BEGIN))
- {
- if (SetEndOfFile(win_file))
- DBUG_RETURN(0);
- }
- my_errno= errno;
+ is_success= SetFilePointer(win_file, length_low, &length_high, FILE_BEGIN);
+ if (is_success == -1 && (my_errno= GetLastError()) != NO_ERROR)
+ goto err;
+ if (SetEndOfFile(win_file))
+ DBUG_RETURN(0);
+ my_errno= GetLastError();
goto err;
}
#elif defined(HAVE_FTRUNCATE)
diff --git a/mysys/queues.c b/mysys/queues.c
index f077b38ca0b..ecf1058af41 100644
--- a/mysys/queues.c
+++ b/mysys/queues.c
@@ -64,7 +64,7 @@ int init_queue(QUEUE *queue, uint max_elements, uint offset_to_key,
/*
- Reinitialize queue for other usage (deletes all elements)
+ Reinitialize queue for other usage
SYNOPSIS
reinit_queue()
@@ -77,8 +77,8 @@ int init_queue(QUEUE *queue, uint max_elements, uint offset_to_key,
first_cmp_arg First argument to compare function
NOTES
- You can't currently resize the number of elements! If you need this,
- fix it :)
+ This will delete all elements from the queue. If you don't want this,
+ use resize_queue() instead.
RETURN
0 ok
@@ -90,15 +90,46 @@ int reinit_queue(QUEUE *queue, uint max_elements, uint offset_to_key,
void *first_cmp_arg)
{
DBUG_ENTER("reinit_queue");
- if (queue->max_elements < max_elements)
- /* It's real easy to do realloc here, just don't want to bother */
- DBUG_RETURN(my_errno=EE_OUTOFMEMORY);
-
queue->elements=0;
queue->compare=compare;
queue->first_cmp_arg=first_cmp_arg;
queue->offset_to_key=offset_to_key;
queue->max_at_top= max_at_top ? (-1 ^ 1) : 0;
+ resize_queue(queue, max_elements);
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Resize queue
+
+ SYNOPSIS
+ resize_queue()
+ queue Queue
+ max_elements New max size for queue
+
+ NOTES
+ If you resize queue to be less than the elements you have in it,
+ the extra elements will be deleted
+
+ RETURN
+ 0 ok
+ 1 Error. In this case the queue is unchanged
+*/
+
+int resize_queue(QUEUE *queue, uint max_elements)
+{
+ byte **new_root;
+ DBUG_ENTER("resize_queue");
+ if (queue->max_elements == max_elements)
+ DBUG_RETURN(0);
+ if ((new_root= (byte **) my_realloc((void *)queue->root,
+ (max_elements+1)*sizeof(void*),
+ MYF(MY_WME))) == 0)
+ DBUG_RETURN(1);
+ set_if_smaller(queue->elements, max_elements);
+ queue->max_elements= max_elements;
+ queue->root= new_root;
DBUG_RETURN(0);
}
diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c
index 2289f8208bc..36bbac16fef 100644
--- a/mysys/thr_alarm.c
+++ b/mysys/thr_alarm.c
@@ -120,6 +120,20 @@ void init_thr_alarm(uint max_alarms)
DBUG_VOID_RETURN;
}
+
+void resize_thr_alarm(uint max_alarms)
+{
+ pthread_mutex_lock(&LOCK_alarm);
+ /*
+ It's ok not to shrink the queue as there may be more pending alarms than
+ than max_alarms
+ */
+ if (alarm_queue.elements < max_alarms)
+ resize_queue(&alarm_queue,max_alarms+1);
+ pthread_mutex_unlock(&LOCK_alarm);
+}
+
+
/*
Request alarm after sec seconds.
diff --git a/netware/BUILD/apply-patch b/netware/BUILD/apply-patch
new file mode 100755
index 00000000000..3fe5a077f9a
--- /dev/null
+++ b/netware/BUILD/apply-patch
@@ -0,0 +1,41 @@
+#! /bin/sh
+
+# debug
+#set -x
+
+# stop on errors
+set -e
+
+# repository directory
+repo_dir=`pwd`
+
+# show usage
+show_usage()
+{
+ cat << EOF
+
+usage: apply-patch
+
+Imports netware/current-changes.patch so that current changes
+for the platform are present on the local repository.
+
+Use from the root directory of the repository, with BitKeeper
+installed.
+
+EOF
+ exit 0;
+}
+
+if test $1 || test -z $BK_USER
+then
+ show_usage
+fi
+
+echo "starting patch..."
+
+echo "user: $BK_USER"
+
+# import patch
+# Note: In future this should be changed to check whether
+# the repo already has this patch
+bk import -tpatch $repo_dir/netware/current-changes.patch $repo_dir
diff --git a/netware/BUILD/save-patch b/netware/BUILD/save-patch
new file mode 100755
index 00000000000..9f9979ace5b
--- /dev/null
+++ b/netware/BUILD/save-patch
@@ -0,0 +1,56 @@
+#! /bin/sh
+
+# debug
+#set -x
+
+# stop on errors
+set -e
+
+# repository directory
+repo_dir=`pwd`
+
+# show usage
+show_usage()
+{
+ cat << EOF
+
+usage: save-patch
+
+Creates a patch file between the latest revision of the current tree
+and the latest revision not created by \$BK_USER and places it in
+the tree as netware/current-changes.patch
+
+EOF
+ exit 0;
+}
+
+if test $1 || test -z $BK_USER
+then
+ show_usage
+fi
+
+echo "starting patch..."
+
+echo "user: $BK_USER"
+
+# check for bk and repo_dir
+bk help > /dev/null
+repo_dir=`bk root $repo_dir`
+cd $repo_dir
+
+# determine version
+version=`grep -e "AM_INIT_AUTOMAKE(mysql, .*)" < configure.in | sed -e "s/AM_INIT_AUTOMAKE(mysql, \(.*\))/\1/"`
+echo "version: $version"
+
+# user revision
+user_rev=`bk changes -e -n -d':REV:' | head -1`
+echo "latest revision: $user_rev"
+
+# tree revision
+tree_rev=`bk changes -e -n -d':REV:' -U$BK_USER | head -1`
+echo "latest non-$BK_USER revision: $tree_rev"
+
+# create patch
+patch="$repo_dir/netware/current-changes.patch"
+echo "creating \"$patch\"..."
+bk export -tpatch -r$tree_rev..$user_rev -xnetware/current-changes.patch > $patch
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index 4782c763447..48592d2ff00 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -37,6 +37,7 @@ bin_SCRIPTS = @server_scripts@ \
mysql_create_system_tables
EXTRA_SCRIPTS = make_binary_distribution.sh \
+ make_sharedlib_distribution.sh \
make_win_src_distribution.sh \
msql2mysql.sh \
mysql_config.sh \
@@ -69,6 +70,7 @@ dist_pkgdata_DATA = fill_help_tables.sql mysql_fix_privilege_tables.sql
# failures with it.
CLEANFILES = @server_scripts@ \
make_binary_distribution \
+ make_sharedlib_distribution \
msql2mysql \
mysql_config \
mysql_fix_privilege_tables \
@@ -141,7 +143,7 @@ SUFFIXES = .sh
# Don't update the files from bitkeeper
%::SCCS/s.%
-all: fill_help_tables.sql make_win_src_distribution make_binary_distribution
+all: fill_help_tables.sql make_win_src_distribution make_binary_distribution make_sharedlib_distribution
fill_help_tables.sql: fill_help_tables ../Docs/manual.texi
./fill_help_tables < ../Docs/manual.texi > fill_help_tables.sql
diff --git a/scripts/fill_help_tables.sh b/scripts/fill_help_tables.sh
index 8ba05910596..cb5437f7178 100644
--- a/scripts/fill_help_tables.sh
+++ b/scripts/fill_help_tables.sh
@@ -112,6 +112,7 @@ sub add_topic_to_category
$categories{$current_category}->{$topic_name}= $topics{$topic_name};
my $category= $categories{$current_category};
+ $category->{__name__}= $current_category;
if (exists($category->{__parent_category__}))
{
@@ -132,7 +133,7 @@ sub add_topic_to_category
my $old_category= $topics{$topic_name}->{category};
if ($old_category ne $category)
{
- print_error "wrong category for $topic_name\n";
+ print_error "wrong category for $topic_name (first one's \"$old_category->{__name__}\" second one's \"$current_category\")\n";
}
}
diff --git a/scripts/make_sharedlib_distribution.sh b/scripts/make_sharedlib_distribution.sh
new file mode 100644
index 00000000000..4104a315296
--- /dev/null
+++ b/scripts/make_sharedlib_distribution.sh
@@ -0,0 +1,117 @@
+#!/bin/sh
+# The default path should be /usr/local
+
+# Get some info from configure
+# chmod +x ./scripts/setsomevars
+
+machine=@MACHINE_TYPE@
+system=@SYSTEM_TYPE@
+version=@VERSION@
+export machine system version
+SOURCE=`pwd`
+CP="cp -p"
+MV="mv"
+
+STRIP=1
+DEBUG=0
+SILENT=0
+TMP=/tmp
+SUFFIX=""
+
+parse_arguments() {
+ for arg do
+ case "$arg" in
+ --debug) DEBUG=1;;
+ --tmp=*) TMP=`echo "$arg" | sed -e "s;--tmp=;;"` ;;
+ --suffix=*) SUFFIX=`echo "$arg" | sed -e "s;--suffix=;;"` ;;
+ --no-strip) STRIP=0 ;;
+ --silent) SILENT=1 ;;
+ *)
+ echo "Unknown argument '$arg'"
+ exit 1
+ ;;
+ esac
+ done
+}
+
+parse_arguments "$@"
+
+BASE=$TMP/my_dist$SUFFIX
+
+if [ -d $BASE ] ; then
+ rm -r -f $BASE
+fi
+
+mkdir -p $BASE/lib
+
+for i in \
+ libmysql/.libs/libmysqlclient.so* \
+ libmysql_r/.libs/libmysqlclient_r.so*
+do
+ if [ -f $i ]
+ then
+ $CP $i $BASE/lib
+ fi
+done
+
+# Change the distribution to a long descriptive name
+NEW_NAME=mysql-shared-$version-$system-$machine$SUFFIX
+BASE2=$TMP/$NEW_NAME
+rm -r -f $BASE2
+mv $BASE $BASE2
+BASE=$BASE2
+
+#if we are debugging, do not do tar/gz
+if [ x$DEBUG = x1 ] ; then
+ exit
+fi
+
+# This is needed to prefer GNU tar instead of tar because tar can't
+# always handle long filenames
+
+PATH_DIRS=`echo $PATH | sed -e 's/^:/. /' -e 's/:$/ ./' -e 's/::/ . /g' -e 's/:/ /g' `
+which_1 ()
+{
+ for cmd
+ do
+ for d in $PATH_DIRS
+ do
+ for file in $d/$cmd
+ do
+ if test -x $file -a ! -d $file
+ then
+ echo $file
+ exit 0
+ fi
+ done
+ done
+ done
+ exit 1
+}
+
+#
+# Create the result tar file
+#
+
+tar=`which_1 gnutar gtar`
+if test "$?" = "1" -o "$tar" = ""
+then
+ tar=tar
+fi
+
+echo "Using $tar to create archive"
+cd $TMP
+
+OPT=cvf
+if [ x$SILENT = x1 ] ; then
+ OPT=cf
+fi
+
+$tar $OPT $SOURCE/$NEW_NAME.tar $NEW_NAME
+cd $SOURCE
+echo "Compressing archive"
+gzip -9 $NEW_NAME.tar
+echo "Removing temporary directory"
+rm -r -f $BASE
+
+echo "$NEW_NAME.tar.gz created"
diff --git a/scripts/mysql_config.sh b/scripts/mysql_config.sh
index 52284104636..6b543bf4a07 100644
--- a/scripts/mysql_config.sh
+++ b/scripts/mysql_config.sh
@@ -62,7 +62,7 @@ get_full_path ()
{
case $1 in
/*) echo "$1";;
- ./*) tmp=`pwd`/$1; echo $tmp | sed -e 's;/./;/;' ;;
+ ./*) tmp=`pwd`/$1; echo $tmp | sed -e 's;/\./;/;' ;;
*) which $1 ;;
esac
}
diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh
index 1c056e963cb..ece4ba098f4 100644
--- a/scripts/mysqld_safe.sh
+++ b/scripts/mysqld_safe.sh
@@ -51,9 +51,9 @@ parse_arguments() {
;;
# these two might have been set in a [mysqld_safe] section of my.cnf
- # they get passed via environment variables to mysqld_safe
- --socket=*) MYSQL_UNIX_PORT=`echo "$arg" | sed -e "s;--socket=;;"` ;;
- --port=*) MYSQL_TCP_PORT=`echo "$arg" | sed -e "s;--port=;;"` ;;
+ # they are added to mysqld command line to override settings from my.cnf
+ --socket=*) mysql_unix_port=`echo "$arg" | sed -e "s;--socket=;;"` ;;
+ --port=*) mysql_tcp_port=`echo "$arg" | sed -e "s;--port=;;"` ;;
# mysqld_safe-specific options - must be set in my.cnf ([mysqld_safe])!
--ledir=*) ledir=`echo "$arg" | sed -e "s;--ledir=;;"` ;;
@@ -114,8 +114,7 @@ else
ledir=@libexecdir@
fi
-MYSQL_UNIX_PORT=${MYSQL_UNIX_PORT:-@MYSQL_UNIX_ADDR@}
-MYSQL_TCP_PORT=${MYSQL_TCP_PORT:-@MYSQL_TCP_PORT@}
+safe_mysql_unix_port=${mysql_unix_port:-${MYSQL_UNIX_PORT:-@MYSQL_UNIX_ADDR@}}
user=@MYSQLD_USER@
niceness=0
@@ -171,9 +170,14 @@ else
fi
test -z "$err_log" && err_log=$DATADIR/`@HOSTNAME@`.err
-export MYSQL_UNIX_PORT
-export MYSQL_TCP_PORT
-
+if test -n "$mysql_unix_port"
+then
+ args="--socket=$mysql_unix_port $args"
+fi
+if test -n "$mysql_tcp_port"
+then
+ args="--port=$mysql_tcp_port $args"
+fi
if test $niceness -eq 0
then
@@ -296,7 +300,7 @@ echo "Starting $MYSQLD daemon with databases from $DATADIR"
echo "`date +'%y%m%d %H:%M:%S mysqld started'`" >> $err_log
while true
do
- rm -f $MYSQL_UNIX_PORT $pid_file # Some extra safety
+ rm -f $safe_mysql_unix_port $pid_file # Some extra safety
if test -z "$args"
then
$NOHUP_NICENESS $ledir/$MYSQLD $defaults --basedir=$MY_BASEDIR_VERSION --datadir=$DATADIR $USER_OPTION --pid-file=$pid_file @MYSQLD_DEFAULT_SWITCHES@ >> $err_log 2>&1
diff --git a/sql-common/client.c b/sql-common/client.c
index 80a5a719376..15f906f4e34 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -1137,8 +1137,8 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
/* Read all rows (fields or data) from server */
-MYSQL_DATA *cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
- unsigned int fields)
+MYSQL_DATA * STDCALL cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
+ unsigned int fields)
{
uint field;
ulong pkt_len;
diff --git a/sql/field.cc b/sql/field.cc
index bb651835194..98eb0e01f56 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -278,7 +278,8 @@ bool Field::get_date(TIME *ltime,bool fuzzydate)
char buff[40];
String tmp(buff,sizeof(buff),&my_charset_bin),tmp2,*res;
if (!(res=val_str(&tmp,&tmp2)) ||
- str_to_TIME(res->ptr(),res->length(),ltime,fuzzydate) == TIMESTAMP_NONE)
+ str_to_TIME(res->ptr(),res->length(),ltime,fuzzydate,current_thd)<=
+ WRONG_TIMESTAMP_FULL)
return 1;
return 0;
}
@@ -288,7 +289,7 @@ bool Field::get_time(TIME *ltime)
char buff[40];
String tmp(buff,sizeof(buff),&my_charset_bin),tmp2,*res;
if (!(res=val_str(&tmp,&tmp2)) ||
- str_to_time(res->ptr(),res->length(),ltime))
+ str_to_time(res->ptr(),res->length(),ltime,current_thd))
return 1;
return 0;
}
@@ -298,28 +299,29 @@ bool Field::get_time(TIME *ltime)
void Field::store_time(TIME *ltime,timestamp_type type)
{
char buff[25];
+ String tmp((char*) buff,sizeof(buff),&my_charset_bin);
+ DATETIME_FORMAT *tmp_format= 0;
+ bool is_time_only= 0;
+
switch (type) {
case TIMESTAMP_NONE:
+ case WRONG_TIMESTAMP_FULL:
store("",0,&my_charset_bin); // Probably an error
- break;
+ return;
case TIMESTAMP_DATE:
- sprintf(buff,"%04d-%02d-%02d", ltime->year,ltime->month,ltime->day);
- store(buff,10,&my_charset_bin);
+ tmp_format= &t_datetime_frm(current_thd, DATE_FORMAT_TYPE).datetime_format;
break;
case TIMESTAMP_FULL:
- sprintf(buff,"%04d-%02d-%02d %02d:%02d:%02d",
- ltime->year,ltime->month,ltime->day,
- ltime->hour,ltime->minute,ltime->second);
- store(buff,19,&my_charset_bin);
+ tmp_format=&t_datetime_frm(current_thd,DATETIME_FORMAT_TYPE).datetime_format;
break;
case TIMESTAMP_TIME:
- {
- ulong length= my_sprintf(buff, (buff, "%02d:%02d:%02d",
- ltime->hour,ltime->minute,ltime->second));
- store(buff,(uint) length, &my_charset_bin);
+ tmp_format= &t_datetime_frm(current_thd, TIME_FORMAT_TYPE).datetime_format;
+ is_time_only= 1;
break;
}
- }
+ make_datetime(&tmp, ltime, is_time_only, 0,
+ tmp_format->format, tmp_format->format_length, 1);
+ store(tmp.ptr(),tmp.length(),&my_charset_bin);
}
@@ -2690,7 +2692,7 @@ Field_timestamp::Field_timestamp(char *ptr_arg, uint32 len_arg,
int Field_timestamp::store(const char *from,uint len,CHARSET_INFO *cs)
{
- long tmp=(long) str_to_timestamp(from,len);
+ long tmp=(long) str_to_timestamp(from,len,current_thd);
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
{
@@ -3024,7 +3026,7 @@ int Field_time::store(const char *from,uint len,CHARSET_INFO *cs)
TIME ltime;
long tmp;
int error= 0;
- if (str_to_time(from,len,&ltime))
+ if (str_to_time(from,len,&ltime,current_thd))
{
tmp=0L;
error= 1;
@@ -3133,19 +3135,25 @@ longlong Field_time::val_int(void)
String *Field_time::val_str(String *val_buffer,
String *val_ptr __attribute__((unused)))
{
+ TIME ltime;
val_buffer->alloc(16);
long tmp=(long) sint3korr(ptr);
const char *sign="";
+ ltime.neg= 0;
if (tmp < 0)
{
tmp= -tmp;
- sign= "-";
- }
- long length= my_sprintf((char*) val_buffer->ptr(),
- ((char*) val_buffer->ptr(),"%s%02d:%02d:%02d",
- sign,(int) (tmp/10000), (int) (tmp/100 % 100),
- (int) (tmp % 100)));
- val_buffer->length(length);
+ ltime.neg= 1;
+ }
+ DATETIME_FORMAT *tmp_format= (&t_datetime_frm
+ (current_thd, TIME_FORMAT_TYPE).datetime_format);
+ ltime.day= (uint) 0;
+ ltime.hour= (uint) (tmp/10000);
+ ltime.minute= (uint) (tmp/100 % 100);
+ ltime.second= (uint) (tmp % 100);
+ make_datetime(val_buffer, &ltime, 0, 0,
+ tmp_format->format,
+ tmp_format->format_length, 1);
return val_buffer;
}
@@ -3311,7 +3319,7 @@ int Field_date::store(const char *from, uint len,CHARSET_INFO *cs)
TIME l_time;
uint32 tmp;
int error= 0;
- if (str_to_TIME(from,len,&l_time,1) == TIMESTAMP_NONE)
+ if (str_to_TIME(from,len,&l_time,1,current_thd) <= WRONG_TIMESTAMP_FULL)
{
tmp=0;
error= 1;
@@ -3421,6 +3429,7 @@ longlong Field_date::val_int(void)
String *Field_date::val_str(String *val_buffer,
String *val_ptr __attribute__((unused)))
{
+ TIME ltime;
val_buffer->alloc(field_length);
val_buffer->length(field_length);
int32 tmp;
@@ -3430,9 +3439,15 @@ String *Field_date::val_str(String *val_buffer,
else
#endif
longget(tmp,ptr);
- sprintf((char*) val_buffer->ptr(),"%04d-%02d-%02d",
- (int) ((uint32) tmp/10000L % 10000), (int) ((uint32) tmp/100 % 100),
- (int) ((uint32) tmp % 100));
+ DATETIME_FORMAT *tmp_format= (&t_datetime_frm
+ (current_thd, DATE_FORMAT_TYPE).datetime_format);
+ ltime.neg= 0;
+ ltime.year= (int) ((uint32) tmp/10000L % 10000);
+ ltime.month= (int) ((uint32) tmp/100 % 100);
+ ltime.day= (int) ((uint32) tmp % 100);
+ make_datetime(val_buffer, &ltime, 0, 0,
+ tmp_format->format,
+ tmp_format->format_length, 1);
return val_buffer;
}
@@ -3491,7 +3506,7 @@ int Field_newdate::store(const char *from,uint len,CHARSET_INFO *cs)
TIME l_time;
long tmp;
int error= 0;
- if (str_to_TIME(from,len,&l_time,1) == TIMESTAMP_NONE)
+ if (str_to_TIME(from,len,&l_time,1,current_thd) <= WRONG_TIMESTAMP_FULL)
{
tmp=0L;
error= 1;
@@ -3660,7 +3675,7 @@ void Field_newdate::sql_type(String &res) const
int Field_datetime::store(const char *from,uint len,CHARSET_INFO *cs)
{
- longlong tmp=str_to_datetime(from,len,1);
+ longlong tmp=str_to_datetime(from,len,1,current_thd);
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
{
diff --git a/sql/field_conv.cc b/sql/field_conv.cc
index 6510a03f5a6..5f08c91372b 100644
--- a/sql/field_conv.cc
+++ b/sql/field_conv.cc
@@ -119,7 +119,7 @@ set_field_to_null(Field *field)
return 0;
}
field->reset();
- if (current_thd->count_cuted_fields)
+ if (current_thd->count_cuted_fields == CHECK_FIELD_WARN)
{
field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,ER_WARN_DATA_TRUNCATED);
return 0;
@@ -176,7 +176,7 @@ set_field_to_null_with_conversions(Field *field, bool no_conversions)
field->table->auto_increment_field_not_null= false;
return 0; // field is set in handler.cc
}
- if (current_thd->count_cuted_fields)
+ if (current_thd->count_cuted_fields == CHECK_FIELD_WARN)
{
field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,ER_WARN_NULL_TO_NOTNULL);
return 0;
diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc
index bac037dcfc7..3e5dc38e864 100644
--- a/sql/ha_berkeley.cc
+++ b/sql/ha_berkeley.cc
@@ -238,7 +238,8 @@ int berkeley_show_logs(Protocol *protocol)
MEM_ROOT *old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC);
DBUG_ENTER("berkeley_show_logs");
- init_alloc_root(&show_logs_root, 1024, 1024);
+ init_sql_alloc(&show_logs_root, BDB_LOG_ALLOC_BLOCK_SIZE,
+ BDB_LOG_ALLOC_BLOCK_SIZE);
my_pthread_setspecific_ptr(THR_MALLOC,&show_logs_root);
if ((error= db_env->log_archive(db_env, &all_logs,
diff --git a/sql/handler.h b/sql/handler.h
index 5fc63cf30f5..638125e23d0 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -169,10 +169,10 @@ typedef struct st_ha_create_information
SQL_LIST merge_list;
enum db_type db_type;
enum row_type row_type;
- uint options; /* OR of HA_CREATE_ options */
+ uint options; /* OR of HA_CREATE_ options */
uint raid_type,raid_chunks;
uint merge_insert_method;
- bool if_not_exists;
+ bool table_existed; /* 1 in create if table existed */
} HA_CREATE_INFO;
diff --git a/sql/item.cc b/sql/item.cc
index 69082fab4c2..e610453e981 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -46,7 +46,7 @@ Item::Item():
collation.set(default_charset(), DERIVATION_COERCIBLE);
name= 0;
decimals= 0; max_length= 0;
- THD *thd= current_thd;
+ thd= current_thd;
next= thd->free_list; // Put in free list
thd->free_list= this;
/*
@@ -69,7 +69,7 @@ Item::Item():
Used for duplicating lists in processing queries with temporary
tables
*/
-Item::Item(THD *thd, Item &item):
+Item::Item(THD *c_thd, Item &item):
str_value(item.str_value),
name(item.name),
max_length(item.max_length),
@@ -82,7 +82,8 @@ Item::Item(THD *thd, Item &item):
fixed(item.fixed),
collation(item.collation)
{
- next=thd->free_list; // Put in free list
+ next=c_thd->free_list; // Put in free list
+ thd= c_thd;
thd->free_list= this;
}
@@ -174,7 +175,8 @@ bool Item::get_date(TIME *ltime,bool fuzzydate)
char buff[40];
String tmp(buff,sizeof(buff), &my_charset_bin),*res;
if (!(res=val_str(&tmp)) ||
- str_to_TIME(res->ptr(),res->length(),ltime,fuzzydate) == TIMESTAMP_NONE)
+ str_to_TIME(res->ptr(),res->length(),ltime,fuzzydate, thd) <=
+ WRONG_TIMESTAMP_FULL)
{
bzero((char*) ltime,sizeof(*ltime));
return 1;
@@ -192,7 +194,7 @@ bool Item::get_time(TIME *ltime)
char buff[40];
String tmp(buff,sizeof(buff),&my_charset_bin),*res;
if (!(res=val_str(&tmp)) ||
- str_to_time(res->ptr(),res->length(),ltime))
+ str_to_time(res->ptr(),res->length(),ltime, thd))
{
bzero((char*) ltime,sizeof(*ltime));
return 1;
@@ -272,11 +274,13 @@ Item_field::Item_field(Field *f) :Item_ident(NullS,f->table_name,f->field_name)
}
// Constructor need to process subselect with temporary tables (see Item)
-Item_field::Item_field(THD *thd, Item_field &item):
- Item_ident(thd, item),
- field(item.field),
- result_field(item.result_field)
-{ collation.set(DERIVATION_IMPLICIT); }
+Item_field::Item_field(THD *thd, Item_field &item)
+ :Item_ident(thd, item),
+ field(item.field),
+ result_field(item.result_field)
+{
+ collation.set(DERIVATION_IMPLICIT);
+}
void Item_field::set_field(Field *field_par)
{
@@ -673,30 +677,28 @@ String *Item_param::query_val_str(String* str)
}
else
{
- char buff[25];
+ DATETIME_FORMAT *tmp_format= 0;
+ bool is_time_only= 0;
switch (ltime.time_type) {
case TIMESTAMP_NONE:
+ case WRONG_TIMESTAMP_FULL:
break;
case TIMESTAMP_DATE:
- sprintf(buff, "%04d-%02d-%02d",
- ltime.year,ltime.month,ltime.day);
- str->append(buff, 10);
+ tmp_format= &t_datetime_frm(thd, DATE_FORMAT_TYPE).datetime_format;
break;
case TIMESTAMP_FULL:
- sprintf(buff, "%04d-%02d-%02d %02d:%02d:%02d",
- ltime.year,ltime.month,ltime.day,
- ltime.hour,ltime.minute,ltime.second);
- str->append(buff, 19);
+ tmp_format= &t_datetime_frm(thd, DATETIME_FORMAT_TYPE).datetime_format;
break;
case TIMESTAMP_TIME:
{
- sprintf(buff, "%02d:%02d:%02d",
- ltime.hour,ltime.minute,ltime.second);
- str->append(buff, 8);
+ tmp_format= &t_datetime_frm(thd, TIME_FORMAT_TYPE).datetime_format;
+ is_time_only= 1;
break;
- }
+ }
}
+ make_datetime(str, &ltime, is_time_only, 0,
+ tmp_format->format, tmp_format->format_length, 0);
}
str->append("'");
}
@@ -1296,6 +1298,14 @@ bool Item::send(Protocol *protocol, String *buffer)
result= protocol->store_longlong(nr, unsigned_flag);
break;
}
+ case MYSQL_TYPE_FLOAT:
+ {
+ float nr;
+ nr= val();
+ if (!null_value)
+ result= protocol->store(nr, decimals, buffer);
+ break;
+ }
case MYSQL_TYPE_DOUBLE:
{
double nr;
diff --git a/sql/item.h b/sql/item.h
index a126a61e32e..c738f92124f 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -113,6 +113,14 @@ public:
my_bool with_sum_func;
my_bool fixed; /* If item fixed with fix_fields */
DTCollation collation;
+
+
+ /*
+ thd is current_thd value. Like some other Item's fields it
+ will be a problem for using one Item in different threads
+ (as stored procedures may want to do in the future)
+ */
+ THD *thd;
// alloc & destruct is done as start of select using sql_alloc
Item();
@@ -124,7 +132,7 @@ public:
top AND/OR ctructure of WHERE clause to protect it of
optimisation changes in prepared statements
*/
- Item(THD *thd, Item &item);
+ Item(THD *c_thd, Item &item);
virtual ~Item() { name=0; } /*lint -e1509 */
void set_name(const char *str,uint length, CHARSET_INFO *cs);
void init_make_field(Send_field *tmp_field,enum enum_field_types type);
@@ -322,7 +330,7 @@ public:
bool long_data_supplied;
uint pos_in_query;
- Item_param::Item_param(uint position)
+ Item_param(uint position)
{
name= (char*) "?";
pos_in_query= position;
diff --git a/sql/item_create.cc b/sql/item_create.cc
index b1173b9c7b8..fce59d68c1f 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -701,3 +701,8 @@ Item *create_func_maketime(Item* a,Item* b,Item* c)
{
return new Item_func_maketime(a, b, c);
}
+
+Item *create_func_str_to_date(Item* a,Item* b)
+{
+ return new Item_func_str_to_date(a, b);
+}
diff --git a/sql/item_create.h b/sql/item_create.h
index c75f4404bad..5d6cbe1d58f 100644
--- a/sql/item_create.h
+++ b/sql/item_create.h
@@ -149,3 +149,4 @@ 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);
+Item *create_func_str_to_date(Item* a,Item* b);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index dde830b61c9..5a7aada8c1d 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -2200,6 +2200,9 @@ double user_var_entry::val(my_bool *null_value)
return (double) *(longlong*) value;
case STRING_RESULT:
return atof(value); // This is null terminated
+ case ROW_RESULT:
+ DBUG_ASSERT(1); // Impossible
+ break;
}
return 0.0; // Impossible
}
@@ -2219,6 +2222,9 @@ longlong user_var_entry::val_int(my_bool *null_value)
return *(longlong*) value;
case STRING_RESULT:
return strtoull(value,NULL,10); // String is null terminated
+ case ROW_RESULT:
+ DBUG_ASSERT(1); // Impossible
+ break;
}
return LL(0); // Impossible
}
@@ -2242,6 +2248,9 @@ String *user_var_entry::val_str(my_bool *null_value, String *str,
case STRING_RESULT:
if (str->copy(value, length, collation.collation))
str= 0; // EOM error
+ case ROW_RESULT:
+ DBUG_ASSERT(1); // Impossible
+ break;
}
return(str);
}
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 55a20908894..99dd06c566c 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -33,7 +33,9 @@
#include "md5.h"
#include "sha1.h"
#include "my_aes.h"
+C_MODE_START
#include "../mysys/my_static.h" // For soundex_map
+C_MODE_END
String my_empty_string("",default_charset_info);
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 9a36f8a60a6..4009256ee17 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -57,82 +57,544 @@ static String day_names[] =
String("Sunday", &my_charset_latin1)
};
-enum date_time_format_types
+uint check_names(String *arr,int item_count,const char *val_ptr,
+ const char *val_end, uint *val, bool check_part)
{
- TIME_ONLY= 0, TIME_MICROSECOND,
- DATE_ONLY, DATE_TIME, DATE_TIME_MICROSECOND
-};
+ for (int i= 0; i < item_count; i++)
+ {
+ String *tmp=&arr[i];
+ if (!my_strnncoll(&my_charset_latin1,
+ (const uchar *) val_ptr, 3,
+ (const uchar *) tmp->ptr(), 3))
+ {
+ if (check_part)
+ {
+ *val= i+1;
+ return 3;
+ }
-struct date_time_format
-{
- const char* format_str;
- uint length;
-};
+ int part_len= tmp->length() - 3;
+ int val_len= val_end - val_ptr - 3;
+ if (val_len < part_len)
+ return 0;
+ val_ptr+=3;
+ if (!my_strnncoll(&my_charset_latin1,
+ (const uchar *) val_ptr, part_len,
+ (const uchar *) tmp->ptr() + 3, part_len))
+ {
+ *val= i+1;
+ return tmp->length();
+ }
+ return 0;
+ }
+ }
+ return 0;
+}
-static struct date_time_format date_time_formats[]=
+uint check_val_is_digit(const char *ptr, uint val_len, uint digit_count)
{
- {"%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}
-};
+ uint i;
+ uint verify_count= (val_len < digit_count ? val_len : digit_count);
+ uint digit_found= 0;
+ for (i= 0; i < verify_count; i++)
+ {
+ if (!my_isdigit(&my_charset_latin1, *(ptr+i)))
+ break;
+ digit_found++;
+ }
+ return digit_found;
+}
/*
- 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.
+ Extract datetime value to TIME struct from string value
+ according to format string.
*/
-
-String *make_datetime(String *str, TIME *ltime,
- enum date_time_format_types format)
+bool extract_datetime(const char *str_val, uint str_val_len,
+ const char *str_format, uint str_format_len,
+ TIME *l_time)
{
- char *buff;
+ char intbuff[15];
+ int weekday= 0, yearday= 0, daypart= 0, len;
+ int val_len= 0;
+ int week_number= -1;
+ ulong length;
CHARSET_INFO *cs= &my_charset_bin;
- uint length= date_time_formats[format].length + 32;
- const char* format_str= date_time_formats[format].format_str;
+ int err= 0;
+ bool usa_time= 0;
+ bool sunday_first= 0;
+ const char *rT_format= "%H:%i:%s";
+ uint part_len= 0;
+ const char *val_ptr=str_val;
+ const char *val_end= str_val + str_val_len;
+ const char *ptr=str_format;
+ const char *end=ptr+ str_format_len;
+
+ DBUG_ENTER("extract_datetime");
+ for (; ptr != end && val_ptr != val_end; ptr++)
+ {
+ if (*ptr == '%' && ptr+1 != end)
+ {
+ val_len= val_end - val_ptr;
+ char *val_end1= (char *) val_end;
+ switch (*++ptr) {
+ case 'h':
+ case 'I':
+ case 'H':
+ l_time->hour= my_strntoll(cs, val_ptr,
+ 2, 10, &val_end1, &err);
+ if (err || (val_end1 - val_ptr != 2))
+ return 1;
+ usa_time= (*ptr == 'I' || *ptr == 'h');
+ val_ptr+=2;
+ break;
+ case 'k':
+ case 'l':
+ l_time->hour= my_strntoll(cs, val_ptr,
+ 2, 10, &val_end1, &err);
+ if (err)
+ return 1;
+ usa_time= (*ptr == 'l');
+ val_ptr= val_end1;
+ break;
+ case 'e':
+ l_time->day= my_strntoll(cs, val_ptr,
+ 2, 10, &val_end1, &err);
+ if (err)
+ return 1;
+ val_ptr= val_end1;
+ break;
+ case 'c':
+ l_time->month= my_strntoll(cs, val_ptr,
+ 2, 10, &val_end1, &err);
+ if (err)
+ return 1;
+ val_ptr= val_end1;
+ break;
+ case 'Y':
+ l_time->year= my_strntoll(cs, val_ptr,
+ 4, 10, &val_end1, &err);
+ if (err || (val_end1 - val_ptr != 4))
+ return 1;
+ val_ptr+=4;
+ break;
+ case 'y':
+ l_time->year= my_strntoll(cs, val_ptr,
+ 2, 10, &val_end1, &err);
+ if (err || (val_end1 - val_ptr != 2))
+ return 1;
+ l_time->year+= (l_time->year < YY_PART_YEAR ? 2000 : 1900);
+ val_ptr+=2;
+ break;
+ case 'm':
+ l_time->month= my_strntoll(cs, val_ptr,
+ 2, 10, &val_end1, &err);
+ if (err || (val_end1 - val_ptr != 2))
+ return 1;
+ val_ptr+=2;
+ break;
+ case 'd':
+ l_time->day= my_strntoll(cs, val_ptr,
+ 2, 10, &val_end1, &err);
+ if (err || (val_end1 - val_ptr != 2))
+ return 1;
+ val_ptr+=2;
+ break;
+ case 'D':
+ l_time->day= my_strntoll(cs, val_ptr,
+ 2, 10, &val_end1, &err);
+ if (err || (val_len < val_end1 - val_ptr + 2))
+ return 1;
+ val_ptr= val_end1 + 2;
+ break;
+ case 'i':
+ l_time->minute=my_strntoll(cs, val_ptr,
+ 2, 10, &val_end1, &err);
+ if (err || (val_end1 - val_ptr != 2))
+ return 1;
+ val_ptr+=2;
+ break;
+ case 's':
+ case 'S':
+ l_time->second= my_strntoll(cs, val_ptr,
+ 2, 10, &val_end1, &err);
+ if (err || (val_end1 - val_ptr != 2))
+ return 1;
+ val_ptr+=2;
+ break;
+ case 'M':
+ if (val_len < 3 ||
+ !(part_len= check_names(month_names, 12 , val_ptr,
+ val_end, &l_time->month, 0)))
+ return 1;
+ val_ptr+= part_len;
+ break;
+ case 'b':
+ if (val_len < 3 ||
+ !(part_len= check_names(month_names, 12 , val_ptr,
+ val_end,(uint *) &l_time->month, 1)))
+ return 1;
+ val_ptr+= part_len;
+ break;
+ case 'W':
+ if (val_len < 3 ||
+ !(part_len= check_names(day_names, 7 , val_ptr,
+ val_end,(uint *) &weekday, 0)))
+ return 1;
+ val_ptr+= part_len;
+ break;
+ case 'a':
+ if (val_len < 3 ||
+ !(part_len= check_names(day_names, 7 , val_ptr,
+ val_end,(uint *) &weekday, 1)))
+ return 1;
+ val_ptr+= part_len;
+ break;
+ case 'w':
+ weekday= my_strntoll(cs, val_ptr, 1, 10, &val_end1, &err);
+ if (err)
+ return 1;
+ val_ptr++;
+ break;
+ case 'j':
+ yearday= my_strntoll(cs, val_ptr, 3, 10, &val_end1, &err);
+ if (err || (val_end1 - val_ptr != 3))
+ return 1;
+ val_ptr+=3;
+ break;
+ case 'f':
+ l_time->second_part= my_strntoll(cs, val_ptr, 3, 10, &val_end1, &err);
+ if (err)
+ return 1;
+ val_ptr= val_end1;
+ break;
+ case 'p':
+ if (val_len < 2)
+ return 1;
+ if (!my_strnncoll(&my_charset_latin1,
+ (const uchar *) val_ptr, 2,
+ (const uchar *) "PM", 2))
+ {
+ daypart= 12;
+ val_ptr+= 2;
+ }
+ break;
+ case 'U':
+ week_number= my_strntoll(cs, val_ptr, 2, 10, &val_end1, &err);
+ if (err || (val_end1 - val_ptr != 2))
+ return 1;
+ sunday_first= 1;
+ val_ptr+=2;
+ break;
+ case 'u':
+ week_number= my_strntoll(cs, val_ptr, 2, 10, &val_end1, &err);
+ if (err || (val_end1 - val_ptr != 2))
+ return 1;
+ sunday_first=0;
+ val_ptr+=2;
+ break;
+ case 'r':
+ case 'T':
+ usa_time= (*ptr == 'r');
+ if (extract_datetime(val_ptr, val_end-val_ptr,
+ rT_format, strlen(rT_format),
+ l_time))
+ return 1;
+ val_ptr+=8;
+ break;
+ default:
+ if (*val_ptr != *ptr)
+ return 1;
+ val_ptr++;
+ }
+ }
+ else
+ {
+ if (*val_ptr != *ptr)
+ return 1;
+ val_ptr++;
+ }
+ }
+ if (usa_time)
+ {
+ if (l_time->hour > 12 || l_time->hour < 1)
+ return 1;
+ l_time->hour= l_time->hour%12+daypart;
+ }
- if (str->alloc(length))
- return 0;
+ if (yearday > 0)
+ {
+ uint days= calc_daynr(l_time->year,1,1) + yearday - 1;
+ if (days > 0 || days < MAX_DAY_NUMBER)
+ {
+ get_date_from_daynr(days,&l_time->year,&l_time->month,&l_time->day);
+ }
+ }
- 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;
+ if (week_number >= 0 && weekday)
+ {
+ int days= calc_daynr(l_time->year,1,1);
+ uint weekday_b;
+
+ if (weekday > 7 || weekday < 0)
+ return 1;
+ if (sunday_first)
+ weekday = weekday%7;
+
+ if (week_number == 53)
+ {
+ days+= (week_number - 1)*7;
+ weekday_b= calc_weekday(days, sunday_first);
+ weekday = weekday - weekday_b - !sunday_first;
+ days+= weekday;
+ }
+ else if (week_number == 0)
+ {
+ weekday_b= calc_weekday(days, sunday_first);
+ weekday = weekday - weekday_b - !sunday_first;
+ days+= weekday;
+ }
+ else
+ {
+ days+= (week_number - !sunday_first)*7;
+ weekday_b= calc_weekday(days, sunday_first);
+ weekday =weekday - weekday_b - !sunday_first;
+ days+= weekday;
+ }
+ if (days > 0 || days < MAX_DAY_NUMBER)
+ {
+ get_date_from_daynr(days,&l_time->year,&l_time->month,&l_time->day);
+ }
}
- str->length(length);
- str->set_charset(cs);
+ if (l_time->month > 12 || l_time->day > 31 || l_time->hour > 23 ||
+ l_time->minute > 59 || l_time->second > 59)
+ return 1;
+
+ DBUG_RETURN(0);
+}
+
+
+
+/*
+ Print datetime string from TIME struct
+ according to format string.
+*/
+
+
+String *make_datetime(String *str, TIME *l_time,
+ const bool is_time_only,
+ const bool add_second_frac,
+ const char *ptr, uint format_length,
+ bool set_len_to_zero)
+{
+ char intbuff[15];
+ uint days_i;
+ uint hours_i;
+ uint weekday;
+ ulong length;
+ if (set_len_to_zero)
+ str->length(0);
+ if (l_time->neg)
+ str->append("-", 1);
+ const char *end=ptr+format_length;
+ for (; ptr != end ; ptr++)
+ {
+ if (*ptr != '%' || ptr+1 == end)
+ str->append(*ptr);
+ else
+ {
+ switch (*++ptr) {
+ case 'M':
+ if (!l_time->month)
+ return 0;
+ str->append(month_names[l_time->month-1]);
+ break;
+ case 'b':
+ if (!l_time->month)
+ return 0;
+ str->append(month_names[l_time->month-1].ptr(),3);
+ break;
+ case 'W':
+ if (is_time_only)
+ return 0;
+ weekday=calc_weekday(calc_daynr(l_time->year,l_time->month,l_time->day),0);
+ str->append(day_names[weekday]);
+ break;
+ case 'a':
+ if (is_time_only)
+ return 0;
+ weekday=calc_weekday(calc_daynr(l_time->year,l_time->month,l_time->day),0);
+ str->append(day_names[weekday].ptr(),3);
+ break;
+ case 'D':
+ if (is_time_only)
+ return 0;
+ 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
+ {
+ switch (l_time->day %10) {
+ case 1:
+ str->append("st",2);
+ break;
+ case 2:
+ str->append("nd",2);
+ break;
+ case 3:
+ str->append("rd",2);
+ break;
+ default:
+ str->append("th",2);
+ break;
+ }
+ }
+ break;
+ case 'Y':
+ length= int10_to_str(l_time->year, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 4, '0');
+ break;
+ case 'y':
+ length= int10_to_str(l_time->year%100, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
+ break;
+ case 'm':
+ length= int10_to_str(l_time->month, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
+ break;
+ case 'c':
+ length= int10_to_str(l_time->month, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 1, '0');
+ break;
+ case 'd':
+ length= int10_to_str(l_time->day, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
+ break;
+ case 'e':
+ 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':
+ length= int10_to_str(l_time->hour, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
+ break;
+ case 'h':
+ case 'I':
+ days_i= l_time->hour/24;
+ hours_i= (l_time->hour%24 + 11)%12+1 + 24*days_i;
+ length= int10_to_str(hours_i, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
+ break;
+ case 'i': /* minutes */
+ length= int10_to_str(l_time->minute, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
+ break;
+ case 'j':
+ if (is_time_only)
+ return 0;
+ 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':
+ length= int10_to_str(l_time->hour, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 1, '0');
+ break;
+ case 'l':
+ days_i= l_time->hour/24;
+ hours_i= (l_time->hour%24 + 11)%12+1 + 24*days_i;
+ length= int10_to_str(hours_i, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 1, '0');
+ break;
+ case 'p':
+ hours_i= l_time->hour%24;
+ str->append(hours_i < 12 ? "AM" : "PM",2);
+ break;
+ case 'r':
+ 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':
+ length= int10_to_str(l_time->second, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
+ if (add_second_frac)
+ {
+ str->append(".", 1);
+ length= int10_to_str(l_time->second_part, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 6, '0');
+ }
+ break;
+ case 'T':
+ 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;
+ if (is_time_only)
+ return 0;
+ 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;
+ if (is_time_only)
+ return 0;
+ 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':
+ case 'X':
+ {
+ uint year;
+ if (is_time_only)
+ return 0;
+ (void) calc_week(l_time, 1, (*ptr) == 'X', &year);
+ length= int10_to_str(year, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 4, '0');
+ }
+ break;
+ case 'w':
+ if (is_time_only)
+ return 0;
+ weekday=calc_weekday(calc_daynr(l_time->year,l_time->month,l_time->day),1);
+ length= int10_to_str(weekday, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 1, '0');
+ break;
+ default:
+ str->append(*ptr);
+ break;
+ }
+ }
+ }
return str;
}
+
/*
** Get a array of positive numbers from a string object.
** Each number is separated by 1 non digit character
@@ -346,7 +808,7 @@ longlong Item_func_year::val_int()
longlong Item_func_unix_timestamp::val_int()
{
if (arg_count == 0)
- return (longlong) current_thd->query_start();
+ return (longlong) thd->query_start();
if (args[0]->type() == FIELD_ITEM)
{ // Optimize timestamp field
Field *field=((Item_field*) args[0])->field;
@@ -358,7 +820,7 @@ longlong Item_func_unix_timestamp::val_int()
{
return 0; /* purecov: inspected */
}
- return (longlong) str_to_timestamp(str->ptr(),str->length());
+ return (longlong) str_to_timestamp(str->ptr(),str->length(), thd);
}
@@ -522,22 +984,26 @@ static bool get_interval_value(Item *args,interval_type int_type,
String *Item_date::val_str(String *str)
{
+ DATETIME_FORMAT *tmp_format;
+ TIME ltime;
ulong value=(ulong) val_int();
if (null_value)
- return (String*) 0;
- if (!value) // zero daynr
- {
- str->copy("0000-00-00",10,&my_charset_latin1,default_charset());
+ goto null_date;
+
+ ltime.year= (value/10000L) % 10000;
+ ltime.month= (value/100)%100;
+ ltime.day= (value%100);
+ ltime.neg=0;
+ ltime.time_type=TIMESTAMP_DATE;
+
+ tmp_format= &t_datetime_frm(thd, DATE_FORMAT_TYPE).datetime_format;
+ if (make_datetime(str, &ltime, 0, 0,
+ tmp_format->format, tmp_format->format_length, 1))
return str;
- }
-
- char tmpbuff[11];
- sprintf(tmpbuff,"%04d-%02d-%02d",
- (int) (value/10000L) % 10000,
- (int) (value/100)%100,
- (int) (value%100));
- str->copy(tmpbuff,10,&my_charset_latin1,default_charset());
- return str;
+
+ null_value= 1;
+null_date:
+ return 0;
}
@@ -577,7 +1043,7 @@ void Item_func_curdate::fix_length_and_dec()
decimals=0;
max_length=10*default_charset()->mbmaxlen;
- store_now_in_tm(current_thd->query_start(),&start);
+ store_now_in_tm(thd->query_start(),&start);
value=(longlong) ((ulong) ((uint) start.tm_year+1900)*10000L+
((uint) start.tm_mon+1)*100+
@@ -632,22 +1098,27 @@ String *Item_func_curtime::val_str(String *str)
void Item_func_curtime::fix_length_and_dec()
{
struct tm start;
- CHARSET_INFO *cs= default_charset();
+ DATETIME_FORMAT *tmp_format;
+ String tmp((char*) buff,sizeof(buff),default_charset());
+ TIME ltime;
decimals=0;
- max_length=8*cs->mbmaxlen;
- collation.set(cs);
-
- store_now_in_tm(current_thd->query_start(),&start);
-
+ store_now_in_tm(thd->query_start(),&start);
value=(longlong) ((ulong) ((uint) start.tm_hour)*10000L+
(ulong) (((uint) start.tm_min)*100L+
(uint) start.tm_sec));
-
- buff_length=cs->cset->snprintf(cs,buff,sizeof(buff),"%02d:%02d:%02d",
- (int) start.tm_hour,
- (int) start.tm_min,
- (int) start.tm_sec);
+ ltime.day= 0;
+ ltime.hour= start.tm_hour;
+ ltime.minute= start.tm_min;
+ ltime.second= start.tm_sec;
+ ltime.second_part= 0;
+ ltime.neg= 0;
+ ltime.time_type= TIMESTAMP_TIME;
+ tmp_format= &t_datetime_frm(thd, TIME_FORMAT_TYPE).datetime_format;
+ make_datetime(&tmp, &ltime, 0, 0,
+ tmp_format->format, tmp_format->format_length, 1);
+ buff_length= tmp.length();
+ max_length= buff_length;
}
@@ -681,14 +1152,11 @@ String *Item_func_now::val_str(String *str)
void Item_func_now::fix_length_and_dec()
{
struct tm start;
- CHARSET_INFO *cs= &my_charset_bin;
+ DATETIME_FORMAT *tmp_format;
+ String tmp((char*) buff,sizeof(buff),&my_charset_bin);
decimals=0;
- max_length=19*cs->mbmaxlen;
- collation.set(cs);
-
- store_now_in_tm(current_thd->query_start(),&start);
-
+ store_now_in_tm(thd->query_start(),&start);
value=((longlong) ((ulong) ((uint) start.tm_year+1900)*10000L+
(((uint) start.tm_mon+1)*100+
(uint) start.tm_mday))*(longlong) 1000000L+
@@ -696,14 +1164,6 @@ void Item_func_now::fix_length_and_dec()
(ulong) (((uint) start.tm_min)*100L+
(uint) start.tm_sec)));
- buff_length= (uint) cs->cset->snprintf(cs,buff, sizeof(buff),
- "%04d-%02d-%02d %02d:%02d:%02d",
- ((int) (start.tm_year+1900)) % 10000,
- (int) start.tm_mon+1,
- (int) start.tm_mday,
- (int) start.tm_hour,
- (int) start.tm_min,
- (int) start.tm_sec);
/* For getdate */
ltime.year= start.tm_year+1900;
ltime.month= start.tm_mon+1;
@@ -711,9 +1171,15 @@ void Item_func_now::fix_length_and_dec()
ltime.hour= start.tm_hour;
ltime.minute= start.tm_min;
ltime.second= start.tm_sec;
- ltime.second_part=0;
- ltime.neg=0;
- ltime.time_type=TIMESTAMP_FULL;
+ ltime.second_part= 0;
+ ltime.neg= 0;
+ ltime.time_type= TIMESTAMP_FULL;
+
+ tmp_format= &t_datetime_frm(thd, DATETIME_FORMAT_TYPE).datetime_format;
+ make_datetime(&tmp, &ltime, 0, 0,
+ tmp_format->format, tmp_format->format_length, 1);
+ buff_length= tmp.length();
+ max_length= buff_length;
}
bool Item_func_now::get_date(TIME *res,
@@ -754,22 +1220,36 @@ void Item_func_now_utc::store_now_in_tm(time_t now, struct tm *now_tm)
String *Item_func_sec_to_time::val_str(String *str)
{
- char buff[23*2];
- const char *sign="";
longlong seconds=(longlong) args[0]->val_int();
- ulong length;
+ uint sec;
+
+ DATETIME_FORMAT *tmp_format;
+ TIME ltime;
+
if ((null_value=args[0]->null_value))
- return (String*) 0;
+ goto null_date;
+
+ ltime.neg= 0;
if (seconds < 0)
{
seconds= -seconds;
- sign= "-";
+ ltime.neg= 1;
}
- uint sec= (uint) ((ulonglong) seconds % 3600);
- length= my_sprintf(buff,(buff,"%s%02lu:%02u:%02u",sign,(long) (seconds/3600),
- sec/60, sec % 60));
- str->copy(buff, length, &my_charset_latin1, default_charset());
- return str;
+
+ sec= (uint) ((ulonglong) seconds % 3600);
+ ltime.day= 0;
+ ltime.hour= seconds/3600;
+ ltime.minute= sec/60;
+ ltime.second= sec % 60;
+
+ tmp_format= &t_datetime_frm(thd, TIME_FORMAT_TYPE).datetime_format;
+ if (make_datetime(str, &ltime, 0, 0,
+ tmp_format->format, tmp_format->format_length, 1))
+ return str;
+
+ null_value= 1;
+null_date:
+ return (String*) 0;
}
@@ -879,9 +1359,7 @@ String *Item_func_date_format::val_str(String *str)
{
String *format;
TIME l_time;
- char intbuff[15];
uint size,weekday;
- ulong length;
if (!date_or_time)
{
@@ -892,24 +1370,17 @@ String *Item_func_date_format::val_str(String *str)
{
String *res;
if (!(res=args[0]->val_str(str)))
- {
- null_value=1;
- return 0;
- }
- if (str_to_time(res->ptr(),res->length(),&l_time))
- {
- null_value=1;
- return 0;
- }
+ goto null_date;
+
+ if (str_to_time(res->ptr(),res->length(),&l_time, thd))
+ goto null_date;
+
l_time.year=l_time.month=l_time.day=0;
null_value=0;
}
if (!(format = args[1]->val_str(str)) || !format->length())
- {
- null_value=1;
- return 0;
- }
+ goto null_date;
if (fixed_length)
size=max_length;
@@ -918,237 +1389,53 @@ String *Item_func_date_format::val_str(String *str)
if (format == str)
str= &value; // Save result here
if (str->alloc(size))
- {
- null_value=1;
- return 0;
- }
- str->length(0);
+ goto null_date;
+
/* Create the result string */
- const char *ptr=format->ptr();
- const char *end=ptr+format->length();
- for (; ptr != end ; ptr++)
- {
- if (*ptr != '%' || ptr+1 == end)
- str->append(*ptr);
- else
- {
- switch (*++ptr) {
- case 'M':
- if (!l_time.month)
- {
- null_value=1;
- return 0;
- }
- str->append(month_names[l_time.month-1]);
- break;
- case 'b':
- if (!l_time.month)
- {
- null_value=1;
- return 0;
- }
- str->append(month_names[l_time.month-1].ptr(),3);
- break;
- case 'W':
- if (date_or_time)
- {
- null_value=1;
- return 0;
- }
- weekday=calc_weekday(calc_daynr(l_time.year,l_time.month,l_time.day),0);
- str->append(day_names[weekday]);
- break;
- case 'a':
- if (date_or_time)
- {
- null_value=1;
- return 0;
- }
- weekday=calc_weekday(calc_daynr(l_time.year,l_time.month,l_time.day),0);
- str->append(day_names[weekday].ptr(),3);
- break;
- case 'D':
- if (date_or_time)
- {
- null_value=1;
- return 0;
- }
- 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
- {
- switch (l_time.day %10) {
- case 1:
- str->append("st",2);
- break;
- case 2:
- str->append("nd",2);
- break;
- case 3:
- str->append("rd",2);
- break;
- default:
- str->append("th",2);
- break;
- }
- }
- break;
- case 'Y':
- length= int10_to_str(l_time.year, intbuff, 10) - intbuff;
- str->append_with_prefill(intbuff, length, 4, '0');
- break;
- case 'y':
- length= int10_to_str(l_time.year%100, intbuff, 10) - intbuff;
- str->append_with_prefill(intbuff, length, 2, '0');
- break;
- case 'm':
- length= int10_to_str(l_time.month, intbuff, 10) - intbuff;
- str->append_with_prefill(intbuff, length, 2, '0');
- break;
- case 'c':
- length= int10_to_str(l_time.month, intbuff, 10) - intbuff;
- str->append_with_prefill(intbuff, length, 1, '0');
- break;
- case 'd':
- length= int10_to_str(l_time.day, intbuff, 10) - intbuff;
- str->append_with_prefill(intbuff, length, 2, '0');
- break;
- case 'e':
- 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':
- length= int10_to_str(l_time.hour, intbuff, 10) - intbuff;
- str->append_with_prefill(intbuff, length, 2, '0');
- break;
- case 'h':
- case 'I':
- 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 */
- 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)
- {
- null_value=1;
- return 0;
- }
- 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':
- length= int10_to_str(l_time.hour, intbuff, 10) - intbuff;
- str->append_with_prefill(intbuff, length, 1, '0');
- break;
- case 'l':
- 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':
- 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':
- length= int10_to_str(l_time.second, intbuff, 10) - intbuff;
- str->append_with_prefill(intbuff, length, 2, '0');
- break;
- case 'T':
- 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;
- 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;
- 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':
- case 'X':
- {
- uint year;
- (void) calc_week(&l_time, 1, (*ptr) == 'X', &year);
- 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);
- length= int10_to_str(weekday, intbuff, 10) - intbuff;
- str->append_with_prefill(intbuff, length, 1, '0');
+ if (make_datetime(str, &l_time, 0, 0,
+ format->ptr(), format->length(), 1))
+ return str;
- break;
- default:
- str->append(*ptr);
- break;
- }
- }
- }
- return str;
+null_date:
+ null_value=1;
+ return 0;
}
String *Item_func_from_unixtime::val_str(String *str)
{
struct tm tm_tmp,*start;
+ DATETIME_FORMAT *tmp_format;
time_t tmp=(time_t) args[0]->val_int();
uint32 l;
CHARSET_INFO *cs=default_charset();
+ TIME ltime;
if ((null_value=args[0]->null_value))
- return 0;
+ goto null_date;
+
localtime_r(&tmp,&tm_tmp);
start=&tm_tmp;
-
+
+ ltime.year= start->tm_year+1900;
+ ltime.month= start->tm_mon+1;
+ ltime.day= start->tm_mday;
+ ltime.hour= start->tm_hour;
+ ltime.minute= start->tm_min;
+ ltime.second= start->tm_sec;
+ ltime.second_part= 0;
+ ltime.neg=0;
+
l=20*cs->mbmaxlen+32;
- if (str->alloc(l))
- return str; /* purecov: inspected */
- l=cs->cset->snprintf(cs,(char*) str->ptr(),l,"%04d-%02d-%02d %02d:%02d:%02d",
- (int) start->tm_year+1900,
- (int) start->tm_mon+1,
- (int) start->tm_mday,
- (int) start->tm_hour,
- (int) start->tm_min,
- (int) start->tm_sec);
- str->length(l);
- str->set_charset(cs);
- return str;
+ tmp_format= &t_datetime_frm(thd, DATETIME_FORMAT_TYPE).datetime_format;
+ if (str->alloc(l) && make_datetime(str, &ltime, 1, 0,
+ tmp_format->format,
+ tmp_format->format_length, 1))
+ return str;
+ null_value= 1;
+null_date:
+ return 0;
}
@@ -1229,7 +1516,7 @@ bool Item_date_add_interval::get_date(TIME *ltime, bool fuzzy_date)
{
long period,sign;
INTERVAL interval;
-
+ ltime->neg= 0;
if (args[0]->get_date(ltime,0) ||
get_interval_value(args[1],int_type,&value,&interval))
goto null_date;
@@ -1329,19 +1616,17 @@ bool Item_date_add_interval::get_date(TIME *ltime, bool fuzzy_date)
String *Item_date_add_interval::val_str(String *str)
{
TIME ltime;
- enum date_time_format_types format;
+ DATETIME_FORMAT *tmp_format;
if (Item_date_add_interval::get_date(&ltime,0))
return 0;
if (ltime.time_type == TIMESTAMP_DATE)
- format= DATE_ONLY;
- else if (ltime.second_part)
- format= DATE_TIME_MICROSECOND;
- else
- format= DATE_TIME;
-
- if (make_datetime(str, &ltime, format))
+ tmp_format= &t_datetime_frm(thd, DATE_FORMAT_TYPE).datetime_format;
+ else
+ tmp_format= &t_datetime_frm(thd, DATETIME_FORMAT_TYPE).datetime_format;
+ if (make_datetime(str, &ltime, 1, ltime.second_part,
+ tmp_format->format, tmp_format->format_length, 1))
return str;
null_value=1;
@@ -1400,7 +1685,7 @@ longlong Item_extract::val_int()
else
{
String *res= args[0]->val_str(&value);
- if (!res || str_to_time(res->ptr(),res->length(),&ltime))
+ if (!res || str_to_time(res->ptr(),res->length(),&ltime, thd))
{
null_value=1;
return 0;
@@ -1408,7 +1693,6 @@ longlong Item_extract::val_int()
neg= ltime.neg ? -1 : 1;
null_value=0;
}
-
switch (int_type) {
case INTERVAL_YEAR: return ltime.year;
case INTERVAL_YEAR_MONTH: return ltime.year*100L+ltime.month;
@@ -1530,10 +1814,12 @@ void Item_char_typecast::fix_length_and_dec()
String *Item_datetime_typecast::val_str(String *str)
{
TIME ltime;
+ DATETIME_FORMAT *tmp_format= (&t_datetime_frm
+ (thd, DATETIME_FORMAT_TYPE).datetime_format);
if (!get_arg0_date(&ltime,1) &&
- make_datetime(str, &ltime, ltime.second_part ?
- DATE_TIME_MICROSECOND : DATE_TIME))
+ make_datetime(str, &ltime, 1, ltime.second_part,
+ tmp_format->format, tmp_format->format_length, 1))
return str;
null_date:
@@ -1553,9 +1839,12 @@ bool Item_time_typecast::get_time(TIME *ltime)
String *Item_time_typecast::val_str(String *str)
{
TIME ltime;
+ DATETIME_FORMAT *tmp_format= (&t_datetime_frm
+ (thd, TIME_FORMAT_TYPE).datetime_format);
if (!get_arg0_time(&ltime) &&
- make_datetime(str, &ltime, ltime.second_part ? TIME_MICROSECOND : TIME_ONLY))
+ make_datetime(str, &ltime, 0, ltime.second_part,
+ tmp_format->format, tmp_format->format_length, 1))
return str;
null_value=1;
@@ -1574,9 +1863,12 @@ bool Item_date_typecast::get_date(TIME *ltime, bool fuzzy_date)
String *Item_date_typecast::val_str(String *str)
{
TIME ltime;
+ DATETIME_FORMAT *tmp_format= (&t_datetime_frm
+ (thd, DATE_FORMAT_TYPE).datetime_format);
if (!get_arg0_date(&ltime,1) &&
- make_datetime(str, &ltime, DATE_ONLY))
+ make_datetime(str, &ltime, 1, 0,
+ tmp_format->format, tmp_format->format_length, 1))
return str;
null_date:
@@ -1605,7 +1897,11 @@ String *Item_func_makedate::val_str(String *str)
{
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))
+
+ DATETIME_FORMAT *tmp_format= (&t_datetime_frm
+ (thd, DATE_FORMAT_TYPE).datetime_format);
+ if (make_datetime(str, &l_time, 1, 0,
+ tmp_format->format, tmp_format->format_length, 1))
return str;
}
@@ -1656,6 +1952,7 @@ String *Item_func_add_time::val_str(String *str)
bool is_time= 0;
long microseconds, seconds, days= 0;
int l_sign= sign;
+ DATETIME_FORMAT *tmp_format;
null_value=0;
l_time3.neg= 0;
@@ -1720,19 +2017,21 @@ String *Item_func_add_time::val_str(String *str)
calc_time_from_sec(&l_time3, seconds, microseconds);
if (!is_time)
{
+ tmp_format= &t_datetime_frm(thd, DATETIME_FORMAT_TYPE).datetime_format;
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))
+ make_datetime(str, &l_time3, 1,
+ l_time1.second_part || l_time2.second_part,
+ tmp_format->format, tmp_format->format_length, 1))
return str;
goto null_date;
}
-
+
+ tmp_format= &t_datetime_frm(thd, TIME_FORMAT_TYPE).datetime_format;
l_time3.hour+= days*24;
- if (make_datetime(str, &l_time3,
- l_time1.second_part || l_time2.second_part ?
- TIME_MICROSECOND : TIME_ONLY))
+ if (make_datetime(str, &l_time3, 0,
+ l_time1.second_part || l_time2.second_part,
+ tmp_format->format, tmp_format->format_length, 1))
return str;
null_date:
@@ -1755,6 +2054,7 @@ String *Item_func_timediff::val_str(String *str)
long days;
int l_sign= 1;
TIME l_time1 ,l_time2, l_time3;
+ DATETIME_FORMAT *tmp_format;
null_value= 0;
if (args[0]->get_time(&l_time1) ||
@@ -1800,9 +2100,11 @@ String *Item_func_timediff::val_str(String *str)
l_time3.neg= l_time3.neg ? 0 : 1;
calc_time_from_sec(&l_time3, seconds, microseconds);
- if (make_datetime(str, &l_time3,
- l_time1.second_part || l_time2.second_part ?
- TIME_MICROSECOND : TIME_ONLY))
+
+ tmp_format= &t_datetime_frm(thd, TIME_FORMAT_TYPE).datetime_format;
+ if (make_datetime(str, &l_time3, 0,
+ l_time1.second_part || l_time2.second_part,
+ tmp_format->format, tmp_format->format_length, 1))
return str;
null_date:
@@ -1819,6 +2121,7 @@ null_date:
String *Item_func_maketime::val_str(String *str)
{
TIME ltime;
+ DATETIME_FORMAT *tmp_format;
long hour= args[0]->val_int();
long minute= args[1]->val_int();
@@ -1840,7 +2143,9 @@ String *Item_func_maketime::val_str(String *str)
ltime.hour= (ulong)hour;
ltime.minute= (ulong)minute;
ltime.second= (ulong)second;
- if (make_datetime(str, &ltime, TIME_ONLY))
+ tmp_format= &t_datetime_frm(thd, TIME_FORMAT_TYPE).datetime_format;
+ if (make_datetime(str, &ltime, 0, 0,
+ tmp_format->format, tmp_format->format_length, 1))
return str;
null_date:
@@ -1860,3 +2165,79 @@ longlong Item_func_microsecond::val_int()
return ltime.second_part;
return 0;
}
+
+/*
+ Array of MySQL date/time/datetime formats
+ Firts element is date format
+ Second element is time format
+ Third element is datetime format
+ Fourth is format name.
+*/
+
+const char *datetime_formats[4][5]=
+{
+ {"%m.%d.%Y", "%Y-%m-%d", "%Y-%m-%d", "%d.%m.%Y", "%Y%m%d"},
+ {"%h:%i:%s %p", "%H:%i:%s", "%H:%i:%s", "%H.%i.%S", "%H%i%s"},
+ {"%Y-%m-%d-%H.%i.%s", "%Y-%m-%d %H:%i:%s", "%Y-%m-%d %H:%i:%s", "%Y-%m-%d-%H.%i.%s", "%Y%m%d%H%i%s"},
+ {"USA", "JIS", "ISO", "EUR", "INTERNAL"}
+};
+
+
+/*
+ Return format string according format name.
+ If name is unknown, result is ISO format string
+*/
+
+String *Item_func_get_format::val_str(String *str)
+{
+ String *val=args[0]->val_str(str);
+ const char *format_str= datetime_formats[tm_format][ISO_FORMAT];
+
+ if (!args[0]->null_value)
+ {
+ const char *val_ptr= val->ptr();
+ uint val_len= val->length();
+ for (int i= 0; i < 5; i++)
+ {
+ const char *name_format_str= datetime_formats[3][i];
+ uint format_str_len= strlen(name_format_str);
+ if ( val_len == format_str_len &&
+ !my_strnncoll(&my_charset_latin1,
+ (const uchar *) val_ptr, val_len,
+ (const uchar *) name_format_str, format_str_len))
+ {
+ format_str= datetime_formats[tm_format][i];
+ break;
+ }
+ }
+ }
+
+ null_value= 0;
+ str->length(0);
+ str->append(format_str);
+ return str;
+}
+
+
+String *Item_func_str_to_date::val_str(String *str)
+{
+ TIME ltime;
+ bzero((char*) &ltime, sizeof(ltime));
+ DATETIME_FORMAT *tmp_format;
+ String *val=args[0]->val_str(str);
+ String *format=args[1]->val_str(str);
+ if (args[0]->null_value || args[1]->null_value ||
+ extract_datetime(val->ptr(), val->length(),
+ format->ptr(), val->length(),
+ &ltime))
+ goto null_date;
+
+ tmp_format= &t_datetime_frm(thd, DATETIME_FORMAT_TYPE).datetime_format;
+ if (make_datetime(str, &ltime, 0, 0, tmp_format->format,
+ tmp_format->format_length, 1))
+ return str;
+
+null_date:
+ null_value=1;
+ return 0;
+}
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index 6dcf7d00ce1..b7bf294b83d 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -763,3 +763,46 @@ public:
maybe_null=1;
}
};
+
+
+enum datetime_format
+{
+ USA_FORMAT, JIS_FORMAT, ISO_FORMAT, EUR_FORMAT, INTERNAL_FORMAT
+};
+
+
+enum datetime_format_types
+{
+ DATE_FORMAT_TYPE= 0, TIME_FORMAT_TYPE, DATETIME_FORMAT_TYPE
+};
+
+
+class Item_func_get_format :public Item_str_func
+{
+ const datetime_format_types tm_format;
+public:
+ Item_func_get_format(datetime_format_types type_arg1, Item *a)
+ :Item_str_func(a), tm_format(type_arg1) {}
+ String *val_str(String *str);
+ const char *func_name() const { return "get_format"; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=17*MY_CHARSET_BIN_MB_MAXLEN;
+ }
+};
+
+
+class Item_func_str_to_date :public Item_str_func
+{
+public:
+ Item_func_str_to_date(Item *a, Item *b)
+ :Item_str_func(a, b) {}
+ String *val_str(String *str);
+ const char *func_name() const { return "str_to_date"; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=29*MY_CHARSET_BIN_MB_MAXLEN;
+ }
+};
diff --git a/sql/lex.h b/sql/lex.h
index f8bb34c5c5b..5d79e378d4f 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -177,6 +177,7 @@ static SYMBOL symbols[] = {
{ "FUNCTION", SYM(UDF_SYM),0,0},
{ "GEOMETRY", SYM(GEOMETRY_SYM),0,0},
{ "GEOMETRYCOLLECTION",SYM(GEOMETRYCOLLECTION),0,0},
+ { "GET_FORMAT", SYM(GET_FORMAT),0,0},
{ "GLOBAL", SYM(GLOBAL_SYM),0,0},
{ "GRANT", SYM(GRANT),0,0},
{ "GRANTS", SYM(GRANTS),0,0},
@@ -640,6 +641,7 @@ static SYMBOL sql_functions[] = {
{ "STARTPOINT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_startpoint)},
{ "STD", SYM(STD_SYM),0,0},
{ "STDDEV", SYM(STD_SYM),0,0},
+ { "STR_TO_DATE", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_str_to_date)},
{ "STRCMP", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_strcmp)},
{ "SUBSTR", SYM(SUBSTRING),0,0},
{ "SUBSTRING", SYM(SUBSTRING),0,0},
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 72e9bbf5bb7..dd5c4837663 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -190,6 +190,19 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
#define MYSQLD_NET_RETRY_COUNT 10 // Abort read after this many int.
#endif
#define TEMP_POOL_SIZE 128
+
+#define QUERY_ALLOC_BLOCK_SIZE 8192
+#define QUERY_ALLOC_PREALLOC_SIZE 8192
+#define TRANS_ALLOC_BLOCK_SIZE 4096
+#define TRANS_ALLOC_PREALLOC_SIZE 4096
+#define RANGE_ALLOC_BLOCK_SIZE 2048
+#define ACL_ALLOC_BLOCK_SIZE 1024
+#define UDF_ALLOC_BLOCK_SIZE 1024
+#define TABLE_ALLOC_BLOCK_SIZE 1024
+#define BDB_LOG_ALLOC_BLOCK_SIZE 1024
+#define WARN_ALLOC_BLOCK_SIZE 2048
+#define WARN_ALLOC_PREALLOC_SIZE 1024
+
/*
The following parameters is to decide when to use an extra cache to
optimise seeks when reading a big table in sorted order
@@ -319,7 +332,7 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
#define MODE_ORACLE 512
#define MODE_MSSQL 1024
#define MODE_DB2 2048
-#define MODE_SAPDB 4096
+#define MODE_MAXDB 4096
#define MODE_NO_KEY_OPTIONS 8192
#define MODE_NO_TABLE_OPTIONS 16384
#define MODE_NO_FIELD_OPTIONS 32768
@@ -914,7 +927,7 @@ extern pthread_mutex_t LOCK_mysql_create_db,LOCK_Acl,LOCK_open,
LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone,
LOCK_slave_list, LOCK_active_mi, LOCK_manager,
LOCK_global_system_variables, LOCK_user_conn;
-extern rw_lock_t LOCK_grant;
+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;
@@ -931,6 +944,14 @@ extern SHOW_COMP_OPTION have_berkeley_db;
extern struct system_variables global_system_variables;
extern struct system_variables max_system_variables;
extern struct rand_struct sql_rand;
+
+#define g_datetime_frm(a) (global_system_variables.datetime_formats[(a)])
+#define t_datetime_frm(a, b) ((a)->variables.datetime_formats[(b)])
+
+extern const char *datetime_formats[4][5];
+extern const char *opt_datetime_format_names[3];
+extern const char *opt_datetime_formats[3];
+
extern String null_string;
extern HASH open_cache;
extern TABLE *unused_tables;
@@ -1001,14 +1022,24 @@ void get_date_from_daynr(long daynr,uint *year, uint *month,
uint *day);
void init_time(void);
long my_gmt_sec(TIME *, long *current_timezone);
-time_t str_to_timestamp(const char *str,uint length);
-bool str_to_time(const char *str,uint length,TIME *l_time);
-longlong str_to_datetime(const char *str,uint length,bool fuzzy_date);
+time_t str_to_timestamp(const char *str,uint length, THD *thd);
+bool str_to_time(const char *str,uint length,TIME *l_time, THD *thd);
+longlong str_to_datetime(const char *str,uint length,bool fuzzy_date, THD *thd);
timestamp_type str_to_TIME(const char *str, uint length, TIME *l_time,
- bool fuzzy_date);
+ bool fuzzy_date, THD *thd);
void localtime_to_TIME(TIME *to, struct tm *from);
void calc_time_from_sec(TIME *to, long seconds, long microseconds);
+extern DATETIME_FORMAT *make_format(DATETIME_FORMAT *datetime_format,
+ datetime_format_types format_type,
+ const char *format_str,
+ uint format_length, bool is_alloc);
+extern String *make_datetime(String *str, TIME *l_time,
+ const bool is_time_only,
+ const bool add_second_frac,
+ const char *ptr, uint format_length,
+ bool set_len_to_zero);
+
int test_if_number(char *str,int *res,bool allow_wildcards);
void change_byte(byte *,uint,char,char);
extern "C" void unireg_abort(int exit_code);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 1bfb8e8cbf1..6cd61536944 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -217,7 +217,7 @@ const char *sql_mode_names[] =
"REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE",
"?", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION",
"NO_DIR_IN_CREATE",
- "POSTGRESQL", "ORACLE", "MSSQL", "DB2", "SAPDB", "NO_KEY_OPTIONS",
+ "POSTGRESQL", "ORACLE", "MSSQL", "DB2", "MAXDB", "NO_KEY_OPTIONS",
"NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", "ANSI",
"NO_AUTO_VALUE_ON_ZERO", NullS
};
@@ -319,6 +319,12 @@ char* log_error_file_ptr= log_error_file;
char mysql_real_data_home[FN_REFLEN],
language[LIBLEN],reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN],
max_sort_char,*mysqld_user,*mysqld_chroot, *opt_init_file;
+
+const char *opt_datetime_formats[3];
+const char *opt_datetime_format_names[3]= {"date_format",
+ "time_format",
+ "datetime_format"};
+
char *language_ptr, *default_collation_name, *default_character_set_name;
char mysql_data_home_buff[2], *mysql_data_home=mysql_real_data_home;
char server_version[SERVER_VERSION_LENGTH]=MYSQL_SERVER_VERSION;
@@ -906,6 +912,9 @@ void clean_up(bool print_message)
#ifdef USE_RAID
end_raid();
#endif
+ g_datetime_frm(DATE_FORMAT_TYPE).clean();
+ g_datetime_frm(TIME_FORMAT_TYPE).clean();
+ g_datetime_frm(DATETIME_FORMAT_TYPE).clean();
if (defaults_argv)
free_defaults(defaults_argv);
free_tmpdir(&mysql_tmpdir_list);
@@ -1998,6 +2007,36 @@ bool open_log(MYSQL_LOG *log, const char *hostname,
}
+int init_global_datetime_format(datetime_format_types format_type, bool is_alloc)
+{
+ const char *format_str= opt_datetime_formats[format_type];
+ uint format_length= 0;
+ DATETIME_FORMAT *tmp_format= &g_datetime_frm(format_type).datetime_format;
+
+ if (format_str)
+ {
+ format_str= opt_datetime_formats[format_type];
+ format_length= strlen(format_str);
+ }
+ else
+ {
+ format_str= datetime_formats[format_type][ISO_FORMAT];
+ format_length= strlen(datetime_formats[format_type][ISO_FORMAT]);
+ opt_datetime_formats[format_type]= format_str;
+ }
+ if (make_format(tmp_format, format_type, format_str,
+ format_length, is_alloc))
+ {
+ g_datetime_frm(format_type).name= opt_datetime_format_names[format_type];
+ g_datetime_frm(format_type).name_length=
+ strlen(opt_datetime_format_names[format_type]);
+ g_datetime_frm(format_type).format_type= format_type;
+ return 0;
+ }
+ return 1;
+}
+
+
static int init_common_variables(const char *conf_file_name, int argc,
char **argv, const char **groups)
{
@@ -2113,6 +2152,12 @@ static int init_common_variables(const char *conf_file_name, int argc,
global_system_variables.collation_connection= default_charset_info;
global_system_variables.character_set_results= default_charset_info;
global_system_variables.character_set_client= default_charset_info;
+ global_system_variables.collation_connection= default_charset_info;
+
+ if (init_global_datetime_format(DATE_FORMAT_TYPE, 1) ||
+ init_global_datetime_format(TIME_FORMAT_TYPE, 1) ||
+ init_global_datetime_format(DATETIME_FORMAT_TYPE, 1))
+ return 1;
if (use_temp_pool && bitmap_init(&temp_pool,0,1024,1))
return 1;
@@ -3453,10 +3498,10 @@ error:
Handle start options
******************************************************************************/
-enum options
+enum options_mysqld
{
- OPT_ISAM_LOG=256, OPT_SKIP_NEW,
- OPT_SKIP_GRANT, OPT_SKIP_LOCK,
+ OPT_ISAM_LOG=256, OPT_SKIP_NEW,
+ OPT_SKIP_GRANT, OPT_SKIP_LOCK,
OPT_ENABLE_LOCK, OPT_USE_LOCKING,
OPT_SOCKET, OPT_UPDATE_LOG,
OPT_BIN_LOG, OPT_SKIP_RESOLVE,
@@ -3567,14 +3612,20 @@ enum options
OPT_BDB_LOG_BUFFER_SIZE,
OPT_BDB_MAX_LOCK,
OPT_ERROR_LOG_FILE,
+ OPT_DEFAULT_WEEK_FORMAT,
+ OPT_RANGE_ALLOC_BLOCK_SIZE,
+ OPT_QUERY_ALLOC_BLOCK_SIZE, OPT_QUERY_PREALLOC_SIZE,
+ OPT_TRANS_ALLOC_BLOCK_SIZE, OPT_TRANS_PREALLOC_SIZE,
OPT_ENABLE_SHARED_MEMORY,
OPT_SHARED_MEMORY_BASE_NAME,
OPT_OLD_PASSWORDS,
OPT_EXPIRE_LOGS_DAYS,
- OPT_DEFAULT_WEEK_FORMAT,
OPT_GROUP_CONCAT_MAX_LEN,
OPT_DEFAULT_COLLATION,
OPT_SECURE_AUTH,
+ OPT_DATE_FORMAT,
+ OPT_TIME_FORMAT,
+ OPT_DATETIME_FORMAT,
OPT_LOG_QUERIES_NOT_USING_INDEXES
};
@@ -4392,6 +4443,11 @@ The minimum value for this variable is 4096.",
(gptr*) &global_system_variables.preload_buff_size,
(gptr*) &max_system_variables.preload_buff_size, 0, GET_ULONG,
REQUIRED_ARG, 32*1024L, 1024, 1024*1024*1024L, 0, 1, 0},
+ {"query_alloc_block_size", OPT_QUERY_ALLOC_BLOCK_SIZE,
+ "Allocation block size for query parsing and execution",
+ (gptr*) &global_system_variables.query_alloc_block_size,
+ (gptr*) &max_system_variables.query_alloc_block_size, 0, GET_ULONG,
+ REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ~0L, 0, 1024, 0},
#ifdef HAVE_QUERY_CACHE
{"query_cache_limit", OPT_QUERY_CACHE_LIMIT,
"Don't cache results that are bigger than this.",
@@ -4413,6 +4469,11 @@ The minimum value for this variable is 4096.",
(gptr*) &global_system_variables.query_cache_type,
(gptr*) &max_system_variables.query_cache_type,
0, GET_ULONG, REQUIRED_ARG, 1, 0, 2, 0, 1, 0},
+ {"query_prealloc_size", OPT_QUERY_PREALLOC_SIZE,
+ "Persistent buffer for query parsing and execution",
+ (gptr*) &global_system_variables.query_prealloc_size,
+ (gptr*) &max_system_variables.query_prealloc_size, 0, GET_ULONG,
+ REQUIRED_ARG, QUERY_ALLOC_PREALLOC_SIZE, 1024, ~0L, 0, 1024, 0},
#endif /*HAVE_QUERY_CACHE*/
{"read_buffer_size", OPT_RECORD_BUFFER,
"Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value.",
@@ -4451,6 +4512,11 @@ The minimum value for this variable is 4096.",
(gptr*) &slave_net_timeout, (gptr*) &slave_net_timeout, 0,
GET_ULONG, REQUIRED_ARG, SLAVE_NET_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
#endif /* HAVE_REPLICATION */
+ {"range_alloc_block_size", OPT_RANGE_ALLOC_BLOCK_SIZE,
+ "Allocation block size for storing ranges during optimization",
+ (gptr*) &global_system_variables.range_alloc_block_size,
+ (gptr*) &max_system_variables.range_alloc_block_size, 0, GET_ULONG,
+ REQUIRED_ARG, RANGE_ALLOC_BLOCK_SIZE, 1024, ~0L, 0, 1024, 0},
{"read-only", OPT_READONLY,
"Make all tables readonly, with the expections for replications (slave) threads and users with the SUPER privilege.",
(gptr*) &opt_readonly,
@@ -4487,6 +4553,16 @@ The minimum value for this variable is 4096.",
"The stack size for each thread.", (gptr*) &thread_stack,
(gptr*) &thread_stack, 0, GET_ULONG, REQUIRED_ARG,DEFAULT_THREAD_STACK,
1024*32, ~0L, 0, 1024, 0},
+ {"transaction_alloc_block_size", OPT_TRANS_ALLOC_BLOCK_SIZE,
+ "Allocation block size for transactions to be stored in binary log",
+ (gptr*) &global_system_variables.trans_alloc_block_size,
+ (gptr*) &max_system_variables.trans_alloc_block_size, 0, GET_ULONG,
+ REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ~0L, 0, 1024, 0},
+ {"transaction_prealloc_size", OPT_TRANS_PREALLOC_SIZE,
+ "Persistent buffer for transactions to be stored in binary log",
+ (gptr*) &global_system_variables.trans_prealloc_size,
+ (gptr*) &max_system_variables.trans_prealloc_size, 0, GET_ULONG,
+ REQUIRED_ARG, TRANS_ALLOC_PREALLOC_SIZE, 1024, ~0L, 0, 1024, 0},
{"wait_timeout", OPT_WAIT_TIMEOUT,
"The number of seconds the server waits for activity on a connection before closing it.",
(gptr*) &global_system_variables.net_wait_timeout,
@@ -4502,6 +4578,21 @@ The minimum value for this variable is 4096.",
(gptr*) &global_system_variables.default_week_format,
(gptr*) &max_system_variables.default_week_format,
0, GET_ULONG, REQUIRED_ARG, 0, 0, 3L, 0, 1, 0},
+ { "date-format", OPT_DATE_FORMAT,
+ "The DATE format.",
+ (gptr*) &opt_datetime_formats[DATE_FORMAT_TYPE],
+ (gptr*) &opt_datetime_formats[DATE_FORMAT_TYPE],
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ { "datetime-format", OPT_DATETIME_FORMAT,
+ "The DATETIME/TIMESTAMP format.",
+ (gptr*) &opt_datetime_formats[DATETIME_FORMAT_TYPE],
+ (gptr*) &opt_datetime_formats[DATETIME_FORMAT_TYPE],
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ { "time-format", OPT_TIME_FORMAT,
+ "The TIME format.",
+ (gptr*) &opt_datetime_formats[TIME_FORMAT_TYPE],
+ (gptr*) &opt_datetime_formats[TIME_FORMAT_TYPE],
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -4879,6 +4970,10 @@ static void mysql_init_variables(void)
max_system_variables.max_join_size= (ulonglong) HA_POS_ERROR;
global_system_variables.old_passwords= 0;
+ init_global_datetime_format(DATE_FORMAT_TYPE, 0);
+ init_global_datetime_format(TIME_FORMAT_TYPE, 0);
+ init_global_datetime_format(DATETIME_FORMAT_TYPE, 0);
+
/* Variables that depends on compile options */
#ifndef DBUG_OFF
default_dbug_option=IF_WIN("d:t:i:O,\\mysqld.trace",
diff --git a/sql/opt_ft.cc b/sql/opt_ft.cc
index b35b3230a39..74349819937 100644
--- a/sql/opt_ft.cc
+++ b/sql/opt_ft.cc
@@ -26,11 +26,11 @@
** Create a FT or QUICK RANGE based on a key
****************************************************************************/
-QUICK_SELECT *get_ft_or_quick_select_for_ref(TABLE *table, JOIN_TAB *tab)
+QUICK_SELECT *get_ft_or_quick_select_for_ref(THD *thd, TABLE *table,
+ JOIN_TAB *tab)
{
if (tab->type == JT_FT)
- return new FT_SELECT(table, &tab->ref);
- else
- return get_quick_select_for_ref(table, &tab->ref);
+ return new FT_SELECT(thd, table, &tab->ref);
+ return get_quick_select_for_ref(thd, table, &tab->ref);
}
diff --git a/sql/opt_ft.h b/sql/opt_ft.h
index b055edc107c..69b6b72f3fc 100644
--- a/sql/opt_ft.h
+++ b/sql/opt_ft.h
@@ -28,13 +28,14 @@ class FT_SELECT: public QUICK_SELECT {
public:
TABLE_REF *ref;
- FT_SELECT(TABLE *table, TABLE_REF *tref) :
- QUICK_SELECT (table,tref->key,1), ref(tref) { init(); }
+ FT_SELECT(THD *thd, TABLE *table, TABLE_REF *tref) :
+ QUICK_SELECT (thd, table, tref->key, 1), ref(tref) { init(); }
int init() { return error=file->ft_init(); }
int get_next() { return error=file->ft_read(record); }
};
-QUICK_SELECT *get_ft_or_quick_select_for_ref(TABLE *table, JOIN_TAB *tab);
+QUICK_SELECT *get_ft_or_quick_select_for_ref(THD *thd, TABLE *table,
+ JOIN_TAB *tab);
#endif
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index a8ea50beafc..cf1838489d0 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -279,6 +279,7 @@ public:
typedef struct st_qsel_param {
+ THD *thd;
TABLE *table;
KEY_PART *key_parts,*key_parts_end,*key[MAX_KEY];
MEM_ROOT *mem_root;
@@ -377,13 +378,14 @@ SQL_SELECT::~SQL_SELECT()
#undef index // Fix for Unixware 7
-QUICK_SELECT::QUICK_SELECT(TABLE *table,uint key_nr,bool no_alloc)
+QUICK_SELECT::QUICK_SELECT(THD *thd, TABLE *table, uint key_nr, bool no_alloc)
:dont_free(0),error(0),index(key_nr),max_used_key_length(0),
used_key_parts(0), head(table), it(ranges),range(0)
{
if (!no_alloc)
{
- init_sql_alloc(&alloc,1024,0); // Allocates everything here
+ // Allocates everything through the internal memroot
+ init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0);
my_pthread_setspecific_ptr(THR_MALLOC,&alloc);
}
else
@@ -455,17 +457,17 @@ SEL_ARG *SEL_ARG::clone(SEL_ARG *new_parent,SEL_ARG **next_arg)
SEL_ARG *tmp;
if (type != KEY_RANGE)
{
- if (!(tmp=new SEL_ARG(type)))
- return 0; // out of memory
+ if (!(tmp= new SEL_ARG(type)))
+ return 0; // out of memory
tmp->prev= *next_arg; // Link into next/prev chain
(*next_arg)->next=tmp;
(*next_arg)= tmp;
}
else
{
- if (!(tmp=new SEL_ARG(field,part, min_value,max_value,
- min_flag, max_flag, maybe_flag)))
- return 0; // out of memory
+ if (!(tmp= new SEL_ARG(field,part, min_value,max_value,
+ min_flag, max_flag, maybe_flag)))
+ return 0; // OOM
tmp->parent=new_parent;
tmp->next_key_part=next_key_part;
if (left != &null_element)
@@ -476,7 +478,8 @@ SEL_ARG *SEL_ARG::clone(SEL_ARG *new_parent,SEL_ARG **next_arg)
(*next_arg)= tmp;
if (right != &null_element)
- tmp->right=right->clone(tmp,next_arg);
+ if (!(tmp->right= right->clone(tmp,next_arg)))
+ return 0; // OOM
}
increment_use_count(1);
return tmp;
@@ -555,10 +558,11 @@ SEL_ARG *SEL_ARG::clone_tree()
{
SEL_ARG tmp_link,*next_arg,*root;
next_arg= &tmp_link;
- root=clone((SEL_ARG *) 0, &next_arg);
+ root= clone((SEL_ARG *) 0, &next_arg);
next_arg->next=0; // Fix last link
tmp_link.next->prev=0; // Fix first link
- root->use_count=0;
+ if (root) // If not OOM
+ root->use_count= 0;
return root;
}
@@ -576,7 +580,8 @@ SEL_ARG *SEL_ARG::clone_tree()
** quick_rows ; How many rows the key matches
*****************************************************************************/
-int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables,
+int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
+ table_map prev_tables,
ha_rows limit, bool force_quick_range)
{
uint basflag;
@@ -617,9 +622,9 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables,
SEL_TREE *tree;
KEY_PART *key_parts;
PARAM param;
- THD *thd= current_thd;
-
+
/* set up parameter that is passed to all functions */
+ param.thd= thd;
param.baseflag=basflag;
param.prev_tables=prev_tables | const_tables;
param.read_tables=read_tables;
@@ -629,7 +634,7 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables,
param.mem_root= &alloc;
thd->no_errors=1; // Don't warn about NULL
- init_sql_alloc(&alloc,2048,0);
+ init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0);
if (!(param.key_parts = (KEY_PART*) alloc_root(&alloc,
sizeof(KEY_PART)*
head->key_parts)))
@@ -764,7 +769,7 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
while ((item=li++))
{
SEL_TREE *new_tree=get_mm_tree(param,item);
- if (current_thd->is_fatal_error)
+ if (param->thd->is_fatal_error)
DBUG_RETURN(0); // out of memory
tree=tree_and(param,tree,new_tree);
if (tree && tree->type == SEL_TREE::IMPOSSIBLE)
@@ -905,7 +910,7 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type,
{
SEL_ARG *sel_arg=0;
if (!tree && !(tree=new SEL_TREE()))
- DBUG_RETURN(0); // out of memory
+ DBUG_RETURN(0); // OOM
if (!value || !(value->used_tables() & ~param->read_tables))
{
sel_arg=get_mm_leaf(param,key_part->field,key_part,type,value);
@@ -917,10 +922,11 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type,
DBUG_RETURN(tree);
}
}
- else {
+ else
+ {
// This key may be used later
- if (!(sel_arg=new SEL_ARG(SEL_ARG::MAYBE_KEY)))
- DBUG_RETURN(0); // out of memory
+ if (!(sel_arg= new SEL_ARG(SEL_ARG::MAYBE_KEY)))
+ DBUG_RETURN(0); // OOM
}
sel_arg->part=(uchar) key_part->part;
tree->keys[key_part->key]=sel_add(tree->keys[key_part->key],sel_arg);
@@ -1125,8 +1131,8 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
******************************************************************************/
/*
-** Add a new key test to a key when scanning through all keys
-** This will never be called for same key parts.
+ Add a new key test to a key when scanning through all keys
+ This will never be called for same key parts.
*/
static SEL_ARG *
@@ -1310,7 +1316,8 @@ key_and(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag)
// key1->part < key2->part
key1->use_count--;
if (key1->use_count > 0)
- key1=key1->clone_tree();
+ if (!(key1= key1->clone_tree()))
+ return 0; // OOM
return and_all_keys(key1,key2,clone_flag);
}
@@ -1329,7 +1336,8 @@ key_and(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag)
if (key1->use_count > 1)
{
key1->use_count--;
- key1=key1->clone_tree();
+ if (!(key1=key1->clone_tree()))
+ return 0; // OOM
key1->use_count++;
}
if (key1->type == SEL_ARG::MAYBE_KEY)
@@ -1373,6 +1381,8 @@ key_and(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag)
if (!next || next->type != SEL_ARG::IMPOSSIBLE)
{
SEL_ARG *new_arg= e1->clone_and(e2);
+ if (!new_arg)
+ return &null_element; // End of memory
new_arg->next_key_part=next;
if (!new_tree)
{
@@ -1460,8 +1470,8 @@ key_or(SEL_ARG *key1,SEL_ARG *key2)
{
swap(SEL_ARG *,key1,key2);
}
- else
- key1=key1->clone_tree();
+ else if (!(key1=key1->clone_tree()))
+ return 0; // OOM
}
// Add tree at key2 to tree at key1
@@ -1529,7 +1539,10 @@ key_or(SEL_ARG *key1,SEL_ARG *key2)
SEL_ARG *next=key2->next; // Keys are not overlapping
if (key2_shared)
{
- key1=key1->insert(new SEL_ARG(*key2)); // Must make copy
+ SEL_ARG *tmp= new SEL_ARG(*key2); // Must make copy
+ if (!tmp)
+ return 0; // OOM
+ key1=key1->insert(tmp);
key2->increment_use_count(key1->use_count+1);
}
else
@@ -1575,6 +1588,8 @@ key_or(SEL_ARG *key1,SEL_ARG *key2)
if (cmp >= 0 && tmp->cmp_min_to_min(key2) < 0)
{ // tmp.min <= x < key2.min
SEL_ARG *new_arg=tmp->clone_first(key2);
+ if (!new_arg)
+ return 0; // OOM
if ((new_arg->next_key_part= key1->next_key_part))
new_arg->increment_use_count(key1->use_count+1);
tmp->copy_min_to_min(key2);
@@ -1588,6 +1603,8 @@ key_or(SEL_ARG *key1,SEL_ARG *key2)
if (tmp->cmp_min_to_min(&key) > 0)
{ // key.min <= x < tmp.min
SEL_ARG *new_arg=key.clone_first(tmp);
+ if (!new_arg)
+ return 0; // OOM
if ((new_arg->next_key_part=key.next_key_part))
new_arg->increment_use_count(key1->use_count+1);
key1=key1->insert(new_arg);
@@ -1602,19 +1619,27 @@ key_or(SEL_ARG *key1,SEL_ARG *key2)
key.copy_max_to_min(tmp);
if (!(tmp=tmp->next))
{
- key1=key1->insert(new SEL_ARG(key));
+ SEL_ARG *tmp2= new SEL_ARG(key);
+ if (!tmp2)
+ return 0; // OOM
+ key1=key1->insert(tmp2);
key2=key2->next;
goto end;
}
if (tmp->cmp_min_to_max(&key) > 0)
{
- key1=key1->insert(new SEL_ARG(key));
+ SEL_ARG *tmp2= new SEL_ARG(key);
+ if (!tmp2)
+ return 0; // OOM
+ key1=key1->insert(tmp2);
break;
}
}
else
{
SEL_ARG *new_arg=tmp->clone_last(&key); // tmp.min <= x <= key.max
+ if (!new_arg)
+ return 0; // OOM
tmp->copy_max_to_min(&key);
tmp->increment_use_count(key1->use_count+1);
new_arg->next_key_part=key_or(tmp->next_key_part,key.next_key_part);
@@ -1631,8 +1656,11 @@ end:
SEL_ARG *next=key2->next;
if (key2_shared)
{
+ SEL_ARG *tmp=new SEL_ARG(*key2); // Must make copy
+ if (!tmp)
+ return 0;
key2->increment_use_count(key1->use_count+1);
- key1=key1->insert(new SEL_ARG(*key2)); // Must make copy
+ key1=key1->insert(tmp);
}
else
key1=key1->insert(key2); // Will destroy key2_root
@@ -2221,7 +2249,8 @@ get_quick_select(PARAM *param,uint idx,SEL_ARG *key_tree)
{
QUICK_SELECT *quick;
DBUG_ENTER("get_quick_select");
- if ((quick=new QUICK_SELECT(param->table,param->real_keynr[idx])))
+ if ((quick=new QUICK_SELECT(param->thd, param->table,
+ param->real_keynr[idx])))
{
if (quick->error ||
get_quick_keys(param,quick,param->key[idx],key_tree,param->min_key,0,
@@ -2333,10 +2362,10 @@ get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *key,
/* Get range for retrieving rows in QUICK_SELECT::get_next */
if (!(range= new QUICK_RANGE(param->min_key,
- (uint) (tmp_min_key - param->min_key),
- param->max_key,
- (uint) (tmp_max_key - param->max_key),
- flag)))
+ (uint) (tmp_min_key - param->min_key),
+ param->max_key,
+ (uint) (tmp_max_key - param->max_key),
+ flag)))
return 1; // out of memory
set_if_bigger(quick->max_used_key_length,range->min_length);
@@ -2393,10 +2422,10 @@ static bool null_part_in_key(KEY_PART *key_part, const char *key, uint length)
** Create a QUICK RANGE based on a key
****************************************************************************/
-QUICK_SELECT *get_quick_select_for_ref(TABLE *table, TABLE_REF *ref)
+QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref)
{
table->file->index_end(); // Remove old cursor
- QUICK_SELECT *quick=new QUICK_SELECT(table, ref->key, 1);
+ QUICK_SELECT *quick=new QUICK_SELECT(thd, table, ref->key, 1);
KEY *key_info = &table->key_info[ref->key];
KEY_PART *key_part;
uint part;
@@ -2405,7 +2434,7 @@ QUICK_SELECT *get_quick_select_for_ref(TABLE *table, TABLE_REF *ref)
return 0; /* no ranges found */
if (cp_buffer_from_ref(ref))
{
- if (current_thd->is_fatal_error)
+ if (thd->is_fatal_error)
return 0; // out of memory
return quick; // empty range
}
diff --git a/sql/opt_range.h b/sql/opt_range.h
index 4931f6f007e..b4d855c0faa 100644
--- a/sql/opt_range.h
+++ b/sql/opt_range.h
@@ -83,7 +83,7 @@ public:
ha_rows records;
double read_time;
- QUICK_SELECT(TABLE *table,uint index_arg,bool no_alloc=0);
+ QUICK_SELECT(THD *thd, TABLE *table,uint index_arg,bool no_alloc=0);
virtual ~QUICK_SELECT();
void reset(void) { next=0; it.rewind(); }
int init() { return error=file->index_init(index); }
@@ -127,13 +127,14 @@ class SQL_SELECT :public Sql_alloc {
SQL_SELECT();
~SQL_SELECT();
- bool check_quick(bool force_quick_range=0, ha_rows limit = HA_POS_ERROR)
- { return test_quick_select(key_map(~0),0,limit, force_quick_range) < 0; }
+ bool check_quick(THD *thd, bool force_quick_range, ha_rows limit)
+ { return test_quick_select(thd, key_map(~0L),0,limit, force_quick_range) < 0; }
inline bool skipp_record() { return cond ? cond->val_int() == 0 : 0; }
- int test_quick_select(key_map keys,table_map prev_tables,ha_rows limit,
- bool force_quick_range=0);
+ int test_quick_select(THD *thd, key_map keys, table_map prev_tables,
+ ha_rows limit, bool force_quick_range=0);
};
-QUICK_SELECT *get_quick_select_for_ref(TABLE *table, struct st_table_ref *ref);
+QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
+ struct st_table_ref *ref);
#endif
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 79420fb71d5..0fe759cff67 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -833,17 +833,12 @@ bool Protocol_simple::store(TIME *tm)
field_pos++;
#endif
char buff[40];
- uint length;
- length= my_sprintf(buff,(buff, "%04d-%02d-%02d %02d:%02d:%02d",
- (int) tm->year,
- (int) tm->month,
- (int) tm->day,
- (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);
+ String tmp((char*) buff,sizeof(buff),&my_charset_bin);
+ DATETIME_FORMAT *tmp_format= (&t_datetime_frm
+ (current_thd, DATETIME_FORMAT_TYPE).datetime_format);
+ make_datetime(&tmp, tm, 1, tm->second_part,
+ tmp_format->format, tmp_format->format_length, 1);
+ return net_store_data((char*) tmp.ptr(), tmp.length());
}
@@ -855,12 +850,12 @@ bool Protocol_simple::store_date(TIME *tm)
field_pos++;
#endif
char buff[40];
- uint length;
- length= my_sprintf(buff,(buff, "%04d-%02d-%02d",
- (int) tm->year,
- (int) tm->month,
- (int) tm->day));
- return net_store_data((char*) buff, length);
+ String tmp((char*) buff,sizeof(buff),&my_charset_bin);
+ DATETIME_FORMAT *tmp_format= (&t_datetime_frm
+ (current_thd, DATE_FORMAT_TYPE).datetime_format);
+ make_datetime(&tmp, tm, 1, 0,
+ tmp_format->format, tmp_format->format_length, 1);
+ return net_store_data((char*) tmp.ptr(), tmp.length());
}
@@ -878,16 +873,14 @@ bool Protocol_simple::store_time(TIME *tm)
field_pos++;
#endif
char buff[40];
- uint length;
+ String tmp((char*) buff,sizeof(buff),&my_charset_bin);
+ DATETIME_FORMAT *tmp_format= (&t_datetime_frm
+ (current_thd, TIME_FORMAT_TYPE).datetime_format);
uint day= (tm->year || tm->month) ? 0 : tm->day;
- length= my_sprintf(buff,(buff, "%s%02ld:%02d:%02d",
- tm->neg ? "-" : "",
- (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);
+ tm->hour= (long) day*24L+(long) tm->hour;
+ make_datetime(&tmp, tm, 0, tm->second_part,
+ tmp_format->format, tmp_format->format_length, 1);
+ return net_store_data((char*) tmp.ptr(), tmp.length());
}
diff --git a/sql/set_var.cc b/sql/set_var.cc
index eb456b0745f..48580960399 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -51,6 +51,7 @@
#include "slave.h"
#include "sql_acl.h"
#include <my_getopt.h>
+#include <thr_alarm.h>
#include <myisam.h>
#ifdef HAVE_BERKELEY_DB
#include "ha_berkeley.h"
@@ -90,6 +91,7 @@ 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 void fix_max_binlog_size(THD *thd, enum_var_type type);
static void fix_max_relay_log_size(THD *thd, enum_var_type type);
+static void fix_max_connections(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);
@@ -162,11 +164,13 @@ sys_var_long_ptr sys_max_binlog_size("max_binlog_size",
&max_binlog_size,
fix_max_binlog_size);
sys_var_long_ptr sys_max_connections("max_connections",
- &max_connections);
+ &max_connections,
+ fix_max_connections);
sys_var_long_ptr sys_max_connect_errors("max_connect_errors",
&max_connect_errors);
sys_var_long_ptr sys_max_delayed_threads("max_delayed_threads",
- &max_insert_delayed_threads);
+ &max_insert_delayed_threads,
+ fix_max_connections);
sys_var_thd_ulong sys_max_error_count("max_error_count",
&SV::max_error_count);
sys_var_thd_ulong sys_max_heap_table_size("max_heap_table_size",
@@ -235,6 +239,18 @@ sys_var_long_ptr sys_rpl_recovery_rank("rpl_recovery_rank",
sys_var_long_ptr sys_query_cache_size("query_cache_size",
&query_cache_size,
fix_query_cache_size);
+
+sys_var_thd_ulong sys_range_alloc_block_size("range_alloc_block_size",
+ &SV::range_alloc_block_size);
+sys_var_thd_ulong sys_query_alloc_block_size("query_alloc_block_size",
+ &SV::query_alloc_block_size);
+sys_var_thd_ulong sys_query_prealloc_size("query_prealloc_size",
+ &SV::query_prealloc_size);
+sys_var_thd_ulong sys_trans_alloc_block_size("transaction_alloc_block_size",
+ &SV::trans_alloc_block_size);
+sys_var_thd_ulong sys_trans_prealloc_size("transaction_prealloc_size",
+ &SV::trans_prealloc_size);
+
#ifdef HAVE_QUERY_CACHE
sys_var_long_ptr sys_query_cache_limit("query_cache_limit",
&query_cache.query_cache_limit);
@@ -387,6 +403,9 @@ sys_var *sys_variables[]=
&sys_collation_server,
&sys_concurrent_insert,
&sys_connect_timeout,
+ &g_datetime_frm(DATE_FORMAT_TYPE),
+ &g_datetime_frm(DATETIME_FORMAT_TYPE),
+ &g_datetime_frm(TIME_FORMAT_TYPE),
&sys_default_week_format,
&sys_delay_key_write,
&sys_delayed_insert_limit,
@@ -441,7 +460,9 @@ sys_var *sys_variables[]=
&sys_old_passwords,
&sys_preload_buff_size,
&sys_pseudo_thread_id,
+ &sys_query_alloc_block_size,
&sys_query_cache_size,
+ &sys_query_prealloc_size,
#ifdef HAVE_QUERY_CACHE
&sys_query_cache_limit,
&sys_query_cache_min_res_unit,
@@ -450,6 +471,7 @@ sys_var *sys_variables[]=
&sys_quote_show_create,
&sys_rand_seed1,
&sys_rand_seed2,
+ &sys_range_alloc_block_size,
&sys_read_buff_size,
&sys_read_rnd_buff_size,
#ifdef HAVE_REPLICATION
@@ -478,6 +500,8 @@ sys_var *sys_variables[]=
&sys_thread_cache_size,
&sys_timestamp,
&sys_tmp_table_size,
+ &sys_trans_alloc_block_size,
+ &sys_trans_prealloc_size,
&sys_tx_isolation,
#ifdef HAVE_INNOBASE_DB
&sys_innodb_max_dirty_pages_pct,
@@ -519,6 +543,8 @@ struct show_var_st init_vars[]= {
{sys_concurrent_insert.name,(char*) &sys_concurrent_insert, SHOW_SYS},
{sys_connect_timeout.name, (char*) &sys_connect_timeout, SHOW_SYS},
{"datadir", mysql_real_data_home, SHOW_CHAR},
+ {"date_format", (char*) &g_datetime_frm(DATE_FORMAT_TYPE), SHOW_SYS},
+ {"datetime_format", (char*) &g_datetime_frm(DATETIME_FORMAT_TYPE), SHOW_SYS},
{"default_week_format", (char*) &sys_default_week_format, SHOW_SYS},
{sys_delay_key_write.name, (char*) &sys_delay_key_write, SHOW_SYS},
{sys_delayed_insert_limit.name, (char*) &sys_delayed_insert_limit,SHOW_SYS},
@@ -629,6 +655,8 @@ struct show_var_st init_vars[]= {
{"protocol_version", (char*) &protocol_version, SHOW_INT},
{sys_preload_buff_size.name, (char*) &sys_preload_buff_size, SHOW_SYS},
{sys_pseudo_thread_id.name, (char*) &sys_pseudo_thread_id, SHOW_SYS},
+ {sys_query_alloc_block_size.name, (char*) &sys_query_alloc_block_size,
+ SHOW_SYS},
#ifdef HAVE_QUERY_CACHE
{sys_query_cache_limit.name,(char*) &sys_query_cache_limit, SHOW_SYS},
{sys_query_cache_min_res_unit.name, (char*) &sys_query_cache_min_res_unit,
@@ -637,6 +665,9 @@ struct show_var_st init_vars[]= {
{sys_query_cache_type.name, (char*) &sys_query_cache_type, SHOW_SYS},
{"secure_auth", (char*) &sys_secure_auth, SHOW_SYS},
#endif /* HAVE_QUERY_CACHE */
+ {sys_query_prealloc_size.name, (char*) &sys_query_prealloc_size, SHOW_SYS},
+ {sys_range_alloc_block_size.name, (char*) &sys_range_alloc_block_size,
+ SHOW_SYS},
{sys_read_buff_size.name, (char*) &sys_read_buff_size, SHOW_SYS},
{sys_readonly.name, (char*) &sys_readonly, SHOW_SYS},
{sys_read_rnd_buff_size.name,(char*) &sys_read_rnd_buff_size, SHOW_SYS},
@@ -670,19 +701,89 @@ struct show_var_st init_vars[]= {
#endif
{"thread_stack", (char*) &thread_stack, SHOW_LONG},
{sys_tx_isolation.name, (char*) &sys_tx_isolation, SHOW_SYS},
+ {"time_format", (char*) &g_datetime_frm(TIME_FORMAT_TYPE), SHOW_SYS},
#ifdef HAVE_TZNAME
{"timezone", time_zone, SHOW_CHAR},
#endif
{sys_tmp_table_size.name, (char*) &sys_tmp_table_size, SHOW_SYS},
{"tmpdir", (char*) &opt_mysql_tmpdir, SHOW_CHAR_PTR},
+ {sys_trans_alloc_block_size.name, (char*) &sys_trans_alloc_block_size,
+ SHOW_SYS},
+ {sys_trans_prealloc_size.name, (char*) &sys_trans_prealloc_size, SHOW_SYS},
{"version", server_version, SHOW_CHAR},
{sys_net_wait_timeout.name, (char*) &sys_net_wait_timeout, SHOW_SYS},
{NullS, NullS, SHOW_LONG}
};
+
/*
Functions to check and update variables
*/
+char *update_datetime_format(THD *thd, enum enum_var_type type,
+ enum datetime_format_types format_type,
+ DATETIME_FORMAT *tmp_format)
+{
+ char *old_value;
+ if (type == OPT_GLOBAL)
+ {
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ old_value= g_datetime_frm(format_type).datetime_format.format;
+ g_datetime_frm(format_type).datetime_format= *tmp_format;
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ }
+ else
+ {
+ old_value= t_datetime_frm(thd,format_type).datetime_format.format;
+ t_datetime_frm(thd, format_type).datetime_format= *tmp_format;
+ }
+ return old_value;
+}
+
+
+bool sys_var_datetime_format::update(THD *thd, set_var *var)
+{
+ DATETIME_FORMAT tmp_format;
+ char *old_value;
+ uint new_length;
+
+ if ((new_length= var->value->str_value.length()))
+ {
+ if (!make_format(&tmp_format, format_type,
+ var->value->str_value.ptr(),
+ new_length, 1))
+ return 1;
+ }
+
+ old_value= update_datetime_format(thd, var->type, format_type, &tmp_format);
+ my_free(old_value, MYF(MY_ALLOW_ZERO_PTR));
+ return 0;
+}
+
+byte *sys_var_datetime_format::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
+{
+ if (type == OPT_GLOBAL)
+ return (byte*) g_datetime_frm(format_type).datetime_format.format;
+ return (byte*) t_datetime_frm(thd, format_type).datetime_format.format;
+}
+
+void sys_var_datetime_format::set_default(THD *thd, enum_var_type type)
+{
+ DATETIME_FORMAT tmp_format;
+ char *old_value;
+ uint new_length;
+
+ if ((new_length= strlen(opt_datetime_formats[format_type])))
+ {
+ if (!make_format(&tmp_format, format_type,
+ opt_datetime_formats[format_type],
+ new_length, 1))
+ return;
+ }
+
+ old_value= update_datetime_format(thd, type, format_type, &tmp_format);
+ my_free(old_value, MYF(MY_ALLOW_ZERO_PTR));
+}
/*
The following 3 functions need to be changed in 4.1 when we allow
@@ -748,7 +849,7 @@ static void fix_max_join_size(THD *thd, enum_var_type type)
thd->options&= ~OPTION_BIG_SELECTS;
}
}
-
+
/*
If one doesn't use the SESSION modifier, the isolation level
@@ -816,7 +917,7 @@ static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type)
#endif
-void fix_delay_key_write(THD *thd, enum_var_type type)
+extern void fix_delay_key_write(THD *thd, enum_var_type type)
{
switch ((enum_delay_key_write) delay_key_write_options) {
case DELAY_KEY_WRITE_NONE:
@@ -832,7 +933,7 @@ void fix_delay_key_write(THD *thd, enum_var_type type)
}
}
-void fix_max_binlog_size(THD *thd, enum_var_type type)
+static void fix_max_binlog_size(THD *thd, enum_var_type type)
{
DBUG_ENTER("fix_max_binlog_size");
DBUG_PRINT("info",("max_binlog_size=%lu max_relay_log_size=%lu",
@@ -845,7 +946,7 @@ void fix_max_binlog_size(THD *thd, enum_var_type type)
DBUG_VOID_RETURN;
}
-void fix_max_relay_log_size(THD *thd, enum_var_type type)
+static void fix_max_relay_log_size(THD *thd, enum_var_type type)
{
DBUG_ENTER("fix_max_relay_log_size");
DBUG_PRINT("info",("max_binlog_size=%lu max_relay_log_size=%lu",
@@ -857,6 +958,13 @@ void fix_max_relay_log_size(THD *thd, enum_var_type type)
DBUG_VOID_RETURN;
}
+
+static void fix_max_connections(THD *thd, enum_var_type type)
+{
+ resize_thr_alarm(max_connections + max_insert_delayed_threads + 10);
+}
+
+
bool sys_var_long_ptr::update(THD *thd, set_var *var)
{
ulonglong tmp= var->value->val_int();
@@ -1082,7 +1190,8 @@ byte *sys_var_thd_bool::value_ptr(THD *thd, enum_var_type type,
bool sys_var::check_enum(THD *thd, set_var *var, TYPELIB *enum_names)
{
- char buff[80], *value;
+ char buff[80];
+ const char *value;
String str(buff, sizeof(buff), system_charset_info), *res;
if (var->value->result_type() == STRING_RESULT)
@@ -1092,7 +1201,7 @@ bool sys_var::check_enum(THD *thd, set_var *var, TYPELIB *enum_names)
(ulong) find_type(res->c_ptr(), enum_names, 3)-1))
< 0)
{
- value=res->c_ptr();
+ value= res ? res->c_ptr() : "NULL";
goto err;
}
}
@@ -2050,7 +2159,7 @@ int set_var::check(THD *thd)
{
my_error(ER_WRONG_TYPE_FOR_VAR, MYF(0), var->name);
return -1;
- }
+ }
return var->check(thd, this) ? -1 : 0;
}
@@ -2205,7 +2314,7 @@ ulong fix_sql_mode(ulong sql_mode)
MODE_IGNORE_SPACE |
MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
MODE_NO_FIELD_OPTIONS);
- if (sql_mode & MODE_SAPDB)
+ if (sql_mode & MODE_MAXDB)
sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
MODE_IGNORE_SPACE |
MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
diff --git a/sql/set_var.h b/sql/set_var.h
index 812bd6c9420..4c67c5ccc59 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -49,6 +49,8 @@ public:
const char *name;
sys_after_update_func after_update;
+ sys_var()
+ {}
sys_var(const char *name_arg) :name(name_arg),after_update(0)
{}
sys_var(const char *name_arg,sys_after_update_func func)
@@ -188,6 +190,9 @@ public:
class sys_var_thd :public sys_var
{
public:
+ sys_var_thd()
+ :sys_var()
+ {}
sys_var_thd(const char *name_arg)
:sys_var(name_arg)
{}
@@ -555,6 +560,51 @@ public:
};
+class sys_var_datetime_format :public sys_var_thd
+{
+public:
+ enum datetime_format_types format_type;
+ DATETIME_FORMAT datetime_format;
+ sys_var_datetime_format(): sys_var_thd()
+ {}
+
+ void clean()
+ {
+ my_free(datetime_format.format, MYF(MY_ALLOW_ZERO_PTR));
+ datetime_format.format=0;
+ }
+
+ /*
+ It's for copying of global_system_variables structure
+ in THD constructor.
+ */
+ inline sys_var_datetime_format& operator= (sys_var_datetime_format& s)
+ {
+ if (&s != this)
+ {
+ name= s.name; name_length= s.name_length;
+ datetime_format= s.datetime_format;
+ datetime_format.format= (my_strdup_with_length
+ (s.datetime_format.format,
+ s.datetime_format.
+ format_length, MYF(0)));
+ format_type= s.format_type;
+ }
+ return *this;
+ }
+
+ SHOW_TYPE type() { return SHOW_CHAR; }
+ bool check_update_type(Item_result type)
+ {
+ return type != STRING_RESULT; /* Only accept strings */
+ }
+ 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, LEX_STRING *base);
+ void set_default(THD *thd, enum_var_type type);
+};
+
+
/* Variable that you can only read from */
class sys_var_readonly: public sys_var
@@ -693,7 +743,7 @@ public:
uint name_length_arg, gptr data_arg)
:name_length(name_length_arg), data(data_arg)
{
- name= my_memdup(name_arg, name_length, MYF(MY_WME));
+ name= my_memdup((byte*) name_arg, name_length, MYF(MY_WME));
links->push_back(this);
}
inline bool cmp(const char *name_cmp, uint length)
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index 74027e78c31..bb7cd90b4c4 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -291,4 +291,4 @@ character-set=latin2
"Wrong parameter or combination of parameters for START SLAVE UNTIL"
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
"SQL thread is not to be started so UNTIL options are ignored"
-
+"Incorrect index name '%-.100s'",
diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt
index aa93758bc8b..48a4fee22f8 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -285,4 +285,4 @@ character-set=latin1
"Wrong parameter or combination of parameters for START SLAVE UNTIL"
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
"SQL thread is not to be started so UNTIL options are ignored"
-
+"Incorrect index name '%-.100s'",
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
index 963f040ae86..98fb9278cc2 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -293,4 +293,4 @@ character-set=latin1
"Wrong parameter or combination of parameters for START SLAVE UNTIL"
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
"SQL thread is not to be started so UNTIL options are ignored"
-
+"Incorrect index name '%-.100s'",
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index 7fb93e70e04..5ccfb39478a 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -282,5 +282,5 @@ character-set=latin1
"Wrong parameter or combination of parameters for START SLAVE UNTIL"
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
"SQL thread is not to be started so UNTIL options are ignored"
+"Incorrect index name '%-.100s'",
"Column '%-.64s' cannot be part of FULLTEXT index"
-
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index 91f530585de..e596863907f 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -287,4 +287,4 @@ character-set=latin7
"Wrong parameter or combination of parameters for START SLAVE UNTIL"
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
"SQL thread is not to be started so UNTIL options are ignored"
-
+"Incorrect index name '%-.100s'",
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index 6ab9529e88d..a81b8859692 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -282,4 +282,4 @@ character-set=latin1
"Wrong parameter or combination of parameters for START SLAVE UNTIL"
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
"SQL thread is not to be started so UNTIL options are ignored"
-
+"Incorrect index name '%-.100s'",
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index 7750b5292fd..9554822a5ff 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -294,4 +294,4 @@ character-set=latin1
"Falscher Parameter oder falsche Kombination von Parametern für START SLAVE UNTIL",
"Es wird empfohlen, mit --skip-slave-start zu starten, wenn mit START SLAVE UNTIL eine Schritt-für-Schritt-Replikation ausgeführt wird. Ansonsten gibt es Probleme, wenn der Slave-Server unerwartet neu startet",
"SQL-Thread soll nicht gestartet werden. Daher werden UNTIL-Optionen ignoriert"
-
+"Incorrect index name '%-.100s'",
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index 46fb9ab2425..073289562b3 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -282,4 +282,4 @@ character-set=greek
"Wrong parameter or combination of parameters for START SLAVE UNTIL"
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
"SQL thread is not to be started so UNTIL options are ignored"
-
+"Incorrect index name '%-.100s'",
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index ddf6b3b5347..c62a7c7b1ae 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -284,4 +284,4 @@ character-set=latin2
"Wrong parameter or combination of parameters for START SLAVE UNTIL"
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
"SQL thread is not to be started so UNTIL options are ignored"
-
+"Incorrect index name '%-.100s'",
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index 9043bd009c6..004d7d00994 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -282,4 +282,4 @@ character-set=latin1
"Wrong parameter or combination of parameters for START SLAVE UNTIL"
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
"SQL thread is not to be started so UNTIL options are ignored"
-
+"Incorrect index name '%-.100s'",
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index 35e8529070b..888ac449a8b 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -284,4 +284,4 @@ character-set=ujis
"Wrong parameter or combination of parameters for START SLAVE UNTIL"
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
"SQL thread is not to be started so UNTIL options are ignored"
-
+"Incorrect index name '%-.100s'",
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index 84e1030c188..a72d6c3fdee 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -282,4 +282,4 @@ character-set=euckr
"Wrong parameter or combination of parameters for START SLAVE UNTIL"
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
"SQL thread is not to be started so UNTIL options are ignored"
-
+"Incorrect index name '%-.100s'",
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index 12c697c7019..3c6dca27016 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -284,4 +284,4 @@ character-set=latin1
"Wrong parameter or combination of parameters for START SLAVE UNTIL"
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
"SQL thread is not to be started so UNTIL options are ignored"
-
+"Incorrect index name '%-.100s'",
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index 916f44b10be..bafc635a184 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -284,4 +284,4 @@ character-set=latin1
"Wrong parameter or combination of parameters for START SLAVE UNTIL"
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
"SQL thread is not to be started so UNTIL options are ignored"
-
+"Incorrect index name '%-.100s'",
diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt
index a9ee2b490ed..0aa25aabb44 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -286,4 +286,4 @@ character-set=latin2
"Wrong parameter or combination of parameters for START SLAVE UNTIL"
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
"SQL thread is not to be started so UNTIL options are ignored"
-
+"Incorrect index name '%-.100s'",
diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt
index b2de951fa31..33d8f68291d 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -283,4 +283,4 @@ character-set=latin1
"Wrong parameter or combination of parameters for START SLAVE UNTIL"
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
"SQL thread is not to be started so UNTIL options are ignored"
-
+"Incorrect index name '%-.100s'",
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index 217743e2542..ff46caf2c6c 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -286,4 +286,4 @@ character-set=latin2
"Wrong parameter or combination of parameters for START SLAVE UNTIL"
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
"SQL thread is not to be started so UNTIL options are ignored"
-
+"Incorrect index name '%-.100s'",
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
index 6456a585585..f8bdb8bf4a5 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -284,4 +284,4 @@ character-set=koi8r
"Wrong parameter or combination of parameters for START SLAVE UNTIL"
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
"SQL thread is not to be started so UNTIL options are ignored"
-
+"Incorrect index name '%-.100s'",
diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt
index a350ab82a98..cede04e36ed 100644
--- a/sql/share/serbian/errmsg.txt
+++ b/sql/share/serbian/errmsg.txt
@@ -277,4 +277,4 @@ character-set=cp1250
"Wrong parameter or combination of parameters for START SLAVE UNTIL"
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
"SQL thread is not to be started so UNTIL options are ignored"
-
+"Incorrect index name '%-.100s'",
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index 711a7ec2fb9..0759f68a1bb 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -290,4 +290,4 @@ character-set=latin2
"Wrong parameter or combination of parameters for START SLAVE UNTIL"
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
"SQL thread is not to be started so UNTIL options are ignored"
-
+"Incorrect index name '%-.100s'",
diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt
index 9c8cf5fceab..b9c1b297e43 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -284,4 +284,4 @@ character-set=latin1
"Wrong parameter or combination of parameters for START SLAVE UNTIL"
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
"SQL thread is not to be started so UNTIL options are ignored"
-
+"Incorrect index name '%-.100s'",
diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt
index 95b44366fdf..456b93fbc4d 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -282,4 +282,4 @@ character-set=latin1
"Wrong parameter or combination of parameters for START SLAVE UNTIL"
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
"SQL thread is not to be started so UNTIL options are ignored"
-
+"Incorrect index name '%-.100s'",
diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt
index 38d0b05a37f..dba62fd60c8 100644
--- a/sql/share/ukrainian/errmsg.txt
+++ b/sql/share/ukrainian/errmsg.txt
@@ -287,4 +287,4 @@ character-set=koi8u
"Wrong parameter or combination of parameters for START SLAVE UNTIL"
"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
"SQL thread is not to be started so UNTIL options are ignored"
-
+"Incorrect index name '%-.100s'",
diff --git a/sql/slave.cc b/sql/slave.cc
index 2aea1056ac8..415969a2955 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -1086,11 +1086,12 @@ static int get_master_version_and_clock(MYSQL* mysql, MASTER_INFO* mi)
BINLOG_FORMAT_323_GEQ_57 ;
break;
case '4':
- case '5':
mi->old_format = BINLOG_FORMAT_CURRENT;
break;
default:
- errmsg = "Master reported unrecognized MySQL version";
+ /* 5.0 is not supported */
+ errmsg = "Master reported an unrecognized MySQL version. Note that 4.0 \
+slaves can't replicate a 5.0 or newer master.";
break;
}
@@ -3165,6 +3166,8 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \
RPL_LOG_NAME, llstr(rli->group_master_log_pos,llbuff));
err:
+ /* Free temporary tables etc */
+ thd->cleanup();
VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->query = thd->db = 0; // extra safety
VOID(pthread_mutex_unlock(&LOCK_thread_count));
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index a47a38f2376..7b79d1aa1b5 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -186,7 +186,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
thd->net.last_error);
goto end;
}
- init_sql_alloc(&mem,1024,0);
+ init_sql_alloc(&mem, ACL_ALLOC_BLOCK_SIZE, 0);
init_read_record(&read_record_info,thd,table= tables[0].table,NULL,1,0);
VOID(my_init_dynamic_array(&acl_hosts,sizeof(ACL_HOST),20,50));
while (!(read_record_info.read_record(&read_record_info)))
@@ -2450,7 +2450,7 @@ my_bool grant_init(THD *org_thd)
(void) hash_init(&column_priv_hash,&my_charset_latin1,
0,0,0, (hash_get_key) get_grant_table,
(hash_free_key) free_grant_table,0);
- init_sql_alloc(&memex,1024,0);
+ init_sql_alloc(&memex, ACL_ALLOC_BLOCK_SIZE, 0);
/* Don't do anything if running with --skip-grant */
if (!initialized)
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index c7d77c67236..588031643d4 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -90,8 +90,9 @@ THD::THD():user_time(0), is_fatal_error(0),
{
host=user=priv_user=db=query=ip=0;
host_or_ip= "connecting host";
- locked=killed=count_cuted_fields=some_tables_deleted=no_errors=password=
+ locked=killed=some_tables_deleted=no_errors=password=
query_start_used=prepare_command=0;
+ count_cuted_fields= CHECK_FIELD_IGNORE;
db_length=query_length=col_access=0;
query_error= tmp_table_used= 0;
next_insert_id=last_insert_id=0;
@@ -147,7 +148,7 @@ THD::THD():user_time(0), is_fatal_error(0),
bzero((char*) &transaction.mem_root,sizeof(transaction.mem_root));
bzero((char*) &con_root,sizeof(con_root));
bzero((char*) &warn_root,sizeof(warn_root));
- init_alloc_root(&warn_root, 1024, 0);
+ init_alloc_root(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
user_connect=(USER_CONN *)0;
hash_init(&user_vars, &my_charset_bin, USER_VARS_HASH_SIZE, 0, 0,
(hash_get_key) get_var_key,
@@ -230,9 +231,11 @@ void THD::init(void)
void THD::init_for_queries()
{
- init_sql_alloc(&mem_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
+ init_sql_alloc(&mem_root, variables.query_alloc_block_size,
+ variables.query_prealloc_size);
init_sql_alloc(&transaction.mem_root,
- TRANS_MEM_ROOT_BLOCK_SIZE, TRANS_MEM_ROOT_PREALLOC);
+ variables.trans_alloc_block_size,
+ variables.trans_prealloc_size);
}
@@ -276,6 +279,9 @@ void THD::cleanup(void)
close_thread_tables(this);
}
close_temporary_tables(this);
+ variables.datetime_formats[DATE_FORMAT_TYPE].clean();
+ variables.datetime_formats[TIME_FORMAT_TYPE].clean();
+ variables.datetime_formats[DATETIME_FORMAT_TYPE].clean();
delete_dynamic(&user_var_events);
hash_free(&user_vars);
if (global_read_lock)
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 146ee18e3e2..06bc29dbb2a 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -34,6 +34,9 @@ enum enum_log_type { LOG_CLOSED, LOG_TO_BE_OPENED, LOG_NORMAL, LOG_NEW, LOG_BIN}
enum enum_delay_key_write { DELAY_KEY_WRITE_NONE, DELAY_KEY_WRITE_ON,
DELAY_KEY_WRITE_ALL };
+enum enum_check_fields { CHECK_FIELD_IGNORE, CHECK_FIELD_WARN,
+ CHECK_FIELD_ERROR_FOR_NULL };
+
extern char internal_table_name[2];
/* log info errors */
@@ -389,10 +392,15 @@ struct system_variables
ulong table_type;
ulong tmp_table_size;
ulong tx_isolation;
- /* Determines if which non-standard SQL behaviour should be enabled */
+ /* Determines which non-standard SQL behaviour should be enabled */
ulong sql_mode;
ulong default_week_format;
ulong max_seeks_for_key;
+ ulong range_alloc_block_size;
+ ulong query_alloc_block_size;
+ ulong query_prealloc_size;
+ ulong trans_alloc_block_size;
+ ulong trans_prealloc_size;
ulong group_concat_max_len;
/*
In slave thread we need to know in behalf of which
@@ -413,6 +421,7 @@ struct system_variables
CHARSET_INFO *collation_server;
CHARSET_INFO *collation_database;
CHARSET_INFO *collation_connection;
+ sys_var_datetime_format datetime_formats[3];
};
void free_tmp_table(THD *thd, TABLE *entry);
@@ -569,6 +578,7 @@ public:
uint select_number; //number of select (used for EXPLAIN)
/* variables.transaction_isolation is reset to this after each commit */
enum_tx_isolation session_tx_isolation;
+ enum_check_fields count_cuted_fields;
/* for user variables replication*/
DYNAMIC_ARRAY user_var_events;
@@ -576,7 +586,7 @@ public:
char scramble[SCRAMBLE_LENGTH+1];
bool slave_thread;
- bool set_query_id,locked,count_cuted_fields,some_tables_deleted;
+ bool set_query_id,locked,some_tables_deleted;
bool last_cuted_field;
bool no_errors, allow_sum_func, password, is_fatal_error;
bool query_start_used,last_insert_id_used,insert_id_used,rand_used;
@@ -858,8 +868,7 @@ public:
List<Item> &select_fields,enum_duplicates duplic)
:select_insert (NULL, &select_fields, duplic), db(db_name),
name(table_name), extra_fields(&fields_par),keys(&keys_par),
- create_info(create_info_par),
- lock(0)
+ create_info(create_info_par), lock(0)
{}
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_data(List<Item> &values);
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index bd76cbd5f36..2985f7e04a0 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -90,7 +90,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
select=make_select(table,0,0,conds,&error);
if (error)
DBUG_RETURN(-1);
- if ((select && select->check_quick(safe_update, limit)) || !limit)
+ if ((select && select->check_quick(thd, safe_update, limit)) || !limit)
{
delete select;
free_underlaid_joins(thd, &thd->lex.select_lex);
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 13d3cc27376..7fd2b751c1d 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -220,7 +220,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
}
}
else
- unit->exclude_level();
+ unit->exclude_tree();
org_table_list->db= (char *)"";
#ifndef DBUG_OFF
/* Try to catch errors if this is accessed */
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index 93ab332bcd5..bce1022d5c0 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -33,7 +33,7 @@
The second is to be freeed only on thread end. mysql_ha_open should
then do { handler_items=concat(handler_items, free_list); free_list=0; }
- But !!! do_cammand calls free_root at the end of every query and frees up
+ But !!! do_command calls free_root at the end of every query and frees up
all the sql_alloc'ed memory. It's harder to work around...
*/
@@ -72,7 +72,11 @@ int mysql_ha_close(THD *thd, TABLE_LIST *tables, bool dont_send_ok)
if (*ptr)
{
VOID(pthread_mutex_lock(&LOCK_open));
- close_thread_table(thd, ptr);
+ if (close_thread_table(thd, ptr))
+ {
+ /* Tell threads waiting for refresh that something has happened */
+ VOID(pthread_cond_broadcast(&COND_refresh));
+ }
VOID(pthread_mutex_unlock(&LOCK_open));
}
else
@@ -89,8 +93,11 @@ int mysql_ha_close(THD *thd, TABLE_LIST *tables, bool dont_send_ok)
int mysql_ha_closeall(THD *thd, TABLE_LIST *tables)
{
TABLE **ptr=find_table_ptr_by_name(thd, tables->db, tables->real_name, 0);
- if (*ptr)
- close_thread_table(thd, ptr);
+ if (*ptr && close_thread_table(thd, ptr))
+ {
+ /* Tell threads waiting for refresh that something has happened */
+ VOID(pthread_cond_broadcast(&COND_refresh));
+ }
return 0;
}
diff --git a/sql/sql_help.cc b/sql/sql_help.cc
index 02fc8591370..6af4ffde0e1 100644
--- a/sql/sql_help.cc
+++ b/sql/sql_help.cc
@@ -599,7 +599,7 @@ SQL_SELECT *prepare_simple_select(THD *thd, Item *cond, TABLE_LIST *tables,
{
cond->fix_fields(thd, tables, &cond); // can never fail
SQL_SELECT *res= make_select(table,0,0,cond,error);
- return (*error || (res && res->check_quick(0, HA_POS_ERROR))) ? 0 : res;
+ return (*error || (res && res->check_quick(thd, 0, HA_POS_ERROR))) ? 0 : res;
}
/*
@@ -627,6 +627,8 @@ SQL_SELECT *prepare_select_for_name(THD *thd, const char *mask, uint mlen,
Item *cond= new Item_func_like(new Item_field(pfname),
new Item_string(mask,mlen,pfname->charset()),
(char*) "\\");
+ if (thd->is_fatal_error)
+ return 0; // OOM
return prepare_simple_select(thd,cond,tables,table,error);
}
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 0ad66beec2e..9077d4c6a2d 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -240,9 +240,14 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
info.handle_duplicates=duplic;
info.update_fields=&update_fields;
info.update_values=&update_values;
- // Don't count warnings for simple inserts
- if (values_list.elements > 1 || (thd->options & OPTION_WARNINGS))
- thd->count_cuted_fields = 1;
+ /*
+ Count warnings for all inserts.
+ For single line insert, generate an error if try to set a NOT NULL field
+ to NULL
+ */
+ thd->count_cuted_fields= ((values_list.elements == 1) ?
+ CHECK_FIELD_ERROR_FOR_NULL :
+ CHECK_FIELD_WARN);
thd->cuted_fields = 0L;
table->next_number_field=table->found_next_number_field;
@@ -394,7 +399,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
}
thd->proc_info="end";
table->next_number_field=0;
- thd->count_cuted_fields=0;
+ thd->count_cuted_fields= CHECK_FIELD_IGNORE;
thd->next_insert_id=0; // Reset this if wrongly used
if (duplic != DUP_ERROR)
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
@@ -1391,7 +1396,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
restore_record(table,default_values); // Get empty record
table->next_number_field=table->found_next_number_field;
- thd->count_cuted_fields=1; // calc cuted fields
+ thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
thd->cuted_fields=0;
if (info.handle_duplicates != DUP_REPLACE)
table->file->extra(HA_EXTRA_WRITE_CACHE);
@@ -1409,7 +1414,7 @@ select_insert::~select_insert()
table->next_number_field=0;
table->file->extra(HA_EXTRA_RESET);
}
- thd->count_cuted_fields=0;
+ thd->count_cuted_fields= CHECK_FIELD_IGNORE;
}
@@ -1548,6 +1553,14 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
if (!table)
DBUG_RETURN(-1); // abort() deletes table
+ if (table->fields < values.elements)
+ {
+ my_printf_error(ER_WRONG_VALUE_COUNT_ON_ROW,
+ ER(ER_WRONG_VALUE_COUNT_ON_ROW),
+ MYF(0),1);
+ DBUG_RETURN(-1);
+ }
+
/* First field to copy */
field=table->field+table->fields - values.elements;
@@ -1559,7 +1572,7 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
table->next_number_field=table->found_next_number_field;
restore_record(table,default_values); // Get empty record
- thd->count_cuted_fields=1; // count warnings
+ thd->count_cuted_fields= CHECK_FIELD_WARN; // count warnings
thd->cuted_fields=0;
if (info.handle_duplicates == DUP_IGNORE ||
info.handle_duplicates == DUP_REPLACE)
@@ -1606,7 +1619,7 @@ bool select_create::send_eof()
*/
if (!table->tmp_table)
hash_delete(&open_cache,(byte*) table);
- lock=0;
+ lock=0;
table=0;
VOID(pthread_mutex_unlock(&LOCK_open));
}
@@ -1627,7 +1640,8 @@ void select_create::abort()
enum db_type table_type=table->db_type;
if (!table->tmp_table)
hash_delete(&open_cache,(byte*) table);
- quick_rm_table(table_type,db,name);
+ if (!create_info->table_existed)
+ quick_rm_table(table_type,db,name);
table=0;
}
VOID(pthread_mutex_unlock(&LOCK_open));
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 80d698dfc26..5b05bf096cb 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1097,6 +1097,16 @@ void st_select_lex_node::exclude()
*/
}
+
+/*
+ Exclude level of current unit from tree of SELECTs
+
+ SYNOPSYS
+ st_select_lex_unit::exclude_level()
+
+ NOTE: units which belong to current will be brought up on level of
+ currernt unit
+*/
void st_select_lex_unit::exclude_level()
{
SELECT_LEX_UNIT *units= 0, **units_last= &units;
@@ -1125,6 +1135,30 @@ void st_select_lex_unit::exclude_level()
(*prev)= next;
}
+
+/*
+ Exclude subtree of current unit from tree of SELECTs
+
+ SYNOPSYS
+ st_select_lex_unit::exclude_tree()
+*/
+void st_select_lex_unit::exclude_tree()
+{
+ SELECT_LEX_UNIT *units= 0, **units_last= &units;
+ for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
+ {
+ if (sl->link_prev && (*sl->link_prev= sl->link_next))
+ sl->link_next->link_prev= sl->link_prev;
+
+ for (SELECT_LEX_UNIT *u= sl->first_inner_unit(); u; u= u->next_unit())
+ {
+ u->exclude_level();
+ }
+ }
+ (*prev)= next;
+}
+
+
/*
st_select_lex_node::mark_as_dependent mark all st_select_lex struct from
this to 'last' as dependent
@@ -1135,7 +1169,6 @@ void st_select_lex_unit::exclude_level()
NOTE
'last' should be reachable from this st_select_lex_node
-
*/
void st_select_lex::mark_as_dependent(SELECT_LEX *last)
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 0166951ab9d..7545f525082 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -321,6 +321,7 @@ public:
st_select_lex_unit* next_unit() { return (st_select_lex_unit*) next; }
st_select_lex* return_after_parsing() { return return_to; }
void exclude_level();
+ void exclude_tree();
/* UNION methods */
int prepare(THD *thd, select_result *result, bool tables_and_fields_initied);
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 0a5c544c2e7..0e7895689b5 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -252,7 +252,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
restore_record(table,default_values);
- thd->count_cuted_fields=1; /* calc cuted fields */
+ thd->count_cuted_fields= CHECK_FIELD_WARN; /* calc cuted fields */
thd->cuted_fields=0L;
if (ex->line_term->length() && field_term->length())
{
@@ -293,7 +293,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
if (file >= 0) my_close(file,MYF(0));
free_blobs(table); /* if pack_blob was used */
table->copy_blobs=0;
- thd->count_cuted_fields=0; /* Don`t calc cuted fields */
+ thd->count_cuted_fields= CHECK_FIELD_IGNORE;
/*
We must invalidate the table in query cache before binlog writing and
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 248dfc0e47a..e8870b20d99 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3407,7 +3407,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
/* grant_option is set if there exists a single table or column grant */
if (db_access == want_access ||
((grant_option && !dont_check_global_grants) &&
- !(want_access & ~TABLE_ACLS)))
+ !(want_access & ~(db_access | TABLE_ACLS))))
DBUG_RETURN(FALSE); /* Ok */
if (!no_errors)
net_printf(thd,ER_DBACCESS_DENIED_ERROR,
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index dd8d5613880..522879c863a 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -888,12 +888,15 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length)
{
MEM_ROOT thd_root= thd->mem_root;
PREP_STMT stmt;
+ SELECT_LEX *sl;
DBUG_ENTER("mysql_stmt_prepare");
bzero((char*) &stmt, sizeof(stmt));
stmt.stmt_id= ++thd->current_stmt_id;
- init_sql_alloc(&stmt.mem_root, 8192, 8192);
+ init_sql_alloc(&stmt.mem_root,
+ thd->variables.query_alloc_block_size,
+ thd->variables.query_prealloc_size);
stmt.thd= thd;
stmt.thd->mem_root= stmt.mem_root;
@@ -908,7 +911,7 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length)
my_pthread_setprio(pthread_self(),WAIT_PRIOR);
// save WHERE clause pointers to avoid damaging they by optimisation
- for (SELECT_LEX *sl= thd->lex.all_selects_list;
+ for (sl= thd->lex.all_selects_list;
sl;
sl= sl->next_select_in_list())
{
@@ -943,8 +946,9 @@ err:
void mysql_stmt_execute(THD *thd, char *packet)
{
- ulong stmt_id= uint4korr(packet);
- PREP_STMT *stmt;
+ ulong stmt_id= uint4korr(packet);
+ PREP_STMT *stmt;
+ SELECT_LEX *sl;
DBUG_ENTER("mysql_stmt_execute");
if (!(stmt=find_prepared_statement(thd, stmt_id, "execute")))
@@ -963,11 +967,13 @@ void mysql_stmt_execute(THD *thd, char *packet)
LEX thd_lex= thd->lex;
thd->lex= stmt->lex;
- for (SELECT_LEX *sl= stmt->lex.all_selects_list;
+ for (sl= stmt->lex.all_selects_list;
sl;
sl= sl->next_select_in_list())
{
- // copy WHERE clause pointers to avoid damaging they by optimisation
+ /*
+ Copy WHERE clause pointers to avoid damaging they by optimisation
+ */
if (sl->prep_where)
sl->where= sl->prep_where->copy_andor_structure(thd);
DBUG_ASSERT(sl->join == 0);
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 5bd494c723d..f25b012a0fa 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1577,7 +1577,8 @@ err:
Approximate how many records will be used in each table
*****************************************************************************/
-static ha_rows get_quick_record_count(SQL_SELECT *select,TABLE *table,
+static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select,
+ TABLE *table,
const key_map& keys,ha_rows limit)
{
int error;
@@ -1586,7 +1587,7 @@ static ha_rows get_quick_record_count(SQL_SELECT *select,TABLE *table,
{
select->head=table;
table->reginfo.impossible_range=0;
- if ((error=select->test_quick_select(keys,(table_map) 0,limit))
+ if ((error=select->test_quick_select(thd, keys,(table_map) 0,limit))
== 1)
DBUG_RETURN(select->quick->records);
if (error == -1)
@@ -1874,8 +1875,8 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
found_const_table_map,
s->on_expr ? s->on_expr : conds,
&error);
- records= get_quick_record_count(select,s->table, s->const_keys,
- join->row_limit);
+ records= get_quick_record_count(join->thd, select, s->table,
+ s->const_keys, join->row_limit);
s->quick=select->quick;
s->needed_reg=select->needed_reg;
select->quick=0;
@@ -3226,9 +3227,9 @@ store_val_in_field(Field *field,Item *item)
bool error;
THD *thd=current_thd;
ha_rows cuted_fields=thd->cuted_fields;
- thd->count_cuted_fields=1;
+ thd->count_cuted_fields= CHECK_FIELD_WARN;
error= item->save_in_field(field, 1);
- thd->count_cuted_fields=0;
+ thd->count_cuted_fields= CHECK_FIELD_IGNORE;
return error || cuted_fields != thd->cuted_fields;
}
@@ -3386,7 +3387,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
/* Join with outer join condition */
COND *orig_cond=sel->cond;
sel->cond=and_conds(sel->cond,tab->on_expr);
- if (sel->test_quick_select(tab->keys,
+ if (sel->test_quick_select(join->thd, tab->keys,
used_tables & ~ current_map,
(join->select_options &
OPTION_FOUND_ROWS ?
@@ -3399,7 +3400,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
*/
sel->cond=orig_cond;
if (!tab->on_expr ||
- sel->test_quick_select(tab->keys,
+ sel->test_quick_select(join->thd, tab->keys,
used_tables & ~ current_map,
(join->select_options &
OPTION_FOUND_ROWS ?
@@ -4882,6 +4883,9 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
recinfo->type=FIELD_NORMAL;
if (!--hidden_field_count)
null_count=(null_count+7) & ~7; // move to next byte
+
+ // fix table name in field entry
+ field->table_name= table->table_name;
}
param->copy_field_end=copy;
@@ -5845,7 +5849,8 @@ test_if_quick_select(JOIN_TAB *tab)
{
delete tab->select->quick;
tab->select->quick=0;
- return tab->select->test_quick_select(tab->keys,(table_map) 0,HA_POS_ERROR);
+ return tab->select->test_quick_select(tab->join->thd, tab->keys,
+ (table_map) 0, HA_POS_ERROR);
}
@@ -6949,7 +6954,8 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
For impossible ranges (like when doing a lookup on NULL on a NOT NULL
field, quick will contain an empty record set.
*/
- if (!(select->quick=get_ft_or_quick_select_for_ref(table, tab)))
+ if (!(select->quick=get_ft_or_quick_select_for_ref(tab->join->thd,
+ table, tab)))
goto err;
}
}
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index a026bd5276d..3be829acbda 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1073,7 +1073,7 @@ store_create_info(THD *thd, TABLE *table, String *packet)
MODE_ORACLE |
MODE_MSSQL |
MODE_DB2 |
- MODE_SAPDB |
+ MODE_MAXDB |
MODE_ANSI)) != 0;
my_bool limited_mysql_mode= (thd->variables.sql_mode &
(MODE_NO_FIELD_OPTIONS | MODE_MYSQL323 |
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 5112dfb59cd..7559f2a86e2 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -886,6 +886,11 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
key_info->name=(char*) key_name;
}
}
+ if (!key_info->name || check_column_name(key_info->name))
+ {
+ my_error(ER_WRONG_INDEX_NAME, MYF(0), key_info->name);
+ DBUG_RETURN(-1);
+ }
if (!(key_info->flags & HA_NULL_PART_KEY))
unique_key=1;
key_info->key_length=(uint16) key_length;
@@ -926,7 +931,10 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
&& find_temporary_table(thd,db,table_name))
{
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
+ {
+ create_info->table_existed= 1; // Mark that table existed
DBUG_RETURN(0);
+ }
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
DBUG_RETURN(-1);
}
@@ -938,14 +946,18 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
if (!access(path,F_OK))
{
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
+ {
+ create_info->table_existed= 1; // Mark that table existed
error= 0;
+ }
else
- my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
+ my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
goto end;
}
}
thd->proc_info="creating table";
+ create_info->table_existed= 0; // Mark that table is created
if (thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE)
create_info->data_file_name= create_info->index_file_name= 0;
@@ -2330,7 +2342,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (use_timestamp)
new_table->time_stamp=0;
new_table->next_number_field=new_table->found_next_number_field;
- thd->count_cuted_fields=1; // calc cuted fields
+ thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
thd->cuted_fields=0L;
thd->proc_info="copy to tmp table";
next_insert_id=thd->next_insert_id; // Remember for loggin
@@ -2340,7 +2352,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
handle_duplicates,
order_num, order, &copied, &deleted);
thd->last_insert_id=next_insert_id; // Needed for correct log
- thd->count_cuted_fields=0; // Don`t calc cuted fields
+ thd->count_cuted_fields= CHECK_FIELD_IGNORE;
new_table->time_stamp=save_time_stamp;
if (table->tmp_table)
@@ -2749,9 +2761,9 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
while (!t->file->rnd_next(t->record[0]))
{
ha_checksum row_crc= 0;
- if (t->record[0] != t->field[0]->ptr)
+ if (t->record[0] != (byte*) t->field[0]->ptr)
row_crc= my_checksum(row_crc, t->record[0],
- t->field[0]->ptr - t->record[0]);
+ ((byte*) t->field[0]->ptr) - t->record[0]);
for (uint i= 0; i < t->fields; i++ )
{
@@ -2760,10 +2772,11 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
{
String tmp;
f->val_str(&tmp,&tmp);
- row_crc= my_checksum(row_crc, tmp.ptr(), tmp.length());
+ row_crc= my_checksum(row_crc, (byte*) tmp.ptr(), tmp.length());
}
else
- row_crc= my_checksum(row_crc, f->ptr, f->pack_length());
+ row_crc= my_checksum(row_crc, (byte*) f->ptr,
+ f->pack_length());
}
crc+= row_crc;
diff --git a/sql/sql_test.cc b/sql/sql_test.cc
index 006a324f16d..d8d6d716abe 100644
--- a/sql/sql_test.cc
+++ b/sql/sql_test.cc
@@ -22,6 +22,7 @@
#include "sql_select.h"
#include <hash.h>
#include <thr_alarm.h>
+#include <malloc.h>
/* Intern key cache variables */
extern "C" pthread_mutex_t THR_LOCK_keycache;
@@ -301,6 +302,8 @@ void mysql_print_status(THD *thd)
printf("\nStatus information:\n\n");
my_getwd(current_dir, sizeof(current_dir),MYF(0));
printf("Current dir: %s\n", current_dir);
+ printf("Running threads: %d Stack size: %ld\n", thread_count,
+ (long) thread_stack);
if (thd)
thd->proc_info="locks";
thr_print_locks(); // Write some debug info
@@ -366,6 +369,34 @@ Next alarm time: %lu\n",
thd->proc_info="malloc";
my_checkmalloc();
TERMINATE(stdout); // Write malloc information
+
+#ifdef HAVE_MALLINFO
+ struct mallinfo info= mallinfo();
+ printf("\nMemory status:\n\
+Non-mmapped space allocated from system: %d\n\
+Number of free chunks: %d\n\
+Number of fastbin blocks: %d\n\
+Number of mmapped regions: %d\n\
+Space in mmapped regions: %d\n\
+Maximum total allocated space: %d\n\
+Space available in freed fastbin blocks: %d\n\
+Total allocated space: %d\n\
+Total free space: %d\n\
+Top-most, releasable space: %d\n\
+Estimated memory (with thread stack): %ld\n",
+ (int) info.arena ,
+ (int) info.ordblks,
+ (int) info.smblks,
+ (int) info.hblks,
+ (int) info.hblkhd,
+ (int) info.usmblks,
+ (int) info.fsmblks,
+ (int) info.uordblks,
+ (int) info.fordblks,
+ (int) info.keepcost,
+ (long) (thread_count * thread_stack + info.hblkhd + info.arena));
+#endif
+ puts("");
if (thd)
thd->proc_info=0;
}
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index c237b023e7b..337f2540a39 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -128,7 +128,7 @@ void udf_init()
my_rwlock_init(&THR_LOCK_udf,NULL);
- init_sql_alloc(&mem, 1024,0);
+ init_sql_alloc(&mem, UDF_ALLOC_BLOCK_SIZE, 0);
THD *new_thd = new THD;
if (!new_thd ||
hash_init(&udf_hash,system_charset_info,32,0,0,get_hash_key, NULL, 0))
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 4cf5f740d17..9214894e214 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -152,7 +152,7 @@ int mysql_update(THD *thd,
table->used_keys.clear_all();
select=make_select(table,0,0,conds,&error);
if (error ||
- (select && select->check_quick(safe_update, limit)) || !limit)
+ (select && select->check_quick(thd, safe_update, limit)) || !limit)
{
delete select;
free_underlaid_joins(thd, &thd->lex.select_lex);
@@ -295,7 +295,7 @@ int mysql_update(THD *thd,
init_read_record(&info,thd,table,select,0,1);
updated= found= 0;
- thd->count_cuted_fields=1; /* calc cuted fields */
+ thd->count_cuted_fields= CHECK_FIELD_WARN; /* calc cuted fields */
thd->cuted_fields=0L;
thd->proc_info="Updating";
query_id=thd->query_id;
@@ -386,7 +386,7 @@ int mysql_update(THD *thd,
thd->insert_id_used ? thd->insert_id() : 0L,buff);
DBUG_PRINT("info",("%d records updated",updated));
}
- thd->count_cuted_fields=0; /* calc cuted fields */
+ thd->count_cuted_fields= CHECK_FIELD_IGNORE; /* calc cuted fields */
free_io_cache(table);
DBUG_RETURN(0);
@@ -492,7 +492,7 @@ int multi_update::prepare(List<Item> &not_used_values, SELECT_LEX_UNIT *unit)
uint i, max_fields;
DBUG_ENTER("multi_update::prepare");
- thd->count_cuted_fields=1;
+ thd->count_cuted_fields= CHECK_FIELD_WARN;
thd->cuted_fields=0L;
thd->proc_info="updating main table";
@@ -732,7 +732,7 @@ multi_update::~multi_update()
}
if (copy_field)
delete [] copy_field;
- thd->count_cuted_fields=0; // Restore this setting
+ thd->count_cuted_fields= CHECK_FIELD_IGNORE; // Restore this setting
if (!trans_safe)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
}
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index f7cd22545c5..04f5043839f 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -78,6 +78,7 @@ inline Item *or_or_concat(THD *thd, Item* A, Item* B)
CHARSET_INFO *charset;
thr_lock_type lock_type;
interval_type interval;
+ datetime_format_types datetime_format_type;
st_select_lex *select_lex;
chooser_compare_func_creator boolfunc2creator;
}
@@ -482,6 +483,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token GEOMETRYCOLLECTION
%token GROUP_CONCAT_SYM
%token GROUP_UNIQUE_USERS
+%token GET_FORMAT
%token HOUR_MICROSECOND_SYM
%token HOUR_MINUTE_SYM
%token HOUR_SECOND_SYM
@@ -644,6 +646,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
UDF_CHAR_FUNC UDF_FLOAT_FUNC UDF_INT_FUNC
UDA_CHAR_SUM UDA_FLOAT_SUM UDA_INT_SUM
+%type <datetime_format_type> datetime_format_type;
%type <interval> interval
%type <db_type> table_types
@@ -1254,7 +1257,7 @@ type:
| TIME_SYM { $$=FIELD_TYPE_TIME; }
| TIMESTAMP
{
- if (YYTHD->variables.sql_mode & MODE_SAPDB)
+ if (YYTHD->variables.sql_mode & MODE_MAXDB)
$$=FIELD_TYPE_DATETIME;
else
$$=FIELD_TYPE_TIMESTAMP;
@@ -2583,6 +2586,8 @@ simple_expr:
{ $$= new Item_func_spatial_collection(* $3,
Geometry::wkbGeometryCollection,
Geometry::wkbPoint); }
+ | GET_FORMAT '(' datetime_format_type ',' expr ')'
+ { $$= new Item_func_get_format($3, $5); }
| HOUR_SYM '(' expr ')'
{ $$= new Item_func_hour($3); }
| IF '(' expr ',' expr ',' expr ')'
@@ -3196,6 +3201,11 @@ interval:
| YEAR_MONTH_SYM { $$=INTERVAL_YEAR_MONTH; }
| YEAR_SYM { $$=INTERVAL_YEAR; };
+datetime_format_type:
+ DATE_SYM {$$=DATE_FORMAT_TYPE;}
+ | TIME_SYM {$$=TIME_FORMAT_TYPE;}
+ | DATETIME {$$=DATETIME_FORMAT_TYPE;};
+
table_alias:
/* empty */
| AS
@@ -4543,6 +4553,7 @@ keyword:
| FLUSH_SYM {}
| GEOMETRY_SYM {}
| GEOMETRYCOLLECTION {}
+ | GET_FORMAT {}
| GRANTS {}
| GLOBAL_SYM {}
| HANDLER_SYM {}
diff --git a/sql/structs.h b/sql/structs.h
index 05ebdba7a37..d9be230c049 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -24,6 +24,11 @@ typedef struct st_date_format { /* How to print date */
uint pos[6]; /* Positions to YY.MM.DD HH:MM:SS */
} DATE_FORMAT;
+typedef struct st_datetime_format {
+ byte dt_pos[8];
+ char *format;
+ uint format_length;
+} DATETIME_FORMAT;
typedef struct st_keyfile_info { /* used with ha_info() */
byte ref[MAX_REFLENGTH]; /* Pointer to current row */
@@ -110,8 +115,8 @@ typedef struct st_read_record { /* Parameter to read_record */
bool print_error, ignore_not_found_rows;
} READ_RECORD;
-enum timestamp_type { TIMESTAMP_NONE, TIMESTAMP_DATE, TIMESTAMP_FULL,
- TIMESTAMP_TIME };
+enum timestamp_type { TIMESTAMP_NONE, WRONG_TIMESTAMP_FULL, TIMESTAMP_DATE, TIMESTAMP_FULL,
+ TIMESTAMP_TIME};
typedef struct st_time {
uint year,month,day,hour,minute,second;
diff --git a/sql/table.cc b/sql/table.cc
index 0281046f6a0..24c5b941c0b 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -90,7 +90,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
outparam->db_stat = db_stat;
error=1;
- init_sql_alloc(&outparam->mem_root,1024,0);
+ init_sql_alloc(&outparam->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
MEM_ROOT *old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC);
my_pthread_setspecific_ptr(THR_MALLOC,&outparam->mem_root);
diff --git a/sql/time.cc b/sql/time.cc
index 70ae8dcd8ed..f2e41afa560 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -27,6 +27,10 @@ uchar *days_in_month= (uchar*) "\037\034\037\036\037\036\037\037\036\037\036\037
/* Init some variabels needed when using my_local_time */
/* Currently only my_time_zone is inited */
+bool parse_datetime_formats(datetime_format_types format_type,
+ const char *format_str, uint format_length,
+ byte *dt_pos);
+
static long my_time_zone=0;
void init_time(void)
@@ -316,10 +320,12 @@ ulong convert_month_to_period(ulong month)
*/
timestamp_type
-str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
+str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date,THD *thd)
{
- uint field_length,year_length,digits,i,number_of_fields,date[7];
+ uint field_length= 0, year_length= 0, digits, i, number_of_fields;
+ uint date[7], date_len[7];
uint not_zero_date;
+ bool is_internal_format= 0;
const char *pos;
const char *end=str+length;
bool found_delimitier= 0;
@@ -336,24 +342,32 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
(YYYY-MM-DD, YYYYMMDD, YYYYYMMDDHHMMSS)
*/
for (pos=str; pos != end && my_isdigit(&my_charset_latin1,*pos) ; pos++) ;
+ /* Check for internal format */
digits= (uint) (pos-str);
- year_length= (digits == 4 || digits == 8 || digits >= 14) ? 4 : 2;
- field_length=year_length-1;
+
+ if (pos == end || digits>=12)
+ {
+ is_internal_format= 1;
+ year_length= (digits == 4 || digits == 8 || digits >= 14) ? 4 : 2;
+ field_length=year_length-1;
+ date_len[0]= year_length;
+ }
not_zero_date= 0;
for (i=0 ; i < 6 && str != end && my_isdigit(&my_charset_latin1,*str) ; i++)
{
+ if (!is_internal_format)
+ date_len[i]= 1;
uint tmp_value=(uint) (uchar) (*str++ - '0');
- while (str != end && my_isdigit(&my_charset_latin1,str[0]) &&
- field_length--)
+ while (str != end && my_isdigit(&my_charset_latin1,str[0])
+ && (is_internal_format && field_length-- || !is_internal_format) )
{
tmp_value=tmp_value*10 + (uint) (uchar) (*str - '0');
str++;
+ if (!is_internal_format)
+ date_len[i]+= 1;
}
- if (found_delimitier && (int) field_length < 0)
- {
- /* The number can't match any valid date or datetime string */
+ if (i == 2 && *str == '.')
DBUG_RETURN(TIMESTAMP_NONE);
- }
date[i]=tmp_value;
not_zero_date|= tmp_value;
if (i == 2 && str != end && *str == 'T')
@@ -371,7 +385,8 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
found_delimitier=1; // Should be a 'normal' date
}
}
- field_length=1; // Rest fields can only be 2
+ if (is_internal_format)
+ field_length=1; // Rest fields can only be 2
}
/* Handle second fractions */
if (i == 6 && (uint) (end-str) >= 2 && *str == '.' &&
@@ -389,14 +404,69 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
else
date[6]=0;
- if (year_length == 2 && i >=2 && (date[1] || date[2]))
- date[0]+= (date[0] < YY_PART_YEAR ? 2000 : 1900);
+ while (str != end && (my_ispunct(&my_charset_latin1,*str) ||
+ my_isspace(&my_charset_latin1,*str)))
+ str++;
+
+ uint add_hours= 0;
+ if (!my_strnncoll(&my_charset_latin1,
+ (const uchar *)str, 2,
+ (const uchar *)"PM", 2))
+ add_hours= 12;
+
number_of_fields=i;
while (i < 6)
date[i++]=0;
- if (number_of_fields < 3 || date[1] > 12 ||
- date[2] > 31 || date[3] > 23 || date[4] > 59 || date[5] > 59 ||
- (!fuzzy_date && (date[1] == 0 || date[2] == 0)))
+
+ if (!is_internal_format)
+ {
+ byte *frm_pos;
+
+ if (number_of_fields <= 3)
+ {
+ frm_pos= t_datetime_frm(thd, DATE_FORMAT_TYPE).datetime_format.dt_pos;
+ l_time->hour= 0;
+ l_time->minute= 0;
+ l_time->second= 0;
+ }
+ else
+ {
+ frm_pos= t_datetime_frm(thd, DATETIME_FORMAT_TYPE).datetime_format.dt_pos;
+ l_time->hour= date[(int) frm_pos[3]];
+ l_time->minute=date[(int) frm_pos[4]];
+ l_time->second=date[(int) frm_pos[5]];
+ if (frm_pos[6] == 1)
+ {
+ if (l_time->hour > 12)
+ DBUG_RETURN(WRONG_TIMESTAMP_FULL);
+ l_time->hour= l_time->hour%12 + add_hours;
+ }
+ }
+
+ l_time->year= date[(int) frm_pos[0]];
+ l_time->month= date[(int) frm_pos[1]];
+ l_time->day= date[(int) frm_pos[2]];
+ year_length= date_len[(int) frm_pos[0]];
+ }
+ else
+ {
+ l_time->year= date[0];
+ l_time->month= date[1];
+ l_time->day= date[2];
+ l_time->hour= date[3];
+ l_time->minute=date[4];
+ l_time->second=date[5];
+ }
+ l_time->second_part=date[6];
+ l_time->neg= 0;
+ if (year_length == 2 && i >=2 && (l_time->month || l_time->day))
+ l_time->year+= (l_time->year < YY_PART_YEAR ? 2000 : 1900);
+
+
+ if (number_of_fields < 3 || l_time->month > 12 ||
+ l_time->day > 31 || l_time->hour > 23 ||
+ l_time->minute > 59 || l_time->second > 59 ||
+ (!fuzzy_date && (l_time->month == 0 || l_time->day == 0)))
{
/* Only give warning for a zero date if there is some garbage after */
if (!not_zero_date) // If zero date
@@ -411,53 +481,46 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
}
}
if (not_zero_date)
- current_thd->cuted_fields++;
- DBUG_RETURN(TIMESTAMP_NONE);
+ thd->cuted_fields++;
+ DBUG_RETURN(WRONG_TIMESTAMP_FULL);
}
- if (str != end && current_thd->count_cuted_fields)
+ if (str != end && thd->count_cuted_fields)
{
for (; str != end ; str++)
{
if (!my_isspace(&my_charset_latin1,*str))
{
- current_thd->cuted_fields++;
+ thd->cuted_fields++;
break;
}
}
}
- l_time->year= date[0];
- l_time->month= date[1];
- l_time->day= date[2];
- l_time->hour= date[3];
- 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));
}
-time_t str_to_timestamp(const char *str,uint length)
+time_t str_to_timestamp(const char *str,uint length, THD *thd)
{
TIME l_time;
long not_used;
- if (str_to_TIME(str,length,&l_time,0) == TIMESTAMP_NONE)
+ if (str_to_TIME(str,length,&l_time,0,thd) <= WRONG_TIMESTAMP_FULL)
return(0);
if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR)
{
- current_thd->cuted_fields++;
+ thd->cuted_fields++;
return(0);
}
return(my_gmt_sec(&l_time, &not_used));
}
-longlong str_to_datetime(const char *str,uint length,bool fuzzy_date)
+longlong str_to_datetime(const char *str,uint length,bool fuzzy_date, THD *thd)
{
TIME l_time;
- if (str_to_TIME(str,length,&l_time,fuzzy_date) == TIMESTAMP_NONE)
+ if (str_to_TIME(str,length,&l_time,fuzzy_date,thd) <= WRONG_TIMESTAMP_FULL)
return(0);
return (longlong) (l_time.year*LL(10000000000) +
l_time.month*LL(100000000)+
@@ -484,12 +547,13 @@ longlong str_to_datetime(const char *str,uint length,bool fuzzy_date)
1 error
*/
-bool str_to_time(const char *str,uint length,TIME *l_time)
+bool str_to_time(const char *str,uint length,TIME *l_time, THD *thd)
{
long date[5],value;
const char *end=str+length;
bool found_days,found_hours;
uint state;
+ byte *frm_pos= t_datetime_frm(thd, TIME_FORMAT_TYPE).datetime_format.dt_pos;
l_time->neg=0;
for (; str != end &&
@@ -507,8 +571,11 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
/* Check first if this is a full TIMESTAMP */
if (length >= 12)
{ // Probably full timestamp
- if (str_to_TIME(str,length,l_time,1) == TIMESTAMP_FULL)
- return 0; // Was an ok timestamp
+ enum timestamp_type tres= str_to_TIME(str,length,l_time,1,thd);
+ if (tres == TIMESTAMP_FULL)
+ return 0;
+ else if (tres == WRONG_TIMESTAMP_FULL)
+ return 1;
}
/* Not a timestamp. Try to get this as a DAYS_TO_SECOND string */
@@ -533,7 +600,7 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
found_days=1;
str++; // Skip space;
}
- else if ((end-str) > 1 && *str == ':' &&
+ else if ((end-str) > 1 && *str == frm_pos[7] &&
my_isdigit(&my_charset_latin1,str[1]))
{
date[0]=0; // Assume we found hours
@@ -559,8 +626,8 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
for (value=0; str != end && my_isdigit(&my_charset_latin1,*str) ; str++)
value=value*10L + (long) (*str - '0');
date[state++]=value;
- if (state == 4 || (end-str) < 2 || *str != ':' ||
- !my_isdigit(&my_charset_latin1,str[1]))
+ if (state == 4 || (end-str) < 2 || *str != frm_pos[7] ||
+ !my_isdigit(&my_charset_latin1,str[1]))
break;
str++; // Skip ':'
}
@@ -577,7 +644,6 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
else
bzero((char*) (date+state), sizeof(long)*(4-state));
}
-
fractional:
/* Get fractional second part */
if ((end-str) >= 2 && *str == '.' && my_isdigit(&my_charset_latin1,str[1]))
@@ -593,6 +659,20 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
else
date[4]=0;
+ while (str != end && !my_isalpha(&my_charset_latin1,*str))
+ str++;
+
+ if ( (end-str)>= 2 &&
+ !my_strnncoll(&my_charset_latin1,
+ (const uchar *)str, 2,
+ (const uchar *)"PM", 2) &&
+ frm_pos[6] == 1)
+ {
+ uint days_i= date[1]/24;
+ uint hours_i= date[1]%24;
+ date[1]= hours_i%12 + 12 + 24*days_i;
+ }
+
/* Some simple checks */
if (date[2] >= 60 || date[3] >= 60)
{
@@ -601,9 +681,9 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
}
l_time->month=0;
l_time->day=date[0];
- l_time->hour=date[1];
- l_time->minute=date[2];
- l_time->second=date[3];
+ l_time->hour=date[frm_pos[3] + 1];
+ l_time->minute=date[frm_pos[4] + 1];
+ l_time->second=date[frm_pos[5] + 1];
l_time->second_part=date[4];
l_time->time_type= TIMESTAMP_TIME;
@@ -648,3 +728,165 @@ void calc_time_from_sec(TIME *to, long seconds, long microseconds)
to->second= t_seconds%60L;
to->second_part= microseconds;
}
+
+
+DATETIME_FORMAT *make_format(DATETIME_FORMAT *datetime_format,
+ datetime_format_types format_type,
+ const char *format_str,
+ uint format_length, bool is_alloc)
+{
+ if (format_length &&
+ !parse_datetime_formats(format_type, format_str,
+ format_length,
+ datetime_format->dt_pos))
+ {
+ if (is_alloc)
+ {
+ if (!(datetime_format->format= my_strdup_with_length(format_str,
+ format_length,
+ MYF(0))))
+ return 0;
+ }
+ else
+ datetime_format->format= (char *) format_str;
+ datetime_format->format_length= format_length;
+ return datetime_format;
+ }
+ return 0;
+}
+
+
+bool parse_datetime_formats(datetime_format_types format_type,
+ const char *format_str, uint format_length,
+ byte *dt_pos)
+{
+ uint pos= 0;
+ dt_pos[0]= dt_pos[1]= dt_pos[2]= dt_pos[3]=
+ dt_pos[4]= dt_pos[5]= dt_pos[6]= dt_pos[7]= -1;
+
+ const char *ptr=format_str;
+ const char *end=ptr+format_length;
+ bool need_p= 0;
+
+ for (; ptr != end; ptr++)
+ {
+ if (*ptr == '%' && ptr+1 != end)
+ {
+ switch (*++ptr) {
+ case 'y':
+ case 'Y':
+ if (dt_pos[0] > -1)
+ return 1;
+ dt_pos[0]= pos;
+ break;
+ case 'c':
+ case 'm':
+ if (dt_pos[1] > -1)
+ return 1;
+ dt_pos[1]= pos;
+ break;
+ case 'd':
+ case 'e':
+ if (dt_pos[2] > -1)
+ return 1;
+ dt_pos[2]= pos;
+ break;
+ case 'H':
+ case 'k':
+ case 'h':
+ case 'I':
+ case 'l':
+ if (dt_pos[3] > -1)
+ return 1;
+ dt_pos[3]= pos;
+ need_p= (*ptr == 'h' || *ptr == 'l' || *ptr == 'I');
+ break;
+ case 'i':
+ if (dt_pos[4] > -1)
+ return 1;
+ dt_pos[4]= pos;
+ break;
+ case 's':
+ case 'S':
+ if (dt_pos[5] > -1)
+ return 1;
+ dt_pos[5]= pos;
+ break;
+ case 'p':
+ if (dt_pos[6] > -1)
+ return 1;
+ /* %p should be last in format string */
+ if (format_type == DATE_FORMAT_TYPE ||
+ (pos != 6 && format_type == DATETIME_FORMAT_TYPE) ||
+ (pos != 3 && format_type == TIME_FORMAT_TYPE))
+ return 1;
+ dt_pos[6]= 1;
+ break;
+ default:
+ return 1;
+ }
+ if (dt_pos[6] == -1)
+ pos++;
+ }
+ }
+
+ if (pos > 5 && format_type == DATETIME_FORMAT_TYPE &&
+ (dt_pos[0] + dt_pos[1] + dt_pos[2] +
+ dt_pos[3] + dt_pos[4] + dt_pos[5] != 15) ||
+ pos > 2 && format_type == DATE_FORMAT_TYPE &&
+ (dt_pos[0] + dt_pos[1] + dt_pos[2] != 3) ||
+ pos > 2 && format_type == TIME_FORMAT_TYPE &&
+ (dt_pos[3] + dt_pos[4] + dt_pos[5] != 3) ||
+ (need_p && dt_pos[6] != 1))
+ return 1;
+
+ /*
+ Check for valid separators between date/time parst
+ */
+ uint tmp_len= format_length;
+ if (dt_pos[6] == 1)
+ {
+ end= end - 2;
+ if (my_ispunct(&my_charset_latin1, *end) || my_isspace(&my_charset_latin1, *end))
+ end--;
+ tmp_len= end - format_str;
+ }
+ switch (format_type) {
+ case DATE_FORMAT_TYPE:
+ case TIME_FORMAT_TYPE:
+ if ((tmp_len == 6 &&
+ !my_strnncoll(&my_charset_bin,
+ (const uchar *) format_str, 6,
+ (const uchar *) datetime_formats
+ [format_type][INTERNAL_FORMAT], 6)) ||
+ tmp_len == 8 &&
+ my_ispunct(&my_charset_latin1, *(format_str+2)) &&
+ my_ispunct(&my_charset_latin1, *(format_str+5)))
+ {
+ if (format_type == TIME_FORMAT_TYPE && tmp_len == 8)
+ {
+ if (*(format_str+2) != *(format_str+5))
+ return 1;
+ dt_pos[7]= *(format_str+2);
+ }
+ return 0;
+ }
+ break;
+ case DATETIME_FORMAT_TYPE:
+ if ((tmp_len == 12 &&
+ !my_strnncoll(&my_charset_bin,
+ (const uchar *) format_str, 12,
+ (const uchar *) datetime_formats
+ [DATETIME_FORMAT_TYPE][INTERNAL_FORMAT], 12)) ||
+ tmp_len == 17 &&
+ my_ispunct(&my_charset_latin1, *(format_str+2)) &&
+ my_ispunct(&my_charset_latin1, *(format_str+5)) &&
+ my_ispunct(&my_charset_latin1, *(format_str+11)) &&
+ my_ispunct(&my_charset_latin1, *(format_str+14)) &&
+ (my_ispunct(&my_charset_latin1, *(format_str+8)) ||
+ my_isspace(&my_charset_latin1, *(format_str+8))))
+ return 0;
+ break;
+ }
+ return 1;
+}
diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c
index cd1b1399506..5a785552b45 100644
--- a/strings/ctype-bin.c
+++ b/strings/ctype-bin.c
@@ -270,9 +270,9 @@ static int my_strnxfrm_bin(CHARSET_INFO *cs __attribute__((unused)),
static
uint my_instr_bin(CHARSET_INFO *cs __attribute__((unused)),
- const char *big, uint b_length,
- const char *small, uint s_length,
- my_match_t *match, uint nmatch)
+ const char *b, uint b_length,
+ const char *s, uint s_length,
+ my_match_t *match, uint nmatch)
{
register const uchar *str, *search, *end, *search_end;
@@ -289,10 +289,10 @@ uint my_instr_bin(CHARSET_INFO *cs __attribute__((unused)),
return 1; /* Empty string is always found */
}
- str= (const uchar*) big;
- search= (const uchar*) small;
- end= (const uchar*) big+b_length-s_length+1;
- search_end= (const uchar*) small + s_length;
+ str= (const uchar*) b;
+ search= (const uchar*) s;
+ end= (const uchar*) b+b_length-s_length+1;
+ search_end= (const uchar*) s + s_length;
skipp:
while (str != end)
@@ -311,7 +311,7 @@ skipp:
if (nmatch > 0)
{
match[0].beg= 0;
- match[0].end= str- (const uchar*)big-1;
+ match[0].end= str- (const uchar*)b-1;
match[0].mblen= match[0].end;
if (nmatch > 1)
diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c
index 813a33fd229..271c56b8a0a 100644
--- a/strings/ctype-mb.c
+++ b/strings/ctype-mb.c
@@ -275,11 +275,11 @@ uint my_charpos_mb(CHARSET_INFO *cs __attribute__((unused)),
}
uint my_instr_mb(CHARSET_INFO *cs,
- const char *big, uint b_length,
- const char *small, uint s_length,
+ const char *b, uint b_length,
+ const char *s, uint s_length,
my_match_t *match, uint nmatch)
{
- register const char *end, *big0;
+ register const char *end, *b0;
int res= 0;
if (s_length <= b_length)
@@ -295,20 +295,20 @@ uint my_instr_mb(CHARSET_INFO *cs,
return 1; /* Empty string is always found */
}
- big0= big;
- end= big+b_length-s_length+1;
+ b0= b;
+ end= b+b_length-s_length+1;
- while (big < end)
+ while (b < end)
{
int mblen;
- if (!cs->coll->strnncoll(cs, (unsigned char*) big, s_length,
- (unsigned char*) small, s_length))
+ if (!cs->coll->strnncoll(cs, (unsigned char*) b, s_length,
+ (unsigned char*) s, s_length))
{
if (nmatch)
{
match[0].beg= 0;
- match[0].end= big-big0;
+ match[0].end= b-b0;
match[0].mblen= res;
if (nmatch > 1)
{
@@ -319,8 +319,8 @@ uint my_instr_mb(CHARSET_INFO *cs,
}
return 2;
}
- mblen= (mblen= my_ismbchar(cs, big, end)) ? mblen : 1;
- big+= mblen;
+ mblen= (mblen= my_ismbchar(cs, b, end)) ? mblen : 1;
+ b+= mblen;
b_length-= mblen;
res++;
}
diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c
index ed1d2c77049..6f77d6f3e16 100644
--- a/strings/ctype-simple.c
+++ b/strings/ctype-simple.c
@@ -1031,8 +1031,8 @@ uint my_lengthsp_8bit(CHARSET_INFO *cs __attribute__((unused)),
uint my_instr_simple(CHARSET_INFO *cs,
- const char *big, uint b_length,
- const char *small, uint s_length,
+ const char *b, uint b_length,
+ const char *s, uint s_length,
my_match_t *match, uint nmatch)
{
register const uchar *str, *search, *end, *search_end;
@@ -1050,10 +1050,10 @@ uint my_instr_simple(CHARSET_INFO *cs,
return 1; /* Empty string is always found */
}
- str= (const uchar*) big;
- search= (const uchar*) small;
- end= (const uchar*) big+b_length-s_length+1;
- search_end= (const uchar*) small + s_length;
+ str= (const uchar*) b;
+ search= (const uchar*) s;
+ end= (const uchar*) b+b_length-s_length+1;
+ search_end= (const uchar*) s + s_length;
skipp:
while (str != end)
@@ -1072,7 +1072,7 @@ skipp:
if (nmatch > 0)
{
match[0].beg= 0;
- match[0].end= str- (const uchar*)big-1;
+ match[0].end= str- (const uchar*)b-1;
match[0].mblen= match[0].end;
if (nmatch > 1)