Commit b9bf4e8c authored by dlenev@mysql.com's avatar dlenev@mysql.com

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

into mysql.com:/home/dlenev/src/mysql-4.1-secfix
parents c4281153 df58c0bc
...@@ -60,6 +60,20 @@ my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, bool *in_dst_time_gap) ...@@ -60,6 +60,20 @@ 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);
/*
Required buffer length for my_time_to_str, my_date_to_str,
my_datetime_to_str and TIME_to_string functions. Note, that the
caller is still responsible to check that given TIME structure
has values in valid ranges, otherwise size of the buffer could
be not enough.
*/
#define MAX_DATE_STRING_REP_LENGTH 30
int my_time_to_str(const MYSQL_TIME *l_time, char *to);
int my_date_to_str(const MYSQL_TIME *l_time, char *to);
int my_datetime_to_str(const MYSQL_TIME *l_time, char *to);
int my_TIME_to_str(const MYSQL_TIME *l_time, char *to);
C_MODE_END C_MODE_END
#endif /* _my_time_h_ */ #endif /* _my_time_h_ */
...@@ -3231,12 +3231,12 @@ static void read_binary_time(MYSQL_TIME *tm, uchar **pos) ...@@ -3231,12 +3231,12 @@ static void read_binary_time(MYSQL_TIME *tm, uchar **pos)
tm->second_part= (length > 8) ? (ulong) sint4korr(to+8) : 0; tm->second_part= (length > 8) ? (ulong) sint4korr(to+8) : 0;
tm->year= tm->month= 0; tm->year= tm->month= 0;
tm->time_type= MYSQL_TIMESTAMP_TIME;
*pos+= length; *pos+= length;
} }
else else
set_zero_time(tm); set_zero_time(tm);
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)
...@@ -3261,12 +3261,12 @@ static void read_binary_datetime(MYSQL_TIME *tm, uchar **pos) ...@@ -3261,12 +3261,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);
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)
...@@ -3283,12 +3283,12 @@ static void read_binary_date(MYSQL_TIME *tm, uchar **pos) ...@@ -3283,12 +3283,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);
tm->time_type= MYSQL_TIMESTAMP_DATE;
} }
...@@ -3566,28 +3566,8 @@ static void fetch_datetime_with_conversion(MYSQL_BIND *param, ...@@ -3566,28 +3566,8 @@ static void fetch_datetime_with_conversion(MYSQL_BIND *param,
Convert time value to string and delegate the rest to Convert time value to string and delegate the rest to
fetch_string_with_conversion: fetch_string_with_conversion:
*/ */
char buff[25]; char buff[MAX_DATE_STRING_REP_LENGTH];
uint length; uint length= my_TIME_to_str(time, buff);
switch (time->time_type) {
case MYSQL_TIMESTAMP_DATE:
length= my_sprintf(buff,(buff, "%04d-%02d-%02d",
time->year, time->month, time->day));
break;
case MYSQL_TIMESTAMP_DATETIME:
length= my_sprintf(buff,(buff, "%04d-%02d-%02d %02d:%02d:%02d",
time->year, time->month, time->day,
time->hour, time->minute, time->second));
break;
case MYSQL_TIMESTAMP_TIME:
length= my_sprintf(buff, (buff, "%02d:%02d:%02d",
time->hour, time->minute, time->second));
break;
default:
length= 0;
buff[0]='\0';
break;
}
/* Resort to string conversion */ /* Resort to string conversion */
fetch_string_with_conversion(param, (char *)buff, length); fetch_string_with_conversion(param, (char *)buff, length);
break; break;
......
...@@ -543,7 +543,8 @@ NdbOperation::getKeyFromTCREQ(Uint32* data, unsigned size) ...@@ -543,7 +543,8 @@ NdbOperation::getKeyFromTCREQ(Uint32* data, unsigned size)
assert(m_accessTable->m_sizeOfKeysInWords == size); assert(m_accessTable->m_sizeOfKeysInWords == size);
unsigned pos = 0; unsigned pos = 0;
while (pos < 8 && pos < size) { while (pos < 8 && pos < size) {
data[pos++] = theKEYINFOptr[pos]; data[pos] = theKEYINFOptr[pos];
pos++;
} }
NdbApiSignal* tSignal = theFirstKEYINFO; NdbApiSignal* tSignal = theFirstKEYINFO;
unsigned n = 0; unsigned n = 0;
......
...@@ -726,3 +726,75 @@ void set_zero_time(MYSQL_TIME *tm) ...@@ -726,3 +726,75 @@ void set_zero_time(MYSQL_TIME *tm)
tm->time_type= MYSQL_TIMESTAMP_NONE; tm->time_type= MYSQL_TIMESTAMP_NONE;
} }
/*
Functions to convert time/date/datetime value to a string,
using default format.
This functions don't check that given TIME structure members are
in valid range. If they are not, return value won't reflect any
valid date either. Additionally, make_time doesn't take into
account time->day member: it's assumed that days have been converted
to hours already.
RETURN
number of characters written to 'to'
*/
int my_time_to_str(const MYSQL_TIME *l_time, char *to)
{
return my_sprintf(to, (to, "%s%02d:%02d:%02d",
(l_time->neg ? "-" : ""),
l_time->hour,
l_time->minute,
l_time->second));
}
int my_date_to_str(const MYSQL_TIME *l_time, char *to)
{
return my_sprintf(to, (to, "%04d-%02d-%02d",
l_time->year,
l_time->month,
l_time->day));
}
int my_datetime_to_str(const MYSQL_TIME *l_time, char *to)
{
return my_sprintf(to, (to, "%04d-%02d-%02d %02d:%02d:%02d",
l_time->year,
l_time->month,
l_time->day,
l_time->hour,
l_time->minute,
l_time->second));
}
/*
Convert struct DATE/TIME/DATETIME value to string using built-in
MySQL time conversion formats.
SYNOPSIS
my_TIME_to_string()
NOTE
The string must have at least MAX_DATE_STRING_REP_LENGTH bytes reserved.
*/
int my_TIME_to_str(const MYSQL_TIME *l_time, char *to)
{
switch (l_time->time_type) {
case MYSQL_TIMESTAMP_DATETIME:
return my_datetime_to_str(l_time, to);
case MYSQL_TIMESTAMP_DATE:
return my_date_to_str(l_time, to);
case MYSQL_TIMESTAMP_TIME:
return my_time_to_str(l_time, to);
case MYSQL_TIMESTAMP_NONE:
case MYSQL_TIMESTAMP_ERROR:
to[0]='\0';
return 0;
default:
DBUG_ASSERT(0);
return 0;
}
}
...@@ -452,11 +452,9 @@ bool Field::get_time(TIME *ltime) ...@@ -452,11 +452,9 @@ bool Field::get_time(TIME *ltime)
void Field::store_time(TIME *ltime,timestamp_type type) void Field::store_time(TIME *ltime,timestamp_type type)
{ {
char buff[MAX_DATE_REP_LENGTH]; char buff[MAX_DATE_STRING_REP_LENGTH];
String tmp; uint length= (uint) my_TIME_to_str(ltime, buff);
tmp.set(buff, sizeof(buff), &my_charset_bin); store(buff, length, &my_charset_bin);
TIME_to_string(ltime, &tmp);
store(buff, tmp.length(), &my_charset_bin);
} }
......
...@@ -988,9 +988,10 @@ String *Item_param::val_str(String* str) ...@@ -988,9 +988,10 @@ String *Item_param::val_str(String* str)
return str; return str;
case TIME_VALUE: case TIME_VALUE:
{ {
if (str->reserve(MAX_DATE_REP_LENGTH)) if (str->reserve(MAX_DATE_STRING_REP_LENGTH))
break; break;
TIME_to_string(&value.time, str); str->length((uint) my_TIME_to_str(&value.time, (char*) str->ptr()));
str->set_charset(&my_charset_bin);
return str; return str;
} }
case NULL_VALUE: case NULL_VALUE:
...@@ -1020,24 +1021,19 @@ const String *Item_param::query_val_str(String* str) const ...@@ -1020,24 +1021,19 @@ const String *Item_param::query_val_str(String* str) const
case TIME_VALUE: case TIME_VALUE:
{ {
char *buf, *ptr; char *buf, *ptr;
String tmp;
str->length(0); str->length(0);
/* /*
TODO: in case of error we need to notify replication TODO: in case of error we need to notify replication
that binary log contains wrong statement that binary log contains wrong statement
*/ */
if (str->reserve(MAX_DATE_REP_LENGTH+3)) if (str->reserve(MAX_DATE_STRING_REP_LENGTH+3))
break; break;
/* Create date string inplace */ /* Create date string inplace */
buf= str->c_ptr_quick(); buf= str->c_ptr_quick();
ptr= buf; ptr= buf;
*ptr++= '\''; *ptr++= '\'';
tmp.set(ptr, MAX_DATE_REP_LENGTH, &my_charset_bin); ptr+= (uint) my_TIME_to_str(&value.time, ptr);
tmp.length(0);
TIME_to_string(&value.time, &tmp);
ptr+= tmp.length();
*ptr++= '\''; *ptr++= '\'';
str->length((uint32) (ptr - buf)); str->length((uint32) (ptr - buf));
break; break;
......
...@@ -1292,14 +1292,13 @@ String *Item_func_curtime::val_str(String *str) ...@@ -1292,14 +1292,13 @@ String *Item_func_curtime::val_str(String *str)
void Item_func_curtime::fix_length_and_dec() void Item_func_curtime::fix_length_and_dec()
{ {
TIME ltime; TIME ltime;
String tmp((char*) buff,sizeof(buff), &my_charset_bin);
decimals=0; decimals=0;
collation.set(&my_charset_bin); collation.set(&my_charset_bin);
store_now_in_TIME(&ltime); store_now_in_TIME(&ltime);
value= TIME_to_ulonglong_time(&ltime); value= TIME_to_ulonglong_time(&ltime);
make_time((DATE_TIME_FORMAT *) 0, &ltime, &tmp); buff_length= (uint) my_time_to_str(&ltime, buff);
max_length= buff_length= tmp.length(); max_length= buff_length;
} }
...@@ -1341,16 +1340,14 @@ String *Item_func_now::val_str(String *str) ...@@ -1341,16 +1340,14 @@ String *Item_func_now::val_str(String *str)
void Item_func_now::fix_length_and_dec() void Item_func_now::fix_length_and_dec()
{ {
String tmp((char*) buff,sizeof(buff),&my_charset_bin);
decimals=0; decimals=0;
collation.set(&my_charset_bin); collation.set(&my_charset_bin);
store_now_in_TIME(&ltime); store_now_in_TIME(&ltime);
value= (longlong) TIME_to_ulonglong_datetime(&ltime); value= (longlong) TIME_to_ulonglong_datetime(&ltime);
make_datetime((DATE_TIME_FORMAT *) 0, &ltime, &tmp); buff_length= (uint) my_datetime_to_str(&ltime, buff);
max_length= buff_length= tmp.length(); max_length= buff_length;
} }
......
...@@ -284,14 +284,6 @@ void debug_sync_point(const char* lock_name, uint lock_timeout); ...@@ -284,14 +284,6 @@ void debug_sync_point(const char* lock_name, uint lock_timeout);
#define WEEK_MONDAY_FIRST 1 #define WEEK_MONDAY_FIRST 1
#define WEEK_YEAR 2 #define WEEK_YEAR 2
#define WEEK_FIRST_WEEKDAY 4 #define WEEK_FIRST_WEEKDAY 4
/*
Required buffer length for make_date, make_time, make_datetime
and TIME_to_string functions. Note, that the caller is still
responsible to check that given TIME structure has values
in valid ranges, otherwise size of the buffer could be not
enough.
*/
#define MAX_DATE_REP_LENGTH 30
enum enum_parsing_place enum enum_parsing_place
{ {
...@@ -1046,7 +1038,6 @@ void make_date(const DATE_TIME_FORMAT *format, const TIME *l_time, ...@@ -1046,7 +1038,6 @@ void make_date(const DATE_TIME_FORMAT *format, const TIME *l_time,
String *str); String *str);
void make_time(const DATE_TIME_FORMAT *format, const TIME *l_time, void make_time(const DATE_TIME_FORMAT *format, const TIME *l_time,
String *str); String *str);
void TIME_to_string(const TIME *time, String *str);
ulonglong TIME_to_ulonglong_datetime(const TIME *time); ulonglong TIME_to_ulonglong_datetime(const TIME *time);
ulonglong TIME_to_ulonglong_date(const TIME *time); ulonglong TIME_to_ulonglong_date(const TIME *time);
ulonglong TIME_to_ulonglong_time(const TIME *time); ulonglong TIME_to_ulonglong_time(const TIME *time);
......
...@@ -880,10 +880,9 @@ bool Protocol_simple::store_date(TIME *tm) ...@@ -880,10 +880,9 @@ bool Protocol_simple::store_date(TIME *tm)
field_types[field_pos] == MYSQL_TYPE_DATE); field_types[field_pos] == MYSQL_TYPE_DATE);
field_pos++; field_pos++;
#endif #endif
char buff[40]; char buff[MAX_DATE_STRING_REP_LENGTH];
String tmp((char*) buff,sizeof(buff),&my_charset_bin); int length= my_date_to_str(tm, buff);
make_date((DATE_TIME_FORMAT *) 0, tm, &tmp); return net_store_data(buff, (uint) length);
return net_store_data((char*) tmp.ptr(), tmp.length());
} }
......
...@@ -747,13 +747,7 @@ const char *get_date_time_format_str(KNOWN_DATE_TIME_FORMAT *format, ...@@ -747,13 +747,7 @@ const char *get_date_time_format_str(KNOWN_DATE_TIME_FORMAT *format,
void make_time(const DATE_TIME_FORMAT *format __attribute__((unused)), void make_time(const DATE_TIME_FORMAT *format __attribute__((unused)),
const TIME *l_time, String *str) const TIME *l_time, String *str)
{ {
long length= my_sprintf((char*) str->ptr(), uint length= (uint) my_time_to_str(l_time, (char*) str->ptr());
((char*) str->ptr(),
"%s%02d:%02d:%02d",
(l_time->neg ? "-" : ""),
l_time->hour,
l_time->minute,
l_time->second));
str->length(length); str->length(length);
str->set_charset(&my_charset_bin); str->set_charset(&my_charset_bin);
} }
...@@ -762,12 +756,7 @@ void make_time(const DATE_TIME_FORMAT *format __attribute__((unused)), ...@@ -762,12 +756,7 @@ void make_time(const DATE_TIME_FORMAT *format __attribute__((unused)),
void make_date(const DATE_TIME_FORMAT *format __attribute__((unused)), void make_date(const DATE_TIME_FORMAT *format __attribute__((unused)),
const TIME *l_time, String *str) const TIME *l_time, String *str)
{ {
long length= my_sprintf((char*) str->ptr(), uint length= (uint) my_date_to_str(l_time, (char*) str->ptr());
((char*) str->ptr(),
"%04d-%02d-%02d",
l_time->year,
l_time->month,
l_time->day));
str->length(length); str->length(length);
str->set_charset(&my_charset_bin); str->set_charset(&my_charset_bin);
} }
...@@ -776,15 +765,7 @@ void make_date(const DATE_TIME_FORMAT *format __attribute__((unused)), ...@@ -776,15 +765,7 @@ void make_date(const DATE_TIME_FORMAT *format __attribute__((unused)),
void make_datetime(const DATE_TIME_FORMAT *format __attribute__((unused)), void make_datetime(const DATE_TIME_FORMAT *format __attribute__((unused)),
const TIME *l_time, String *str) const TIME *l_time, String *str)
{ {
long length= my_sprintf((char*) str->ptr(), uint length= (uint) my_datetime_to_str(l_time, (char*) str->ptr());
((char*) str->ptr(),
"%04d-%02d-%02d %02d:%02d:%02d",
l_time->year,
l_time->month,
l_time->day,
l_time->hour,
l_time->minute,
l_time->second));
str->length(length); str->length(length);
str->set_charset(&my_charset_bin); str->set_charset(&my_charset_bin);
} }
...@@ -894,38 +875,4 @@ ulonglong TIME_to_ulonglong(const TIME *time) ...@@ -894,38 +875,4 @@ ulonglong TIME_to_ulonglong(const TIME *time)
return 0; return 0;
} }
/*
Convert struct DATE/TIME/DATETIME value to string using built-in
MySQL time conversion formats.
SYNOPSIS
TIME_to_string()
NOTE
The string must have at least MAX_DATE_REP_LENGTH bytes reserved.
*/
void TIME_to_string(const TIME *time, String *str)
{
switch (time->time_type) {
case MYSQL_TIMESTAMP_DATETIME:
make_datetime((DATE_TIME_FORMAT*) 0, time, str);
break;
case MYSQL_TIMESTAMP_DATE:
make_date((DATE_TIME_FORMAT*) 0, time, str);
break;
case MYSQL_TIMESTAMP_TIME:
make_time((DATE_TIME_FORMAT*) 0, time, str);
break;
case MYSQL_TIMESTAMP_NONE:
case MYSQL_TIMESTAMP_ERROR:
str->length(0);
str->set_charset(&my_charset_bin);
break;
default:
DBUG_ASSERT(0);
}
}
#endif #endif
...@@ -3431,7 +3431,7 @@ static void test_fetch_date() ...@@ -3431,7 +3431,7 @@ static void test_fetch_date()
MYSQL_STMT *stmt; MYSQL_STMT *stmt;
uint i; uint i;
int rc, year; int rc, year;
char date[25], time[25], ts[25], ts_4[15], ts_6[20], dt[20]; char date[25], time[25], ts[25], ts_4[25], ts_6[20], dt[20];
ulong d_length, t_length, ts_length, ts4_length, ts6_length, ulong d_length, t_length, ts_length, ts4_length, ts6_length,
dt_length, y_length; dt_length, y_length;
MYSQL_BIND bind[8]; MYSQL_BIND bind[8];
...@@ -3541,8 +3541,8 @@ static void test_fetch_date() ...@@ -3541,8 +3541,8 @@ static void test_fetch_date()
DIE_UNLESS(strcmp(dt, "2010-07-10 00:00:00") == 0); DIE_UNLESS(strcmp(dt, "2010-07-10 00:00:00") == 0);
DIE_UNLESS(dt_length == 19); DIE_UNLESS(dt_length == 19);
DIE_UNLESS(ts_4[0] == '\0'); DIE_UNLESS(strcmp(ts_4, "0000-00-00 00:00:00") == 0);
DIE_UNLESS(ts4_length == 0); DIE_UNLESS(ts4_length == strlen("0000-00-00 00:00:00"));
DIE_UNLESS(strcmp(ts_6, "1999-12-29 00:00:00") == 0); DIE_UNLESS(strcmp(ts_6, "1999-12-29 00:00:00") == 0);
DIE_UNLESS(ts6_length == 19); DIE_UNLESS(ts6_length == 19);
...@@ -10533,6 +10533,99 @@ static void test_bug5315() ...@@ -10533,6 +10533,99 @@ static void test_bug5315()
} }
static void test_bug6049()
{
MYSQL_STMT *stmt;
MYSQL_BIND bind[1];
MYSQL_RES *res;
MYSQL_ROW row;
const char *stmt_text;
char buffer[30];
ulong length;
int rc;
myheader("test_bug6049");
stmt_text= "SELECT MAKETIME(-25, 12, 12)";
rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
myquery(rc);
res= mysql_store_result(mysql);
row= mysql_fetch_row(res);
stmt= mysql_stmt_init(mysql);
rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
check_execute(stmt, rc);
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
bzero(bind, sizeof(bind));
bind[0].buffer_type = MYSQL_TYPE_STRING;
bind[0].buffer = &buffer;
bind[0].buffer_length = sizeof(buffer);
bind[0].length = &length;
mysql_stmt_bind_result(stmt, bind);
rc= mysql_stmt_fetch(stmt);
DIE_UNLESS(rc == 0);
printf("Result from query: %s\n", row[0]);
printf("Result from prepared statement: %s\n", (char*) buffer);
DIE_UNLESS(strcmp(row[0], (char*) buffer) == 0);
mysql_free_result(res);
mysql_stmt_close(stmt);
}
static void test_bug6058()
{
MYSQL_STMT *stmt;
MYSQL_BIND bind[1];
MYSQL_RES *res;
MYSQL_ROW row;
const char *stmt_text;
char buffer[30];
ulong length;
int rc;
myheader("test_bug6058");
stmt_text= "SELECT CAST('0000-00-00' AS DATE)";
rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
myquery(rc);
res= mysql_store_result(mysql);
row= mysql_fetch_row(res);
stmt= mysql_stmt_init(mysql);
rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
check_execute(stmt, rc);
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
bzero(bind, sizeof(bind));
bind[0].buffer_type = MYSQL_TYPE_STRING;
bind[0].buffer = &buffer;
bind[0].buffer_length = sizeof(buffer);
bind[0].length = &length;
mysql_stmt_bind_result(stmt, bind);
rc= mysql_stmt_fetch(stmt);
DIE_UNLESS(rc == 0);
printf("Result from query: %s\n", row[0]);
printf("Result from prepared statement: %s\n", buffer);
DIE_UNLESS(strcmp(row[0], buffer) == 0);
mysql_free_result(res);
mysql_stmt_close(stmt);
}
/* /*
Read and parse arguments and MySQL options from my.cnf Read and parse arguments and MySQL options from my.cnf
*/ */
...@@ -10843,6 +10936,8 @@ int main(int argc, char **argv) ...@@ -10843,6 +10936,8 @@ int main(int argc, char **argv)
test_bug5194(); /* bulk inserts in prepared mode */ test_bug5194(); /* bulk inserts in prepared mode */
test_bug5315(); /* check that mysql_change_user closes all test_bug5315(); /* check that mysql_change_user closes all
prepared statements */ prepared statements */
test_bug6049(); /* check support for negative TIME values */
test_bug6058(); /* check support for 0000-00-00 dates */
/* /*
XXX: PLEASE RUN THIS PROGRAM UNDER VALGRIND AND VERIFY THAT YOUR TEST XXX: PLEASE RUN THIS PROGRAM UNDER VALGRIND AND VERIFY THAT YOUR TEST
DOESN'T CONTAIN WARNINGS/ERRORS BEFORE YOU PUSH. DOESN'T CONTAIN WARNINGS/ERRORS BEFORE YOU PUSH.
......
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