Commit e1dc7b06 authored by pekka@mysql.com's avatar pekka@mysql.com

Merge pnousiainen@bk-internal.mysql.com:/home/bk/mysql-4.1

into mysql.com:/orca/space/pekka/ndb/version/my41
parents 1a432513 6337ea8a
...@@ -163,6 +163,7 @@ pem@mysql.com ...@@ -163,6 +163,7 @@ pem@mysql.com
peter@linux.local peter@linux.local
peter@mysql.com peter@mysql.com
peterg@mysql.com peterg@mysql.com
petr@mysql.com
pgulutzan@linux.local pgulutzan@linux.local
ram@deer.(none) ram@deer.(none)
ram@gw.mysql.r18.ru ram@gw.mysql.r18.ru
......
...@@ -1687,7 +1687,7 @@ AC_DEFUN([MYSQL_CHECK_NDBCLUSTER], [ ...@@ -1687,7 +1687,7 @@ AC_DEFUN([MYSQL_CHECK_NDBCLUSTER], [
ndbcluster_includes="-I../ndb/include -I../ndb/include/ndbapi" ndbcluster_includes="-I../ndb/include -I../ndb/include/ndbapi"
ndbcluster_libs="\$(top_builddir)/ndb/src/.libs/libndbclient.a" ndbcluster_libs="\$(top_builddir)/ndb/src/.libs/libndbclient.a"
ndbcluster_system_libs="" ndbcluster_system_libs=""
ndb_mgmclient_libs="\$(top_builddir)/ndb/src/mgmclient/libndbmgmclient.la \$(top_builddir)/mysys/libmysys.a" ndb_mgmclient_libs="\$(top_builddir)/ndb/src/mgmclient/libndbmgmclient.la"
MYSQL_CHECK_NDB_OPTIONS MYSQL_CHECK_NDB_OPTIONS
;; ;;
* ) * )
......
...@@ -20,8 +20,7 @@ ...@@ -20,8 +20,7 @@
INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/regex \ INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/regex \
$(openssl_includes) $(openssl_includes)
LIBS = @CLIENT_LIBS@ LIBS = @CLIENT_LIBS@
DEPLIB= @ndb_mgmclient_libs@ \ DEPLIB= ../libmysql/libmysqlclient.la
../libmysql/libmysqlclient.la
LDADD = @CLIENT_EXTRA_LDFLAGS@ $(DEPLIB) LDADD = @CLIENT_EXTRA_LDFLAGS@ $(DEPLIB)
bin_PROGRAMS = mysql mysqladmin mysqlcheck mysqlshow \ bin_PROGRAMS = mysql mysqladmin mysqlcheck mysqlshow \
mysqldump mysqlimport mysqltest mysqlbinlog mysqlmanagerc mysqlmanager-pwgen mysqldump mysqlimport mysqltest mysqlbinlog mysqlmanagerc mysqlmanager-pwgen
......
...@@ -1609,7 +1609,7 @@ static void print_help_item(MYSQL_ROW *cur, int num_name, int num_cat, char *las ...@@ -1609,7 +1609,7 @@ static void print_help_item(MYSQL_ROW *cur, int num_name, int num_cat, char *las
char ccat= (*cur)[num_cat][0]; char ccat= (*cur)[num_cat][0];
if (*last_char != ccat) if (*last_char != ccat)
{ {
put_info(ccat == 'Y' ? "categories :" : "topics :", INFO_INFO); put_info(ccat == 'Y' ? "categories:" : "topics:", INFO_INFO);
*last_char= ccat; *last_char= ccat;
} }
tee_fprintf(PAGER, " %s\n", (*cur)[num_name]); tee_fprintf(PAGER, " %s\n", (*cur)[num_name]);
...@@ -1676,8 +1676,8 @@ static int com_server_help(String *buffer __attribute__((unused)), ...@@ -1676,8 +1676,8 @@ static int com_server_help(String *buffer __attribute__((unused)),
if (num_fields == 2) if (num_fields == 2)
{ {
put_info("Many help items for your request exist", INFO_INFO); put_info("Many help items for your request exist.", INFO_INFO);
put_info("To make a more specific request, please type 'help <item>',\nwhere item is one of next", INFO_INFO); put_info("To make a more specific request, please type 'help <item>',\nwhere item is one of the following", INFO_INFO);
num_name= 0; num_name= 0;
num_cat= 1; num_cat= 1;
last_char= '_'; last_char= '_';
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <mysql.h> #include <mysql.h>
#ifdef HAVE_NDBCLUSTER_DB #ifdef LATER_HAVE_NDBCLUSTER_DB
#include "../ndb/src/mgmclient/ndb_mgmclient.h" #include "../ndb/src/mgmclient/ndb_mgmclient.h"
#endif #endif
...@@ -45,7 +45,7 @@ static uint tcp_port = 0, option_wait = 0, option_silent=0, nr_iterations, ...@@ -45,7 +45,7 @@ static uint tcp_port = 0, option_wait = 0, option_silent=0, nr_iterations,
opt_count_iterations= 0; opt_count_iterations= 0;
static ulong opt_connect_timeout, opt_shutdown_timeout; static ulong opt_connect_timeout, opt_shutdown_timeout;
static my_string unix_port=0; static my_string unix_port=0;
#ifdef HAVE_NDBCLUSTER_DB #ifdef LATER_HAVE_NDBCLUSTER_DB
static my_bool opt_ndbcluster=0; static my_bool opt_ndbcluster=0;
static char *opt_ndb_connectstring=0; static char *opt_ndb_connectstring=0;
#endif #endif
...@@ -101,7 +101,7 @@ enum commands { ...@@ -101,7 +101,7 @@ enum commands {
ADMIN_PING, ADMIN_EXTENDED_STATUS, ADMIN_FLUSH_STATUS, ADMIN_PING, ADMIN_EXTENDED_STATUS, ADMIN_FLUSH_STATUS,
ADMIN_FLUSH_PRIVILEGES, ADMIN_START_SLAVE, ADMIN_STOP_SLAVE, ADMIN_FLUSH_PRIVILEGES, ADMIN_START_SLAVE, ADMIN_STOP_SLAVE,
ADMIN_FLUSH_THREADS, ADMIN_OLD_PASSWORD ADMIN_FLUSH_THREADS, ADMIN_OLD_PASSWORD
#ifdef HAVE_NDBCLUSTER_DB #ifdef LATER_HAVE_NDBCLUSTER_DB
,ADMIN_NDB_MGM ,ADMIN_NDB_MGM
#endif #endif
}; };
...@@ -114,7 +114,7 @@ static const char *command_names[]= { ...@@ -114,7 +114,7 @@ static const char *command_names[]= {
"ping", "extended-status", "flush-status", "ping", "extended-status", "flush-status",
"flush-privileges", "start-slave", "stop-slave", "flush-privileges", "start-slave", "stop-slave",
"flush-threads","old-password", "flush-threads","old-password",
#ifdef HAVE_NDBCLUSTER_DB #ifdef LATER_HAVE_NDBCLUSTER_DB
"ndb-mgm", "ndb-mgm",
#endif #endif
NullS NullS
...@@ -197,7 +197,7 @@ static struct my_option my_long_options[] = ...@@ -197,7 +197,7 @@ static struct my_option my_long_options[] =
{"shutdown_timeout", OPT_SHUTDOWN_TIMEOUT, "", (gptr*) &opt_shutdown_timeout, {"shutdown_timeout", OPT_SHUTDOWN_TIMEOUT, "", (gptr*) &opt_shutdown_timeout,
(gptr*) &opt_shutdown_timeout, 0, GET_ULONG, REQUIRED_ARG, (gptr*) &opt_shutdown_timeout, 0, GET_ULONG, REQUIRED_ARG,
SHUTDOWN_DEF_TIMEOUT, 0, 3600*12, 0, 1, 0}, SHUTDOWN_DEF_TIMEOUT, 0, 3600*12, 0, 1, 0},
#ifdef HAVE_NDBCLUSTER_DB #ifdef LATER_HAVE_NDBCLUSTER_DB
{"ndbcluster", OPT_NDBCLUSTER, "" {"ndbcluster", OPT_NDBCLUSTER, ""
"", (gptr*) &opt_ndbcluster, "", (gptr*) &opt_ndbcluster,
(gptr*) &opt_ndbcluster, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, (gptr*) &opt_ndbcluster, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
...@@ -903,7 +903,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv) ...@@ -903,7 +903,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
} }
mysql->reconnect=1; /* Automatic reconnect is default */ mysql->reconnect=1; /* Automatic reconnect is default */
break; break;
#ifdef HAVE_NDBCLUSTER_DB #ifdef LATER_HAVE_NDBCLUSTER_DB
case ADMIN_NDB_MGM: case ADMIN_NDB_MGM:
{ {
if (argc < 2) if (argc < 2)
......
...@@ -44,7 +44,7 @@ static const char *load_default_groups[]= { "mysqlbinlog","client",0 }; ...@@ -44,7 +44,7 @@ static const char *load_default_groups[]= { "mysqlbinlog","client",0 };
void sql_print_error(const char *format, ...); void sql_print_error(const char *format, ...);
static bool one_database=0, to_last_remote_log= 0; static bool one_database=0, to_last_remote_log= 0, disable_log_bin= 0;
static const char* database= 0; static const char* database= 0;
static my_bool force_opt= 0, short_form= 0, remote_opt= 0; static my_bool force_opt= 0, short_form= 0, remote_opt= 0;
static ulonglong offset = 0; static ulonglong offset = 0;
...@@ -438,6 +438,13 @@ static struct my_option my_long_options[] = ...@@ -438,6 +438,13 @@ static struct my_option my_long_options[] =
{"database", 'd', "List entries for just this database (local log only).", {"database", 'd', "List entries for just this database (local log only).",
(gptr*) &database, (gptr*) &database, 0, GET_STR_ALLOC, REQUIRED_ARG, (gptr*) &database, (gptr*) &database, 0, GET_STR_ALLOC, REQUIRED_ARG,
0, 0, 0, 0, 0, 0}, 0, 0, 0, 0, 0, 0},
{"disable-log-bin", 'D', "Disable binary log. This is useful, if you "
"enabled --to-last-log and are sending the output to the same MySQL server. "
"This way you could avoid an endless loop. You would also like to use it "
"when restoring after a crash to avoid duplication of the statements you "
"already have. NOTE: you will need a SUPER privilege to use this option.",
(gptr*) &disable_log_bin, (gptr*) &disable_log_bin, 0, GET_BOOL,
NO_ARG, 0, 0, 0, 0, 0, 0},
{"force-read", 'f', "Force reading unknown binlog events.", {"force-read", 'f', "Force reading unknown binlog events.",
(gptr*) &force_opt, (gptr*) &force_opt, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, (gptr*) &force_opt, (gptr*) &force_opt, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
0, 0}, 0, 0},
...@@ -1068,6 +1075,11 @@ int main(int argc, char** argv) ...@@ -1068,6 +1075,11 @@ int main(int argc, char** argv)
fprintf(result_file, fprintf(result_file,
"/*!40019 SET @@session.max_insert_delayed_threads=0*/;\n"); "/*!40019 SET @@session.max_insert_delayed_threads=0*/;\n");
if (disable_log_bin)
fprintf(result_file,
"/*!32316 SET @OLD_SQL_LOG_BIN=@@SQL_LOG_BIN, SQL_LOG_BIN=0*/;\n");
for (save_stop_position= stop_position, stop_position= ~(my_off_t)0 ; for (save_stop_position= stop_position, stop_position= ~(my_off_t)0 ;
(--argc >= 0) && !stop_passed ; ) (--argc >= 0) && !stop_passed ; )
{ {
...@@ -1082,6 +1094,9 @@ int main(int argc, char** argv) ...@@ -1082,6 +1094,9 @@ int main(int argc, char** argv)
start_position= BIN_LOG_HEADER_SIZE; start_position= BIN_LOG_HEADER_SIZE;
} }
if (disable_log_bin)
fprintf(result_file, "/*!32316 SET SQL_LOG_BIN=@OLD_SQL_LOG_BIN*/;\n");
if (tmpdir.list) if (tmpdir.list)
free_tmpdir(&tmpdir); free_tmpdir(&tmpdir);
if (result_file != stdout) if (result_file != stdout)
......
...@@ -58,14 +58,15 @@ void init_time(void); ...@@ -58,14 +58,15 @@ void init_time(void);
my_time_t my_time_t
my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, bool *in_dst_time_gap); my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, bool *in_dst_time_gap);
void set_zero_time(MYSQL_TIME *tm); void set_zero_time(MYSQL_TIME *tm, enum enum_mysql_timestamp_type time_type);
/* /*
Required buffer length for my_time_to_str, my_date_to_str, Required buffer length for my_time_to_str, my_date_to_str,
my_datetime_to_str and TIME_to_string functions. Note, that the my_datetime_to_str and TIME_to_string functions. Note, that the
caller is still responsible to check that given TIME structure caller is still responsible to check that given TIME structure
has values in valid ranges, otherwise size of the buffer could has values in valid ranges, otherwise size of the buffer could
be not enough. be not enough. We also rely on the fact that even wrong values
sent using binary protocol fit in this buffer.
*/ */
#define MAX_DATE_STRING_REP_LENGTH 30 #define MAX_DATE_STRING_REP_LENGTH 30
......
...@@ -33,6 +33,18 @@ enum enum_mysql_timestamp_type ...@@ -33,6 +33,18 @@ enum enum_mysql_timestamp_type
}; };
/*
Structure which is used to represent datetime values inside MySQL.
We assume that values in this structure are normalized, i.e. year <= 9999,
month <= 12, day <= 31, hour <= 23, hour <= 59, hour <= 59. Many functions
in server such as my_system_gmt_sec() or make_time() family of functions
rely on this (actually now usage of make_*() family relies on a bit weaker
restriction). Also functions that produce MYSQL_TIME as result ensure this.
There is one exception to this rule though if this structure holds time
value (time_type == MYSQL_TIMESTAMP_TIME) days and hour member can hold
bigger values.
*/
typedef struct st_mysql_time typedef struct st_mysql_time
{ {
unsigned int year, month, day, hour, minute, second; unsigned int year, month, day, hour, minute, second;
......
...@@ -3257,11 +3257,12 @@ static void read_binary_time(MYSQL_TIME *tm, uchar **pos) ...@@ -3257,11 +3257,12 @@ static void read_binary_time(MYSQL_TIME *tm, uchar **pos)
tm->hour+= tm->day*24; tm->hour+= tm->day*24;
tm->day= 0; tm->day= 0;
} }
tm->time_type= MYSQL_TIMESTAMP_TIME;
*pos+= length; *pos+= length;
} }
else else
set_zero_time(tm); set_zero_time(tm, MYSQL_TIMESTAMP_TIME);
tm->time_type= MYSQL_TIMESTAMP_TIME;
} }
static void read_binary_datetime(MYSQL_TIME *tm, uchar **pos) static void read_binary_datetime(MYSQL_TIME *tm, uchar **pos)
...@@ -3286,12 +3287,12 @@ static void read_binary_datetime(MYSQL_TIME *tm, uchar **pos) ...@@ -3286,12 +3287,12 @@ static void read_binary_datetime(MYSQL_TIME *tm, uchar **pos)
else else
tm->hour= tm->minute= tm->second= 0; tm->hour= tm->minute= tm->second= 0;
tm->second_part= (length > 7) ? (ulong) sint4korr(to+7) : 0; tm->second_part= (length > 7) ? (ulong) sint4korr(to+7) : 0;
tm->time_type= MYSQL_TIMESTAMP_DATETIME;
*pos+= length; *pos+= length;
} }
else else
set_zero_time(tm); set_zero_time(tm, MYSQL_TIMESTAMP_DATETIME);
tm->time_type= MYSQL_TIMESTAMP_DATETIME;
} }
static void read_binary_date(MYSQL_TIME *tm, uchar **pos) static void read_binary_date(MYSQL_TIME *tm, uchar **pos)
...@@ -3308,12 +3309,12 @@ static void read_binary_date(MYSQL_TIME *tm, uchar **pos) ...@@ -3308,12 +3309,12 @@ static void read_binary_date(MYSQL_TIME *tm, uchar **pos)
tm->hour= tm->minute= tm->second= 0; tm->hour= tm->minute= tm->second= 0;
tm->second_part= 0; tm->second_part= 0;
tm->neg= 0; tm->neg= 0;
tm->time_type= MYSQL_TIMESTAMP_DATE;
*pos+= length; *pos+= length;
} }
else else
set_zero_time(tm); set_zero_time(tm, MYSQL_TIMESTAMP_DATE);
tm->time_type= MYSQL_TIMESTAMP_DATE;
} }
......
...@@ -474,6 +474,12 @@ unix_timestamp(@a) ...@@ -474,6 +474,12 @@ unix_timestamp(@a)
select unix_timestamp('1969-12-01 19:00:01'); select unix_timestamp('1969-12-01 19:00:01');
unix_timestamp('1969-12-01 19:00:01') unix_timestamp('1969-12-01 19:00:01')
0 0
select from_unixtime(0);
from_unixtime(0)
NULL
select from_unixtime(2145916800);
from_unixtime(2145916800)
NULL
CREATE TABLE t1 (datetime datetime, timestamp timestamp, date date, time time); CREATE TABLE t1 (datetime datetime, timestamp timestamp, date date, time time);
INSERT INTO t1 values ("2001-01-02 03:04:05", "2002-01-02 03:04:05", "2003-01-02", "06:07:08"); INSERT INTO t1 values ("2001-01-02 03:04:05", "2002-01-02 03:04:05", "2003-01-02", "06:07:08");
SELECT * from t1; SELECT * from t1;
......
...@@ -450,3 +450,24 @@ PREPARE stmt FROM 'UPDATE t1 AS P1 INNER JOIN (SELECT N FROM t1 GROUP BY N HAVIN ...@@ -450,3 +450,24 @@ PREPARE stmt FROM 'UPDATE t1 AS P1 INNER JOIN (SELECT N FROM t1 GROUP BY N HAVIN
EXECUTE stmt; EXECUTE stmt;
DEALLOCATE PREPARE stmt; DEALLOCATE PREPARE stmt;
DROP TABLE t1; DROP TABLE t1;
prepare stmt from "select ? is null, ? is not null, ?";
select @no_such_var is null, @no_such_var is not null, @no_such_var;
@no_such_var is null @no_such_var is not null @no_such_var
1 0 NULL
execute stmt using @no_such_var, @no_such_var, @no_such_var;
? is null ? is not null ?
1 0 NULL
set @var='abc';
select @var is null, @var is not null, @var;
@var is null @var is not null @var
0 1 abc
execute stmt using @var, @var, @var;
? is null ? is not null ?
0 1 abc
set @var=null;
select @var is null, @var is not null, @var;
@var is null @var is not null @var
1 0 NULL
execute stmt using @var, @var, @var;
? is null ? is not null ?
1 0 NULL
...@@ -97,13 +97,15 @@ select * from t1 where a is null or b is null; ...@@ -97,13 +97,15 @@ select * from t1 where a is null or b is null;
a b a b
drop table t1; drop table t1;
create table t1 (t datetime); create table t1 (t datetime);
insert into t1 values (20030102030460),(20030102036301),(20030102240401),(20030132030401),(20031302030460); insert into t1 values (20030102030460),(20030102036301),(20030102240401),
(20030132030401),(20031302030401),(100001202030401);
Warnings: Warnings:
Warning 1265 Data truncated for column 't' at row 1 Warning 1265 Data truncated for column 't' at row 1
Warning 1265 Data truncated for column 't' at row 2 Warning 1265 Data truncated for column 't' at row 2
Warning 1265 Data truncated for column 't' at row 3 Warning 1265 Data truncated for column 't' at row 3
Warning 1265 Data truncated for column 't' at row 4 Warning 1265 Data truncated for column 't' at row 4
Warning 1265 Data truncated for column 't' at row 5 Warning 1265 Data truncated for column 't' at row 5
Warning 1265 Data truncated for column 't' at row 6
select * from t1; select * from t1;
t t
0000-00-00 00:00:00 0000-00-00 00:00:00
...@@ -111,14 +113,18 @@ t ...@@ -111,14 +113,18 @@ t
0000-00-00 00:00:00 0000-00-00 00:00:00
0000-00-00 00:00:00 0000-00-00 00:00:00
0000-00-00 00:00:00 0000-00-00 00:00:00
0000-00-00 00:00:00
delete from t1; delete from t1;
insert into t1 values ("20030102030460"),("20030102036301"),("20030102240401"),("20030132030401"),("20031302030460"); insert into t1 values
("2003-01-02 03:04:60"),("2003-01-02 03:63:01"),("2003-01-02 24:04:01"),
("2003-01-32 03:04:01"),("2003-13-02 03:04:01"), ("10000-12-02 03:04:00");
Warnings: Warnings:
Warning 1264 Data truncated; out of range for column 't' at row 1 Warning 1264 Data truncated; out of range for column 't' at row 1
Warning 1264 Data truncated; out of range for column 't' at row 2 Warning 1264 Data truncated; out of range for column 't' at row 2
Warning 1264 Data truncated; out of range for column 't' at row 3 Warning 1264 Data truncated; out of range for column 't' at row 3
Warning 1264 Data truncated; out of range for column 't' at row 4 Warning 1264 Data truncated; out of range for column 't' at row 4
Warning 1264 Data truncated; out of range for column 't' at row 5 Warning 1264 Data truncated; out of range for column 't' at row 5
Warning 1264 Data truncated; out of range for column 't' at row 6
select * from t1; select * from t1;
t t
0000-00-00 00:00:00 0000-00-00 00:00:00
...@@ -126,6 +132,7 @@ t ...@@ -126,6 +132,7 @@ t
0000-00-00 00:00:00 0000-00-00 00:00:00
0000-00-00 00:00:00 0000-00-00 00:00:00
0000-00-00 00:00:00 0000-00-00 00:00:00
0000-00-00 00:00:00
delete from t1; delete from t1;
insert into t1 values ("0000-00-00 00:00:00 some trailer"),("2003-01-01 00:00:00 some trailer"); insert into t1 values ("0000-00-00 00:00:00 some trailer"),("2003-01-01 00:00:00 some trailer");
Warnings: Warnings:
......
...@@ -229,6 +229,13 @@ select @a:=FROM_UNIXTIME(1); ...@@ -229,6 +229,13 @@ select @a:=FROM_UNIXTIME(1);
select unix_timestamp(@a); select unix_timestamp(@a);
select unix_timestamp('1969-12-01 19:00:01'); select unix_timestamp('1969-12-01 19:00:01');
#
# Test for bug #6439 "unix_timestamp() function returns wrong datetime
# values for too big argument". It should return error instead.
#
select from_unixtime(0);
select from_unixtime(2145916800);
# #
# Test types from + INTERVAL # Test types from + INTERVAL
# #
......
...@@ -458,3 +458,17 @@ EXECUTE stmt; ...@@ -458,3 +458,17 @@ EXECUTE stmt;
DEALLOCATE PREPARE stmt; DEALLOCATE PREPARE stmt;
DROP TABLE t1; DROP TABLE t1;
#
# Bug#6297 "prepared statement, wrong handling of <parameter> IS NULL"
# Test that placeholders work with IS NULL/IS NOT NULL clauses.
#
prepare stmt from "select ? is null, ? is not null, ?";
select @no_such_var is null, @no_such_var is not null, @no_such_var;
execute stmt using @no_such_var, @no_such_var, @no_such_var;
set @var='abc';
select @var is null, @var is not null, @var;
execute stmt using @var, @var, @var;
set @var=null;
select @var is null, @var is not null, @var;
execute stmt using @var, @var, @var;
...@@ -77,10 +77,13 @@ drop table t1; ...@@ -77,10 +77,13 @@ drop table t1;
# warnings (for both strings and numbers) # warnings (for both strings and numbers)
# #
create table t1 (t datetime); create table t1 (t datetime);
insert into t1 values (20030102030460),(20030102036301),(20030102240401),(20030132030401),(20031302030460); insert into t1 values (20030102030460),(20030102036301),(20030102240401),
(20030132030401),(20031302030401),(100001202030401);
select * from t1; select * from t1;
delete from t1; delete from t1;
insert into t1 values ("20030102030460"),("20030102036301"),("20030102240401"),("20030132030401"),("20031302030460"); insert into t1 values
("2003-01-02 03:04:60"),("2003-01-02 03:63:01"),("2003-01-02 24:04:01"),
("2003-01-32 03:04:01"),("2003-13-02 03:04:01"), ("10000-12-02 03:04:00");
select * from t1; select * from t1;
delete from t1; delete from t1;
insert into t1 values ("0000-00-00 00:00:00 some trailer"),("2003-01-01 00:00:00 some trailer"); insert into t1 values ("0000-00-00 00:00:00 some trailer"),("2003-01-01 00:00:00 some trailer");
......
...@@ -750,8 +750,8 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){ ...@@ -750,8 +750,8 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){
noOfMetaTables); noOfMetaTables);
cfg.put(CFG_TUP_TABLE_DESC, cfg.put(CFG_TUP_TABLE_DESC,
4 * NO_OF_FRAG_PER_NODE * noOfAttributes* noOfReplicas + 2 * 6 * NO_OF_FRAG_PER_NODE * noOfAttributes * noOfReplicas +
12 * NO_OF_FRAG_PER_NODE * noOfMetaTables* noOfReplicas ); 2 * 10 * NO_OF_FRAG_PER_NODE * noOfMetaTables * noOfReplicas );
cfg.put(CFG_TUP_STORED_PROC, cfg.put(CFG_TUP_STORED_PROC,
noOfLocalScanRecords); noOfLocalScanRecords);
......
...@@ -1571,7 +1571,13 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb, ...@@ -1571,7 +1571,13 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
NdbApiSignal tSignal(m_reference); NdbApiSignal tSignal(m_reference);
tSignal.theReceiversBlockNumber = DBDICT; tSignal.theReceiversBlockNumber = DBDICT;
if (alter) {
LinearSectionPtr ptr[3];
ptr[0].p = (Uint32*)m_buffer.get_data();
ptr[0].sz = m_buffer.length() / 4;
int ret;
if (alter)
{
AlterTableReq * const req = AlterTableReq * const req =
CAST_PTR(AlterTableReq, tSignal.getDataPtrSend()); CAST_PTR(AlterTableReq, tSignal.getDataPtrSend());
...@@ -1582,8 +1588,10 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb, ...@@ -1582,8 +1588,10 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
req->tableVersion = impl.m_version;; req->tableVersion = impl.m_version;;
tSignal.theVerId_signalNumber = GSN_ALTER_TABLE_REQ; tSignal.theVerId_signalNumber = GSN_ALTER_TABLE_REQ;
tSignal.theLength = AlterTableReq::SignalLength; tSignal.theLength = AlterTableReq::SignalLength;
ret= alterTable(&tSignal, ptr);
} }
else { else
{
CreateTableReq * const req = CreateTableReq * const req =
CAST_PTR(CreateTableReq, tSignal.getDataPtrSend()); CAST_PTR(CreateTableReq, tSignal.getDataPtrSend());
...@@ -1591,25 +1599,21 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb, ...@@ -1591,25 +1599,21 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
req->senderData = 0; req->senderData = 0;
tSignal.theVerId_signalNumber = GSN_CREATE_TABLE_REQ; tSignal.theVerId_signalNumber = GSN_CREATE_TABLE_REQ;
tSignal.theLength = CreateTableReq::SignalLength; tSignal.theLength = CreateTableReq::SignalLength;
} ret= createTable(&tSignal, ptr);
LinearSectionPtr ptr[3]; if (ret)
ptr[0].p = (Uint32*)m_buffer.get_data(); return ret;
ptr[0].sz = m_buffer.length() / 4;
if (haveAutoIncrement) {
int ret = (alter) ? if (!ndb.setAutoIncrementValue(impl.m_externalName.c_str(),
alterTable(&tSignal, ptr) autoIncrementValue)) {
: createTable(&tSignal, ptr); if (ndb.theError.code == 0) {
m_error.code = 4336;
if (!alter && haveAutoIncrement) { ndb.theError = m_error;
if (!ndb.setAutoIncrementValue(impl.m_externalName.c_str(), } else
autoIncrementValue)) { m_error= ndb.theError;
if (ndb.theError.code == 0) { ret = -1; // errorcode set in initialize_autoincrement
m_error.code = 4336; }
ndb.theError = m_error;
} else
m_error= ndb.theError;
ret = -1; // errorcode set in initialize_autoincrement
} }
} }
return ret; return ret;
......
...@@ -343,7 +343,8 @@ str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time, ...@@ -343,7 +343,8 @@ str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time,
(l_time->month || l_time->day)) (l_time->month || l_time->day))
l_time->year+= (l_time->year < YY_PART_YEAR ? 2000 : 1900); l_time->year+= (l_time->year < YY_PART_YEAR ? 2000 : 1900);
if (number_of_fields < 3 || l_time->month > 12 || if (number_of_fields < 3 ||
l_time->year > 9999 || l_time->month > 12 ||
l_time->day > 31 || l_time->hour > 23 || l_time->day > 31 || l_time->hour > 23 ||
l_time->minute > 59 || l_time->second > 59 || l_time->minute > 59 || l_time->second > 59 ||
(!(flags & TIME_FUZZY_DATE) && (l_time->month == 0 || l_time->day == 0))) (!(flags & TIME_FUZZY_DATE) && (l_time->month == 0 || l_time->day == 0)))
...@@ -733,10 +734,10 @@ my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, bool *in_dst_time_gap) ...@@ -733,10 +734,10 @@ my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, bool *in_dst_time_gap)
/* Set MYSQL_TIME structure to 0000-00-00 00:00:00.000000 */ /* Set MYSQL_TIME structure to 0000-00-00 00:00:00.000000 */
void set_zero_time(MYSQL_TIME *tm) void set_zero_time(MYSQL_TIME *tm, enum enum_mysql_timestamp_type time_type)
{ {
bzero((void*) tm, sizeof(*tm)); bzero((void*) tm, sizeof(*tm));
tm->time_type= MYSQL_TIMESTAMP_NONE; tm->time_type= time_type;
} }
......
...@@ -4086,6 +4086,10 @@ int Field_datetime::store(longlong nr) ...@@ -4086,6 +4086,10 @@ int Field_datetime::store(longlong nr)
void Field_datetime::store_time(TIME *ltime,timestamp_type type) void Field_datetime::store_time(TIME *ltime,timestamp_type type)
{ {
longlong tmp; longlong tmp;
/*
We don't perform range checking here since values stored in TIME
structure always fit into DATETIME range.
*/
if (type == MYSQL_TIMESTAMP_DATE || type == MYSQL_TIMESTAMP_DATETIME) if (type == MYSQL_TIMESTAMP_DATE || type == MYSQL_TIMESTAMP_DATETIME)
tmp=((ltime->year*10000L+ltime->month*100+ltime->day)*LL(1000000)+ tmp=((ltime->year*10000L+ltime->month*100+ltime->day)*LL(1000000)+
(ltime->hour*10000L+ltime->minute*100+ltime->second)); (ltime->hour*10000L+ltime->minute*100+ltime->second));
......
...@@ -837,6 +837,21 @@ void Item_param::set_double(double d) ...@@ -837,6 +837,21 @@ void Item_param::set_double(double d)
} }
/*
Set parameter value from TIME value.
SYNOPSIS
set_time()
tm - datetime value to set (time_type is ignored)
type - type of datetime value
max_length_arg - max length of datetime value as string
NOTE
If we value to be stored is not normalized, zero value will be stored
instead and proper warning will be produced. This function relies on
the fact that even wrong value sent over binary protocol fits into
MAX_DATE_STRING_REP_LENGTH buffer.
*/
void Item_param::set_time(TIME *tm, timestamp_type type, uint32 max_length_arg) void Item_param::set_time(TIME *tm, timestamp_type type, uint32 max_length_arg)
{ {
DBUG_ENTER("Item_param::set_time"); DBUG_ENTER("Item_param::set_time");
...@@ -844,6 +859,17 @@ void Item_param::set_time(TIME *tm, timestamp_type type, uint32 max_length_arg) ...@@ -844,6 +859,17 @@ void Item_param::set_time(TIME *tm, timestamp_type type, uint32 max_length_arg)
value.time= *tm; value.time= *tm;
value.time.time_type= type; value.time.time_type= type;
if (value.time.year > 9999 || value.time.month > 12 ||
value.time.day > 31 ||
type != MYSQL_TIMESTAMP_TIME && value.time.hour > 23 ||
value.time.minute > 59 || value.time.second > 59)
{
char buff[MAX_DATE_STRING_REP_LENGTH];
uint length= my_TIME_to_str(&value.time, buff);
make_truncated_value_warning(current_thd, buff, length, type);
set_zero_time(&value.time, MYSQL_TIMESTAMP_ERROR);
}
state= TIME_VALUE; state= TIME_VALUE;
maybe_null= 0; maybe_null= 0;
max_length= max_length_arg; max_length= max_length_arg;
......
...@@ -266,6 +266,14 @@ public: ...@@ -266,6 +266,14 @@ public:
virtual bool get_time(TIME *ltime); virtual bool get_time(TIME *ltime);
virtual bool get_date_result(TIME *ltime,uint fuzzydate) virtual bool get_date_result(TIME *ltime,uint fuzzydate)
{ return get_date(ltime,fuzzydate); } { return get_date(ltime,fuzzydate); }
/*
This function is used only in Item_func_isnull/Item_func_isnotnull
(implementations of IS NULL/IS NOT NULL clauses). Item_func_is{not}null
calls this method instead of one of val/result*() methods, which
normally will set null_value. This allows to determine nullness of
a complex expression without fully evaluating it.
Any new item which can be NULL must implement this call.
*/
virtual bool is_null() { return 0; } virtual bool is_null() { return 0; }
/* /*
it is "top level" item of WHERE clause and we do not need correct NULL it is "top level" item of WHERE clause and we do not need correct NULL
...@@ -573,6 +581,8 @@ public: ...@@ -573,6 +581,8 @@ public:
void print(String *str) { str->append('?'); } void print(String *str) { str->append('?'); }
/* parameter never equal to other parameter of other item */ /* parameter never equal to other parameter of other item */
bool eq(const Item *item, bool binary_cmp) const { return 0; } bool eq(const Item *item, bool binary_cmp) const { return 0; }
bool is_null()
{ DBUG_ASSERT(state != NO_VALUE); return state == NULL_VALUE; }
}; };
class Item_int :public Item_num class Item_int :public Item_num
......
...@@ -1601,50 +1601,46 @@ void Item_func_from_unixtime::fix_length_and_dec() ...@@ -1601,50 +1601,46 @@ void Item_func_from_unixtime::fix_length_and_dec()
String *Item_func_from_unixtime::val_str(String *str) String *Item_func_from_unixtime::val_str(String *str)
{ {
TIME time_tmp; TIME time_tmp;
my_time_t tmp;
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
tmp= (time_t) args[0]->val_int();
if ((null_value=args[0]->null_value)) if (get_date(&time_tmp, 0))
goto null_date; return 0;
thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp, tmp);
if (str->alloc(20*MY_CHARSET_BIN_MB_MAXLEN)) if (str->alloc(20*MY_CHARSET_BIN_MB_MAXLEN))
goto null_date; {
null_value= 1;
return 0;
}
make_datetime((DATE_TIME_FORMAT *) 0, &time_tmp, str); make_datetime((DATE_TIME_FORMAT *) 0, &time_tmp, str);
return str; return str;
null_date:
null_value=1;
return 0;
} }
longlong Item_func_from_unixtime::val_int() longlong Item_func_from_unixtime::val_int()
{ {
TIME time_tmp; TIME time_tmp;
my_time_t tmp;
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
tmp= (time_t) (ulong) args[0]->val_int(); if (get_date(&time_tmp, 0))
if ((null_value=args[0]->null_value))
return 0; return 0;
current_thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp, tmp);
return (longlong) TIME_to_ulonglong_datetime(&time_tmp); return (longlong) TIME_to_ulonglong_datetime(&time_tmp);
} }
bool Item_func_from_unixtime::get_date(TIME *ltime, bool Item_func_from_unixtime::get_date(TIME *ltime,
uint fuzzy_date __attribute__((unused))) uint fuzzy_date __attribute__((unused)))
{ {
my_time_t tmp=(my_time_t) args[0]->val_int(); longlong tmp= args[0]->val_int();
if ((null_value=args[0]->null_value))
if ((null_value= (args[0]->null_value ||
tmp < TIMESTAMP_MIN_VALUE ||
tmp > TIMESTAMP_MAX_VALUE)))
return 1; return 1;
current_thd->variables.time_zone->gmt_sec_to_TIME(ltime, tmp); thd->variables.time_zone->gmt_sec_to_TIME(ltime, (my_time_t)tmp);
return 0; return 0;
} }
......
...@@ -349,12 +349,6 @@ static void set_param_time(Item_param *param, uchar **pos, ulong len) ...@@ -349,12 +349,6 @@ static void set_param_time(Item_param *param, uchar **pos, ulong len)
tm.neg= (bool) to[0]; tm.neg= (bool) to[0];
day= (uint) sint4korr(to+1); day= (uint) sint4korr(to+1);
/*
Note, that though ranges of hour, minute and second are not checked
here we rely on them being < 256: otherwise
we'll get buffer overflow in make_{date,time} functions,
which are called when time value is converted to string.
*/
tm.hour= (uint) to[5] + day * 24; tm.hour= (uint) to[5] + day * 24;
tm.minute= (uint) to[6]; tm.minute= (uint) to[6];
tm.second= (uint) to[7]; tm.second= (uint) to[7];
...@@ -369,7 +363,7 @@ static void set_param_time(Item_param *param, uchar **pos, ulong len) ...@@ -369,7 +363,7 @@ static void set_param_time(Item_param *param, uchar **pos, ulong len)
tm.day= tm.year= tm.month= 0; tm.day= tm.year= tm.month= 0;
} }
else else
set_zero_time(&tm); set_zero_time(&tm, MYSQL_TIMESTAMP_TIME);
param->set_time(&tm, MYSQL_TIMESTAMP_TIME, param->set_time(&tm, MYSQL_TIMESTAMP_TIME,
MAX_TIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN); MAX_TIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN);
*pos+= length; *pos+= length;
...@@ -388,11 +382,6 @@ static void set_param_datetime(Item_param *param, uchar **pos, ulong len) ...@@ -388,11 +382,6 @@ static void set_param_datetime(Item_param *param, uchar **pos, ulong len)
tm.year= (uint) sint2korr(to); tm.year= (uint) sint2korr(to);
tm.month= (uint) to[2]; tm.month= (uint) to[2];
tm.day= (uint) to[3]; tm.day= (uint) to[3];
/*
Note, that though ranges of hour, minute and second are not checked
here we rely on them being < 256: otherwise
we'll get buffer overflow in make_{date,time} functions.
*/
if (length > 4) if (length > 4)
{ {
tm.hour= (uint) to[4]; tm.hour= (uint) to[4];
...@@ -405,7 +394,7 @@ static void set_param_datetime(Item_param *param, uchar **pos, ulong len) ...@@ -405,7 +394,7 @@ static void set_param_datetime(Item_param *param, uchar **pos, ulong len)
tm.second_part= (length > 7) ? (ulong) sint4korr(to+7) : 0; tm.second_part= (length > 7) ? (ulong) sint4korr(to+7) : 0;
} }
else else
set_zero_time(&tm); set_zero_time(&tm, MYSQL_TIMESTAMP_DATETIME);
param->set_time(&tm, MYSQL_TIMESTAMP_DATETIME, param->set_time(&tm, MYSQL_TIMESTAMP_DATETIME,
MAX_DATETIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN); MAX_DATETIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN);
*pos+= length; *pos+= length;
...@@ -419,11 +408,7 @@ static void set_param_date(Item_param *param, uchar **pos, ulong len) ...@@ -419,11 +408,7 @@ static void set_param_date(Item_param *param, uchar **pos, ulong len)
if (length >= 4) if (length >= 4)
{ {
uchar *to= *pos; uchar *to= *pos;
/*
Note, that though ranges of hour, minute and second are not checked
here we rely on them being < 256: otherwise
we'll get buffer overflow in make_{date,time} functions.
*/
tm.year= (uint) sint2korr(to); tm.year= (uint) sint2korr(to);
tm.month= (uint) to[2]; tm.month= (uint) to[2];
tm.day= (uint) to[3]; tm.day= (uint) to[3];
...@@ -433,7 +418,7 @@ static void set_param_date(Item_param *param, uchar **pos, ulong len) ...@@ -433,7 +418,7 @@ static void set_param_date(Item_param *param, uchar **pos, ulong len)
tm.neg= 0; tm.neg= 0;
} }
else else
set_zero_time(&tm); set_zero_time(&tm, MYSQL_TIMESTAMP_DATE);
param->set_time(&tm, MYSQL_TIMESTAMP_DATE, param->set_time(&tm, MYSQL_TIMESTAMP_DATE,
MAX_DATE_WIDTH * MY_CHARSET_BIN_MB_MAXLEN); MAX_DATE_WIDTH * MY_CHARSET_BIN_MB_MAXLEN);
*pos+= length; *pos+= length;
......
...@@ -11121,6 +11121,140 @@ static void test_bug6096() ...@@ -11121,6 +11121,140 @@ static void test_bug6096()
} }
/*
Test of basic checks that are performed in server for components
of MYSQL_TIME parameters.
*/
static void test_datetime_ranges()
{
const char *stmt_text;
int rc, i;
MYSQL_STMT *stmt;
MYSQL_BIND bind[6];
MYSQL_TIME tm[6];
myheader("test_datetime_ranges");
stmt_text= "drop table if exists t1";
rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
myquery(rc);
stmt_text= "create table t1 (year datetime, month datetime, day datetime, "
"hour datetime, min datetime, sec datetime)";
rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
myquery(rc);
stmt= mysql_simple_prepare(mysql,
"INSERT INTO t1 VALUES (?, ?, ?, ?, ?, ?)");
check_stmt(stmt);
verify_param_count(stmt, 6);
bzero(bind, sizeof(bind));
for (i= 0; i < 6; i++)
{
bind[i].buffer_type= MYSQL_TYPE_DATETIME;
bind[i].buffer= &tm[i];
}
rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
tm[0].year= 2004; tm[0].month= 11; tm[0].day= 10;
tm[0].hour= 12; tm[0].minute= 30; tm[0].second= 30;
tm[0].second_part= 0; tm[0].neg= 0;
tm[5]= tm[4]= tm[3]= tm[2]= tm[1]= tm[0];
tm[0].year= 10000; tm[1].month= 13; tm[2].day= 32;
tm[3].hour= 24; tm[4].minute= 60; tm[5].second= 60;
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
DIE_UNLESS(mysql_warning_count(mysql) != 6);
verify_col_data("t1", "year", "0000-00-00 00:00:00");
verify_col_data("t1", "month", "0000-00-00 00:00:00");
verify_col_data("t1", "day", "0000-00-00 00:00:00");
verify_col_data("t1", "hour", "0000-00-00 00:00:00");
verify_col_data("t1", "min", "0000-00-00 00:00:00");
verify_col_data("t1", "sec", "0000-00-00 00:00:00");
mysql_stmt_close(stmt);
stmt_text= "delete from t1";
rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
myquery(rc);
stmt= mysql_simple_prepare(mysql, "INSERT INTO t1 (year, month, day) "
"VALUES (?, ?, ?)");
check_stmt(stmt);
verify_param_count(stmt, 3);
/*
We reuse contents of bind and tm arrays left from previous part of test.
*/
for (i= 0; i < 3; i++)
bind[i].buffer_type= MYSQL_TYPE_DATE;
rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
DIE_UNLESS(mysql_warning_count(mysql) != 3);
verify_col_data("t1", "year", "0000-00-00 00:00:00");
verify_col_data("t1", "month", "0000-00-00 00:00:00");
verify_col_data("t1", "day", "0000-00-00 00:00:00");
mysql_stmt_close(stmt);
stmt_text= "drop table t1";
rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
myquery(rc);
stmt_text= "create table t1 (day_ovfl time, day time, hour time, min time, sec time)";
rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
myquery(rc);
stmt= mysql_simple_prepare(mysql,
"INSERT INTO t1 VALUES (?, ?, ?, ?, ?)");
check_stmt(stmt);
verify_param_count(stmt, 5);
/*
Again we reuse what we can from previous part of test.
*/
for (i= 0; i < 5; i++)
bind[i].buffer_type= MYSQL_TYPE_TIME;
rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
tm[0].year= 0; tm[0].month= 0; tm[0].day= 10;
tm[0].hour= 12; tm[0].minute= 30; tm[0].second= 30;
tm[0].second_part= 0; tm[0].neg= 0;
tm[4]= tm[3]= tm[2]= tm[1]= tm[0];
tm[0].day= 35; tm[1].day= 34; tm[2].hour= 30; tm[3].minute= 60; tm[4].second= 60;
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
DIE_UNLESS(mysql_warning_count(mysql) != 2);
verify_col_data("t1", "day_ovfl", "838:59:59");
verify_col_data("t1", "day", "828:30:30");
verify_col_data("t1", "hour", "270:30:30");
verify_col_data("t1", "min", "00:00:00");
verify_col_data("t1", "sec", "00:00:00");
mysql_stmt_close(stmt);
stmt_text= "drop table t1";
rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
myquery(rc);
}
static void test_bug4172() static void test_bug4172()
{ {
MYSQL_STMT *stmt; MYSQL_STMT *stmt;
...@@ -11455,6 +11589,7 @@ static struct my_tests_st my_tests[]= { ...@@ -11455,6 +11589,7 @@ static struct my_tests_st my_tests[]= {
{ "test_bug6046", test_bug6046 }, { "test_bug6046", test_bug6046 },
{ "test_bug6081", test_bug6081 }, { "test_bug6081", test_bug6081 },
{ "test_bug6096", test_bug6096 }, { "test_bug6096", test_bug6096 },
{ "test_datetime_ranges", test_datetime_ranges },
{ "test_bug4172", test_bug4172 }, { "test_bug4172", test_bug4172 },
{ "test_conversion", test_conversion }, { "test_conversion", test_conversion },
{ 0, 0 } { 0, 0 }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment