diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index ef063bd6ab7..543e9e677a2 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -48,6 +48,7 @@ dlenev@build.mysql.com dlenev@jabberwock.localdomain dlenev@mysql.com ejonore@mc03.ndb.mysql.com +gbichot@production.mysql.com gbichot@quadita2.mysql.com gbichot@quadxeon.mysql.com georg@beethoven.local diff --git a/Docs/mysqld_error.txt b/Docs/mysqld_error.txt index 6370d8aac46..7f5560a5914 100644 --- a/Docs/mysqld_error.txt +++ b/Docs/mysqld_error.txt @@ -595,3 +595,5 @@ character-set=latin1 "Invalid ON UPDATE clause for '%-.64s' field", #define ER_UNSUPPORTED_PS 1295 "This command is not supported in the prepared statement protocol yet", +#define ER_CANT_CREATE_USER_WITH_GRANT 1296 +"You are not allowed to create a user with GRANT" diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index c296447def9..59c90f59e8e 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -33,9 +33,9 @@ #undef MYSQL_SERVER #include "client_priv.h" #include -#include "log_event.h" /* That one is necessary for defines of OPTION_NO_FOREIGN_KEY_CHECKS etc */ #include "mysql_priv.h" +#include "log_event.h" #define BIN_LOG_HEADER_SIZE 4 #define PROBE_HEADER_LEN (EVENT_LEN_OFFSET+4) diff --git a/client/mysqldump.c b/client/mysqldump.c index 46337c99732..867aa86c1fc 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1093,7 +1093,7 @@ static void print_xml_row(FILE *xml_file, const char *row_name, number of fields in table, 0 if error */ -static uint getTableStructure(char *table, char* db) +static uint getTableStructure(char *table, char *db) { MYSQL_RES *tableRes; MYSQL_ROW row; @@ -1396,10 +1396,9 @@ static uint getTableStructure(char *table, char* db) /* Get MySQL specific create options */ if (create_options) { - char show_name_buff[FN_REFLEN]; + char show_name_buff[NAME_LEN*2+2+24]; /* Check memory for quote_for_like() */ - DBUG_ASSERT(2*sizeof(table) < sizeof(show_name_buff)); my_snprintf(buff, sizeof(buff), "show table status like %s", quote_for_like(table, show_name_buff)); diff --git a/configure.in b/configure.in index b2a8e9ebe70..79750496d2f 100644 --- a/configure.in +++ b/configure.in @@ -6,7 +6,7 @@ AC_PREREQ(2.50)dnl Minimum Autoconf version required. AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # Don't forget to also update the NDB lines below. -AM_INIT_AUTOMAKE(mysql, 5.0.3-alpha) +AM_INIT_AUTOMAKE(mysql, 5.0.3-beta) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 @@ -18,7 +18,7 @@ SHARED_LIB_VERSION=14:0:0 NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 NDB_VERSION_BUILD=3 -NDB_VERSION_STATUS="alpha" +NDB_VERSION_STATUS="beta" # Set all version vars based on $VERSION. How do we do this more elegant ? # Remember that regexps needs to quote [ and ] since this is run through m4 diff --git a/include/config-netware.h b/include/config-netware.h index e84fd6ae472..4a6dc3b1bb9 100644 --- a/include/config-netware.h +++ b/include/config-netware.h @@ -80,6 +80,9 @@ extern "C" { /* On NetWare, stack grows towards lower address*/ #define STACK_DIRECTION -1 +/* On NetWare, to fix the problem with the deletion of open files */ +#define CANT_DELETE_OPEN_FILES 1 + /* default directory information */ #define DEFAULT_MYSQL_HOME "sys:/mysql" #define PACKAGE "mysql" diff --git a/include/decimal.h b/include/decimal.h index 3f4a2122c57..7b49841ca88 100644 --- a/include/decimal.h +++ b/include/decimal.h @@ -20,47 +20,50 @@ typedef enum {TRUNCATE=0, HALF_EVEN, HALF_UP, CEILING, FLOOR} decimal_round_mode; -typedef int32 decimal_digit; +typedef int32 decimal_digit_t; -typedef struct st_decimal { +typedef struct st_decimal_t { int intg, frac, len; my_bool sign; - decimal_digit *buf; -} decimal; + decimal_digit_t *buf; +} decimal_t; -int internal_str2dec(const char *from, decimal *to, char **end, my_bool fixed); -int decimal2string(decimal *from, char *to, int *to_len, +int internal_str2dec(const char *from, decimal_t *to, char **end, + my_bool fixed); +int decimal2string(decimal_t *from, char *to, int *to_len, int fixed_precision, int fixed_decimals, char filler); -int decimal2ulonglong(decimal *from, ulonglong *to); -int ulonglong2decimal(ulonglong from, decimal *to); -int decimal2longlong(decimal *from, longlong *to); -int longlong2decimal(longlong from, decimal *to); -int decimal2double(decimal *from, double *to); -int double2decimal(double from, decimal *to); -void decimal_optimize_fraction(decimal *from); -int decimal2bin(decimal *from, char *to, int precision, int scale); -int bin2decimal(char *from, decimal *to, int precision, int scale); +int decimal2ulonglong(decimal_t *from, ulonglong *to); +int ulonglong2decimal(ulonglong from, decimal_t *to); +int decimal2longlong(decimal_t *from, longlong *to); +int longlong2decimal(longlong from, decimal_t *to); +int decimal2double(decimal_t *from, double *to); +int double2decimal(double from, decimal_t *to); +void decimal_optimize_fraction(decimal_t *from); +int decimal2bin(decimal_t *from, char *to, int precision, int scale); +int bin2decimal(char *from, decimal_t *to, int precision, int scale); int decimal_size(int precision, int scale); int decimal_bin_size(int precision, int scale); -int decimal_result_size(decimal *from1, decimal *from2, char op, int param); +int decimal_result_size(decimal_t *from1, decimal_t *from2, char op, + int param); -int decimal_add(decimal *from1, decimal *from2, decimal *to); -int decimal_sub(decimal *from1, decimal *from2, decimal *to); -int decimal_cmp(decimal *from1, decimal *from2); -int decimal_mul(decimal *from1, decimal *from2, decimal *to); -int decimal_div(decimal *from1, decimal *from2, decimal *to, int scale_incr); -int decimal_mod(decimal *from1, decimal *from2, decimal *to); -int decimal_round(decimal *from, decimal *to, int new_scale, +int decimal_add(decimal_t *from1, decimal_t *from2, decimal_t *to); +int decimal_sub(decimal_t *from1, decimal_t *from2, decimal_t *to); +int decimal_cmp(decimal_t *from1, decimal_t *from2); +int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to); +int decimal_div(decimal_t *from1, decimal_t *from2, decimal_t *to, + int scale_incr); +int decimal_mod(decimal_t *from1, decimal_t *from2, decimal_t *to); +int decimal_round(decimal_t *from, decimal_t *to, int new_scale, decimal_round_mode mode); -int decimal_is_zero(decimal *from); -void max_decimal(int precision, int frac, decimal *to); +int decimal_is_zero(decimal_t *from); +void max_decimal(int precision, int frac, decimal_t *to); #define string2decimal(A,B,C) internal_str2dec((A), (B), (C), 0) #define string2decimal_fixed(A,B,C) internal_str2dec((A), (B), (C), 1) -/* set a decimal to zero */ +/* set a decimal_t to zero */ #define decimal_make_zero(dec) do { \ (dec)->buf[0]=0; \ diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h index 64e9c87fbbd..d46613c3a68 100644 --- a/innobase/include/trx0trx.h +++ b/innobase/include/trx0trx.h @@ -381,6 +381,12 @@ struct trx_struct{ in MySQL's binlog write, we will flush the log to disk later in a separate call */ + ibool must_flush_log_later;/* this flag is set to TRUE in + trx_commit_off_kernel() if + flush_log_later was TRUE, and there + were modifications by the transaction; + in that case we must flush the log + in trx_commit_complete_for_mysql() */ dulint commit_lsn; /* lsn at the time of the commit */ ibool dict_operation; /* TRUE if the trx is used to create a table, create an index, or drop a diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c index 643f7e164e5..cdda1dd4dee 100644 --- a/innobase/trx/trx0trx.c +++ b/innobase/trx/trx0trx.c @@ -99,6 +99,7 @@ trx_create( trx->check_unique_secondary = TRUE; trx->flush_log_later = FALSE; + trx->must_flush_log_later = FALSE; trx->dict_operation = FALSE; @@ -710,6 +711,8 @@ trx_commit_off_kernel( ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ + trx->must_flush_log_later = FALSE; + rseg = trx->rseg; if (trx->insert_undo != NULL || trx->update_undo != NULL) { @@ -875,6 +878,7 @@ trx_commit_off_kernel( if (trx->flush_log_later) { /* Do nothing yet */ + trx->must_flush_log_later = TRUE; } else if (srv_flush_log_at_trx_commit == 0) { /* Do nothing */ } else if (srv_flush_log_at_trx_commit == 1) { @@ -1594,7 +1598,9 @@ trx_commit_complete_for_mysql( trx->op_info = "flushing log"; - if (srv_flush_log_at_trx_commit == 0) { + if (!trx->must_flush_log_later) { + /* Do nothing */ + } else if (srv_flush_log_at_trx_commit == 0) { /* Do nothing */ } else if (srv_flush_log_at_trx_commit == 1) { if (srv_unix_file_flush_method == SRV_UNIX_NOSYNC) { @@ -1615,6 +1621,8 @@ trx_commit_complete_for_mysql( } else { ut_error; } + + trx->must_flush_log_later = FALSE; trx->op_info = ""; diff --git a/mysql-test/lib/init_db.sql b/mysql-test/lib/init_db.sql index 902af0b0842..e3bf669db4e 100644 --- a/mysql-test/lib/init_db.sql +++ b/mysql-test/lib/init_db.sql @@ -16,6 +16,11 @@ CREATE TABLE db ( Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db,User), KEY User (User) ) engine=MyISAM @@ -23,8 +28,8 @@ CHARACTER SET utf8 COLLATE utf8_bin comment='Database privileges'; -INSERT INTO db VALUES ('%','test' ,'','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y'); -INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y'); +INSERT INTO db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N'); +INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N'); CREATE TABLE host ( @@ -42,6 +47,8 @@ CREATE TABLE host ( Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin @@ -73,6 +80,10 @@ CREATE TABLE user ( Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, @@ -80,15 +91,16 @@ CREATE TABLE user ( max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, + max_user_connections int(11) unsigned DEFAULT 0 NOT NULL, PRIMARY KEY Host (Host,User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges'; -INSERT INTO user VALUES ('localhost' ,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); -INSERT INTO user VALUES ('@HOSTNAME@%','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); -REPLACE INTO user VALUES ('127.0.0.1' ,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); +INSERT INTO user VALUES ('localhost' ,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0); +INSERT INTO user VALUES ('@HOSTNAME@%' ,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0); +REPLACE INTO user VALUES ('127.0.0.1' ,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0); INSERT INTO user (host,user) VALUES ('localhost',''); INSERT INTO user (host,user) VALUES ('@HOSTNAME@%',''); @@ -468,3 +480,74 @@ INSERT INTO time_zone_leap_second ( ,(662688015, 16) ,(709948816, 17) ,(741484817, 18) ,(773020818, 19) ,(820454419, 20) ,(867715220, 21) ,(915148821, 22); + + +CREATE TABLE procs_priv ( + Host char(60) binary DEFAULT '' NOT NULL, + Db char(64) binary DEFAULT '' NOT NULL, + User char(16) binary DEFAULT '' NOT NULL, + Routine_name char(64) binary DEFAULT '' NOT NULL, + Grantor char(77) DEFAULT '' NOT NULL, + Timestamp timestamp(14), + Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, + PRIMARY KEY (Host,Db,User,Routine_name), + KEY Grantor (Grantor) +) engine=MyISAM +CHARACTER SET utf8 COLLATE utf8_bin +comment='Procedure privileges'; + + +CREATE TABLE proc ( + db char(64) binary DEFAULT '' NOT NULL, + name char(64) DEFAULT '' NOT NULL, + type enum('FUNCTION','PROCEDURE') NOT NULL, + specific_name char(64) DEFAULT '' NOT NULL, + language enum('SQL') DEFAULT 'SQL' NOT NULL, + sql_data_access enum('CONTAINS_SQL', + 'NO_SQL', + 'READS_SQL_DATA', + 'MODIFIES_SQL_DATA' + ) DEFAULT 'CONTAINS_SQL' NOT NULL, + is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, + security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, + param_list blob DEFAULT '' NOT NULL, + returns char(64) DEFAULT '' NOT NULL, + body blob DEFAULT '' NOT NULL, + definer char(77) binary DEFAULT '' NOT NULL, + created timestamp, + modified timestamp, + sql_mode set( + 'REAL_AS_FLOAT', + 'PIPES_AS_CONCAT', + 'ANSI_QUOTES', + 'IGNORE_SPACE', + 'NOT_USED', + 'ONLY_FULL_GROUP_BY', + 'NO_UNSIGNED_SUBTRACTION', + 'NO_DIR_IN_CREATE', + 'POSTGRESQL', + 'ORACLE', + 'MSSQL', + 'DB2', + 'MAXDB', + 'NO_KEY_OPTIONS', + 'NO_TABLE_OPTIONS', + 'NO_FIELD_OPTIONS', + 'MYSQL323', + 'MYSQL40', + 'ANSI', + 'NO_AUTO_VALUE_ON_ZERO', + 'NO_BACKSLASH_ESCAPES', + 'STRICT_TRANS_TABLES', + 'STRICT_ALL_TABLES', + 'NO_ZERO_IN_DATE', + 'NO_ZERO_DATE', + 'INVALID_DATES', + 'ERROR_FOR_DIVISION_BY_ZERO', + 'TRADITIONAL', + 'NO_AUTO_CREATE_USER', + 'HIGH_NOT_PRECEDENCE' + ) DEFAULT 0 NOT NULL, + comment char(64) binary DEFAULT '' NOT NULL, + PRIMARY KEY (db,name,type) +) comment='Stored Procedures'; diff --git a/mysql-test/lib/mtr_cases.pl b/mysql-test/lib/mtr_cases.pl index 5977bb380cf..878afe95f2c 100644 --- a/mysql-test/lib/mtr_cases.pl +++ b/mysql-test/lib/mtr_cases.pl @@ -63,21 +63,24 @@ sub collect_test_cases ($) { # To speed things up, we sort first in if the test require a restart # or not, second in alphanumeric order. -# @$cases = sort { -# if ( $a->{'master_restart'} and $b->{'master_restart'} or -# ! $a->{'master_restart'} and ! $b->{'master_restart'} ) -# { -# return $a->{'name'} cmp $b->{'name'}; -# } -# if ( $a->{'master_restart'} ) -# { -# return 1; # Is greater -# } -# else -# { -# return -1; # Is less -# } -# } @$cases; + if ( $::opt_reorder ) + { + @$cases = sort { + if ( $a->{'master_restart'} and $b->{'master_restart'} or + ! $a->{'master_restart'} and ! $b->{'master_restart'} ) + { + return $a->{'name'} cmp $b->{'name'}; + } + if ( $a->{'master_restart'} ) + { + return 1; # Is greater + } + else + { + return -1; # Is less + } + } @$cases; + } return $cases; } diff --git a/mysql-test/lib/mtr_report.pl b/mysql-test/lib/mtr_report.pl index 9947fed9d27..fd665b154b8 100644 --- a/mysql-test/lib/mtr_report.pl +++ b/mysql-test/lib/mtr_report.pl @@ -89,12 +89,11 @@ sub mtr_report_test_passed ($) { my $tinfo= shift; my $timer= ""; -# FIXME -# if ( $::opt_timer and -f "$::glob_mysql_test_dir/var/log/timer" ) -# { -# $timer= `cat var/log/timer`; -# $timer= sprintf "%13s", $timer; -# } + if ( $::opt_timer and -f "$::glob_mysql_test_dir/var/log/timer" ) + { + $timer= mtr_fromfile("$::glob_mysql_test_dir/var/log/timer"); + $timer= sprintf "%12s", $timer; + } $tinfo->{'result'}= 'MTR_RES_PASSED'; print "[ pass ] $timer\n"; } diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index ce419540bf2..c3dc6cc3267 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -214,6 +214,7 @@ our $opt_embedded_server; our $opt_extern; our $opt_fast; our $opt_force; +our $opt_reorder; our $opt_gcov; our $opt_gcov_err; @@ -525,6 +526,7 @@ sub command_line_setup () { 'local-master' => \$opt_local_master, 'netware' => \$opt_netware, 'old-master' => \$opt_old_master, + 'reorder' => \$opt_reorder, 'script-debug' => \$opt_script_debug, 'sleep=i' => \$opt_sleep, 'socket=s' => \$opt_socket, @@ -576,7 +578,7 @@ sub command_line_setup () { $slave->[0]->{'path_mypid'}= "$glob_mysql_test_dir/var/run/slave.pid"; $slave->[0]->{'path_mysock'}= "$opt_tmpdir/slave.sock"; $slave->[0]->{'path_myport'}= $opt_slave_myport; - $slave->[0]->{'start_timeout'}= 400; + $slave->[0]->{'start_timeout'}= 400; $slave->[1]->{'path_myddir'}= "$glob_mysql_test_dir/var/slave1-data"; $slave->[1]->{'path_myerr'}= "$glob_mysql_test_dir/var/log/slave1.err"; @@ -584,7 +586,7 @@ sub command_line_setup () { $slave->[1]->{'path_mypid'}= "$glob_mysql_test_dir/var/run/slave1.pid"; $slave->[1]->{'path_mysock'}= "$opt_tmpdir/slave1.sock"; $slave->[1]->{'path_myport'}= $opt_slave_myport + 1; - $slave->[1]->{'start_timeout'}= 30; + $slave->[1]->{'start_timeout'}= 300; $slave->[2]->{'path_myddir'}= "$glob_mysql_test_dir/var/slave2-data"; $slave->[2]->{'path_myerr'}= "$glob_mysql_test_dir/var/log/slave2.err"; @@ -592,7 +594,7 @@ sub command_line_setup () { $slave->[2]->{'path_mypid'}= "$glob_mysql_test_dir/var/run/slave2.pid"; $slave->[2]->{'path_mysock'}= "$opt_tmpdir/slave2.sock"; $slave->[2]->{'path_myport'}= $opt_slave_myport + 2; - $slave->[2]->{'start_timeout'}= 30; + $slave->[2]->{'start_timeout'}= 300; # Do sanity checks of command line arguments @@ -1365,7 +1367,10 @@ sub run_testcase ($) { mtr_report_test_name($tinfo); mtr_tofile($master->[0]->{'path_myerr'},"CURRENT_TEST: $tname\n"); - do_before_start_master($tname,$tinfo->{'master_sh'}); + +# FIXME test cases that depend on each other, prevent this from +# being at this location. +# do_before_start_master($tname,$tinfo->{'master_sh'}); # ---------------------------------------------------------------------- # If any mysqld servers running died, we have to know @@ -1397,6 +1402,8 @@ sub run_testcase ($) { } if ( ! $master->[0]->{'pid'} ) { + # FIXME not correct location for do_before_start_master() + do_before_start_master($tname,$tinfo->{'master_sh'}); $master->[0]->{'pid'}= mysqld_start('master',0,$tinfo->{'master_opt'},[]); if ( ! $master->[0]->{'pid'} ) @@ -1532,9 +1539,10 @@ sub do_before_start_master ($$) { $tname ne "rpl_crash_binlog_ib_3b") { # FIXME we really want separate dir for binlogs - # FIXME replace 'rm' in backticks with portable Perl function - `rm -f $glob_mysql_test_dir/var/log/master-bin*`; -# unlink("$glob_mysql_test_dir/var/log/master-bin*"); + foreach my $bin ( glob("$glob_mysql_test_dir/var/log/master*-bin.*") ) + { + unlink($bin); + } } # Remove old master.info and relay-log.info files @@ -1568,9 +1576,10 @@ sub do_before_start_slave ($$) { $tname ne "rpl_crash_binlog_ib_3b" ) { # FIXME we really want separate dir for binlogs - # FIXME replace 'rm' in backticks with portable Perl function - `rm -fr $glob_mysql_test_dir/var/log/slave*-bin.*`; -# unlink("$glob_mysql_test_dir/var/log/slave*-bin.*"); # FIXME idx??? + foreach my $bin ( glob("$glob_mysql_test_dir/var/log/slave*-bin.*") ) + { + unlink($bin); + } # FIXME really master?! unlink("$glob_mysql_test_dir/var/slave-data/master.info"); unlink("$glob_mysql_test_dir/var/slave-data/relay-log.info"); @@ -1656,13 +1665,15 @@ sub mysqld_arguments ($$$$$) { mtr_add_arg($args, "%s--datadir=%s", $prefix, $slave->[$idx]->{'path_myddir'}); + % FIXME slave get this option twice?! mtr_add_arg($args, "%s--exit-info=256", $prefix); mtr_add_arg($args, "%s--init-rpl-role=slave", $prefix); mtr_add_arg($args, "%s--log-bin=%s/var/log/slave%s-bin", $prefix, $glob_mysql_test_dir, $sidx); # FIXME use own dir for binlogs mtr_add_arg($args, "%s--log-slave-updates", $prefix); + % FIXME option duplicated for slave mtr_add_arg($args, "%s--log=%s", $prefix, - $slave->[$idx]->{'path_myerr'}); + $slave->[$idx]->{'path_mylog'}); mtr_add_arg($args, "%s--master-retry-count=10", $prefix); mtr_add_arg($args, "%s--pid-file=%s", $prefix, $slave->[$idx]->{'path_mypid'}); @@ -2043,7 +2054,7 @@ sub run_mysqltest ($$) { if ( $opt_timer ) { - mtr_add_arg($args, "--timer-file=var/log/timer"); + mtr_add_arg($args, "--timer-file=%s/var/log/timer", $glob_mysql_test_dir); } if ( $opt_big_test ) @@ -2172,6 +2183,7 @@ Misc options timer Show test case execution time start-and-exit Only initiate and start the "mysqld" servers fast Don't try to cleanup from earlier runs + reorder Reorder tests to get less server restarts help Get this help text unified-diff | udiff When presenting differences, use unified diff diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index e4343807124..e97c64e9653 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -238,7 +238,7 @@ SLEEP_TIME_FOR_DELETE=10 SLEEP_TIME_FOR_FIRST_MASTER=400 # Enough time to create innodb tables SLEEP_TIME_FOR_SECOND_MASTER=400 SLEEP_TIME_FOR_FIRST_SLAVE=400 -SLEEP_TIME_FOR_SECOND_SLAVE=30 +SLEEP_TIME_FOR_SECOND_SLAVE=300 CHARACTER_SET=latin1 DBUSER="" START_WAIT_TIMEOUT=10 diff --git a/mysql-test/r/grant2.result b/mysql-test/r/grant2.result index e6db7bd682f..ecd43cc2860 100644 --- a/mysql-test/r/grant2.result +++ b/mysql-test/r/grant2.result @@ -165,7 +165,7 @@ GRANT UPDATE (c2) ON "test"."t2" TO 'mysqltest_1'@'%' GRANT UPDATE ON "test"."t1" TO 'mysqltest_1'@'%' drop user 'mysqltest_1', 'mysqltest_3'; grant all on test.t1 to 'mysqltest_1'; -ERROR 42000: 'root'@'localhost' is not allowed to create new users +ERROR HY000: You are not allowed to create a user with GRANT drop user 'mysqltest_1'; ERROR HY000: Operation DROP USER failed for 'mysqltest_1'@'%' drop table t1, t2; diff --git a/mysql-test/r/grant3.result b/mysql-test/r/grant3.result new file mode 100644 index 00000000000..ae37db3af42 --- /dev/null +++ b/mysql-test/r/grant3.result @@ -0,0 +1,17 @@ +SET NAMES binary; +drop table if exists t1; +delete from mysql.user where user like 'mysqltest\_%'; +delete from mysql.db where user like 'mysqltest\_%'; +delete from mysql.tables_priv where user like 'mysqltest\_%'; +delete from mysql.columns_priv where user like 'mysqltest\_%'; +flush privileges; +create user mysqltest_1@localhost; +grant grant option on mysql.* to mysqltest_1@localhost; +grant select on `my\_1`.* to mysqltest_1@localhost with grant option; +grant select on `my\_1`.* to mysqltest_2@localhost; +ERROR HY000: You are not allowed to create a user with GRANT +delete from mysql.user where user like 'mysqltest\_%'; +delete from mysql.db where user like 'mysqltest\_%'; +delete from mysql.tables_priv where user like 'mysqltest\_%'; +delete from mysql.columns_priv where user like 'mysqltest\_%'; +flush privileges; diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index dc456e80e63..1c3525c1508 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -118,8 +118,8 @@ t2 t3 show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t2 MyISAM 9 Fixed 0 0 0 # 1024 0 NULL # # NULL latin1_swedish_ci NULL -t3 MyISAM 9 Fixed 0 0 0 # 1024 0 NULL # # NULL latin1_swedish_ci NULL +t2 MyISAM 10 Fixed 0 0 0 # 1024 0 NULL # # NULL latin1_swedish_ci NULL +t3 MyISAM 10 Fixed 0 0 0 # 1024 0 NULL # # NULL latin1_swedish_ci NULL v1 NULL NULL NULL NULL NULL NULL # NULL NULL NULL # # NULL NULL NULL NULL view show full columns from t3 like "a%"; Field Type Collation Null Key Default Extra Privileges Comment @@ -432,7 +432,6 @@ information_schema.tables) union select version from information_schema.tables; s1 0 -9 10 drop table t1; SHOW CREATE TABLE INFORMATION_SCHEMA.character_sets; diff --git a/mysql-test/r/ndb_autodiscover.result b/mysql-test/r/ndb_autodiscover.result index 38b34579f03..27ebda36669 100644 --- a/mysql-test/r/ndb_autodiscover.result +++ b/mysql-test/r/ndb_autodiscover.result @@ -144,8 +144,8 @@ Handler_discover 1 flush tables; show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t6 MyISAM 9 Fixed 1 260 # # # 0 NULL # # NULL # NULL # -t7 ndbcluster 9 Fixed 1 276 # # # 0 NULL # # NULL # NULL # +t6 MyISAM 10 Fixed 1 260 # # # 0 NULL # # NULL # NULL # +t7 ndbcluster 10 Fixed 1 276 # # # 0 NULL # # NULL # NULL # show status like 'handler_discover%'; Variable_name Value Handler_discover 2 diff --git a/mysql-test/r/olap.result b/mysql-test/r/olap.result index 4863cb5b75e..91e52841c3b 100644 --- a/mysql-test/r/olap.result +++ b/mysql-test/r/olap.result @@ -378,6 +378,51 @@ a sum(b) 2 6 4 4 NULL 14 +SELECT b, a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP; +b a sum(b) +4 1 4 +NULL 1 4 +1 2 2 +2 2 4 +NULL 2 6 +1 4 4 +NULL 4 4 +NULL NULL 14 +SELECT DISTINCT b,a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP; +b a sum(b) +4 1 4 +NULL 1 4 +1 2 2 +2 2 4 +NULL 2 6 +1 4 4 +NULL 4 4 +NULL NULL 14 +ALTER TABLE t1 ADD COLUMN c INT; +SELECT a,b,sum(c) FROM t1 GROUP BY a,b,c WITH ROLLUP; +a b sum(c) +1 4 NULL +1 4 NULL +1 NULL NULL +2 1 NULL +2 1 NULL +2 2 NULL +2 2 NULL +2 NULL NULL +4 1 NULL +4 1 NULL +4 NULL NULL +NULL NULL NULL +SELECT distinct a,b,sum(c) FROM t1 GROUP BY a,b,c WITH ROLLUP; +a b sum(c) +1 4 NULL +1 NULL NULL +2 1 NULL +2 2 NULL +2 NULL NULL +4 1 NULL +4 NULL NULL +NULL NULL NULL DROP TABLE t1; CREATE TABLE t1 (a int, b int); INSERT INTO t1 VALUES diff --git a/mysql-test/r/ps_1general.result b/mysql-test/r/ps_1general.result index cd3c8e162f7..342b3e3ef06 100644 --- a/mysql-test/r/ps_1general.result +++ b/mysql-test/r/ps_1general.result @@ -290,7 +290,7 @@ t2 1 t2_idx 1 b A NULL NULL NULL YES BTREE prepare stmt4 from ' show table status from test like ''t2%'' '; execute stmt4; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t2 MyISAM 9 Fixed 0 0 0 64424509439 1024 0 NULL # # # latin1_swedish_ci NULL +t2 MyISAM 10 Fixed 0 0 0 64424509439 1024 0 NULL # # # latin1_swedish_ci NULL prepare stmt4 from ' show table status from test like ''t9%'' '; execute stmt4; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment diff --git a/mysql-test/r/rpl_timezone.result b/mysql-test/r/rpl_timezone.result index cd2c4d099be..8975333d1db 100644 --- a/mysql-test/r/rpl_timezone.result +++ b/mysql-test/r/rpl_timezone.result @@ -4,21 +4,31 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; +set timestamp=100000000; create table t1 (t timestamp); create table t2 (t char(32)); select @@time_zone; @@time_zone +Japan +select @@time_zone; +@@time_zone Europe/Moscow +insert into t1 values ('20050101000000'), ('20050611093902'); set time_zone='UTC'; insert into t1 values ('20040101000000'), ('20040611093902'); select * from t1; t +2004-12-31 21:00:00 +2005-06-11 05:39:02 2004-01-01 00:00:00 2004-06-11 09:39:02 +set time_zone='UTC'; select * from t1; t -2004-01-01 03:00:00 -2004-06-11 13:39:02 +2004-12-31 21:00:00 +2005-06-11 05:39:02 +2004-01-01 00:00:00 +2004-06-11 09:39:02 delete from t1; set time_zone='Europe/Moscow'; insert into t1 values ('20040101000000'), ('20040611093902'); @@ -26,19 +36,35 @@ select * from t1; t 2004-01-01 00:00:00 2004-06-11 09:39:02 +set time_zone='Europe/Moscow'; select * from t1; t 2004-01-01 00:00:00 2004-06-11 09:39:02 -show binlog events; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Format_desc 1 # Server ver: VERSION, Binlog ver: 4 -master-bin.000001 # Query 1 # use `test`; create table t1 (t timestamp) -master-bin.000001 # Query 1 # use `test`; create table t2 (t char(32)) -master-bin.000001 # Query 1 # use `test`; SET ONE_SHOT TIME_ZONE='UTC' -master-bin.000001 # Query 1 # use `test`; insert into t1 values ('20040101000000'), ('20040611093902') -master-bin.000001 # Query 1 # use `test`; delete from t1 -master-bin.000001 # Query 1 # use `test`; insert into t1 values ('20040101000000'), ('20040611093902') +/*!40019 SET @@session.max_insert_delayed_threads=0*/; +/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; +ROLLBACK; +use test; +SET TIMESTAMP=100000000; +SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1; +SET @@session.sql_mode=0; +SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8; +create table t1 (t timestamp); +SET TIMESTAMP=100000000; +create table t2 (t char(32)); +SET TIMESTAMP=100000000; +SET @@session.time_zone='Europe/Moscow'; +insert into t1 values ('20050101000000'), ('20050611093902'); +SET TIMESTAMP=100000000; +SET @@session.time_zone='UTC'; +insert into t1 values ('20040101000000'), ('20040611093902'); +SET TIMESTAMP=100000000; +delete from t1; +SET TIMESTAMP=100000000; +SET @@session.time_zone='Europe/Moscow'; +insert into t1 values ('20040101000000'), ('20040611093902'); +ROLLBACK; +/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; set time_zone='MET'; insert into t2 (select t from t1); select * from t1; @@ -52,10 +78,6 @@ t delete from t2; set timestamp=1000072000; insert into t2 values (current_timestamp), (current_date), (current_time); -set timestamp=1000072000; -select current_timestamp, current_date, current_time; -current_timestamp current_date current_time -2001-09-10 01:46:40 2001-09-10 01:46:40 select * from t2; t 2001-09-09 23:46:40 @@ -73,5 +95,16 @@ t 2001-09-09 03:46:40 1000000000 set global time_zone='MET'; -ERROR HY000: Binary logging and replication forbid changing the global server time zone +delete from t2; +set time_zone='UTC'; +insert into t2 values(convert_tz('2004-01-01 00:00:00','MET',@@time_zone)); +insert into t2 values(convert_tz('2005-01-01 00:00:00','MET','Japan')); +select * from t2; +t +2003-12-31 23:00:00 +2005-01-01 08:00:00 +select * from t2; +t +2003-12-31 23:00:00 +2005-01-01 08:00:00 drop table t1, t2; diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index 15cae7646f9..7c34481b519 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -315,57 +315,57 @@ insert into t2 values (1),(2); insert into t3 values (1,1),(2,2); show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 MEMORY 9 Fixed 2 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL -t2 MEMORY 9 Fixed 2 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL -t3 MEMORY 9 Fixed 2 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t1 MEMORY 10 Fixed 2 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t2 MEMORY 10 Fixed 2 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t3 MEMORY 10 Fixed 2 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL insert into t1 values (3),(4); insert into t2 values (3),(4); insert into t3 values (3,3),(4,4); show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 MEMORY 9 Fixed 4 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL -t2 MEMORY 9 Fixed 4 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL -t3 MEMORY 9 Fixed 4 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t1 MEMORY 10 Fixed 4 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t2 MEMORY 10 Fixed 4 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t3 MEMORY 10 Fixed 4 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL insert into t1 values (5); insert into t2 values (5); insert into t3 values (5,5); show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 MEMORY 9 Fixed 5 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL -t2 MEMORY 9 Fixed 5 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL -t3 MEMORY 9 Fixed 5 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t1 MEMORY 10 Fixed 5 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t2 MEMORY 10 Fixed 5 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t3 MEMORY 10 Fixed 5 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL delete from t1 where a=3; delete from t2 where b=3; delete from t3 where a=3; show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 MEMORY 9 Fixed 4 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL -t2 MEMORY 9 Fixed 4 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL -t3 MEMORY 9 Fixed 4 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL +t1 MEMORY 10 Fixed 4 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL +t2 MEMORY 10 Fixed 4 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL +t3 MEMORY 10 Fixed 4 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL delete from t1; delete from t2; delete from t3; show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 MEMORY 9 Fixed 0 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL -t2 MEMORY 9 Fixed 0 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL -t3 MEMORY 9 Fixed 0 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t1 MEMORY 10 Fixed 0 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t2 MEMORY 10 Fixed 0 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t3 MEMORY 10 Fixed 0 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL insert into t1 values (5); insert into t2 values (5); insert into t3 values (5,5); show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 MEMORY 9 Fixed 1 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL -t2 MEMORY 9 Fixed 1 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL -t3 MEMORY 9 Fixed 1 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t1 MEMORY 10 Fixed 1 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t2 MEMORY 10 Fixed 1 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t3 MEMORY 10 Fixed 1 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL delete from t1 where a=5; delete from t2 where b=5; delete from t3 where a=5; show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 MEMORY 9 Fixed 0 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL -t2 MEMORY 9 Fixed 0 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL -t3 MEMORY 9 Fixed 0 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL +t1 MEMORY 10 Fixed 0 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL +t2 MEMORY 10 Fixed 0 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL +t3 MEMORY 10 Fixed 0 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL drop table t1, t2, t3; create database mysqltest; show create database mysqltest; diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 75459bd960b..ae1bb42cc29 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -149,7 +149,7 @@ v5 VIEW v6 VIEW show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 MyISAM 9 Fixed 5 9 45 38654705663 1024 0 NULL # # NULL latin1_swedish_ci NULL +t1 MyISAM 10 Fixed 5 9 45 38654705663 1024 0 NULL # # NULL latin1_swedish_ci NULL v1 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL # # NULL NULL NULL NULL view v2 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL # # NULL NULL NULL NULL view v3 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL # # NULL NULL NULL NULL view @@ -1115,7 +1115,7 @@ select * from v1; ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 MyISAM 9 Fixed 0 0 0 # 1024 0 NULL # # NULL latin1_swedish_ci NULL +t1 MyISAM 10 Fixed 0 0 0 # 1024 0 NULL # # NULL latin1_swedish_ci NULL v1 NULL NULL NULL NULL NULL NULL # NULL NULL NULL # # NULL NULL NULL NULL View 'test.v1' references invalid table(s) or column(s) or function(s) drop view v1; drop table t1; diff --git a/mysql-test/t/grant2.test b/mysql-test/t/grant2.test index f86cf2a1db7..7aefbb5d9ff 100644 --- a/mysql-test/t/grant2.test +++ b/mysql-test/t/grant2.test @@ -179,7 +179,7 @@ show grants for 'mysqltest_1'; drop user 'mysqltest_1', 'mysqltest_3'; # # Grant must not create user ---error 1211 +--error 1410 grant all on test.t1 to 'mysqltest_1'; --error 1396 drop user 'mysqltest_1'; diff --git a/mysql-test/t/grant3-master.opt b/mysql-test/t/grant3-master.opt new file mode 100644 index 00000000000..4b11f5902c1 --- /dev/null +++ b/mysql-test/t/grant3-master.opt @@ -0,0 +1 @@ +--safe-user-create diff --git a/mysql-test/t/grant3.test b/mysql-test/t/grant3.test new file mode 100644 index 00000000000..dca4ff9496e --- /dev/null +++ b/mysql-test/t/grant3.test @@ -0,0 +1,32 @@ +# Test of GRANT commands + +SET NAMES binary; +connect (master,localhost,root,,); +connection master; + +# Cleanup +--disable_warnings +drop table if exists t1; +--enable_warnings + +delete from mysql.user where user like 'mysqltest\_%'; +delete from mysql.db where user like 'mysqltest\_%'; +delete from mysql.tables_priv where user like 'mysqltest\_%'; +delete from mysql.columns_priv where user like 'mysqltest\_%'; +flush privileges; + +create user mysqltest_1@localhost; +grant grant option on mysql.* to mysqltest_1@localhost; +grant select on `my\_1`.* to mysqltest_1@localhost with grant option; +connect (user_a,localhost,mysqltest_1,,); +connection user_a; +--error 1410 +grant select on `my\_1`.* to mysqltest_2@localhost; +disconnect user_a; +connection default; + +delete from mysql.user where user like 'mysqltest\_%'; +delete from mysql.db where user like 'mysqltest\_%'; +delete from mysql.tables_priv where user like 'mysqltest\_%'; +delete from mysql.columns_priv where user like 'mysqltest\_%'; +flush privileges; diff --git a/mysql-test/t/olap.test b/mysql-test/t/olap.test index 3aac0f45ead..6e83968a506 100644 --- a/mysql-test/t/olap.test +++ b/mysql-test/t/olap.test @@ -153,6 +153,13 @@ SELECT DISTINCT SUM(b), COUNT(DISTINCT b), COUNT(*) FROM t1 SELECT a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP; SELECT DISTINCT a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP; +SELECT b, a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP; +SELECT DISTINCT b,a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP; + +ALTER TABLE t1 ADD COLUMN c INT; +SELECT a,b,sum(c) FROM t1 GROUP BY a,b,c WITH ROLLUP; +SELECT distinct a,b,sum(c) FROM t1 GROUP BY a,b,c WITH ROLLUP; + DROP TABLE t1; # diff --git a/mysql-test/t/rpl_timezone-slave.opt b/mysql-test/t/rpl_timezone-slave.opt index 8e43bfbbb7e..191182c329c 100644 --- a/mysql-test/t/rpl_timezone-slave.opt +++ b/mysql-test/t/rpl_timezone-slave.opt @@ -1 +1 @@ ---default-time-zone=Europe/Moscow +--default-time-zone=Japan diff --git a/mysql-test/t/rpl_timezone.test b/mysql-test/t/rpl_timezone.test index 3c180ca8849..cc8dcb6ce26 100644 --- a/mysql-test/t/rpl_timezone.test +++ b/mysql-test/t/rpl_timezone.test @@ -1,23 +1,38 @@ # Test of replication of time zones. + +# There is currently some bug possibly in prepared statements (this +# test fails with --ps-protocol): sys_var_thd_time_zone::value_ptr() +# is called only at prepare time, not at execution time. So, +# thd->time_zone_used is not equal to 1 (it is back to 0, because of +# reset_thd_for_next_command called at execution time), so the +# timezone used in CONVERT_TZ is not binlogged. To debug (by Guilhem +# and possibly Konstantin). + +--disable_ps_protocol + source include/master-slave.inc; # Some preparations let $VERSION=`select version()`; +set timestamp=100000000; # for fixed output of mysqlbinlog create table t1 (t timestamp); create table t2 (t char(32)); +connection slave; +select @@time_zone; + # # Let us check how well replication works when we are saving datetime # value in TIMESTAMP field. # connection master; select @@time_zone; +insert into t1 values ('20050101000000'), ('20050611093902'); set time_zone='UTC'; insert into t1 values ('20040101000000'), ('20040611093902'); select * from t1; -# On slave we still in 'Europe/Moscow' so we should see equivalent but -# textually different values. sync_slave_with_master; +set time_zone='UTC'; select * from t1; # Let us check also that setting of time_zone back to default also works @@ -28,12 +43,11 @@ set time_zone='Europe/Moscow'; insert into t1 values ('20040101000000'), ('20040611093902'); select * from t1; sync_slave_with_master; +set time_zone='Europe/Moscow'; select * from t1; connection master; -# We should not see SET ONE_SHOT time_zone before second insert ---replace_result $VERSION VERSION ---replace_column 2 # 5 # -show binlog events; +--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +--exec $MYSQL_BINLOG --short-form $MYSQL_TEST_DIR/var/log/master-bin.000001 # # Now let us check how well we replicate statments reading TIMESTAMP fields @@ -54,10 +68,6 @@ delete from t2; set timestamp=1000072000; insert into t2 values (current_timestamp), (current_date), (current_time); sync_slave_with_master; -# Values in ouput of these to queries should differ because we are in -# in 'MET' on master and in 'Europe/Moscow on slave... -set timestamp=1000072000; -select current_timestamp, current_date, current_time; select * from t2; # @@ -73,13 +83,24 @@ sync_slave_with_master; select * from t2; # -# Let us check that we are not allowing to set global time_zone with +# Let us check that we are allowing to set global time_zone with # replication # connection master; ---error 1387 set global time_zone='MET'; +# +# Let us see if CONVERT_TZ(@@time_zone) replicates +# +delete from t2; +set time_zone='UTC'; +insert into t2 values(convert_tz('2004-01-01 00:00:00','MET',@@time_zone)); +insert into t2 values(convert_tz('2005-01-01 00:00:00','MET','Japan')); +select * from t2; +sync_slave_with_master; +select * from t2; + # Clean up +connection master; drop table t1, t2; sync_slave_with_master; diff --git a/scripts/fill_func_tables.sh b/scripts/fill_func_tables.sh index 459afee2fe1..203c730dd9a 100644 --- a/scripts/fill_func_tables.sh +++ b/scripts/fill_func_tables.sh @@ -131,8 +131,8 @@ print "USE mysql_help;\n"; print "DROP TABLE IF EXISTS function;\n"; print "CREATE TABLE function ("; print " func_id int unsigned not null auto_increment,"; -print " name varchar(64) not null,"; -print " url varchar(128) not null,"; +print " name char(64) not null,"; +print " url char(128) not null,"; print " description text not null,"; print " example text not null,"; print " min_args tinyint not null,"; @@ -145,8 +145,8 @@ print ") type=myisam;\n\n"; print "DROP TABLE IF EXISTS function_category_name;\n"; print "CREATE TABLE function_category_name ("; print " cat_id smallint unsigned not null auto_increment,"; -print " name varchar(64) not null,"; -print " url varchar(128) not null,"; +print " name char(64) not null,"; +print " url char(128) not null,"; print " date_created datetime not null,"; print " last_modified timestamp not null,"; print " primary key (cat_id)"; diff --git a/scripts/mysql_create_system_tables.sh b/scripts/mysql_create_system_tables.sh index d87113d3656..0260bdea887 100644 --- a/scripts/mysql_create_system_tables.sh +++ b/scripts/mysql_create_system_tables.sh @@ -269,11 +269,11 @@ then c_ht="$c_ht CREATE TABLE help_topic (" c_ht="$c_ht help_topic_id int unsigned not null," - c_ht="$c_ht name varchar(64) not null," + c_ht="$c_ht name char(64) not null," c_ht="$c_ht help_category_id smallint unsigned not null," c_ht="$c_ht description text not null," c_ht="$c_ht example text not null," - c_ht="$c_ht url varchar(128) not null," + c_ht="$c_ht url char(128) not null," c_ht="$c_ht primary key (help_topic_id)," c_ht="$c_ht unique index (name)" c_ht="$c_ht ) engine=MyISAM" @@ -291,9 +291,9 @@ then c_hc="$c_hc CREATE TABLE help_category (" c_hc="$c_hc help_category_id smallint unsigned not null," - c_hc="$c_hc name varchar(64) not null," + c_hc="$c_hc name char(64) not null," c_hc="$c_hc parent_category_id smallint unsigned null," - c_hc="$c_hc url varchar(128) not null," + c_hc="$c_hc url char(128) not null," c_hc="$c_hc primary key (help_category_id)," c_hc="$c_hc unique index (name)" c_hc="$c_hc ) engine=MyISAM" @@ -309,7 +309,7 @@ then c_hk="$c_hk CREATE TABLE help_keyword (" c_hk="$c_hk help_keyword_id int unsigned not null," - c_hk="$c_hk name varchar(64) not null," + c_hk="$c_hk name char(64) not null," c_hk="$c_hk primary key (help_keyword_id)," c_hk="$c_hk unique index (name)" c_hk="$c_hk ) engine=MyISAM" diff --git a/scripts/mysql_fix_privilege_tables.sh b/scripts/mysql_fix_privilege_tables.sh index d5c96532782..d080b68b268 100644 --- a/scripts/mysql_fix_privilege_tables.sh +++ b/scripts/mysql_fix_privilege_tables.sh @@ -13,7 +13,7 @@ args="" port="" socket="" database="mysql" -bindir="." +bindir="" pkgdatadir="@pkgdatadir@" print_defaults_bindir="." diff --git a/scripts/mysql_fix_privilege_tables.sql b/scripts/mysql_fix_privilege_tables.sql index 2310e8d0bef..344f8ca5bb3 100644 --- a/scripts/mysql_fix_privilege_tables.sql +++ b/scripts/mysql_fix_privilege_tables.sql @@ -307,19 +307,19 @@ KEY Grantor (Grantor) CREATE TABLE IF NOT EXISTS help_topic ( help_topic_id int unsigned not null, -name varchar(64) not null, +name char(64) not null, help_category_id smallint unsigned not null, description text not null, example text not null, -url varchar(128) not null, +url char(128) not null, primary key (help_topic_id), unique index (name) ) CHARACTER SET utf8 comment='help topics'; CREATE TABLE IF NOT EXISTS help_category ( help_category_id smallint unsigned not null, -name varchar(64) not null, +name char(64) not null, parent_category_id smallint unsigned null, -url varchar(128) not null, +url char(128) not null, primary key (help_category_id), unique index (name) ) CHARACTER SET utf8 comment='help categories'; @@ -332,7 +332,7 @@ primary key (help_keyword_id, help_topic_id) CREATE TABLE IF NOT EXISTS help_keyword ( help_keyword_id int unsigned not null, -name varchar(64) not null, +name char(64) not null, primary key (help_keyword_id), unique index (name) ) CHARACTER SET utf8 comment='help keywords'; @@ -479,3 +479,35 @@ ALTER TABLE proc MODIFY name char(64) DEFAULT '' NOT NULL, 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE' ) DEFAULT 0 NOT NULL; + +# +# Change all varchar fields in privilege tables to CHAR, to ensure that +# we can use the privilege tables in MySQL 4.1 +# Note that for this hack to work, we must change all CHAR() columns at +# the same time +# + +ALTER TABLE mysql.user +modify Host char(60) binary DEFAULT '' NOT NULL, +modify User char(16) binary DEFAULT '' NOT NULL, +modify Password char(41) binary DEFAULT '' NOT NULL; + +ALTER TABLE mysql.db +modify Host char(60) binary DEFAULT '' NOT NULL, +modify Db char(64) binary DEFAULT '' NOT NULL, +modify User char(16) binary DEFAULT '' NOT NULL; + +ALTER TABLE mysql.host +modify Host char(60) binary DEFAULT '' NOT NULL, +modify Db char(64) binary DEFAULT '' NOT NULL; + +ALTER TABLE help_topic +modify name char(64) not null, +modify url char(128) not null; + +ALTER TABLE help_category +modify name char(64) not null, +modify url char(128) not null; + +ALTER TABLE help_keyword +modify name char(64) not null; diff --git a/server-tools/instance-manager/commands.cc b/server-tools/instance-manager/commands.cc index 9831ad3a891..426f0cc40b2 100644 --- a/server-tools/instance-manager/commands.cc +++ b/server-tools/instance-manager/commands.cc @@ -14,14 +14,17 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "command.h" #include "commands.h" -#include "instance.h" + #include "instance_map.h" #include "messages.h" +#include "mysqld_error.h" +#include "mysql_manager_error.h" #include "protocol.h" #include "buffer.h" + #include +#include /* implementation for Show_instances: */ diff --git a/server-tools/instance-manager/commands.h b/server-tools/instance-manager/commands.h index cd13bf09549..bab67f9c6b4 100644 --- a/server-tools/instance-manager/commands.h +++ b/server-tools/instance-manager/commands.h @@ -16,8 +16,8 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "command.h" #include "instance.h" -#include "my_global.h" /* Print all instances of this instance manager. diff --git a/server-tools/instance-manager/factory.cc b/server-tools/instance-manager/factory.cc index cde5d0564aa..538d9353983 100644 --- a/server-tools/instance-manager/factory.cc +++ b/server-tools/instance-manager/factory.cc @@ -15,11 +15,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "factory.h" -#include "my_global.h" - -#include -#include - Show_instances *Command_factory::new_Show_instances() { diff --git a/server-tools/instance-manager/guardian.cc b/server-tools/instance-manager/guardian.cc index 4fbfaf2672d..5d89f167f2f 100644 --- a/server-tools/instance-manager/guardian.cc +++ b/server-tools/instance-manager/guardian.cc @@ -20,10 +20,12 @@ #endif #include "guardian.h" + #include "instance_map.h" #include "instance.h" #include "mysql_manager_error.h" #include "log.h" + #include #include #include diff --git a/server-tools/instance-manager/guardian.h b/server-tools/instance-manager/guardian.h index e43b5d565d7..502dc86b2ae 100644 --- a/server-tools/instance-manager/guardian.h +++ b/server-tools/instance-manager/guardian.h @@ -17,9 +17,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include +#include "thread_registry.h" + #include #include -#include "thread_registry.h" #ifdef __GNUC__ #pragma interface diff --git a/server-tools/instance-manager/instance.cc b/server-tools/instance-manager/instance.cc index 97282f3f800..00fcf6c3a98 100644 --- a/server-tools/instance-manager/instance.cc +++ b/server-tools/instance-manager/instance.cc @@ -19,16 +19,17 @@ #endif #include "instance.h" + #include "mysql_manager_error.h" #include "log.h" #include "instance_map.h" #include "priv.h" +#include #include #include #include -#include - +#include C_MODE_START diff --git a/server-tools/instance-manager/instance.h b/server-tools/instance-manager/instance.h index c141ff7b30d..14ef5cfcfb9 100644 --- a/server-tools/instance-manager/instance.h +++ b/server-tools/instance-manager/instance.h @@ -17,8 +17,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include -#include -#include #include "instance_options.h" #ifdef __GNUC__ diff --git a/server-tools/instance-manager/instance_map.cc b/server-tools/instance-manager/instance_map.cc index d19d42662e5..3e76c24a9a1 100644 --- a/server-tools/instance-manager/instance_map.cc +++ b/server-tools/instance-manager/instance_map.cc @@ -19,10 +19,11 @@ #endif #include "instance_map.h" + #include "buffer.h" #include "instance.h" + #include -#include #include #include diff --git a/server-tools/instance-manager/instance_map.h b/server-tools/instance-manager/instance_map.h index 8d8ea33cf5d..46247c82a16 100644 --- a/server-tools/instance-manager/instance_map.h +++ b/server-tools/instance-manager/instance_map.h @@ -17,6 +17,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include + +#include "protocol.h" +#include "guardian.h" + #include #include @@ -24,9 +28,6 @@ #pragma interface #endif -#include "protocol.h" -#include "guardian.h" - class Instance; extern int load_all_groups(char ***groups, const char *filename); extern void free_groups(char **groups); diff --git a/server-tools/instance-manager/instance_options.cc b/server-tools/instance-manager/instance_options.cc index e1b81bc93b1..0d602f88ad2 100644 --- a/server-tools/instance-manager/instance_options.cc +++ b/server-tools/instance-manager/instance_options.cc @@ -19,8 +19,10 @@ #endif #include "instance_options.h" + #include "parse_output.h" #include "buffer.h" + #include #include #include diff --git a/server-tools/instance-manager/log.cc b/server-tools/instance-manager/log.cc index dbcea3f9c3d..5491b4e70e9 100644 --- a/server-tools/instance-manager/log.cc +++ b/server-tools/instance-manager/log.cc @@ -14,8 +14,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "log.h" #include + +#include "log.h" + #include #include #include diff --git a/server-tools/instance-manager/manager.cc b/server-tools/instance-manager/manager.cc index 8629c5e9d9c..fd8673c4d66 100644 --- a/server-tools/instance-manager/manager.cc +++ b/server-tools/instance-manager/manager.cc @@ -14,6 +14,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include "manager.h" #include "priv.h" @@ -25,7 +26,6 @@ #include "log.h" #include "guardian.h" -#include #include #include #include diff --git a/server-tools/instance-manager/messages.cc b/server-tools/instance-manager/messages.cc index e3c2423a47e..d044c0f65db 100644 --- a/server-tools/instance-manager/messages.cc +++ b/server-tools/instance-manager/messages.cc @@ -13,11 +13,14 @@ 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 "messages.h" #include -#include +#include "messages.h" +#include "mysqld_error.h" +#include "mysql_manager_error.h" + +#include #include diff --git a/server-tools/instance-manager/messages.h b/server-tools/instance-manager/messages.h index 4cc15b5efe4..b771efe5e13 100644 --- a/server-tools/instance-manager/messages.h +++ b/server-tools/instance-manager/messages.h @@ -16,9 +16,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "mysqld_error.h" -#include "mysql_manager_error.h" - const char *message(unsigned sql_errno); const char *errno_to_sqlstate(unsigned sql_errno); diff --git a/server-tools/instance-manager/mysql_connection.cc b/server-tools/instance-manager/mysql_connection.cc index 7947de70459..215dbe51b58 100644 --- a/server-tools/instance-manager/mysql_connection.cc +++ b/server-tools/instance-manager/mysql_connection.cc @@ -19,14 +19,10 @@ #endif #include "mysql_connection.h" + #include "priv.h" - -#include -#include -#include -#include -#include - +#include "mysql_manager_error.h" +#include "mysqld_error.h" #include "thread_registry.h" #include "log.h" #include "user_map.h" @@ -36,6 +32,13 @@ #include "factory.h" #include "parse.h" +#include +#include +#include +#include +#include + + Command *parse_command(Command_factory * factory, const char *text); Mysql_connection_thread_args::Mysql_connection_thread_args( diff --git a/server-tools/instance-manager/mysqlmanager.cc b/server-tools/instance-manager/mysqlmanager.cc index e1d267b492e..262686c3fab 100644 --- a/server-tools/instance-manager/mysqlmanager.cc +++ b/server-tools/instance-manager/mysqlmanager.cc @@ -14,11 +14,12 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include "manager.h" + #include "options.h" #include "log.h" -#include #include #include #include diff --git a/server-tools/instance-manager/options.cc b/server-tools/instance-manager/options.cc index 9e4205b1407..4b5ec27f302 100644 --- a/server-tools/instance-manager/options.cc +++ b/server-tools/instance-manager/options.cc @@ -20,14 +20,13 @@ #include "options.h" -#include +#include "priv.h" + #include #include #include #include -#include "priv.h" - #define QUOTE2(x) #x #define QUOTE(x) QUOTE2(x) diff --git a/server-tools/instance-manager/parse.cc b/server-tools/instance-manager/parse.cc index 4c897ddf933..d3fb10b7c94 100644 --- a/server-tools/instance-manager/parse.cc +++ b/server-tools/instance-manager/parse.cc @@ -15,6 +15,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "parse.h" + #include enum Token diff --git a/server-tools/instance-manager/parse_output.cc b/server-tools/instance-manager/parse_output.cc index 6fee0797395..77fa40ca352 100644 --- a/server-tools/instance-manager/parse_output.cc +++ b/server-tools/instance-manager/parse_output.cc @@ -14,10 +14,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include "parse.h" #include -#include #include #include diff --git a/server-tools/instance-manager/protocol.cc b/server-tools/instance-manager/protocol.cc index 60cd0e8714f..9c8975a78be 100644 --- a/server-tools/instance-manager/protocol.cc +++ b/server-tools/instance-manager/protocol.cc @@ -14,13 +14,13 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include -#include +#include "protocol.h" + +#include "messages.h" + #include #include -#include "messages.h" -#include "protocol.h" static char eof_buff[1]= { (char) 254 }; /* Marker for end of fields */ diff --git a/server-tools/instance-manager/protocol.h b/server-tools/instance-manager/protocol.h index 1102f95ff8f..b7b18b4b76c 100644 --- a/server-tools/instance-manager/protocol.h +++ b/server-tools/instance-manager/protocol.h @@ -17,6 +17,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "buffer.h" + #include typedef struct field { diff --git a/server-tools/instance-manager/thread_registry.cc b/server-tools/instance-manager/thread_registry.cc index bf01aa6d7b2..16821df4146 100644 --- a/server-tools/instance-manager/thread_registry.cc +++ b/server-tools/instance-manager/thread_registry.cc @@ -20,10 +20,11 @@ #include "thread_registry.h" +#include "log.h" + #include #include #include -#include "log.h" /* Kick-off signal handler */ diff --git a/server-tools/instance-manager/user_map.h b/server-tools/instance-manager/user_map.h index dcd2fd1494d..4c86edd93d9 100644 --- a/server-tools/instance-manager/user_map.h +++ b/server-tools/instance-manager/user_map.h @@ -17,10 +17,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef __GNUC__ -#pragma interface +#pragma interface #endif #include + #include #include diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 072f6866d7a..349a69e5a80 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -1309,6 +1309,9 @@ innobase_end(void) } #endif if (innodb_inited) { + +#ifndef __NETWARE__ /* NetWare can't close unclosed files, kill remaining + threads, etc, so we disable the very fast shutdown */ if (innobase_very_fast_shutdown) { srv_very_fast_shutdown = TRUE; fprintf(stderr, @@ -1316,6 +1319,7 @@ innobase_end(void) "InnoDB: the InnoDB buffer pool to data files. At the next mysqld startup\n" "InnoDB: InnoDB will do a crash recovery!\n"); } +#endif innodb_inited = 0; if (innobase_shutdown_for_mysql() != DB_SUCCESS) { diff --git a/sql/handler.cc b/sql/handler.cc index 78f9ce61d57..d23553014ef 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -764,14 +764,13 @@ static char* xid_to_str(char *buf, XID *xid) for (i=0; i < xid->gtrid_length+xid->bqual_length; i++) { uchar c=(uchar)xid->data[i]; - bool is_next_dig; + /* is_next_dig is set if next character is a number */ + bool is_next_dig= FALSE; if (i < XIDDATASIZE) { - char ch=xid->data[i+1]; - is_next_dig=(c >= '0' && c <='9'); + char ch= xid->data[i+1]; + is_next_dig= (ch >= '0' && ch <='9'); } - else - is_next_dig=FALSE; if (i == xid->gtrid_length) { *s++='\''; @@ -784,6 +783,11 @@ static char* xid_to_str(char *buf, XID *xid) if (c < 32 || c > 126) { *s++='\\'; + /* + If next character is a number, write current character with + 3 octal numbers to ensure that the next number is not seen + as part of the octal number + */ if (c > 077 || is_next_dig) *s++=_dig_vec_lower[c >> 6]; if (c > 007 || is_next_dig) diff --git a/sql/item.cc b/sql/item.cc index 69aaec44f55..457aa774352 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -586,18 +586,8 @@ Item *Item_string::safe_charset_converter(CHARSET_INFO *tocs) return NULL; } conv->str_value.copy(); - /* - The above line executes str_value.realloc() internally, - which alligns Alloced_length using ALLIGN_SIZE. - In the case of Item_string::str_value we don't want - Alloced_length to be longer than str_length. - Otherwise, some functions like Item_func_concat::val_str() - try to reuse str_value as a buffer for concatenation result - for optimization purposes, so our string constant become - corrupted. See bug#8785 for more details. - Let's shrink Alloced_length to str_length to avoid this problem. - */ - conv->str_value.shrink_to_length(); + /* Ensure that no one is going to change the result string */ + conv->str_value.mark_as_const(); return conv; } diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 9fc68931ef6..49f32cb0245 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -2158,7 +2158,7 @@ int composite_key_cmp(void* arg, byte* key1, byte* key2) } -static int count_distinct_walk(void *elem, unsigned int count, void *arg) +static int count_distinct_walk(void *elem, element_count count, void *arg) { (*((ulonglong*)arg))++; return 0; @@ -2667,11 +2667,11 @@ int dump_leaf_key(byte* key, uint32 count __attribute__((unused)), TABLE *table= item->table; char *record= (char*) table->record[0] + table->s->null_bytes; String tmp(table->record[1], table->s->reclength, default_charset_info), tmp2; - String &result= item->result; + String *result= &item->result; Item **arg= item->args, **arg_end= item->args + item->arg_count_field; - if (result.length()) - result.append(*item->separator); + if (result->length()) + result->append(*item->separator); tmp.length(0); @@ -2698,14 +2698,14 @@ int dump_leaf_key(byte* key, uint32 count __attribute__((unused)), else res= (*arg)->val_str(&tmp); if (res) - result.append(*res); + result->append(*res); } /* stop if length of result more than max_length */ - if (result.length() > item->max_length) + if (result->length() > item->max_length) { item->count_cut_values++; - result.length(item->max_length); + result->length(item->max_length); item->warning_for_row= TRUE; return 1; } @@ -2906,8 +2906,6 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) MYF(0)); return TRUE; } - if (!args) /* allocation in constructor may fail */ - return TRUE; thd->allow_sum_func= 0; maybe_null= 0; @@ -2968,12 +2966,10 @@ bool Item_func_group_concat::setup(THD *thd) if (item->null_value) { always_null= 1; - break; + DBUG_RETURN(FALSE); } } } - if (always_null) - DBUG_RETURN(FALSE); List all_fields(list); /* diff --git a/sql/log.cc b/sql/log.cc index af1e59df255..9af70a4d527 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1638,57 +1638,6 @@ bool MYSQL_LOG::write(Log_event *event_info) if (thd) { -#if MYSQL_VERSION_ID < 50003 - /* - To make replication of charsets working in 4.1 we are writing values - of charset related variables before every statement in the binlog, - if values of those variables differ from global server-wide defaults. - We are using SET ONE_SHOT command so that the charset vars get reset - to default after the first non-SET statement. - In the next 5.0 this won't be needed as we will use the new binlog - format to store charset info. - */ - if ((thd->variables.character_set_client->number != - global_system_variables.collation_server->number) || - (thd->variables.character_set_client->number != - thd->variables.collation_connection->number) || - (thd->variables.collation_server->number != - thd->variables.collation_connection->number)) - { - char buf[200]; - int written= my_snprintf(buf, sizeof(buf)-1, - "SET ONE_SHOT CHARACTER_SET_CLIENT=%u,\ -COLLATION_CONNECTION=%u,COLLATION_DATABASE=%u,COLLATION_SERVER=%u", - (uint) thd->variables.character_set_client->number, - (uint) thd->variables.collation_connection->number, - (uint) thd->variables.collation_database->number, - (uint) thd->variables.collation_server->number); - Query_log_event e(thd, buf, written, 0, FALSE); - if (e.write(file)) - goto err; - } -#endif - /* - We use the same ONE_SHOT trick for making replication of time zones - working in 4.1. Again in 5.0 we have better means for doing this. - - TODO: we should do like we now do with charsets (no more ONE_SHOT; - logging in each event in a compact format). Dmitri says we can do: - if (time_zone_used) write the timezone to binlog (in a format to be - defined). - */ - if (thd->time_zone_used && - thd->variables.time_zone != global_system_variables.time_zone) - { - char buf[MAX_TIME_ZONE_NAME_LENGTH + 26]; - char *buf_end= strxmov(buf, "SET ONE_SHOT TIME_ZONE='", - thd->variables.time_zone->get_name()->ptr(), - "'", NullS); - Query_log_event e(thd, buf, buf_end - buf, 0, FALSE); - if (e.write(file)) - goto err; - } - if (thd->last_insert_id_used) { Intvar_log_event e(thd,(uchar) LAST_INSERT_ID_EVENT, diff --git a/sql/log_event.cc b/sql/log_event.cc index 500408f34a7..27c30cadd11 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -506,8 +506,6 @@ void Log_event::init_show_field_list(List* field_list) field_list->push_back(new Item_empty_string("Info", 20)); } -#endif /* !MYSQL_CLIENT */ - /* Log_event::write() @@ -592,7 +590,6 @@ bool Log_event::write_header(IO_CACHE* file, ulong event_data_length) */ -#ifndef MYSQL_CLIENT int Log_event::read_log_event(IO_CACHE* file, String* packet, pthread_mutex_t* log_lock) { @@ -956,6 +953,7 @@ void Query_log_event::pack_info(Protocol *protocol) } #endif +#ifndef MYSQL_CLIENT /* Query_log_event::write() @@ -973,7 +971,8 @@ bool Query_log_event::write(IO_CACHE* file) 1+8+ // code of sql_mode and sql_mode 1+1+FN_REFLEN+ // code of catalog and catalog length and catalog 1+4+ // code of autoinc and the 2 autoinc variables - 1+6 // code of charset and charset + 1+6+ // code of charset and charset + 1+1+MAX_TIME_ZONE_NAME_LENGTH // code of tz and tz length and tz name ], *start, *start_of_status; ulong event_length; @@ -1030,20 +1029,20 @@ bool Query_log_event::write(IO_CACHE* file) start_of_status= start= buf+QUERY_HEADER_LEN; if (flags2_inited) { - *(start++)= Q_FLAGS2_CODE; + *start++= Q_FLAGS2_CODE; int4store(start, flags2); start+= 4; } if (sql_mode_inited) { - *(start++)= Q_SQL_MODE_CODE; + *start++= Q_SQL_MODE_CODE; int8store(start, (ulonglong)sql_mode); start+= 8; } - if (catalog_len >= 0) // i.e. "catalog inited" (false for 4.0 events) + if (catalog_len) // i.e. "catalog inited" (false for 4.0 events) { - *(start++)= Q_CATALOG_CODE; - *(start++)= (uchar) catalog_len; + *start++= Q_CATALOG_CODE; + *start++= (uchar) catalog_len; bmove(start, catalog, catalog_len); start+= catalog_len; /* @@ -1071,15 +1070,24 @@ bool Query_log_event::write(IO_CACHE* file) } if (charset_inited) { - *(start++)= Q_CHARSET_CODE; + *start++= Q_CHARSET_CODE; memcpy(start, charset, 6); start+= 6; } + if (time_zone_len) + { + /* In the TZ sys table, column Name is of length 64 so this should be ok */ + DBUG_ASSERT(time_zone_len <= MAX_TIME_ZONE_NAME_LENGTH); + *start++= Q_TIME_ZONE_CODE; + *start++= time_zone_len; + memcpy(start, time_zone_str, time_zone_len); + start+= time_zone_len; + } /* Here there could be code like if (command-line-option-which-says-"log_this_variable" && inited) { - *(start++)= Q_THIS_VARIABLE_CODE; + *start++= Q_THIS_VARIABLE_CODE; int4store(start, this_variable); start+= 4; } @@ -1108,8 +1116,6 @@ bool Query_log_event::write(IO_CACHE* file) /* Query_log_event::Query_log_event() */ - -#ifndef MYSQL_CLIENT Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length, bool using_trans, bool suppress_use) @@ -1150,6 +1156,18 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, int2store(charset, thd_arg->variables.character_set_client->number); int2store(charset+2, thd_arg->variables.collation_connection->number); int2store(charset+4, thd_arg->variables.collation_server->number); + if (thd_arg->time_zone_used) + { + /* + Note that our event becomes dependent on the Time_zone object + representing the time zone. Fortunately such objects are never deleted + or changed during mysqld's lifetime. + */ + time_zone_len= thd_arg->variables.time_zone->get_name()->length(); + time_zone_str= thd_arg->variables.time_zone->get_name()->ptr(); + } + else + time_zone_len= 0; DBUG_PRINT("info",("Query_log_event has flags2=%lu sql_mode=%lu",flags2,sql_mode)); } #endif /* MYSQL_CLIENT */ @@ -1163,15 +1181,17 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, Query_log_event::Query_log_event(const char* buf, uint event_len, const Format_description_log_event *description_event, Log_event_type event_type) - :Log_event(buf, description_event), data_buf(0), query(NullS), catalog(NullS), + :Log_event(buf, description_event), data_buf(0), query(NullS), db(NullS), catalog_len(0), status_vars_len(0), flags2_inited(0), sql_mode_inited(0), charset_inited(0), - auto_increment_increment(1), auto_increment_offset(1) + auto_increment_increment(1), auto_increment_offset(1), + time_zone_len(0) { ulong data_len; uint32 tmp; uint8 common_header_len, post_header_len; - const char *start, *end; + char *start; + const char *end; DBUG_ENTER("Query_log_event::Query_log_event(char*,...)"); common_header_len= description_event->common_header_len; @@ -1191,7 +1211,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, slave_proxy_id= thread_id = uint4korr(buf + Q_THREAD_ID_OFFSET); exec_time = uint4korr(buf + Q_EXEC_TIME_OFFSET); - db_len = (uint)buf[Q_DB_LEN_OFFSET]; + db_len = (uint)buf[Q_DB_LEN_OFFSET]; // TODO: add a check of all *_len vars error_code = uint2korr(buf + Q_ERR_CODE_OFFSET); /* @@ -1217,7 +1237,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, /* variable-part: the status vars; only in MySQL 5.0 */ start= (char*) (buf+post_header_len); - end= (char*) (start+status_vars_len); + end= (const char*) (start+status_vars_len); for (const uchar* pos= (const uchar*) start; pos < (const uchar*) end;) { switch (*pos++) { @@ -1240,8 +1260,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, break; } case Q_CATALOG_CODE: - catalog_len= *pos; - if (catalog_len) + if ((catalog_len= *pos)) catalog= (char*) pos+1; // Will be copied later pos+= catalog_len+2; break; @@ -1257,6 +1276,13 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, pos+= 6; break; } + case Q_TIME_ZONE_CODE: + { + if ((time_zone_len= *pos)) + time_zone_str= (char *)(pos+1); + pos+= time_zone_len+1; + break; + } default: /* That's why you must write status vars in growing order of code */ DBUG_PRINT("info",("Query_log_event has unknown status vars (first has\ @@ -1265,24 +1291,29 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, } } - /* A 2nd variable part; this is common to all versions */ - - if (!(start= data_buf = (char*) my_malloc(catalog_len + data_len +2, MYF(MY_WME)))) + if (!(start= data_buf = (char*) my_malloc(catalog_len + 1 + + time_zone_len + 1 + + data_len + 1, MYF(MY_WME)))) DBUG_VOID_RETURN; - if (catalog) // If catalog is given + if (catalog_len) // If catalog is given { - memcpy((char*) start, catalog, catalog_len+1); // Copy name and end \0 + memcpy(start, catalog, catalog_len+1); // Copy name and end \0 catalog= start; start+= catalog_len+1; } + if (time_zone_len) + { + memcpy(start, time_zone_str, time_zone_len); + time_zone_str= start; + start+= time_zone_len; + *start++= 0; + } + /* A 2nd variable part; this is common to all versions */ memcpy((char*) start, end, data_len); // Copy db and query - ((char*) start)[data_len]= '\0'; // End query with \0 (For safetly) + start[data_len]= '\0'; // End query with \0 (For safetly) db= start; query= start + db_len + 1; q_len= data_len - db_len -1; - /* This is used to detect wrong parsing. Could be removed in the future. */ - DBUG_PRINT("info", ("catalog: '%s' len: %u db: '%s' len: %u q_len: %lu", - catalog, (uint) catalog_len, db, (uint) db_len,q_len)); DBUG_VOID_RETURN; } @@ -1390,6 +1421,8 @@ void Query_log_event::print_query_header(FILE* file, bool short_form, last_event_info->auto_increment_offset= auto_increment_offset; } + /* TODO: print the catalog when we feature SET CATALOG */ + if (likely(charset_inited)) { if (unlikely(!last_event_info->charset_inited)) /* first Query event */ @@ -1410,6 +1443,14 @@ void Query_log_event::print_query_header(FILE* file, bool short_form, memcpy(last_event_info->charset, charset, 6); } } + if (time_zone_len) + { + if (bcmp(last_event_info->time_zone_str, time_zone_str, time_zone_len+1)) + { + fprintf(file,"SET @@session.time_zone='%s';\n", time_zone_str); + memcpy(last_event_info->time_zone_str, time_zone_str, time_zone_len+1); + } + } } @@ -1443,7 +1484,7 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli, const char *query alloced block (see Query_log_event::exec_event()). Same for thd->db. Thank you. */ - thd->catalog= (char*) catalog; + thd->catalog= catalog_len ? (char *) catalog : (char *)""; thd->db_length= db_len; thd->db= (char*) rewrite_db(db, &thd->db_length); thd->variables.auto_increment_increment= auto_increment_increment; @@ -1513,20 +1554,28 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli, const char *query get_charset(uint2korr(charset+4), MYF(MY_WME)))) { /* - We updated the thd->variables with nonsensical values (0), and the - thread is not guaranteed to terminate now (as it may be configured - to ignore EE_UNKNOWN_CHARSET);if we're going to execute a next - statement we'll have a new charset info with it, so no problem to - have stored 0 in thd->variables. But we invalidate cached - charset to force a check next time (otherwise if next time - charset is unknown again we won't detect it). + We updated the thd->variables with nonsensical values (0). Let's + set them to something safe (i.e. which avoids crash), and we'll + stop with EE_UNKNOWN_CHARSET in compare_errors (unless set to + ignore this error). */ - rli->cached_charset_invalidate(); + set_slave_thread_default_charset(thd, rli); goto compare_errors; } thd->update_charset(); // for the charset change to take effect } } + if (time_zone_len) + { + String tmp(time_zone_str, time_zone_len, &my_charset_bin); + if (!(thd->variables.time_zone= + my_tz_find_with_opening_tz_tables(thd, &tmp))) + { + my_error(ER_UNKNOWN_TIME_ZONE, MYF(0), tmp.c_ptr()); + thd->variables.time_zone= global_system_variables.time_zone; + goto compare_errors; + } + } /* Execute the query (note that we bypass dispatch_command()) */ mysql_parse(thd, thd->query, thd->query_length); @@ -1751,6 +1800,7 @@ Start_log_event_v3::Start_log_event_v3(const char* buf, Start_log_event_v3::write() */ +#ifndef MYSQL_CLIENT bool Start_log_event_v3::write(IO_CACHE* file) { char buff[START_V3_HEADER_LEN]; @@ -1760,6 +1810,7 @@ bool Start_log_event_v3::write(IO_CACHE* file) return (write_header(file, sizeof(buff)) || my_b_safe_write(file, (byte*) buff, sizeof(buff))); } +#endif /* @@ -1975,7 +2026,7 @@ Format_description_log_event(const char* buf, DBUG_VOID_RETURN; } - +#ifndef MYSQL_CLIENT bool Format_description_log_event::write(IO_CACHE* file) { /* @@ -1992,6 +2043,7 @@ bool Format_description_log_event::write(IO_CACHE* file) return (write_header(file, sizeof(buff)) || my_b_safe_write(file, buff, sizeof(buff))); } +#endif /* SYNOPSIS @@ -2210,6 +2262,8 @@ void Load_log_event::pack_info(Protocol *protocol) #endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */ +#ifndef MYSQL_CLIENT + /* Load_log_event::write_data_header() */ @@ -2251,7 +2305,6 @@ bool Load_log_event::write_data_body(IO_CACHE* file) Load_log_event::Load_log_event() */ -#ifndef MYSQL_CLIENT Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex, const char *db_arg, const char *table_name_arg, List &fields_arg, @@ -2865,6 +2918,7 @@ Rotate_log_event::Rotate_log_event(const char* buf, uint event_len, Rotate_log_event::write() */ +#ifndef MYSQL_CLIENT bool Rotate_log_event::write(IO_CACHE* file) { char buf[ROTATE_HEADER_LEN]; @@ -2873,7 +2927,7 @@ bool Rotate_log_event::write(IO_CACHE* file) my_b_safe_write(file, (byte*)buf, ROTATE_HEADER_LEN) || my_b_safe_write(file, (byte*)new_log_ident, (uint) ident_len)); } - +#endif /* Rotate_log_event::exec_event() @@ -2931,17 +2985,10 @@ int Rotate_log_event::exec_event(struct st_relay_log_info* rli) master is 4.0 then the events are in the slave's format (conversion). */ set_slave_thread_options(thd); + set_slave_thread_default_charset(thd, rli); thd->variables.sql_mode= global_system_variables.sql_mode; thd->variables.auto_increment_increment= thd->variables.auto_increment_offset= 1; - thd->variables.character_set_client= - global_system_variables.character_set_client; - thd->variables.collation_connection= - global_system_variables.collation_connection; - thd->variables.collation_server= - global_system_variables.collation_server; - thd->update_charset(); - rli->cached_charset_invalidate(); } pthread_mutex_unlock(&rli->data_lock); pthread_cond_broadcast(&rli->data_cond); @@ -3003,6 +3050,7 @@ const char* Intvar_log_event::get_var_type_name() Intvar_log_event::write() */ +#ifndef MYSQL_CLIENT bool Intvar_log_event::write(IO_CACHE* file) { byte buf[9]; @@ -3011,6 +3059,7 @@ bool Intvar_log_event::write(IO_CACHE* file) return (write_header(file, sizeof(buf)) || my_b_safe_write(file, buf, sizeof(buf))); } +#endif /* @@ -3095,6 +3144,7 @@ Rand_log_event::Rand_log_event(const char* buf, } +#ifndef MYSQL_CLIENT bool Rand_log_event::write(IO_CACHE* file) { byte buf[16]; @@ -3103,6 +3153,7 @@ bool Rand_log_event::write(IO_CACHE* file) return (write_header(file, sizeof(buf)) || my_b_safe_write(file, buf, sizeof(buf))); } +#endif #ifdef MYSQL_CLIENT @@ -3166,11 +3217,13 @@ Xid_log_event(const char* buf, } +#ifndef MYSQL_CLIENT bool Xid_log_event::write(IO_CACHE* file) { return write_header(file, sizeof(xid)) || my_b_safe_write(file, (byte*) &xid, sizeof(xid)); } +#endif #ifdef MYSQL_CLIENT @@ -3304,6 +3357,7 @@ User_var_log_event(const char* buf, } +#ifndef MYSQL_CLIENT bool User_var_log_event::write(IO_CACHE* file) { char buf[UV_NAME_LEN_SIZE]; @@ -3338,7 +3392,7 @@ bool User_var_log_event::write(IO_CACHE* file) dec->fix_buffer_pointer(); buf2[0]= (char)(dec->intg + dec->frac); buf2[1]= (char)dec->frac; - decimal2bin((decimal*)val, buf2+2, buf2[0], buf2[1]); + decimal2bin((decimal_t*)val, buf2+2, buf2[0], buf2[1]); val_len= decimal_bin_size(buf2[0], buf2[1]) + 2; break; } @@ -3363,6 +3417,7 @@ bool User_var_log_event::write(IO_CACHE* file) my_b_safe_write(file, (byte*) buf1, buf1_length) || my_b_safe_write(file, (byte*) pos, val_len)); } +#endif /* @@ -3405,8 +3460,8 @@ void User_var_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* las int str_len= sizeof(str_buf) - 1; int precision= (int)val[0]; int scale= (int)val[1]; - decimal_digit dec_buf[10]; - decimal dec; + decimal_digit_t dec_buf[10]; + decimal_t dec; dec.len= 10; dec.buf= dec_buf; @@ -3636,6 +3691,7 @@ int Slave_log_event::get_data_size() } +#ifndef MYSQL_CLIENT bool Slave_log_event::write(IO_CACHE* file) { ulong event_length= get_data_size(); @@ -3646,6 +3702,7 @@ bool Slave_log_event::write(IO_CACHE* file) return (write_header(file, event_length) || my_b_safe_write(file, (byte*) mem_pool, event_length)); } +#endif void Slave_log_event::init_from_mem_pool(int data_size) @@ -3772,7 +3829,6 @@ Create_file_log_event(THD* thd_arg, sql_exchange* ex, sql_ex.force_new_format(); DBUG_VOID_RETURN; } -#endif /* !MYSQL_CLIENT */ /* @@ -3817,6 +3873,7 @@ bool Create_file_log_event::write_base(IO_CACHE* file) return res; } +#endif /* !MYSQL_CLIENT */ /* Create_file_log_event ctor @@ -4044,6 +4101,7 @@ Append_block_log_event::Append_block_log_event(const char* buf, uint len, Append_block_log_event::write() */ +#ifndef MYSQL_CLIENT bool Append_block_log_event::write(IO_CACHE* file) { byte buf[APPEND_BLOCK_HEADER_LEN]; @@ -4052,6 +4110,7 @@ bool Append_block_log_event::write(IO_CACHE* file) my_b_safe_write(file, buf, APPEND_BLOCK_HEADER_LEN) || my_b_safe_write(file, (byte*) block, block_len)); } +#endif /* @@ -4173,6 +4232,7 @@ Delete_file_log_event::Delete_file_log_event(const char* buf, uint len, Delete_file_log_event::write() */ +#ifndef MYSQL_CLIENT bool Delete_file_log_event::write(IO_CACHE* file) { byte buf[DELETE_FILE_HEADER_LEN]; @@ -4180,6 +4240,7 @@ bool Delete_file_log_event::write(IO_CACHE* file) return (write_header(file, sizeof(buf)) || my_b_safe_write(file, buf, sizeof(buf))); } +#endif /* @@ -4267,6 +4328,7 @@ Execute_load_log_event::Execute_load_log_event(const char* buf, uint len, Execute_load_log_event::write() */ +#ifndef MYSQL_CLIENT bool Execute_load_log_event::write(IO_CACHE* file) { byte buf[EXEC_LOAD_HEADER_LEN]; @@ -4274,6 +4336,7 @@ bool Execute_load_log_event::write(IO_CACHE* file) return (write_header(file, sizeof(buf)) || my_b_safe_write(file, buf, sizeof(buf))); } +#endif /* @@ -4477,6 +4540,7 @@ ulong Execute_load_query_log_event::get_post_header_size_for_derived() } +#ifndef MYSQL_CLIENT bool Execute_load_query_log_event::write_post_header_for_derived(IO_CACHE* file) { @@ -4487,6 +4551,7 @@ Execute_load_query_log_event::write_post_header_for_derived(IO_CACHE* file) *(buf + 4 + 4 + 4)= (char)dup_handling; return my_b_safe_write(file, (byte*) buf, EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN); } +#endif #ifdef MYSQL_CLIENT diff --git a/sql/log_event.h b/sql/log_event.h index 43a801da851..72142db0aa7 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -237,6 +237,7 @@ struct sql_ex_info #define Q_CATALOG_CODE 2 #define Q_AUTO_INCREMENT 3 #define Q_CHARSET_CODE 4 +#define Q_TIME_ZONE_CODE 5 /* Intvar event post-header */ @@ -448,6 +449,7 @@ typedef struct st_last_event_info ulong auto_increment_increment, auto_increment_offset; bool charset_inited; char charset[6]; // 3 variables, each of them storable in 2 bytes + char time_zone_str[MAX_TIME_ZONE_NAME_LENGTH]; st_last_event_info() :flags2_inited(0), sql_mode_inited(0), auto_increment_increment(1),auto_increment_offset(1), charset_inited(0) @@ -459,6 +461,7 @@ typedef struct st_last_event_info */ bzero(db, sizeof(db)); bzero(charset, sizeof(charset)); + bzero(time_zone_str, sizeof(time_zone_str)); } } LAST_EVENT_INFO; #endif @@ -583,6 +586,7 @@ public: my_free((gptr) ptr, MYF(MY_WME|MY_ALLOW_ZERO_PTR)); } +#ifndef MYSQL_CLIENT bool write_header(IO_CACHE* file, ulong data_length); virtual bool write(IO_CACHE* file) { @@ -590,13 +594,14 @@ public: write_data_header(file) || write_data_body(file)); } - virtual bool is_artificial_event() { return 0; } virtual bool write_data_header(IO_CACHE* file) { return 0; } virtual bool write_data_body(IO_CACHE* file __attribute__((unused))) { return 0; } +#endif virtual Log_event_type get_type_code() = 0; virtual bool is_valid() const = 0; + virtual bool is_artificial_event() { return 0; } inline bool get_cache_stmt() { return cache_stmt; } Log_event(const char* buf, const Format_description_log_event* description_event); virtual ~Log_event() { free_temp_buf();} @@ -672,7 +677,7 @@ public: concerned) from here. */ - int catalog_len; // <= 255 char; -1 means uninited + uint catalog_len; // <= 255 char; 0 means uninited /* We want to be able to store a variable number of N-bit status vars: @@ -714,6 +719,8 @@ public: ulong sql_mode; ulong auto_increment_increment, auto_increment_offset; char charset[6]; + uint time_zone_len; /* 0 means uninited */ + const char *time_zone_str; #ifndef MYSQL_CLIENT @@ -737,12 +744,13 @@ public: ~Query_log_event() { if (data_buf) - { my_free((gptr) data_buf, MYF(0)); - } } Log_event_type get_type_code() { return QUERY_EVENT; } +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); + virtual bool write_post_header_for_derived(IO_CACHE* file) { return FALSE; } +#endif bool is_valid() const { return query != 0; } /* @@ -751,7 +759,6 @@ public: */ virtual ulong get_post_header_size_for_derived() { return 0; } /* Writes derived event-specific part of post header. */ - virtual bool write_post_header_for_derived(IO_CACHE* file) { return FALSE; } }; #ifdef HAVE_REPLICATION @@ -790,7 +797,9 @@ public: int get_data_size(); bool is_valid() const { return master_host != 0; } Log_event_type get_type_code() { return SLAVE_EVENT; } +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif }; #endif /* HAVE_REPLICATION */ @@ -885,8 +894,10 @@ public: { return sql_ex.new_format() ? NEW_LOAD_EVENT: LOAD_EVENT; } +#ifndef MYSQL_CLIENT bool write_data_header(IO_CACHE* file); bool write_data_body(IO_CACHE* file); +#endif bool is_valid() const { return table_name != 0; } int get_data_size() { @@ -962,7 +973,9 @@ public: const Format_description_log_event* description_event); ~Start_log_event_v3() {} Log_event_type get_type_code() { return START_EVENT_V3;} +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif bool is_valid() const { return 1; } int get_data_size() { @@ -1004,7 +1017,9 @@ public: const Format_description_log_event* description_event); ~Format_description_log_event() { my_free((gptr)post_header_len, MYF(0)); } Log_event_type get_type_code() { return FORMAT_DESCRIPTION_EVENT;} +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif bool is_valid() const { return ((common_header_len >= ((binlog_version==1) ? OLD_HEADER_LEN : @@ -1054,7 +1069,9 @@ public: Log_event_type get_type_code() { return INTVAR_EVENT;} const char* get_var_type_name(); int get_data_size() { return 9; /* sizeof(type) + sizeof(val) */;} +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif bool is_valid() const { return 1; } }; @@ -1092,7 +1109,9 @@ class Rand_log_event: public Log_event ~Rand_log_event() {} Log_event_type get_type_code() { return RAND_EVENT;} int get_data_size() { return 16; /* sizeof(ulonglong) * 2*/ } +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif bool is_valid() const { return 1; } }; @@ -1127,7 +1146,9 @@ class Xid_log_event: public Log_event ~Xid_log_event() {} Log_event_type get_type_code() { return XID_EVENT;} int get_data_size() { return sizeof(xid); } +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif bool is_valid() const { return 1; } }; @@ -1169,7 +1190,9 @@ public: User_var_log_event(const char* buf, const Format_description_log_event* description_event); ~User_var_log_event() {} Log_event_type get_type_code() { return USER_VAR_EVENT;} +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif bool is_valid() const { return 1; } }; @@ -1239,7 +1262,9 @@ public: Log_event_type get_type_code() { return ROTATE_EVENT;} int get_data_size() { return ident_len + ROTATE_HEADER_LEN;} bool is_valid() const { return new_log_ident != 0; } +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif }; @@ -1299,6 +1324,7 @@ public: 4 + 1 + block_len); } bool is_valid() const { return inited_from_old || block != 0; } +#ifndef MYSQL_CLIENT bool write_data_header(IO_CACHE* file); bool write_data_body(IO_CACHE* file); /* @@ -1306,6 +1332,7 @@ public: write it as Load event - used on the slave */ bool write_base(IO_CACHE* file); +#endif }; @@ -1352,7 +1379,9 @@ public: Log_event_type get_type_code() { return APPEND_BLOCK_EVENT;} int get_data_size() { return block_len + APPEND_BLOCK_HEADER_LEN ;} bool is_valid() const { return block != 0; } +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif const char* get_db() { return db; } }; @@ -1386,7 +1415,9 @@ public: Log_event_type get_type_code() { return DELETE_FILE_EVENT;} int get_data_size() { return DELETE_FILE_HEADER_LEN ;} bool is_valid() const { return file_id != 0; } +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif const char* get_db() { return db; } }; @@ -1419,7 +1450,9 @@ public: Log_event_type get_type_code() { return EXEC_LOAD_EVENT;} int get_data_size() { return EXEC_LOAD_HEADER_LEN ;} bool is_valid() const { return file_id != 0; } +#ifndef MYSQL_CLIENT bool write(IO_CACHE* file); +#endif const char* get_db() { return db; } }; @@ -1507,7 +1540,9 @@ public: bool is_valid() const { return Query_log_event::is_valid() && file_id != 0; } ulong get_post_header_size_for_derived(); +#ifndef MYSQL_CLIENT bool write_post_header_for_derived(IO_CACHE* file); +#endif }; diff --git a/sql/my_decimal.cc b/sql/my_decimal.cc index 334c40c0f70..19b6abd7243 100644 --- a/sql/my_decimal.cc +++ b/sql/my_decimal.cc @@ -88,7 +88,7 @@ int my_decimal2string(uint mask, const my_decimal *d, int result; if (str->alloc(length)) return check_result(mask, E_DEC_OOM); - result= decimal2string((decimal*) d, (char*) str->ptr(), + result= decimal2string((decimal_t*) d, (char*) str->ptr(), &length, fixed_prec, fixed_dec, filler); str->length(length); @@ -172,7 +172,7 @@ int str2my_decimal(uint mask, const char *from, uint length, charset= &my_charset_bin; } from_end= end= (char*) from+length; - err= string2decimal((char *)from, (decimal *)decimal_value, &end); + err= string2decimal((char *)from, (decimal_t*) decimal_value, &end); if (end != from_end && !err) { /* Give warining if there is something other than end space */ diff --git a/sql/my_decimal.h b/sql/my_decimal.h index 44530acd0cc..03801390d82 100644 --- a/sql/my_decimal.h +++ b/sql/my_decimal.h @@ -69,15 +69,15 @@ inline uint my_decimal_size(uint precision, uint scale) /* - my_decimal class limits 'decimal' type to what we need in MySQL + my_decimal class limits 'decimal_t' type to what we need in MySQL It contains internally all necessary space needed by the instance so no extra memory is needed. One should call fix_buffer_pointer() function when he moves my_decimal objects in memory */ -class my_decimal :public decimal +class my_decimal :public decimal_t { - decimal_digit buffer[DECIMAL_BUFF_LENGTH]; + decimal_digit_t buffer[DECIMAL_BUFF_LENGTH]; public: @@ -97,8 +97,8 @@ public: } void fix_buffer_pointer() { buf= buffer; } - bool sign() const { return decimal::sign; } - void sign(bool s) { decimal::sign= s; } + bool sign() const { return decimal_t::sign; } + void sign(bool s) { decimal_t::sign= s; } }; @@ -165,7 +165,7 @@ inline int binary2my_decimal(uint mask, const char *bin, my_decimal *d, int prec, int scale) { - return check_result(mask, bin2decimal((char *)bin, (decimal*) d, prec, + return check_result(mask, bin2decimal((char *)bin, (decimal_t*) d, prec, scale)); } @@ -173,7 +173,7 @@ int binary2my_decimal(uint mask, const char *bin, my_decimal *d, int prec, inline int my_decimal_set_zero(my_decimal *d) { - decimal_make_zero(((decimal*) d)); + decimal_make_zero(((decimal_t*) d)); return 0; } @@ -181,7 +181,7 @@ int my_decimal_set_zero(my_decimal *d) inline bool my_decimal_is_zero(const my_decimal *decimal_value) { - return decimal_is_zero((decimal*) decimal_value); + return decimal_is_zero((decimal_t*) decimal_value); } @@ -189,7 +189,7 @@ inline int my_decimal_round(uint mask, const my_decimal *from, int scale, bool truncate, my_decimal *to) { - return check_result(mask, decimal_round((decimal*) from, to, scale, + return check_result(mask, decimal_round((decimal_t*) from, to, scale, (truncate ? TRUNCATE : HALF_UP))); } @@ -197,14 +197,14 @@ int my_decimal_round(uint mask, const my_decimal *from, int scale, inline int my_decimal_floor(uint mask, const my_decimal *from, my_decimal *to) { - return check_result(mask, decimal_round((decimal*) from, to, 0, FLOOR)); + return check_result(mask, decimal_round((decimal_t*) from, to, 0, FLOOR)); } inline int my_decimal_ceiling(uint mask, const my_decimal *from, my_decimal *to) { - return check_result(mask, decimal_round((decimal*) from, to, 0, CEILING)); + return check_result(mask, decimal_round((decimal_t*) from, to, 0, CEILING)); } @@ -219,7 +219,7 @@ int my_decimal2int(uint mask, const my_decimal *d, my_bool unsigned_flag, { my_decimal rounded; /* decimal_round can return only E_DEC_TRUNCATED */ - decimal_round((decimal*)d, &rounded, 0, HALF_UP); + decimal_round((decimal_t*)d, &rounded, 0, HALF_UP); return check_result(mask, (unsigned_flag ? decimal2ulonglong(&rounded, (ulonglong *)l) : decimal2longlong(&rounded, l))); @@ -230,14 +230,14 @@ inline int my_decimal2double(uint mask, const my_decimal *d, double *result) { /* No need to call check_result as this will always succeed */ - return decimal2double((decimal*) d, result); + return decimal2double((decimal_t*) d, result); } inline int str2my_decimal(uint mask, const char *str, my_decimal *d, char **end) { - return check_result(mask, string2decimal(str, (decimal*) d, end)); + return check_result(mask, string2decimal(str, (decimal_t*) d, end)); } @@ -255,7 +255,7 @@ int string2my_decimal(uint mask, const String *str, my_decimal *d) inline int double2my_decimal(uint mask, double val, my_decimal *d) { - return check_result(mask, double2decimal(val, (decimal*) d)); + return check_result(mask, double2decimal(val, (decimal_t*) d)); } @@ -269,7 +269,7 @@ int int2my_decimal(uint mask, longlong i, my_bool unsigned_flag, my_decimal *d) inline -void my_decimal_neg(st_decimal *arg) +void my_decimal_neg(decimal_t *arg) { decimal_neg(arg); } @@ -279,7 +279,7 @@ inline int my_decimal_add(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b) { - return check_result(mask, decimal_add((decimal*) a, (decimal*) b, res)); + return check_result(mask, decimal_add((decimal_t*) a, (decimal_t*) b, res)); } @@ -287,7 +287,7 @@ inline int my_decimal_sub(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b) { - return check_result(mask, decimal_sub((decimal*) a, (decimal*) b, res)); + return check_result(mask, decimal_sub((decimal_t*) a, (decimal_t*) b, res)); } @@ -295,7 +295,7 @@ inline int my_decimal_mul(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b) { - return check_result(mask, decimal_mul((decimal*) a, (decimal*) b, res)); + return check_result(mask, decimal_mul((decimal_t*) a, (decimal_t*) b, res)); } @@ -303,7 +303,7 @@ inline int my_decimal_div(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b, int div_scale_inc) { - return check_result(mask, decimal_div((decimal*) a, (decimal*) b, res, + return check_result(mask, decimal_div((decimal_t*) a, (decimal_t*) b, res, div_scale_inc)); } @@ -312,7 +312,7 @@ inline int my_decimal_mod(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b) { - return check_result(mask, decimal_mod((decimal*) a, (decimal*) b, res)); + return check_result(mask, decimal_mod((decimal_t*) a, (decimal_t*) b, res)); } @@ -320,14 +320,14 @@ int my_decimal_mod(uint mask, my_decimal *res, const my_decimal *a, inline int my_decimal_cmp(const my_decimal *a, const my_decimal *b) { - return decimal_cmp((decimal*) a, (decimal*) b); + return decimal_cmp((decimal_t*) a, (decimal_t*) b); } inline void max_my_decimal(my_decimal *to, int precision, int frac) { DBUG_ASSERT(precision <= DECIMAL_MAX_LENGTH); - max_decimal(precision, frac, (decimal*) to); + max_decimal(precision, frac, (decimal_t*) to); } #endif /*my_decimal_h*/ diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index dfa945c3fd3..1ee53e5ed64 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -264,6 +264,12 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset; /* Flag set if setup_tables already done */ #define OPTION_SETUP_TABLES_DONE (1L << 30) +/* + Maximum length of time zone name that we support + (Time zone name is char(64) in db). mysqlbinlog needs it. +*/ +#define MAX_TIME_ZONE_NAME_LENGTH 72 + /* The rest of the file is included in the server only */ #ifndef MYSQL_CLIENT diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 6747b79703b..ecaa7ace841 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3310,9 +3310,10 @@ default_service_handling(char **argv, int main(int argc, char **argv) { - /* When several instances are running on the same machine, we - need to have an unique named hEventShudown through the - application PID e.g.: MySQLShutdown1890; MySQLShutdown2342 + /* + When several instances are running on the same machine, we + need to have an unique named hEventShudown through the + application PID e.g.: MySQLShutdown1890; MySQLShutdown2342 */ int10_to_str((int) GetCurrentProcessId(),strmov(shutdown_event_name, "MySQLShutdown"), 10); diff --git a/sql/set_var.cc b/sql/set_var.cc index 0c9483b2783..f5df4dfbd2c 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -2095,27 +2095,6 @@ void sys_var_character_set_server::set_default(THD *thd, enum_var_type type) } } -#if defined(HAVE_REPLICATION) && (MYSQL_VERSION_ID < 50003) -bool sys_var_character_set_server::check(THD *thd, set_var *var) -{ - /* - To be perfect we should fail even if we are a 5.0.3 slave, a 4.1 master, - and user wants to change our global character set variables. Because - replicating a 4.1 assumes those are not changed. But that's not easy to - do. - */ - if ((var->type == OPT_GLOBAL) && - (mysql_bin_log.is_open() || - active_mi->slave_running || active_mi->rli.slave_running)) - { - my_error(ER_LOGGING_PROHIBIT_CHANGING_OF, MYF(0), - "character set, collation"); - return 1; - } - return sys_var_character_set::check(thd,var); -} -#endif - CHARSET_INFO ** sys_var_character_set_database::ci_ptr(THD *thd, enum_var_type type) { @@ -2208,20 +2187,6 @@ void sys_var_collation_database::set_default(THD *thd, enum_var_type type) } } -#if defined(HAVE_REPLICATION) && (MYSQL_VERSION_ID < 50003) -bool sys_var_collation_server::check(THD *thd, set_var *var) -{ - if ((var->type == OPT_GLOBAL) && - (mysql_bin_log.is_open() || - active_mi->slave_running || active_mi->rli.slave_running)) - { - my_error(ER_LOGGING_PROHIBIT_CHANGING_OF, MYF(0), - "character set, collation"); - return 1; - } - return sys_var_collation::check(thd,var); -} -#endif bool sys_var_collation_server::update(THD *thd, set_var *var) { @@ -2560,16 +2525,6 @@ bool sys_var_thd_time_zone::check(THD *thd, set_var *var) String str(buff, sizeof(buff), &my_charset_latin1); String *res= var->value->val_str(&str); -#if defined(HAVE_REPLICATION) - if ((var->type == OPT_GLOBAL) && - (mysql_bin_log.is_open() || - active_mi->slave_running || active_mi->rli.slave_running)) - { - my_error(ER_LOGGING_PROHIBIT_CHANGING_OF, MYF(0), "time zone"); - return 1; - } -#endif - if (!(var->save_result.time_zone= my_tz_find(res, thd->lex->time_zone_tables_used))) { @@ -2605,7 +2560,18 @@ byte *sys_var_thd_time_zone::value_ptr(THD *thd, enum_var_type type, if (type == OPT_GLOBAL) return (byte *)(global_system_variables.time_zone->get_name()->ptr()); else + { + /* + This is an ugly fix for replication: we don't replicate properly queries + invoking system variables' values to update tables; but + CONVERT_TZ(,,@@session.time_zone) is so popular that we make it + replicable (i.e. we tell the binlog code to store the session + timezone). If it's the global value which was used we can't replicate + (binlog code stores session value only). + */ + thd->time_zone_used= 1; return (byte *)(thd->variables.time_zone->get_name()->ptr()); + } } diff --git a/sql/set_var.h b/sql/set_var.h index d78c228c142..585f6df3547 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -565,9 +565,6 @@ class sys_var_character_set_server :public sys_var_character_set public: sys_var_character_set_server(const char *name_arg) : sys_var_character_set(name_arg) {} -#if defined(HAVE_REPLICATION) && (MYSQL_VERSION_ID < 50003) - bool check(THD *thd, set_var *var); -#endif void set_default(THD *thd, enum_var_type type); CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type); }; @@ -603,9 +600,6 @@ class sys_var_collation_server :public sys_var_collation { public: sys_var_collation_server(const char *name_arg) :sys_var_collation(name_arg) {} -#if defined(HAVE_REPLICATION) && (MYSQL_VERSION_ID < 50003) - bool check(THD *thd, set_var *var); -#endif bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index d4caeebb70c..886c37b7061 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5332,3 +5332,5 @@ ER_STARTUP eng "%s: ready for connections.\nVersion: '%s' socket: '%s' port: %d %s" ER_LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR eng "Can't load value from file with fixed size rows to variable" +ER_CANT_CREATE_USER_WITH_GRANT + eng "You are not allowed to create a user with GRANT" diff --git a/sql/slave.cc b/sql/slave.cc index 73dd0fd13c3..c92350f4a2f 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1456,11 +1456,10 @@ be equal for replication to work"; such check will broke everything for them. (And now everything will work for them because by default both their master and slave will have 'SYSTEM' time zone). - - TODO: when the new replication of timezones is sorted out with Dmitri, - change >= '4' to == '4'. + This check is only necessary for 4.x masters (and < 5.0.4 masters but + those were alpha). */ - if ((*mysql->server_version >= '4') && + if ((*mysql->server_version == '4') && !mysql_real_query(mysql, "SELECT @@GLOBAL.TIME_ZONE", 25) && (master_res= mysql_store_result(mysql))) { @@ -2770,6 +2769,18 @@ void set_slave_thread_options(THD* thd) thd->variables.completion_type= 0; } +void set_slave_thread_default_charset(THD* thd, RELAY_LOG_INFO *rli) +{ + thd->variables.character_set_client= + global_system_variables.character_set_client; + thd->variables.collation_connection= + global_system_variables.collation_connection; + thd->variables.collation_server= + global_system_variables.collation_server; + thd->update_charset(); + rli->cached_charset_invalidate(); +} + /* init_slave_thread() */ diff --git a/sql/slave.h b/sql/slave.h index ee5541ffe08..bc41cd4deca 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -562,6 +562,7 @@ int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,ulonglong pos, int purge_relay_logs(RELAY_LOG_INFO* rli, THD *thd, bool just_reset, const char** errmsg); void set_slave_thread_options(THD* thd); +void set_slave_thread_default_charset(THD* thd, RELAY_LOG_INFO *rli); void rotate_relay_log(MASTER_INFO* mi); extern "C" pthread_handler_decl(handle_slave_io,arg); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index c51e5e00aa1..de5df4559db 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1627,7 +1627,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, else if (((thd->variables.sql_mode & MODE_NO_AUTO_CREATE_USER) && !password_len) || !create_user) { - my_error(ER_NO_PERMISSION_TO_CREATE_USER, MYF(0), + my_error(ER_CANT_CREATE_USER_WITH_GRANT, MYF(0), thd->user, thd->host_or_ip); goto end; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index b6cda4f8d85..856fb937b6e 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -10144,20 +10144,18 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), join->sum_funcs_end[send_group_parts]); if (join->having && join->having->val_int() == 0) error= -1; - else if ((error=table->file->write_row(table->record[0]))) + else if ((error= table->file->write_row(table->record[0]))) { if (create_myisam_from_heap(join->thd, table, &join->tmp_table_param, error, 0)) DBUG_RETURN(-1); } - if (join->rollup.state != ROLLUP::STATE_NONE && error <= 0) + if (join->rollup.state != ROLLUP::STATE_NONE) { if (join->rollup_write_data((uint) (idx+1), table)) - error= 1; + DBUG_RETURN(-1); } - if (error > 0) - DBUG_RETURN(-1); if (end_of_records) DBUG_RETURN(0); } @@ -12684,17 +12682,21 @@ bool JOIN::rollup_make_fields(List &fields_arg, List &sel_fields, { /* Check if this is something that is part of this group by */ ORDER *group_tmp; - for (group_tmp= start_group, i-- ; + for (group_tmp= start_group, i= pos ; group_tmp ; group_tmp= group_tmp->next, i++) { if (*group_tmp->item == item) { + Item_null_result *null_item; /* This is an element that is used by the GROUP BY and should be set to NULL in this level */ item->maybe_null= 1; // Value will be null sometimes - Item_null_result *null_item= rollup.null_items[i]; + null_item= rollup.null_items[i]; + DBUG_ASSERT(null_item->result_field == 0 || + null_item->result_field == + ((Item_field *) item)->result_field); null_item->result_field= ((Item_field *) item)->result_field; item= null_item; break; diff --git a/sql/sql_string.h b/sql/sql_string.h index fc1e9f171b6..7ece9885040 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -84,6 +84,7 @@ public: inline char& operator [] (uint32 i) const { return Ptr[i]; } inline void length(uint32 len) { str_length=len ; } inline bool is_empty() { return (str_length == 0); } + inline void mark_as_const() { Alloced_length= 0;} inline const char *ptr() const { return Ptr; } inline char *c_ptr() { @@ -205,10 +206,6 @@ public: } } } - inline void shrink_to_length() - { - Alloced_length= str_length; - } bool is_alloced() { return alloced; } inline String& operator = (const String &s) { diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 82d887891cf..b125eeaf03a 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -613,7 +613,7 @@ int prepare_create_field(create_field *sql_field, Prepares the table and key structures for table creation. NOTES - sets create_info->varchar if the table has a varchar or blob. + sets create_info->varchar if the table has a varchar RETURN VALUES 0 ok @@ -862,12 +862,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, ×tamps, ×tamps_with_niladic, file->table_flags())) DBUG_RETURN(-1); - if (sql_field->sql_type == FIELD_TYPE_BLOB || - sql_field->sql_type == FIELD_TYPE_MEDIUM_BLOB || - sql_field->sql_type == FIELD_TYPE_TINY_BLOB || - sql_field->sql_type == FIELD_TYPE_LONG_BLOB || - sql_field->sql_type == FIELD_TYPE_GEOMETRY || - sql_field->sql_type == MYSQL_TYPE_VARCHAR) + if (sql_field->sql_type == MYSQL_TYPE_VARCHAR) create_info->varchar= 1; sql_field->offset= pos; if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER) diff --git a/sql/table.cc b/sql/table.cc index 939690395d4..9238d8aa68e 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -149,6 +149,15 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, *fn_ext(index_file)='\0'; // Remove .frm extension share->frm_version= head[2]; + /* + Check if .frm file created by MySQL 5.0. In this case we want to + display CHAR fields as CHAR and not as VARCHAR. + We do it this way as we want to keep the old frm version to enable + MySQL 4.1 to read these files. + */ + if (share->frm_version == FRM_VER_TRUE_VARCHAR -1 && head[33] == 5) + share->frm_version= FRM_VER_TRUE_VARCHAR; + share->db_type= ha_checktype((enum db_type) (uint) *(head+3)); share->db_create_options= db_create_options=uint2korr(head+30); share->db_options_in_use= share->db_create_options; @@ -1317,6 +1326,7 @@ File create_frm(register my_string name, uint reclength, uchar *fileinfo, create_info->table_options|=HA_OPTION_LONG_BLOB_PTR; // Use portable blob pointers int2store(fileinfo+30,create_info->table_options); fileinfo[32]=0; // No filename anymore + fileinfo[33]=5; // Mark for 5.0 frm file int4store(fileinfo+34,create_info->avg_row_length); fileinfo[38]= (create_info->default_table_charset ? create_info->default_table_charset->number : 0); diff --git a/sql/tztime.cc b/sql/tztime.cc index bd9d49f0ab0..983c630071e 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -2178,7 +2178,7 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables) DBUG_PRINT("enter", ("time zone name='%s'", name ? ((String *)name)->c_ptr() : "NULL")); - DBUG_ASSERT(!time_zone_tables_exist || tz_tables); + DBUG_ASSERT(!time_zone_tables_exist || tz_tables || current_thd->slave_thread); if (!name) DBUG_RETURN(0); @@ -2210,7 +2210,7 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables) (const byte *)name->ptr(), name->length()))) result_tz= tmp_tzname->tz; - else if (time_zone_tables_exist) + else if (time_zone_tables_exist && tz_tables) result_tz= tz_load_from_open_tables(name, tz_tables); } @@ -2219,6 +2219,58 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables) DBUG_RETURN(result_tz); } + +/* + A more standalone version of my_tz_find(): will open tz tables if needed. + This is so far only used by replication, where time zone setting does not + happen in the usual query context. + + SYNOPSIS + my_tz_find_with_opening_tz_tables() + thd - pointer to thread's THD structure + name - time zone specification + + DESCRIPTION + This function tries to find a time zone which matches the named passed in + argument. If it fails, it will open time zone tables and re-try the + search. + This function is needed for the slave SQL thread, which does not do the + addition of time zone tables which is usually done during query parsing + (as time zone setting by slave does not happen in mysql_parse() but + before). So it needs to open tz tables by itself if needed. + See notes of my_tz_find() as they also apply here. + + RETURN VALUE + Pointer to corresponding Time_zone object. 0 - in case of bad time zone + specification or other error. + +*/ +Time_zone *my_tz_find_with_opening_tz_tables(THD *thd, const String *name) +{ + Time_zone *tz; + DBUG_ENTER("my_tz_find_with_opening_tables"); + DBUG_ASSERT(thd); + DBUG_ASSERT(thd->slave_thread); // intended for use with slave thread only + if (!(tz= my_tz_find(name, 0)) && time_zone_tables_exist) + { + /* + Probably we have not loaded this time zone yet so let us look it up in + our time zone tables. Note that if we don't have tz tables on this + slave, we don't even try. + */ + TABLE_LIST tables[4]; + TABLE_LIST *dummy; + TABLE_LIST **dummyp= &dummy; + tz_init_table_list(tables, &dummyp); + if (simple_open_n_lock_tables(thd, tables)) + DBUG_RETURN(0); + tz= my_tz_find(name, tables); + /* We need to close tables _now_ to not pollute coming query */ + close_thread_tables(thd); + } + DBUG_RETURN(tz); +} + #endif /* !defined(TESTTIME) && !defined(TZINFO2SQL) */ diff --git a/sql/tztime.h b/sql/tztime.h index caf663fc8cb..777e521d761 100644 --- a/sql/tztime.h +++ b/sql/tztime.h @@ -61,6 +61,7 @@ extern Time_zone * my_tz_UTC; extern Time_zone * my_tz_SYSTEM; extern TABLE_LIST * my_tz_get_table_list(THD *thd, TABLE_LIST ***global_next_ptr); extern Time_zone * my_tz_find(const String *name, TABLE_LIST *tz_tables); +extern Time_zone * my_tz_find_with_opening_tz_tables(THD *thd, const String *name); extern my_bool my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap); extern void my_tz_free(); @@ -96,10 +97,4 @@ inline bool my_tz_check_n_skip_implicit_tables(TABLE_LIST **table, return FALSE; } -/* - Maximum length of time zone name that we support - (Time zone name is char(64) in db) -*/ -#define MAX_TIME_ZONE_NAME_LENGTH 72 - #endif /* !defined(TESTTIME) && !defined(TZINFO2SQL) */ diff --git a/strings/decimal.c b/strings/decimal.c index f288a93eb5e..d7bea3e291d 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -109,20 +109,20 @@ /* Internally decimal numbers are stored base 10^9 (see DIG_BASE below) - So one "decimal_digit" is + So one variable of type decimal_digit_t is limited: 0 < decimal_digit <= DIG_MAX < DIG_BASE - in the struct st_decimal: + in the struct st_decimal_t: - intg is the number of *decimal* digits (NOT number of decimal_digit's !) + intg is the number of *decimal* digits (NOT number of decimal_digit_t's !) before the point frac - number of decimal digits after the point - buf is an array of decimal_digit's - len is the length of buf (length of allocated space) in decimal_digit's, + buf is an array of decimal_digit_t's + len is the length of buf (length of allocated space) in decimal_digit_t's, not in bytes */ -typedef decimal_digit dec1; +typedef decimal_digit_t dec1; typedef longlong dec2; #define DIG_PER_DEC1 9 @@ -223,7 +223,7 @@ static const dec1 frac_max[DIG_PER_DEC1-1]={ to->buf and to->len must be set. */ -void max_decimal(int precision, int frac, decimal *to) +void max_decimal(int precision, int frac, decimal_t *to) { int intpart; dec1 *buf= to->buf; @@ -250,7 +250,7 @@ void max_decimal(int precision, int frac, decimal *to) } -static dec1 *remove_leading_zeroes(decimal *from, int *intg_result) +static dec1 *remove_leading_zeroes(decimal_t *from, int *intg_result) { int intg= from->intg, i; dec1 *buf0= from->buf; @@ -281,7 +281,7 @@ static dec1 *remove_leading_zeroes(decimal *from, int *intg_result) from number for processing */ -void decimal_optimize_fraction(decimal *from) +void decimal_optimize_fraction(decimal_t *from) { int frac= from->frac, i; dec1 *buf0= from->buf + ROUND_UP(from->intg) + ROUND_UP(frac) - 1; @@ -328,7 +328,7 @@ void decimal_optimize_fraction(decimal *from) E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW */ -int decimal2string(decimal *from, char *to, int *to_len, +int decimal2string(decimal_t *from, char *to, int *to_len, int fixed_precision, int fixed_decimals, char filler) { @@ -453,7 +453,7 @@ int decimal2string(decimal *from, char *to, int *to_len, be written by this address */ -static void digits_bounds(decimal *from, int *start_result, int *end_result) +static void digits_bounds(decimal_t *from, int *start_result, int *end_result) { int start, stop, i; dec1 *buf_beg= from->buf; @@ -520,7 +520,7 @@ static void digits_bounds(decimal *from, int *start_result, int *end_result) 'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive) */ -void do_mini_left_shift(decimal *dec, int shift, int beg, int last) +void do_mini_left_shift(decimal_t *dec, int shift, int beg, int last) { dec1 *from= dec->buf + ROUND_UP(beg + 1) - 1; dec1 *end= dec->buf + ROUND_UP(last) - 1; @@ -550,7 +550,7 @@ void do_mini_left_shift(decimal *dec, int shift, int beg, int last) 'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive) */ -void do_mini_right_shift(decimal *dec, int shift, int beg, int last) +void do_mini_right_shift(decimal_t *dec, int shift, int beg, int last) { dec1 *from= dec->buf + ROUND_UP(last) - 1; dec1 *end= dec->buf + ROUND_UP(beg + 1) - 1; @@ -583,7 +583,7 @@ void do_mini_right_shift(decimal *dec, int shift, int beg, int last) E_DEC_TRUNCATED number was rounded to fit into buffer */ -int decimal_shift(decimal *dec, int shift) +int decimal_shift(decimal_t *dec, int shift) { /* index of first non zero digit (all indexes from 0) */ int beg; @@ -780,7 +780,8 @@ int decimal_shift(decimal *dec, int shift) (to make error handling easier) */ -int internal_str2dec(const char *from, decimal *to, char **end, my_bool fixed) +int +internal_str2dec(const char *from, decimal_t *to, char **end, my_bool fixed) { const char *s= from, *s1, *endp, *end_of_string= *end; int i, intg, frac, error, intg1, frac1; @@ -937,7 +938,7 @@ fatal_error: E_DEC_OK */ -int decimal2double(decimal *from, double *to) +int decimal2double(decimal_t *from, double *to) { double x=0, t=DIG_BASE; int intg, frac; @@ -963,7 +964,7 @@ int decimal2double(decimal *from, double *to) E_DEC_OK/E_DEC_OVERFLOW/E_DEC_TRUNCATED */ -int double2decimal(double from, decimal *to) +int double2decimal(double from, decimal_t *to) { /* TODO: fix it, when we'll have dtoa */ char s[400], *end; @@ -972,7 +973,7 @@ int double2decimal(double from, decimal *to) return string2decimal(s, to, &end); } -static int ull2dec(ulonglong from, decimal *to) +static int ull2dec(ulonglong from, decimal_t *to) { int intg1, error=E_DEC_OK; ulonglong x=from; @@ -998,20 +999,20 @@ static int ull2dec(ulonglong from, decimal *to) return error; } -int ulonglong2decimal(ulonglong from, decimal *to) +int ulonglong2decimal(ulonglong from, decimal_t *to) { to->sign=0; return ull2dec(from, to); } -int longlong2decimal(longlong from, decimal *to) +int longlong2decimal(longlong from, decimal_t *to) { if ((to->sign= from < 0)) return ull2dec(-from, to); return ull2dec(from, to); } -int decimal2ulonglong(decimal *from, ulonglong *to) +int decimal2ulonglong(decimal_t *from, ulonglong *to) { dec1 *buf=from->buf; ulonglong x=0; @@ -1040,7 +1041,7 @@ int decimal2ulonglong(decimal *from, ulonglong *to) return E_DEC_OK; } -int decimal2longlong(decimal *from, longlong *to) +int decimal2longlong(decimal_t *from, longlong *to) { dec1 *buf=from->buf; longlong x=0; @@ -1112,7 +1113,7 @@ int decimal2longlong(decimal *from, longlong *to) 3. The first intg % DIG_PER_DEC1 digits are stored in the reduced number of bytes (enough bytes to store this number of digits - see dig2bytes) - 4. same for frac - full decimal_digit's are stored as is, + 4. same for frac - full decimal_digit_t's are stored as is, the last frac % DIG_PER_DEC1 digits - in the reduced number of bytes. 5. If the number is negative - every byte is inversed. 5. The very first bit of the resulting byte array is inverted (because @@ -1122,7 +1123,7 @@ int decimal2longlong(decimal *from, longlong *to) 1234567890.1234 - internally is represented as 3 decimal_digit's + internally is represented as 3 decimal_digit_t's 1 234567890 123400000 @@ -1131,13 +1132,13 @@ int decimal2longlong(decimal *from, longlong *to) 00-00-00-01 0D-FB-38-D2 07-5A-EF-40 - now, middle decimal_digit is full - it stores 9 decimal digits. It goes + now, middle decimal_digit_t is full - it stores 9 decimal digits. It goes into binary representation as is: ........... 0D-FB-38-D2 ............ - First decimal_digit has only one decimal digit. We can store one digit in + First decimal_digit_t has only one decimal digit. We can store one digit in one byte, no need to waste four: 01 0D-FB-38-D2 ............ @@ -1155,7 +1156,7 @@ int decimal2longlong(decimal *from, longlong *to) 7E F2 04 37 2D FB 2D */ -int decimal2bin(decimal *from, char *to, int precision, int frac) +int decimal2bin(decimal_t *from, char *to, int precision, int frac) { dec1 mask=from->sign ? -1 : 0, *buf1=from->buf, *stop1; int error=E_DEC_OK, intg=precision-frac, @@ -1283,7 +1284,7 @@ int decimal2bin(decimal *from, char *to, int precision, int frac) E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW */ -int bin2decimal(char *from, decimal *to, int precision, int scale) +int bin2decimal(char *from, decimal_t *to, int precision, int scale) { int error=E_DEC_OK, intg=precision-scale, intg0=intg/DIG_PER_DEC1, frac0=scale/DIG_PER_DEC1, @@ -1424,7 +1425,9 @@ int decimal_bin_size(int precision, int scale) E_DEC_OK/E_DEC_TRUNCATED */ -int decimal_round(decimal *from, decimal *to, int scale, decimal_round_mode mode) +int +decimal_round(decimal_t *from, decimal_t *to, int scale, + decimal_round_mode mode) { int frac0=scale>0 ? ROUND_UP(scale) : scale/DIG_PER_DEC1, frac1=ROUND_UP(from->frac), round_digit, @@ -1585,7 +1588,7 @@ done: multiply by sizeof(dec1) */ -int decimal_result_size(decimal *from1, decimal *from2, char op, int param) +int decimal_result_size(decimal_t *from1, decimal_t *from2, char op, int param) { switch (op) { case '-': @@ -1604,7 +1607,7 @@ int decimal_result_size(decimal *from1, decimal *from2, char op, int param) return -1; /* shut up the warning */ } -static int do_add(decimal *from1, decimal *from2, decimal *to) +static int do_add(decimal_t *from1, decimal_t *from2, decimal_t *to) { int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg), frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac), @@ -1680,7 +1683,7 @@ static int do_add(decimal *from1, decimal *from2, decimal *to) /* to=from1-from2. if to==0, return -1/0/+1 - the result of the comparison */ -static int do_sub(decimal *from1, decimal *from2, decimal *to) +static int do_sub(decimal_t *from1, decimal_t *from2, decimal_t *to) { int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg), frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac); @@ -1741,7 +1744,7 @@ static int do_sub(decimal *from1, decimal *from2, decimal *to) /* ensure that always from1 > from2 (and intg1 >= intg2) */ if (carry) { - swap_variables(decimal *,from1,from1); + swap_variables(decimal_t *,from1,from1); swap_variables(dec1 *,start1, start2); swap_variables(int,intg1,intg2); swap_variables(int,frac1,frac2); @@ -1807,28 +1810,28 @@ static int do_sub(decimal *from1, decimal *from2, decimal *to) return error; } -int decimal_add(decimal *from1, decimal *from2, decimal *to) +int decimal_add(decimal_t *from1, decimal_t *from2, decimal_t *to) { if (likely(from1->sign == from2->sign)) return do_add(from1, from2, to); return do_sub(from1, from2, to); } -int decimal_sub(decimal *from1, decimal *from2, decimal *to) +int decimal_sub(decimal_t *from1, decimal_t *from2, decimal_t *to) { if (likely(from1->sign == from2->sign)) return do_sub(from1, from2, to); return do_add(from1, from2, to); } -int decimal_cmp(decimal *from1, decimal *from2) +int decimal_cmp(decimal_t *from1, decimal_t *from2) { if (likely(from1->sign == from2->sign)) return do_sub(from1, from2, 0); return from1->sign > from2->sign ? -1 : 1; } -int decimal_is_zero(decimal *from) +int decimal_is_zero(decimal_t *from) { dec1 *buf1=from->buf, *end=buf1+ROUND_UP(from->intg)+ROUND_UP(from->frac); @@ -1859,7 +1862,7 @@ int decimal_is_zero(decimal *from) XXX if this library is to be used with huge numbers of thousands of digits, fast multiplication must be implemented. */ -int decimal_mul(decimal *from1, decimal *from2, decimal *to) +int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to) { int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg), frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac), @@ -1932,8 +1935,8 @@ int decimal_mul(decimal *from1, decimal *from2, decimal *to) changed to malloc (or at least fallback to malloc if alloca() fails) but then, decimal_mod() should be rewritten too :( */ -static int do_div_mod(decimal *from1, decimal *from2, - decimal *to, decimal *mod, int scale_incr) +static int do_div_mod(decimal_t *from1, decimal_t *from2, + decimal_t *to, decimal_t *mod, int scale_incr) { int frac1=ROUND_UP(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1, frac2=ROUND_UP(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2, @@ -2208,7 +2211,8 @@ done: see do_div_mod() */ -int decimal_div(decimal *from1, decimal *from2, decimal *to, int scale_incr) +int +decimal_div(decimal_t *from1, decimal_t *from2, decimal_t *to, int scale_incr) { return do_div_mod(from1, from2, to, 0, scale_incr); } @@ -2240,7 +2244,7 @@ int decimal_div(decimal *from1, decimal *from2, decimal *to, int scale_incr) thus, there's no requirement for M or N to be integers */ -int decimal_mod(decimal *from1, decimal *from2, decimal *to) +int decimal_mod(decimal_t *from1, decimal_t *from2, decimal_t *to) { return do_div_mod(from1, from2, 0, to, 0); } @@ -2248,10 +2252,10 @@ int decimal_mod(decimal *from1, decimal *from2, decimal *to) #ifdef MAIN int full= 0; -decimal a, b, c; +decimal_t a, b, c; char buf1[100], buf2[100], buf3[100]; -void dump_decimal(decimal *d) +void dump_decimal(decimal_t *d) { int i; printf("/* intg=%d, frac=%d, sign=%d, buf[]={", d->intg, d->frac, d->sign); @@ -2271,7 +2275,7 @@ void check_result_code(int actual, int want) } -void print_decimal(decimal *d, const char *orig, int actual, int want) +void print_decimal(decimal_t *d, const char *orig, int actual, int want) { char s[100]; int slen=sizeof(s);