summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bzrignore16
-rw-r--r--BUILD/FINISH.sh8
-rwxr-xr-xBUILD/cleanup8
-rw-r--r--[-rwxr-xr-x]INSTALL-WIN-SOURCE0
-rw-r--r--client/mysqladmin.c9
-rw-r--r--client/mysqldump.c8
-rw-r--r--include/errmsg.h1
-rw-r--r--include/my_pthread.h1
-rw-r--r--include/my_sys.h9
-rw-r--r--include/myisam.h2
-rw-r--r--include/mysql.h14
-rw-r--r--include/mysql_com.h60
-rw-r--r--include/mysqld_error.h6
-rw-r--r--include/thr_alarm.h2
-rw-r--r--innobase/row/row0sel.c33
-rw-r--r--isam/isamchk.c2
-rw-r--r--isam/isamdef.h1
-rw-r--r--isam/open.c19
-rw-r--r--isam/pack_isam.c2
-rw-r--r--libmysql/errmsg.c9
-rw-r--r--libmysql/libmysql.c61
-rw-r--r--libmysqld/lib_sql.cc26
-rw-r--r--libmysqld/libmysqld.c20
-rw-r--r--myisam/mi_checksum.c19
-rw-r--r--mysql-test/Makefile.am12
-rw-r--r--mysql-test/r/connect.result1
-rw-r--r--mysql-test/r/create.result49
-rw-r--r--mysql-test/r/derived.result8
-rw-r--r--mysql-test/r/drop.result10
-rw-r--r--mysql-test/r/func_crypt.result88
-rw-r--r--mysql-test/r/func_gconcat.result18
-rw-r--r--mysql-test/r/innodb.result49
-rw-r--r--mysql-test/r/isam.result8
-rw-r--r--mysql-test/r/myisam.result23
-rw-r--r--mysql-test/r/olap.result15
-rw-r--r--mysql-test/r/rpl000015.result14
-rw-r--r--mysql-test/r/rpl_empty_master_crash.result2
-rw-r--r--mysql-test/r/rpl_error_ignored_table.result4
-rw-r--r--mysql-test/r/rpl_flush_log_loop.result4
-rw-r--r--mysql-test/r/rpl_loaddata.result12
-rw-r--r--mysql-test/r/rpl_log.result4
-rw-r--r--mysql-test/r/rpl_log_pos.result16
-rw-r--r--mysql-test/r/rpl_max_relay_size.result24
-rw-r--r--mysql-test/r/rpl_openssl.result30
-rw-r--r--mysql-test/r/rpl_redirect.result2
-rw-r--r--mysql-test/r/rpl_replicate_do.result4
-rw-r--r--mysql-test/r/rpl_reset_slave.result16
-rw-r--r--mysql-test/r/rpl_rotate_logs.result12
-rw-r--r--mysql-test/r/show_check.result2
-rw-r--r--mysql-test/r/subselect.result31
-rw-r--r--mysql-test/r/symlink.result2
-rw-r--r--mysql-test/r/union.result2
-rw-r--r--mysql-test/t/connect.test5
-rw-r--r--mysql-test/t/create.test40
-rw-r--r--mysql-test/t/derived.test13
-rw-r--r--mysql-test/t/drop.test10
-rw-r--r--mysql-test/t/func_crypt.test34
-rw-r--r--mysql-test/t/func_gconcat.test21
-rw-r--r--mysql-test/t/innodb.test41
-rw-r--r--mysql-test/t/loaddata.test4
-rw-r--r--mysql-test/t/myisam.test13
-rw-r--r--mysql-test/t/olap.test11
-rw-r--r--mysql-test/t/rpl_openssl.test60
-rw-r--r--mysql-test/t/subselect.test33
-rw-r--r--mysys/Makefile.am2
-rw-r--r--mysys/checksum.c23
-rw-r--r--mysys/my_crc32.c36
-rw-r--r--mysys/my_malloc.c34
-rw-r--r--mysys/my_realloc.c33
-rw-r--r--scripts/mysql_config.sh4
-rw-r--r--scripts/mysql_create_system_tables.sh2
-rw-r--r--scripts/mysql_fix_privilege_tables.sql14
-rw-r--r--sql-common/client.c176
-rw-r--r--sql/field.h29
-rw-r--r--sql/ha_myisam.cc8
-rw-r--r--sql/ha_myisam.h1
-rw-r--r--sql/handler.cc3
-rw-r--r--sql/handler.h71
-rw-r--r--sql/item.cc98
-rw-r--r--sql/item.h16
-rw-r--r--sql/item_cmpfunc.cc38
-rw-r--r--sql/item_cmpfunc.h37
-rw-r--r--sql/item_create.cc33
-rw-r--r--sql/item_create.h4
-rw-r--r--sql/item_func.cc59
-rw-r--r--sql/item_func.h24
-rw-r--r--sql/item_geofunc.h24
-rw-r--r--sql/item_strfunc.cc142
-rw-r--r--sql/item_strfunc.h80
-rw-r--r--sql/item_subselect.cc36
-rw-r--r--sql/item_subselect.h2
-rw-r--r--sql/item_sum.cc41
-rw-r--r--sql/item_sum.h33
-rw-r--r--sql/item_timefunc.h11
-rw-r--r--sql/item_uniq.h2
-rw-r--r--sql/lex.h10
-rw-r--r--sql/mysql_priv.h7
-rw-r--r--sql/mysqld.cc74
-rw-r--r--sql/password.c824
-rw-r--r--sql/protocol.cc27
-rw-r--r--sql/protocol.h1
-rw-r--r--sql/repl_failsafe.cc11
-rw-r--r--sql/set_var.cc6
-rw-r--r--sql/set_var.h3
-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.cc162
-rw-r--r--sql/slave.h14
-rw-r--r--sql/sql_acl.cc615
-rw-r--r--sql/sql_acl.h13
-rw-r--r--sql/sql_class.cc1
-rw-r--r--sql/sql_class.h11
-rw-r--r--sql/sql_crypt.cc2
-rw-r--r--sql/sql_derived.cc2
-rw-r--r--sql/sql_insert.cc4
-rw-r--r--sql/sql_lex.cc1
-rw-r--r--sql/sql_lex.h36
-rw-r--r--sql/sql_load.cc30
-rw-r--r--sql/sql_parse.cc650
-rw-r--r--sql/sql_prepare.cc22
-rw-r--r--sql/sql_repl.cc19
-rw-r--r--sql/sql_select.cc80
-rw-r--r--sql/sql_select.h1
-rw-r--r--sql/sql_show.cc6
-rw-r--r--sql/sql_table.cc129
-rw-r--r--sql/sql_udf.cc11
-rw-r--r--sql/sql_udf.h25
-rw-r--r--sql/sql_union.cc45
-rw-r--r--sql/sql_yacc.yy146
-rw-r--r--sql/table.cc7
-rw-r--r--sql/udf_example.cc25
-rw-r--r--tests/client_test.c168
153 files changed, 3332 insertions, 2101 deletions
diff --git a/.bzrignore b/.bzrignore
index 35db3c5d5ba..e4317a564a9 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -23,6 +23,7 @@
.vimrc
50
=6
+BUILD/compile-pentium-maintainer
BitKeeper/etc/config
BitKeeper/etc/csets
BitKeeper/etc/csets-in
@@ -30,6 +31,8 @@ BitKeeper/etc/csets-out
BitKeeper/etc/gone
BitKeeper/etc/level
BitKeeper/etc/pushed
+BitKeeper/post-commit
+BitKeeper/post-commit-manual
BitKeeper/tmp/*
BitKeeper/tmp/bkr3sAHD
BitKeeper/tmp/gone
@@ -223,6 +226,7 @@ bkpull.log.5
bkpull.log.6
bkpush.log
build.log
+build_tags.sh
client/insert_test
client/log_event.cc
client/log_event.h
@@ -311,6 +315,8 @@ libmysql_r/conf_to_src
libmysql_r/my_static.h
libmysql_r/mysys_priv.h
libmysqld/backup_dir
+libmysqld/client.c
+libmysqld/client_settings.h
libmysqld/convert.cc
libmysqld/derror.cc
libmysqld/errmsg.c
@@ -355,6 +361,7 @@ libmysqld/item_sum.cc
libmysqld/item_timefunc.cc
libmysqld/item_uniq.cc
libmysqld/key.cc
+libmysqld/libmysql.c
libmysqld/lock.cc
libmysqld/log.cc
libmysqld/log_event.cc
@@ -366,6 +373,7 @@ libmysqld/net_serv.cc
libmysqld/opt_ft.cc
libmysqld/opt_range.cc
libmysqld/opt_sum.cc
+libmysqld/pack.c
libmysqld/password.c
libmysqld/procedure.cc
libmysqld/protocol.cc
@@ -473,6 +481,7 @@ mysql-test/r/rpl_log.eval
mysql-test/r/slave-running.eval
mysql-test/r/slave-stopped.eval
mysql-test/share/mysql
+mysql-test/std_data/*.pem
mysql-test/var/*
mysql.kdevprj
mysql.proj
@@ -482,6 +491,7 @@ mysys/#mf_iocache.c#
mysys/charset2html
mysys/getopt.c
mysys/getopt1.c
+mysys/main.cc
mysys/ste5KbMa
mysys/test_charset
mysys/test_dir
@@ -585,6 +595,7 @@ stamp-h1
stamp-h2
stamp-h3
stamp-h4
+start_mysqld.sh
strings/conf_to_src
strings/ctype_autoconf.c
strings/ctype_extra_sources.c
@@ -611,6 +622,7 @@ support-files/mysql.spec
tags
test_xml
tests/client_test
+tests/connect_test
thread_test
tmp/*
tools/my_vsnprintf.c
@@ -622,7 +634,3 @@ vio/test-ssl
vio/test-sslclient
vio/test-sslserver
vio/viotest-ssl
-libmysqld/client.c
-libmysqld/client_settings.h
-libmysqld/libmysql.c
-libmysqld/pack.c
diff --git a/BUILD/FINISH.sh b/BUILD/FINISH.sh
index 32a4efefdfb..72188b9c24b 100644
--- a/BUILD/FINISH.sh
+++ b/BUILD/FINISH.sh
@@ -23,12 +23,16 @@ autoconf || (echo \"Can't execute autoconf\" && exit 1)
if [ -d gemini ]
then
(cd gemini && aclocal && autoheader && aclocal && automake && autoconf)
-fi
+fi"
+if [ -z "$just_clean" ]
+then
+commands="$commands
CFLAGS=\"$cflags\" CXX=\"$CXX\" CXXFLAGS=\"$cxxflags\" CXXLDFLAGS=\"$CXXLDFLAGS\" \
$configure"
+fi
-if [ -z "$just_configure" ]
+if [ -z "$just_configure" -a -z "$just_clean" ]
then
commands="$commands
diff --git a/BUILD/cleanup b/BUILD/cleanup
new file mode 100755
index 00000000000..518c5722d87
--- /dev/null
+++ b/BUILD/cleanup
@@ -0,0 +1,8 @@
+#! /bin/sh
+
+path=`dirname $0`
+. "$path/SETUP.sh"
+
+just_clean=1;
+
+. "$path/FINISH.sh"
diff --git a/INSTALL-WIN-SOURCE b/INSTALL-WIN-SOURCE
index 969eb91f5b1..969eb91f5b1 100755..100644
--- a/INSTALL-WIN-SOURCE
+++ b/INSTALL-WIN-SOURCE
diff --git a/client/mysqladmin.c b/client/mysqladmin.c
index 018bcbc1963..f263d321a7b 100644
--- a/client/mysqladmin.c
+++ b/client/mysqladmin.c
@@ -769,9 +769,12 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
return 1;
}
if (argv[1][0])
- make_scrambled_password(crypted_pw,argv[1],
- (find_type(argv[0], &command_typelib, 2) ==
- ADMIN_OLD_PASSWORD), &rand_st);
+ {
+ if (find_type(argv[0], &command_typelib, 2) == ADMIN_OLD_PASSWORD)
+ make_scrambled_password_323(crypted_pw, argv[1]);
+ else
+ make_scrambled_password(crypted_pw, argv[1]);
+ }
else
crypted_pw[0]=0; /* No password */
sprintf(buff,"set password='%s',sql_log_off=0",crypted_pw);
diff --git a/client/mysqldump.c b/client/mysqldump.c
index b317c7e5d13..feaaaccd01d 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -1137,7 +1137,7 @@ static void dumpTable(uint numFields, char *table)
safe_exit(EX_CONSCHECK);
return;
}
- if (extended_insert)
+ if (extended_insert && !opt_xml)
{
ulong length = lengths[i];
if (i == 0)
@@ -1222,7 +1222,7 @@ static void dumpTable(uint numFields, char *table)
if (opt_xml)
fprintf(md_result_file, "\t</row>\n");
- if (extended_insert)
+ if (extended_insert && !opt_xml)
{
ulong row_length;
dynstr_append(&extended_row,")");
@@ -1404,7 +1404,7 @@ static int init_dumping(char *database)
(opt_quoted ? "`" : ""));
}
}
- if (extended_insert)
+ if (extended_insert && !opt_xml)
if (init_dynamic_string(&extended_row, "", 1024, 1024))
exit(EX_EOM);
return 0;
@@ -1676,7 +1676,7 @@ int main(int argc, char **argv)
if (md_result_file != stdout)
my_fclose(md_result_file, MYF(0));
my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
- if (extended_insert)
+ if (extended_insert & !opt_xml)
dynstr_free(&extended_row);
my_end(0);
return(first_error);
diff --git a/include/errmsg.h b/include/errmsg.h
index 1f4e6e12f00..a354c125e36 100644
--- a/include/errmsg.h
+++ b/include/errmsg.h
@@ -86,3 +86,4 @@ extern const char *client_errors[]; /* Error messages */
#define CR_SHARED_MEMORY_CONNECT_SET_ERROR 2045
#define CR_CONN_UNKNOW_PROTOCOL 2046
#define CR_INVALID_CONN_HANDLE 2047
+#define CR_MYSQL_SERVER_INIT_MISSED 2048
diff --git a/include/my_pthread.h b/include/my_pthread.h
index d8374cad314..f4976abee10 100644
--- a/include/my_pthread.h
+++ b/include/my_pthread.h
@@ -111,7 +111,6 @@ void pthread_exit(void *a); /* was #define pthread_exit(A) ExitThread(A)*/
#endif
#define pthread_self() win_pthread_self
#define HAVE_LOCALTIME_R 1
-#define HAVE_GMTIME_R 1
#define _REENTRANT 1
#define HAVE_PTHREAD_ATTR_SETSTACKSIZE 1
diff --git a/include/my_sys.h b/include/my_sys.h
index 688e8bfc9e3..4e727af3aa8 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -213,7 +213,7 @@ extern uint get_charset_number(const char *cs_name);
extern const char *get_charset_name(uint cs_number);
extern CHARSET_INFO *get_charset(uint cs_number, myf flags);
extern CHARSET_INFO *get_charset_by_name(const char *cs_name, myf flags);
-extern CHARSET_INFO *get_charset_by_csname(const char *cs_name,
+extern CHARSET_INFO *get_charset_by_csname(const char *cs_name,
uint cs_flags, myf my_flags);
extern void free_charsets(void);
extern char *get_charsets_dir(char *buf);
@@ -507,6 +507,8 @@ typedef struct st_keycache
ulonglong size;
} KEY_CACHE;
+typedef uint32 ha_checksum;
+
#include <my_alloc.h>
/* Prototypes for mysys and my_func functions */
@@ -749,10 +751,11 @@ extern void print_defaults(const char *conf_file, const char **groups);
extern my_bool my_compress(byte *, ulong *, ulong *);
extern my_bool my_uncompress(byte *, ulong *, ulong *);
extern byte *my_compress_alloc(const byte *packet, ulong *len, ulong *complen);
-extern ulong checksum(const byte *mem, uint count);
+extern ha_checksum my_checksum(ha_checksum crc, const byte *mem, uint count);
extern uint my_bit_log2(ulong value);
-uint my_count_bits(ulonglong v);
+extern uint my_count_bits(ulonglong v);
extern void my_sleep(ulong m_seconds);
+extern ulong crc32(ulong crc, const uchar *buf, uint len);
#ifdef __WIN__
extern my_bool have_tcpip; /* Is set if tcpip is used */
diff --git a/include/myisam.h b/include/myisam.h
index e85d3057672..0ffcdae8567 100644
--- a/include/myisam.h
+++ b/include/myisam.h
@@ -53,8 +53,6 @@ extern "C" {
#define mi_portable_sizeof_char_ptr 8
-typedef uint32 ha_checksum;
-
/* Param to/from mi_info */
typedef struct st_mi_isaminfo /* Struct from h_info */
diff --git a/include/mysql.h b/include/mysql.h
index 8e8ffc2b788..2e23a1e2f98 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -229,7 +229,9 @@ typedef struct st_mysql
enum mysql_status status;
my_bool free_me; /* If free in mysql_close */
my_bool reconnect; /* set to 1 if automatic reconnect */
- char scramble_buff[21]; /* New protocol requires longer scramble*/
+
+ /* session-wide random string */
+ char scramble[SCRAMBLE_LENGTH+1];
/*
Set if this is the original connection, not a master or a slave we have
@@ -541,16 +543,16 @@ typedef struct st_mysql_stmt
typedef struct st_mysql_methods
{
- my_bool STDCALL (*read_query_result)(MYSQL *mysql);
- my_bool STDCALL (*advanced_command)(MYSQL *mysql,
+ my_bool (STDCALL *read_query_result)(MYSQL *mysql);
+ my_bool (STDCALL *advanced_command)(MYSQL *mysql,
enum enum_server_command command,
const char *header,
unsigned long header_length,
const char *arg,
unsigned long arg_length, my_bool skip_check);
- MYSQL_RES * STDCALL (*store_result)(MYSQL *mysql);
- MYSQL_RES * STDCALL (*use_result)(MYSQL *mysql);
- void STDCALL (*fetch_lengths)(unsigned long *to, MYSQL_ROW column, uint field_count);
+ MYSQL_RES * (STDCALL *store_result)(MYSQL *mysql);
+ MYSQL_RES * (STDCALL *use_result)(MYSQL *mysql);
+ void (STDCALL *fetch_lengths)(unsigned long *to, MYSQL_ROW column, uint field_count);
} MYSQL_METHODS;
MYSQL_STMT * STDCALL mysql_prepare(MYSQL * mysql, const char *query,
diff --git a/include/mysql_com.h b/include/mysql_com.h
index b1c94e5c735..b8dc877f125 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -49,8 +49,15 @@ enum enum_server_command
};
-#define SCRAMBLE_LENGTH 8
-#define SCRAMBLE41_LENGTH 20
+/*
+ Length of random string sent by server on handshake; this is also length of
+ obfuscated password, recieved from client
+*/
+#define SCRAMBLE_LENGTH 20
+#define SCRAMBLE_LENGTH_323 8
+/* length of password stored in the db: new passwords are preceeded with '*' */
+#define SCRAMBLED_PASSWORD_CHAR_LENGTH (SCRAMBLE_LENGTH*2+1)
+#define SCRAMBLED_PASSWORD_CHAR_LENGTH_323 (SCRAMBLE_LENGTH_323*2)
#define NOT_NULL_FLAG 1 /* Field can't be NULL */
@@ -302,31 +309,34 @@ extern "C" {
extern unsigned long max_allowed_packet;
extern unsigned long net_buffer_length;
-void randominit(struct rand_struct *,unsigned long seed1,
- unsigned long seed2);
+/*
+ These functions are used for authentication by client and server and
+ implemented in sql/password.c
+*/
+
+void randominit(struct rand_struct *, unsigned long seed1,
+ unsigned long seed2);
double my_rnd(struct rand_struct *);
-void make_scrambled_password(char *to,const char *password,
- my_bool force_old_scramble,struct rand_struct *rand_st);
-int get_password_length(my_bool force_old_scramble);
-char get_password_version(const char* password);
-void create_random_string(int length,struct rand_struct *rand_st,char* target);
-my_bool validate_password(const char* password, const char* message,
- unsigned long* salt);
-void password_hash_stage1(char *to, const char *password);
-void password_hash_stage2(char *to,const char *salt);
-void password_crypt(const char* from,char* to, const char* password,int length);
-void get_hash_and_password(unsigned long* salt, unsigned char pversion,char* hash,
- unsigned char* bin_password);
-void get_salt_from_password(unsigned long *res,const char *password);
-void create_key_from_old_password(const char* password,char* key);
-void make_password_from_salt(char *to, unsigned long *hash_res,
- unsigned char password_version);
-char *scramble(char *to,const char *message,const char *password,
- my_bool old_ver);
-my_bool check_scramble(const char *, const char *message,
- unsigned long *salt,my_bool old_ver);
+void create_random_string(char *to, uint length, struct rand_struct *rand_st);
+
+void hash_password(unsigned long *to, const char *password, uint password_len);
+void make_scrambled_password_323(char *to, const char *password);
+void scramble_323(char *to, const char *message, const char *password);
+my_bool check_scramble_323(const char *, const char *message,
+ unsigned long *salt);
+void get_salt_from_password_323(unsigned long *res, const char *password);
+void make_password_from_salt_323(char *to, const unsigned long *salt);
+
+void make_scrambled_password(char *to, const char *password);
+void scramble(char *to, const char *message, const char *password);
+my_bool check_scramble(const char *reply, const char *message,
+ const unsigned char *hash_stage2);
+void get_salt_from_password(unsigned char *res, const char *password);
+void make_password_from_salt(char *to, const unsigned char *hash_stage2);
+
+/* end of password.c */
+
char *get_tty_password(char *opt_message);
-void hash_password(unsigned long *result, const char *password);
const char *mysql_errno_to_sqlstate(unsigned int mysql_errno);
/* Some other useful functions */
diff --git a/include/mysqld_error.h b/include/mysqld_error.h
index 861e0314e28..c863a6c9854 100644
--- a/include/mysqld_error.h
+++ b/include/mysqld_error.h
@@ -289,5 +289,7 @@
#define ER_CANT_AGGREGATE_NCOLLATIONS 1270
#define ER_VARIABLE_IS_NOT_STRUCT 1271
#define ER_UNKNOWN_COLLATION 1272
-#define ER_WARN_FIELD_RESOLVED 1273
-#define ER_ERROR_MESSAGES 274
+#define ER_SLAVE_IGNORED_SSL_PARAMS 1273
+#define ER_SERVER_IS_IN_SECURE_AUTH_MODE 1274
+#define ER_WARN_FIELD_RESOLVED 1275
+#define ER_ERROR_MESSAGES 276
diff --git a/include/thr_alarm.h b/include/thr_alarm.h
index 439f046252f..8ff4472f700 100644
--- a/include/thr_alarm.h
+++ b/include/thr_alarm.h
@@ -100,7 +100,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);
-bool thr_alarm(thr_alarm_t *alarmed, uint sec, ALARM *buff);
+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);
void end_thr_alarm(my_bool free_structures);
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index 81bbf5053c0..d0f6965f94e 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -2170,7 +2170,7 @@ row_sel_store_mysql_rec(
ulint len;
byte* blob_buf;
ulint i;
-
+
ut_ad(prebuilt->mysql_template);
if (prebuilt->blob_heap != NULL) {
@@ -2178,9 +2178,9 @@ row_sel_store_mysql_rec(
prebuilt->blob_heap = NULL;
}
- /* Mark all columns as not SQL NULL */
+ /* Mark all columns as SQL NULL */
- memset(mysql_rec, '\0', prebuilt->null_bitmap_len);
+ memset(mysql_rec, 255, prebuilt->null_bitmap_len);
for (i = 0; i < prebuilt->n_template; i++) {
@@ -2235,16 +2235,21 @@ row_sel_store_mysql_rec(
data = blob_buf;
}
-
+
row_sel_field_store_in_mysql_format(
mysql_rec + templ->mysql_col_offset,
templ->mysql_col_len, data, len,
templ->type, templ->is_unsigned);
if (extern_field_heap) {
- mem_heap_free(extern_field_heap);
+ mem_heap_free(extern_field_heap);
extern_field_heap = NULL;
- }
+ }
+
+ if (templ->mysql_null_bit_mask) {
+ mysql_rec[templ->mysql_null_byte_offset] &=
+ ~(byte) (templ->mysql_null_bit_mask);
+ }
} else {
/* MySQL seems to assume the field for an SQL NULL
value is set to zero. Not taking this into account
@@ -2252,19 +2257,13 @@ row_sel_store_mysql_rec(
bug number 154 in the MySQL bug database: GROUP BY
and DISTINCT could treat NULL values inequal. */
- memset(mysql_rec + templ->mysql_col_offset, '\0',
+ memset(mysql_rec + templ->mysql_col_offset,
+ ((templ->type == DATA_VARCHAR ||
+ templ->type == DATA_VARMYSQL ||
+ templ->type == DATA_BINARY) ? ' ' : '\0'),
templ->mysql_col_len);
-
- if (!templ->mysql_null_bit_mask) {
- fprintf(stderr,
-"InnoDB: Error: trying to return an SQL NULL field in a non-null\n"
-"innoDB: column! Table name %s\n", prebuilt->table->name);
- } else {
- mysql_rec[templ->mysql_null_byte_offset] |=
- (byte) (templ->mysql_null_bit_mask);
- }
}
- }
+ }
return(TRUE);
}
diff --git a/isam/isamchk.c b/isam/isamchk.c
index dc772290e13..939a4be732f 100644
--- a/isam/isamchk.c
+++ b/isam/isamchk.c
@@ -1328,7 +1328,7 @@ int extend;
print_error("Found wrong record at %lu",(ulong) start_recpos);
got_error=1;
}
- crc^=checksum(record,info->s->base.reclength);
+ crc^=_nisam_checksum(record,info->s->base.reclength);
link_used+=info->s->pack.ref_length;
used+=block_info.rec_len+info->s->pack.ref_length;
}
diff --git a/isam/isamdef.h b/isam/isamdef.h
index 0884b18e997..54656b6842e 100644
--- a/isam/isamdef.h
+++ b/isam/isamdef.h
@@ -358,6 +358,7 @@ extern int _nisam_read_pack_record(N_INFO *info,ulong filepos,byte *buf);
extern int _nisam_read_rnd_pack_record(N_INFO*, byte *,ulong, int);
extern int _nisam_pack_rec_unpack(N_INFO *info,byte *to,byte *from,
uint reclength);
+extern ulong _nisam_checksum(const byte *mem, uint count);
typedef struct st_sortinfo {
uint key_length;
diff --git a/isam/open.c b/isam/open.c
index 48fab27cac1..824fbe804ee 100644
--- a/isam/open.c
+++ b/isam/open.c
@@ -453,3 +453,22 @@ static void setup_key_functions(register N_KEYDEF *keyinfo)
}
return;
}
+
+/*
+ Calculate a long checksum for a memoryblock. Used to verify pack_isam
+
+ SYNOPSIS
+ checksum()
+ mem Pointer to memory block
+ count Count of bytes
+*/
+
+ulong _nisam_checksum(const byte *mem, uint count)
+{
+ ulong crc;
+ for (crc= 0; count-- ; mem++)
+ crc= ((crc << 1) + *((uchar*) mem)) +
+ test(crc & ((ulong) 1L << (8*sizeof(ulong)-1)));
+ return crc;
+}
+
diff --git a/isam/pack_isam.c b/isam/pack_isam.c
index fd12aac1e09..9108070f918 100644
--- a/isam/pack_isam.c
+++ b/isam/pack_isam.c
@@ -738,7 +738,7 @@ static int get_statistic(MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
{
if (! error)
{
- crc^=checksum(record,reclength);
+ crc^=_nisam_checksum(record,reclength);
for (pos=record,count=huff_counts ;
count < end_count ;
count++,
diff --git a/libmysql/errmsg.c b/libmysql/errmsg.c
index bbb85885886..d27e981aaab 100644
--- a/libmysql/errmsg.c
+++ b/libmysql/errmsg.c
@@ -71,7 +71,8 @@ const char *client_errors[]=
"Can't open shared memory. Server abandoded and don't sent the answer event (%lu)",
"Can't open shared memory. Can't send the request event to server (%lu)",
"Wrong or unknown protocol",
- "Invalid connection handle"
+ "Invalid connection handle",
+ "mysql_server_init wasn't called"
};
/* Start of code added by Roberto M. Serqueira - martinsc@uol.com.br - 05.24.2001 */
@@ -126,7 +127,8 @@ const char *client_errors[]=
"Can't open shared memory. Server abandoded and don't sent the answer event (%lu)",
"Can't open shared memory. Can't send the request event to server (%lu)",
"Wrong or unknown protocol",
- "Invalid connection handle"
+ "Invalid connection handle",
+ "mysql_server_init wasn't called"
};
#else /* ENGLISH */
@@ -179,7 +181,8 @@ const char *client_errors[]=
"Can't open shared memory. Server abandoded and don't sent the answer event (%lu)",
"Can't open shared memory. Can't send the request event to server (%lu)",
"Wrong or unknown protocol",
- "Invalid connection handle"
+ "Invalid connection handle",
+ "mysql_server_init wasn't called"
};
#endif
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index 19cfedce51d..0a9e1114fc5 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -594,6 +594,8 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
const char *passwd, const char *db)
{
char buff[512],*end=buff;
+ NET *net= &mysql->net;
+ ulong pkt_length;
DBUG_ENTER("mysql_change_user");
if (!user)
@@ -604,41 +606,54 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
/* Store user into the buffer */
end=strmov(end,user)+1;
- /*
- We always start with old type handshake the only difference is message sent
- If server handles secure connection type we'll not send the real scramble
- */
- if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
+ /* write scrambled password according to server capabilities */
+ if (passwd[0])
{
- if (passwd[0])
+ if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
{
- /* Prepare false scramble */
- bfill(end, SCRAMBLE_LENGTH, 'x');
- end+=SCRAMBLE_LENGTH;
- *end=0;
-
+ *end++= SCRAMBLE_LENGTH;
+ scramble(end, mysql->scramble, passwd);
+ end+= SCRAMBLE_LENGTH;
+ }
+ else
+ {
+ scramble_323(end, mysql->scramble, passwd);
+ end+= SCRAMBLE_LENGTH_323 + 1;
}
- else /* For empty password */
- *end=0; /* zero length scramble */
}
else
- {
- /*
- Real scramble is only sent to old servers. This can be blocked
- by calling mysql_options(MYSQL *, MYSQL_SECURE_CONNECT, (char*) &1);
- */
- end=scramble(end, mysql->scramble_buff, passwd,
- (my_bool) (mysql->protocol_version == 9));
- }
+ *end++= '\0'; // empty password
/* Add database if needed */
- end=strmov(end+1,db ? db : "");
+ end= strmov(end, db ? db : "") + 1;
/* Write authentication package */
simple_command(mysql,COM_CHANGE_USER, buff,(ulong) (end-buff),1);
- if (mysql_autenticate(mysql, passwd))
+ pkt_length= net_safe_read(mysql);
+
+ if (pkt_length == packet_error)
goto error;
+ if (pkt_length == 1 && net->read_pos[0] == 254 &&
+ mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
+ {
+ /*
+ By sending this very specific reply server asks us to send scrambled
+ password in old format. The reply contains scramble_323.
+ */
+ scramble_323(buff, mysql->scramble, passwd);
+ if (my_net_write(net, buff, SCRAMBLE_LENGTH_323 + 1) || net_flush(net))
+ {
+ net->last_errno= CR_SERVER_LOST;
+ strmov(net->sqlstate, unknown_sqlstate);
+ strmov(net->last_error,ER(net->last_errno));
+ goto error;
+ }
+ /* Read what server thinks about out new auth message report */
+ if (net_safe_read(mysql) == packet_error)
+ goto error;
+ }
+
/* Free old connect information */
my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR));
diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index aaa31908360..5b3278694e3 100644
--- a/libmysqld/lib_sql.cc
+++ b/libmysqld/lib_sql.cc
@@ -26,7 +26,8 @@
static int fake_argc= 1;
static char *fake_argv[]= {(char *)"", 0};
static const char *fake_groups[] = { "server", "embedded", 0 };
-static char inited, org_my_init_done;
+static char org_my_init_done;
+char server_inited;
#if defined (__WIN__)
#include "../sql/mysqld.cpp"
@@ -34,9 +35,9 @@ static char inited, org_my_init_done;
#include "../sql/mysqld.cc"
#endif
-#define SCRAMBLE_LENGTH 8
C_MODE_START
#include <mysql.h>
+#undef ER
#include "errmsg.h"
#include <sql_common.h>
@@ -48,19 +49,20 @@ static bool check_user(THD *thd, enum_server_command command,
char * get_mysql_home(){ return mysql_home;};
char * get_mysql_real_data_home(){ return mysql_real_data_home;};
-my_bool
+my_bool STDCALL
emb_advanced_command(MYSQL *mysql, enum enum_server_command command,
const char *header, ulong header_length,
const char *arg, ulong arg_length, my_bool skip_check)
{
my_bool result= 1;
THD *thd=(THD *) mysql->thd;
+ NET *net= &mysql->net;
/* Check that we are calling the client functions in right order */
if (mysql->status != MYSQL_STATUS_READY)
{
- strmov(thd->net.last_error,
- ER(thd->net.last_errno=CR_COMMANDS_OUT_OF_SYNC));
+ strmov(net->last_error,
+ ER(net->last_errno=CR_COMMANDS_OUT_OF_SYNC));
return 1;
}
@@ -76,12 +78,12 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command,
if (!skip_check)
result= thd->net.last_errno ? -1 : 0;
- if ((mysql->net.last_errno= thd->net.last_errno))
+ if ((net->last_errno= thd->net.last_errno))
{
- memcpy(mysql->net.last_error, thd->net.last_error,
- sizeof(mysql->net.last_error));
- memcpy(mysql->net.sqlstate, thd->net.sqlstate,
- sizeof(mysql->net.sqlstate));
+ memcpy(net->last_error, net->last_error,
+ sizeof(net->last_error));
+ memcpy(net->sqlstate, thd->net.sqlstate,
+ sizeof(net->sqlstate));
}
mysql->warning_count= ((THD*)mysql->thd)->total_warn_count;
return result;
@@ -182,9 +184,9 @@ int STDCALL mysql_server_init(int argc, char **argv, char **groups)
/* Only call MY_INIT() if it hasn't been called before */
- if (!inited)
+ if (!server_inited)
{
- inited=1;
+ server_inited=1;
org_my_init_done=my_init_done;
}
if (!org_my_init_done)
diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c
index 357c13c5826..0c772587c4b 100644
--- a/libmysqld/libmysqld.c
+++ b/libmysqld/libmysqld.c
@@ -59,7 +59,7 @@
#endif
void free_old_query(MYSQL *mysql);
-my_bool
+my_bool STDCALL
emb_advanced_command(MYSQL *mysql, enum enum_server_command command,
const char *header, ulong header_length,
const char *arg, ulong arg_length, my_bool skip_check);
@@ -79,6 +79,8 @@ struct passwd *getpwuid(uid_t);
char* getlogin(void);
#endif
+extern char server_inited;
+
#ifdef __WIN__
static my_bool is_NT(void)
{
@@ -169,7 +171,7 @@ static inline int mysql_init_charset(MYSQL *mysql)
else the lengths are calculated from the offset between pointers.
**************************************************************************/
-static void emb_fetch_lengths(ulong *to, MYSQL_ROW column, uint field_count)
+static void STDCALL emb_fetch_lengths(ulong *to, MYSQL_ROW column, uint field_count)
{
MYSQL_ROW end;
@@ -210,6 +212,20 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
db ? db : "(Null)",
user ? user : "(Null)"));
+#ifdef EMBEDDED_LIBRARY
+ /*
+ Here we check that mysql_server_init was called before.
+ Actually we can perform the test for client (not embedded) library as well.
+ But i'm afraid some old applications will be broken then.
+ */
+ if (!server_inited)
+ {
+ mysql->net.last_errno=CR_MYSQL_SERVER_INIT_MISSED;
+ strmov(mysql->net.last_error,ER(mysql->net.last_errno));
+ goto error;
+ }
+#endif /*EMBEDDED_LIBRARY*/
+
if (mysql->options.methods_to_use == MYSQL_OPT_USE_REMOTE_CONNECTION)
cli_mysql_real_connect(mysql, host, user,
passwd, db, port, unix_socket, client_flag);
diff --git a/myisam/mi_checksum.c b/myisam/mi_checksum.c
index a760b03a032..cdbb634c5ff 100644
--- a/myisam/mi_checksum.c
+++ b/myisam/mi_checksum.c
@@ -28,30 +28,29 @@ ha_checksum mi_checksum(MI_INFO *info, const byte *buf)
{
const byte *pos;
const byte *end;
+ ulong length;
switch (rec->type) {
case FIELD_BLOB:
{
- ulong length=_mi_calc_blob_length(rec->length-
+ length=_mi_calc_blob_length(rec->length-
mi_portable_sizeof_char_ptr,
buf);
memcpy((char*) &pos, buf+rec->length- mi_portable_sizeof_char_ptr,
sizeof(char*));
- end=pos+length;
break;
}
case FIELD_VARCHAR:
{
- uint length;
length=uint2korr(buf);
- pos=buf+2; end=pos+length;
+ pos=buf+2;
break;
}
default:
- pos=buf; end=buf+rec->length;
+ length=rec->length;
+ pos=buf;
break;
}
- for ( ; pos != end ; pos++)
- crc=((crc << 8) + *((uchar*) pos)) + (crc >> (8*sizeof(ha_checksum)-8));
+ crc=my_checksum(crc, pos ? pos : "", length);
}
return crc;
}
@@ -59,9 +58,5 @@ ha_checksum mi_checksum(MI_INFO *info, const byte *buf)
ha_checksum mi_static_checksum(MI_INFO *info, const byte *pos)
{
- ha_checksum crc;
- const byte *end=pos+info->s->base.reclength;
- for (crc=0; pos != end; pos++)
- crc=((crc << 8) + *((uchar*) pos)) + (crc >> (8*sizeof(ha_checksum)-8));
- return crc;
+ return my_checksum(0, pos, info->s->base.reclength);
}
diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am
index fb97dd5b1de..2babb6fba66 100644
--- a/mysql-test/Makefile.am
+++ b/mysql-test/Makefile.am
@@ -21,8 +21,9 @@ benchdir_root= $(prefix)
testdir = $(benchdir_root)/mysql-test
EXTRA_SCRIPTS = mysql-test-run.sh install_test_db.sh
EXTRA_DIST = $(EXTRA_SCRIPTS)
-test_SCRIPTS = mysql-test-run install_test_db
-CLEANFILES = $(test_SCRIPTS)
+test_SCRIPTS = mysql-test-run install_test_db
+test_DATA = std_data/client-key.pem std_data/client-cert.pem std_data/cacert.pem
+CLEANFILES = $(test_SCRIPTS) $(test_DATA)
dist-hook:
mkdir -p $(distdir)/t $(distdir)/r $(distdir)/include \
@@ -32,6 +33,8 @@ dist-hook:
$(INSTALL_DATA) $(srcdir)/r/*.result $(srcdir)/r/*.require $(distdir)/r
$(INSTALL_DATA) $(srcdir)/std_data/*.dat $(srcdir)/std_data/*.000001 $(distdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/des_key_file $(distdir)/std_data
+ $(INSTALL_DATA) $(srcdir)/std_data/*.pem $(distdir)/std_data
+
install-data-local:
$(mkinstalldirs) \
@@ -49,6 +52,11 @@ install-data-local:
$(INSTALL_DATA) $(srcdir)/include/*.inc $(DESTDIR)$(testdir)/include
$(INSTALL_DATA) $(srcdir)/std_data/*.dat $(DESTDIR)$(testdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/des_key_file $(DESTDIR)$(testdir)/std_data
+ $(INSTALL_DATA) $(srcdir)/std_data/*.pem $(DESTDIR)$(testdir)/std_data
+
+std_data/%.pem:
+ @CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data
+
SUFFIXES = .sh
diff --git a/mysql-test/r/connect.result b/mysql-test/r/connect.result
index 9c848c3434f..c0608af0de2 100644
--- a/mysql-test/r/connect.result
+++ b/mysql-test/r/connect.result
@@ -30,6 +30,7 @@ show tables;
Tables_in_test
update mysql.user set password=old_password("gambling2") where user="test";
flush privileges;
+set password=old_password('gambling3');
show tables;
Tables_in_mysql
columns_priv
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result
index b51836f39e0..80ff8aef15b 100644
--- a/mysql-test/r/create.result
+++ b/mysql-test/r/create.result
@@ -312,3 +312,52 @@ 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)
+values(2,-2,2,'1825-12-14','a','2003-1-1 3:2:1','4:3:2','binary data');
+select * from t1;
+a b c d e f g h
+1 NULL NULL NULL NULL NULL NULL NULL
+2 -2 2 1825-12-14 a 2003-01-01 03:02:01 04:03:02 binary data
+select a,
+ifnull(b,cast(-7 as signed)) as b,
+ifnull(c,cast(7 as unsigned)) as c,
+ifnull(d,cast('2000-01-01' as date)) as d,
+ifnull(e,cast('b' as char)) as e,
+ifnull(f,cast('2000-01-01' as datetime)) as f,
+ifnull(g,cast('5:4:3' as time)) as g,
+ifnull(h,cast('yet another binary data' as binary)) as h,
+addtime(cast('1:0:0' as time),cast('1:0:0' as time)) as dd
+from t1;
+a b c d e f g h dd
+1 -7 7 2000-01-01 b 2000-01-01 00:00:00 05:04:03 yet another binary data 02:00:00
+2 -2 2 1825-12-14 a 2003-01-01 03:02:01 04:03:02 binary data 02:00:00
+create table t2
+select
+a,
+ifnull(b,cast(-7 as signed)) as b,
+ifnull(c,cast(7 as unsigned)) as c,
+ifnull(d,cast('2000-01-01' as date)) as d,
+ifnull(e,cast('b' as char)) as e,
+ifnull(f,cast('2000-01-01' as datetime)) as f,
+ifnull(g,cast('5:4:3' as time)) as g,
+ifnull(h,cast('yet another binary data' as binary)) as h,
+addtime(cast('1:0:0' as time),cast('1:0:0' as time)) as dd
+from t1;
+explain t2;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b bigint(11) 0
+c bigint(10) 0
+d date 0000-00-00
+e char(1)
+f datetime 0000-00-00 00:00:00
+g time 00:00:00
+h mediumblob
+dd time 00:00:00
+select * from t2;
+a b c d e f g h dd
+1 -7 7 2000-01-01 b 2000-01-01 00:00:00 05:04:03 yet another binary data 02:00:00
+2 -2 2 1825-12-14 a 2003-01-01 03:02:01 04:03:02 binary data 02:00:00
+drop table t1, t2;
diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result
index f9e52174469..944253bd527 100644
--- a/mysql-test/r/derived.result
+++ b/mysql-test/r/derived.result
@@ -196,3 +196,11 @@ drop table t1,t2;
SELECT a.x FROM (SELECT 1 AS x) AS a HAVING a.x = 1;
x
1
+create table a1 select 1 as a;
+select 2 as a from (select * from a1) b;
+ERROR 3D000: No Database Selected
+use test;
+select 2 as a from (select * from a1) b;
+a
+2
+drop table a1;
diff --git a/mysql-test/r/drop.result b/mysql-test/r/drop.result
index 367b28e9bf7..3748af1b8f9 100644
--- a/mysql-test/r/drop.result
+++ b/mysql-test/r/drop.result
@@ -44,3 +44,13 @@ mysql
test
drop database mysqltest;
ERROR HY000: Can't drop database 'mysqltest'; database doesn't exist
+drop table t1;
+flush tables with read lock;
+create table t1(n int);
+ERROR HY000: Can't execute the query because you have a conflicting read lock
+unlock tables;
+create table t1(n int);
+show tables;
+Tables_in_test
+t1
+drop table t1;
diff --git a/mysql-test/r/func_crypt.result b/mysql-test/r/func_crypt.result
index 461ae1e7e09..5ee0f0f3e93 100644
--- a/mysql-test/r/func_crypt.result
+++ b/mysql-test/r/func_crypt.result
@@ -1,15 +1,79 @@
select length(encrypt('foo', 'ff')) <> 0;
length(encrypt('foo', 'ff')) <> 0
1
-select password("a",""), password("a",NULL), password("","a"), password(NULL,"a");
-password("a","") password("a",NULL) password("","a") password(NULL,"a")
-*2517f7235d68d4ba2e5019c93420523101157a792c01 NULL NULL
-select password("aaaaaaaaaaaaaaaa","a"), password("a","aaaaaaaaaaaaaaaa");
-password("aaaaaaaaaaaaaaaa","a") password("a","aaaaaaaaaaaaaaaa")
-*2cd3b9a44e9a9994789a30f935c92f45a96c5472f381 *37c7c5c794ff144819f2531bf03c57772cd84e40db09
-select old_password('test'), length(password("1")), length(encrypt('test')), encrypt('test','aa');
-old_password('test') length(password("1")) length(encrypt('test')) encrypt('test','aa')
-378b243e220ca493 45 13 aaqPiZY5xR5l.
-select old_password(""), old_password(NULL), password(""), password(NULL);
-old_password("") old_password(NULL) password("") password(NULL)
- NULL NULL
+select password('abc');
+password('abc')
+*0D3CED9BEC10A777AEC23CCC353A8C08A633045E
+select password('');
+password('')
+
+select old_password('abc');
+old_password('abc')
+7cd2b5942be28759
+select old_password('');
+old_password('')
+
+select password('gabbagabbahey');
+password('gabbagabbahey')
+*B0F99D2963660DD7E16B751EC9EE2F17B6A68FA6
+select old_password('idkfa');
+old_password('idkfa')
+5c078dc54ca0fcca
+select length(password('1'));
+length(password('1'))
+41
+select length(encrypt('test'));
+length(encrypt('test'))
+13
+select encrypt('test','aa');
+encrypt('test','aa')
+aaqPiZY5xR5l.
+select old_password(NULL);
+old_password(NULL)
+NULL
+select password(NULL);
+password(NULL)
+NULL
+set global old_passwords=on;
+select password('');
+password('')
+
+select old_password('');
+old_password('')
+
+select password('idkfa');
+password('idkfa')
+*B669C9DAC3AA6F2254B03CDEF8DFDD6B2D1054BA
+select old_password('idkfa');
+old_password('idkfa')
+5c078dc54ca0fcca
+set old_passwords=on;
+select password('idkfa');
+password('idkfa')
+5c078dc54ca0fcca
+select old_password('idkfa');
+old_password('idkfa')
+5c078dc54ca0fcca
+set global old_passwords=off;
+select password('idkfa');
+password('idkfa')
+5c078dc54ca0fcca
+select old_password('idkfa');
+old_password('idkfa')
+5c078dc54ca0fcca
+set old_passwords=off;
+select password('idkfa ');
+password('idkfa ')
+*2DC31D90647B4C1ABC9231563D2236E96C9A2DB2
+select password('idkfa');
+password('idkfa')
+*B669C9DAC3AA6F2254B03CDEF8DFDD6B2D1054BA
+select password(' idkfa');
+password(' idkfa')
+*12B099E56BB7FE8D43C78FD834A9D1D11178D045
+select old_password('idkfa');
+old_password('idkfa')
+5c078dc54ca0fcca
+select old_password(' i d k f a ');
+old_password(' i d k f a ')
+5c078dc54ca0fcca
diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result
index a4493e7c95c..5c3c2f10000 100644
--- a/mysql-test/r/func_gconcat.result
+++ b/mysql-test/r/func_gconcat.result
@@ -167,6 +167,11 @@ t2.URL_ID = t1.URL_ID group by REQ_ID;
REQ_ID URL
1 X
5 X,X,X
+select REQ_ID, Group_Concat(URL) as URL, Min(t1.URL_ID) urll,
+Max(t1.URL_ID) urlg from t1, t2 where t2.URL_ID = t1.URL_ID group by REQ_ID;
+REQ_ID URL urll urlg
+1 X 4 4
+5 X,X,X 4 5
drop table t1;
drop table t2;
create table t1 (id int, name varchar(16));
@@ -178,3 +183,16 @@ select distinct ifnull(group_concat(concat(t1.id, ':', t1.name)), 'shortname') a
with distinct: cutoff at length of shortname
1:longername,1:evenlongername
drop table t1;
+create table t1(id int);
+create table t2(id int);
+insert into t1 values(0),(1);
+select group_concat(t1.id) FROM t1,t2;
+group_concat(t1.id)
+NULL
+drop table t1;
+drop table t2;
+create table t1 (bar varchar(32));
+insert into t1 values('test'),('test2');
+select * from t1 having group_concat(bar)='';
+bar
+drop table t1;
diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result
index 8592393fd42..718e554b904 100644
--- a/mysql-test/r/innodb.result
+++ b/mysql-test/r/innodb.result
@@ -251,6 +251,18 @@ n
6
rollback;
drop table t1;
+create table t1 (n int not null primary key) type=innodb;
+start transaction;
+insert into t1 values (4);
+flush tables with read lock;
+commit;
+ERROR HY000: Can't execute the query because you have a conflicting read lock
+unlock tables;
+commit;
+select * from t1;
+n
+4
+drop table t1;
create table t1 ( id int NOT NULL PRIMARY KEY, nom varchar(64)) type=innodb;
begin;
insert into t1 values(1,'hamdouni');
@@ -1342,3 +1354,40 @@ id label
3524 Societe Test
3525 Fournisseur Test
drop table t1,t2;
+create table t1 (c1 char(5) unique not null, c2 int, stamp timestamp) type=innodb;
+select * from t1;
+c1 c2 stamp
+replace delayed into t1 (c1, c2) values ( "text1","11"),( "text2","12");
+ERROR HY000: Table storage engine for 't1' doesn't have this option
+select * from t1;
+c1 c2 stamp
+replace delayed into t1 (c1, c2) values ( "text1","12"),( "text2","13"),( "text3","14", "a" ),( "text4","15", "b" );
+ERROR HY000: Table storage engine for 't1' doesn't have this option
+select * from t1;
+c1 c2 stamp
+drop table t1;
+create table t1 (a int, b varchar(200), c text not null) checksum=1 type=myisam;
+create table t2 (a int, b varchar(200), c text not null) checksum=0 type=innodb;
+create table t3 (a int, b varchar(200), c text not null) checksum=1 type=innodb;
+insert t1 values (1, "aaa", "bbb"), (NULL, "", "ccccc"), (0, NULL, "");
+insert t2 select * from t1;
+insert t3 select * from t1;
+checksum table t1, t2, t3, t4 quick;
+Table Checksum
+test.t1 968604391
+test.t2 NULL
+test.t3 NULL
+test.t4 NULL
+checksum table t1, t2, t3, t4;
+Table Checksum
+test.t1 968604391
+test.t2 968604391
+test.t3 968604391
+test.t4 NULL
+checksum table t1, t2, t3, t4 extended;
+Table Checksum
+test.t1 968604391
+test.t2 968604391
+test.t3 968604391
+test.t4 NULL
+drop table t1,t2,t3;
diff --git a/mysql-test/r/isam.result b/mysql-test/r/isam.result
index b83185b0c01..bacb88a27fc 100644
--- a/mysql-test/r/isam.result
+++ b/mysql-test/r/isam.result
@@ -1,13 +1,5 @@
drop table if exists t1,t2;
create table t1 (a tinyint not null auto_increment, b blob not null, primary key (a)) type=isam;
-Warnings:
-Warning 1263 Data truncated for column 'b' at row 1
-Warnings:
-Warning 1263 Data truncated for column 'b' at row 1
-Warnings:
-Warning 1263 Data truncated for column 'b' at row 1
-Warnings:
-Warning 1263 Data truncated for column 'b' at row 1
delete from t1 where (a & 1);
select sum(length(b)) from t1;
sum(length(b))
diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result
index d158c39cba8..5971ffedcfc 100644
--- a/mysql-test/r/myisam.result
+++ b/mysql-test/r/myisam.result
@@ -367,6 +367,23 @@ id select_type table type possible_keys key key_len ref rows Extra
drop table t1,t2;
CREATE TABLE t1 (`a` int(11) NOT NULL default '0', `b` int(11) NOT NULL default '0', UNIQUE KEY `a` USING RTREE (`a`,`b`)) TYPE=MyISAM;
ERROR 42000: This version of MySQL doesn't yet support 'RTREE INDEX'
-DROP TABLE IF EXISTS t1;
-Warnings:
-Note 1051 Unknown table 't1'
+create table t1 (a int, b varchar(200), c text not null) checksum=1;
+create table t2 (a int, b varchar(200), c text not null) checksum=0;
+insert t1 values (1, "aaa", "bbb"), (NULL, "", "ccccc"), (0, NULL, "");
+insert t2 select * from t1;
+checksum table t1, t2, t3 quick;
+Table Checksum
+test.t1 968604391
+test.t2 NULL
+test.t3 NULL
+checksum table t1, t2, t3;
+Table Checksum
+test.t1 968604391
+test.t2 968604391
+test.t3 NULL
+checksum table t1, t2, t3 extended;
+Table Checksum
+test.t1 968604391
+test.t2 968604391
+test.t3 NULL
+drop table t1,t2;
diff --git a/mysql-test/r/olap.result b/mysql-test/r/olap.result
index 0b7a98e3fb3..84e37bf56a9 100644
--- a/mysql-test/r/olap.result
+++ b/mysql-test/r/olap.result
@@ -254,3 +254,18 @@ ERROR 42000: This version of MySQL doesn't yet support 'CUBE'
select product, country_id , year, sum(profit) from t1 group by product, country_id, year with cube union all select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup;
ERROR 42000: This version of MySQL doesn't yet support 'CUBE'
drop table t1,t2;
+CREATE TABLE t1 (i int);
+INSERT INTO t1 VALUES(100);
+CREATE TABLE t2 (i int);
+INSERT INTO t2 VALUES (100),(200);
+SELECT i, COUNT(*) FROM t1 GROUP BY i WITH ROLLUP;
+i COUNT(*)
+100 1
+NULL 1
+SELECT t1.i, t2.i, COUNT(*) FROM t1,t2 GROUP BY t1.i,t2.i WITH ROLLUP;
+i i COUNT(*)
+100 100 1
+100 200 1
+100 NULL 2
+NULL NULL 2
+drop table t1,t2;
diff --git a/mysql-test/r/rpl000015.result b/mysql-test/r/rpl000015.result
index 047f1ac5044..8a9f8320218 100644
--- a/mysql-test/r/rpl000015.result
+++ b/mysql-test/r/rpl000015.result
@@ -4,20 +4,20 @@ File Position Binlog_do_db Binlog_ignore_db
master-bin.000001 79
reset slave;
show slave status;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
change master to master_host='127.0.0.1';
show slave status;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 test MASTER_PORT 7 4 slave-relay-bin.000001 4 No No 0 0 0 4
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
+127.0.0.1 test MASTER_PORT 7 4 slave-relay-bin.000001 4 No No 0 0 0 4 No
change master to master_host='127.0.0.1',master_user='root',
master_password='',master_port=MASTER_PORT;
show slave status;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 7 4 slave-relay-bin.000001 4 No No 0 0 0 4
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
+127.0.0.1 root MASTER_PORT 7 4 slave-relay-bin.000001 4 No No 0 0 0 4 No
start slave;
show slave status;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 7 master-bin.000001 79 slave-relay-bin.000001 123 master-bin.000001 Yes Yes 0 0 79 123
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
+127.0.0.1 root MASTER_PORT 7 master-bin.000001 79 slave-relay-bin.000001 123 master-bin.000001 Yes Yes 0 0 79 123 No
drop table if exists t1;
create table t1 (n int);
insert into t1 values (10),(45),(90);
diff --git a/mysql-test/r/rpl_empty_master_crash.result b/mysql-test/r/rpl_empty_master_crash.result
index 6aac1cbfc91..10b1fdeb0ec 100644
--- a/mysql-test/r/rpl_empty_master_crash.result
+++ b/mysql-test/r/rpl_empty_master_crash.result
@@ -5,7 +5,7 @@ reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
show slave status;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
load table t1 from master;
ERROR 08S01: Error connecting to master: Master is not configured
load table t1 from master;
diff --git a/mysql-test/r/rpl_error_ignored_table.result b/mysql-test/r/rpl_error_ignored_table.result
index f22b62838bb..23b92e270a6 100644
--- a/mysql-test/r/rpl_error_ignored_table.result
+++ b/mysql-test/r/rpl_error_ignored_table.result
@@ -8,8 +8,8 @@ create table t1 (a int primary key);
insert into t1 values (1),(1);
ERROR 23000: Duplicate entry '1' for key 1
show slave status;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 1 master-bin.000001 213 slave-relay-bin.000002 257 master-bin.000001 Yes Yes test.t1 0 0 213 257
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
+127.0.0.1 root MASTER_PORT 1 master-bin.000001 213 slave-relay-bin.000002 257 master-bin.000001 Yes Yes test.t1 0 0 213 257 No
show tables like 't1';
Tables_in_test (t1)
drop table t1;
diff --git a/mysql-test/r/rpl_flush_log_loop.result b/mysql-test/r/rpl_flush_log_loop.result
index a1709647f19..5b5a47d438d 100644
--- a/mysql-test/r/rpl_flush_log_loop.result
+++ b/mysql-test/r/rpl_flush_log_loop.result
@@ -13,5 +13,5 @@ master_password='',master_port=SLAVE_PORT;
start slave;
flush logs;
show slave status;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root SLAVE_PORT 60 slave-bin.000001 79 relay-log.000002 4 slave-bin.000001 Yes Yes 0 0 79 4
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
+127.0.0.1 root SLAVE_PORT 60 slave-bin.000001 79 relay-log.000002 4 slave-bin.000001 Yes Yes 0 0 79 4 No
diff --git a/mysql-test/r/rpl_loaddata.result b/mysql-test/r/rpl_loaddata.result
index 55dcf2f4f0f..8b31d41412d 100644
--- a/mysql-test/r/rpl_loaddata.result
+++ b/mysql-test/r/rpl_loaddata.result
@@ -28,8 +28,8 @@ load data infile '../../std_data/rpl_loaddata.dat' into table t1;
set global sql_slave_skip_counter=1;
start slave;
show slave status;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 1 master-bin.000001 1311 slave-relay-bin.000002 1355 master-bin.000001 Yes Yes 0 0 1311 1355
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
+127.0.0.1 root MASTER_PORT 1 master-bin.000001 1311 slave-relay-bin.000002 1355 master-bin.000001 Yes Yes 0 0 1311 1355 No
set sql_log_bin=0;
delete from t1;
set sql_log_bin=1;
@@ -38,8 +38,8 @@ stop slave;
change master to master_user='test';
change master to master_user='root';
show slave status;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 1 master-bin.000001 1442 slave-relay-bin.000001 4 master-bin.000001 No No 0 0 1442 4
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
+127.0.0.1 root MASTER_PORT 1 master-bin.000001 1442 slave-relay-bin.000001 4 master-bin.000001 No No 0 0 1442 4 No
set global sql_slave_skip_counter=1;
start slave;
set sql_log_bin=0;
@@ -49,5 +49,5 @@ load data infile '../../std_data/rpl_loaddata.dat' into table t1;
stop slave;
reset slave;
show slave status;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 1 4 slave-relay-bin.000001 4 No No 0 0 0 4
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
+127.0.0.1 root MASTER_PORT 1 4 slave-relay-bin.000001 4 No No 0 0 0 4 No
diff --git a/mysql-test/r/rpl_log.result b/mysql-test/r/rpl_log.result
index ab45826a3e7..1583ac3038d 100644
--- a/mysql-test/r/rpl_log.result
+++ b/mysql-test/r/rpl_log.result
@@ -92,7 +92,7 @@ slave-bin.000002 4 Query 1 110 use `test`; create table t1 (n int)
slave-bin.000002 62 Query 1 168 use `test`; insert into t1 values (1)
slave-bin.000002 122 Query 1 228 use `test`; drop table t1
show slave status;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 1 master-bin.000002 276 slave-relay-bin.000003 214 master-bin.000002 Yes Yes 0 0 276 214
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
+127.0.0.1 root MASTER_PORT 1 master-bin.000002 276 slave-relay-bin.000003 214 master-bin.000002 Yes Yes 0 0 276 214 No
show binlog events in 'slave-bin.000005' from 4;
ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Could not find target log
diff --git a/mysql-test/r/rpl_log_pos.result b/mysql-test/r/rpl_log_pos.result
index bc655b9b15a..df6a83fff35 100644
--- a/mysql-test/r/rpl_log_pos.result
+++ b/mysql-test/r/rpl_log_pos.result
@@ -8,26 +8,26 @@ show master status;
File Position Binlog_do_db Binlog_ignore_db
master-bin.000001 79
show slave status;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 1 master-bin.000001 79 slave-relay-bin.000002 123 master-bin.000001 Yes Yes 0 0 79 123
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
+127.0.0.1 root MASTER_PORT 1 master-bin.000001 79 slave-relay-bin.000002 123 master-bin.000001 Yes Yes 0 0 79 123 No
stop slave;
change master to master_log_pos=73;
start slave;
stop slave;
change master to master_log_pos=73;
show slave status;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 1 master-bin.000001 73 slave-relay-bin.000001 4 master-bin.000001 No No 0 0 73 4
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
+127.0.0.1 root MASTER_PORT 1 master-bin.000001 73 slave-relay-bin.000001 4 master-bin.000001 No No 0 0 73 4 No
start slave;
show slave status;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 1 master-bin.000001 73 slave-relay-bin.000001 48 master-bin.000001 No Yes 0 0 73 48
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
+127.0.0.1 root MASTER_PORT 1 master-bin.000001 73 slave-relay-bin.000001 48 master-bin.000001 No Yes 0 0 73 48 No
stop slave;
change master to master_log_pos=173;
start slave;
show slave status;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 1 master-bin.000001 173 slave-relay-bin.000001 4 master-bin.000001 No Yes 0 0 173 4
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
+127.0.0.1 root MASTER_PORT 1 master-bin.000001 173 slave-relay-bin.000001 4 master-bin.000001 No Yes 0 0 173 4 No
show master status;
File Position Binlog_do_db Binlog_ignore_db
master-bin.000001 79
diff --git a/mysql-test/r/rpl_max_relay_size.result b/mysql-test/r/rpl_max_relay_size.result
index 741b3538799..98efa3d848e 100644
--- a/mysql-test/r/rpl_max_relay_size.result
+++ b/mysql-test/r/rpl_max_relay_size.result
@@ -15,8 +15,8 @@ select @@global.max_relay_log_size;
4096
start slave;
show slave status;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 1 master-bin.000001 50477 slave-relay-bin.000014 1221 master-bin.000001 Yes Yes 0 0 50477 1221
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
+127.0.0.1 root MASTER_PORT 1 master-bin.000001 50477 slave-relay-bin.000014 1221 master-bin.000001 Yes Yes 0 0 50477 1221 No
stop slave;
reset slave;
set global max_relay_log_size=(5*4096);
@@ -25,8 +25,8 @@ select @@global.max_relay_log_size;
20480
start slave;
show slave status;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 1 master-bin.000001 50477 slave-relay-bin.000004 9457 master-bin.000001 Yes Yes 0 0 50477 9457
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
+127.0.0.1 root MASTER_PORT 1 master-bin.000001 50477 slave-relay-bin.000004 9457 master-bin.000001 Yes Yes 0 0 50477 9457 No
stop slave;
reset slave;
set global max_relay_log_size=0;
@@ -35,26 +35,26 @@ select @@global.max_relay_log_size;
0
start slave;
show slave status;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 1 master-bin.000001 50477 slave-relay-bin.000008 1283 master-bin.000001 Yes Yes 0 0 50477 1283
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
+127.0.0.1 root MASTER_PORT 1 master-bin.000001 50477 slave-relay-bin.000008 1283 master-bin.000001 Yes Yes 0 0 50477 1283 No
stop slave;
reset slave;
flush logs;
show slave status;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 1 4 slave-relay-bin.000001 4 No No 0 0 0 4
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
+127.0.0.1 root MASTER_PORT 1 4 slave-relay-bin.000001 4 No No 0 0 0 4 No
reset slave;
start slave;
flush logs;
create table t1 (a int);
show slave status;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 1 master-bin.000001 50535 slave-relay-bin.000009 62 master-bin.000001 Yes Yes 0 0 50535 62
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
+127.0.0.1 root MASTER_PORT 1 master-bin.000001 50535 slave-relay-bin.000009 62 master-bin.000001 Yes Yes 0 0 50535 62 No
flush logs;
drop table t1;
show slave status;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 1 master-bin.000001 50583 slave-relay-bin.000010 52 master-bin.000001 Yes Yes 0 0 50583 52
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
+127.0.0.1 root MASTER_PORT 1 master-bin.000001 50583 slave-relay-bin.000010 52 master-bin.000001 Yes Yes 0 0 50583 52 No
flush logs;
show master status;
File Position Binlog_do_db Binlog_ignore_db
diff --git a/mysql-test/r/rpl_openssl.result b/mysql-test/r/rpl_openssl.result
new file mode 100644
index 00000000000..f6c084d5a71
--- /dev/null
+++ b/mysql-test/r/rpl_openssl.result
@@ -0,0 +1,30 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+grant replication slave on *.* to replssl@'%' require ssl;
+create table t1 (t int);
+stop slave;
+change master to master_user='replssl',master_password='';
+start slave;
+insert into t1 values (1);
+select * from t1;
+t
+stop slave;
+change master to master_ssl=1 , master_ssl_ca ='MYSQL_TEST_DIR/std_data/cacert.pem', master_ssl_cert='MYSQL_TEST_DIR/std_data/client-cert.pem', master_ssl_key='MYSQL_TEST_DIR/std_data/client-key.pem';
+start slave;
+select * from t1;
+t
+1
+show slave status;
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
+127.0.0.1 replssl MASTER_MYPORT 1 master-bin.000001 289 slave-relay-bin.000001 108 master-bin.000001 Yes Yes 0 0 289 108 Yes MYSQL_TEST_DIR/std_data/cacert.pem MYSQL_TEST_DIR/std_data/client-cert.pem MYSQL_TEST_DIR/std_data/client-key.pem
+stop slave;
+change master to master_user='root',master_password='', master_ssl=0;
+start slave;
+drop table t1;
+show slave status;
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
+127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 337 slave-relay-bin.000001 96 master-bin.000001 Yes Yes 0 0 337 96 No MYSQL_TEST_DIR/std_data/cacert.pem MYSQL_TEST_DIR/std_data/client-cert.pem MYSQL_TEST_DIR/std_data/client-key.pem
diff --git a/mysql-test/r/rpl_redirect.result b/mysql-test/r/rpl_redirect.result
index 79ff6685706..ce82ef54355 100644
--- a/mysql-test/r/rpl_redirect.result
+++ b/mysql-test/r/rpl_redirect.result
@@ -5,7 +5,7 @@ reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
SHOW SLAVE STATUS;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
SHOW SLAVE HOSTS;
Server_id Host Port Rpl_recovery_rank Master_id
2 127.0.0.1 SLAVE_PORT 2 1
diff --git a/mysql-test/r/rpl_replicate_do.result b/mysql-test/r/rpl_replicate_do.result
index ad92ee5b491..a2cafd67a67 100644
--- a/mysql-test/r/rpl_replicate_do.result
+++ b/mysql-test/r/rpl_replicate_do.result
@@ -27,5 +27,5 @@ select * from t11;
ERROR 42S02: Table 'test.t11' doesn't exist
drop table if exists t1,t2,t11;
show slave status;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 1 master-bin.000001 1281 slave-relay-bin.000002 1325 master-bin.000001 Yes Yes test.t1 0 0 1281 1325
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
+127.0.0.1 root MASTER_PORT 1 master-bin.000001 1281 slave-relay-bin.000002 1325 master-bin.000001 Yes Yes test.t1 0 0 1281 1325 No
diff --git a/mysql-test/r/rpl_reset_slave.result b/mysql-test/r/rpl_reset_slave.result
index 239c4158410..a0750a57260 100644
--- a/mysql-test/r/rpl_reset_slave.result
+++ b/mysql-test/r/rpl_reset_slave.result
@@ -5,18 +5,18 @@ reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
show slave status;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 1 master-bin.000001 79 slave-relay-bin.000002 123 master-bin.000001 Yes Yes 0 0 79 123
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
+127.0.0.1 root MASTER_PORT 1 master-bin.000001 79 slave-relay-bin.000002 123 master-bin.000001 Yes Yes 0 0 79 123 No
stop slave;
change master to master_user='test';
show slave status;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 test MASTER_PORT 1 master-bin.000001 79 slave-relay-bin.000001 4 master-bin.000001 No No 0 0 79 4
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
+127.0.0.1 test MASTER_PORT 1 master-bin.000001 79 slave-relay-bin.000001 4 master-bin.000001 No No 0 0 79 4 No
reset slave;
show slave status;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 1 4 slave-relay-bin.000001 4 No No 0 0 0 4
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
+127.0.0.1 root MASTER_PORT 1 4 slave-relay-bin.000001 4 No No 0 0 0 4 No
start slave;
show slave status;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 1 master-bin.000001 79 slave-relay-bin.000002 123 master-bin.000001 Yes Yes 0 0 79 123
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
+127.0.0.1 root MASTER_PORT 1 master-bin.000001 79 slave-relay-bin.000002 123 master-bin.000001 Yes Yes 0 0 79 123 No
diff --git a/mysql-test/r/rpl_rotate_logs.result b/mysql-test/r/rpl_rotate_logs.result
index 7c5057c7fb2..c472b313365 100644
--- a/mysql-test/r/rpl_rotate_logs.result
+++ b/mysql-test/r/rpl_rotate_logs.result
@@ -15,8 +15,8 @@ insert into temp_table values ("testing temporary tables");
create table t1 (s text);
insert into t1 values('Could not break slave'),('Tried hard');
show slave status;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 60 master-bin.000001 417 slave-relay-bin.000001 461 master-bin.000001 Yes Yes 0 0 417 461
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
+127.0.0.1 root MASTER_PORT 60 master-bin.000001 417 slave-relay-bin.000001 461 master-bin.000001 Yes Yes 0 0 417 461 No
select * from t1;
s
Could not break slave
@@ -56,8 +56,8 @@ Log_name
master-bin.000003
insert into t2 values (65);
show slave status;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 60 master-bin.000003 290 slave-relay-bin.000001 1088 master-bin.000003 Yes Yes 0 0 290 1088
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
+127.0.0.1 root MASTER_PORT 60 master-bin.000003 290 slave-relay-bin.000001 1088 master-bin.000003 Yes Yes 0 0 290 1088 No
select * from t2;
m
34
@@ -80,8 +80,8 @@ select * from t4;
a
testing temporary tables part 2
show slave status;
-Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 60 master-bin.000004 2886 slave-relay-bin.000001 7891 master-bin.000004 Yes Yes 0 0 2886 7891
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
+127.0.0.1 root MASTER_PORT 60 master-bin.000004 2886 slave-relay-bin.000001 7891 master-bin.000004 Yes Yes 0 0 2886 7891 No
lock tables t3 read;
select count(*) from t3 where n >= 4;
count(*)
diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result
index 201d1b541ae..682c48c9c55 100644
--- a/mysql-test/r/show_check.result
+++ b/mysql-test/r/show_check.result
@@ -43,7 +43,7 @@ wait_timeout 28800
show variables like "this_doesn't_exists%";
Variable_name Value
show table status from test like "this_doesn't_exists%";
-Name Type Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Charset Create_options Comment
+Name Type Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Charset Checksum Create_options Comment
show databases;
Database
mysql
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index 0fb5625854b..3340c2e188c 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -1355,3 +1355,34 @@ a
2
10
drop table t1,t2;
+CREATE TABLE t1 (s1 CHAR(5) COLLATE latin1_german1_ci,
+s2 CHAR(5) COLLATE latin1_swedish_ci);
+INSERT INTO t1 VALUES ('z','?');
+select * from t1 where s1 > (select max(s2) from t1);
+ERROR HY000: Illegal mix of collations (latin1_german1_ci,IMPLICIT) and (latin1_swedish_ci,IMPLICIT) for operation '>'
+select * from t1 where s1 > any (select max(s2) from t1);
+ERROR HY000: Illegal mix of collations (latin1_german1_ci,IMPLICIT) and (latin1_swedish_ci,IMPLICIT) for operation '>'
+drop table t1;
+create table t1(toid int,rd int);
+create table t2(userid int,pmnew int,pmtotal int);
+insert into t2 values(1,0,0),(2,0,0);
+insert into t1 values(1,0),(1,0),(1,0),(1,12),(1,15),(1,123),(1,12312),(1,12312),(1,123),(2,0),(2,0),(2,1),(2,2);
+select userid,pmtotal,pmnew, (select count(rd) from t1 where toid=t2.userid) calc_total, (select count(rd) from t1 where rd=0 and toid=t2.userid) calc_new from t2 where userid in (select distinct toid from t1);
+userid pmtotal pmnew calc_total calc_new
+1 0 0 9 3
+2 0 0 4 2
+drop table t1, t2;
+create table t1 (s1 char(5));
+select (select 'a','b' from t1 union select 'a','b' from t1) from t1;
+ERROR 21000: Cardinality error (more/less than 1 columns)
+insert into t1 values ('tttt');
+select * from t1 where ('a','b')=(select 'a','b' from t1 union select 'a','b' from t1);
+s1
+tttt
+explain (select * from t1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 system NULL NULL NULL NULL 1
+(select * from t1);
+s1
+tttt
+drop table t1;
diff --git a/mysql-test/r/symlink.result b/mysql-test/r/symlink.result
index 216fb4d6124..4469ca36941 100644
--- a/mysql-test/r/symlink.result
+++ b/mysql-test/r/symlink.result
@@ -46,8 +46,6 @@ alter table t8 rename t7;
rename table t7 to t9;
drop table t1;
Got one of the listed errors
-Warnings:
-Note 1008 Can't drop database 'test_mysqltest'; database doesn't exist
Got one of the listed errors
Got one of the listed errors
Got one of the listed errors
diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result
index 396eba7197b..fc72f55172b 100644
--- a/mysql-test/r/union.result
+++ b/mysql-test/r/union.result
@@ -103,7 +103,7 @@ a b
2 b
select found_rows();
found_rows()
-6
+8
explain select a,b from t1 union all select a,b from t2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 4
diff --git a/mysql-test/t/connect.test b/mysql-test/t/connect.test
index e6ccc52f0d4..7585ff0f608 100644
--- a/mysql-test/t/connect.test
+++ b/mysql-test/t/connect.test
@@ -48,8 +48,9 @@ flush privileges;
#connect (con1,localhost,test,gambling2,"");
#show tables;
connect (con1,localhost,test,gambling2,mysql);
+set password=old_password('gambling3');
show tables;
-connect (con1,localhost,test,gambling2,test);
+connect (con1,localhost,test,gambling3,test);
show tables;
# Re enable this one day if error handling on connect will take place
@@ -63,7 +64,9 @@ show tables;
#connect (con1,localhost,test,zorro,);
#--error 1045
+
# remove user 'test' so that other tests which may use 'test'
# do not depend on this test.
+
delete from mysql.user where user="test";
flush privileges;
diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test
index ebb3854309b..2e21768dc0b 100644
--- a/mysql-test/t/create.test
+++ b/mysql-test/t/create.test
@@ -219,6 +219,44 @@ drop table t1;
#
# Bug # 801
#
-
create table t1 select x'4132';
drop table t1;
+
+#
+# Test types of data for create select with functions
+#
+
+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)
+values(2,-2,2,'1825-12-14','a','2003-1-1 3:2:1','4:3:2','binary data');
+select * from t1;
+select a,
+ ifnull(b,cast(-7 as signed)) as b,
+ ifnull(c,cast(7 as unsigned)) as c,
+ ifnull(d,cast('2000-01-01' as date)) as d,
+ ifnull(e,cast('b' as char)) as e,
+ ifnull(f,cast('2000-01-01' as datetime)) as f,
+ ifnull(g,cast('5:4:3' as time)) as g,
+ ifnull(h,cast('yet another binary data' as binary)) as h,
+ addtime(cast('1:0:0' as time),cast('1:0:0' as time)) as dd
+from t1;
+
+create table t2
+select
+ a,
+ ifnull(b,cast(-7 as signed)) as b,
+ ifnull(c,cast(7 as unsigned)) as c,
+ ifnull(d,cast('2000-01-01' as date)) as d,
+ ifnull(e,cast('b' as char)) as e,
+ ifnull(f,cast('2000-01-01' as datetime)) as f,
+ ifnull(g,cast('5:4:3' as time)) as g,
+ ifnull(h,cast('yet another binary data' as binary)) as h,
+ addtime(cast('1:0:0' as time),cast('1:0:0' as time)) as dd
+from t1;
+explain t2;
+
+select * from t2;
+
+drop table t1, t2;
+
diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test
index c3edbabcd53..3c735878e46 100644
--- a/mysql-test/t/derived.test
+++ b/mysql-test/t/derived.test
@@ -94,3 +94,16 @@ drop table t1,t2;
# derived table reference
#
SELECT a.x FROM (SELECT 1 AS x) AS a HAVING a.x = 1;
+
+#
+# Test for select if database is not selected.
+#
+# Connect without a database
+create table a1 select 1 as a;
+connect (con1,localhost,mysqltest_1,,*NO-ONE*,$MASTER_MYPORT,master.sock);
+connection con1;
+--error 1046
+select 2 as a from (select * from a1) b;
+use test;
+select 2 as a from (select * from a1) b;
+drop table a1;
diff --git a/mysql-test/t/drop.test b/mysql-test/t/drop.test
index a55cbb45fd9..43329a849f8 100644
--- a/mysql-test/t/drop.test
+++ b/mysql-test/t/drop.test
@@ -43,3 +43,13 @@ drop database mysqltest;
show databases;
--error 1008
drop database mysqltest;
+
+# test create table and FLUSH TABLES WITH READ LOCK
+drop table t1;
+flush tables with read lock;
+--error 1223;
+create table t1(n int);
+unlock tables;
+create table t1(n int);
+show tables;
+drop table t1;
diff --git a/mysql-test/t/func_crypt.test b/mysql-test/t/func_crypt.test
index c72356bda1a..c1c7090cab3 100644
--- a/mysql-test/t/func_crypt.test
+++ b/mysql-test/t/func_crypt.test
@@ -4,7 +4,33 @@ select length(encrypt('foo', 'ff')) <> 0;
--replace_result $1$aa$4OSUA5cjdx0RUQ08opV27/ aaqPiZY5xR5l.
# Test new and old password handling functions
-select password("a",""), password("a",NULL), password("","a"), password(NULL,"a");
-select password("aaaaaaaaaaaaaaaa","a"), password("a","aaaaaaaaaaaaaaaa");
-select old_password('test'), length(password("1")), length(encrypt('test')), encrypt('test','aa');
-select old_password(""), old_password(NULL), password(""), password(NULL);
+select password('abc');
+select password('');
+select old_password('abc');
+select old_password('');
+select password('gabbagabbahey');
+select old_password('idkfa');
+select length(password('1'));
+select length(encrypt('test'));
+select encrypt('test','aa');
+select old_password(NULL);
+select password(NULL);
+set global old_passwords=on;
+select password('');
+select old_password('');
+select password('idkfa');
+select old_password('idkfa');
+set old_passwords=on;
+select password('idkfa');
+select old_password('idkfa');
+set global old_passwords=off;
+select password('idkfa');
+select old_password('idkfa');
+
+# this test shows that new scrambles honor spaces in passwords:
+set old_passwords=off;
+select password('idkfa ');
+select password('idkfa');
+select password(' idkfa');
+select old_password('idkfa');
+select old_password(' i d k f a ');
diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test
index f426f9ca4ee..b10f6d2af21 100644
--- a/mysql-test/t/func_gconcat.test
+++ b/mysql-test/t/func_gconcat.test
@@ -91,6 +91,11 @@ insert into t2 values (1,4), (5,4), (5,5);
--replace_result www.help.com X www.host.com X www.google.com X
select REQ_ID, Group_Concat(URL) as URL from t1, t2 where
t2.URL_ID = t1.URL_ID group by REQ_ID;
+# check min/max function
+--replace_result www.help.com X www.host.com X www.google.com X
+select REQ_ID, Group_Concat(URL) as URL, Min(t1.URL_ID) urll,
+Max(t1.URL_ID) urlg from t1, t2 where t2.URL_ID = t1.URL_ID group by REQ_ID;
+
drop table t1;
drop table t2;
@@ -99,3 +104,19 @@ insert into t1 values (1,'longername'),(1,'evenlongername');
select ifnull(group_concat(concat(t1.id, ':', t1.name)), 'shortname') as 'without distinct: how it should be' from t1;
select distinct ifnull(group_concat(concat(t1.id, ':', t1.name)), 'shortname') as 'with distinct: cutoff at length of shortname' from t1;
drop table t1;
+
+# check zero rows
+create table t1(id int);
+create table t2(id int);
+insert into t1 values(0),(1);
+select group_concat(t1.id) FROM t1,t2;
+drop table t1;
+drop table t2;
+
+# check having
+create table t1 (bar varchar(32));
+insert into t1 values('test'),('test2');
+select * from t1 having group_concat(bar)='';
+drop table t1;
+
+
diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test
index 6e7eb0ea06f..823ac25cf66 100644
--- a/mysql-test/t/innodb.test
+++ b/mysql-test/t/innodb.test
@@ -134,6 +134,21 @@ rollback;
drop table t1;
#
+# Test for commit and FLUSH TABLES WITH READ LOCK
+#
+
+create table t1 (n int not null primary key) type=innodb;
+start transaction;
+insert into t1 values (4);
+flush tables with read lock;
+--error 1223;
+commit;
+unlock tables;
+commit;
+select * from t1;
+drop table t1;
+
+#
# Testing transactions
#
@@ -925,3 +940,29 @@ SELECT t2.id, t1.label FROM t2 INNER JOIN
(SELECT t1.id_object as id_object FROM t1 WHERE t1.label LIKE '%test%') AS lbl
ON (t2.id = lbl.id_object) INNER JOIN t1 ON (t2.id = t1.id_object);
drop table t1,t2;
+
+#
+# Bug #1078
+#
+create table t1 (c1 char(5) unique not null, c2 int, stamp timestamp) type=innodb;
+select * from t1;
+--error 1031
+replace delayed into t1 (c1, c2) values ( "text1","11"),( "text2","12");
+select * from t1;
+--error 1031
+replace delayed into t1 (c1, c2) values ( "text1","12"),( "text2","13"),( "text3","14", "a" ),( "text4","15", "b" );
+select * from t1;
+drop table t1;
+
+create table t1 (a int, b varchar(200), c text not null) checksum=1 type=myisam;
+create table t2 (a int, b varchar(200), c text not null) checksum=0 type=innodb;
+create table t3 (a int, b varchar(200), c text not null) checksum=1 type=innodb;
+insert t1 values (1, "aaa", "bbb"), (NULL, "", "ccccc"), (0, NULL, "");
+insert t2 select * from t1;
+insert t3 select * from t1;
+checksum table t1, t2, t3, t4 quick;
+checksum table t1, t2, t3, t4;
+checksum table t1, t2, t3, t4 extended;
+#show table status;
+drop table t1,t2,t3;
+
diff --git a/mysql-test/t/loaddata.test b/mysql-test/t/loaddata.test
index 2f484d30ff7..199da9c4a84 100644
--- a/mysql-test/t/loaddata.test
+++ b/mysql-test/t/loaddata.test
@@ -15,7 +15,3 @@ truncate table t1;
load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',' LINES STARTING BY ',' (b,c,d);
SELECT * from t1;
drop table t1;
-
-
-
-
diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test
index 5267b57259b..7e6242c9b68 100644
--- a/mysql-test/t/myisam.test
+++ b/mysql-test/t/myisam.test
@@ -363,4 +363,15 @@ drop table t1,t2;
CREATE TABLE t1 (`a` int(11) NOT NULL default '0', `b` int(11) NOT NULL default '0', UNIQUE KEY `a` USING RTREE (`a`,`b`)) TYPE=MyISAM;
# INSERT INTO t1 VALUES (1,1),(1,1);
# DELETE FROM rt WHERE a<1;
-DROP TABLE IF EXISTS t1;
+# DROP TABLE IF EXISTS t1;
+
+create table t1 (a int, b varchar(200), c text not null) checksum=1;
+create table t2 (a int, b varchar(200), c text not null) checksum=0;
+insert t1 values (1, "aaa", "bbb"), (NULL, "", "ccccc"), (0, NULL, "");
+insert t2 select * from t1;
+checksum table t1, t2, t3 quick;
+checksum table t1, t2, t3;
+checksum table t1, t2, t3 extended;
+#show table status;
+drop table t1,t2;
+
diff --git a/mysql-test/t/olap.test b/mysql-test/t/olap.test
index 3b1e3fac7c2..17bf6230f76 100644
--- a/mysql-test/t/olap.test
+++ b/mysql-test/t/olap.test
@@ -77,3 +77,14 @@ select product, country_id , year, sum(profit) from t1 group by product, country
drop table t1,t2;
+#
+# Test bug with const tables
+#
+
+CREATE TABLE t1 (i int);
+INSERT INTO t1 VALUES(100);
+CREATE TABLE t2 (i int);
+INSERT INTO t2 VALUES (100),(200);
+SELECT i, COUNT(*) FROM t1 GROUP BY i WITH ROLLUP;
+SELECT t1.i, t2.i, COUNT(*) FROM t1,t2 GROUP BY t1.i,t2.i WITH ROLLUP;
+drop table t1,t2;
diff --git a/mysql-test/t/rpl_openssl.test b/mysql-test/t/rpl_openssl.test
new file mode 100644
index 00000000000..bd658786bd7
--- /dev/null
+++ b/mysql-test/t/rpl_openssl.test
@@ -0,0 +1,60 @@
+source include/have_openssl_1.inc;
+source include/master-slave.inc;
+
+# We don't test all types of ssl auth params here since it's a bit hard
+# until problems with OpenSSL 0.9.7 are unresolved
+
+# creating replication user for whom ssl auth is required
+# preparing playground
+connection master;
+grant replication slave on *.* to replssl@'%' require ssl;
+create table t1 (t int);
+save_master_pos;
+
+#syncing with master
+connection slave;
+sync_with_master;
+
+#trying to use this user without ssl
+stop slave;
+change master to master_user='replssl',master_password='';
+start slave;
+
+#showing that replication don't work
+connection master;
+insert into t1 values (1);
+#reasonable timeout for changes to propagate to slave
+sleep 3;
+connection slave;
+select * from t1;
+
+#showing that replication could work with ssl params
+stop slave;
+--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
+eval change master to master_ssl=1 , master_ssl_ca ='$MYSQL_TEST_DIR/std_data/cacert.pem', master_ssl_cert='$MYSQL_TEST_DIR/std_data/client-cert.pem', master_ssl_key='$MYSQL_TEST_DIR/std_data/client-key.pem';
+start slave;
+
+#avoiding unneeded sleeps
+connection master;
+save_master_pos;
+connection slave;
+sync_with_master;
+
+#checking that replication is ok
+select * from t1;
+
+#checking show slave status
+--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR $MASTER_MYPORT MASTER_MYPORT
+show slave status;
+
+#checking if replication works without ssl also performing clean up
+stop slave;
+change master to master_user='root',master_password='', master_ssl=0;
+start slave;
+connection master;
+drop table t1;
+save_master_pos;
+connection slave;
+sync_with_master;
+--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR $MASTER_MYPORT MASTER_MYPORT
+show slave status;
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index e1c9e09ae6d..bd6a4037f3d 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -901,3 +901,36 @@ insert into t3 values (1),(2),(10),(50);
select a from t3 where t3.a in (select a from t1 where a <= 3 union select * from t2 where a <= 30);
drop table t1,t2;
+#
+# collation test
+#
+CREATE TABLE t1 (s1 CHAR(5) COLLATE latin1_german1_ci,
+ s2 CHAR(5) COLLATE latin1_swedish_ci);
+INSERT INTO t1 VALUES ('z','?');
+-- error 1266
+select * from t1 where s1 > (select max(s2) from t1);
+-- error 1266
+select * from t1 where s1 > any (select max(s2) from t1);
+drop table t1;
+
+#
+# aggregate functions reinitialization
+#
+create table t1(toid int,rd int);
+create table t2(userid int,pmnew int,pmtotal int);
+insert into t2 values(1,0,0),(2,0,0);
+insert into t1 values(1,0),(1,0),(1,0),(1,12),(1,15),(1,123),(1,12312),(1,12312),(1,123),(2,0),(2,0),(2,1),(2,2);
+select userid,pmtotal,pmnew, (select count(rd) from t1 where toid=t2.userid) calc_total, (select count(rd) from t1 where rd=0 and toid=t2.userid) calc_new from t2 where userid in (select distinct toid from t1);
+drop table t1, t2;
+
+#
+# row union
+#
+create table t1 (s1 char(5));
+-- error 1240
+select (select 'a','b' from t1 union select 'a','b' from t1) from t1;
+insert into t1 values ('tttt');
+select * from t1 where ('a','b')=(select 'a','b' from t1 union select 'a','b' from t1);
+explain (select * from t1);
+(select * from t1);
+drop table t1;
diff --git a/mysys/Makefile.am b/mysys/Makefile.am
index 5b1c859cb2a..9e563755ebd 100644
--- a/mysys/Makefile.am
+++ b/mysys/Makefile.am
@@ -29,7 +29,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c\
mf_path.c mf_loadpath.c\
my_open.c my_create.c my_dup.c my_seek.c my_read.c \
my_pread.c my_write.c \
- mf_keycache.c \
+ mf_keycache.c my_crc32.c \
mf_iocache.c mf_iocache2.c mf_cache.c mf_tempfile.c \
mf_tempdir.c my_lock.c mf_brkhant.c my_alarm.c \
my_malloc.c my_realloc.c my_once.c mulalloc.c \
diff --git a/mysys/checksum.c b/mysys/checksum.c
index 1dd135c7ad9..664e768ef4e 100644
--- a/mysys/checksum.c
+++ b/mysys/checksum.c
@@ -19,19 +19,22 @@
#include "my_sys.h"
/*
- Calculate a long checksum for a memoryblock. Used to verify pack_isam
-
+ Calculate a long checksum for a memoryblock.
+
SYNOPSIS
- checksum()
- mem Pointer to memory block
- count Count of bytes
+ my_checksum()
+ crc start value for crc
+ pos pointer to memory block
+ length length of the block
*/
-ulong checksum(const byte *mem, uint count)
+ha_checksum my_checksum(ha_checksum crc, const byte *pos, uint length)
{
- ulong crc;
- for (crc= 0; count-- ; mem++)
- crc= ((crc << 1) + *((uchar*) mem)) +
- test(crc & ((ulong) 1L << (8*sizeof(ulong)-1)));
+/* const byte *end=pos+length;
+ for ( ; pos != end ; pos++)
+ crc=((crc << 8) + *((uchar*) pos)) + (crc >> (8*sizeof(ha_checksum)-8));
return crc;
+*/
+ return (ha_checksum)crc32((uint)crc, (const uchar *)pos, length);
}
+
diff --git a/mysys/my_crc32.c b/mysys/my_crc32.c
new file mode 100644
index 00000000000..5514b01ede2
--- /dev/null
+++ b/mysys/my_crc32.c
@@ -0,0 +1,36 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "mysys_priv.h"
+
+#ifndef HAVE_COMPRESS
+
+/* minimal set of defines for using crc32() from zlib codebase */
+#define _ZLIB_H
+#define ZEXPORT
+#define Z_NULL 0
+#define OF(args) args
+#undef DYNAMIC_CRC_TABLE
+typedef uchar Byte;
+typedef uchar Bytef;
+typedef uint uInt;
+typedef ulong uLong;
+typedef ulong uLongf;
+
+#include "../zlib/crc32.c"
+
+#endif
+
diff --git a/mysys/my_malloc.c b/mysys/my_malloc.c
index b273363aaf1..df9fe1f9bc4 100644
--- a/mysys/my_malloc.c
+++ b/mysys/my_malloc.c
@@ -24,26 +24,26 @@
/* My memory allocator */
-gptr my_malloc(unsigned int Size, myf MyFlags)
+gptr my_malloc(unsigned int size, myf my_flags)
{
gptr point;
DBUG_ENTER("my_malloc");
- DBUG_PRINT("my",("Size: %u MyFlags: %d",Size, MyFlags));
+ DBUG_PRINT("my",("size: %u my_flags: %d",size, my_flags));
- if (!Size)
- Size=1; /* Safety */
- if ((point = (char*)malloc(Size)) == NULL)
+ if (!size)
+ size=1; /* Safety */
+ if ((point = (char*)malloc(size)) == NULL)
{
my_errno=errno;
- if (MyFlags & MY_FAE)
+ if (my_flags & MY_FAE)
error_handler_hook=fatal_error_handler_hook;
- if (MyFlags & (MY_FAE+MY_WME))
- my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG),Size);
- if (MyFlags & MY_FAE)
+ if (my_flags & (MY_FAE+MY_WME))
+ my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG),size);
+ if (my_flags & MY_FAE)
exit(1);
}
- else if (MyFlags & MY_ZEROFILL)
- bzero(point,Size);
+ else if (my_flags & MY_ZEROFILL)
+ bzero(point,size);
DBUG_PRINT("exit",("ptr: %lx",point));
DBUG_RETURN(point);
} /* my_malloc */
@@ -64,29 +64,29 @@ void my_no_flags_free(gptr ptr)
/* malloc and copy */
-gptr my_memdup(const byte *from, uint length, myf MyFlags)
+gptr my_memdup(const byte *from, uint length, myf my_flags)
{
gptr ptr;
- if ((ptr=my_malloc(length,MyFlags)) != 0)
+ if ((ptr=my_malloc(length,my_flags)) != 0)
memcpy((byte*) ptr, (byte*) from,(size_t) length);
return(ptr);
}
-char *my_strdup(const char *from, myf MyFlags)
+char *my_strdup(const char *from, myf my_flags)
{
gptr ptr;
uint length=(uint) strlen(from)+1;
- if ((ptr=my_malloc(length,MyFlags)) != 0)
+ if ((ptr=my_malloc(length,my_flags)) != 0)
memcpy((byte*) ptr, (byte*) from,(size_t) length);
return((my_string) ptr);
}
-char *my_strdup_with_length(const byte *from, uint length, myf MyFlags)
+char *my_strdup_with_length(const byte *from, uint length, myf my_flags)
{
gptr ptr;
- if ((ptr=my_malloc(length+1,MyFlags)) != 0)
+ if ((ptr=my_malloc(length+1,my_flags)) != 0)
{
memcpy((byte*) ptr, (byte*) from,(size_t) length);
((char*) ptr)[length]=0;
diff --git a/mysys/my_realloc.c b/mysys/my_realloc.c
index 49d96c2eb4f..5190fa75dce 100644
--- a/mysys/my_realloc.c
+++ b/mysys/my_realloc.c
@@ -23,40 +23,41 @@
/* My memory re allocator */
-gptr my_realloc(gptr oldpoint, uint Size, myf MyFlags)
+gptr my_realloc(gptr oldpoint, uint size, myf my_flags)
{
gptr point;
DBUG_ENTER("my_realloc");
- DBUG_PRINT("my",("ptr: %lx Size: %u MyFlags: %d",oldpoint, Size, MyFlags));
+ DBUG_PRINT("my",("ptr: %lx size: %u my_flags: %d",oldpoint, size,
+ my_flags));
- if (!oldpoint && (MyFlags & MY_ALLOW_ZERO_PTR))
- DBUG_RETURN(my_malloc(Size,MyFlags));
+ if (!oldpoint && (my_flags & MY_ALLOW_ZERO_PTR))
+ DBUG_RETURN(my_malloc(size,my_flags));
#ifdef USE_HALLOC
- if (!(point = malloc(Size)))
+ if (!(point = malloc(size)))
{
- if (MyFlags & MY_FREE_ON_ERROR)
- my_free(oldpoint,MyFlags);
- if (MyFlags & MY_HOLD_ON_ERROR)
+ if (my_flags & MY_FREE_ON_ERROR)
+ my_free(oldpoint,my_flags);
+ if (my_flags & MY_HOLD_ON_ERROR)
DBUG_RETURN(oldpoint);
my_errno=errno;
- if (MyFlags & MY_FAE+MY_WME)
- my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG),Size);
+ if (my_flags & MY_FAE+MY_WME)
+ my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG),size);
}
else
{
- memcpy(point,oldpoint,Size);
+ memcpy(point,oldpoint,size);
free(oldpoint);
}
#else
- if ((point = (char*)realloc(oldpoint,Size)) == NULL)
+ if ((point = (char*)realloc(oldpoint,size)) == NULL)
{
- if (MyFlags & MY_FREE_ON_ERROR)
+ if (my_flags & MY_FREE_ON_ERROR)
my_free(oldpoint,MyFLAGS);
- if (MyFlags & MY_HOLD_ON_ERROR)
+ if (my_flags & MY_HOLD_ON_ERROR)
DBUG_RETURN(oldpoint);
my_errno=errno;
- if (MyFlags & (MY_FAE+MY_WME))
- my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG), Size);
+ if (my_flags & (MY_FAE+MY_WME))
+ my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG), size);
}
#endif
DBUG_PRINT("exit",("ptr: %lx",point));
diff --git a/scripts/mysql_config.sh b/scripts/mysql_config.sh
index 3cc5b3a5016..e8cc9322eaf 100644
--- a/scripts/mysql_config.sh
+++ b/scripts/mysql_config.sh
@@ -86,6 +86,8 @@ client_libs='@CLIENT_LIBS@'
libs="$ldflags -L'$pkglibdir' -lmysqlclient $client_libs"
libs=`echo $libs | sed -e 's; +;;'`
+libs_r="$ldflags -L'$pkglibdir' -lmysqlclient_r $client_libs"
+libs_r=`echo $libs_r | sed -e 's; +;;'`
cflags="-I'$pkgincludedir'"
embedded_libs="$ldflags -L'$pkglibdir' -lmysqld @LIBS@ @innodb_system_libs@"
@@ -95,6 +97,7 @@ Usage: $0 [OPTIONS]
Options:
--cflags [$cflags]
--libs [$libs]
+ --libs_r [$libs_r]
--socket [$socket]
--port [$port]
--version [$version]
@@ -109,6 +112,7 @@ while test $# -gt 0; do
case $1 in
--cflags) echo "$cflags" ;;
--libs) echo "$libs" ;;
+ --libs_r) echo "$libs_r" ;;
--socket) echo "$socket" ;;
--port) echo "$port" ;;
--version) echo "$version" ;;
diff --git a/scripts/mysql_create_system_tables.sh b/scripts/mysql_create_system_tables.sh
index 2739c45e750..c4cdc7b52d7 100644
--- a/scripts/mysql_create_system_tables.sh
+++ b/scripts/mysql_create_system_tables.sh
@@ -108,7 +108,7 @@ then
c_u="$c_u CREATE TABLE user ("
c_u="$c_u Host char(60) binary DEFAULT '' NOT NULL,"
c_u="$c_u User char(16) binary DEFAULT '' NOT NULL,"
- c_u="$c_u Password char(45) binary DEFAULT '' NOT NULL,"
+ c_u="$c_u Password char(41) binary DEFAULT '' NOT NULL,"
c_u="$c_u Select_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_u="$c_u Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_u="$c_u Update_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
diff --git a/scripts/mysql_fix_privilege_tables.sql b/scripts/mysql_fix_privilege_tables.sql
index 43dc6d89481..220bf4036db 100644
--- a/scripts/mysql_fix_privilege_tables.sql
+++ b/scripts/mysql_fix_privilege_tables.sql
@@ -1,10 +1,22 @@
+-- This script converts any old privilege tables to privilege tables suitable
+-- for MySQL 4.0.
+
+-- You can safely ignore all 'Duplicate column' and 'Unknown column' errors"
+-- as this just means that your tables where already up to date.
+-- This script is safe to run even if your tables are already up to date!
+
+-- On unix, you should use the mysql_fix_privilege_tables script to execute
+-- this sql script.
+-- On windows you should do 'mysql --force < mysql_fix_privilege_tables.sql'
+
+USE mysql;
ALTER TABLE user type=MyISAM;
ALTER TABLE db type=MyISAM;
ALTER TABLE host type=MyISAM;
ALTER TABLE func type=MyISAM;
ALTER TABLE columns_priv type=MyISAM;
ALTER TABLE tables_priv type=MyISAM;
-ALTER TABLE user change Password Password char(45) not null;
+ALTER TABLE user change Password Password char(41) not null;
ALTER TABLE user add File_priv enum('N','Y') NOT NULL;
CREATE TABLE IF NOT EXISTS func (
name char(64) DEFAULT '' NOT NULL,
diff --git a/sql-common/client.c b/sql-common/client.c
index 222f0bf0288..b4d875b8132 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -587,7 +587,7 @@ net_safe_read(MYSQL *mysql)
DBUG_PRINT("error",("Wrong connection or packet. fd: %s len: %d",
vio_description(net->vio),len));
#ifdef MYSQL_SERVER
- if (socket_errno == SOCKET_EINTR)
+ if (vio_errno(net->vio) == SOCKET_EINTR)
return (packet_error);
#endif /*MYSQL_SERVER*/
end_server(mysql);
@@ -636,7 +636,7 @@ void free_rows(MYSQL_DATA *cur)
}
}
-static my_bool
+static my_bool STDCALL
cli_advanced_command(MYSQL *mysql, enum enum_server_command command,
const char *header, ulong header_length,
const char *arg, ulong arg_length, my_bool skip_check)
@@ -1008,7 +1008,7 @@ void mysql_read_default_options(struct st_mysql_options *options,
else the lengths are calculated from the offset between pointers.
**************************************************************************/
-static void cli_fetch_lengths(ulong *to, MYSQL_ROW column, uint field_count)
+static void STDCALL cli_fetch_lengths(ulong *to, MYSQL_ROW column, uint field_count)
{
ulong *prev_length;
byte *start=0;
@@ -1392,76 +1392,6 @@ mysql_ssl_free(MYSQL *mysql __attribute__((unused)))
/*
- Handle password authentication
-*/
-
-my_bool mysql_autenticate(MYSQL *mysql, const char *passwd)
-{
- ulong pkt_length;
- NET *net= &mysql->net;
- char buff[SCRAMBLE41_LENGTH];
- char password_hash[SCRAMBLE41_LENGTH]; /* Used for storage of stage1 hash */
-
- /* We shall only query server if it expect us to do so */
- if ((pkt_length=net_safe_read(mysql)) == packet_error)
- goto error;
-
- if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
- {
- /*
- This should always happen with new server unless empty password
- OK/Error packets have zero as the first char
- */
- if (pkt_length == 24 && net->read_pos[0])
- {
- /* Old passwords will have '*' at the first byte of hash */
- if (net->read_pos[0] != '*')
- {
- /* Build full password hash as it is required to decode scramble */
- password_hash_stage1(buff, passwd);
- /* Store copy as we'll need it later */
- memcpy(password_hash,buff,SCRAMBLE41_LENGTH);
- /* Finally hash complete password using hash we got from server */
- password_hash_stage2(password_hash,(const char*) net->read_pos);
- /* Decypt and store scramble 4 = hash for stage2 */
- password_crypt((const char*) net->read_pos+4,mysql->scramble_buff,
- password_hash, SCRAMBLE41_LENGTH);
- mysql->scramble_buff[SCRAMBLE41_LENGTH]=0;
- /* Encode scramble with password. Recycle buffer */
- password_crypt(mysql->scramble_buff,buff,buff,SCRAMBLE41_LENGTH);
- }
- else
- {
- /* Create password to decode scramble */
- create_key_from_old_password(passwd,password_hash);
- /* Decypt and store scramble 4 = hash for stage2 */
- password_crypt((const char*) net->read_pos+4,mysql->scramble_buff,
- password_hash, SCRAMBLE41_LENGTH);
- mysql->scramble_buff[SCRAMBLE41_LENGTH]=0;
- /* Finally scramble decoded scramble with password */
- scramble(buff, mysql->scramble_buff, passwd,0);
- }
- /* Write second package of authentication */
- if (my_net_write(net,buff,SCRAMBLE41_LENGTH) || net_flush(net))
- {
- net->last_errno= CR_SERVER_LOST;
- strmov(net->sqlstate, unknown_sqlstate);
- strmov(net->last_error,ER(net->last_errno));
- goto error;
- }
- /* Read what server thinks about out new auth message report */
- if (net_safe_read(mysql) == packet_error)
- goto error;
- }
- }
- return 0;
-
-error:
- return 1;
-}
-
-
-/*
Note that the mysql argument must be initialized with mysql_init()
before calling mysql_real_connect !
*/
@@ -1553,7 +1483,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
mysql->server_status=SERVER_STATUS_AUTOCOMMIT;
/*
- Grab a socket and connect it to the server
+ Part 0: Grab a socket and connect it to the server
*/
#if defined(HAVE_SMEM)
if ((!mysql->options.protocol ||
@@ -1754,6 +1684,11 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
strmov(net->last_error,ER(net->last_errno));
goto error;
}
+
+ /*
+ Part 1: Connection established, read and parse first packet
+ */
+
if ((pkt_length=net_safe_read(mysql)) == packet_error)
goto error;
@@ -1774,8 +1709,13 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
end=strend((char*) net->read_pos+1);
mysql->thread_id=uint4korr(end+1);
end+=5;
- strmake(mysql->scramble_buff,end,8);
- end+=9;
+ /*
+ Scramble is split into two parts because old clients does not understand
+ long scrambles; here goes the first part.
+ */
+ strmake(mysql->scramble, end, SCRAMBLE_LENGTH_323);
+ end+= SCRAMBLE_LENGTH_323+1;
+
if (pkt_length >= (uint) (end+1 - (char*) net->read_pos))
mysql->server_capabilities=uint2korr(end);
if (pkt_length >= (uint) (end+18 - (char*) net->read_pos))
@@ -1784,6 +1724,14 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
mysql->server_language=end[2];
mysql->server_status=uint2korr(end+3);
}
+ end+= 18;
+ if (pkt_length >= (uint) (end + SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1 -
+ (char *) net->read_pos))
+ strmake(mysql->scramble+SCRAMBLE_LENGTH_323, end,
+ SCRAMBLE_LENGTH-SCRAMBLE_LENGTH_323);
+ else
+ mysql->server_capabilities&= ~CLIENT_SECURE_CONNECTION;
+
charset_number= mysql->server_language;
/* Set character set */
@@ -1860,9 +1808,12 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
mysql->unix_socket=0;
strmov(mysql->server_version,(char*) net->read_pos+1);
mysql->port=port;
- client_flag|=mysql->options.client_flag;
- /* Send client information for access check */
+ /*
+ Part 2: format and send client info to the server for access check
+ */
+
+ client_flag|=mysql->options.client_flag;
client_flag|=CLIENT_CAPABILITIES;
if (client_flag & CLIENT_MULTI_QUERIES)
client_flag|= CLIENT_MULTI_RESULTS;
@@ -1949,7 +1900,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
mysql->server_status, client_flag));
/* This needs to be changed as it's not useful with big packets */
if (user && user[0])
- strmake(end,user,32); /* Max user name */
+ strmake(end,user,USERNAME_LENGTH); /* Max user name */
else
read_user_name((char*) end);
@@ -1958,41 +1909,30 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
#include "_cust_libmysql.h"
#endif
DBUG_PRINT("info",("user: %s",end));
- /*
- We always start with old type handshake the only difference is message sent
- If server handles secure connection type we'll not send the real scramble
- */
- if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
+ end= strend(end) + 1;
+ if (passwd[0])
{
- if (passwd[0])
+ if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
{
- /* Prepare false scramble */
- end=strend(end)+1;
- bfill(end, SCRAMBLE_LENGTH, 'x');
- end+=SCRAMBLE_LENGTH;
- *end=0;
+ *end++= SCRAMBLE_LENGTH;
+ scramble(end, mysql->scramble, passwd);
+ end+= SCRAMBLE_LENGTH;
}
- else /* For empty password*/
+ else
{
- end=strend(end)+1;
- *end=0; /* Store zero length scramble */
+ scramble_323(end, mysql->scramble, passwd);
+ end+= SCRAMBLE_LENGTH_323 + 1;
}
}
else
- {
- /*
- Real scramble is only sent to old servers. This can be blocked
- by calling mysql_options(MYSQL *, MYSQL_SECURE_CONNECT, (char*) &1);
- */
- end=scramble(strend(end)+1, mysql->scramble_buff, passwd,
- (my_bool) (mysql->protocol_version == 9));
- }
+ *end++= '\0'; /* empty password */
+
/* Add database if needed */
if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
{
- end=strmake(end+1,db,NAME_LEN);
- mysql->db=my_strdup(db,MYF(MY_WME));
- db=0;
+ end= strmake(end, db, NAME_LEN) + 1;
+ mysql->db= my_strdup(db,MYF(MY_WME));
+ db= 0;
}
/* Write authentication package */
if (my_net_write(net,buff,(ulong) (end-buff)) || net_flush(net))
@@ -2002,10 +1942,36 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
strmov(net->last_error,ER(net->last_errno));
goto error;
}
+
+ /*
+ Part 3: Authorization data's been sent. Now server can reply with
+ OK-packet, or re-request scrambled password.
+ */
- if (mysql_autenticate(mysql, passwd))
+ if ((pkt_length=net_safe_read(mysql)) == packet_error)
goto error;
+ if (pkt_length == 1 && net->read_pos[0] == 254 &&
+ mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
+ {
+ /*
+ By sending this very specific reply server asks us to send scrambled
+ password in old format.
+ */
+ scramble_323(buff, mysql->scramble, passwd);
+ if (my_net_write(net, buff, SCRAMBLE_LENGTH_323 + 1) || net_flush(net))
+ {
+ net->last_errno= CR_SERVER_LOST;
+ strmov(net->sqlstate, unknown_sqlstate);
+ strmov(net->last_error,ER(net->last_errno));
+ goto error;
+ }
+ /* Read what server thinks about out new auth message report */
+ if (net_safe_read(mysql) == packet_error)
+ goto error;
+ }
+
+
if (client_flag & CLIENT_COMPRESS) /* We will use compression */
net->compress=1;
diff --git a/sql/field.h b/sql/field.h
index 794b4a89542..10d3e671867 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -305,6 +305,11 @@ public:
unireg_check_arg, field_name_arg, table_arg,
dec_arg, zero_arg,unsigned_arg)
{}
+ Field_decimal(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
+ struct st_table *table_arg,bool unsigned_arg)
+ :Field_num((char*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0,
+ NONE, field_name_arg, table_arg,0,0,unsigned_arg)
+ {}
enum_field_types type() const { return FIELD_TYPE_DECIMAL;}
enum ha_base_keytype key_type() const
{ return zerofill ? HA_KEYTYPE_BINARY : HA_KEYTYPE_NUM; }
@@ -334,6 +339,11 @@ public:
unireg_check_arg, field_name_arg, table_arg,
0, zero_arg,unsigned_arg)
{}
+ Field_tiny(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
+ struct st_table *table_arg,bool unsigned_arg)
+ :Field_num((char*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0,
+ NONE, field_name_arg, table_arg,0,0,unsigned_arg)
+ {}
enum Item_result result_type () const { return INT_RESULT; }
enum_field_types type() const { return FIELD_TYPE_TINY;}
enum ha_base_keytype key_type() const
@@ -364,6 +374,11 @@ public:
unireg_check_arg, field_name_arg, table_arg,
0, zero_arg,unsigned_arg)
{}
+ Field_short(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
+ struct st_table *table_arg,bool unsigned_arg)
+ :Field_num((char*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0,
+ NONE, field_name_arg, table_arg,0,0,unsigned_arg)
+ {}
enum Item_result result_type () const { return INT_RESULT; }
enum_field_types type() const { return FIELD_TYPE_SHORT;}
enum ha_base_keytype key_type() const
@@ -497,6 +512,11 @@ public:
unireg_check_arg, field_name_arg, table_arg,
dec_arg, zero_arg,unsigned_arg)
{}
+ Field_float(uint32 len_arg, bool maybe_null_arg, const char *field_name_arg,
+ struct st_table *table_arg, uint8 dec_arg)
+ :Field_num((char*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, (uint) 0,
+ NONE, field_name_arg, table_arg,dec_arg,0,0)
+ {}
enum_field_types type() const { return FIELD_TYPE_FLOAT;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_FLOAT; }
int store(const char *to,uint length,CHARSET_INFO *charset);
@@ -558,6 +578,11 @@ public:
:Field_str(ptr_arg, len_arg, null, 1,
unireg_check_arg, field_name_arg, table_arg, cs)
{}
+ Field_null(uint32 len_arg, const char *field_name_arg,
+ struct st_table *table_arg, CHARSET_INFO *cs)
+ :Field_str((char*) 0, len_arg, null, 1,
+ NONE, field_name_arg, table_arg, cs)
+ {}
enum_field_types type() const { return FIELD_TYPE_NULL;}
int store(const char *to, uint length, CHARSET_INFO *cs) { null[0]=1; return 0; }
int store(double nr) { null[0]=1; return 0; }
@@ -627,6 +652,10 @@ public:
:Field_tiny(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, table_arg, 1, 1)
{}
+ Field_year(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
+ struct st_table *table_arg)
+ :Field_tiny(len_arg,maybe_null_arg,field_name_arg,table_arg,1)
+ {}
enum_field_types type() const { return FIELD_TYPE_YEAR;}
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index e8e4798c2b2..a87bed94484 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -236,6 +236,8 @@ int ha_myisam::open(const char *name, int mode, uint test_if_locked)
VOID(mi_extra(file, HA_EXTRA_WAIT_LOCK, 0));
if (!table->db_record_offset)
int_table_flags|=HA_REC_NOT_IN_SEQ;
+ if (file->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
+ int_table_flags|=HA_HAS_CHECKSUM;
return (0);
}
@@ -1414,3 +1416,9 @@ int ha_myisam::ft_read(byte * buf)
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
}
+
+uint ha_myisam::checksum() const
+{
+ return (uint)file->s->state.checksum;
+}
+
diff --git a/sql/ha_myisam.h b/sql/ha_myisam.h
index 8486e25556b..e4e3192af10 100644
--- a/sql/ha_myisam.h
+++ b/sql/ha_myisam.h
@@ -64,6 +64,7 @@ class ha_myisam: public handler
uint max_keys() const { return MI_MAX_KEY; }
uint max_key_parts() const { return MAX_REF_PARTS; }
uint max_key_length() const { return MI_MAX_KEY_LENGTH; }
+ uint checksum() const;
int open(const char *name, int mode, uint test_if_locked);
int close(void);
diff --git a/sql/handler.cc b/sql/handler.cc
index b4d370491bb..851e73f15d2 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -359,7 +359,10 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
if (trans == &thd->transaction.all && mysql_bin_log.is_open() &&
my_b_tell(&thd->transaction.trans_log))
{
+ if (wait_if_global_read_lock(thd, 0))
+ DBUG_RETURN(1);
mysql_bin_log.write(thd, &thd->transaction.trans_log);
+ start_waiting_global_read_lock(thd);
reinit_io_cache(&thd->transaction.trans_log,
WRITE_CACHE, (my_off_t) 0, 0, 1);
thd->transaction.trans_log.end_of_file= max_binlog_cache_size;
diff --git a/sql/handler.h b/sql/handler.h
index b1b5cfb02b0..b74e06c6edf 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -42,38 +42,39 @@
#define HA_ADMIN_INVALID -5
/* Bits in table_flags() to show what database can do */
-#define HA_READ_RND_SAME 1 /* Read RND-record to KEY-record
- (To update with RND-read) */
-#define HA_KEYPOS_TO_RNDPOS 2 /* ha_info gives pos to record */
-#define HA_TABLE_SCAN_ON_INDEX 4 /* No separate data/index file */
-#define HA_REC_NOT_IN_SEQ 8 /* ha_info don't return recnumber;
- It returns a position to ha_r_rnd */
-#define HA_HAS_GEOMETRY 16
-#define HA_NO_INDEX 32 /* No index needed for next/prev */
-#define HA_KEY_READ_WRONG_STR 64 /* keyread returns converted strings */
-#define HA_NULL_KEY 128 /* One can have keys with NULL */
-#define HA_DUPP_POS 256 /* ha_position() gives dupp row */
-#define HA_NO_BLOBS 512 /* Doesn't support blobs */
-#define HA_BLOB_KEY (HA_NO_BLOBS*2) /* key on blob */
-#define HA_AUTO_PART_KEY (HA_BLOB_KEY*2)
-#define HA_REQUIRE_PRIMARY_KEY (HA_AUTO_PART_KEY*2)
-#define HA_NOT_EXACT_COUNT (HA_REQUIRE_PRIMARY_KEY*2)
-#define HA_NO_WRITE_DELAYED (HA_NOT_EXACT_COUNT*2)
-#define HA_PRIMARY_KEY_IN_READ_INDEX (HA_NO_WRITE_DELAYED*2)
-#define HA_DROP_BEFORE_CREATE (HA_PRIMARY_KEY_IN_READ_INDEX*2)
-#define HA_NOT_READ_AFTER_KEY (HA_DROP_BEFORE_CREATE*2)
-#define HA_NOT_DELETE_WITH_CACHE (HA_NOT_READ_AFTER_KEY*2)
-#define HA_NO_TEMP_TABLES (HA_NOT_DELETE_WITH_CACHE*2)
-#define HA_NO_PREFIX_CHAR_KEYS (HA_NO_TEMP_TABLES*2)
-#define HA_CAN_FULLTEXT (HA_NO_PREFIX_CHAR_KEYS*2)
-#define HA_CAN_SQL_HANDLER (HA_CAN_FULLTEXT*2)
-#define HA_NO_AUTO_INCREMENT (HA_CAN_SQL_HANDLER*2)
+#define HA_READ_RND_SAME 1 /* Read RND-record to KEY-record
+ (To update with RND-read) */
+#define HA_KEYPOS_TO_RNDPOS 2 /* ha_info gives pos to record */
+#define HA_TABLE_SCAN_ON_INDEX 4 /* No separate data/index file */
+#define HA_REC_NOT_IN_SEQ 8 /* ha_info don't return recnumber;
+ It returns a position to ha_r_rnd */
+#define HA_HAS_GEOMETRY (1 << 4)
+#define HA_NO_INDEX (1 << 5) /* No index needed for next/prev */
+#define HA_KEY_READ_WRONG_STR (1 << 6) /* keyread returns converted strings */
+#define HA_NULL_KEY (1 << 7) /* One can have keys with NULL */
+#define HA_DUPP_POS (1 << 8) /* ha_position() gives dupp row */
+#define HA_NO_BLOBS (1 << 9) /* Doesn't support blobs */
+#define HA_BLOB_KEY (1 << 10) /* key on blob */
+#define HA_AUTO_PART_KEY (1 << 11)
+#define HA_REQUIRE_PRIMARY_KEY (1 << 12)
+#define HA_NOT_EXACT_COUNT (1 << 13)
+#define HA_NO_WRITE_DELAYED (1 << 14)
+#define HA_PRIMARY_KEY_IN_READ_INDEX (1 << 15)
+#define HA_DROP_BEFORE_CREATE (1 << 16)
+#define HA_NOT_READ_AFTER_KEY (1 << 17)
+#define HA_NOT_DELETE_WITH_CACHE (1 << 18)
+#define HA_NO_TEMP_TABLES (1 << 19)
+#define HA_NO_PREFIX_CHAR_KEYS (1 << 20)
+#define HA_CAN_FULLTEXT (1 << 21)
+#define HA_CAN_SQL_HANDLER (1 << 22)
+#define HA_NO_AUTO_INCREMENT (1 << 23)
+#define HA_HAS_CHECKSUM (1 << 24)
/*
Next record gives next record according last record read (even
if database is updated after read). Not used at this point.
*/
-#define HA_LASTKEY_ORDER (HA_NO_AUTO_INCREMENT*2)
+#define HA_LASTKEY_ORDER (1 << 25)
/* bits in index_flags(index_number) for what you can do with index */
@@ -306,8 +307,8 @@ public:
virtual bool check_and_repair(THD *thd) {return 1;}
virtual int optimize(THD* thd,HA_CHECK_OPT* check_opt);
virtual int analyze(THD* thd, HA_CHECK_OPT* check_opt);
- virtual int backup(THD* thd, HA_CHECK_OPT* check_opt);
virtual int preload_keys(THD* thd, HA_CHECK_OPT* check_opt);
+ virtual int backup(THD* thd, HA_CHECK_OPT* check_opt);
/*
restore assumes .frm file must exist, and that generate_table() has been
called; It will just copy the data file and run repair.
@@ -325,8 +326,8 @@ public:
virtual char* get_foreign_key_create_info()
{ return(NULL);} /* gets foreign key create string from InnoDB */
virtual void init_table_handle_for_HANDLER()
- { return; } /* prepare InnoDB for HANDLER */
- virtual void free_foreign_key_create_info(char* str) {}
+ { return; } /* prepare InnoDB for HANDLER */
+ virtual void free_foreign_key_create_info(char* str) {}
/* The following can be called without an open handler */
virtual const char *table_type() const =0;
virtual const char **bas_ext() const =0;
@@ -342,6 +343,7 @@ public:
virtual uint max_key_part_length() { return 255; }
virtual uint min_record_length(uint options) const { return 1; }
virtual bool low_byte_first() const { return 1; }
+ virtual uint checksum() const { return 0; }
virtual bool is_crashed() const { return 0; }
virtual bool auto_repair() const { return 0; }
@@ -355,13 +357,12 @@ public:
/* Type of table for caching query */
virtual uint8 table_cache_type() { return HA_CACHE_TBL_NONTRANSACT; }
- /*
- Is query with this cable cachable (have sense only for ASKTRANSACT
+ /*
+ Is query with this table cachable (have sense only for ASKTRANSACT
tables)
*/
- static bool caching_allowed(THD* thd, char* table_key,
+ static bool caching_allowed(THD* thd, char* table_key,
uint key_length, uint8 cahe_type);
-
};
/* Some extern variables used with handlers */
@@ -390,7 +391,7 @@ int ha_delete_table(enum db_type db_type, const char *path);
void ha_drop_database(char* path);
void ha_key_cache(void);
void ha_resize_key_cache(void);
-int ha_start_stmt(THD *thd);
+int ha_start_stmt(THD *thd);
int ha_report_binlog_offset_and_commit(THD *thd, char *log_file_name,
my_off_t end_offset);
int ha_commit_complete(THD *thd);
diff --git a/sql/item.cc b/sql/item.cc
index 17b9e1b508f..0f799184559 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -490,27 +490,38 @@ String *Item_null::val_str(String *str)
/* Item_param related */
void Item_param::set_null()
-{
- maybe_null=null_value=1;
+{
+ DBUG_ENTER("Item_param::set_null");
+ maybe_null= null_value= 1;
+ DBUG_VOID_RETURN;
}
void Item_param::set_int(longlong i)
-{
- int_value=(longlong)i;
- item_type = INT_ITEM;
+{
+ DBUG_ENTER("Item_param::set_int");
+ int_value= (longlong)i;
+ item_type= INT_ITEM;
+ DBUG_PRINT("info", ("integer: %lld", int_value));
+ DBUG_VOID_RETURN;
}
void Item_param::set_double(double value)
-{
+{
+ DBUG_ENTER("Item_param::set_double");
real_value=value;
- item_type = REAL_ITEM;
+ item_type= REAL_ITEM;
+ DBUG_PRINT("info", ("double: %lg", real_value));
+ DBUG_VOID_RETURN;
}
void Item_param::set_value(const char *str, uint length)
-{
- str_value.set(str,length,default_charset());
- item_type = STRING_ITEM;
+{
+ DBUG_ENTER("Item_param::set_value");
+ str_value.copy(str,length,default_charset());
+ item_type= STRING_ITEM;
+ DBUG_PRINT("info", ("string: %s", str_value.ptr()));
+ DBUG_VOID_RETURN;
}
@@ -923,6 +934,73 @@ enum_field_types Item::field_type() const
FIELD_TYPE_DOUBLE);
}
+Field *Item::tmp_table_field_from_field_type(TABLE *table)
+{
+ switch (field_type())
+ {
+ case MYSQL_TYPE_DECIMAL:
+ return new Field_decimal(max_length, maybe_null, name, table,
+ unsigned_flag);
+ case MYSQL_TYPE_TINY:
+ return new Field_tiny(max_length, maybe_null, name, table,
+ unsigned_flag);
+ case MYSQL_TYPE_SHORT:
+ return new Field_short(max_length, maybe_null, name, table,
+ unsigned_flag);
+ case MYSQL_TYPE_LONG:
+ return new Field_long(max_length, maybe_null, name, table,
+ unsigned_flag);
+ case MYSQL_TYPE_FLOAT:
+ return new Field_float(max_length, maybe_null, name, table, decimals);
+ case MYSQL_TYPE_DOUBLE:
+ return new Field_double(max_length, maybe_null, name, table, decimals);
+ case MYSQL_TYPE_NULL:
+ return new Field_null(max_length, name, table, &my_charset_bin);
+#ifdef HAVE_LONG_LONG
+ case MYSQL_TYPE_LONGLONG:
+ return new Field_longlong(max_length, maybe_null, name, table,
+ unsigned_flag);
+#endif
+ case MYSQL_TYPE_NEWDATE:
+ case MYSQL_TYPE_INT24:
+ return new Field_long(max_length, maybe_null, name, table,
+ unsigned_flag);
+ case MYSQL_TYPE_DATE:
+ return new Field_date(maybe_null, name, table, &my_charset_bin);
+ case MYSQL_TYPE_TIME:
+ return new Field_time(maybe_null, name, table, &my_charset_bin);
+ case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_DATETIME:
+ return new Field_datetime(maybe_null, name, table, &my_charset_bin);
+ case MYSQL_TYPE_YEAR:
+ return new Field_year(max_length, maybe_null, name, table);
+ case MYSQL_TYPE_ENUM:
+ case MYSQL_TYPE_SET:
+ return new Field_long(max_length, maybe_null, name, table,
+ unsigned_flag);
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_GEOMETRY:
+ return new Field_blob(max_length, maybe_null, name, table, collation.collation);
+ case MYSQL_TYPE_VAR_STRING:
+ if (max_length > 255)
+ return new Field_blob(max_length, maybe_null, name, table, collation.collation);
+ else
+ return new Field_varstring(max_length, maybe_null, name, table, collation.collation);
+ case MYSQL_TYPE_STRING:
+ if (max_length > 255)
+ return new Field_blob(max_length, maybe_null, name, table, collation.collation);
+ else
+ return new Field_string(max_length, maybe_null, name, table, collation.collation);
+ default:
+ // This case should never be choosen
+ DBUG_ASSERT(0);
+ return 0;
+ }
+}
+
/* ARGSUSED */
void Item_field::make_field(Send_field *tmp_field)
{
diff --git a/sql/item.h b/sql/item.h
index 296ad18b1f1..147c350878e 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -120,6 +120,9 @@ public:
Constructor used by Item_field, Item_ref & agregate (sum) functions.
Used for duplicating lists in processing queries with temporary
tables
+ Also it used for Item_cond_and/Item_cond_or for creating
+ top AND/OR ctructure of WHERE clause to protect it of
+ optimisation changes in prepared statements
*/
Item(THD *thd, Item &item);
virtual ~Item() { name=0; } /*lint -e1509 */
@@ -140,7 +143,7 @@ public:
virtual double val()=0;
virtual longlong val_int()=0;
virtual String *val_str(String*)=0;
- virtual Field *tmp_table_field() { return 0; }
+ virtual Field *get_tmp_table_field() { return 0; }
virtual Field *tmp_table_field(TABLE *t_arg) { return 0; }
virtual const char *full_name() const { return name ? name : "???"; }
virtual double val_result() { return val(); }
@@ -184,6 +187,7 @@ public:
virtual void save_in_result_field(bool no_conversions) {}
virtual void no_rows_in_result() {}
virtual Item *copy_or_same(THD *thd) { return this; }
+ virtual Item *copy_andor_structure(THD *thd) { return this; }
virtual Item *real_item() { return this; }
virtual Item *get_tmp_table_item(THD *thd) { return copy_or_same(thd); }
@@ -205,6 +209,8 @@ public:
virtual bool null_inside() { return 0; }
// used in row subselects to get value of elements
virtual void bring_value() {}
+
+ Field *tmp_table_field_from_field_type(TABLE *table);
};
@@ -265,7 +271,7 @@ public:
{
return field->type();
}
- Field *tmp_table_field() { return result_field; }
+ Field *get_tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg) { return result_field; }
bool get_date(TIME *ltime,bool fuzzydate);
bool get_date_result(TIME *ltime,bool fuzzydate);
@@ -539,12 +545,12 @@ class Item_result_field :public Item /* Item with result field */
public:
Field *result_field; /* Save result here */
Item_result_field() :result_field(0) {}
- // Constructor used for Item_sum (see Item comment)
+ // Constructor used for Item_sum/Item_cond_and/or (see Item comment)
Item_result_field(THD *thd, Item_result_field &item):
Item(thd, item), result_field(item.result_field)
{}
~Item_result_field() {} /* Required with gcc 2.95 */
- Field *tmp_table_field() { return result_field; }
+ Field *get_tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg) { return result_field; }
table_map used_tables() const { return 1; }
virtual void fix_length_and_dec()=0;
@@ -862,6 +868,7 @@ public:
{
value= item->val_int_result();
null_value= item->null_value;
+ collation.set(item->collation);
}
double val() { return (double) value; }
longlong val_int() { return value; }
@@ -879,6 +886,7 @@ public:
{
value= item->val_result();
null_value= item->null_value;
+ collation.set(item->collation);
}
double val() { return value; }
longlong val_int() { return (longlong) (value+(value > 0 ? 0.5 : -0.5)); }
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 053eb9e6fef..7460c103550 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -698,8 +698,21 @@ Item_func_ifnull::fix_length_and_dec()
agg_arg_collations(collation, args, arg_count);
else if (cached_result_type != REAL_RESULT)
decimals= 0;
+
+ cached_field_type= args[0]->field_type();
+ if (cached_field_type != args[1]->field_type())
+ cached_field_type= Item_func::field_type();
+}
+
+enum_field_types Item_func_ifnull::field_type() const
+{
+ return cached_field_type;
}
+Field *Item_func_ifnull::tmp_table_field(TABLE *table)
+{
+ return tmp_table_field_from_field_type(table);
+}
double
Item_func_ifnull::val()
@@ -1536,6 +1549,31 @@ longlong Item_func_bit_and::val_int()
return (longlong) (arg1 & arg2);
}
+Item_cond::Item_cond(THD *thd, Item_cond &item)
+ :Item_bool_func(thd, item),
+ abort_on_null(item.abort_on_null),
+ and_tables_cache(item.and_tables_cache)
+{
+ /*
+ here should be following text:
+
+ List_iterator_fast<Item*> li(item.list);
+ while(Item *it= li++)
+ list.push_back(it);
+
+ but it do not need,
+ because this constructor used only for AND/OR and
+ argument list will be copied by copy_andor_arguments call
+ */
+
+}
+
+void Item_cond::copy_andor_arguments(THD *thd, Item_cond *item)
+{
+ List_iterator_fast<Item> li(item->list);
+ while(Item *it= li++)
+ list.push_back(it->copy_andor_structure(thd));
+}
bool
Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 5c06f4fa1df..f8104491978 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -82,6 +82,7 @@ public:
Item_bool_func() :Item_int_func() {}
Item_bool_func(Item *a) :Item_int_func(a) {}
Item_bool_func(Item *a,Item *b) :Item_int_func(a,b) {}
+ Item_bool_func(THD *thd, Item_bool_func &item) :Item_int_func(thd, item) {}
void fix_length_and_dec() { decimals=0; max_length=1; }
};
@@ -115,8 +116,8 @@ protected:
String tmp_value1,tmp_value2;
public:
- Item_bool_func2(Item *a,Item *b):
- Item_int_func(a,b), cmp(tmp_arg, tmp_arg+1) {}
+ Item_bool_func2(Item *a,Item *b)
+ :Item_int_func(a,b), cmp(tmp_arg, tmp_arg+1) {}
void fix_length_and_dec();
void set_cmp_func()
{
@@ -158,7 +159,7 @@ public:
class Item_func_eq :public Item_bool_rowready_func2
{
public:
- Item_func_eq(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
+ Item_func_eq(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}
longlong val_int();
enum Functype functype() const { return EQ_FUNC; }
enum Functype rev_functype() const { return EQ_FUNC; }
@@ -280,6 +281,8 @@ public:
class Item_func_ifnull :public Item_func
{
enum Item_result cached_result_type;
+ enum_field_types cached_field_type;
+ bool field_type_defined;
public:
Item_func_ifnull(Item *a,Item *b)
:Item_func(a,b), cached_result_type(INT_RESULT)
@@ -288,8 +291,10 @@ public:
longlong val_int();
String *val_str(String *str);
enum Item_result result_type () const { return cached_result_type; }
+ enum_field_types field_type() const;
void fix_length_and_dec();
const char *func_name() const { return "ifnull"; }
+ Field *tmp_table_field(TABLE *table);
table_map not_null_tables() const { return 0; }
};
@@ -787,8 +792,13 @@ protected:
public:
/* Item_cond() is only used to create top level items */
Item_cond() : Item_bool_func(), abort_on_null(1) { const_item_cache=0; }
- Item_cond(Item *i1,Item *i2) :Item_bool_func(), abort_on_null(0)
- { list.push_back(i1); list.push_back(i2); }
+ Item_cond(Item *i1,Item *i2)
+ :Item_bool_func(), abort_on_null(0)
+ {
+ list.push_back(i1);
+ list.push_back(i2);
+ }
+ Item_cond(THD *thd, Item_cond &item);
~Item_cond() { list.delete_elements(); }
bool add(Item *item) { return list.push_back(item); }
bool fix_fields(THD *, struct st_table_list *, Item **ref);
@@ -801,6 +811,7 @@ public:
void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
friend int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
void top_level_item() { abort_on_null=1; }
+ void copy_andor_arguments(THD *thd, Item_cond *item);
bool walk(Item_processor processor, byte *arg);
};
@@ -811,9 +822,17 @@ class Item_cond_and :public Item_cond
public:
Item_cond_and() :Item_cond() {}
Item_cond_and(Item *i1,Item *i2) :Item_cond(i1,i2) {}
+ Item_cond_and(THD *thd, Item_cond_and &item) :Item_cond(thd, item) {}
enum Functype functype() const { return COND_AND_FUNC; }
longlong val_int();
const char *func_name() const { return "and"; }
+ Item* copy_andor_structure(THD *thd)
+ {
+ Item_cond_and *item;
+ if((item= new Item_cond_and(thd, *this)))
+ item->copy_andor_arguments(thd, this);
+ return item;
+ }
};
class Item_cond_or :public Item_cond
@@ -821,10 +840,18 @@ class Item_cond_or :public Item_cond
public:
Item_cond_or() :Item_cond() {}
Item_cond_or(Item *i1,Item *i2) :Item_cond(i1,i2) {}
+ Item_cond_or(THD *thd, Item_cond_or &item) :Item_cond(thd, item) {}
enum Functype functype() const { return COND_OR_FUNC; }
longlong val_int();
const char *func_name() const { return "or"; }
table_map not_null_tables() const { return and_tables_cache; }
+ Item* copy_andor_structure(THD *thd)
+ {
+ Item_cond_or *item;
+ if((item= new Item_cond_or(thd, *this)))
+ item->copy_andor_arguments(thd, this);
+ return item;
+ }
};
diff --git a/sql/item_create.cc b/sql/item_create.cc
index e3e3c021a1e..b1173b9c7b8 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -52,13 +52,6 @@ Item *create_func_ord(Item* a)
return new Item_func_ord(a);
}
-Item *create_func_old_password(Item* a)
-{
- return new Item_func_old_password(a);
-}
-
-
-
Item *create_func_asin(Item* a)
{
return new Item_func_asin(a);
@@ -107,14 +100,6 @@ Item *create_func_cot(Item* a)
new Item_func_tan(a));
}
-
-#ifdef HAVE_COMPRESS
-Item *create_func_crc32(Item* a)
-{
- return new Item_func_crc32(a);
-}
-#endif
-
Item *create_func_date_format(Item* a,Item *b)
{
return new Item_func_date_format(a,b,0);
@@ -332,11 +317,6 @@ Item *create_func_quarter(Item* a)
return new Item_func_quarter(a);
}
-Item *create_func_password(Item* a)
-{
- return new Item_func_password(a);
-}
-
Item *create_func_radians(Item *a)
{
return new Item_func_units((char*) "radians",a,M_PI/180,0.0);
@@ -666,13 +646,10 @@ Item *create_func_point(Item *a, Item *b)
return new Item_func_point(a, b);
}
-#if !defined(HAVE_COMPRESS)
-
-Item *create_func_compress (Item*a __attribute__((unused))){return 0;}
-Item *create_func_uncompress (Item*a __attribute__((unused))){return 0;}
-Item *create_func_uncompressed_length(Item*a __attribute__((unused))){return 0;}
-
-#else
+Item *create_func_crc32(Item* a)
+{
+ return new Item_func_crc32(a);
+}
Item *create_func_compress(Item* a)
{
@@ -689,8 +666,6 @@ Item *create_func_uncompressed_length(Item* a)
return new Item_func_uncompressed_length(a);
}
-#endif
-
Item *create_func_datediff(Item *a, Item *b)
{
return new Item_func_minus(new Item_func_to_days(a),
diff --git a/sql/item_create.h b/sql/item_create.h
index 16c4fccf709..c75f4404bad 100644
--- a/sql/item_create.h
+++ b/sql/item_create.h
@@ -33,9 +33,7 @@ Item *create_func_connection_id(void);
Item *create_func_conv(Item* a, Item *b, Item *c);
Item *create_func_cos(Item* a);
Item *create_func_cot(Item* a);
-#ifdef HAVE_COMPRESS
Item *create_func_crc32(Item* a);
-#endif
Item *create_func_date_format(Item* a,Item *b);
Item *create_func_dayname(Item* a);
Item *create_func_dayofmonth(Item* a);
@@ -69,14 +67,12 @@ Item *create_func_monthname(Item* a);
Item *create_func_nullif(Item* a, Item *b);
Item *create_func_oct(Item *);
Item *create_func_ord(Item* a);
-Item *create_func_old_password(Item* a);
Item *create_func_period_add(Item* a, Item *b);
Item *create_func_period_diff(Item* a, Item *b);
Item *create_func_pi(void);
Item *create_func_pow(Item* a, Item *b);
Item *create_func_current_user(void);
Item *create_func_quarter(Item* a);
-Item *create_func_password(Item* a);
Item *create_func_radians(Item *a);
Item *create_func_release_lock(Item* a);
Item *create_func_repeat(Item* a, Item *b);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 4bda8ae78cd..5ebc4e82f13 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -27,22 +27,18 @@
#include <hash.h>
#include <time.h>
#include <ft_global.h>
-#ifdef HAVE_COMPRESS
-#include <zlib.h>
-#endif
static void my_coll_agg_error(DTCollation &c1, DTCollation &c2,
const char *fname)
{
my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0),
- c1.collation->name,c1.derivation_name(),
+ c1.collation->name,c1.derivation_name(),
c2.collation->name,c2.derivation_name(),
fname);
}
-
-static void my_coll_agg_error(DTCollation &c1,
+static void my_coll_agg_error(DTCollation &c1,
DTCollation &c2,
DTCollation &c3,
const char *fname)
@@ -134,6 +130,27 @@ Item_func::Item_func(List<Item> &list)
set_arguments(list);
}
+Item_func::Item_func(THD *thd, Item_func &item)
+ :Item_result_field(thd, item),
+ allowed_arg_cols(item.allowed_arg_cols),
+ arg_count(item.arg_count),
+ used_tables_cache(item.used_tables_cache),
+ not_null_tables_cache(item.not_null_tables_cache),
+ const_item_cache(item.const_item_cache)
+{
+ if (arg_count)
+ {
+ if (arg_count <=2)
+ args= tmp_arg;
+ else
+ {
+ if (!(args=(Item**) thd->alloc(sizeof(Item*)*arg_count)))
+ return;
+ }
+ memcpy((char*) args, (char*) item.args, sizeof(Item*)*arg_count);
+ }
+}
+
/*
Resolve references to table column for a function and it's argument
@@ -1085,36 +1102,6 @@ longlong Item_func_min_max::val_int()
return value;
}
-
-#ifdef HAVE_COMPRESS
-longlong Item_func_crc32::val_int()
-{
- String *res=args[0]->val_str(&value);
- if (!res)
- {
- null_value=1;
- return 0; /* purecov: inspected */
- }
- null_value=0;
- return (longlong) crc32(0L, (Bytef*)res->ptr(), res->length());
-}
-
-
-longlong Item_func_uncompressed_length::val_int()
-{
- String *res= args[0]->val_str(&value);
- if (!res)
- {
- null_value=1;
- return 0; /* purecov: inspected */
- }
- null_value=0;
- if (res->is_empty()) return 0;
- return uint4korr(res->c_ptr()) & 0x3FFFFFFF;
-}
-#endif /* HAVE_COMPRESS */
-
-
longlong Item_func_length::val_int()
{
String *res=args[0]->val_str(&value);
diff --git a/sql/item_func.h b/sql/item_func.h
index 7fedbcf48ee..cf554f613d4 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -104,6 +104,8 @@ public:
}
}
Item_func(List<Item> &list);
+ // Constructor used for Item_cond_and/or (see Item comment)
+ Item_func(THD *thd, Item_func &item);
~Item_func() {} /* Nothing to do; Items are freed automaticly */
bool fix_fields(THD *,struct st_table_list *, Item **ref);
table_map used_tables() const;
@@ -196,6 +198,7 @@ public:
Item_int_func(Item *a,Item *b) :Item_func(a,b) { max_length=21; }
Item_int_func(Item *a,Item *b,Item *c) :Item_func(a,b,c) { max_length=21; }
Item_int_func(List<Item> &list) :Item_func(list) { max_length=21; }
+ Item_int_func(THD *thd, Item_int_func &item) :Item_func(thd, item) {}
double val() { return (double) val_int(); }
String *val_str(String*str);
enum Item_result result_type () const { return INT_RESULT; }
@@ -555,27 +558,6 @@ public:
};
-#ifdef HAVE_COMPRESS
-class Item_func_crc32 :public Item_int_func
-{
- String value;
-public:
- Item_func_crc32(Item *a) :Item_int_func(a) {}
- longlong val_int();
- const char *func_name() const { return "crc32"; }
- void fix_length_and_dec() { max_length=10; }
-};
-class Item_func_uncompressed_length : public Item_int_func
-{
- String value;
-public:
- Item_func_uncompressed_length(Item *a):Item_int_func(a){}
- longlong val_int();
- const char *func_name() const{return "uncompressed_length";}
- void fix_length_and_dec() { max_length=10; }
-};
-#endif
-
class Item_func_length :public Item_int_func
{
String value;
diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h
index d86914eb6c5..79e45cca26f 100644
--- a/sql/item_geofunc.h
+++ b/sql/item_geofunc.h
@@ -167,30 +167,6 @@ public:
const char *func_name() const { return "multipoint"; }
};
-#ifdef HAVE_COMPRESS
-
-class Item_func_compress: public Item_str_func
-{
- String buffer;
-public:
- Item_func_compress(Item *a):Item_str_func(a){}
- String *val_str(String *);
- void fix_length_and_dec(){max_length= (args[0]->max_length*120)/100+12;}
- const char *func_name() const{return "compress";}
-};
-
-class Item_func_uncompress: public Item_str_func
-{
- String buffer;
-public:
- Item_func_uncompress(Item *a): Item_str_func(a){}
- String *val_str(String *);
- void fix_length_and_dec(){max_length= MAX_BLOB_WIDTH;}
- const char *func_name() const{return "uncompress";}
-};
-
-#endif
-
/*
Spatial relations
*/
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index b0b9cc01bf1..f8cc602129f 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1327,95 +1327,49 @@ void Item_func_trim::fix_length_and_dec()
}
-
-
-void Item_func_password::fix_length_and_dec()
-{
- /*
- If PASSWORD() was called with only one argument, it depends on a random
- number so we need to save this random number into the binary log.
- If called with two arguments, it is repeatable.
- */
- if (arg_count == 1)
- {
- THD *thd= current_thd;
- thd->rand_used= 1;
- thd->rand_saved_seed1= thd->rand.seed1;
- thd->rand_saved_seed2= thd->rand.seed2;
- }
- max_length= get_password_length(use_old_passwords);
-}
-
-/*
- Password() function has 2 arguments. Second argument can be used
- to make results repeatable
-*/
+/* Item_func_password */
String *Item_func_password::val_str(String *str)
{
- struct rand_struct rand_st; // local structure for 2 param version
- ulong seed=0; // seed to initialise random generator to
-
- String *res =args[0]->val_str(str);
+ String *res= args[0]->val_str(str);
if ((null_value=args[0]->null_value))
return 0;
-
- if (arg_count == 1)
- {
- if (res->length() == 0)
- return &empty_string;
- make_scrambled_password(tmp_value,res->c_ptr(),use_old_passwords,
- &current_thd->rand);
- str->set(tmp_value,get_password_length(use_old_passwords),res->charset());
- return str;
- }
- else
- {
- /* We'll need the buffer to get second parameter */
- char key_buff[80];
- String tmp_key_value(key_buff, sizeof(key_buff), system_charset_info);
- String *key =args[1]->val_str(&tmp_key_value);
-
- /* Check second argument for NULL value. First one is already checked */
- if ((null_value=args[1]->null_value))
- return 0;
-
- /* This shall be done after checking for null for proper results */
- if (res->length() == 0)
- return &empty_string;
-
- /* Generate the seed first this allows to avoid double allocation */
- char* seed_ptr=key->c_ptr();
- while (*seed_ptr)
- {
- seed=(seed*211+*seed_ptr) & 0xffffffffL; /* Use simple hashing */
- seed_ptr++;
- }
-
- /* Use constants which allow nice random values even with small seed */
- randominit(&rand_st,
- (ulong) ((ulonglong) seed*111111+33333333L) & (ulong) 0xffffffff,
- (ulong) ((ulonglong) seed*1111+55555555L) & (ulong) 0xffffffff);
-
- make_scrambled_password(tmp_value,res->c_ptr(),use_old_passwords,
- &rand_st);
- str->set(tmp_value,get_password_length(use_old_passwords),res->charset());
- return str;
- }
+ if (res->length() == 0)
+ return &empty_string;
+ make_scrambled_password(tmp_value, res->c_ptr());
+ str->set(tmp_value, SCRAMBLED_PASSWORD_CHAR_LENGTH, res->charset());
+ return str;
+}
+
+char *Item_func_password::alloc(THD *thd, const char *password)
+{
+ char *buff= (char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1);
+ if (buff)
+ make_scrambled_password(buff, password);
+ return buff;
}
+/* Item_func_old_password */
+
String *Item_func_old_password::val_str(String *str)
{
- String *res =args[0]->val_str(str);
+ String *res= args[0]->val_str(str);
if ((null_value=args[0]->null_value))
return 0;
if (res->length() == 0)
return &empty_string;
- make_scrambled_password(tmp_value,res->c_ptr(),1,&current_thd->rand);
- str->set(tmp_value,16,res->charset());
+ make_scrambled_password_323(tmp_value, res->c_ptr());
+ str->set(tmp_value, SCRAMBLED_PASSWORD_CHAR_LENGTH_323, res->charset());
return str;
}
+char *Item_func_old_password::alloc(THD *thd, const char *password)
+{
+ char *buff= (char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH_323+1);
+ if (buff)
+ make_scrambled_password_323(buff, password);
+ return buff;
+}
#define bin_to_ascii(c) ((c)>=38?((c)-38+'a'):(c)>=12?((c)-12+'A'):(c)+'.')
@@ -2554,6 +2508,31 @@ null:
return 0;
}
+longlong Item_func_uncompressed_length::val_int()
+{
+ String *res= args[0]->val_str(&value);
+ if (!res)
+ {
+ null_value=1;
+ return 0; /* purecov: inspected */
+ }
+ null_value=0;
+ if (res->is_empty()) return 0;
+ return uint4korr(res->c_ptr()) & 0x3FFFFFFF;
+}
+
+longlong Item_func_crc32::val_int()
+{
+ String *res=args[0]->val_str(&value);
+ if (!res)
+ {
+ null_value=1;
+ return 0; /* purecov: inspected */
+ }
+ null_value=0;
+ return (longlong) crc32(0L, (uchar*)res->ptr(), res->length());
+}
+
#ifdef HAVE_COMPRESS
#include "zlib.h"
@@ -2581,7 +2560,7 @@ String *Item_func_compress::val_str(String *str)
buffer.realloc((uint32)new_size + 4 + 1);
Byte *body= ((Byte*)buffer.c_ptr()) + 4;
-
+
if ((err= compress(body, &new_size,
(const Bytef*)res->c_ptr(), res->length())) != Z_OK)
{
@@ -2603,7 +2582,7 @@ String *Item_func_compress::val_str(String *str)
}
buffer.length((uint32)new_size + 4);
-
+
return &buffer;
}
@@ -2615,7 +2594,7 @@ String *Item_func_uncompress::val_str(String *str)
ulong new_size= uint4korr(res->c_ptr()) & 0x3FFFFFFF;
int err= Z_OK;
uint code;
-
+
if (new_size > MAX_BLOB_WIDTH)
{
push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
@@ -2624,21 +2603,20 @@ String *Item_func_uncompress::val_str(String *str)
null_value= 0;
return 0;
}
-
+
buffer.realloc((uint32)new_size);
-
- if ((err= uncompress((Byte*)buffer.c_ptr(), &new_size,
+
+ if ((err= uncompress((Byte*)buffer.c_ptr(), &new_size,
((const Bytef*)res->c_ptr())+4,res->length())) == Z_OK)
{
buffer.length((uint32)new_size);
return &buffer;
}
-
- code= err==Z_BUF_ERROR ? ER_ZLIB_Z_BUF_ERROR :
+
+ code= err==Z_BUF_ERROR ? ER_ZLIB_Z_BUF_ERROR :
err==Z_MEM_ERROR ? ER_ZLIB_Z_MEM_ERROR : ER_ZLIB_Z_DATA_ERROR;
push_warning(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,code,ER(code));
null_value= 1;
return 0;
}
-
#endif
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index f64a145b136..b82dacb4fe0 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -254,30 +254,45 @@ public:
};
+/*
+ Item_func_password -- new (4.1.1) PASSWORD() function implementation.
+ Returns strcat('*', octet2hex(sha1(sha1(password)))). '*' stands for new
+ password format, sha1(sha1(password) is so-called hash_stage2 value.
+ Length of returned string is always 41 byte. To find out how entire
+ authentification procedure works, see comments in password.c.
+*/
+
class Item_func_password :public Item_str_func
{
- char tmp_value[64]; /* This should be enough for new password format */
+ char tmp_value[SCRAMBLED_PASSWORD_CHAR_LENGTH+1];
public:
Item_func_password(Item *a) :Item_str_func(a) {}
- Item_func_password(Item *a, Item *b) :Item_str_func(a,b) {}
- String *val_str(String *);
- void fix_length_and_dec();
+ String *val_str(String *str);
+ void fix_length_and_dec() { max_length= SCRAMBLED_PASSWORD_CHAR_LENGTH; }
const char *func_name() const { return "password"; }
+ static char *alloc(THD *thd, const char *password);
};
+/*
+ Item_func_old_password -- PASSWORD() implementation used in MySQL 3.21 - 4.0
+ compatibility mode. This item is created in sql_yacc.yy when
+ 'old_passwords' session variable is set, and to handle OLD_PASSWORD()
+ function.
+*/
+
class Item_func_old_password :public Item_str_func
{
- char tmp_value[17]; /* old password length +1 */
+ char tmp_value[SCRAMBLED_PASSWORD_CHAR_LENGTH_323+1];
public:
Item_func_old_password(Item *a) :Item_str_func(a) {}
- String *val_str(String *);
- void fix_length_and_dec() { max_length = get_password_length(1); }
+ String *val_str(String *str);
+ void fix_length_and_dec() { max_length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; }
const char *func_name() const { return "old_password"; }
+ static char *alloc(THD *thd, const char *password);
};
-
class Item_func_des_encrypt :public Item_str_func
{
String tmp_value;
@@ -624,9 +639,56 @@ public:
Item_func_collation(Item *a) :Item_str_func(a) {}
String *val_str(String *);
const char *func_name() const { return "collation"; }
- void fix_length_and_dec()
+ void fix_length_and_dec()
{
max_length=40; // should be enough
collation.set(system_charset_info);
};
};
+
+class Item_func_crc32 :public Item_int_func
+{
+ String value;
+public:
+ Item_func_crc32(Item *a) :Item_int_func(a) {}
+ const char *func_name() const { return "crc32"; }
+ void fix_length_and_dec() { max_length=10; }
+ longlong val_int();
+};
+
+class Item_func_uncompressed_length : public Item_int_func
+{
+ String value;
+public:
+ Item_func_uncompressed_length(Item *a):Item_int_func(a){}
+ const char *func_name() const{return "uncompressed_length";}
+ void fix_length_and_dec() { max_length=10; }
+ longlong val_int();
+};
+
+#ifdef HAVE_COMPRESS
+#define ZLIB_DEPENDED_FUNCTION ;
+#else
+#define ZLIB_DEPENDED_FUNCTION { null_value=1; return 0; }
+#endif
+
+class Item_func_compress: public Item_str_func
+{
+ String buffer;
+public:
+ Item_func_compress(Item *a):Item_str_func(a){}
+ void fix_length_and_dec(){max_length= (args[0]->max_length*120)/100+12;}
+ const char *func_name() const{return "compress";}
+ String *val_str(String *) ZLIB_DEPENDED_FUNCTION
+};
+
+class Item_func_uncompress: public Item_str_func
+{
+ String buffer;
+public:
+ Item_func_uncompress(Item *a): Item_str_func(a){}
+ void fix_length_and_dec(){max_length= MAX_BLOB_WIDTH;}
+ const char *func_name() const{return "uncompress";}
+ String *val_str(String *) ZLIB_DEPENDED_FUNCTION
+};
+
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index cbda995504c..79366086a8d 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -72,7 +72,7 @@ Item_subselect::trans_res
Item_subselect::select_transformer(JOIN *join)
{
DBUG_ENTER("Item_subselect::select_transformer");
- DBUG_RETURN(OK);
+ DBUG_RETURN(RES_OK);
}
@@ -214,14 +214,14 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
cond= join->having;
else
if (!(cond= new Item_cond_and(join->conds, join->having)))
- return ERROR;
+ return RES_ERROR;
if (!(substitution= new Item_func_if(cond, substitution,
new Item_null())))
- return ERROR;
+ return RES_ERROR;
}
- return REDUCE;
+ return RES_REDUCE;
}
- return OK;
+ return RES_OK;
}
void Item_singlerow_subselect::store(uint i, Item *item)
@@ -508,7 +508,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
if (!optimizer || optimizer->fix_left(thd, up->get_table_list(), 0))
{
thd->lex.current_select= current;
- DBUG_RETURN(ERROR);
+ DBUG_RETURN(RES_ERROR);
}
thd->lex.current_select= current;
@@ -528,7 +528,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
if (select_lex->item_list.elements > 1)
{
my_error(ER_CARDINALITY_COL, MYF(0), 1);
- DBUG_RETURN(ERROR);
+ DBUG_RETURN(RES_ERROR);
}
item= (Item*) select_lex->item_list.head();
@@ -546,7 +546,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
if (join->having->fix_fields(thd, join->tables_list, &join->having))
{
select_lex->having_fix_field= 0;
- DBUG_RETURN(ERROR);
+ DBUG_RETURN(RES_ERROR);
}
select_lex->having_fix_field= 0;
}
@@ -570,7 +570,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
if (join->having->fix_fields(thd, join->tables_list, &join->having))
{
select_lex->having_fix_field= 0;
- DBUG_RETURN(ERROR);
+ DBUG_RETURN(RES_ERROR);
}
select_lex->having_fix_field= 0;
item= new Item_cond_or(item,
@@ -578,7 +578,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
}
join->conds= and_items(join->conds, item);
if (join->conds->fix_fields(thd, join->tables_list, &join->conds))
- DBUG_RETURN(ERROR);
+ DBUG_RETURN(RES_ERROR);
}
else
{
@@ -592,7 +592,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
if (join->having->fix_fields(thd, join->tables_list, &join->having))
{
select_lex->having_fix_field= 0;
- DBUG_RETURN(ERROR);
+ DBUG_RETURN(RES_ERROR);
}
select_lex->having_fix_field= 0;
}
@@ -610,11 +610,11 @@ Item_in_subselect::single_value_transformer(JOIN *join,
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_SELECT_REDUCED, warn_buff);
}
- DBUG_RETURN(REDUCE);
+ DBUG_RETURN(RES_REDUCE);
}
}
}
- DBUG_RETURN(OK);
+ DBUG_RETURN(RES_OK);
}
Item_subselect::trans_res
@@ -640,7 +640,7 @@ Item_in_subselect::row_value_transformer(JOIN *join,
if (!optimizer || optimizer->fix_left(thd, up->get_table_list(), 0))
{
thd->lex.current_select= current;
- DBUG_RETURN(ERROR);
+ DBUG_RETURN(RES_ERROR);
}
thd->lex.current_select= current;
@@ -679,7 +679,7 @@ Item_in_subselect::row_value_transformer(JOIN *join,
if (join->having->fix_fields(thd, join->tables_list, &join->having))
{
select_lex->having_fix_field= 0;
- DBUG_RETURN(ERROR);
+ DBUG_RETURN(RES_ERROR);
}
select_lex->having_fix_field= 0;
}
@@ -687,9 +687,9 @@ Item_in_subselect::row_value_transformer(JOIN *join,
{
join->conds= and_items(join->conds, item);
if (join->conds->fix_fields(thd, join->tables_list, &join->having))
- DBUG_RETURN(ERROR);
+ DBUG_RETURN(RES_ERROR);
}
- DBUG_RETURN(OK);
+ DBUG_RETURN(RES_OK);
}
Item_subselect::trans_res
@@ -846,7 +846,7 @@ void subselect_union_engine::fix_length_and_dec(Item_cache **row)
SELECT_LEX *sl= unit->first_select();
bool fake= 0;
res_type= set_row(sl, item, row, &fake);
- for (sl= sl->next_select(); sl; sl->next_select())
+ for (sl= sl->next_select(); sl; sl= sl->next_select())
{
List_iterator_fast<Item> li(sl->item_list);
Item *sel_item;
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index ddb53ab616a..174e8809688 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -51,7 +51,7 @@ public:
/* changed engine indicator */
bool engine_changed;
- enum trans_res {OK, REDUCE, ERROR};
+ enum trans_res {RES_OK, RES_REDUCE, RES_ERROR};
enum subs_type {UNKNOWN_SUBS, SINGLEROW_SUBS,
EXISTS_SUBS, IN_SUBS, ALLANY_SUBS};
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 0d05d05f0af..814612cfca8 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -223,10 +223,9 @@ Item *Item_sum_sum::copy_or_same(THD* thd)
}
-bool Item_sum_sum::reset()
+void Item_sum_sum::clear()
{
null_value=1; sum=0.0;
- return Item_sum_sum::add();
}
@@ -251,10 +250,9 @@ Item *Item_sum_count::copy_or_same(THD* thd)
}
-bool Item_sum_count::reset()
+void Item_sum_count::clear()
{
- count=0;
- return add();
+ count= 0;
}
@@ -286,10 +284,9 @@ Item *Item_sum_avg::copy_or_same(THD* thd)
}
-bool Item_sum_avg::reset()
+void Item_sum_avg::clear()
{
sum=0.0; count=0;
- return Item_sum_avg::add();
}
@@ -342,11 +339,10 @@ Item *Item_sum_variance::copy_or_same(THD* thd)
}
-bool Item_sum_variance::reset()
+void Item_sum_variance::clear()
{
sum=sum_sqr=0.0;
count=0;
- return Item_sum_variance::add();
}
bool Item_sum_variance::add()
@@ -592,10 +588,9 @@ longlong Item_sum_bit::val_int()
}
-bool Item_sum_bit::reset()
+void Item_sum_bit::clear()
{
- bits=reset_bits;
- return add();
+ bits= reset_bits;
}
Item *Item_sum_or::copy_or_same(THD* thd)
@@ -1280,7 +1275,7 @@ Item *Item_sum_count_distinct::copy_or_same(THD* thd)
}
-bool Item_sum_count_distinct::reset()
+void Item_sum_count_distinct::clear()
{
if (use_tree)
reset_tree(tree);
@@ -1290,7 +1285,6 @@ bool Item_sum_count_distinct::reset()
table->file->delete_all_rows();
table->file->extra(HA_EXTRA_WRITE_CACHE);
}
- return add();
}
bool Item_sum_count_distinct::add()
@@ -1353,11 +1347,11 @@ longlong Item_sum_count_distinct::val_int()
#ifdef HAVE_DLOPEN
-bool Item_udf_sum::reset()
+void Item_udf_sum::clear()
{
- DBUG_ENTER("Item_udf_sum::reset");
- udf.reset(&null_value);
- DBUG_RETURN(0);
+ DBUG_ENTER("Item_udf_sum::clear");
+ udf.clear();
+ DBUG_VOID_RETURN;
}
bool Item_udf_sum::add()
@@ -1466,7 +1460,7 @@ int group_concat_key_cmp_with_distinct(void* arg, byte* key1,
for (uint i= 0; i < item->arg_count_field; i++)
{
Item *field_item= item->args[i];
- Field *field= field_item->tmp_table_field();
+ Field *field= field_item->real_item()->get_tmp_table_field();
if (field)
{
uint offset= field->abs_offset;
@@ -1497,7 +1491,7 @@ int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2)
{
ORDER *order_item= item->order[i];
Item *item= *order_item->item;
- Field *field= item->tmp_table_field();
+ Field *field= item->real_item()->get_tmp_table_field();
if (field)
{
uint offset= field->abs_offset;
@@ -1548,7 +1542,7 @@ int dump_leaf_key(byte* key, uint32 count __attribute__((unused)),
Item *show_item= group_concat_item->args[i];
if (!show_item->const_item())
{
- Field *f= show_item->tmp_table_field();
+ Field *f= show_item->real_item()->get_tmp_table_field();
char *sv= f->ptr;
f->ptr= (char *)key + f->abs_offset;
String *res= f->val_str(&tmp,&tmp2);
@@ -1685,7 +1679,7 @@ Item *Item_func_group_concat::copy_or_same(THD* thd)
}
-bool Item_func_group_concat::reset()
+void Item_func_group_concat::clear()
{
result.length(0);
result.copy();
@@ -1699,7 +1693,6 @@ bool Item_func_group_concat::reset()
}
if (tree_mode)
reset_tree(tree);
- return add();
}
@@ -1716,7 +1709,7 @@ bool Item_func_group_concat::add()
Item *show_item= args[i];
if (!show_item->const_item())
{
- Field *f= show_item->tmp_table_field();
+ Field *f= show_item->real_item()->get_tmp_table_field();
if (!f->is_null())
{
record_is_null= FALSE;
diff --git a/sql/item_sum.h b/sql/item_sum.h
index ebb90c05215..b2377a96833 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -62,7 +62,8 @@ public:
enum Type type() const { return SUM_FUNC_ITEM; }
virtual enum Sumfunctype sum_func () const=0;
- virtual bool reset()=0;
+ inline bool reset() { clear(); return add(); };
+ virtual void clear()= 0;
virtual bool add()=0;
virtual void reset_field()=0;
virtual void update_field(int offset)=0;
@@ -124,7 +125,7 @@ class Item_sum_sum :public Item_sum_num
Item_sum_sum(THD *thd, Item_sum_sum &item)
:Item_sum_num(thd, item), sum(item.sum) {}
enum Sumfunctype sum_func () const {return SUM_FUNC;}
- bool reset();
+ void clear();
bool add();
double val();
void reset_field();
@@ -151,7 +152,7 @@ class Item_sum_count :public Item_sum_int
table_map used_tables() const { return used_table_cache; }
bool const_item() const { return !used_table_cache; }
enum Sumfunctype sum_func () const { return COUNT_FUNC; }
- bool reset();
+ void clear();
void no_rows_in_result() { count=0; }
bool add();
void make_const(longlong count_arg) { count=count_arg; used_table_cache=0; }
@@ -225,7 +226,7 @@ class Item_sum_count_distinct :public Item_sum_int
table_map used_tables() const { return used_table_cache; }
enum Sumfunctype sum_func () const { return COUNT_DISTINCT_FUNC; }
- bool reset();
+ void clear();
bool add();
longlong val_int();
void reset_field() { return ;} // Never called
@@ -269,7 +270,7 @@ class Item_sum_avg :public Item_sum_num
Item_sum_avg(THD *thd, Item_sum_avg &item)
:Item_sum_num(thd, item), sum(item.sum), count(item.count) {}
enum Sumfunctype sum_func () const {return AVG_FUNC;}
- bool reset();
+ void clear();
bool add();
double val();
void reset_field();
@@ -322,7 +323,7 @@ class Item_sum_variance : public Item_sum_num
Item_sum_num(thd, item), sum(item.sum), sum_sqr(item.sum_sqr),
count(item.count) {}
enum Sumfunctype sum_func () const { return VARIANCE_FUNC; }
- bool reset();
+ void clear();
bool add();
double val();
void reset_field();
@@ -385,19 +386,18 @@ class Item_sum_hybrid :public Item_sum
Item_sum_hybrid(THD *thd, Item_sum_hybrid &item):
Item_sum(thd, item), value(item.value), tmp_value(item.tmp_value),
sum(item.sum), sum_int(item.sum_int), hybrid_type(item.hybrid_type),
- cmp_sign(item.cmp_sign), used_table_cache(used_table_cache),
- cmp_charset(item.cmp_charset) {}
+ hybrid_field_type(item.hybrid_field_type),cmp_sign(item.cmp_sign),
+ used_table_cache(used_table_cache), cmp_charset(item.cmp_charset) {}
bool fix_fields(THD *, TABLE_LIST *, Item **);
table_map used_tables() const { return used_table_cache; }
bool const_item() const { return !used_table_cache; }
- bool reset()
+ void clear()
{
sum=0.0;
sum_int=0;
value.length(0);
null_value=1;
- return add();
}
double val();
longlong val_int();
@@ -451,7 +451,7 @@ class Item_sum_bit :public Item_sum_int
Item_sum_bit(THD *thd, Item_sum_bit &item):
Item_sum_int(thd, item), reset_bits(item.reset_bits), bits(item.bits) {}
enum Sumfunctype sum_func () const {return SUM_BIT_FUNC;}
- bool reset();
+ void clear();
longlong val_int();
void reset_field();
void fix_length_and_dec()
@@ -509,7 +509,7 @@ public:
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
virtual bool have_field_update(void) const { return 0; }
- bool reset();
+ void clear();
bool add();
void reset_field() {};
void update_field(int offset_arg) {};
@@ -591,7 +591,7 @@ class Item_sum_udf_float :public Item_sum_num
~Item_sum_udf_float() {}
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
double val() { return 0.0; }
- bool reset() { return 0; }
+ void clear() {}
bool add() { return 0; }
void update_field(int offset) {}
};
@@ -608,7 +608,7 @@ public:
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
longlong val_int() { return 0; }
double val() { return 0; }
- bool reset() { return 0; }
+ void clear() {}
bool add() { return 0; }
void update_field(int offset) {}
};
@@ -628,7 +628,7 @@ public:
enum Item_result result_type () const { return STRING_RESULT; }
void fix_length_and_dec() { maybe_null=1; max_length=0; }
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
- bool reset() { return 0; }
+ void clear() {}
bool add() { return 0; }
void update_field(int offset) {}
};
@@ -714,7 +714,7 @@ class Item_func_group_concat : public Item_sum
const char *func_name() const { return "group_concat"; }
enum Type type() const { return SUM_FUNC_ITEM; }
virtual Item_result result_type () const { return STRING_RESULT; }
- bool reset();
+ void clear();
bool add();
void reset_field();
bool fix_fields(THD *, TABLE_LIST *, Item **);
@@ -733,4 +733,5 @@ class Item_func_group_concat : public Item_sum
}
String* val_str(String* str);
Item *copy_or_same(THD* thd);
+ void no_rows_in_result() {}
};
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index d84267a5066..6dcf7d00ce1 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -327,7 +327,6 @@ public:
max_length=10*default_charset()->mbmaxlen;
}
int save_in_field(Field *to, bool no_conversions);
- Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
{
return (new Field_date(maybe_null, name, t_arg, default_charset()));
@@ -342,7 +341,6 @@ public:
Item_date_func(Item *a) :Item_str_func(a) {}
Item_date_func(Item *a,Item *b) :Item_str_func(a,b) {}
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
- Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
{
return (new Field_datetime(maybe_null, name, t_arg, default_charset()));
@@ -366,7 +364,6 @@ public:
longlong val_int() { return value; }
String *val_str(String *str);
void fix_length_and_dec();
- Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
{
return (new Field_time(maybe_null, name, t_arg, default_charset()));
@@ -533,7 +530,6 @@ public:
}
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
const char *func_name() const { return "sec_to_time"; }
- Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
{
return (new Field_time(maybe_null, name, t_arg, default_charset()));
@@ -634,7 +630,6 @@ public:
bool get_date(TIME *ltime, bool fuzzy_date);
const char *func_name() const { return "date"; }
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
- Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
{
return (new Field_date(maybe_null, name, t_arg, default_charset()));
@@ -650,7 +645,6 @@ public:
bool get_time(TIME *ltime);
const char *func_name() const { return "time"; }
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
- Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
{
return (new Field_time(maybe_null, name, t_arg, default_charset()));
@@ -665,7 +659,6 @@ public:
String *val_str(String *str);
const char *func_name() const { return "datetime"; }
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
- Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
{
return (new Field_datetime(maybe_null, name, t_arg, default_charset()));
@@ -684,7 +677,6 @@ public:
decimals=0;
max_length=8*MY_CHARSET_BIN_MB_MAXLEN;
}
- Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
{
return (new Field_date(maybe_null, name, t_arg, &my_charset_bin));
@@ -711,7 +703,6 @@ public:
Change this when we support
microseconds in TIME/DATETIME
*/
- Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
{
if (cached_field_type == MYSQL_TYPE_TIME)
@@ -735,7 +726,6 @@ public:
decimals=0;
max_length=17*MY_CHARSET_BIN_MB_MAXLEN;
}
- Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
{
return (new Field_time(maybe_null, name, t_arg, &my_charset_bin));
@@ -755,7 +745,6 @@ public:
decimals=0;
max_length=8*MY_CHARSET_BIN_MB_MAXLEN;
}
- Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
{
return (new Field_time(maybe_null, name, t_arg, &my_charset_bin));
diff --git a/sql/item_uniq.h b/sql/item_uniq.h
index f2c64c4bde9..e41397dac44 100644
--- a/sql/item_uniq.h
+++ b/sql/item_uniq.h
@@ -41,7 +41,7 @@ public:
:Item_sum_num(thd, item) {}
double val() { return 0.0; }
enum Sumfunctype sum_func () const {return UNIQUE_USERS_FUNC;}
- bool reset() { return 0;}
+ void clear() {}
bool add() { return 0; }
void reset_field() {}
void update_field(int offset) {}
diff --git a/sql/lex.h b/sql/lex.h
index 24bfe796cc0..aa6d96d4029 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -249,6 +249,12 @@ static SYMBOL symbols[] = {
{ "MASTER_PASSWORD", SYM(MASTER_PASSWORD_SYM),0,0},
{ "MASTER_PORT", SYM(MASTER_PORT_SYM),0,0},
{ "MASTER_SERVER_ID", SYM(MASTER_SERVER_ID_SYM),0,0},
+ { "MASTER_SSL", SYM(MASTER_SSL_SYM),0,0},
+ { "MASTER_SSL_CA", SYM(MASTER_SSL_CA_SYM),0,0},
+ { "MASTER_SSL_CAPATH",SYM(MASTER_SSL_CAPATH_SYM),0,0},
+ { "MASTER_SSL_CERT", SYM(MASTER_SSL_CERT_SYM),0,0},
+ { "MASTER_SSL_CIPHER",SYM(MASTER_SSL_CIPHER_SYM),0,0},
+ { "MASTER_SSL_KEY", SYM(MASTER_SSL_KEY_SYM),0,0},
{ "MASTER_USER", SYM(MASTER_USER_SYM),0,0},
{ "MAX_ROWS", SYM(MAX_ROWS),0,0},
{ "MAX_QUERIES_PER_HOUR", SYM(MAX_QUERIES_PER_HOUR), 0,0},
@@ -288,6 +294,7 @@ static SYMBOL symbols[] = {
{ "NULL", SYM(NULL_SYM),0,0},
{ "NUMERIC", SYM(NUMERIC_SYM),0,0},
{ "OFFSET", SYM(OFFSET_SYM),0,0},
+ { "OLD_PASSWORD", SYM(OLD_PASSWORD),0,0},
{ "ON", SYM(ON),0,0},
{ "OPEN", SYM(OPEN_SYM),0,0},
{ "OPTIMIZE", SYM(OPTIMIZE),0,0},
@@ -473,9 +480,7 @@ static SYMBOL sql_functions[] = {
{ "COUNT", SYM(COUNT_SYM),0,0},
{ "COS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_cos)},
{ "COT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_cot)},
-#ifdef HAVE_COMPRESS
{ "CRC32", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_crc32)},
-#endif
{ "CROSSES", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_crosses)},
{ "CURDATE", SYM(CURDATE),0,0},
{ "CURTIME", SYM(CURTIME),0,0},
@@ -590,7 +595,6 @@ static SYMBOL sql_functions[] = {
{ "NUMPOINTS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_numpoints)},
{ "OCTET_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_length)},
{ "OCT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_oct)},
- { "OLD_PASSWORD", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_old_password)},
{ "ORD", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ord)},
{ "OVERLAPS", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_overlaps)},
{ "PERIOD_ADD", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_period_add)},
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index a5d9ce5bce3..ea5dc909f74 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -74,9 +74,6 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
****************************************************************************/
#define ACL_CACHE_SIZE 256
-/* Password lengh for 4.1 version previous versions had 16 bytes password hash */
-#define HASH_PASSWORD_LENGTH 45
-#define HASH_OLD_PASSWORD_LENGTH 16
#define MAX_PASSWORD_LENGTH 32
#define HOST_CACHE_SIZE 128
#define MAX_ACCEPT_RETRY 10 // Test accept this many times
@@ -411,6 +408,8 @@ bool check_global_access(THD *thd, ulong want_access);
int mysql_backup_table(THD* thd, TABLE_LIST* table_list);
int mysql_restore_table(THD* thd, TABLE_LIST* table_list);
+int mysql_checksum_table(THD* thd, TABLE_LIST* table_list,
+ HA_CHECK_OPT* check_opt);
int mysql_check_table(THD* thd, TABLE_LIST* table_list,
HA_CHECK_OPT* check_opt);
int mysql_repair_table(THD* thd, TABLE_LIST* table_list,
@@ -771,7 +770,7 @@ extern my_bool opt_safe_show_db, opt_local_infile, lower_case_table_names;
extern my_bool opt_slave_compressed_protocol, use_temp_pool;
extern my_bool opt_readonly;
extern my_bool opt_enable_named_pipe;
-extern my_bool opt_old_passwords, use_old_passwords;
+extern my_bool opt_secure_auth;
extern char *shared_memory_base_name, *mysqld_unix_port;
extern bool opt_enable_shared_memory;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 41bd9706fc3..45c1fdc82d1 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -257,9 +257,10 @@ my_bool opt_local_infile, opt_external_locking, opt_slave_compressed_protocol;
my_bool opt_safe_user_create = 0, opt_no_mix_types = 0;
my_bool lower_case_table_names, opt_old_rpl_compat;
my_bool opt_show_slave_auth_info, opt_sql_bin_update = 0;
-my_bool opt_log_slave_updates= 0, opt_old_passwords=0, use_old_passwords=0;
+my_bool opt_log_slave_updates= 0;
my_bool opt_console= 0, opt_bdb, opt_innodb, opt_isam;
my_bool opt_readonly, use_temp_pool, relay_log_purge;
+my_bool opt_secure_auth= 0;
volatile bool mqh_used = 0;
uint mysqld_port, test_flags, select_errors, dropping_tables, ha_open_options;
@@ -362,15 +363,15 @@ pthread_t signal_thread;
pthread_attr_t connection_attrib;
/* replication parameters, if master_host is not NULL, we are a slave */
-my_bool master_ssl;
uint master_port= MYSQL_PORT, master_connect_retry = 60;
uint report_port= MYSQL_PORT;
ulong master_retry_count=0;
char *master_user, *master_password, *master_host, *master_info_file;
-char *relay_log_info_file, *master_ssl_key, *master_ssl_cert;
-char *master_ssl_capath, *master_ssl_cipher, *report_user;
-char *report_password, *report_host;
+char *relay_log_info_file, *report_user, *report_password, *report_host;
char *opt_relay_logname = 0, *opt_relaylog_index_name=0;
+my_bool master_ssl;
+char *master_ssl_key, *master_ssl_cert;
+char *master_ssl_ca, *master_ssl_capath, *master_ssl_cipher;
/* Static variables */
@@ -2819,12 +2820,6 @@ static void create_new_thread(THD *thd)
if (thread_count-delayed_insert_threads > max_used_connections)
max_used_connections=thread_count-delayed_insert_threads;
thd->thread_id=thread_id++;
- for (uint i=0; i < 8 ; i++) // Generate password teststring
- thd->scramble[i]= (char) (my_rnd(&sql_rand)*94+33);
- thd->scramble[8]=0;
- // Back it up as old clients may need it
- memcpy(thd->old_scramble,thd->scramble,9);
-
thd->real_id=pthread_self(); // Keep purify happy
@@ -3445,7 +3440,7 @@ enum options
OPT_MASTER_RETRY_COUNT,
OPT_MASTER_SSL, OPT_MASTER_SSL_KEY,
OPT_MASTER_SSL_CERT, OPT_MASTER_SSL_CAPATH,
- OPT_MASTER_SSL_CIPHER,
+ OPT_MASTER_SSL_CIPHER, OPT_MASTER_SSL_CA,
OPT_SQL_BIN_UPDATE_SAME, OPT_REPLICATE_DO_DB,
OPT_REPLICATE_IGNORE_DB, OPT_LOG_SLAVE_UPDATES,
OPT_BINLOG_DO_DB, OPT_BINLOG_IGNORE_DB,
@@ -3535,7 +3530,8 @@ enum options
OPT_EXPIRE_LOGS_DAYS,
OPT_DEFAULT_WEEK_FORMAT,
OPT_GROUP_CONCAT_MAX_LEN,
- OPT_DEFAULT_COLLATION
+ OPT_DEFAULT_COLLATION,
+ OPT_SECURE_AUTH
};
@@ -3783,27 +3779,28 @@ thread is in the master's binlogs.",
(gptr*) &master_info_file, (gptr*) &master_info_file, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"master-ssl", OPT_MASTER_SSL,
- "Planned to enable the slave to connect to the master using SSL. Does nothing yet.",
+ "Enable the slave to connect to the master using SSL.",
(gptr*) &master_ssl, (gptr*) &master_ssl, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
0, 0},
{"master-ssl-key", OPT_MASTER_SSL_KEY,
- "Master SSL keyfile name. Only applies if you have enabled master-ssl. Does \
-nothing yet.",
+ "Master SSL keyfile name. Only applies if you have enabled master-ssl.",
(gptr*) &master_ssl_key, (gptr*) &master_ssl_key, 0, GET_STR, OPT_ARG,
0, 0, 0, 0, 0, 0},
{"master-ssl-cert", OPT_MASTER_SSL_CERT,
"Master SSL certificate file name. Only applies if you have enabled \
-master-ssl. Does nothing yet.",
+master-ssl",
(gptr*) &master_ssl_cert, (gptr*) &master_ssl_cert, 0, GET_STR, OPT_ARG,
0, 0, 0, 0, 0, 0},
+ {"master-ssl-ca", OPT_MASTER_SSL_CA,
+ "Master SSL CA file. Only applies if you have enabled master-ssl.",
+ (gptr*) &master_ssl_ca, (gptr*) &master_ssl_ca, 0, GET_STR, OPT_ARG,
+ 0, 0, 0, 0, 0, 0},
{"master-ssl-capath", OPT_MASTER_SSL_CAPATH,
- "Master SSL CA path. Only applies if you have enabled master-ssl. \
-Does nothing yet.",
+ "Master SSL CA path. Only applies if you have enabled master-ssl.",
(gptr*) &master_ssl_capath, (gptr*) &master_ssl_capath, 0, GET_STR, OPT_ARG,
0, 0, 0, 0, 0, 0},
{"master-ssl-cipher", OPT_MASTER_SSL_CIPHER,
- "Master SSL cipher. Only applies if you have enabled master-ssl. \
-Does nothing yet.",
+ "Master SSL cipher. Only applies if you have enabled master-ssl.",
(gptr*) &master_ssl_cipher, (gptr*) &master_ssl_capath, 0, GET_STR, OPT_ARG,
0, 0, 0, 0, 0, 0},
{"myisam-recover", OPT_MYISAM_RECOVER,
@@ -3844,9 +3841,10 @@ Does nothing yet.",
(gptr*) &opt_no_mix_types, (gptr*) &opt_no_mix_types, 0, GET_BOOL, NO_ARG,
0, 0, 0, 0, 0, 0},
#endif
- {"old-protocol", 'o', "Use the old (3.20) protocol client/server protocol.",
- (gptr*) &protocol_version, (gptr*) &protocol_version, 0, GET_UINT, NO_ARG,
- PROTOCOL_VERSION, 0, 0, 0, 0, 0},
+ {"old-passwords", OPT_OLD_PASSWORDS, "Use old password encryption method (needed for 4.0 and older clients).",
+ (gptr*) &global_system_variables.old_passwords,
+ (gptr*) &max_system_variables.old_passwords, 0, GET_BOOL, NO_ARG,
+ 0, 0, 0, 0, 0, 0},
{"old-rpl-compat", OPT_OLD_RPL_COMPAT,
"Use old LOAD DATA format in the binary log (don't save data in file).",
(gptr*) &opt_old_rpl_compat, (gptr*) &opt_old_rpl_compat, 0, GET_BOOL,
@@ -3913,8 +3911,6 @@ relay logs.",
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"safe-mode", OPT_SAFE, "Skip some optimize stages (for testing).",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"old-passwords", OPT_OLD_PASSWORDS, "Use old password encryption method (needed for 4.0 and older clients).",
- (gptr*) &opt_old_passwords, (gptr*) &opt_old_passwords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
#ifndef TO_BE_DELETED
{"safe-show-database", OPT_SAFE_SHOW_DB,
"Deprecated option; One should use GRANT SHOW DATABASES instead...",
@@ -3924,6 +3920,9 @@ relay logs.",
"Don't allow new user creation by the user who has no write privileges to the mysql.user table.",
(gptr*) &opt_safe_user_create, (gptr*) &opt_safe_user_create, 0, GET_BOOL,
NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"secure-auth", OPT_SECURE_AUTH, "Disallow authentication for accounts that have old (pre-4.1) passwords.",
+ (gptr*) &opt_secure_auth, (gptr*) &opt_secure_auth, 0, GET_BOOL, NO_ARG,
+ my_bool(0), 0, 0, 0, 0, 0},
{"server-id", OPT_SERVER_ID,
"Uniquely identifies the server instance in the community of replication partners.",
(gptr*) &server_id, (gptr*) &server_id, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 0,
@@ -4452,14 +4451,15 @@ struct show_var_st status_vars[]= {
{"Bytes_received", (char*) &bytes_received, SHOW_LONG},
{"Bytes_sent", (char*) &bytes_sent, SHOW_LONG},
{"Com_admin_commands", (char*) &com_other, SHOW_LONG},
- {"Com_alter_table", (char*) (com_stat+(uint) SQLCOM_ALTER_TABLE),SHOW_LONG},
{"Com_alter_db", (char*) (com_stat+(uint) SQLCOM_ALTER_DB),SHOW_LONG},
+ {"Com_alter_table", (char*) (com_stat+(uint) SQLCOM_ALTER_TABLE),SHOW_LONG},
{"Com_analyze", (char*) (com_stat+(uint) SQLCOM_ANALYZE),SHOW_LONG},
{"Com_backup_table", (char*) (com_stat+(uint) SQLCOM_BACKUP_TABLE),SHOW_LONG},
{"Com_begin", (char*) (com_stat+(uint) SQLCOM_BEGIN),SHOW_LONG},
{"Com_change_db", (char*) (com_stat+(uint) SQLCOM_CHANGE_DB),SHOW_LONG},
{"Com_change_master", (char*) (com_stat+(uint) SQLCOM_CHANGE_MASTER),SHOW_LONG},
{"Com_check", (char*) (com_stat+(uint) SQLCOM_CHECK),SHOW_LONG},
+ {"Com_checksum", (char*) (com_stat+(uint) SQLCOM_CHECKSUM),SHOW_LONG},
{"Com_commit", (char*) (com_stat+(uint) SQLCOM_COMMIT),SHOW_LONG},
{"Com_create_db", (char*) (com_stat+(uint) SQLCOM_CREATE_DB),SHOW_LONG},
{"Com_create_function", (char*) (com_stat+(uint) SQLCOM_CREATE_FUNCTION),SHOW_LONG},
@@ -4472,6 +4472,7 @@ struct show_var_st status_vars[]= {
{"Com_drop_function", (char*) (com_stat+(uint) SQLCOM_DROP_FUNCTION),SHOW_LONG},
{"Com_drop_index", (char*) (com_stat+(uint) SQLCOM_DROP_INDEX),SHOW_LONG},
{"Com_drop_table", (char*) (com_stat+(uint) SQLCOM_DROP_TABLE),SHOW_LONG},
+ {"Com_drop_user", (char*) (com_stat+(uint) SQLCOM_DROP_USER),SHOW_LONG},
{"Com_flush", (char*) (com_stat+(uint) SQLCOM_FLUSH),SHOW_LONG},
{"Com_grant", (char*) (com_stat+(uint) SQLCOM_GRANT),SHOW_LONG},
{"Com_ha_close", (char*) (com_stat+(uint) SQLCOM_HA_CLOSE),SHOW_LONG},
@@ -4486,6 +4487,7 @@ struct show_var_st status_vars[]= {
{"Com_load_master_table", (char*) (com_stat+(uint) SQLCOM_LOAD_MASTER_TABLE),SHOW_LONG},
{"Com_lock_tables", (char*) (com_stat+(uint) SQLCOM_LOCK_TABLES),SHOW_LONG},
{"Com_optimize", (char*) (com_stat+(uint) SQLCOM_OPTIMIZE),SHOW_LONG},
+ {"Com_preload_keys", (char*) (com_stat+(uint) SQLCOM_PRELOAD_KEYS),SHOW_LONG},
{"Com_purge", (char*) (com_stat+(uint) SQLCOM_PURGE),SHOW_LONG},
{"Com_purge_before_date", (char*) (com_stat+(uint) SQLCOM_PURGE_BEFORE),SHOW_LONG},
{"Com_rename_table", (char*) (com_stat+(uint) SQLCOM_RENAME_TABLE),SHOW_LONG},
@@ -4495,13 +4497,15 @@ struct show_var_st status_vars[]= {
{"Com_reset", (char*) (com_stat+(uint) SQLCOM_RESET),SHOW_LONG},
{"Com_restore_table", (char*) (com_stat+(uint) SQLCOM_RESTORE_TABLE),SHOW_LONG},
{"Com_revoke", (char*) (com_stat+(uint) SQLCOM_REVOKE),SHOW_LONG},
+ {"Com_revoke_all", (char*) (com_stat+(uint) SQLCOM_REVOKE_ALL),SHOW_LONG},
{"Com_rollback", (char*) (com_stat+(uint) SQLCOM_ROLLBACK),SHOW_LONG},
{"Com_savepoint", (char*) (com_stat+(uint) SQLCOM_SAVEPOINT),SHOW_LONG},
{"Com_select", (char*) (com_stat+(uint) SQLCOM_SELECT),SHOW_LONG},
{"Com_set_option", (char*) (com_stat+(uint) SQLCOM_SET_OPTION),SHOW_LONG},
- {"Com_show_binlog_events", (char*) (com_stat+(uint) SQLCOM_SHOW_BINLOG_EVENTS),SHOW_LONG},
{"Com_show_binlogs", (char*) (com_stat+(uint) SQLCOM_SHOW_BINLOGS),SHOW_LONG},
+ {"Com_show_binlog_events", (char*) (com_stat+(uint) SQLCOM_SHOW_BINLOG_EVENTS),SHOW_LONG},
{"Com_show_charsets", (char*) (com_stat+(uint) SQLCOM_SHOW_CHARSETS),SHOW_LONG},
+ {"Com_show_collations", (char*) (com_stat+(uint) SQLCOM_SHOW_COLLATIONS),SHOW_LONG},
{"Com_show_column_types", (char*) (com_stat+(uint) SQLCOM_SHOW_COLUMN_TYPES),SHOW_LONG},
{"Com_show_create_table", (char*) (com_stat+(uint) SQLCOM_SHOW_CREATE),SHOW_LONG},
{"Com_show_create_db", (char*) (com_stat+(uint) SQLCOM_SHOW_CREATE_DB),SHOW_LONG},
@@ -4509,6 +4513,7 @@ struct show_var_st status_vars[]= {
{"Com_show_errors", (char*) (com_stat+(uint) SQLCOM_SHOW_ERRORS),SHOW_LONG},
{"Com_show_fields", (char*) (com_stat+(uint) SQLCOM_SHOW_FIELDS),SHOW_LONG},
{"Com_show_grants", (char*) (com_stat+(uint) SQLCOM_SHOW_GRANTS),SHOW_LONG},
+ {"Com_show_innodb_status", (char*) (com_stat+(uint) SQLCOM_SHOW_INNODB_STATUS),SHOW_LONG},
{"Com_show_keys", (char*) (com_stat+(uint) SQLCOM_SHOW_KEYS),SHOW_LONG},
{"Com_show_logs", (char*) (com_stat+(uint) SQLCOM_SHOW_LOGS),SHOW_LONG},
{"Com_show_master_status", (char*) (com_stat+(uint) SQLCOM_SHOW_MASTER_STAT),SHOW_LONG},
@@ -4519,7 +4524,6 @@ struct show_var_st status_vars[]= {
{"Com_show_slave_hosts", (char*) (com_stat+(uint) SQLCOM_SHOW_SLAVE_HOSTS),SHOW_LONG},
{"Com_show_slave_status", (char*) (com_stat+(uint) SQLCOM_SHOW_SLAVE_STAT),SHOW_LONG},
{"Com_show_status", (char*) (com_stat+(uint) SQLCOM_SHOW_STATUS),SHOW_LONG},
- {"Com_show_innodb_status", (char*) (com_stat+(uint) SQLCOM_SHOW_INNODB_STATUS),SHOW_LONG},
{"Com_show_tables", (char*) (com_stat+(uint) SQLCOM_SHOW_TABLES),SHOW_LONG},
{"Com_show_table_types", (char*) (com_stat+(uint) SQLCOM_SHOW_TABLE_TYPES),SHOW_LONG},
{"Com_show_variables", (char*) (com_stat+(uint) SQLCOM_SHOW_VARIABLES),SHOW_LONG},
@@ -4708,7 +4712,8 @@ static void mysql_init_variables(void)
opt_log= opt_update_log= opt_bin_log= opt_slow_log= 0;
opt_disable_networking= opt_skip_show_db=0;
opt_logname= opt_update_logname= opt_binlog_index_name= opt_slow_logname=0;
- opt_bootstrap= opt_myisam_log= use_old_passwords= 0;
+ opt_secure_auth= 0;
+ opt_bootstrap= opt_myisam_log= 0;
mqh_used= 0;
segfaulted= kill_in_progress= 0;
cleanup_done= 0;
@@ -4787,8 +4792,9 @@ static void mysql_init_variables(void)
master_user= (char*) "test";
master_password= master_host= 0;
master_info_file= (char*) "master.info",
- relay_log_info_file= (char*) "relay-log.info",
- master_ssl_key= master_ssl_cert= master_ssl_capath= master_ssl_cipher= 0;
+ relay_log_info_file= (char*) "relay-log.info";
+ master_ssl_key= master_ssl_cert= master_ssl_ca=
+ master_ssl_capath= master_ssl_cipher= 0;
report_user= report_password = report_host= 0; /* TO BE DELETED */
opt_relay_logname= opt_relaylog_index_name= 0;
@@ -4811,6 +4817,7 @@ static void mysql_init_variables(void)
max_system_variables.select_limit= (ulonglong) HA_POS_ERROR;
global_system_variables.max_join_size= (ulonglong) HA_POS_ERROR;
max_system_variables.max_join_size= (ulonglong) HA_POS_ERROR;
+ global_system_variables.old_passwords= 0;
/* Variables that depends on compile options */
#ifndef DBUG_OFF
@@ -4932,9 +4939,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case 'L':
strmake(language, argument, sizeof(language)-1);
break;
- case 'o':
- protocol_version=PROTOCOL_VERSION-1;
- break;
#ifdef HAVE_REPLICATION
case OPT_SLAVE_SKIP_ERRORS:
init_slave_skip_errors(argument);
diff --git a/sql/password.c b/sql/password.c
index 257547671e5..9f4910d8c60 100644
--- a/sql/password.c
+++ b/sql/password.c
@@ -29,28 +29,33 @@
The password is saved (in user.password) by using the PASSWORD() function in
mysql.
+ This is .c file because it's used in libmysqlclient, which is entirely in C.
+ (we need it to be portable to a variety of systems).
Example:
update user set password=PASSWORD("hello") where user="test"
This saves a hashed number as a string in the password field.
+ The new autentication is performed in following manner:
- New in MySQL 4.1 authentication works even more secure way.
- At the first step client sends user name to the sever, and password if
- it is empty. So in case of empty password authentication is as fast as before.
- At the second stap servers sends scramble to client, which is encoded with
- password stage2 hash stored in the password database as well as salt, needed
- for client to build stage2 password to decrypt scramble.
- Client decrypts the scramble and encrypts it once again with stage1 password.
- This information is sent to server.
- Server decrypts the scramble to get stage1 password and hashes it to get
- stage2 hash. This hash is when compared to hash stored in the database.
+ SERVER: public_seed=create_random_string()
+ send(public_seed)
- This authentication needs 2 packet round trips instead of one but it is much
- stronger. Now if one will steal mysql database content he will not be able
- to break into MySQL.
+ CLIENT: recv(public_seed)
+ hash_stage1=sha1("password")
+ hash_stage2=sha1(hash_stage1)
+ reply=xor(hash_stage1, sha1(public_seed,hash_stage2)
- New Password handling functions by Peter Zaitsev
+ // this three steps are done in scramble()
+ send(reply)
+
+
+ SERVER: recv(reply)
+ hash_stage1=xor(reply, sha1(public_seed,hash_stage2))
+ candidate_hash2=sha1(hash_stage1)
+ check(candidate_hash2==hash_stage2)
+
+ // this three steps are done in check_scramble()
*****************************************************************************/
@@ -60,31 +65,21 @@
#include <sha1.h>
#include "mysql.h"
-
-
-/* Character to use as version identifier for version 4.1 */
-#define PVERSION41_CHAR '*'
-
-/* Scramble length for new password version */
-
+/************ MySQL 3.23-4.0 authentification routines: untouched ***********/
/*
New (MySQL 3.21+) random generation structure initialization
-
SYNOPSIS
randominit()
rand_st OUT Structure to initialize
seed1 IN First initialization parameter
seed2 IN Second initialization parameter
-
- RETURN
- none
*/
-void randominit(struct rand_struct *rand_st,ulong seed1, ulong seed2)
-{ /* For mysql 3.21.# */
+void randominit(struct rand_struct *rand_st, ulong seed1, ulong seed2)
+{ /* For mysql 3.21.# */
#ifdef HAVE_purify
- bzero((char*) rand_st,sizeof(*rand_st)); /* Avoid UMC varnings */
+ bzero((char*) rand_st,sizeof(*rand_st)); /* Avoid UMC varnings */
#endif
rand_st->max_value= 0x3FFFFFFFL;
rand_st->max_value_dbl=(double) rand_st->max_value;
@@ -94,35 +89,12 @@ void randominit(struct rand_struct *rand_st,ulong seed1, ulong seed2)
/*
- Old (MySQL 3.20) random generation structure initialization
-
- SYNOPSIS
- old_randominit()
- rand_st OUT Structure to initialize
- seed1 IN First initialization parameter
-
- RETURN
- none
-*/
-
-static void old_randominit(struct rand_struct *rand_st,ulong seed1)
-{ /* For mysql 3.20.# */
- rand_st->max_value= 0x01FFFFFFL;
- rand_st->max_value_dbl=(double) rand_st->max_value;
- seed1%=rand_st->max_value;
- rand_st->seed1=seed1 ; rand_st->seed2=seed1/2;
-}
-
-
-/*
- Generate Random number
-
+ Generate random number.
SYNOPSIS
my_rnd()
rand_st INOUT Structure used for number generation
-
- RETURN
- Generated pseudo random number
+ RETURN VALUE
+ generated pseudo random number
*/
double my_rnd(struct rand_struct *rand_st)
@@ -134,73 +106,24 @@ double my_rnd(struct rand_struct *rand_st)
/*
- Generate String of printable random characters of requested length
- String will not be zero terminated.
-
+ Generate binary hash from raw text string
+ Used for Pre-4.1 password handling
SYNOPSIS
- create_random_string()
- length IN Lenght of
- rand_st INOUT Structure used for number generation
- target OUT Buffer for generation
-
- RETURN
- none
+ hash_password()
+ result OUT store hash in this location
+ password IN plain text password to build hash
+ password_len IN password length (password may be not null-terminated)
*/
-void create_random_string(int length,struct rand_struct *rand_st,char *target)
-{
- char *end=target+length;
- /* Use pointer arithmetics as it is faster way to do so. */
- for (; target<end ; target++)
- *target= (char) (my_rnd(rand_st)*94+33);
-}
-
-
-/*
- Encrypt/Decrypt function used for password encryption in authentication
- Simple XOR is used here but it is OK as we crypt random strings
-
- SYNOPSIS
- password_crypt()
- from IN Data for encryption
- to OUT Encrypt data to the buffer (may be the same)
- password IN Password used for encryption (same length)
- length IN Length of data to encrypt
-
- RETURN
- none
-*/
-
-void password_crypt(const char *from,char *to, const char *password,int length)
-{
- const char *from_end=from+length;
-
- while (from < from_end)
- *to++= *(from++) ^* (password++);
-}
-
-
-/*
- Generate binary hash from raw text password
- Used for Pre-4.1 Password handling
-
- SYNOPSIS
- hash_pasword()
- result OUT Store hash in this location
- password IN Plain text password to build hash
-
- RETURN
- none
-*/
-
-void hash_password(ulong *result, const char *password)
+void hash_password(ulong *result, const char *password, uint password_len)
{
register ulong nr=1345345333L, add=7, nr2=0x12345671L;
ulong tmp;
- for (; *password ; password++)
+ const char *password_end= password + password_len;
+ for (; password < password_end; password++)
{
if (*password == ' ' || *password == '\t')
- continue; /* skipp space in password */
+ continue; /* skip space in password */
tmp= (ulong) (uchar) *password;
nr^= (((nr & 63)+add)*tmp)+ (nr << 8);
nr2+=(nr2 << 8) ^ nr;
@@ -208,519 +131,388 @@ void hash_password(ulong *result, const char *password)
}
result[0]=nr & (((ulong) 1L << 31) -1L); /* Don't use sign bit (str2int) */;
result[1]=nr2 & (((ulong) 1L << 31) -1L);
- return;
}
/*
- Stage one password hashing.
- Used in MySQL 4.1 password handling
-
+ Create password to be stored in user database from raw string
+ Used for pre-4.1 password handling
SYNOPSIS
- password_hash_stage1()
- to OUT Store stage one hash to this location
- password IN Plain text password to build hash
-
- RETURN
- none
+ make_scrambled_password_323()
+ to OUT store scrambled password here
+ password IN user-supplied password
*/
-void password_hash_stage1(char *to, const char *password)
+void make_scrambled_password_323(char *to, const char *password)
{
- SHA1_CONTEXT context;
- sha1_reset(&context);
- for (; *password ; password++)
- {
- if (*password == ' ' || *password == '\t')
- continue;/* skip space in password */
- sha1_input(&context,(uint8*) &password[0],1);
- }
- sha1_result(&context,(uint8*)to);
+ ulong hash_res[2];
+ hash_password(hash_res, password, strlen(password));
+ sprintf(to, "%08lx%08lx", hash_res[0], hash_res[1]);
}
/*
- Stage two password hashing.
- Used in MySQL 4.1 password handling
-
+ Scramble string with password.
+ Used in pre 4.1 authentication phase.
SYNOPSIS
- password_hash_stage2()
- to INOUT Use this as stage one hash and store stage two hash here
- salt IN Salt used for stage two hashing
-
- RETURN
- none
+ scramble_323()
+ to OUT Store scrambled message here. Buffer must be at least
+ SCRAMBLE_LENGTH_323+1 bytes long
+ message IN Message to scramble. Message must be at least
+ SRAMBLE_LENGTH_323 bytes long.
+ password IN Password to use while scrambling
*/
-void password_hash_stage2(char *to, const char *salt)
+void scramble_323(char *to, const char *message, const char *password)
{
- SHA1_CONTEXT context;
- sha1_reset(&context);
- sha1_input(&context,(uint8*) salt, 4);
- sha1_input(&context,(uint8*) to, SHA1_HASH_SIZE);
- sha1_result(&context,(uint8*) to);
+ struct rand_struct rand_st;
+ ulong hash_pass[2], hash_message[2];
+
+ if (password && password[0])
+ {
+ char extra, *to_start=to;
+ const char *message_end= message + SCRAMBLE_LENGTH_323;
+ hash_password(hash_pass,password, strlen(password));
+ hash_password(hash_message, message, SCRAMBLE_LENGTH_323);
+ randominit(&rand_st,hash_pass[0] ^ hash_message[0],
+ hash_pass[1] ^ hash_message[1]);
+ for (; message < message_end; message++)
+ *to++= (char) (floor(my_rnd(&rand_st)*31)+64);
+ extra=(char) (floor(my_rnd(&rand_st)*31));
+ while (to_start != to)
+ *(to_start++)^=extra;
+ }
+ *to= 0;
}
/*
- Create password to be stored in user database from raw string
- Handles both MySQL 4.1 and Pre-MySQL 4.1 passwords
-
+ Check scrambled message
+ Used in pre 4.1 password handling
SYNOPSIS
- make_scramble_password()
- to OUT Store scrambled password here
- password IN Raw string password
- force_old_scramle
- IN Force generation of old scramble variant
- rand_st INOUT Structure for temporary number generation.
- RETURN
- none
+ check_scramble_323()
+ scrambled scrambled message to check.
+ message original random message which was used for scrambling; must
+ be exactly SCRAMBLED_LENGTH_323 bytes long and
+ NULL-terminated.
+ hash_pass password which should be used for scrambling
+ All params are IN.
+
+ RETURN VALUE
+ 0 - password correct
+ !0 - password invalid
*/
-void make_scrambled_password(char *to,const char *password,
- my_bool force_old_scramble,
- struct rand_struct *rand_st)
+my_bool
+check_scramble_323(const char *scrambled, const char *message,
+ ulong *hash_pass)
{
- ulong hash_res[2]; /* Used for pre 4.1 password hashing */
- unsigned short salt; /* Salt for 4.1 version password */
- uint8 digest[SHA1_HASH_SIZE];
- if (force_old_scramble) /* Pre 4.1 password encryption */
- {
- hash_password(hash_res,password);
- sprintf(to,"%08lx%08lx",hash_res[0],hash_res[1]);
- }
- else /* New password 4.1 password scrambling */
+ struct rand_struct rand_st;
+ ulong hash_message[2];
+ char buff[16],*to,extra; /* Big enough for check */
+ const char *pos;
+
+ hash_password(hash_message, message, SCRAMBLE_LENGTH_323);
+ randominit(&rand_st,hash_pass[0] ^ hash_message[0],
+ hash_pass[1] ^ hash_message[1]);
+ to=buff;
+ for (pos=scrambled ; *pos ; pos++)
+ *to++=(char) (floor(my_rnd(&rand_st)*31)+64);
+ extra=(char) (floor(my_rnd(&rand_st)*31));
+ to=buff;
+ while (*scrambled)
{
- to[0]=PVERSION41_CHAR; /* New passwords have version prefix */
- /* Rnd returns number from 0 to 1 so this would be good salt generation.*/
- salt=(unsigned short) (my_rnd(rand_st)*65535+1);
- /* Use only 2 first bytes from it */
- sprintf(to+1,"%04x",salt);
- /* First hasing is done without salt */
- password_hash_stage1((char*) digest, password);
- /* Second stage is done with salt */
- password_hash_stage2((char*) digest,(char*)to+1),
- /* Print resulting hash into the password*/
- sprintf(to+5,
- "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
- digest[0],digest[1],digest[2],digest[3],digest[4],digest[5],digest[6],
- digest[7],digest[8],digest[9],digest[10],digest[11],digest[12],digest[13],
- digest[14],digest[15],digest[16],digest[17],digest[18],digest[19]);
+ if (*scrambled++ != (char) (*to++ ^ extra))
+ return 1; /* Wrong password */
}
+ return 0;
}
+static inline uint8 char_val(uint8 X)
+{
+ return (uint) (X >= '0' && X <= '9' ? X-'0' :
+ X >= 'A' && X <= 'Z' ? X-'A'+10 : X-'a'+10);
+}
-/*
- Convert password from binary string form to salt form
- Used for MySQL 4.1 password handling
+/*
+ Convert password from hex string (as stored in mysql.user) to binary form.
SYNOPSIS
- get_salt_from_bin_password()
- res OUT Store salt form password here
- password IN Binary password to be converted
- salt IN hashing-salt to be used for salt form generation
-
- RETURN
- none
+ get_salt_from_password_323()
+ res OUT store salt here
+ password IN password string as stored in mysql.user
+ NOTE
+ This function does not have length check for passwords. It will just crash
+ Password hashes in old format must have length divisible by 8
*/
-void get_salt_from_bin_password(ulong *res,unsigned char *password,ulong salt)
+void get_salt_from_password_323(ulong *res, const char *password)
{
- unsigned char *password_end=password+SCRAMBLE41_LENGTH;
- *res=salt;
- res++;
-
- /* Process password of known length*/
- while (password<password_end)
+ res[0]= res[1]= 0;
+ if (password)
{
- ulong val=0;
- uint i;
- for (i=0 ; i < 4 ; i++)
- val=(val << 8)+(*password++);
- *res++=val;
+ while (*password)
+ {
+ ulong val=0;
+ uint i;
+ for (i=0 ; i < 8 ; i++)
+ val=(val << 4)+char_val(*password++);
+ *res++=val;
+ }
}
}
/*
- Validate password for MySQL 4.1 password handling.
-
+ Convert scrambled password from binary form to asciiz hex string.
SYNOPSIS
- validate_password()
- password IN Encrypted Scramble which we got from the client
- message IN Original scramble which we have sent to the client before
- salt IN Password in the salted form to match to
-
- RETURN
- 0 for correct password
- !0 for invalid password
+ make_password_from_salt_323()
+ to OUT store resulting string password here, at least 17 bytes
+ salt IN password in salt format, 2 ulongs
*/
-my_bool validate_password(const char *password, const char *message,
- ulong *salt)
+void make_password_from_salt_323(char *to, const ulong *salt)
{
- char buffer[SCRAMBLE41_LENGTH]; /* Used for password validation */
- char tmpsalt[8]; /* Temporary value to convert salt to string form */
- ulong salt_candidate[6]; /* Computed candidate salt */
- ulong *sc=salt_candidate; /* we need to be able to increment */
- ulong *salt_end;
-
- /* Now we shall get stage1 encrypted password in buffer*/
- password_crypt(password,buffer,message,SCRAMBLE41_LENGTH);
-
- /* For compatibility reasons we use ulong to store salt while we need char */
- sprintf(tmpsalt,"%04x",(unsigned short)salt[0]);
-
- password_hash_stage2(buffer,tmpsalt);
- /* Convert password to salt to compare */
- get_salt_from_bin_password(salt_candidate,(uchar*) buffer,salt[0]);
-
- /* Now we shall get exactly the same password as we have stored for user */
- for (salt_end=salt+5 ; salt < salt_end; )
- if (*++salt != *++sc)
- return 1;
-
- /* Or password correct*/
- return 0;
+ sprintf(to,"%08lx%08lx", salt[0], salt[1]);
}
/*
- Get length of password string which is stored in mysql.user table
+ **************** MySQL 4.1.1 authentification routines *************
+*/
+/*
+ Generate string of printable random characters of requested length
SYNOPSIS
- get_password_length()
- force_old_scramble IN If we wish to use pre 4.1 scramble format
-
- RETURN
- password length >0
+ create_random_string()
+ to OUT buffer for generation; must be at least length+1 bytes
+ long; result string is always null-terminated
+ length IN how many random characters to put in buffer
+ rand_st INOUT structure used for number generation
*/
-int get_password_length(my_bool force_old_scramble)
+void create_random_string(char *to, uint length, struct rand_struct *rand_st)
{
- return (force_old_scramble) ? 16 : SHA1_HASH_SIZE*2+4+1;
+ char *end= to + length;
+ /* Use pointer arithmetics as it is faster way to do so. */
+ for (; to < end; to++)
+ *to= (char) (my_rnd(rand_st)*94+33);
+ *to= '\0';
}
-/*
- Get version of the password based on mysql.user password string
-
- SYNOPSIS
- get_password_version()
- password IN Password string as stored in mysql.user
-
- RETURN
- 0 for pre 4.1 passwords
- !0 password version char for newer passwords
-*/
+/* Character to use as version identifier for version 4.1 */
-char get_password_version(const char *password)
-{
- if (password==NULL) return 0;
- if (password[0]==PVERSION41_CHAR) return PVERSION41_CHAR;
- return 0;
-}
+#define PVERSION41_CHAR '*'
/*
- Get integer value of Hex character
-
+ Convert given octet sequence to asciiz string of hex characters;
+ str..str+len and 'to' may not overlap.
SYNOPSIS
- char_val()
- X IN Character to find value for
-
- RETURN
- Appropriate integer value
+ octet2hex()
+ buf OUT output buffer. Must be at least 2*len+1 bytes
+ str, len IN the beginning and the length of the input string
*/
-
-
-static inline unsigned int char_val(char X)
+static void
+octet2hex(char *to, const uint8 *str, uint len)
{
- return (uint) (X >= '0' && X <= '9' ? X-'0' :
- X >= 'A' && X <= 'Z' ? X-'A'+10 :
- X-'a'+10);
+ const uint8 *str_end= str + len;
+ for (; str != str_end; ++str)
+ {
+ *to++= _dig_vec[(*str & 0xF0) >> 4];
+ *to++= _dig_vec[*str & 0x0F];
+ }
+ *to= '\0';
}
/*
- Get Binary salt from password as in mysql.user format
-
+ Convert given asciiz string of hex (0..9 a..f) characters to octet
+ sequence.
SYNOPSIS
- get_salt_from_password()
- res OUT Store binary salt here
- password IN Password string as stored in mysql.user
-
- RETURN
- none
-
- NOTE
- This function does not have length check for passwords. It will just crash
- Password hashes in old format must have length divisible by 8
-*/
-
-void get_salt_from_password(ulong *res,const char *password)
+ hex2octet()
+ to OUT buffer to place result; must be at least len/2 bytes
+ str, len IN begin, length for character string; str and to may not
+ overlap; len % 2 == 0
+*/
+
+static void
+hex2octet(uint8 *to, const char *str, uint len)
{
- if (password) /* zero salt corresponds to empty password */
+ const char *str_end= str + len;
+ while (str < str_end)
{
- if (password[0]==PVERSION41_CHAR) /* if new password */
- {
- uint val=0;
- uint i;
- password++; /* skip version identifier */
-
- /*get hashing salt from password and store in in the start of array */
- for (i=0 ; i < 4 ; i++)
- val=(val << 4)+char_val(*password++);
- *res++=val;
- }
- /* We process old passwords the same way as new ones in other case */
-#ifdef EXTRA_DEBUG
- if (strlen(password)%8!=0)
- fprintf(stderr,"Warning: Incorrect password length for salting: %d\n",
- strlen(password));
-#endif
- while (*password)
- {
- ulong val=0;
- uint i;
- for (i=0 ; i < 8 ; i++)
- val=(val << 4)+char_val(*password++);
- *res++=val;
- }
+ register char tmp= char_val(*str++);
+ *to++= (tmp << 4) | char_val(*str++);
}
- return;
}
/*
- Get string version as stored in mysql.user from salt form
-
+ Encrypt/Decrypt function used for password encryption in authentication.
+ Simple XOR is used here but it is OK as we crypt random strings. Note,
+ that XOR(s1, XOR(s1, s2)) == s2, XOR(s1, s2) == XOR(s2, s1)
SYNOPSIS
- make_password_from_salt()
- to OUT Store resulting string password here
- hash_res IN Password in salt format
- password_version
- IN According to which version salt should be treated
-
- RETURN
- none
+ my_crypt()
+ to OUT buffer to hold crypted string; must be at least len bytes
+ long; to and s1 (or s2) may be the same.
+ s1, s2 IN input strings (of equal length)
+ len IN length of s1 and s2
*/
-void make_password_from_salt(char *to, ulong *hash_res,uint8 password_version)
+static void
+my_crypt(char *to, const uchar *s1, const uchar *s2, uint len)
{
- if (!password_version) /* Handling of old passwords. */
- sprintf(to,"%08lx%08lx",hash_res[0],hash_res[1]);
- else
- if (password_version==PVERSION41_CHAR)
- sprintf(to,"%c%04x%08lx%08lx%08lx%08lx%08lx",PVERSION41_CHAR,(unsigned short)hash_res[0],hash_res[1],
- hash_res[2],hash_res[3],hash_res[4],hash_res[5]);
- else /* Just use empty password if we can't handle it. This should not happen */
- to[0]='\0';
+ const uint8 *s1_end= s1 + len;
+ while (s1 < s1_end)
+ *to++= *s1++ ^ *s2++;
}
/*
- Convert password in salted form to binary string password and hash-salt
- For old password this involes one more hashing
-
+ MySQL 4.1.1 password hashing: SHA conversion (see RFC 2289, 3174) twice
+ applied to the password string, and then produced octet sequence is
+ converted to hex string.
+ The result of this function is used as return value from PASSWORD() and
+ is stored in the database.
SYNOPSIS
- get_hash_and_password()
- salt IN Salt to convert from
- pversion IN Password version to use
- hash OUT Store zero ended hash here
- bin_password OUT Store binary password here (no zero at the end)
-
- RETURN
- 0 for pre 4.1 passwords
- !0 password version char for newer passwords
+ make_scrambled_password()
+ buf OUT buffer of size 2*SHA1_HASH_SIZE + 2 to store hex string
+ password IN NULL-terminated password string
*/
-void get_hash_and_password(ulong *salt, uint8 pversion, char *hash,
- unsigned char *bin_password)
+void
+make_scrambled_password(char *to, const char *password)
{
- int t;
- ulong* salt_end;
- ulong val;
- SHA1_CONTEXT context;
-
- if (pversion) /* New password version assumed */
- {
- salt_end=salt+5;
- sprintf(hash,"%04x",(unsigned short)salt[0]);
- while (salt<salt_end)
- {
- val=*(++salt);
- for (t=3; t>=0; t--)
- {
- bin_password[t]= (char) (val & 255);
- val>>=8; /* Scroll 8 bits to get next part*/
- }
- bin_password+=4; /* Get to next 4 chars*/
- }
- }
- else
- {
- unsigned char *bp= bin_password; /* Binary password loop pointer */
-
- /* Use zero starting hash as an indication of old password */
- hash[0]=0;
- salt_end=salt+2;
- /* Encode salt using SHA1 here */
- sha1_reset(&context);
- while (salt<salt_end) /* Iterate over these elements*/
- {
- val= *salt;
- for (t=3;t>=0;t--)
- {
- bp[t]= (uchar) (val & 255);
- val>>=8; /* Scroll 8 bits to get next part*/
- }
- bp+= 4; /* Get to next 4 chars*/
- salt++;
- }
- /* Use 8 bytes of binary password for hash */
- sha1_input(&context,(uint8*)bin_password,8);
- sha1_result(&context,(uint8*)bin_password);
- }
+ SHA1_CONTEXT sha1_context;
+ uint8 hash_stage2[SHA1_HASH_SIZE];
+
+ sha1_reset(&sha1_context);
+ /* stage 1: hash password */
+ sha1_input(&sha1_context, (uint8 *) password, strlen(password));
+ sha1_result(&sha1_context, (uint8 *) to);
+ /* stage 2: hash stage1 output */
+ sha1_reset(&sha1_context);
+ sha1_input(&sha1_context, (uint8 *) to, SHA1_HASH_SIZE);
+ /* separate buffer is used to pass 'to' in octet2hex */
+ sha1_result(&sha1_context, hash_stage2);
+ /* convert hash_stage2 to hex string */
+ *to++= PVERSION41_CHAR;
+ octet2hex(to, hash_stage2, SHA1_HASH_SIZE);
}
-
+
/*
- Create key from old password to decode scramble
- Used in 4.1 authentication with passwords stored old way
-
+ Produce an obscure octet sequence from password and random
+ string, recieved from the server. This sequence corresponds to the
+ password, but password can not be easily restored from it. The sequence
+ is then sent to the server for validation. Trailing zero is not stored
+ in the buf as it is not needed.
+ This function is used by client to create authenticated reply to the
+ server's greeting.
SYNOPSIS
- create_key_from_old_password()
- passwd IN Password used for key generation
- key OUT Created 20 bytes key
-
- RETURN
- None
+ scramble()
+ buf OUT store scrambled string here. The buf must be at least
+ SHA1_HASH_SIZE bytes long.
+ message IN random message, must be exactly SCRAMBLE_LENGTH long and
+ NULL-terminated.
+ password IN users' password
*/
-
-void create_key_from_old_password(const char *passwd, char *key)
+void
+scramble(char *to, const char *message, const char *password)
{
- char buffer[SCRAMBLE41_LENGTH]; /* Buffer for various needs */
- ulong salt[6]; /* Salt (large for safety) */
- /* At first hash password to the string stored in password */
- make_scrambled_password(buffer,passwd,1,(struct rand_struct *)NULL);
- /* Now convert it to the salt form */
- get_salt_from_password(salt,buffer);
- /* Finally get hash and bin password from salt */
- get_hash_and_password(salt,0,buffer,(unsigned char*) key);
+ SHA1_CONTEXT sha1_context;
+ uint8 hash_stage1[SHA1_HASH_SIZE];
+ uint8 hash_stage2[SHA1_HASH_SIZE];
+
+ sha1_reset(&sha1_context);
+ /* stage 1: hash password */
+ sha1_input(&sha1_context, (uint8 *) password, strlen(password));
+ sha1_result(&sha1_context, hash_stage1);
+ /* stage 2: hash stage 1; note that hash_stage2 is stored in the database */
+ sha1_reset(&sha1_context);
+ sha1_input(&sha1_context, hash_stage1, SHA1_HASH_SIZE);
+ sha1_result(&sha1_context, hash_stage2);
+ /* create crypt string as sha1(message, hash_stage2) */;
+ sha1_reset(&sha1_context);
+ sha1_input(&sha1_context, (const uint8 *) message, SCRAMBLE_LENGTH);
+ sha1_input(&sha1_context, hash_stage2, SHA1_HASH_SIZE);
+ /* xor allows 'from' and 'to' overlap: lets take advantage of it */
+ sha1_result(&sha1_context, (uint8 *) to);
+ my_crypt(to, (const uchar *) to, hash_stage1, SCRAMBLE_LENGTH);
}
/*
- Scramble string with password
- Used at pre 4.1 authentication phase.
-
+ Check that scrambled message corresponds to the password; the function
+ is used by server to check that recieved reply is authentic.
+ This function does not check lengths of given strings: message must be
+ null-terminated, reply and hash_stage2 must be at least SHA1_HASH_SIZE
+ long (if not, something fishy is going on).
SYNOPSIS
- scramble()
- to OUT Store scrambled message here
- message IN Message to scramble
- password IN Password to use while scrambling
- old_ver IN Forse old version random number generator
-
- RETURN
- End of scrambled string
+ check_scramble()
+ scramble clients' reply, presumably produced by scramble()
+ message original random string, previously sent to client
+ (presumably second argument of scramble()), must be
+ exactly SCRAMBLE_LENGTH long and NULL-terminated.
+ hash_stage2 hex2octet-decoded database entry
+ All params are IN.
+
+ RETURN VALUE
+ 0 password is correct
+ !0 password is invalid
*/
-char *scramble(char *to,const char *message,const char *password,
- my_bool old_ver)
+my_bool
+check_scramble(const char *scramble, const char *message,
+ const uint8 *hash_stage2)
{
- struct rand_struct rand_st;
- ulong hash_pass[2],hash_message[2];
- char message_buffer[9]; /* Real message buffer */
- char *msg=message_buffer;
-
- /* We use special message buffer now as new server can provide longer hash */
-
- memcpy(message_buffer,message,8);
- message_buffer[8]=0;
-
- if (password && password[0])
- {
- char *to_start=to;
- hash_password(hash_pass,password);
- hash_password(hash_message,message_buffer);
- if (old_ver)
- old_randominit(&rand_st,hash_pass[0] ^ hash_message[0]);
- else
- randominit(&rand_st,hash_pass[0] ^ hash_message[0],
- hash_pass[1] ^ hash_message[1]);
- while (*msg++)
- *to++= (char) (floor(my_rnd(&rand_st)*31)+64);
- if (!old_ver)
- { /* Make it harder to break */
- char extra=(char) (floor(my_rnd(&rand_st)*31));
- while (to_start != to)
- *(to_start++)^=extra;
- }
- }
- *to=0;
- return to;
+ SHA1_CONTEXT sha1_context;
+ uint8 buf[SHA1_HASH_SIZE];
+ uint8 hash_stage2_reassured[SHA1_HASH_SIZE];
+
+ sha1_reset(&sha1_context);
+ /* create key to encrypt scramble */
+ sha1_input(&sha1_context, (const uint8 *) message, SCRAMBLE_LENGTH);
+ sha1_input(&sha1_context, hash_stage2, SHA1_HASH_SIZE);
+ sha1_result(&sha1_context, buf);
+ /* encrypt scramble */
+ my_crypt((char *) buf, buf, (const uchar *) scramble, SCRAMBLE_LENGTH);
+ /* now buf supposedly contains hash_stage1: so we can get hash_stage2 */
+ sha1_reset(&sha1_context);
+ sha1_input(&sha1_context, buf, SHA1_HASH_SIZE);
+ sha1_result(&sha1_context, hash_stage2_reassured);
+ return memcmp(hash_stage2, hash_stage2_reassured, SHA1_HASH_SIZE);
}
/*
- Check scrambled message
- Used for pre 4.1 password handling
+ Convert scrambled password from asciiz hex string to binary form.
+ SYNOPSIS
+ get_salt_from_password()
+ res OUT buf to hold password. Must be at least SHA1_HASH_SIZE
+ bytes long.
+ password IN 4.1.1 version value of user.password
+*/
+
+void get_salt_from_password(uint8 *hash_stage2, const char *password)
+{
+ hex2octet(hash_stage2, password+1 /* skip '*' */, SHA1_HASH_SIZE * 2);
+}
+/*
+ Convert scrambled password from binary form to asciiz hex string.
SYNOPSIS
- scramble()
- scrambled IN Scrambled message to check
- message IN Original message which was scramble
- hash_pass IN Password which should be used for scrambling
- old_ver IN Forse old version random number generator
-
- RETURN
- 0 Password correct
- !0 Password invalid
+ make_password_from_salt()
+ to OUT store resulting string here, 2*SHA1_HASH_SIZE+2 bytes
+ salt IN password in salt format
*/
-my_bool check_scramble(const char *scrambled, const char *message,
- ulong *hash_pass, my_bool old_ver)
+void make_password_from_salt(char *to, const uint8 *hash_stage2)
{
- struct rand_struct rand_st;
- ulong hash_message[2];
- char buff[16],*to,extra; /* Big enough for check */
- const char *pos;
- char message_buffer[SCRAMBLE_LENGTH+1]; /* Copy of message */
-
- /* We need to copy the message as this function can be called for MySQL 4.1
- scramble which is not zero ended and can have zeroes inside
- We could just write zero to proper place in original message but
- this would make it harder to understand code for next generations
- */
-
- memcpy(message_buffer,message,SCRAMBLE_LENGTH); /* Ignore the rest */
- message_buffer[SCRAMBLE_LENGTH]=0;
-
- /* Check if this exactly N bytes. Overwise this is something fishy */
- if (strlen(message_buffer)!=SCRAMBLE_LENGTH)
- return 1; /* Wrong password */
-
- hash_password(hash_message,message_buffer);
- if (old_ver)
- old_randominit(&rand_st,hash_pass[0] ^ hash_message[0]);
- else
- randominit(&rand_st,hash_pass[0] ^ hash_message[0],
- hash_pass[1] ^ hash_message[1]);
- to=buff;
- for (pos=scrambled ; *pos ; pos++)
- *to++=(char) (floor(my_rnd(&rand_st)*31)+64);
- if (old_ver)
- extra=0;
- else
- extra=(char) (floor(my_rnd(&rand_st)*31));
- to=buff;
- while (*scrambled)
- {
- if (*scrambled++ != (char) (*to++ ^ extra))
- return 1; /* Wrong password */
- }
- return 0;
+ *to++= PVERSION41_CHAR;
+ octet2hex(to, hash_stage2, SHA1_HASH_SIZE);
}
diff --git a/sql/protocol.cc b/sql/protocol.cc
index e90aa7585e2..d1eb3460fc8 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -349,10 +349,35 @@ send_eof(THD *thd, bool no_flush)
}
DBUG_VOID_RETURN;
}
+
+/*
+ Please client to send scrambled_password in old format.
+ SYNOPSYS
+ send_old_password_request()
+ thd thread handle
+
+ RETURN VALUE
+ 0 ok
+ !0 error
+*/
+
+bool send_old_password_request(THD *thd)
+{
+ static char buff[1]= { (char) 254 };
+ NET *net= &thd->net;
+ return my_net_write(net, buff, 1) || net_flush(net);
+}
+
#endif /* EMBEDDED_LIBRARY */
/*
- Faster net_store_length when we know length is a 32 bit integer
+ Faster net_store_length when we know that length is less than 65536.
+ We keep a separate version for that range because it's widely used in
+ libmysql.
+ uint is used as agrument type because of MySQL type conventions:
+ uint for 0..65536
+ ulong for 0..4294967296
+ ulonglong for bigger numbers.
*/
char *net_store_length(char *pkg, uint length)
diff --git a/sql/protocol.h b/sql/protocol.h
index 05aee12d3d9..f32c135ab3c 100644
--- a/sql/protocol.h
+++ b/sql/protocol.h
@@ -164,6 +164,7 @@ void net_printf(THD *thd,uint sql_errno, ...);
void send_ok(THD *thd, ha_rows affected_rows=0L, ulonglong id=0L,
const char *info=0);
void send_eof(THD *thd, bool no_flush=0);
+bool send_old_password_request(THD *thd);
char *net_store_length(char *packet,ulonglong length);
char *net_store_length(char *packet,uint length);
char *net_store_data(char *to,const char *from, uint length);
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index e9c3b1ed0b0..d9c09c88f0d 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -670,6 +670,17 @@ int connect_to_master(THD *thd, MYSQL* mysql, MASTER_INFO* mi)
}
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *) &slave_net_timeout);
mysql_options(mysql, MYSQL_OPT_READ_TIMEOUT, (char *) &slave_net_timeout);
+
+#ifdef HAVE_OPENSSL
+ if (mi->ssl)
+ mysql_ssl_set(mysql,
+ mi->ssl_key[0]?mi->ssl_key:0,
+ mi->ssl_cert[0]?mi->ssl_cert:0,
+ mi->ssl_ca[0]?mi->ssl_ca:0,
+ mi->ssl_capath[0]?mi->ssl_capath:0,
+ mi->ssl_cipher[0]?mi->ssl_cipher:0);
+#endif
+
mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset_info->csname);
mysql_options(mysql, MYSQL_SET_CHARSET_DIR, (char *) charsets_dir);
if (!mysql_real_connect(mysql, mi->host, mi->user, mi->password, 0,
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 91583759c70..d07bcd52559 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -216,6 +216,7 @@ sys_var_thd_ulong sys_net_retry_count("net_retry_count",
&SV::net_retry_count,
fix_net_retry_count);
sys_var_thd_bool sys_new_mode("new", &SV::new_mode);
+sys_var_thd_bool sys_old_passwords("old_passwords", &SV::old_passwords);
sys_var_thd_ulong sys_preload_buff_size("preload_buffer_size",
&SV::preload_buff_size);
sys_var_thd_ulong sys_read_buff_size("read_buffer_size",
@@ -242,6 +243,7 @@ sys_var_thd_enum sys_query_cache_type("query_cache_type",
&SV::query_cache_type,
&query_cache_type_typelib);
#endif /* HAVE_QUERY_CACHE */
+sys_var_bool_ptr sys_secure_auth("secure_auth", &opt_secure_auth);
sys_var_long_ptr sys_server_id("server_id",&server_id);
sys_var_bool_ptr sys_slave_compressed_protocol("slave_compressed_protocol",
&opt_slave_compressed_protocol);
@@ -432,6 +434,7 @@ sys_var *sys_variables[]=
&sys_net_wait_timeout,
&sys_net_write_timeout,
&sys_new_mode,
+ &sys_old_passwords,
&sys_preload_buff_size,
&sys_pseudo_thread_id,
&sys_query_cache_size,
@@ -450,6 +453,7 @@ sys_var *sys_variables[]=
#endif
&sys_rpl_recovery_rank,
&sys_safe_updates,
+ &sys_secure_auth,
&sys_select_limit,
&sys_server_id,
#ifdef HAVE_REPLICATION
@@ -608,6 +612,7 @@ struct show_var_st init_vars[]= {
{sys_net_retry_count.name, (char*) &sys_net_retry_count, SHOW_SYS},
{sys_net_write_timeout.name,(char*) &sys_net_write_timeout, SHOW_SYS},
{sys_new_mode.name, (char*) &sys_new_mode, SHOW_SYS},
+ {sys_old_passwords.name, (char*) &sys_old_passwords, SHOW_SYS},
{"open_files_limit", (char*) &open_files_limit, SHOW_LONG},
{"pid_file", (char*) pidfile_name, SHOW_CHAR},
{"log_error", (char*) log_error_file, SHOW_CHAR},
@@ -628,6 +633,7 @@ struct show_var_st init_vars[]= {
SHOW_SYS},
{sys_query_cache_size.name, (char*) &sys_query_cache_size, SHOW_SYS},
{sys_query_cache_type.name, (char*) &sys_query_cache_type, SHOW_SYS},
+ {"secure_auth", (char*) &sys_secure_auth, SHOW_SYS},
#endif /* HAVE_QUERY_CACHE */
#ifdef HAVE_SMEM
{"shared_memory", (char*) &opt_enable_shared_memory, SHOW_MY_BOOL},
diff --git a/sql/set_var.h b/sql/set_var.h
index f06b5ed22d3..9c9ad071967 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -689,6 +689,9 @@ public:
}
};
+/* updated in sql_acl.cc */
+
+extern sys_var_thd_bool sys_old_passwords;
/* For sql_yacc */
struct sys_var_with_base
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index 2ff51418d14..1450243019f 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -278,4 +278,6 @@ v/*
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt
index cd47f4098e9..014c35e81be 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -272,4 +272,6 @@
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
index 406f2dd1cdd..ff866c284f0 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -280,4 +280,6 @@
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index 5e938074f32..a803f6673f4 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -274,4 +274,6 @@
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index c1d7762fef8..9312dfa9dc2 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -274,4 +274,6 @@
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index 2e52ec04030..f4a29caf000 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -269,4 +269,6 @@
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index 6910894b095..512f593dc53 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -278,4 +278,6 @@
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index f52987e56cf..47ee14cf592 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -269,4 +269,6 @@
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index 3fbec6f9fc7..e8e8cf6e1e3 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -271,4 +271,6 @@
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index 7ad72412035..c6b2b829fdd 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -269,4 +269,6 @@
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index 9609fa8d8a4..1f134b6e9ba 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -271,4 +271,6 @@
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index aeb62784594..08f635c8f20 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -269,4 +269,6 @@
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index a79d20cc20e..9089985b262 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -271,4 +271,6 @@
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index b018313ea39..4e08813a5ac 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -271,4 +271,6 @@
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt
index 5fcdb6d84c2..b767125f73d 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -273,4 +273,6 @@
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt
index ea639e1f8cd..95e388c2245 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -269,4 +269,6 @@
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index 49c64272dd8..0f53d2a2010 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -273,4 +273,6 @@
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
index b711d107c23..0fb0646f040 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -271,4 +271,6 @@
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
+"óÅÒ×ÅÒ ÚÁÐÕÝÅÎ × ÒÅÖÉÍÅ --secure-auth (ÂÅÚÏÐÁÓÎÏÊ Á×ÔÏÒÉÚÁÃÉÉ), ÎÏ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÑ '%s@%s' ÐÁÒÏÌØ ÓÏÈÒÁÎ£Î × ÓÔÁÒÏÍ ÆÏÒÍÁÔÅ; ÎÅÏÂÈÏÄÉÍÏ ÏÂÎÏ×ÉÔØ ÆÏÒÍÁÔ ÐÁÒÏÌÑ"
"ðÏÌÅ ÉÌÉ ÓÓÙÌËÁ '%-.64s%s%-.64s%s%-.64s' ÉÚ SELECTÁ #%d ÂÙÌÁ ÎÁÊÄÅÎÁ × SELECTÅ #%d",
diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt
index 0129cd0d643..c8420110ee8 100644
--- a/sql/share/serbian/errmsg.txt
+++ b/sql/share/serbian/errmsg.txt
@@ -264,4 +264,6 @@
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index ac8e7a5c7eb..6370d148ae2 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -277,4 +277,6 @@
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt
index 86a3ab090a2..6cb031c46e3 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -270,4 +270,6 @@
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt
index 0add28faab1..a36e0f9731f 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -269,4 +269,6 @@
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt
index 99d3f9c6a52..2865edf9175 100644
--- a/sql/share/ukrainian/errmsg.txt
+++ b/sql/share/ukrainian/errmsg.txt
@@ -274,4 +274,6 @@
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
"óÔÏ×ÂÅÃØ ÁÂÏ ÐÏÓÉÌÁÎÎÑ '%-.64s%s%-.64s%s%-.64s' ¦Ú SELECTÕ #%d ÂÕÌÏ ÚÎÁÊÄÅÎÅ Õ SELECT¦ #%d",
diff --git a/sql/slave.cc b/sql/slave.cc
index d45cf1aa8b9..dd25fe5e75e 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -1554,9 +1554,21 @@ void init_master_info_with_options(MASTER_INFO* mi)
if (master_user)
strmake(mi->user, master_user, sizeof(mi->user) - 1);
if (master_password)
- strmake(mi->password, master_password, HASH_PASSWORD_LENGTH);
+ strmake(mi->password, master_password, MAX_PASSWORD_LENGTH);
mi->port = master_port;
mi->connect_retry = master_connect_retry;
+
+ mi->ssl= master_ssl;
+ if (master_ssl_ca)
+ strmake(mi->ssl_ca, master_ssl_ca, sizeof(mi->ssl_ca)-1);
+ if (master_ssl_capath)
+ strmake(mi->ssl_capath, master_ssl_capath, sizeof(mi->ssl_capath)-1);
+ if (master_ssl_cert)
+ strmake(mi->ssl_cert, master_ssl_cert, sizeof(mi->ssl_cert)-1);
+ if (master_ssl_cipher)
+ strmake(mi->ssl_cipher, master_ssl_cipher, sizeof(mi->ssl_cipher)-1);
+ if (master_ssl_key)
+ strmake(mi->ssl_key, master_ssl_key, sizeof(mi->ssl_key)-1);
}
void clear_last_slave_error(RELAY_LOG_INFO* rli)
@@ -1566,6 +1578,10 @@ void clear_last_slave_error(RELAY_LOG_INFO* rli)
rli->last_slave_errno=0;
}
+
+#define LINES_IN_MASTER_INFO_WITH_SSL 14
+
+
int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
const char* slave_info_fname,
bool abort_if_no_master_info_file)
@@ -1643,25 +1659,87 @@ file '%s')", fname);
}
mi->fd = fd;
- int port, connect_retry, master_log_pos;
-
+ int port, connect_retry, master_log_pos, ssl= 0, lines;
+ char *first_non_digit;
+
+ /*
+ Starting from 4.1.x master.info has new format. Now its
+ first line contains number of lines in file. By reading this
+ number we will be always distinguish to which version our
+ master.info corresponds to. We can't simply count lines in
+ file since versions before 4.1.x could generate files with more
+ lines than needed.
+ If first line doesn't contain a number or contain number less than
+ 14 then such file is treated like file from pre 4.1.1 version.
+ There is no ambiguity when reading an old master.info, as before
+ 4.1.1, the first line contained the binlog's name, which is either
+ empty or has an extension (contains a '.'), so can't be confused
+ with an integer.
+
+ So we're just reading first line and trying to figure which version
+ is this.
+ */
+
+ /*
+ The first row is temporarily stored in mi->master_log_name,
+ if it is line count and not binlog name (new format) it will be
+ overwritten by the second row later.
+ */
if (init_strvar_from_file(mi->master_log_name,
sizeof(mi->master_log_name), &mi->file,
- "") ||
- init_intvar_from_file(&master_log_pos, &mi->file, 4) ||
+ ""))
+ goto errwithmsg;
+
+ lines= strtoul(mi->master_log_name, &first_non_digit, 10);
+
+ if (mi->master_log_name[0]!='\0' &&
+ *first_non_digit=='\0' && lines >= LINES_IN_MASTER_INFO_WITH_SSL)
+ { // Seems to be new format
+ if (init_strvar_from_file(mi->master_log_name,
+ sizeof(mi->master_log_name), &mi->file, ""))
+ goto errwithmsg;
+ }
+ else
+ lines= 7;
+
+ if (init_intvar_from_file(&master_log_pos, &mi->file, 4) ||
init_strvar_from_file(mi->host, sizeof(mi->host), &mi->file,
master_host) ||
init_strvar_from_file(mi->user, sizeof(mi->user), &mi->file,
master_user) ||
- init_strvar_from_file(mi->password, HASH_PASSWORD_LENGTH+1, &mi->file,
- master_password) ||
+ init_strvar_from_file(mi->password, SCRAMBLED_PASSWORD_CHAR_LENGTH+1,
+ &mi->file, master_password) ||
init_intvar_from_file(&port, &mi->file, master_port) ||
init_intvar_from_file(&connect_retry, &mi->file,
master_connect_retry))
- {
- sql_print_error("Error reading master configuration");
- goto err;
- }
+ goto errwithmsg;
+
+ /*
+ If file has ssl part use it even if we have server without
+ SSL support. But these option will be ignored later when
+ slave will try connect to master, so in this case warning
+ is printed.
+ */
+ if (lines >= LINES_IN_MASTER_INFO_WITH_SSL &&
+ (init_intvar_from_file(&ssl, &mi->file, master_ssl) ||
+ init_strvar_from_file(mi->ssl_ca, sizeof(mi->ssl_ca),
+ &mi->file, master_ssl_ca) ||
+ init_strvar_from_file(mi->ssl_capath, sizeof(mi->ssl_capath),
+ &mi->file, master_ssl_capath) ||
+ init_strvar_from_file(mi->ssl_cert, sizeof(mi->ssl_cert),
+ &mi->file, master_ssl_cert) ||
+ init_strvar_from_file(mi->ssl_cipher, sizeof(mi->ssl_cipher),
+ &mi->file, master_ssl_cipher) ||
+ init_strvar_from_file(mi->ssl_key, sizeof(mi->ssl_key),
+ &mi->file, master_ssl_key)))
+ goto errwithmsg;
+#ifndef HAVE_OPENSSL
+ if (ssl)
+ sql_print_error("SSL information in the master info file "
+ "('%s') are ignored because this MySQL slave was compiled "
+ "without SSL support.", fname);
+#endif /* HAVE_OPENSSL */
+
/*
This has to be handled here as init_intvar_from_file can't handle
my_off_t types
@@ -1669,6 +1747,7 @@ file '%s')", fname);
mi->master_log_pos= (my_off_t) master_log_pos;
mi->port= (uint) port;
mi->connect_retry= (uint) connect_retry;
+ mi->ssl= (my_bool) ssl;
}
DBUG_PRINT("master_info",("log_file_name: %s position: %ld",
mi->master_log_name,
@@ -1685,7 +1764,10 @@ file '%s')", fname);
sql_print_error("Failed to flush master info file");
pthread_mutex_unlock(&mi->data_lock);
DBUG_RETURN(error);
-
+
+errwithmsg:
+ sql_print_error("Error reading master configuration");
+
err:
if (fd >= 0)
{
@@ -1820,6 +1902,18 @@ int show_master_info(THD* thd, MASTER_INFO* mi)
MYSQL_TYPE_LONGLONG));
field_list.push_back(new Item_return_int("Relay_log_space", 10,
MYSQL_TYPE_LONGLONG));
+ field_list.push_back(new Item_empty_string("Master_SSL_Allowed", 7));
+ field_list.push_back(new Item_empty_string("Master_SSL_CA_File",
+ sizeof(mi->ssl_ca)));
+ field_list.push_back(new Item_empty_string("Master_SSL_CA_Path",
+ sizeof(mi->ssl_capath)));
+ field_list.push_back(new Item_empty_string("Master_SSL_Cert",
+ sizeof(mi->ssl_cert)));
+ field_list.push_back(new Item_empty_string("Master_SSL_Cipher",
+ sizeof(mi->ssl_cipher)));
+ field_list.push_back(new Item_empty_string("Master_SSL_Key",
+ sizeof(mi->ssl_key)));
+
if (protocol->send_fields(&field_list, 1))
DBUG_RETURN(-1);
@@ -1868,6 +1962,17 @@ int show_master_info(THD* thd, MASTER_INFO* mi)
protocol->store((uint32) mi->rli.slave_skip_counter);
protocol->store((ulonglong) mi->rli.group_master_log_pos);
protocol->store((ulonglong) mi->rli.log_space_total);
+#ifdef HAVE_OPENSSL
+ protocol->store(mi->ssl? "Yes":"No", &my_charset_bin);
+#else
+ protocol->store(mi->ssl? "Ignored":"No", &my_charset_bin);
+#endif
+ protocol->store(mi->ssl_ca, &my_charset_bin);
+ protocol->store(mi->ssl_capath, &my_charset_bin);
+ protocol->store(mi->ssl_cert, &my_charset_bin);
+ protocol->store(mi->ssl_cipher, &my_charset_bin);
+ protocol->store(mi->ssl_key, &my_charset_bin);
+
pthread_mutex_unlock(&mi->rli.data_lock);
pthread_mutex_unlock(&mi->data_lock);
@@ -1886,11 +1991,22 @@ bool flush_master_info(MASTER_INFO* mi)
DBUG_ENTER("flush_master_info");
DBUG_PRINT("enter",("master_pos: %ld", (long) mi->master_log_pos));
+ /*
+ In certain cases this code may create master.info files that seems
+ corrupted, because of extra lines filled with garbage in the end
+ file (this happens if new contents take less space than previous
+ contents of file). But because of number of lines in the first line
+ of file we don't care about this garbage.
+ */
+
my_b_seek(file, 0L);
- my_b_printf(file, "%s\n%s\n%s\n%s\n%s\n%d\n%d\n",
- mi->master_log_name, llstr(mi->master_log_pos, lbuf),
+ my_b_printf(file, "%u\n%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n%s\n%s\n%s\n%s\n%s\n",
+ LINES_IN_MASTER_INFO_WITH_SSL,
+ mi->master_log_name, llstr(mi->master_log_pos, lbuf),
mi->host, mi->user,
- mi->password, mi->port, mi->connect_retry);
+ mi->password, mi->port, mi->connect_retry,
+ (int)(mi->ssl), mi->ssl_ca, mi->ssl_capath, mi->ssl_cert,
+ mi->ssl_cipher, mi->ssl_key);
flush_io_cache(file);
DBUG_RETURN(0);
}
@@ -2303,9 +2419,10 @@ server_errno=%d)",
return packet_error;
}
- if (len == 1)
+ /* Check if eof packet */
+ if (len < 8 && mysql->net.read_pos[0] == 254)
{
- sql_print_error("Slave: received 0 length packet from server, apparent\
+ sql_print_error("Slave: received end packet from server, apparent\
master shutdown: %s",
mysql_error(mysql));
return packet_error;
@@ -3273,6 +3390,17 @@ static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi,
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *) &slave_net_timeout);
mysql_options(mysql, MYSQL_OPT_READ_TIMEOUT, (char *) &slave_net_timeout);
+
+#ifdef HAVE_OPENSSL
+ if (mi->ssl)
+ mysql_ssl_set(mysql,
+ mi->ssl_key[0]?mi->ssl_key:0,
+ mi->ssl_cert[0]?mi->ssl_cert:0,
+ mi->ssl_ca[0]?mi->ssl_ca:0,
+ mi->ssl_capath[0]?mi->ssl_capath:0,
+ mi->ssl_cipher[0]?mi->ssl_cipher:0);
+#endif
+
mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset_info->csname);
/* This one is not strictly needed but we have it here for completeness */
mysql_options(mysql, MYSQL_SET_CHARSET_DIR, (char *) charsets_dir);
diff --git a/sql/slave.h b/sql/slave.h
index 0cd291a50f8..f7d288ca64e 100644
--- a/sql/slave.h
+++ b/sql/slave.h
@@ -288,16 +288,19 @@ Log_event* next_event(RELAY_LOG_INFO* rli);
typedef struct st_master_info
{
+ /* the variables below are needed because we can change masters on the fly */
char master_log_name[FN_REFLEN];
char host[HOSTNAME_LENGTH+1];
char user[USERNAME_LENGTH+1];
char password[MAX_PASSWORD_LENGTH+1];
+ my_bool ssl; // enables use of SSL connection if true
+ char ssl_ca[FN_REFLEN], ssl_capath[FN_REFLEN], ssl_cert[FN_REFLEN];
+ char ssl_cipher[FN_REFLEN], ssl_key[FN_REFLEN];
my_off_t master_log_pos;
File fd; // we keep the file open, so we need to remember the file pointer
IO_CACHE file;
- /* the variables below are needed because we can change masters on the fly */
pthread_mutex_t data_lock,run_lock;
pthread_cond_t data_cond,start_cond,stop_cond;
THD *io_thd;
@@ -315,10 +318,13 @@ typedef struct st_master_info
volatile ulong slave_run_id;
st_master_info()
- :fd(-1), io_thd(0), inited(0), old_format(BINLOG_FORMAT_CURRENT),
+ :ssl(0), fd(-1), io_thd(0), inited(0), old_format(BINLOG_FORMAT_CURRENT),
abort_slave(0),slave_running(0), slave_run_id(0)
{
host[0] = 0; user[0] = 0; password[0] = 0;
+ ssl_ca[0]= 0; ssl_capath[0]= 0; ssl_cert[0]= 0;
+ ssl_cipher[0]= 0; ssl_key[0]= 0;
+
bzero((char*) &file, sizeof(file));
pthread_mutex_init(&run_lock, MY_MUTEX_INIT_FAST);
pthread_mutex_init(&data_lock, MY_MUTEX_INIT_FAST);
@@ -468,6 +474,10 @@ extern my_string master_user, master_password, master_host,
master_info_file, relay_log_info_file, report_user, report_host,
report_password;
+extern my_bool master_ssl;
+extern my_string master_ssl_ca, master_ssl_capath, master_ssl_cert,
+ master_ssl_cipher, master_ssl_key;
+
extern I_List<i_string> replicate_do_db, replicate_ignore_db;
extern I_List<i_string_pair> replicate_rewrite_db;
extern I_List<THD> threads;
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 9738c0c5d9e..a7fe77f6b06 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -51,7 +51,7 @@ static byte* acl_entry_get_key(acl_entry *entry,uint *length,
return (byte*) entry->key;
}
-#define ACL_KEY_LENGTH (sizeof(long)+NAME_LEN+17)
+#define ACL_KEY_LENGTH (sizeof(long)+NAME_LEN+USERNAME_LENGTH+1)
static DYNAMIC_ARRAY acl_hosts,acl_users,acl_dbs;
static MEM_ROOT mem, memex;
@@ -68,12 +68,54 @@ static ulong get_sort(uint count,...);
static void init_check_host(void);
static ACL_USER *find_acl_user(const char *host, const char *user);
static bool update_user_table(THD *thd, const char *host, const char *user,
- const char *new_password);
+ const char *new_password, uint new_password_len);
static void update_hostname(acl_host_and_ip *host, const char *hostname);
static bool compare_hostname(const acl_host_and_ip *host,const char *hostname,
const char *ip);
/*
+ Convert scrambled password to binary form, according to scramble type,
+ Binary form is stored in user.salt.
+*/
+
+static
+void
+set_user_salt(ACL_USER *acl_user, const char *password, uint password_len)
+{
+ if (password_len == SCRAMBLED_PASSWORD_CHAR_LENGTH)
+ {
+ get_salt_from_password(acl_user->salt, password);
+ acl_user->salt_len= SCRAMBLE_LENGTH;
+ }
+ else if (password_len == SCRAMBLED_PASSWORD_CHAR_LENGTH_323)
+ {
+ get_salt_from_password_323((ulong *) acl_user->salt, password);
+ acl_user->salt_len= SCRAMBLE_LENGTH_323;
+ }
+ else
+ acl_user->salt_len= 0;
+}
+
+/*
+ This after_update function is used when user.password is less than
+ SCRAMBLE_LENGTH bytes.
+*/
+
+static void restrict_update_of_old_passwords_var(THD *thd,
+ enum_var_type var_type)
+{
+ if (var_type == OPT_GLOBAL)
+ {
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ global_system_variables.old_passwords= 1;
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ }
+ else
+ thd->variables.old_passwords= 1;
+}
+
+
+/*
Read grant privileges from the privilege tables in the 'mysql' database.
SYNOPSIS
@@ -114,8 +156,6 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
if (!(thd=new THD))
DBUG_RETURN(1); /* purecov: inspected */
thd->store_globals();
- /* Use passwords according to command line option */
- use_old_passwords= opt_old_passwords;
acl_cache->clear(1); // Clear locked hostname cache
thd->db= my_strdup("mysql",MYF(0));
@@ -172,103 +212,126 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
init_read_record(&read_record_info,thd,table=tables[1].table,NULL,1,0);
VOID(my_init_dynamic_array(&acl_users,sizeof(ACL_USER),50,100));
- if (table->field[2]->field_length == 8 &&
- protocol_version == PROTOCOL_VERSION)
+ if (table->field[2]->field_length < SCRAMBLED_PASSWORD_CHAR_LENGTH_323)
{
- sql_print_error("Old 'user' table. (Check README or the Reference manual). Continuing --old-protocol"); /* purecov: tested */
- protocol_version=9; /* purecov: tested */
+ sql_print_error("Fatal error: mysql.user table is damaged or in "
+ "unsupported 3.20 format.");
+ goto end;
}
DBUG_PRINT("info",("user table fields: %d, password length: %d",
table->fields, table->field[2]->field_length));
- if (table->field[2]->field_length < 45 && !use_old_passwords)
+
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ if (table->field[2]->field_length < SCRAMBLED_PASSWORD_CHAR_LENGTH)
+ {
+ if (opt_secure_auth)
+ {
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ sql_print_error("Fatal error: mysql.user table is in old format, "
+ "but server started with --secure-auth option.");
+ goto end;
+ }
+ sys_old_passwords.after_update= restrict_update_of_old_passwords_var;
+ if (global_system_variables.old_passwords)
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ else
+ {
+ global_system_variables.old_passwords= 1;
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ sql_print_error("mysql.user table is not updated to new password format; "
+ "Disabling new password usage until "
+ "mysql_fix_privilege_tables is run");
+ }
+ thd->variables.old_passwords= 1;
+ }
+ else
{
- sql_print_error("mysql.user table is not updated to new password format; Disabling new password usage until mysql_fix_privilege_tables is run");
- use_old_passwords= 1;
+ sys_old_passwords.after_update= 0;
+ pthread_mutex_unlock(&LOCK_global_system_variables);
}
allow_all_hosts=0;
while (!(read_record_info.read_record(&read_record_info)))
{
ACL_USER user;
- uint length=0;
- update_hostname(&user.host,get_field(&mem, table->field[0]));
- user.user=get_field(&mem, table->field[1]);
- user.password=get_field(&mem, table->field[2]);
- if (user.password && (length=(uint) strlen(user.password)) == 8 &&
- protocol_version == PROTOCOL_VERSION)
- {
- sql_print_error(
- "Found old style password for user '%s'. Ignoring user. (You may want to restart mysqld using --old-protocol)",
- user.user ? user.user : ""); /* purecov: tested */
- }
- else /* non empty and not short passwords */
- {
- user.pversion=get_password_version(user.password);
- /* Only passwords of specific lengths depending on version are allowed */
- if ((!user.pversion && (length % 8 || length > 16)) ||
- (user.pversion && length != 45))
- {
- sql_print_error(
- "Found invalid password for user: '%s'@'%s'; Ignoring user",
- user.user ? user.user : "",
- user.host.hostname ? user.host.hostname : ""); /* purecov: tested */
- continue; /* purecov: tested */
+ update_hostname(&user.host, get_field(&mem, table->field[0]));
+ user.user= get_field(&mem, table->field[1]);
+ const char *password= get_field(&mem, table->field[2]);
+ uint password_len= password ? strlen(password) : 0;
+ set_user_salt(&user, password, password_len);
+ if (user.salt_len == 0 && password_len != 0)
+ {
+ switch (password_len) {
+ case 45: /* 4.1: to be removed */
+ sql_print_error("Found 4.1 style password for user '%s@%s'. "
+ "Ignoring user. "
+ "You should change password for this user.",
+ user.user ? user.user : "",
+ user.host.hostname ? user.host.hostname : "");
+ break;
+ default:
+ sql_print_error("Found invalid password for user: '%s@%s'; "
+ "Ignoring user", user.user ? user.user : "",
+ user.host.hostname ? user.host.hostname : "");
+ break;
}
}
- get_salt_from_password(user.salt,user.password);
- user.access=get_access(table,3) & GLOBAL_ACLS;
- user.sort=get_sort(2,user.host.hostname,user.user);
- user.hostname_length= (user.host.hostname ?
- (uint) strlen(user.host.hostname) : 0);
- if (table->fields >= 31) /* Starting from 4.0.2 we have more fields */
- {
- char *ssl_type=get_field(&mem, table->field[24]);
- if (!ssl_type)
- user.ssl_type=SSL_TYPE_NONE;
- else if (!strcmp(ssl_type, "ANY"))
- user.ssl_type=SSL_TYPE_ANY;
- else if (!strcmp(ssl_type, "X509"))
- user.ssl_type=SSL_TYPE_X509;
- else /* !strcmp(ssl_type, "SPECIFIED") */
- user.ssl_type=SSL_TYPE_SPECIFIED;
-
- user.ssl_cipher= get_field(&mem, table->field[25]);
- user.x509_issuer= get_field(&mem, table->field[26]);
- user.x509_subject= get_field(&mem, table->field[27]);
-
- char *ptr = get_field(&mem, table->field[28]);
- user.user_resource.questions=atoi(ptr);
- ptr = get_field(&mem, table->field[29]);
- user.user_resource.updates=atoi(ptr);
- ptr = get_field(&mem, table->field[30]);
- user.user_resource.connections=atoi(ptr);
- if (user.user_resource.questions || user.user_resource.updates ||
- user.user_resource.connections)
- mqh_used=1;
- }
- else
+ else // password is correct
{
- user.ssl_type=SSL_TYPE_NONE;
- bzero((char *)&(user.user_resource),sizeof(user.user_resource));
-#ifndef TO_BE_REMOVED
- if (table->fields <= 13)
- { // Without grant
- if (user.access & CREATE_ACL)
- user.access|=REFERENCES_ACL | INDEX_ACL | ALTER_ACL;
+ user.access= get_access(table,3) & GLOBAL_ACLS;
+ user.sort= get_sort(2,user.host.hostname,user.user);
+ user.hostname_length= (user.host.hostname ?
+ (uint) strlen(user.host.hostname) : 0);
+ if (table->fields >= 31) /* Starting from 4.0.2 we have more fields */
+ {
+ char *ssl_type=get_field(&mem, table->field[24]);
+ if (!ssl_type)
+ user.ssl_type=SSL_TYPE_NONE;
+ else if (!strcmp(ssl_type, "ANY"))
+ user.ssl_type=SSL_TYPE_ANY;
+ else if (!strcmp(ssl_type, "X509"))
+ user.ssl_type=SSL_TYPE_X509;
+ else /* !strcmp(ssl_type, "SPECIFIED") */
+ user.ssl_type=SSL_TYPE_SPECIFIED;
+
+ user.ssl_cipher= get_field(&mem, table->field[25]);
+ user.x509_issuer= get_field(&mem, table->field[26]);
+ user.x509_subject= get_field(&mem, table->field[27]);
+
+ char *ptr = get_field(&mem, table->field[28]);
+ user.user_resource.questions=atoi(ptr);
+ ptr = get_field(&mem, table->field[29]);
+ user.user_resource.updates=atoi(ptr);
+ ptr = get_field(&mem, table->field[30]);
+ user.user_resource.connections=atoi(ptr);
+ if (user.user_resource.questions || user.user_resource.updates ||
+ user.user_resource.connections)
+ mqh_used=1;
}
- /* Convert old privileges */
- user.access|= LOCK_TABLES_ACL | CREATE_TMP_ACL | SHOW_DB_ACL;
- if (user.access & FILE_ACL)
- user.access|= REPL_CLIENT_ACL | REPL_SLAVE_ACL;
- if (user.access & PROCESS_ACL)
- user.access|= SUPER_ACL | EXECUTE_ACL;
+ else
+ {
+ user.ssl_type=SSL_TYPE_NONE;
+ bzero((char *)&(user.user_resource),sizeof(user.user_resource));
+#ifndef TO_BE_REMOVED
+ if (table->fields <= 13)
+ { // Without grant
+ if (user.access & CREATE_ACL)
+ user.access|=REFERENCES_ACL | INDEX_ACL | ALTER_ACL;
+ }
+ /* Convert old privileges */
+ user.access|= LOCK_TABLES_ACL | CREATE_TMP_ACL | SHOW_DB_ACL;
+ if (user.access & FILE_ACL)
+ user.access|= REPL_CLIENT_ACL | REPL_SLAVE_ACL;
+ if (user.access & PROCESS_ACL)
+ user.access|= SUPER_ACL | EXECUTE_ACL;
#endif
+ }
+ VOID(push_dynamic(&acl_users,(gptr) &user));
+ if (!user.host.hostname || user.host.hostname[0] == wild_many &&
+ !user.host.hostname[1])
+ allow_all_hosts=1; // Anyone can connect
}
- VOID(push_dynamic(&acl_users,(gptr) &user));
- if (!user.host.hostname || user.host.hostname[0] == wild_many &&
- !user.host.hostname[1])
- allow_all_hosts=1; // Anyone can connect
}
qsort((gptr) dynamic_element(&acl_users,0,ACL_USER*),acl_users.elements,
sizeof(ACL_USER),(qsort_cmp) acl_compare);
@@ -469,135 +532,105 @@ static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b)
/*
- Prepare crypted scramble to be sent to the client
-*/
-
-void prepare_scramble(THD *thd, ACL_USER *acl_user,char* prepared_scramble)
-{
- /* Binary password format to be used for generation*/
- char bin_password[SCRAMBLE41_LENGTH];
- /* Generate new long scramble for the thread */
- create_random_string(SCRAMBLE41_LENGTH,&thd->rand,thd->scramble);
- thd->scramble[SCRAMBLE41_LENGTH]=0;
- /* Get binary form, First 4 bytes of prepared scramble is salt */
- get_hash_and_password(acl_user->salt,acl_user->pversion,prepared_scramble,
- (unsigned char*) bin_password);
- /* Store "*" as identifier for old passwords */
- if (!acl_user->pversion)
- prepared_scramble[0]='*';
- /* Finally encrypt password to get prepared scramble */
- password_crypt(thd->scramble, prepared_scramble+4, bin_password,
- SCRAMBLE41_LENGTH);
-}
+ Seek ACL entry for a user, check password, SSL cypher, and if
+ everything is OK, update THD user data and USER_RESOURCES struct.
+ IMPLEMENTATION
+ This function does not check if the user has any sensible privileges:
+ only user's existence and validity is checked.
+ Note, that entire operation is protected by acl_cache_lock.
-/*
- Get master privilges for user (priviliges for all tables).
- Required before connecting to MySQL
-
- As we have 2 stage handshake now we cache user not to lookup
- it second time. At the second stage we do not lookup user in case
- we already know it;
-
+ SYNOPSIS
+ acl_getroot()
+ thd thread handle. If all checks are OK,
+ thd->priv_user, thd->master_access are updated.
+ thd->host, thd->ip, thd->user are used for checks.
+ mqh user resources; on success mqh is reset, else
+ unchanged
+ passwd scrambled & crypted password, recieved from client
+ (to check): thd->scramble or thd->scramble_323 is
+ used to decrypt passwd, so they must contain
+ original random string,
+ passwd_len length of passwd, must be one of 0, 8,
+ SCRAMBLE_LENGTH_323, SCRAMBLE_LENGTH
+ 'thd' and 'mqh' are updated on success; other params are IN.
+
+ RETURN VALUE
+ 0 success: thd->priv_user, thd->priv_host, thd->master_access, mqh are
+ updated
+ 1 user not found or authentification failure
+ 2 user found, has long (4.1.1) salt, but passwd is in old (3.23) format.
+ -1 user found, has short (3.23) salt, but passwd is in new (4.1.1) format.
*/
-ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
- const char *password,const char *message,char **priv_user,
- char *priv_host, bool old_ver, USER_RESOURCES *mqh,
- char *prepared_scramble, uint *cur_priv_version,
- ACL_USER **cached_user)
+int acl_getroot(THD *thd, USER_RESOURCES *mqh,
+ const char *passwd, uint passwd_len)
{
- ulong user_access=NO_ACCESS;
- *priv_user= (char*) user;
- bool password_correct= 0;
- int stage= (*cached_user != NULL); /* NULL passed as first stage */
- ACL_USER *acl_user= NULL;
DBUG_ENTER("acl_getroot");
- bzero((char*) mqh, sizeof(USER_RESOURCES));
if (!initialized)
{
- // If no data allow anything
- DBUG_RETURN((ulong) ~NO_ACCESS); /* purecov: tested */
+ /*
+ here if mysqld's been started with --skip-grant-tables option.
+ */
+ thd->priv_user= (char *) ""; // privileges for
+ *thd->priv_host= '\0'; // the user are unknown
+ thd->master_access= ~NO_ACCESS; // everything is allowed
+ bzero(mqh, sizeof(*mqh));
+ DBUG_RETURN(0);
}
+
+ int res= 1;
+
VOID(pthread_mutex_lock(&acl_cache->lock));
/*
- Get possible access from user_list. This is or'ed to others not
- fully specified
-
- If we have cached user use it, in other case look it up.
+ Find acl entry in user database. Note, that find_acl_user is not the same,
+ because it doesn't take into account the case when user is not empty,
+ but acl_user->user is empty
*/
- if (stage && (*cur_priv_version == priv_version))
- acl_user= *cached_user;
- else
+ ACL_USER *acl_user= 0;
+ for (uint i=0 ; i < acl_users.elements ; i++)
{
- for (uint i=0 ; i < acl_users.elements ; i++)
+ ACL_USER *user_i = dynamic_element(&acl_users,i,ACL_USER*);
+ if (!user_i->user || !strcmp(thd->user, user_i->user))
{
- ACL_USER *acl_user_search=dynamic_element(&acl_users,i,ACL_USER*);
- if (!acl_user_search->user || !strcmp(user,acl_user_search->user))
+ if (compare_hostname(&user_i->host, thd->host, thd->ip))
{
- if (compare_hostname(&acl_user_search->host,host,ip))
+ /* check password: it should be empty or valid */
+ if (passwd_len == user_i->salt_len)
{
- /* Found mathing user */
- acl_user= acl_user_search;
- /* Store it as a cache */
- *cached_user= acl_user;
- *cur_priv_version= priv_version;
- break;
+ if (user_i->salt_len == 0 ||
+ user_i->salt_len == SCRAMBLE_LENGTH &&
+ check_scramble(passwd, thd->scramble, user_i->salt) == 0 ||
+ check_scramble_323(passwd, thd->scramble,
+ (ulong *) user_i->salt) == 0)
+ {
+ acl_user= user_i;
+ res= 0;
+ }
}
+ else if (passwd_len == SCRAMBLE_LENGTH &&
+ user_i->salt_len == SCRAMBLE_LENGTH_323)
+ res= -1;
+ else if (passwd_len == SCRAMBLE_LENGTH_323 &&
+ user_i->salt_len == SCRAMBLE_LENGTH)
+ res= 2;
+ /* linear search complete: */
+ break;
}
}
}
-
- /* Now we have acl_user found and may start our checks */
+ /*
+ This was moved to separate tree because of heavy HAVE_OPENSSL case.
+ If acl_user is not null, res is 0.
+ */
if (acl_user)
{
- /* Password should present for both or absend for both */
- if (!acl_user->password && !*password)
- password_correct=1;
- else if (!acl_user->password || !*password)
- {
- *cached_user= 0; // Impossible to connect
- }
- else
- {
- /* New version password is checked differently */
- if (acl_user->pversion)
- {
- if (stage) /* We check password only on the second stage */
- {
- if (!validate_password(password,message,acl_user->salt))
- password_correct=1;
- }
- else /* First stage - just prepare scramble */
- prepare_scramble(thd,acl_user,prepared_scramble);
- }
- /* Old way to check password */
- else
- {
- /* Checking the scramble at any stage. First - old clients */
- if (!check_scramble(password,message,acl_user->salt,
- (my_bool) old_ver))
- password_correct=1;
- else if (!stage) /* Here if password incorrect */
- {
- /* At the first stage - prepare scramble */
- prepare_scramble(thd,acl_user,prepared_scramble);
- }
- }
- }
- }
-
- /* If user not found password_correct will also be zero */
- if (!password_correct)
- goto unlock_and_exit;
-
- /* OK. User found and password checked continue validation */
-
- {
+ /* OK. User found and password checked continue validation */
+ thd->master_access= NO_ACCESS;
Vio *vio=thd->net.vio;
/*
At this point we know that user is allowed to connect
@@ -608,32 +641,32 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
switch (acl_user->ssl_type) {
case SSL_TYPE_NOT_SPECIFIED: // Impossible
case SSL_TYPE_NONE: /* SSL is not required to connect */
- user_access=acl_user->access;
+ thd->master_access= acl_user->access;
break;
#ifdef HAVE_OPENSSL
case SSL_TYPE_ANY: /* Any kind of SSL is good enough */
if (vio_type(vio) == VIO_TYPE_SSL)
- user_access=acl_user->access;
+ thd->master_access= acl_user->access;
break;
case SSL_TYPE_X509: /* Client should have any valid certificate. */
/*
- Connections with non-valid certificates are dropped already
- in sslaccept() anyway, so we do not check validity here.
-
- We need to check for absence of SSL because without SSL
- we should reject connection.
+ Connections with non-valid certificates are dropped already
+ in sslaccept() anyway, so we do not check validity here.
+
+ We need to check for absence of SSL because without SSL
+ we should reject connection.
*/
if (vio_type(vio) == VIO_TYPE_SSL &&
SSL_get_verify_result(vio->ssl_) == X509_V_OK &&
SSL_get_peer_certificate(vio->ssl_))
- user_access=acl_user->access;
+ thd->master_access= acl_user->access;
break;
case SSL_TYPE_SPECIFIED: /* Client should have specified attrib */
/*
- We do not check for absence of SSL because without SSL it does
- not pass all checks here anyway.
- If cipher name is specified, we compare it to actual cipher in
- use.
+ We do not check for absence of SSL because without SSL it does
+ not pass all checks here anyway.
+ If cipher name is specified, we compare it to actual cipher in
+ use.
*/
if (vio_type(vio) != VIO_TYPE_SSL ||
SSL_get_verify_result(vio->ssl_) != X509_V_OK)
@@ -643,14 +676,13 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
DBUG_PRINT("info",("comparing ciphers: '%s' and '%s'",
acl_user->ssl_cipher,SSL_get_cipher(vio->ssl_)));
if (!strcmp(acl_user->ssl_cipher,SSL_get_cipher(vio->ssl_)))
- user_access=acl_user->access;
+ thd->master_access= acl_user->access;
else
{
if (global_system_variables.log_warnings)
sql_print_error("X509 ciphers mismatch: should be '%s' but is '%s'",
acl_user->ssl_cipher,
SSL_get_cipher(vio->ssl_));
- user_access=NO_ACCESS;
break;
}
}
@@ -661,64 +693,58 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
/* If X509 issuer is speified, we check it... */
if (acl_user->x509_issuer)
{
- DBUG_PRINT("info",("checkpoint 3"));
+ DBUG_PRINT("info",("checkpoint 3"));
char *ptr = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
DBUG_PRINT("info",("comparing issuers: '%s' and '%s'",
acl_user->x509_issuer, ptr));
- if (strcmp(acl_user->x509_issuer, ptr))
- {
- if (global_system_variables.log_warnings)
- sql_print_error("X509 issuer mismatch: should be '%s' but is '%s'",
- acl_user->x509_issuer, ptr);
- user_access=NO_ACCESS;
- free(ptr);
- break;
- }
- user_access=acl_user->access;
- free(ptr);
+ if (strcmp(acl_user->x509_issuer, ptr))
+ {
+ if (global_system_variables.log_warnings)
+ sql_print_error("X509 issuer mismatch: should be '%s' "
+ "but is '%s'", acl_user->x509_issuer, ptr);
+ free(ptr);
+ break;
+ }
+ thd->master_access= acl_user->access;
+ free(ptr);
}
DBUG_PRINT("info",("checkpoint 4"));
/* X509 subject is specified, we check it .. */
if (acl_user->x509_subject)
{
- char *ptr= X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
- DBUG_PRINT("info",("comparing subjects: '%s' and '%s'",
- acl_user->x509_subject, ptr));
- if (strcmp(acl_user->x509_subject,ptr))
- {
- if (global_system_variables.log_warnings)
- sql_print_error("X509 subject mismatch: '%s' vs '%s'",
- acl_user->x509_subject, ptr);
- user_access=NO_ACCESS;
- }
- else
- user_access=acl_user->access;
- free(ptr);
+ char *ptr= X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
+ DBUG_PRINT("info",("comparing subjects: '%s' and '%s'",
+ acl_user->x509_subject, ptr));
+ if (strcmp(acl_user->x509_subject,ptr))
+ {
+ if (global_system_variables.log_warnings)
+ sql_print_error("X509 subject mismatch: '%s' vs '%s'",
+ acl_user->x509_subject, ptr);
+ }
+ else
+ thd->master_access= acl_user->access;
+ free(ptr);
}
break;
-#else /* HAVE_OPENSSL */
+#else /* HAVE_OPENSSL */
default:
/*
- If we don't have SSL but SSL is required for this user the
- authentication should fail.
- */
+ If we don't have SSL but SSL is required for this user the
+ authentication should fail.
+ */
break;
#endif /* HAVE_OPENSSL */
}
- }
+ thd->priv_user= acl_user->user ? thd->user : (char *) "";
+ *mqh= acl_user->user_resource;
- *mqh=acl_user->user_resource;
- if (!acl_user->user)
- *priv_user=(char*) ""; // Change to anonymous user /* purecov: inspected */
-
- if (acl_user->host.hostname)
- strmake(priv_host, acl_user->host.hostname, MAX_HOSTNAME);
- else
- *priv_host= 0;
-
-unlock_and_exit:
+ if (acl_user->host.hostname)
+ strmake(thd->priv_host, acl_user->host.hostname, MAX_HOSTNAME);
+ else
+ *thd->priv_host= 0;
+ }
VOID(pthread_mutex_unlock(&acl_cache->lock));
- DBUG_RETURN(user_access);
+ DBUG_RETURN(res);
}
@@ -729,8 +755,9 @@ static byte* check_get_key(ACL_USER *buff,uint *length,
return (byte*) buff->host.hostname;
}
+
static void acl_update_user(const char *user, const char *host,
- const char *password,
+ const char *password, uint password_len,
enum SSL_type ssl_type,
const char *ssl_cipher,
const char *x509_issuer,
@@ -766,20 +793,9 @@ static void acl_update_user(const char *user, const char *host,
acl_user->x509_subject= (x509_subject ?
strdup_root(&mem,x509_subject) : 0);
}
- if (password)
- {
- if (!password[0]) /* If password is empty set it to null */
- {
- acl_user->password=0;
- acl_user->pversion=0; // just initialize
- }
- else
- {
- acl_user->password=(char*) ""; // Just point at something
- get_salt_from_password(acl_user->salt,password);
- acl_user->pversion=get_password_version(acl_user->password);
- }
- }
+
+ set_user_salt(acl_user, password, password_len);
+ /* search complete: */
break;
}
}
@@ -788,7 +804,7 @@ static void acl_update_user(const char *user, const char *host,
static void acl_insert_user(const char *user, const char *host,
- const char *password,
+ const char *password, uint password_len,
enum SSL_type ssl_type,
const char *ssl_cipher,
const char *x509_issuer,
@@ -799,7 +815,6 @@ static void acl_insert_user(const char *user, const char *host,
ACL_USER acl_user;
acl_user.user=*user ? strdup_root(&mem,user) : 0;
update_hostname(&acl_user.host,strdup_root(&mem,host));
- acl_user.password=0;
acl_user.access=privileges;
acl_user.user_resource = *mqh;
acl_user.sort=get_sort(2,acl_user.host.hostname,acl_user.user);
@@ -809,12 +824,8 @@ static void acl_insert_user(const char *user, const char *host,
acl_user.ssl_cipher= ssl_cipher ? strdup_root(&mem,ssl_cipher) : 0;
acl_user.x509_issuer= x509_issuer ? strdup_root(&mem,x509_issuer) : 0;
acl_user.x509_subject=x509_subject ? strdup_root(&mem,x509_subject) : 0;
- if (password)
- {
- acl_user.password=(char*) ""; // Just point at something
- get_salt_from_password(acl_user.salt,password);
- acl_user.pversion=get_password_version(password);
- }
+
+ set_user_salt(&acl_user, password, password_len);
VOID(push_dynamic(&acl_users,(gptr) &acl_user));
if (!acl_user.host.hostname || acl_user.host.hostname[0] == wild_many
@@ -1151,7 +1162,6 @@ bool check_change_password(THD *thd, const char *host, const char *user)
bool change_password(THD *thd, const char *host, const char *user,
char *new_password)
{
- uint length=0;
DBUG_ENTER("change_password");
DBUG_PRINT("enter",("host: '%s' user: '%s' new_password: '%s'",
host,user,new_password));
@@ -1160,37 +1170,27 @@ bool change_password(THD *thd, const char *host, const char *user,
if (check_change_password(thd, host, user))
DBUG_RETURN(1);
- /*
- password should always be 0,16 or 45 chars;
- Simple hack to avoid cracking
- */
- length=(uint) strlen(new_password);
- if (length != 45)
- new_password[length & 16]=0;
-
VOID(pthread_mutex_lock(&acl_cache->lock));
ACL_USER *acl_user;
- if (!(acl_user= find_acl_user(host,user)))
+ if (!(acl_user= find_acl_user(host, user)))
{
- send_error(thd, ER_PASSWORD_NO_MATCH);
VOID(pthread_mutex_unlock(&acl_cache->lock));
+ send_error(thd, ER_PASSWORD_NO_MATCH);
DBUG_RETURN(1);
}
+ /* update loaded acl entry: */
+ uint new_password_len= new_password ? strlen(new_password) : 0;
+ set_user_salt(acl_user, new_password, new_password_len);
+
if (update_user_table(thd,
acl_user->host.hostname ? acl_user->host.hostname : "",
acl_user->user ? acl_user->user : "",
- new_password))
+ new_password, new_password_len))
{
VOID(pthread_mutex_unlock(&acl_cache->lock)); /* purecov: deadcode */
send_error(thd,0); /* purecov: deadcode */
DBUG_RETURN(1); /* purecov: deadcode */
}
- get_salt_from_password(acl_user->salt,new_password);
- acl_user->pversion=get_password_version(new_password);
- if (!new_password[0])
- acl_user->password=0;
- else
- acl_user->password=(char*) ""; // Point at something
acl_cache->clear(1); // Clear locked hostname cache
VOID(pthread_mutex_unlock(&acl_cache->lock));
@@ -1230,7 +1230,7 @@ find_acl_user(const char *host, const char *user)
if (!acl_user->user && !user[0] ||
acl_user->user && !strcmp(user,acl_user->user))
{
- if (compare_hostname(&(acl_user->host),host,host))
+ if (compare_hostname(&acl_user->host,host,host))
{
DBUG_RETURN(acl_user);
}
@@ -1303,7 +1303,7 @@ static bool compare_hostname(const acl_host_and_ip *host, const char *hostname,
*/
static bool update_user_table(THD *thd, const char *host, const char *user,
- const char *new_password)
+ const char *new_password, uint new_password_len)
{
TABLE_LIST tables;
TABLE *table;
@@ -1345,7 +1345,7 @@ static bool update_user_table(THD *thd, const char *host, const char *user,
DBUG_RETURN(1); /* purecov: deadcode */
}
store_record(table,record[1]);
- table->field[2]->store(new_password,(uint) strlen(new_password), &my_charset_latin1);
+ table->field[2]->store(new_password, new_password_len, &my_charset_latin1);
if ((error=table->file->update_row(table->record[1],table->record[0])))
{
table->file->print_error(error,MYF(0)); /* purecov: deadcode */
@@ -1393,24 +1393,23 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
{
int error = -1;
bool old_row_exists=0;
- char *password,empty_string[1];
+ const char *password= "";
+ uint password_len= 0;
char what= (revoke_grant) ? 'N' : 'Y';
DBUG_ENTER("replace_user_table");
safe_mutex_assert_owner(&acl_cache->lock);
- password=empty_string;
- empty_string[0]=0;
-
if (combo.password.str && combo.password.str[0])
{
- if ((combo.password.length != HASH_PASSWORD_LENGTH)
- && combo.password.length != HASH_OLD_PASSWORD_LENGTH)
+ if (combo.password.length != SCRAMBLED_PASSWORD_CHAR_LENGTH &&
+ combo.password.length != SCRAMBLED_PASSWORD_CHAR_LENGTH_323)
{
my_printf_error(ER_PASSWORD_NO_MATCH,
- "Password hash should be a %d-digit hexadecimal number",
- MYF(0),HASH_PASSWORD_LENGTH);
+ "Password hash should be a %d-digit hexadecimal number",
+ MYF(0), SCRAMBLED_PASSWORD_CHAR_LENGTH);
DBUG_RETURN(-1);
}
+ password_len= combo.password.length;
password=combo.password.str;
}
@@ -1435,17 +1434,20 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
goto end;
}
old_row_exists = 0;
- restore_record(table,default_values); // cp empty row from default_values
- table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1);
- table->field[1]->store(combo.user.str,combo.user.length, &my_charset_latin1);
- table->field[2]->store(password,(uint) strlen(password), &my_charset_latin1);
+ restore_record(table,default_values); // cp empty row from default_values
+ table->field[0]->store(combo.host.str,combo.host.length,
+ &my_charset_latin1);
+ table->field[1]->store(combo.user.str,combo.user.length,
+ &my_charset_latin1);
+ table->field[2]->store(password, password_len,
+ &my_charset_latin1);
}
else
{
old_row_exists = 1;
store_record(table,record[1]); // Save copy for update
if (combo.password.str) // If password given
- table->field[2]->store(password,(uint) strlen(password), &my_charset_latin1);
+ table->field[2]->store(password, password_len, &my_charset_latin1);
}
/* Update table columns with new privileges */
@@ -1542,10 +1544,8 @@ end:
if (!error)
{
acl_cache->clear(1); // Clear privilege cache
- if (!combo.password.str)
- password=0; // No password given on command
if (old_row_exists)
- acl_update_user(combo.user.str,combo.host.str,password,
+ acl_update_user(combo.user.str, combo.host.str, password, password_len,
thd->lex.ssl_type,
thd->lex.ssl_cipher,
thd->lex.x509_issuer,
@@ -1553,7 +1553,7 @@ end:
&thd->lex.mqh,
rights);
else
- acl_insert_user(combo.user.str,combo.host.str,password,
+ acl_insert_user(combo.user.str, combo.host.str, password, password_len,
thd->lex.ssl_type,
thd->lex.ssl_cipher,
thd->lex.x509_issuer,
@@ -3024,12 +3024,15 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
global.append ("'@'",3);
global.append(lex_user->host.str,lex_user->host.length);
global.append ('\'');
- if (acl_user->password)
+ if (acl_user->salt_len)
{
- char passd_buff[HASH_PASSWORD_LENGTH+1];
- make_password_from_salt(passd_buff,acl_user->salt,acl_user->pversion);
+ char passwd_buff[SCRAMBLED_PASSWORD_CHAR_LENGTH+1];
+ if (acl_user->salt_len == SCRAMBLE_LENGTH)
+ make_password_from_salt(passwd_buff, acl_user->salt);
+ else
+ make_password_from_salt_323(passwd_buff, (ulong *) acl_user->salt);
global.append(" IDENTIFIED BY PASSWORD '",25);
- global.append(passd_buff);
+ global.append(passwd_buff);
global.append('\'');
}
/* "show grants" SSL related stuff */
diff --git a/sql/sql_acl.h b/sql/sql_acl.h
index 0dc8c058b3d..0b2df8e765a 100644
--- a/sql/sql_acl.h
+++ b/sql/sql_acl.h
@@ -111,9 +111,9 @@ public:
acl_host_and_ip host;
uint hostname_length;
USER_RESOURCES user_resource;
- char *user,*password;
- ulong salt[6]; // New password has longer length
- uint8 pversion; // password version
+ char *user;
+ uint8 salt[SCRAMBLE_LENGTH+1]; // scrambled password in binary form
+ uint8 salt_len; // 0 - no password, 4 - 3.20, 8 - 3.23, 20 - 4.1.1
enum SSL_type ssl_type;
const char *ssl_cipher, *x509_issuer, *x509_subject;
};
@@ -135,11 +135,8 @@ void acl_reload(THD *thd);
void acl_free(bool end=0);
ulong acl_get(const char *host, const char *ip, const char *bin_ip,
const char *user, const char *db, my_bool db_is_pattern);
-ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
- const char *password,const char *scramble,
- char **priv_user, char *priv_host,
- bool old_ver, USER_RESOURCES *max,char* prepared_scramble,
- uint *cur_priv_version, ACL_USER **cached_user);
+int acl_getroot(THD *thd, USER_RESOURCES *mqh, const char *passwd,
+ uint passwd_len);
bool acl_check_host(const char *host, const char *ip);
bool check_change_password(THD *thd, const char *host, const char *user);
bool change_password(THD *thd, const char *host, const char *user,
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 763408dc5c2..ba1952e533e 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -138,6 +138,7 @@ THD::THD():user_time(0), is_fatal_error(0),
set_query_id=1;
db_access=NO_ACCESS;
version=refresh_version; // For boot
+ *scramble= '\0';
init();
/* Initialize sub structures */
diff --git a/sql/sql_class.h b/sql/sql_class.h
index e10795c4d9d..a49162bb4ef 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -385,6 +385,7 @@ struct system_variables
ulong table_type;
ulong tmp_table_size;
ulong tx_isolation;
+ /* Determines if which non-standard SQL behaviour should be enabled */
ulong sql_mode;
ulong default_week_format;
ulong max_seeks_for_key;
@@ -398,6 +399,7 @@ struct system_variables
my_bool log_warnings;
my_bool low_priority_updates;
my_bool new_mode;
+ my_bool old_passwords;
CHARSET_INFO *character_set_server;
CHARSET_INFO *character_set_database;
@@ -459,7 +461,6 @@ public:
const char *host_or_ip;
ulong client_capabilities; /* What the client supports */
- /* Determines if which non-standard SQL behaviour should be enabled */
ulong max_client_packet_length;
ulong master_access; /* Global privileges from mysql.user */
ulong db_access; /* Privileges for current db */
@@ -556,10 +557,10 @@ public:
enum_tx_isolation session_tx_isolation;
/* for user variables replication*/
DYNAMIC_ARRAY user_var_events;
- // extend scramble to handle new auth
- char scramble[SCRAMBLE41_LENGTH+1];
- // old scramble is needed to handle old clients
- char old_scramble[SCRAMBLE_LENGTH+1];
+
+ /* scramble - random string sent to client on handshake */
+ char scramble[SCRAMBLE_LENGTH+1];
+
uint8 query_cache_type; // type of query cache processing
bool slave_thread;
bool set_query_id,locked,count_cuted_fields,some_tables_deleted;
diff --git a/sql/sql_crypt.cc b/sql/sql_crypt.cc
index 930ecfffef7..b0b8050e311 100644
--- a/sql/sql_crypt.cc
+++ b/sql/sql_crypt.cc
@@ -32,7 +32,7 @@
SQL_CRYPT::SQL_CRYPT(const char *password)
{
ulong rand_nr[2];
- hash_password(rand_nr,password);
+ hash_password(rand_nr,password, strlen(password));
crypt_init(rand_nr);
}
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 771d68e8462..5d05fea4fe3 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -96,7 +96,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
else
res= check_access(thd, SELECT_ACL, any_db);
if (res)
- DBUG_RETURN(-1);
+ DBUG_RETURN(1);
if (!(res=open_and_lock_tables(thd,tables)))
{
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 947205949f1..6cc5d25c34e 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -172,7 +172,10 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
else
res= (table == 0);
else
+ {
+ lock_type=TL_WRITE;
res= open_and_lock_tables(thd, table_list);
+ }
}
else
res= open_and_lock_tables(thd, table_list);
@@ -627,6 +630,7 @@ public:
thd.current_tablenr=0;
thd.version=refresh_version;
thd.command=COM_DELAYED_INSERT;
+ thd.lex.current_select= 0; /* for my_message_sql */
bzero((char*) &thd.net,sizeof(thd.net)); // Safety
thd.system_thread=1;
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index d6cfd555c40..80d698dfc26 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -982,6 +982,7 @@ void st_select_lex::init_query()
cond_count= with_wild= 0;
ref_pointer_array= 0;
select_n_having_items= 0;
+ prep_where= 0;
}
void st_select_lex::init_select()
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 7a7071ae56b..d4148ad3414 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -60,7 +60,7 @@ enum enum_sql_command {
SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT,
SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION,
SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK, SQLCOM_PRELOAD_KEYS,
- SQLCOM_FLUSH, SQLCOM_KILL, SQLCOM_ANALYZE,
+ SQLCOM_FLUSH, SQLCOM_KILL, SQLCOM_ANALYZE,
SQLCOM_ROLLBACK, SQLCOM_ROLLBACK_TO_SAVEPOINT,
SQLCOM_COMMIT, SQLCOM_SAVEPOINT,
SQLCOM_SLAVE_START, SQLCOM_SLAVE_STOP,
@@ -73,7 +73,7 @@ enum enum_sql_command {
SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER, SQLCOM_DO,
SQLCOM_SHOW_WARNS, SQLCOM_EMPTY_QUERY, SQLCOM_SHOW_ERRORS,
SQLCOM_SHOW_COLUMN_TYPES, SQLCOM_SHOW_TABLE_TYPES, SQLCOM_SHOW_PRIVILEGES,
- SQLCOM_HELP, SQLCOM_DROP_USER, SQLCOM_REVOKE_ALL,
+ SQLCOM_HELP, SQLCOM_DROP_USER, SQLCOM_REVOKE_ALL, SQLCOM_CHECKSUM,
/* This should be the last !!! */
SQLCOM_END
@@ -87,6 +87,13 @@ typedef struct st_lex_master_info
uint port, connect_retry;
ulonglong pos;
ulong server_id;
+ /*
+ Variable for MASTER_SSL option.
+ MASTER_SSL=0 in CHANGE MASTER TO corresponds to SSL_DISABLE
+ MASTER_SSL=1 corresponds to SSL_ENABLE
+ */
+ enum {SSL_UNCHANGED=0, SSL_DISABLE, SSL_ENABLE} ssl;
+ char *ssl_key, *ssl_cert, *ssl_ca, *ssl_capath, *ssl_cipher;
char *relay_log_name;
ulong relay_log_pos;
} LEX_MASTER_INFO;
@@ -272,8 +279,8 @@ protected:
select_result *result;
int res;
- bool describe, found_rows_for_union,
- prepared, // prepare phase already performed for UNION (unit)
+ ulong describe, found_rows_for_union;
+ bool prepared, // prepare phase already performed for UNION (unit)
optimized, // optimize phase already performed for UNION (unit)
executed, // already executed
t_and_f; // used for transferring tables_and_fields_initied UNIT:: methods
@@ -332,6 +339,7 @@ class st_select_lex: public st_select_lex_node
public:
char *db, *db1, *table1, *db2, *table2; /* For outer join using .. */
Item *where, *having; /* WHERE & HAVING clauses */
+ Item *prep_where; /* saved WHERE clause for prepared statement processing */
enum olap_type olap;
SQL_LIST table_list, group_list; /* FROM & GROUP BY clauses */
List<Item> item_list; /* list of fields & expressions */
@@ -472,15 +480,21 @@ typedef struct st_lex
SELECT_LEX *all_selects_list;
uchar *ptr,*tok_start,*tok_end,*end_of_query;
char *length,*dec,*change,*name;
+ char *help_arg;
char *backup_dir; /* For RESTORE/BACKUP */
char* to_log; /* For PURGE MASTER LOGS TO */
time_t purge_time; /* For PURGE MASTER LOGS BEFORE */
char* x509_subject,*x509_issuer,*ssl_cipher;
char* found_colon; /* For multi queries - next query */
- enum SSL_type ssl_type; /* defined in violite.h */
String *wild;
sql_exchange *exchange;
select_result *result;
+ Item *default_value, *comment;
+ LEX_USER *grant_user;
+ gptr yacc_yyss,yacc_yyvs;
+ THD *thd;
+ CHARSET_INFO *charset;
+ SQL_LIST *gorder_list;
List<key_part_spec> col_list;
List<key_part_spec> ref_list;
@@ -499,11 +513,6 @@ typedef struct st_lex
TYPELIB *interval;
create_field *last_field;
char *savepoint_name; // Transaction savepoint id
- Item *default_value, *comment;
- uint uint_geom_type;
- LEX_USER *grant_user;
- gptr yacc_yyss,yacc_yyvs;
- THD *thd;
udf_func udf;
HA_CHECK_OPT check_opt; // check/repair options
HA_CREATE_INFO create_info;
@@ -512,6 +521,7 @@ typedef struct st_lex
ulong thread_id,type;
enum_sql_command sql_command;
thr_lock_type lock_option;
+ enum SSL_type ssl_type; /* defined in violite.h */
enum my_lex_states next_state;
enum enum_duplicates duplicates;
enum enum_tx_isolation tx_isolation;
@@ -519,17 +529,15 @@ typedef struct st_lex
enum ha_rkey_function ha_rkey_mode;
enum enum_enable_or_disable alter_keys_onoff;
enum enum_var_type option_type;
+ uint uint_geom_type;
uint grant, grant_tot_col, which_columns;
uint fk_delete_opt, fk_update_opt, fk_match_option;
uint param_count;
+ uint slave_thd_opt;
bool drop_primary, drop_if_exists, drop_temporary, local_file;
bool in_comment, ignore_space, verbose, simple_alter, no_write_to_binlog;
bool derived_tables, describe;
bool safe_to_cache_query;
- uint slave_thd_opt;
- CHARSET_INFO *charset;
- char *help_arg;
- SQL_LIST *gorder_list;
st_lex() {}
inline void uncacheable()
{
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index d030eaf617c..dd6bdf45e82 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -77,9 +77,6 @@ static int read_sep_field(THD *thd,COPY_INFO &info,TABLE *table,
List<Item> &fields, READ_INFO &read_info,
String &enclosed);
-
-#ifndef EMBEDDED_LIBRARY
-
int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
List<Item> &fields, enum enum_duplicates handle_duplicates,
bool read_file_from_client,thr_lock_type lock_type)
@@ -91,7 +88,9 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
String *field_term=ex->field_term,*escaped=ex->escaped,
*enclosed=ex->enclosed;
bool is_fifo=0;
+#ifndef EMBEDDED_LIBRARY
LOAD_FILE_INFO lf_info;
+#endif
char *db = table_list->db; // This is never null
/* If no current database, use database where table is located */
char *tdb= thd->db ? thd->db : db;
@@ -184,6 +183,17 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
}
else
{
+#ifdef EMBEDDED_LIBRARY
+ char *chk_name= ex->file_name;
+ while ((*chk_name == ' ') || (*chk_name == 't'))
+ chk_name++;
+ if (*chk_name == FN_CURLIB)
+ {
+ sprintf(name, "%s%s", mysql_data_home, ex->file_name);
+ unpack_filename(name, name);
+ }
+ else
+#endif /*EMBEDDED_LIBRARY*/
unpack_filename(name,ex->file_name);
#if !defined(__WIN__) && !defined(OS2) && ! defined(__NETWARE__)
MY_STAT stat_info;
@@ -225,6 +235,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
DBUG_RETURN(-1); // Can't allocate buffers
}
+#ifndef EMBEDDED_LIBRARY
if (!opt_old_rpl_compat && mysql_bin_log.is_open())
{
lf_info.thd = thd;
@@ -238,6 +249,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
lf_info.log_delayed= log_delayed;
read_info.set_io_cache_arg((void*) &lf_info);
}
+#endif /*!EMBEDDED_LIBRARY*/
+
restore_record(table,default_values);
thd->count_cuted_fields=1; /* calc cuted fields */
@@ -293,6 +306,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
{
if (transactional_table)
ha_autocommit_or_rollback(thd,error);
+#ifndef EMBEDDED_LIBRARY
if (!opt_old_rpl_compat && mysql_bin_log.is_open())
{
if (lf_info.wrote_create_file)
@@ -315,6 +329,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
mysql_bin_log.write(&d);
}
}
+#endif /*!EMBEDDED_LIBRARY*/
error= -1; // Error on read
goto err;
}
@@ -327,6 +342,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
if (!log_delayed)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
+#ifndef EMBEDDED_LIBRARY
if (mysql_bin_log.is_open())
{
if (opt_old_rpl_compat)
@@ -348,6 +364,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
}
}
}
+#endif /*!EMBEDDED_LIBRARY*/
if (transactional_table)
error=ha_autocommit_or_rollback(thd,error);
err:
@@ -359,8 +376,6 @@ err:
DBUG_RETURN(error);
}
-#endif /* EMBEDDED_LIBRARY */
-
/****************************************************************************
** Read of rows of fixed size + optional garage + optonal newline
****************************************************************************/
@@ -640,11 +655,12 @@ READ_INFO::READ_INFO(File file_par, uint tot_length, CHARSET_INFO *cs,
mysys/mf_iocache.c. So we work around the problem with a
manual assignment
*/
+ need_end_io_cache = 1;
+
+#ifndef EMBEDDED_LIBRARY
if (get_it_from_net)
cache.read_function = _my_b_net_read;
- need_end_io_cache = 1;
-#ifndef EMBEDDED_LIBRARY
if (!opt_old_rpl_compat && mysql_bin_log.is_open())
cache.pre_read = cache.pre_close =
(IO_CACHE_CALLBACK) log_loaded_block;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 33e96cc2776..ff66892262d 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -176,154 +176,184 @@ end:
}
+#ifndef EMBEDDED_LIBRARY
/*
- Check if user is ok
-
+ Check if user exist and password supplied is correct.
SYNOPSIS
check_user()
- thd Thread handle
- command Command for connection (for log)
- user Name of user trying to connect
- passwd Scrambled password sent from client
- db Database to connect to
- check_count If set to 1, don't allow too many connection
- simple_connect If 1 then client is of old type and we should connect
- using the old method (no challange)
- do_send_error Set to 1 if we should send error to user
- prepared_scramble Buffer to store hash password of new connection
- had_password Set to 1 if the user gave a password
- cur_priv_version Check flag to know if someone flushed the privileges
- since last code
- hint_user Pointer used by acl_getroot() to remmeber user for
- next call
-
- RETURN
- 0 ok
- thd->user, thd->master_access, thd->priv_user, thd->db and
- thd->db_access are updated
- 1 Access denied; Error sent to client
- -1 If do_send_error == 1: Failed connect, error sent to client
- If do_send_error == 0: Prepare for stage of connect
+ thd thread handle, thd->{host,user,ip} are used
+ command originator of the check: now check_user is called
+ during connect and change user procedures; used for
+ logging.
+ passwd scrambled password recieved from client
+ passwd_len length of scrambled password
+ db database name to connect to, may be NULL
+ check_count dont know exactly
+
+ Note, that host, user and passwd may point to communication buffer.
+ Current implementation does not depened on that, but future changes
+ should be done with this in mind; 'thd' is INOUT, all other params
+ are 'IN'.
+
+ RETURN VALUE
+ 0 OK; thd->user, thd->master_access, thd->priv_user, thd->db and
+ thd->db_access are updated; OK is sent to client;
+ -1 access denied or handshake error; error is sent to client;
+ >0 error, not sent to client
*/
-static int check_user(THD *thd,enum_server_command command, const char *user,
- const char *passwd, const char *db, bool check_count,
- bool simple_connect, bool do_send_error,
- char *prepared_scramble, bool had_password,
- uint *cur_priv_version, ACL_USER** hint_user)
+static int check_user(THD *thd, enum enum_server_command command,
+ const char *passwd, uint passwd_len, const char *db,
+ bool check_count)
{
- thd->db=0;
- thd->db_length=0;
- USER_RESOURCES ur;
- char tmp_passwd[SCRAMBLE41_LENGTH+1];
DBUG_ENTER("check_user");
+ my_bool opt_secure_auth_local;
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ opt_secure_auth_local= opt_secure_auth;
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+
/*
- Move password to temporary buffer as it may be stored in communication
- buffer
+ If the server is running in secure auth mode, short scrambles are
+ forbidden.
*/
- strmake(tmp_passwd, passwd, sizeof(tmp_passwd));
- passwd= tmp_passwd; // Use local copy
-
- /* We shall avoid dupplicate user allocations here */
- if (!thd->user && !(thd->user = my_strdup(user, MYF(0))))
+ if (opt_secure_auth_local && passwd_len == SCRAMBLE_LENGTH_323)
{
- send_error(thd,ER_OUT_OF_RESOURCES);
- DBUG_RETURN(1);
+ net_printf(thd, ER_NOT_SUPPORTED_AUTH_MODE);
+ mysql_log.write(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
+ DBUG_RETURN(-1);
}
- thd->master_access=acl_getroot(thd, thd->host, thd->ip, thd->user,
- passwd, thd->scramble,
- &thd->priv_user, thd->priv_host,
- (protocol_version == 9 ||
- !(thd->client_capabilities &
- CLIENT_LONG_PASSWORD)),
- &ur,prepared_scramble,
- cur_priv_version,hint_user);
-
- DBUG_PRINT("info",
- ("Capabilities: %d packet_length: %ld Host: '%s' Login user: '%s' Priv_user: '%s' Using password: %s Access: %u db: '%s'",
- thd->client_capabilities, thd->max_client_packet_length,
- thd->host_or_ip, thd->user, thd->priv_user,
- had_password ? "yes": "no",
- thd->master_access, thd->db ? thd->db : "*none*"));
+ if (passwd_len != 0 &&
+ passwd_len != SCRAMBLE_LENGTH &&
+ passwd_len != SCRAMBLE_LENGTH_323)
+ DBUG_RETURN(ER_HANDSHAKE_ERROR);
/*
- In case we're going to retry we should not send error message at this
- point
+ Clear thd->db as it points to something, that will be freed when
+ connection is closed. We don't want to accidently free a wrong pointer
+ if connect failed. Also in case of 'CHANGE USER' failure, current
+ database will be switched to 'no database selected'.
*/
- if (thd->master_access & NO_ACCESS)
+ thd->db= 0;
+ thd->db_length= 0;
+
+ USER_RESOURCES ur;
+ int res= acl_getroot(thd, &ur, passwd, passwd_len);
+ if (res == -1)
{
- if (do_send_error || !had_password || !*hint_user)
+ /*
+ This happens when client (new) sends password scrambled with
+ scramble(), but database holds old value (scrambled with
+ scramble_323()). Here we please client to send scrambled_password
+ in old format.
+ */
+ NET *net= &thd->net;
+ if (opt_secure_auth_local)
{
- DBUG_PRINT("info",("Access denied"));
+ net_printf(thd, ER_SERVER_IS_IN_SECURE_AUTH_MODE,
+ thd->user, thd->host_or_ip);
+ mysql_log.write(thd, COM_CONNECT, ER(ER_SERVER_IS_IN_SECURE_AUTH_MODE),
+ thd->user, thd->host_or_ip);
+ DBUG_RETURN(-1);
+ }
+ if (send_old_password_request(thd) ||
+ my_net_read(net) != SCRAMBLE_LENGTH_323 + 1) // We have to read very
+ { // specific packet size
+ inc_host_errors(&thd->remote.sin_addr);
+ DBUG_RETURN(ER_HANDSHAKE_ERROR);
+ }
+ /* Final attempt to check the user based on reply */
+ /* So as passwd is short, errcode is always >= 0 */
+ res= acl_getroot(thd, &ur, (char *) net->read_pos, SCRAMBLE_LENGTH_323);
+ }
+ /* here res is always >= 0 */
+ if (res == 0)
+ {
+ if (!(thd->master_access & NO_ACCESS)) // authentification is OK
+ {
+ DBUG_PRINT("info",
+ ("Capabilities: %d packet_length: %ld Host: '%s' "
+ "Login user: '%s' Priv_user: '%s' Using password: %s "
+ "Access: %u db: '%s'",
+ thd->client_capabilities, thd->max_client_packet_length,
+ thd->host_or_ip, thd->user, thd->priv_user,
+ passwd_len ? "yes": "no",
+ thd->master_access, thd->db ? thd->db : "*none*"));
+
+ if (check_count)
+ {
+ VOID(pthread_mutex_lock(&LOCK_thread_count));
+ bool count_ok= thread_count < max_connections + delayed_insert_threads
+ || (thd->master_access & SUPER_ACL);
+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
+ if (!count_ok)
+ { // too many connections
+ send_error(thd, ER_CON_COUNT_ERROR);
+ DBUG_RETURN(-1);
+ }
+ }
+
+ /* Why logging is performed before all checks've passed? */
+ mysql_log.write(thd,command,
+ (thd->priv_user == thd->user ?
+ (char*) "%s@%s on %s" :
+ (char*) "%s@%s as anonymous on %s"),
+ thd->user, thd->host_or_ip,
+ db ? db : (char*) "");
+
/*
- Old client should get nicer error message if password version is
- not supported
+ This is the default access rights for the current database. It's
+ set to 0 here because we don't have an active database yet (and we
+ may not have an active database to set.
*/
- if (simple_connect && *hint_user && (*hint_user)->pversion)
+ thd->db_access=0;
+
+ /* Don't allow user to connect if he has done too many queries */
+ if ((ur.questions || ur.updates ||
+ ur.connections || max_user_connections) &&
+ get_or_create_user_conn(thd,thd->user,thd->host_or_ip,&ur))
+ DBUG_RETURN(1);
+ if (thd->user_connect && thd->user_connect->user_resources.connections &&
+ check_for_max_user_connections(thd, thd->user_connect))
+ DBUG_RETURN(1);
+
+ /* Change database if necessary: OK or FAIL is sent in mysql_change_db */
+ if (db && db[0])
{
- net_printf(thd, ER_NOT_SUPPORTED_AUTH_MODE);
- mysql_log.write(thd,COM_CONNECT,ER(ER_NOT_SUPPORTED_AUTH_MODE));
+ if (mysql_change_db(thd, db))
+ {
+ if (thd->user_connect)
+ decrease_user_connections(thd->user_connect);
+ DBUG_RETURN(-1);
+ }
}
else
- {
- net_printf(thd, ER_ACCESS_DENIED_ERROR,
- thd->user,
- thd->host_or_ip,
- had_password ? ER(ER_YES) : ER(ER_NO));
- mysql_log.write(thd,COM_CONNECT,ER(ER_ACCESS_DENIED_ERROR),
- thd->user,
- thd->host_or_ip,
- had_password ? ER(ER_YES) : ER(ER_NO));
- }
- DBUG_RETURN(1); // Error already given
- }
- DBUG_PRINT("info",("Prepare for second part of handshake"));
- DBUG_RETURN(-1); // no report error in special handshake
- }
-
- if (check_count)
- {
- VOID(pthread_mutex_lock(&LOCK_thread_count));
- bool tmp=(thread_count - delayed_insert_threads >= max_connections &&
- !(thd->master_access & SUPER_ACL));
- VOID(pthread_mutex_unlock(&LOCK_thread_count));
- if (tmp)
- { // Too many connections
- send_error(thd, ER_CON_COUNT_ERROR);
- DBUG_RETURN(1);
+ send_ok(thd);
+ thd->password= test(passwd_len); // remember for error messages
+ /* Ready to handle queries */
+ DBUG_RETURN(0);
}
}
- mysql_log.write(thd,command,
- (thd->priv_user == thd->user ?
- (char*) "%s@%s on %s" :
- (char*) "%s@%s as anonymous on %s"),
- user,
- thd->host_or_ip,
- db ? db : (char*) "");
- thd->db_access=0;
- /* Don't allow user to connect if he has done too many queries */
- if ((ur.questions || ur.updates || ur.connections || max_user_connections) &&
- get_or_create_user_conn(thd,user,thd->host_or_ip,&ur))
- DBUG_RETURN(1);
- if (thd->user_connect && ((thd->user_connect->user_resources.connections) ||
- max_user_connections) &&
- check_for_max_user_connections(thd, thd->user_connect))
- DBUG_RETURN(1);
-
- if (db && db[0])
- {
- int error= test(mysql_change_db(thd,db));
- if (error && thd->user_connect)
- decrease_user_connections(thd->user_connect);
- DBUG_RETURN(error);
- }
- send_ok(thd); // Ready to handle questions
- thd->password= test(passwd[0]); // Remember for error messages
- DBUG_RETURN(0); // ok
+ else if (res == 2) // client gave short hash, server has long hash
+ {
+ net_printf(thd, ER_NOT_SUPPORTED_AUTH_MODE);
+ mysql_log.write(thd,COM_CONNECT,ER(ER_NOT_SUPPORTED_AUTH_MODE));
+ DBUG_RETURN(-1);
+ }
+ net_printf(thd, ER_ACCESS_DENIED_ERROR,
+ thd->user,
+ thd->host_or_ip,
+ passwd_len ? ER(ER_YES) : ER(ER_NO));
+ mysql_log.write(thd, COM_CONNECT, ER(ER_ACCESS_DENIED_ERROR),
+ thd->user,
+ thd->host_or_ip,
+ passwd_len ? ER(ER_YES) : ER(ER_NO));
+ DBUG_RETURN(-1);
}
+#endif // EMBEDDED_LIBRARY
+
/*
Check for maximum allowable user connections, if the mysqld server is
@@ -526,45 +556,36 @@ static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them= 0)
/*
- Check connnectionn and get priviliges
-
+ Perform handshake, authorize client and update thd ACL variables.
SYNOPSIS
- check_connections
- thd Thread handle
+ check_connection()
+ thd thread handle
RETURN
- 0 ok
- -1 Error, which is sent to user
- > 0 Error code (not sent to user)
+ 0 success, OK is sent to user, thd is updated.
+ -1 error, which is sent to user
+ > 0 error code (not sent to user)
*/
#ifndef EMBEDDED_LIBRARY
static int
-check_connections(THD *thd)
+check_connection(THD *thd)
{
- int res;
- uint connect_errors=0;
- uint cur_priv_version;
- bool using_password;
+ uint connect_errors= 0;
NET *net= &thd->net;
- char *end, *user, *passwd, *db;
- char prepared_scramble[SCRAMBLE41_LENGTH+4]; /* Buffer for scramble&hash */
- char db_buff[NAME_LEN+1];
- ACL_USER* cached_user=NULL; /* Initialise to NULL for first stage */
- DBUG_PRINT("info",("New connection received on %s",
- vio_description(net->vio)));
-
- /* Remove warning from valgrind. TODO: Fix it in password.c */
- bzero((char*) &prepared_scramble[0], sizeof(prepared_scramble));
+
+ DBUG_PRINT("info",
+ ("New connection received on %s", vio_description(net->vio)));
+
if (!thd->host) // If TCP/IP connection
{
char ip[30];
if (vio_peer_addr(net->vio, ip, &thd->peer_port))
return (ER_BAD_HOST_ERROR);
- if (!(thd->ip = my_strdup(ip,MYF(0))))
+ if (!(thd->ip= my_strdup(ip,MYF(0))))
return (ER_OUT_OF_RESOURCES);
- thd->host_or_ip=thd->ip;
+ thd->host_or_ip= thd->ip;
#if !defined(HAVE_SYS_UN_H) || defined(HAVE_mit_thread)
/* Fast local hostname resolve for Win32 */
if (!strcmp(thd->ip,"127.0.0.1"))
@@ -600,15 +621,16 @@ check_connections(THD *thd)
DBUG_PRINT("info",("Host: %s",thd->host));
thd->host_or_ip= thd->host;
thd->ip= 0;
- bzero((char*) &thd->remote,sizeof(struct sockaddr));
+ bzero((char*) &thd->remote, sizeof(struct sockaddr));
}
/* Ensure that wrong hostnames doesn't cause buffer overflows */
vio_keepalive(net->vio, TRUE);
- ulong pkt_len=0;
+ ulong pkt_len= 0;
+ char *end;
{
/* buff[] needs to big enough to hold the server_version variable */
- char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH+64];
+ char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH + 64];
ulong client_flags = (CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB |
CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION);
@@ -622,19 +644,34 @@ check_connections(THD *thd)
client_flags |= CLIENT_SSL; /* Wow, SSL is avalaible! */
#endif /* HAVE_OPENSSL */
- end=strnmov(buff,server_version,SERVER_VERSION_LENGTH)+1;
- int4store((uchar*) end,thd->thread_id);
- end+=4;
- memcpy(end,thd->scramble,SCRAMBLE_LENGTH+1);
- end+=SCRAMBLE_LENGTH +1;
- int2store(end,client_flags);
+ end= strnmov(buff, server_version, SERVER_VERSION_LENGTH) + 1;
+ int4store((uchar*) end, thd->thread_id);
+ end+= 4;
+ /*
+ So as check_connection is the only entry point to authorization
+ procedure, scramble is set here. This gives us new scramble for
+ each handshake.
+ */
+ create_random_string(thd->scramble, SCRAMBLE_LENGTH, &thd->rand);
+ /*
+ Old clients does not understand long scrambles, but can ignore packet
+ tail: that's why first part of the scramble is placed here, and second
+ part at the end of packet.
+ */
+ end= strmake(end, thd->scramble, SCRAMBLE_LENGTH_323) + 1;
+
+ int2store(end, client_flags);
+ /* write server characteristics: up to 16 bytes allowed */
end[2]=(char) default_charset_info->number;
- int2store(end+3,thd->server_status);
- bzero(end+5,13);
- end+=18;
-
- // At this point we write connection message and read reply
- if (net_write_command(net,(uchar) protocol_version, "", 0, buff,
+ int2store(end+3, thd->server_status);
+ bzero(end+5, 13);
+ end+= 18;
+ /* write scramble tail */
+ end= strmake(end, thd->scramble + SCRAMBLE_LENGTH_323,
+ SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323) + 1;
+
+ /* At this point we write connection message and read reply */
+ if (net_write_command(net, (uchar) protocol_version, "", 0, buff,
(uint) (end-buff)) ||
(pkt_len= my_net_read(net)) == packet_error ||
pkt_len < MIN_HANDSHAKE_SIZE)
@@ -723,7 +760,7 @@ check_connections(THD *thd)
return(ER_HANDSHAKE_ERROR);
}
DBUG_PRINT("info", ("Reading user information over SSL layer"));
- if ((pkt_len=my_net_read(net)) == packet_error ||
+ if ((pkt_len= my_net_read(net)) == packet_error ||
pkt_len < NORMAL_HANDSHAKE_SIZE)
{
DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)",
@@ -740,25 +777,6 @@ check_connections(THD *thd)
return(ER_HANDSHAKE_ERROR);
}
- user= end;
- passwd= strend(user)+1;
- db=0;
- using_password= test(passwd[0]);
- if (thd->client_capabilities & CLIENT_CONNECT_WITH_DB)
- {
- db= strend(passwd)+1;
- uint32 length= copy_and_convert(db_buff, sizeof(db_buff)-1,
- system_charset_info,
- db, strlen(db),
- thd->charset());
- db_buff[length]= 0;
- db= db_buff;
- }
-
- /* We can get only old hash at this point */
- if (using_password && strlen(passwd) != SCRAMBLE_LENGTH)
- return ER_HANDSHAKE_ERROR;
-
if (thd->client_capabilities & CLIENT_INTERACTIVE)
thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
@@ -766,60 +784,36 @@ check_connections(THD *thd)
net->return_status= &thd->server_status;
net->read_timeout=(uint) thd->variables.net_read_timeout;
- /* Simple connect only for old clients. New clients always use secure auth */
- bool simple_connect=(!(thd->client_capabilities & CLIENT_SECURE_CONNECTION));
+ char *user= end;
+ char *passwd= strend(user)+1;
+ char *db= passwd;
+ char db_buff[NAME_LEN+1]; // buffer to store db in utf8
+ /*
+ Old clients send null-terminated string as password; new clients send
+ the size (1 byte) + string (not null-terminated). Hence in case of empty
+ password both send '\0'.
+ */
+ uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
+ *passwd++ : strlen(passwd);
+ db= thd->client_capabilities & CLIENT_CONNECT_WITH_DB ?
+ db + passwd_len + 1 : 0;
- /* Check user permissions. If password failure we'll get scramble back */
- if ((res=check_user(thd, COM_CONNECT, user, passwd, db, 1, simple_connect,
- simple_connect, prepared_scramble, using_password,
- &cur_priv_version,
- &cached_user)) < 0)
+ /* Since 4.1 all database names are stored in utf8 */
+ if (db)
{
- /* Store current used and database as they are erased with next packet */
- char tmp_user[USERNAME_LENGTH+1];
- char tmp_db[NAME_LEN+1];
-
- /* If the client is old we just have to return error */
- if (simple_connect)
- return -1;
-
- DBUG_PRINT("info",("password challenge"));
-
- tmp_user[0]= tmp_db[0]= 0;
- if (user)
- strmake(tmp_user,user,USERNAME_LENGTH);
- if (db)
- strmake(tmp_db,db,NAME_LEN);
+ uint32 length= copy_and_convert(db_buff, sizeof(db_buff)-1,
+ system_charset_info,
+ db, strlen(db),
+ thd->charset());
+ db_buff[length]= 0;
+ db= db_buff;
+ }
- /* Write hash and encrypted scramble to client */
- if (my_net_write(net,prepared_scramble,SCRAMBLE41_LENGTH+4) ||
- net_flush(net))
- {
- inc_host_errors(&thd->remote.sin_addr);
- return ER_HANDSHAKE_ERROR;
- }
- /* Reading packet back */
- if ((pkt_len= my_net_read(net)) == packet_error)
- {
- inc_host_errors(&thd->remote.sin_addr);
- return ER_HANDSHAKE_ERROR;
- }
- /* We have to get very specific packet size */
- if (pkt_len != SCRAMBLE41_LENGTH)
- {
- inc_host_errors(&thd->remote.sin_addr);
- return ER_HANDSHAKE_ERROR;
- }
- /* Final attempt to check the user based on reply */
- if (check_user(thd,COM_CONNECT, tmp_user, (char*)net->read_pos,
- tmp_db, 1, 0, 1, prepared_scramble, using_password,
- &cur_priv_version,
- &cached_user))
- return -1;
- }
- else if (res)
- return -1; // Error sent from check_user()
- return 0;
+ if (thd->user)
+ x_free(thd->user);
+ if (!(thd->user= my_strdup(user, MYF(0))))
+ return (ER_OUT_OF_RESOURCES);
+ return check_user(thd, COM_CONNECT, passwd, passwd_len, db, true);
}
@@ -876,7 +870,7 @@ pthread_handler_decl(handle_one_connection,arg)
NET *net= &thd->net;
thd->thread_stack= (char*) &thd;
- if ((error=check_connections(thd)))
+ if ((error=check_connection(thd)))
{ // Wrong permissions
if (error > 0)
net_printf(thd,error,thd->host_or_ip);
@@ -1161,7 +1155,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
mysql_log.write(thd,command,"%s",thd->db);
break;
}
-#ifndef EMBEDDED_LIBRARY
+#ifdef HAVE_REPLICATION
case COM_REGISTER_SLAVE:
{
if (!register_slave(thd, (uchar*)packet, packet_length))
@@ -1188,116 +1182,72 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
case COM_CHANGE_USER:
{
thd->change_user();
- thd->clear_error(); // If errors from rollback
+ thd->clear_error(); // if errors from rollback
- statistic_increment(com_other,&LOCK_status);
- char *user= (char*) packet;
+ statistic_increment(com_other, &LOCK_status);
+ char *user= (char*) packet;
char *passwd= strend(user)+1;
- char *db= strend(passwd)+1;
-
- /* Save user and privileges */
- uint save_master_access=thd->master_access;
- uint save_db_access= thd->db_access;
- uint save_db_length= thd->db_length;
- char *save_user= thd->user;
- thd->user=NULL; /* Needed for check_user to allocate new user */
- char *save_priv_user= thd->priv_user;
- char *save_db= thd->db;
- USER_CONN *save_uc= thd->user_connect;
- bool simple_connect;
- bool using_password;
- char prepared_scramble[SCRAMBLE41_LENGTH+4];/* Buffer for scramble,hash */
- char tmp_user[USERNAME_LENGTH+1];
- char tmp_db[NAME_LEN+1];
- ACL_USER* cached_user ; /* Cached user */
- uint cur_priv_version; /* Cached grant version */
- int res;
- ulong pkt_len= 0; /* Length of reply packet */
-
- bzero((char*) prepared_scramble, sizeof(prepared_scramble));
+ /*
+ Old clients send null-terminated string ('\0' for empty string) for
+ password. New clients send the size (1 byte) + string (not null
+ terminated, so also '\0' for empty string).
+ */
+ char *db= passwd;
+ uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
+ *passwd++ : strlen(passwd);
+ db+= passwd_len + 1;
/* Small check for incomming packet */
-
if ((uint) ((uchar*) db - net->read_pos) > packet_length)
- goto restore_user_err;
-
- /* Now we shall basically perform authentication again */
-
- /* We can get only old hash at this point */
- if (passwd[0] && strlen(passwd)!=SCRAMBLE_LENGTH)
- goto restore_user_err;
-
- cached_user= NULL;
-
- /* Simple connect only for old clients. New clients always use sec. auth*/
- simple_connect=(!(thd->client_capabilities & CLIENT_SECURE_CONNECTION));
-
- /* Store information if we used password. passwd will be dammaged */
- using_password=test(passwd[0]);
+ {
+ send_error(thd, ER_UNKNOWN_COM_ERROR);
+ break;
+ }
- if (simple_connect) /* Restore scramble for old clients */
- memcpy(thd->scramble,thd->old_scramble,9);
+ /* Convert database name to utf8 */
+ String convdb;
+ convdb.copy(db, strlen(db), thd->variables.character_set_client,
+ system_charset_info);
+ db= convdb.c_ptr();
- /*
- Check user permissions. If password failure we'll get scramble back
- Do not retry if we already have sent error (result>0)
- */
- if ((res=check_user(thd,COM_CHANGE_USER, user, passwd, db, 0,
- simple_connect, simple_connect, prepared_scramble,
- using_password, &cur_priv_version, &cached_user)) < 0)
+ /* Save user and privileges */
+ uint save_master_access= thd->master_access;
+ uint save_db_access= thd->db_access;
+ uint save_db_length= thd->db_length;
+ char *save_user= thd->user;
+ char *save_priv_user= thd->priv_user;
+ char *save_db= thd->db;
+ USER_CONN *save_uc= thd->user_connect;
+ thd->user= my_strdup(user, MYF(0));
+ if (!thd->user)
{
- /* If the client is old we just have to have auth failure */
- if (simple_connect)
- goto restore_user; /* Error is already reported */
-
- /* Store current used and database as they are erased with next packet */
- tmp_user[0]= tmp_db[0]= 0;
- if (user)
- strmake(tmp_user,user,USERNAME_LENGTH);
- if (db)
- strmake(tmp_db,db,NAME_LEN);
-
- /* Write hash and encrypted scramble to client */
- if (my_net_write(net,prepared_scramble,SCRAMBLE41_LENGTH+4) ||
- net_flush(net))
- goto restore_user_err;
-
- /* Reading packet back */
- if ((pkt_len=my_net_read(net)) == packet_error)
- goto restore_user_err;
-
- /* We have to get very specific packet size */
- if (pkt_len != SCRAMBLE41_LENGTH)
- goto restore_user;
-
- /* Final attempt to check the user based on reply */
- if (check_user(thd,COM_CHANGE_USER, tmp_user, (char*) net->read_pos,
- tmp_db, 0, 0, 1, prepared_scramble, using_password,
- &cur_priv_version, &cached_user))
- goto restore_user;
+ thd->user= save_user;
+ send_error(thd, ER_OUT_OF_RESOURCES);
+ break;
}
- else if (res)
- goto restore_user;
-
- /* Finally we've authenticated new user */
- if (max_connections && save_uc)
- decrease_user_connections(save_uc);
- x_free((gptr) save_db);
- x_free((gptr) save_user);
- thd->password=using_password;
- break;
- /* Bad luck we shall restore old user */
-restore_user_err:
- send_error(thd, ER_UNKNOWN_COM_ERROR);
+ int res= check_user(thd, COM_CHANGE_USER, passwd, passwd_len, db, false);
-restore_user:
- x_free(thd->user);
- thd->master_access=save_master_access;
- thd->db_access=save_db_access;
- thd->db=save_db;
- thd->db_length=save_db_length;
- thd->user=save_user;
- thd->priv_user=save_priv_user;
+ if (res)
+ {
+ /* authentification failure, we shall restore old user */
+ if (res > 0)
+ send_error(thd, ER_UNKNOWN_COM_ERROR);
+ x_free(thd->user);
+ thd->user= save_user;
+ thd->priv_user= save_priv_user;
+ thd->master_access= save_master_access;
+ thd->db_access= save_db_access;
+ thd->db= save_db;
+ thd->db_length= save_db_length;
+ }
+ else
+ {
+ /* we've authenticated new user */
+ if (max_connections && save_uc)
+ decrease_user_connections(save_uc);
+ x_free((gptr) save_db);
+ x_free((gptr) save_user);
+ }
break;
}
#endif /* EMBEDDED_LIBRARY */
@@ -1711,7 +1661,7 @@ mysql_execute_command(THD *thd)
}
#endif
}
-#endif /* EMBEDDED_LIBRARY */
+#endif /* !EMBEDDED_LIBRARY */
/*
TODO: make derived tables processing 'inside' SELECT processing.
TODO: solve problem with depended derived tables in subselects
@@ -1887,7 +1837,7 @@ mysql_execute_command(THD *thd)
break;
}
-#ifndef EMBEDDED_LIBRARY
+#ifdef HAVE_REPLICATION
case SQLCOM_SHOW_SLAVE_HOSTS:
{
if (check_global_access(thd, REPL_SLAVE_ACL))
@@ -1933,7 +1883,7 @@ mysql_execute_command(THD *thd)
}
-#ifndef EMBEDDED_LIBRARY
+#ifdef HAVE_REPLICATION
case SQLCOM_CHANGE_MASTER:
{
if (check_global_access(thd, SUPER_ACL))
@@ -1970,7 +1920,7 @@ mysql_execute_command(THD *thd)
else
res = load_master_data(thd);
break;
-#endif /* EMBEDDED_LIBRARY */
+#endif /* HAVE_REPLICATION */
#ifdef HAVE_INNOBASE_DB
case SQLCOM_SHOW_INNODB_STATUS:
@@ -1982,7 +1932,7 @@ mysql_execute_command(THD *thd)
}
#endif
-#ifndef EMBEDDED_LIBRARY
+#ifdef HAVE_REPLICATION
case SQLCOM_LOAD_MASTER_TABLE:
{
if (!tables->db)
@@ -2014,7 +1964,7 @@ mysql_execute_command(THD *thd)
UNLOCK_ACTIVE_MI;
break;
}
-#endif /* EMBEDDED_LIBRARY */
+#endif /* HAVE_REPLICATION */
case SQLCOM_CREATE_TABLE:
{
@@ -2131,7 +2081,7 @@ mysql_execute_command(THD *thd)
res = mysql_create_index(thd, tables, lex->key_list);
break;
-#ifndef EMBEDDED_LIBRARY
+#ifdef HAVE_REPLICATION
case SQLCOM_SLAVE_START:
{
LOCK_ACTIVE_MI;
@@ -2164,7 +2114,7 @@ mysql_execute_command(THD *thd)
UNLOCK_ACTIVE_MI;
break;
}
-#endif
+#endif /* HAVE_REPLICATION */
case SQLCOM_ALTER_TABLE:
#if defined(DONT_ALLOW_SHOW_COMMANDS)
@@ -2285,6 +2235,14 @@ mysql_execute_command(THD *thd)
break;
}
#endif
+ case SQLCOM_CHECKSUM:
+ {
+ if (check_db_used(thd,tables) ||
+ check_table_access(thd, SELECT_ACL | EXTRA_ACL , tables))
+ goto error; /* purecov: inspected */
+ res = mysql_checksum_table(thd, tables, &lex->check_opt);
+ break;
+ }
case SQLCOM_REPAIR:
{
if (check_db_used(thd,tables) ||
@@ -2662,8 +2620,10 @@ mysql_execute_command(THD *thd)
break;
#endif
case SQLCOM_SHOW_PROCESSLIST:
+#ifndef EMBEDDED_LIBRARY
if (!thd->priv_user[0] && check_global_access(thd,PROCESS_ACL))
break;
+#endif
mysqld_list_processes(thd,thd->master_access & PROCESS_ACL ? NullS :
thd->priv_user,lex->verbose);
break;
@@ -2797,7 +2757,7 @@ mysql_execute_command(THD *thd)
case SQLCOM_CHANGE_DB:
mysql_change_db(thd,select_lex->db);
break;
-#ifndef EMBEDDED_LIBRARY
+
case SQLCOM_LOAD:
{
uint privilege= (lex->duplicates == DUP_REPLACE ?
@@ -2824,7 +2784,7 @@ mysql_execute_command(THD *thd)
lex->duplicates, (bool) lex->local_file, lex->lock_option);
break;
}
-#endif /* EMBEDDED_LIBRARY */
+
case SQLCOM_SET_OPTION:
if (tables && ((res= check_table_access(thd, SELECT_ACL, tables)) ||
(res= open_and_lock_tables(thd,tables))))
@@ -3247,7 +3207,7 @@ error:
Check grants for commands which work only with one table and all other
tables belong to subselects.
- SYNOPSYS
+ SYNOPSIS
single_table_command_access()
thd - Thread handler
privilege - asked privelage
@@ -4418,7 +4378,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
refresh_status();
if (options & REFRESH_THREADS)
flush_thread_cache();
-#ifndef EMBEDDED_LIBRARY
+#ifdef HAVE_REPLICATION
if (options & REFRESH_MASTER)
{
tmp_write_to_binlog= 0;
@@ -4433,7 +4393,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
result=load_des_key_file(des_key_file);
}
#endif
-#ifndef EMBEDDED_LIBRARY
+#ifdef HAVE_REPLICATION
if (options & REFRESH_SLAVE)
{
tmp_write_to_binlog= 0;
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 550e4bbe086..4abbbcaff1f 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -873,11 +873,21 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length)
if (!(specialflag & SPECIAL_NO_PRIOR))
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;
+ sl;
+ sl= sl->next_select_in_list())
+ {
+ sl->prep_where= sl->where;
+ }
+
if (init_param_items(&stmt))
goto err;
+
- stmt.mem_root= stmt.thd->mem_root;
+ stmt.mem_root= stmt.thd->mem_root;
tree_insert(&thd->prepared_statements, (void *)&stmt, 0, (void *)0);
thd->mem_root= thd_root; // restore main mem_root
DBUG_RETURN(0);
@@ -919,6 +929,16 @@ 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;
+ sl;
+ sl= sl->next_select_in_list())
+ {
+ // 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);
+ }
init_stmt_execute(stmt);
if (stmt->param_count && setup_params_data(stmt))
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 3cdf033c477..229fa770b0e 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -949,6 +949,25 @@ int change_master(THD* thd, MASTER_INFO* mi)
mi->port = lex_mi->port;
if (lex_mi->connect_retry)
mi->connect_retry = lex_mi->connect_retry;
+
+ if (lex_mi->ssl != LEX_MASTER_INFO::SSL_UNCHANGED)
+ mi->ssl= (lex_mi->ssl == LEX_MASTER_INFO::SSL_ENABLE);
+ if (lex_mi->ssl_ca)
+ strmake(mi->ssl_ca, lex_mi->ssl_ca, sizeof(mi->ssl_ca)-1);
+ if (lex_mi->ssl_capath)
+ strmake(mi->ssl_capath, lex_mi->ssl_capath, sizeof(mi->ssl_capath)-1);
+ if (lex_mi->ssl_cert)
+ strmake(mi->ssl_cert, lex_mi->ssl_cert, sizeof(mi->ssl_cert)-1);
+ if (lex_mi->ssl_cipher)
+ strmake(mi->ssl_cipher, lex_mi->ssl_cipher, sizeof(mi->ssl_cipher)-1);
+ if (lex_mi->ssl_key)
+ strmake(mi->ssl_key, lex_mi->ssl_key, sizeof(mi->ssl_key)-1);
+#ifndef HAVE_OPENSSL
+ if (lex_mi->ssl || lex_mi->ssl_ca || lex_mi->ssl_capath ||
+ lex_mi->ssl_cert || lex_mi->ssl_cipher || lex_mi->ssl_key )
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_SLAVE_IGNORED_SSL_PARAMS, ER(ER_SLAVE_IGNORED_SSL_PARAMS));
+#endif
if (lex_mi->relay_log_name)
{
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 15d6b3954ff..5d96f6aeee1 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -117,10 +117,8 @@ static Item* part_of_refkey(TABLE *form,Field *field);
static uint find_shortest_key(TABLE *table, key_map usable_keys);
static bool test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,
ha_rows select_limit, bool no_changes);
-static int create_sort_index(THD *thd, JOIN_TAB *tab,ORDER *order,
+static int create_sort_index(THD *thd, JOIN *join, ORDER *order,
ha_rows filesort_limit, ha_rows select_limit);
-static int create_sort_index(THD *thd, JOIN_TAB *tab,ORDER *order,
- ha_rows select_limit);
static int remove_duplicates(JOIN *join,TABLE *entry,List<Item> &fields,
Item *having);
static int remove_dup_with_compare(THD *thd, TABLE *entry, Field **field,
@@ -326,8 +324,8 @@ JOIN::prepare(Item ***rref_pointer_array,
{
Item_subselect::trans_res res;
if ((res= subselect->select_transformer(this)) !=
- Item_subselect::OK)
- DBUG_RETURN((res == Item_subselect::ERROR));
+ Item_subselect::RES_OK)
+ DBUG_RETURN((res == Item_subselect::RES_ERROR));
}
}
@@ -916,7 +914,7 @@ JOIN::optimize()
{
DBUG_PRINT("info",("Sorting for group"));
thd->proc_info="Sorting for group";
- if (create_sort_index(thd, &join_tab[const_tables], group_list,
+ if (create_sort_index(thd, this, group_list,
HA_POS_ERROR, HA_POS_ERROR) ||
alloc_group_fields(this, group_list) ||
make_sum_func_list(all_fields, fields_list, 1))
@@ -931,7 +929,7 @@ JOIN::optimize()
{
DBUG_PRINT("info",("Sorting for order"));
thd->proc_info="Sorting for order";
- if (create_sort_index(thd, &join_tab[const_tables], order,
+ if (create_sort_index(thd, this, order,
HA_POS_ERROR, HA_POS_ERROR))
DBUG_RETURN(1);
order=0;
@@ -1005,12 +1003,6 @@ JOIN::reinit()
/* Reset of sum functions */
first_record= 0;
- if (sum_funcs)
- {
- Item_sum *func, **func_ptr= sum_funcs;
- while ((func= *(func_ptr++)))
- func->null_value= 1;
- }
if (exec_tmp_table1)
{
@@ -1045,6 +1037,7 @@ JOIN::exec()
DBUG_ENTER("JOIN::exec");
error= 0;
+ thd->limit_found_rows= thd->examined_row_count= 0;
if (procedure)
{
if (procedure->change_columns(fields_list) ||
@@ -1235,7 +1228,7 @@ JOIN::exec()
if (curr_join->group_list)
{
thd->proc_info= "Creating sort index";
- if (create_sort_index(thd, curr_join->join_tab, curr_join->group_list,
+ if (create_sort_index(thd, curr_join, curr_join->group_list,
HA_POS_ERROR, HA_POS_ERROR) ||
make_group_fields(this, curr_join))
{
@@ -1416,7 +1409,7 @@ JOIN::exec()
}
}
}
- if (create_sort_index(thd, &curr_join->join_tab[curr_join->const_tables],
+ if (create_sort_index(thd, curr_join,
curr_join->group_list ?
curr_join->group_list : curr_join->order,
curr_join->select_limit, unit->select_limit_cnt))
@@ -1427,6 +1420,8 @@ JOIN::exec()
thd->proc_info="Sending data";
error= thd->net.report_error ||
do_select(curr_join, curr_fields_list, NULL, procedure);
+ thd->limit_found_rows= curr_join->send_records;
+ thd->examined_row_count= curr_join->examined_rows;
DBUG_VOID_RETURN;
}
@@ -1549,8 +1544,6 @@ err:
(join->tmp_join->error=join->error,join->tmp_join):
join);
- thd->limit_found_rows= curr_join->send_records;
- thd->examined_row_count= curr_join->examined_rows;
thd->proc_info="end";
err= join->cleanup();
if (thd->net.report_error)
@@ -2461,7 +2454,7 @@ static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array)
Constant tables are ignored.
To avoid bad matches, we don't make ref_table_rows less than 100.
*/
- keyuse->ref_table_rows= ~(table_map) 0; // If no ref
+ keyuse->ref_table_rows= ~(ha_rows) 0; // If no ref
if (keyuse->used_tables &
(map= (keyuse->used_tables & ~join->const_table_map &
~OUTER_REF_TABLE_BIT)))
@@ -4796,7 +4789,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
keyinfo->algorithm= HA_KEY_ALG_UNDEF;
for (; group ; group=group->next,key_part_info++)
{
- Field *field=(*group->item)->tmp_table_field();
+ Field *field=(*group->item)->get_tmp_table_field();
bool maybe_null=(*group->item)->maybe_null;
key_part_info->null_bit=0;
key_part_info->field= field;
@@ -5980,8 +5973,7 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
if (!join->first_record)
{
/* No matching rows for group function */
- clear_tables(join);
- copy_fields(&join->tmp_table_param);
+ join->clear();
}
if (join->having && join->having->val_int() == 0)
error= -1; // Didn't satisfy having
@@ -6065,7 +6057,7 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
Item *item= *group->item;
if (item->maybe_null)
{
- Field *field=item->tmp_table_field();
+ Field *field=item->get_tmp_table_field();
field->ptr[-1]= (byte) (field->is_null() ? 1 : 0);
}
}
@@ -6247,8 +6239,7 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
if (!join->first_record)
{
/* No matching rows for group function */
- clear_tables(join);
- copy_fields(&join->tmp_table_param);
+ join->clear();
}
copy_sum_funcs(join->sum_funcs);
if (!join->having || join->having->val_int())
@@ -6770,16 +6761,23 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
*/
static int
-create_sort_index(THD *thd, JOIN_TAB *tab, ORDER *order,
+create_sort_index(THD *thd, JOIN *join, ORDER *order,
ha_rows filesort_limit, ha_rows select_limit)
{
SORT_FIELD *sortorder;
uint length;
ha_rows examined_rows;
- TABLE *table=tab->table;
- SQL_SELECT *select=tab->select;
+ TABLE *table;
+ SQL_SELECT *select;
+ JOIN_TAB *tab;
DBUG_ENTER("create_sort_index");
+ if (join->tables == join->const_tables)
+ DBUG_RETURN(0); // One row, no need to sort
+ tab= join->join_tab + join->const_tables;
+ table= tab->table;
+ select= tab->select;
+
if (test_if_skip_sort_order(tab,order,select_limit,0))
DBUG_RETURN(0);
if (!(sortorder=make_unireg_sortorder(order,&length)))
@@ -6928,7 +6926,7 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having)
Item *item;
while ((item=it++))
{
- if (item->tmp_table_field() && ! item->const_item())
+ if (item->get_tmp_table_field() && ! item->const_item())
field_count++;
}
@@ -7164,7 +7162,7 @@ SORT_FIELD *make_unireg_sortorder(ORDER *order, uint *length)
pos->field= ((Item_field*) (*order->item))->field;
else if (order->item[0]->type() == Item::SUM_FUNC_ITEM &&
!order->item[0]->const_item())
- pos->field= ((Item_sum*) order->item[0])->tmp_table_field();
+ pos->field= ((Item_sum*) order->item[0])->get_tmp_table_field();
else if (order->item[0]->type() == Item::COPY_STR_ITEM)
{ // Blob patch
pos->item= ((Item_copy_string*) (*order->item))->item;
@@ -7761,7 +7759,7 @@ calc_group_buffer(JOIN *join,ORDER *group)
join->group= 1;
for (; group ; group=group->next)
{
- Field *field=(*group->item)->tmp_table_field();
+ Field *field=(*group->item)->get_tmp_table_field();
if (field)
{
if (field->type() == FIELD_TYPE_BLOB)
@@ -8105,7 +8103,7 @@ change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
{
item_field= item->get_tmp_table_item(thd);
}
- else if ((field= item->tmp_table_field()))
+ else if ((field= item->get_tmp_table_field()))
{
if (item->type() == Item::SUM_FUNC_ITEM && field->table->group)
item_field= ((Item_sum*) item)->result_item(field);
@@ -8536,6 +8534,26 @@ int JOIN::rollup_send_data(uint idx)
return 0;
}
+/*
+ clear results if there are not rows found for group
+ (end_send_group/end_write_group)
+
+ SYNOPSYS
+ JOIN::clear()
+*/
+
+void JOIN::clear()
+{
+ clear_tables(this);
+ copy_fields(&tmp_table_param);
+
+ if (sum_funcs)
+ {
+ Item_sum *func, **func_ptr= sum_funcs;
+ while ((func= *(func_ptr++)))
+ func->clear();
+ }
+}
/****************************************************************************
EXPLAIN handling
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 208eaaea7bd..9ca46a505aa 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -279,6 +279,7 @@ class JOIN :public Sql_alloc
Item_sum ***func);
int rollup_send_data(uint idx);
bool test_in_subselect(Item **where);
+ void clear();
};
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 9084269f486..7dd2004b664 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -503,6 +503,8 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
item->maybe_null=1;
field_list.push_back(item=new Item_empty_string("Charset",32));
item->maybe_null=1;
+ field_list.push_back(item=new Item_int("Checksum",(longlong) 1,21));
+ item->maybe_null=1;
field_list.push_back(item=new Item_empty_string("Create_options",255));
item->maybe_null=1;
field_list.push_back(item=new Item_empty_string("Comment",80));
@@ -588,6 +590,10 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
}
str= (table->table_charset ? table->table_charset->name : "default");
protocol->store(str, system_charset_info);
+ if (file->table_flags() & HA_HAS_CHECKSUM)
+ protocol->store((ulonglong)file->checksum());
+ else
+ protocol->store_null(); // Checksum
{
char option_buff[350],*ptr;
ptr=option_buff;
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 37f8d0d7f4f..6ea7003eba6 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -350,10 +350,10 @@ static int sort_keys(KEY *a, KEY *b)
fields List of fields to create
keys List of keys to create
tmp_table Set to 1 if this is an internal temporary table
- (From ALTER TABLE)
+ (From ALTER TABLE)
no_log Don't log the query to binary log.
- DESCRIPTION
+ DESCRIPTION
If one creates a temporary table, this is automaticly opened
no_log is needed for the case of CREATE ... SELECT,
@@ -672,11 +672,11 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
/*
Make SPATIAL to be RTREE by default
SPATIAL only on BLOB or at least BINARY, this
- actually should be replaced by special GEOM type
+ actually should be replaced by special GEOM type
in near future when new frm file is ready
checking for proper key parts number:
*/
-
+
if (key_info->flags == HA_SPATIAL)
{
if (key_info->key_parts != 1)
@@ -699,7 +699,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
MYF(0), "RTREE INDEX");
DBUG_RETURN(-1);
}
-
+
List_iterator<key_part_spec> cols(key->columns);
for (uint column_nr=0 ; (column=cols++) ; column_nr++)
{
@@ -745,9 +745,9 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
{
if (!column->length )
{
- /*
+ /*
BAR: 4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case
- Lately we'll extend this code to support more dimensions
+ Lately we'll extend this code to support more dimensions
*/
column->length=4*sizeof(double);
}
@@ -798,7 +798,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
{
}
else if (column->length > length ||
- ((f_is_packed(sql_field->pack_flag) ||
+ ((f_is_packed(sql_field->pack_flag) ||
((file->table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
(key_info->flags & HA_NOSAME))) &&
column->length != length))
@@ -899,16 +899,18 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
DBUG_RETURN(-1);
}
+ if (wait_if_global_read_lock(thd, 0))
+ DBUG_RETURN(error);
VOID(pthread_mutex_lock(&LOCK_open));
if (!tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
{
if (!access(path,F_OK))
{
- VOID(pthread_mutex_unlock(&LOCK_open));
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
- DBUG_RETURN(0);
- my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
- DBUG_RETURN(-1);
+ error= 0;
+ else
+ my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
+ goto end;
}
}
@@ -946,6 +948,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
error=0;
end:
VOID(pthread_mutex_unlock(&LOCK_open));
+ start_waiting_global_read_lock(thd);
thd->proc_info="After create";
DBUG_RETURN(error);
}
@@ -2558,7 +2561,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
delete_count++;
}
else
- found_count++;
+ found_count++;
}
end_read_record(&info);
free_io_cache(from);
@@ -2590,3 +2593,103 @@ copy_data_between_tables(TABLE *from,TABLE *to,
*deleted=delete_count;
DBUG_RETURN(error > 0 ? -1 : 0);
}
+
+int mysql_checksum_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT *check_opt)
+{
+ TABLE_LIST *table;
+ List<Item> field_list;
+ Item *item;
+ Protocol *protocol= thd->protocol;
+ DBUG_ENTER("mysql_admin_table");
+
+ field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
+ item->maybe_null= 1;
+ field_list.push_back(item=new Item_int("Checksum",(longlong) 1,21));
+ item->maybe_null= 1;
+ if (protocol->send_fields(&field_list, 1))
+ DBUG_RETURN(-1);
+
+ for (table = tables; table; table = table->next)
+ {
+ char table_name[NAME_LEN*2+2];
+ char* db = (table->db) ? table->db : thd->db;
+ bool fatal_error=0;
+ TABLE *t;
+ strxmov(table_name,db ? db : "",".",table->real_name,NullS);
+
+ t=table->table = open_ltable(thd, table, TL_READ_NO_INSERT);
+#ifdef EMBEDDED_LIBRARY
+ thd->net.last_errno= 0; // these errors shouldn't get client
+#endif
+
+ protocol->prepare_for_resend();
+ protocol->store(table_name, system_charset_info);
+
+ if (!t)
+ {
+ protocol->store_null();
+ thd->net.last_error[0]=0;
+ }
+ else
+ {
+ t->pos_in_table_list= table;
+
+ if (t->file->table_flags() & HA_HAS_CHECKSUM &&
+ !(check_opt->flags & T_EXTEND))
+ protocol->store((ulonglong)t->file->checksum());
+ else if (!(t->file->table_flags() & HA_HAS_CHECKSUM) &&
+ check_opt->flags & T_QUICK)
+ protocol->store_null();
+ else
+ {
+ /* calculating table's checksum */
+ ha_checksum crc=0;
+ if (t->file->rnd_init(1))
+ protocol->store_null();
+ else
+ {
+ while (!t->file->rnd_next(t->record[0]))
+ {
+ ha_checksum row_crc=0;
+ if (t->record[0] != t->field[0]->ptr)
+ row_crc=my_checksum(row_crc, t->record[0],
+ t->field[0]->ptr - t->record[0]);
+
+ for (uint i=0; i < t->fields; i++ )
+ {
+ Field *f=t->field[i];
+ if (f->type() == FIELD_TYPE_BLOB)
+ {
+ String tmp;
+ f->val_str(&tmp,&tmp);
+ row_crc=my_checksum(row_crc, tmp.ptr(), tmp.length());
+ }
+ else
+ row_crc=my_checksum(row_crc, f->ptr, f->pack_length());
+ }
+
+ crc+=row_crc;
+ }
+ protocol->store((ulonglong)crc);
+ }
+ }
+#ifdef EMBEDDED_LIBRARY
+ thd->net.last_errno= 0; // these errors shouldn't get client
+#endif
+
+ close_thread_tables(thd);
+ table->table=0; // For query cache
+ }
+ if (protocol->write())
+ goto err;
+ }
+
+ send_eof(thd);
+ DBUG_RETURN(0);
+ err:
+ close_thread_tables(thd); // Shouldn't be needed
+ if (table)
+ table->table=0;
+ DBUG_RETURN(-1);
+}
+
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index d191550f396..99410bb34ac 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -92,10 +92,13 @@ static void init_syms(udf_func *tmp)
tmp->func_deinit = dlsym(tmp->dlhandle, nm);
if (tmp->type == UDFTYPE_AGGREGATE)
{
- (void)strmov( end, "_reset" );
- tmp->func_reset = dlsym( tmp->dlhandle, nm );
+ (void)strmov( end, "_clear" );
+ tmp->func_clear = dlsym( tmp->dlhandle, nm );
(void)strmov( end, "_add" );
tmp->func_add = dlsym( tmp->dlhandle, nm );
+ /* Give error if _clear and _add doesn't exists */
+ if (!tmp->func_clear || ! tmp->func_add)
+ tmp->func= 0;
}
}
@@ -417,7 +420,7 @@ int mysql_create_function(THD *thd,udf_func *udf)
u_d->func=udf->func;
u_d->func_init=udf->func_init;
u_d->func_deinit=udf->func_deinit;
- u_d->func_reset=udf->func_reset;
+ u_d->func_clear=udf->func_clear;
u_d->func_add=udf->func_add;
/* create entry in mysql/func table */
@@ -429,7 +432,7 @@ int mysql_create_function(THD *thd,udf_func *udf)
if (!(table = open_ltable(thd,&tables,TL_WRITE)))
goto err;
- restore_record(table,default_values); // Get default values for fields
+ restore_record(table,default_values); // Default values for fields
table->field[0]->store(u_d->name.str, u_d->name.length, system_charset_info);
table->field[1]->store((longlong) u_d->returns);
table->field[2]->store(u_d->dl,(uint) strlen(u_d->dl), system_charset_info);
diff --git a/sql/sql_udf.h b/sql/sql_udf.h
index 29a351ac52f..7b10b80f148 100644
--- a/sql/sql_udf.h
+++ b/sql/sql_udf.h
@@ -33,7 +33,7 @@ typedef struct st_udf_func
void *func;
void *func_init;
void *func_deinit;
- void *func_reset;
+ void *func_clear;
void *func_add;
ulong usage_count;
} udf_func;
@@ -49,7 +49,7 @@ class udf_handler :public Sql_alloc
UDF_ARGS f_args;
UDF_INIT initid;
char *num_buffer;
- uchar error;
+ uchar error, is_null;
bool initialized;
Item **args;
@@ -57,7 +57,7 @@ class udf_handler :public Sql_alloc
table_map used_tables_cache;
bool const_item_cache;
udf_handler(udf_func *udf_arg) :u_d(udf_arg), buffers(0), error(0),
- initialized(0)
+ is_null(0), initialized(0)
{}
~udf_handler();
const char *name() const { return u_d ? u_d->name.str : "?"; }
@@ -73,7 +73,6 @@ class udf_handler :public Sql_alloc
*null_value=1;
return 0.0;
}
- uchar is_null=0;
double (*func)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *)=
(double (*)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *)) u_d->func;
double tmp=func(&initid, &f_args, &is_null, &error);
@@ -92,7 +91,6 @@ class udf_handler :public Sql_alloc
*null_value=1;
return LL(0);
}
- uchar is_null=0;
longlong (*func)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *)=
(longlong (*)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *)) u_d->func;
longlong tmp=func(&initid, &f_args, &is_null, &error);
@@ -104,22 +102,15 @@ class udf_handler :public Sql_alloc
*null_value=0;
return tmp;
}
- void reset(my_bool *null_value)
+ void clear()
{
- uchar is_null=0;
- if (get_arguments())
- {
- *null_value=1;
- return;
- }
- void (*func)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *)=
- (void (*)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *)) u_d->func_reset;
- func(&initid, &f_args, &is_null, &error);
- *null_value= (my_bool) (is_null || error);
+ is_null= 0;
+ void (*func)(UDF_INIT *, uchar *, uchar *)=
+ (void (*)(UDF_INIT *, uchar *, uchar *)) u_d->func_clear;
+ func(&initid, &is_null, &error);
}
void add(my_bool *null_value)
{
- uchar is_null=0;
if (get_arguments())
{
*null_value=1;
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index ae91b0b3ace..55f697e9981 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -116,7 +116,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result,
bool tables_and_fields_initied)
{
SELECT_LEX *lex_select_save= thd->lex.current_select;
- SELECT_LEX *select_cursor;
+ SELECT_LEX *select_cursor,*sl;
DBUG_ENTER("st_select_lex_unit::prepare");
if (prepared)
@@ -130,7 +130,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result,
t_and_f= tables_and_fields_initied;
bzero((char *)&tmp_table_param,sizeof(TMP_TABLE_PARAM));
- thd->lex.current_select= select_cursor= first_select_in_union();
+ thd->lex.current_select= sl= select_cursor= first_select_in_union();
/* Global option */
if (t_and_f)
{
@@ -185,7 +185,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result,
union_result->not_describe=1;
union_result->tmp_table_param=tmp_table_param;
- for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select())
+ for (;sl; sl= sl->next_select())
{
JOIN *join= new JOIN(thd, sl->item_list,
sl->options | thd->options | SELECT_NO_UNLOCK,
@@ -195,7 +195,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result,
select_limit_cnt= sl->select_limit+sl->offset_limit;
if (select_limit_cnt < sl->select_limit)
select_limit_cnt= HA_POS_ERROR; // no limit
- if (select_limit_cnt == HA_POS_ERROR && !sl->braces)
+ if (select_limit_cnt == HA_POS_ERROR || sl->braces)
sl->options&= ~OPTION_FOUND_ROWS;
res= join->prepare(&sl->ref_pointer_array,
@@ -256,7 +256,7 @@ int st_select_lex_unit::exec()
}
for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select())
{
- ha_rows rows= 0;
+ ha_rows records_at_start= 0;
thd->lex.current_select= sl;
if (optimized)
@@ -267,12 +267,15 @@ int st_select_lex_unit::exec()
select_limit_cnt= sl->select_limit+sl->offset_limit;
if (select_limit_cnt < sl->select_limit)
select_limit_cnt= HA_POS_ERROR; // no limit
- if (select_limit_cnt == HA_POS_ERROR)
+ if (select_limit_cnt == HA_POS_ERROR || sl->braces)
sl->options&= ~OPTION_FOUND_ROWS;
- else if (found_rows_for_union)
+ else
{
- rows= sl->select_limit;
- sl->options|= OPTION_FOUND_ROWS;
+ /*
+ We are doing an union without braces. In this case
+ SQL_CALC_FOUND_ROWS should be done on all sub parts
+ */
+ sl->options|= found_rows_for_union;
}
/*
@@ -301,6 +304,7 @@ int st_select_lex_unit::exec()
}
if (!res)
{
+ records_at_start= table->file->records;
sl->join->exec();
res= sl->join->error;
if (!res && union_result->flush())
@@ -314,10 +318,17 @@ int st_select_lex_unit::exec()
thd->lex.current_select= lex_select_save;
DBUG_RETURN(res);
}
- if (found_rows_for_union && !sl->braces &&
- (sl->options & OPTION_FOUND_ROWS))
- add_rows+= (sl->join->send_records > rows) ?
- sl->join->send_records - rows : 0;
+ if (found_rows_for_union & sl->options)
+ {
+ /*
+ This is a union without braces. Remember the number of rows that could
+ also have been part of the result set.
+ We get this from the difference of between total number of possible
+ rows and actual rows added to the temporary table.
+ */
+ add_rows+= (ha_rows) (thd->limit_found_rows - (ulonglong)
+ ((table->file->records - records_at_start)));
+ }
}
}
optimized= 1;
@@ -382,12 +393,8 @@ int st_select_lex_unit::exec()
(ORDER*) NULL, NULL, (ORDER*) NULL,
options | SELECT_NO_UNLOCK,
result, this, fake_select_lex, 0);
- if (found_rows_for_union && !res)
- {
- thd->limit_found_rows= table->file->records;
- if (!select_cursor->braces)
- thd->limit_found_rows+= add_rows;
- }
+ if (!res)
+ thd->limit_found_rows = (ulonglong)table->file->records + add_rows;
/*
Mark for slow query log if any of the union parts didn't use
indexes efficiently
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 539bb90d907..b84a21b1440 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -277,6 +277,12 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token MASTER_PORT_SYM
%token MASTER_CONNECT_RETRY_SYM
%token MASTER_SERVER_ID_SYM
+%token MASTER_SSL_SYM
+%token MASTER_SSL_CA_SYM
+%token MASTER_SSL_CAPATH_SYM
+%token MASTER_SSL_CERT_SYM
+%token MASTER_SSL_CIPHER_SYM
+%token MASTER_SSL_KEY_SYM
%token RELAY_LOG_FILE_SYM
%token RELAY_LOG_POS_SYM
%token MATCH
@@ -500,6 +506,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token MULTIPOINT
%token MULTIPOLYGON
%token NOW_SYM
+%token OLD_PASSWORD
%token PASSWORD
%token POINTFROMTEXT
%token POINT_SYM
@@ -671,7 +678,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
show describe load alter optimize preload flush
reset purge begin commit rollback savepoint
slave master_def master_defs
- repair restore backup analyze check start
+ repair restore backup analyze check start checksum
field_list field_list_item field_spec kill column_def key_def
preload_list preload_keys
select_item_list select_item values_list no_braces
@@ -729,23 +736,26 @@ verb_clause:
| begin
| change
| check
+ | checksum
| commit
| create
| delete
| describe
| do
| drop
+ | flush
| grant
+ | handler
+ | help
| insert
- | flush
+ | kill
| load
| lock
- | kill
| optimize
| preload
| purge
| rename
- | repair
+ | repair
| replace
| reset
| restore
@@ -754,15 +764,14 @@ verb_clause:
| savepoint
| select
| set
+ | show
| slave
| start
- | show
| truncate
- | handler
| unlock
| update
| use
- | help;
+ ;
/* help */
@@ -850,6 +859,31 @@ master_def:
/* Adjust if < BIN_LOG_HEADER_SIZE (same comment as Lex->mi.pos) */
Lex->mi.relay_log_pos = max(BIN_LOG_HEADER_SIZE, Lex->mi.relay_log_pos);
}
+ | MASTER_SSL_SYM EQ ULONG_NUM
+ {
+ Lex->mi.ssl= $3 ?
+ LEX_MASTER_INFO::SSL_ENABLE : LEX_MASTER_INFO::SSL_DISABLE;
+ }
+ | MASTER_SSL_CA_SYM EQ TEXT_STRING_sys
+ {
+ Lex->mi.ssl_ca= $3.str;
+ }
+ | MASTER_SSL_CAPATH_SYM EQ TEXT_STRING_sys
+ {
+ Lex->mi.ssl_capath= $3.str;
+ }
+ | MASTER_SSL_CERT_SYM EQ TEXT_STRING_sys
+ {
+ Lex->mi.ssl_cert= $3.str;
+ }
+ | MASTER_SSL_CIPHER_SYM EQ TEXT_STRING_sys
+ {
+ Lex->mi.ssl_cipher= $3.str;
+ }
+ | MASTER_SSL_KEY_SYM EQ TEXT_STRING_sys
+ {
+ Lex->mi.ssl_key= $3.str;
+ }
;
@@ -1099,7 +1133,7 @@ opt_select_from:
| select_from select_lock_type;
udf_func_type:
- /* empty */ { $$ = UDFTYPE_FUNCTION; }
+ /* empty */ { $$ = UDFTYPE_FUNCTION; }
| AGGREGATE_SYM { $$ = UDFTYPE_AGGREGATE; };
udf_type:
@@ -1566,7 +1600,7 @@ opt_ident:
opt_component:
/* empty */ { $$.str= 0; $$.length= 0; }
| '.' ident { $$=$2; };
-
+
string_list:
text_string { Lex->interval_list.push_back($1); }
| string_list ',' text_string { Lex->interval_list.push_back($3); };
@@ -1773,6 +1807,22 @@ backup:
Lex->backup_dir = $6.str;
};
+checksum:
+ CHECKSUM_SYM table_or_tables
+ {
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_CHECKSUM;
+ }
+ table_list opt_checksum_type
+ {}
+ ;
+
+opt_checksum_type:
+ /* nothing */ { Lex->check_opt.flags= 0; }
+ | QUICK { Lex->check_opt.flags= T_QUICK; }
+ | EXTENDED_SYM { Lex->check_opt.flags= T_EXTEND; }
+ ;
+
repair:
REPAIR opt_no_write_to_binlog table_or_tables
{
@@ -1962,8 +2012,9 @@ select_init:
YYABORT;
}
/* select in braces, can't contain global parameters */
- sel->master_unit()->global_parameters=
- sel->master_unit()->fake_select_lex;
+ if (sel->master_unit()->fake_select_lex)
+ sel->master_unit()->global_parameters=
+ sel->master_unit()->fake_select_lex;
} union_opt;
select_init2:
@@ -2576,9 +2627,13 @@ simple_expr:
| NOW_SYM '(' expr ')'
{ $$= new Item_func_now_local($3); Lex->safe_to_cache_query=0;}
| PASSWORD '(' expr ')'
- { $$= new Item_func_password($3); }
- | PASSWORD '(' expr ',' expr ')'
- { $$= new Item_func_password($3,$5); }
+ {
+ $$= YYTHD->variables.old_passwords ?
+ (Item *) new Item_func_old_password($3) :
+ (Item *) new Item_func_password($3);
+ }
+ | OLD_PASSWORD '(' expr ')'
+ { $$= new Item_func_old_password($3); }
| POINT_SYM '(' expr ',' expr ')'
{ $$= new Item_func_point($3,$5); }
| POINTFROMTEXT '(' expr ')'
@@ -3382,7 +3437,7 @@ do: DO_SYM
*/
drop:
- DROP opt_temporary TABLE_SYM if_exists table_list opt_restrict
+ DROP opt_temporary table_or_tables if_exists table_list opt_restrict
{
LEX *lex=Lex;
lex->sql_command = SQLCOM_DROP_TABLE;
@@ -4380,6 +4435,7 @@ keyword:
| BOOL_SYM {}
| BOOLEAN_SYM {}
| BYTE_SYM {}
+ | BTREE_SYM {}
| CACHE_SYM {}
| CHANGED {}
| CHARSET {}
@@ -4408,6 +4464,7 @@ keyword:
| DYNAMIC_SYM {}
| END {}
| ENUM {}
+ | ERRORS {}
| ESCAPE_SYM {}
| EVENTS_SYM {}
| EXECUTE_SYM {}
@@ -4425,6 +4482,7 @@ keyword:
| GRANTS {}
| GLOBAL_SYM {}
| HANDLER_SYM {}
+ | HASH_SYM {}
| HEAP_SYM {}
| HELP_SYM {}
| HOSTS_SYM {}
@@ -4453,6 +4511,12 @@ keyword:
| MASTER_USER_SYM {}
| MASTER_PASSWORD_SYM {}
| MASTER_CONNECT_RETRY_SYM {}
+ | MASTER_SSL_SYM {}
+ | MASTER_SSL_CA_SYM {}
+ | MASTER_SSL_CAPATH_SYM {}
+ | MASTER_SSL_CERT_SYM {}
+ | MASTER_SSL_CIPHER_SYM {}
+ | MASTER_SSL_KEY_SYM {}
| MAX_CONNECTIONS_PER_HOUR {}
| MAX_QUERIES_PER_HOUR {}
| MAX_UPDATES_PER_HOUR {}
@@ -4477,6 +4541,7 @@ keyword:
| NO_SYM {}
| NONE_SYM {}
| OFFSET_SYM {}
+ | OLD_PASSWORD {}
| OPEN_SYM {}
| PACK_KEYS_SYM {}
| PARTIAL {}
@@ -4507,6 +4572,7 @@ keyword:
| ROWS_SYM {}
| ROW_FORMAT_SYM {}
| ROW_SYM {}
+ | RTREE_SYM {}
| SAVEPOINT_SYM {}
| SECOND_SYM {}
| SERIAL_SYM {}
@@ -4543,6 +4609,7 @@ keyword:
| USE_FRM {}
| VARIABLES {}
| VALUE_SYM {}
+ | WARNINGS {}
| WORK_SYM {}
| X509_SYM {}
| YEAR_SYM {}
@@ -4699,15 +4766,15 @@ text_or_password:
TEXT_STRING { $$=$1.str;}
| PASSWORD '(' TEXT_STRING ')'
{
- if (!$3.length)
- $$=$3.str;
- else
- {
- char *buff=(char*) YYTHD->alloc(HASH_PASSWORD_LENGTH+1);
- make_scrambled_password(buff,$3.str,use_old_passwords,
- &YYTHD->rand);
- $$=buff;
- }
+ $$= $3.length ? YYTHD->variables.old_passwords ?
+ Item_func_old_password::alloc(YYTHD, $3.str) :
+ Item_func_password::alloc(YYTHD, $3.str) :
+ $3.str;
+ }
+ | OLD_PASSWORD '(' TEXT_STRING ')'
+ {
+ $$= $3.length ? Item_func_old_password::alloc(YYTHD, $3.str) :
+ $3.str;
}
;
@@ -4883,7 +4950,7 @@ grant_privilege_list:
| grant_privilege_list ',' grant_privilege;
grant_privilege:
- SELECT_SYM { Lex->which_columns = SELECT_ACL;} opt_column_list {}
+ SELECT_SYM { Lex->which_columns = SELECT_ACL;} opt_column_list {}
| INSERT { Lex->which_columns = INSERT_ACL;} opt_column_list {}
| UPDATE_SYM { Lex->which_columns = UPDATE_ACL; } opt_column_list {}
| REFERENCES { Lex->which_columns = REFERENCES_ACL;} opt_column_list {}
@@ -5015,14 +5082,24 @@ grant_user:
$$=$1; $1->password=$4;
if ($4.length)
{
- char *buff=(char*) YYTHD->alloc(HASH_PASSWORD_LENGTH+1);
- if (buff)
- {
- make_scrambled_password(buff,$4.str,use_old_passwords,
- &YYTHD->rand);
- $1->password.str=buff;
- $1->password.length=HASH_PASSWORD_LENGTH;
- }
+ if (YYTHD->variables.old_passwords)
+ {
+ char *buff=
+ (char *) YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH_323+1);
+ if (buff)
+ make_scrambled_password_323(buff, $4.str);
+ $1->password.str= buff;
+ $1->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
+ }
+ else
+ {
+ char *buff=
+ (char *) YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1);
+ if (buff)
+ make_scrambled_password(buff, $4.str);
+ $1->password.str= buff;
+ $1->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH;
+ }
}
}
| user IDENTIFIED_SYM BY PASSWORD TEXT_STRING
@@ -5181,7 +5258,7 @@ union_opt:
;
optional_order_or_limit:
- /* Empty */ {}
+ /* Empty */ {}
|
{
THD *thd= YYTHD;
@@ -5276,3 +5353,4 @@ subselect_end:
LEX *lex=Lex;
lex->current_select = lex->current_select->return_after_parsing();
};
+
diff --git a/sql/table.cc b/sql/table.cc
index 9d12de1f6c7..a980e086d60 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -1207,17 +1207,14 @@ bool get_field(MEM_ROOT *mem, Field *field, String *res)
char *get_field(MEM_ROOT *mem, Field *field)
{
- char buff[MAX_FIELD_WIDTH], *to;
+ char buff[MAX_FIELD_WIDTH];
String str(buff,sizeof(buff),&my_charset_bin);
uint length;
field->val_str(&str,&str);
if (!(length= str.length()))
return NullS;
- to= (char*) alloc_root(mem,length+1);
- memcpy(to, str.ptr(), (uint) length);
- to[length]=0;
- return to;
+ return strmake_root(mem, str.ptr(), length);
}
diff --git a/sql/udf_example.cc b/sql/udf_example.cc
index 7f4417bf8fe..ba056a9d2fd 100644
--- a/sql/udf_example.cc
+++ b/sql/udf_example.cc
@@ -149,6 +149,7 @@ longlong sequence(UDF_INIT *initid, UDF_ARGS *args, char *is_null,
my_bool avgcost_init( UDF_INIT* initid, UDF_ARGS* args, char* message );
void avgcost_deinit( UDF_INIT* initid );
void avgcost_reset( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error );
+void avgcost_clear( UDF_INIT* initid, char* is_null, char *error );
void avgcost_add( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error );
double avgcost( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error );
}
@@ -902,21 +903,29 @@ avgcost_deinit( UDF_INIT* initid )
delete initid->ptr;
}
+
+/* This is only for MySQL 4.0 compability */
void
-avgcost_reset( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* message )
+avgcost_reset(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* message)
{
- struct avgcost_data* data = (struct avgcost_data*)initid->ptr;
- data->totalprice = 0.0;
- data->totalquantity = 0;
- data->count = 0;
+ avgcost_clear(initid, is_null, message);
+ avgcost_add(initid, args, is_null, message);
+}
- *is_null = 0;
- avgcost_add( initid, args, is_null, message );
+/* This is needed to get things to work in MySQL 4.1.1 and above */
+
+void
+avgcost_clear(UDF_INIT* initid, char* is_null, char* message)
+{
+ struct avgcost_data* data = (struct avgcost_data*)initid->ptr;
+ data->totalprice= 0.0;
+ data->totalquantity= 0;
+ data->count= 0;
}
void
-avgcost_add( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* message )
+avgcost_add(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* message)
{
if (args->args[0] && args->args[1])
{
diff --git a/tests/client_test.c b/tests/client_test.c
index 6aeb865aa20..c2bc966fee8 100644
--- a/tests/client_test.c
+++ b/tests/client_test.c
@@ -1717,7 +1717,7 @@ static void test_select()
rc = mysql_commit(mysql);
myquery(rc);
- /* now insert the second row, and rollback the transaction */
+ /* now insert the second row, and rollback the transaction */
rc = mysql_query(mysql,"INSERT INTO test_select VALUES(20,'mysql')");
myquery(rc);
@@ -1755,6 +1755,168 @@ static void test_select()
mysql_stmt_close(stmt);
}
+/*
+ test BUG#1115 (incorrect string parameter value allocation)
+*/
+static void test_bug1115()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ MYSQL_BIND bind[1];
+ ulong length[1];
+ char szData[11];
+ int nData=1;
+
+ myheader("test_bug1115");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_select");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_select(\
+session_id char(9) NOT NULL, \
+ a int(8) unsigned NOT NULL, \
+ b int(5) NOT NULL, \
+ c int(5) NOT NULL, \
+ d datetime NOT NULL)");
+ myquery(rc);
+ rc = mysql_query(mysql,"INSERT INTO test_select VALUES (\"abc\",1,2,3,2003-08-30), (\"abd\",1,2,3,2003-08-30), (\"abf\",1,2,3,2003-08-30), (\"abg\",1,2,3,2003-08-30), (\"abh\",1,2,3,2003-08-30), (\"abj\",1,2,3,2003-08-30), (\"abk\",1,2,3,2003-08-30), (\"abl\",1,2,3,2003-08-30), (\"abq\",1,2,3,2003-08-30), (\"abw\",1,2,3,2003-08-30), (\"abe\",1,2,3,2003-08-30), (\"abr\",1,2,3,2003-08-30), (\"abt\",1,2,3,2003-08-30), (\"aby\",1,2,3,2003-08-30), (\"abu\",1,2,3,2003-08-30), (\"abi\",1,2,3,2003-08-30), (\"abo\",1,2,3,2003-08-30), (\"abp\",1,2,3,2003-08-30), (\"abz\",1,2,3,2003-08-30), (\"abx\",1,2,3,2003-08-30)");
+ myquery(rc);
+
+ strmov(query,"SELECT * FROM test_select WHERE session_id = ?");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,1);
+
+ strmov(szData,(char *)"abc");
+ bind[0].buffer_type=FIELD_TYPE_STRING;
+ bind[0].buffer=(char *)szData;
+ bind[0].buffer_length= 10;
+ bind[0].length= &length[0];
+ length[0]= 3;
+ bind[0].is_null=0;
+
+ rc = mysql_bind_param(stmt,bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ myassert(my_process_stmt_result(stmt) == 1);
+
+ strmov(szData,(char *)"venu");
+ bind[0].buffer_type=FIELD_TYPE_STRING;
+ bind[0].buffer=(char *)szData;
+ bind[0].buffer_length= 10;
+ bind[0].length= &length[0];
+ length[0]= 4;
+ bind[0].is_null=0;
+
+ rc = mysql_bind_param(stmt,bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ myassert(my_process_stmt_result(stmt) == 0);
+
+ strmov(szData,(char *)"abc");
+ bind[0].buffer_type=FIELD_TYPE_STRING;
+ bind[0].buffer=(char *)szData;
+ bind[0].buffer_length= 10;
+ bind[0].length= &length[0];
+ length[0]= 3;
+ bind[0].is_null=0;
+
+ rc = mysql_bind_param(stmt,bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ myassert(my_process_stmt_result(stmt) == 1);
+
+ mysql_stmt_close(stmt);
+}
+
+/*
+ test BUG#1180 (optimized away part of WHERE clause)
+*/
+static void test_bug1180()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ MYSQL_BIND bind[1];
+ ulong length[1];
+ char szData[11];
+ int nData=1;
+
+ myheader("test_select_bug");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_select");
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_select(session_id char(9) NOT NULL)");
+ myquery(rc);
+ rc = mysql_query(mysql,"INSERT INTO test_select VALUES (\"abc\")");
+ myquery(rc);
+
+ strmov(query,"SELECT * FROM test_select WHERE ?=\"1111\" and session_id = \"abc\"");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,1);
+
+ strmov(szData,(char *)"abc");
+ bind[0].buffer_type=FIELD_TYPE_STRING;
+ bind[0].buffer=(char *)szData;
+ bind[0].buffer_length= 10;
+ bind[0].length= &length[0];
+ length[0]= 3;
+ bind[0].is_null=0;
+
+ rc = mysql_bind_param(stmt,bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ myassert(my_process_stmt_result(stmt) == 0);
+
+ strmov(szData,(char *)"1111");
+ bind[0].buffer_type=FIELD_TYPE_STRING;
+ bind[0].buffer=(char *)szData;
+ bind[0].buffer_length= 10;
+ bind[0].length= &length[0];
+ length[0]= 4;
+ bind[0].is_null=0;
+
+ rc = mysql_bind_param(stmt,bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ myassert(my_process_stmt_result(stmt) == 1);
+
+ strmov(szData,(char *)"abc");
+ bind[0].buffer_type=FIELD_TYPE_STRING;
+ bind[0].buffer=(char *)szData;
+ bind[0].buffer_length= 10;
+ bind[0].length= &length[0];
+ length[0]= 3;
+ bind[0].is_null=0;
+
+ rc = mysql_bind_param(stmt,bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ myassert(my_process_stmt_result(stmt) == 0);
+
+ mysql_stmt_close(stmt);
+}
/********************************************************
* to test simple select show *
@@ -5896,7 +6058,7 @@ static void test_field_misc()
"@@table_type","", /* field and its org name */
MYSQL_TYPE_STRING, /* field type */
"", "", /* table and its org name */
- "",type_length,0); /* db name, length */
+ "",type_length*3,0); /* db name, length */
mysql_free_result(result);
mysql_stmt_close(stmt);
@@ -7814,6 +7976,8 @@ int main(int argc, char **argv)
test_fetch_column(); /* to test mysql_fetch_column */
test_sqlmode(); /* test for SQL_MODE */
test_ts(); /* test for timestamp BR#819 */
+ test_bug1115(); /* BUG#1115 */
+ test_bug1180(); /* BUG#1180 */
end_time= time((time_t *)0);
total_time+= difftime(end_time, start_time);