Auto-merge from mysql-5.1.

This commit is contained in:
Alexander Nozdrin 2009-11-05 14:03:16 +03:00
commit 258ec2ebaa
17 changed files with 540 additions and 100 deletions

View File

@ -557,6 +557,16 @@ unsigned long STDCALL mysql_real_escape_string(MYSQL *mysql,
char *to,const char *from, char *to,const char *from,
unsigned long length); unsigned long length);
void STDCALL mysql_debug(const char *debug); void STDCALL mysql_debug(const char *debug);
char * STDCALL mysql_odbc_escape_string(MYSQL *mysql,
char *to,
unsigned long to_length,
const char *from,
unsigned long from_length,
void *param,
char *
(*extend_buffer)
(void *, char *to,
unsigned long *length));
void STDCALL myodbc_remove_escape(MYSQL *mysql,char *name); void STDCALL myodbc_remove_escape(MYSQL *mysql,char *name);
unsigned int STDCALL mysql_thread_safe(void); unsigned int STDCALL mysql_thread_safe(void);
my_bool STDCALL mysql_embedded(void); my_bool STDCALL mysql_embedded(void);

View File

@ -518,6 +518,16 @@ unsigned long mysql_real_escape_string(MYSQL *mysql,
char *to,const char *from, char *to,const char *from,
unsigned long length); unsigned long length);
void mysql_debug(const char *debug); void mysql_debug(const char *debug);
char * mysql_odbc_escape_string(MYSQL *mysql,
char *to,
unsigned long to_length,
const char *from,
unsigned long from_length,
void *param,
char *
(*extend_buffer)
(void *, char *to,
unsigned long *length));
void myodbc_remove_escape(MYSQL *mysql,char *name); void myodbc_remove_escape(MYSQL *mysql,char *name);
unsigned int mysql_thread_safe(void); unsigned int mysql_thread_safe(void);
my_bool mysql_embedded(void); my_bool mysql_embedded(void);

View File

@ -1629,6 +1629,18 @@ mysql_real_escape_string(MYSQL *mysql, char *to,const char *from,
return (uint) escape_string_for_mysql(mysql->charset, to, 0, from, length); return (uint) escape_string_for_mysql(mysql->charset, to, 0, from, length);
} }
char * STDCALL
mysql_odbc_escape_string(MYSQL *mysql,
char *to, ulong to_length,
const char *from, ulong from_length,
void *param,
char * (*extend_buffer)
(void *, char *, ulong *))
{
return NULL;
}
void STDCALL void STDCALL
myodbc_remove_escape(MYSQL *mysql,char *name) myodbc_remove_escape(MYSQL *mysql,char *name)
{ {

View File

@ -78,6 +78,7 @@ EXPORTS
mysql_next_result mysql_next_result
mysql_num_fields mysql_num_fields
mysql_num_rows mysql_num_rows
mysql_odbc_escape_string
mysql_options mysql_options
mysql_stmt_param_count mysql_stmt_param_count
mysql_stmt_param_metadata mysql_stmt_param_metadata

View File

@ -50,6 +50,7 @@ EXPORTS
mysql_next_result mysql_next_result
mysql_num_fields mysql_num_fields
mysql_num_rows mysql_num_rows
mysql_odbc_escape_string
mysql_options mysql_options
mysql_ping mysql_ping
mysql_query mysql_query

View File

@ -158,4 +158,65 @@ LOAD DATA INFILE "../../std_data/words.dat" INTO TABLE t1;
DROP TABLE IF EXISTS t1; DROP TABLE IF EXISTS t1;
# BUG#48297: Schema name is ignored when LOAD DATA is written into binlog,
# replication aborts
-- source include/master-slave-reset.inc
-- let $db1= b48297_db1
-- let $db2= b42897_db2
-- connection master
-- disable_warnings
-- eval drop database if exists $db1
-- eval drop database if exists $db2
-- enable_warnings
-- eval create database $db1
-- eval create database $db2
-- eval use $db1
-- eval CREATE TABLE t1 (c1 VARCHAR(256)) engine=$engine_type;
-- eval use $db2
-- echo ### assertion: works with cross-referenced database
-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
-- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1
-- eval use $db1
-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
-- echo ### assertion: works with fully qualified name on current database
-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
-- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1
-- echo ### assertion: works without fully qualified name on current database
-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
-- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE t1
-- echo ### create connection without default database
-- echo ### connect (conn2,localhost,root,,*NO-ONE*);
connect (conn2,localhost,root,,*NO-ONE*);
-- connection conn2
-- echo ### assertion: works without stating the default database
-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
-- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1
-- echo ### disconnect and switch back to master connection
-- disconnect conn2
-- connection master
-- sync_slave_with_master
-- eval use $db1
let $diff_table_1=master:$db1.t1;
let $diff_table_2=slave:$db1.t1;
source include/diff_tables.inc;
-- connection master
-- eval DROP DATABASE $db1
-- eval DROP DATABASE $db2
-- sync_slave_with_master
# End of 4.1 tests # End of 4.1 tests

View File

@ -1406,4 +1406,201 @@ INSERT INTO t1 VALUES (1), (NULL);
SELECT * FROM t1 WHERE a <> NULL and (a <> NULL or a <= NULL); SELECT * FROM t1 WHERE a <> NULL and (a <> NULL or a <= NULL);
a a
DROP TABLE t1; DROP TABLE t1;
#
# Bug#47925: regression of range optimizer and date comparison in 5.1.39!
#
CREATE TABLE t1 ( a DATE, KEY ( a ) );
CREATE TABLE t2 ( a DATETIME, KEY ( a ) );
# Make optimizer choose range scan
INSERT INTO t1 VALUES ('2009-09-22'), ('2009-09-22'), ('2009-09-22');
INSERT INTO t1 VALUES ('2009-09-23'), ('2009-09-23'), ('2009-09-23');
INSERT INTO t2 VALUES ('2009-09-22 12:00:00'), ('2009-09-22 12:00:00'),
('2009-09-22 12:00:00');
INSERT INTO t2 VALUES ('2009-09-23 12:00:00'), ('2009-09-23 12:00:00'),
('2009-09-23 12:00:00');
# DATE vs DATE
EXPLAIN
SELECT * FROM t1 WHERE a >= '2009/09/23';
id select_type table type possible_keys key key_len ref rows Extra
X X X range a a X X X X
SELECT * FROM t1 WHERE a >= '2009/09/23';
a
2009-09-23
2009-09-23
2009-09-23
SELECT * FROM t1 WHERE a >= '20090923';
a
2009-09-23
2009-09-23
2009-09-23
SELECT * FROM t1 WHERE a >= 20090923;
a
2009-09-23
2009-09-23
2009-09-23
SELECT * FROM t1 WHERE a >= '2009-9-23';
a
2009-09-23
2009-09-23
2009-09-23
SELECT * FROM t1 WHERE a >= '2009.09.23';
a
2009-09-23
2009-09-23
2009-09-23
SELECT * FROM t1 WHERE a >= '2009:09:23';
a
2009-09-23
2009-09-23
2009-09-23
# DATE vs DATETIME
EXPLAIN
SELECT * FROM t2 WHERE a >= '2009/09/23';
id select_type table type possible_keys key key_len ref rows Extra
X X X range a a X X X X
SELECT * FROM t2 WHERE a >= '2009/09/23';
a
2009-09-23 12:00:00
2009-09-23 12:00:00
2009-09-23 12:00:00
SELECT * FROM t2 WHERE a >= '2009/09/23';
a
2009-09-23 12:00:00
2009-09-23 12:00:00
2009-09-23 12:00:00
SELECT * FROM t2 WHERE a >= '20090923';
a
2009-09-23 12:00:00
2009-09-23 12:00:00
2009-09-23 12:00:00
SELECT * FROM t2 WHERE a >= 20090923;
a
2009-09-23 12:00:00
2009-09-23 12:00:00
2009-09-23 12:00:00
SELECT * FROM t2 WHERE a >= '2009-9-23';
a
2009-09-23 12:00:00
2009-09-23 12:00:00
2009-09-23 12:00:00
SELECT * FROM t2 WHERE a >= '2009.09.23';
a
2009-09-23 12:00:00
2009-09-23 12:00:00
2009-09-23 12:00:00
SELECT * FROM t2 WHERE a >= '2009:09:23';
a
2009-09-23 12:00:00
2009-09-23 12:00:00
2009-09-23 12:00:00
# DATETIME vs DATETIME
EXPLAIN
SELECT * FROM t2 WHERE a >= '2009/09/23 12:00:00';
id select_type table type possible_keys key key_len ref rows Extra
X X X range a a X X X X
SELECT * FROM t2 WHERE a >= '2009/09/23 12:00:00';
a
2009-09-23 12:00:00
2009-09-23 12:00:00
2009-09-23 12:00:00
SELECT * FROM t2 WHERE a >= '20090923120000';
a
2009-09-23 12:00:00
2009-09-23 12:00:00
2009-09-23 12:00:00
SELECT * FROM t2 WHERE a >= 20090923120000;
a
2009-09-23 12:00:00
2009-09-23 12:00:00
2009-09-23 12:00:00
SELECT * FROM t2 WHERE a >= '2009-9-23 12:00:00';
a
2009-09-23 12:00:00
2009-09-23 12:00:00
2009-09-23 12:00:00
SELECT * FROM t2 WHERE a >= '2009.09.23 12:00:00';
a
2009-09-23 12:00:00
2009-09-23 12:00:00
2009-09-23 12:00:00
SELECT * FROM t2 WHERE a >= '2009:09:23 12:00:00';
a
2009-09-23 12:00:00
2009-09-23 12:00:00
2009-09-23 12:00:00
# DATETIME vs DATE
EXPLAIN
SELECT * FROM t1 WHERE a >= '2009/09/23 00:00:00';
id select_type table type possible_keys key key_len ref rows Extra
X X X range a a X X X X
SELECT * FROM t1 WHERE a >= '2009/09/23 00:00:00';
a
2009-09-23
2009-09-23
2009-09-23
SELECT * FROM t1 WHERE a >= '2009/09/23 00:00:00';
a
2009-09-23
2009-09-23
2009-09-23
SELECT * FROM t1 WHERE a >= '20090923000000';
a
2009-09-23
2009-09-23
2009-09-23
SELECT * FROM t1 WHERE a >= 20090923000000;
a
2009-09-23
2009-09-23
2009-09-23
SELECT * FROM t1 WHERE a >= '2009-9-23 00:00:00';
a
2009-09-23
2009-09-23
2009-09-23
SELECT * FROM t1 WHERE a >= '2009.09.23 00:00:00';
a
2009-09-23
2009-09-23
2009-09-23
SELECT * FROM t1 WHERE a >= '2009:09:23 00:00:00';
a
2009-09-23
2009-09-23
2009-09-23
# Test of the new get_date_from_str implementation
# Behavior differs slightly between the trunk and mysql-pe.
# The former may give errors for the truncated values, while the latter
# gives warnings. The purpose of this test is not to interfere, and only
# preserve existing behavior.
SELECT str_to_date('2007-10-00', '%Y-%m-%d') >= '' AND
str_to_date('2007-10-00', '%Y-%m-%d') <= '2007/10/20';
str_to_date('2007-10-00', '%Y-%m-%d') >= '' AND
str_to_date('2007-10-00', '%Y-%m-%d') <= '2007/10/20'
1
Warnings:
Warning 1292 Truncated incorrect date value: ''
SELECT str_to_date('2007-20-00', '%Y-%m-%d') >= '2007/10/20' AND
str_to_date('2007-20-00', '%Y-%m-%d') <= '';
str_to_date('2007-20-00', '%Y-%m-%d') >= '2007/10/20' AND
str_to_date('2007-20-00', '%Y-%m-%d') <= ''
NULL
Warnings:
Warning 1292 Truncated incorrect date value: ''
Error 1411 Incorrect datetime value: '2007-20-00' for function str_to_date
Error 1411 Incorrect datetime value: '2007-20-00' for function str_to_date
SELECT str_to_date('2007-10-00', '%Y-%m-%d') BETWEEN '' AND '2007/10/20';
str_to_date('2007-10-00', '%Y-%m-%d') BETWEEN '' AND '2007/10/20'
1
Warnings:
Warning 1292 Truncated incorrect datetime value: ''
SELECT str_to_date('2007-20-00', '%Y-%m-%d') BETWEEN '2007/10/20' AND '';
str_to_date('2007-20-00', '%Y-%m-%d') BETWEEN '2007/10/20' AND ''
NULL
Warnings:
Error 1411 Incorrect datetime value: '2007-20-00' for function str_to_date
SELECT str_to_date('', '%Y-%m-%d');
str_to_date('', '%Y-%m-%d')
0000-00-00
DROP TABLE t1, t2;
End of 5.1 tests End of 5.1 tests

View File

@ -86,3 +86,32 @@ CREATE TABLE t1 (word CHAR(20) NOT NULL PRIMARY KEY) ENGINE=INNODB;
LOAD DATA INFILE "../../std_data/words.dat" INTO TABLE t1; LOAD DATA INFILE "../../std_data/words.dat" INTO TABLE t1;
ERROR 23000: Duplicate entry 'Aarhus' for key 'PRIMARY' ERROR 23000: Duplicate entry 'Aarhus' for key 'PRIMARY'
DROP TABLE IF EXISTS t1; DROP TABLE IF EXISTS t1;
stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
drop database if exists b48297_db1;
drop database if exists b42897_db2;
create database b48297_db1;
create database b42897_db2;
use b48297_db1;
CREATE TABLE t1 (c1 VARCHAR(256)) engine=MyISAM;;
use b42897_db2;
### assertion: works with cross-referenced database
LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE b48297_db1.t1;
use b48297_db1;
### assertion: works with fully qualified name on current database
LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE b48297_db1.t1;
### assertion: works without fully qualified name on current database
LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE t1;
### create connection without default database
### connect (conn2,localhost,root,,*NO-ONE*);
### assertion: works without stating the default database
LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE b48297_db1.t1;
### disconnect and switch back to master connection
use b48297_db1;
Comparing tables master:b48297_db1.t1 and slave:b48297_db1.t1
DROP DATABASE b48297_db1;
DROP DATABASE b42897_db2;

View File

@ -1181,4 +1181,83 @@ INSERT INTO t1 VALUES (1), (NULL);
SELECT * FROM t1 WHERE a <> NULL and (a <> NULL or a <= NULL); SELECT * FROM t1 WHERE a <> NULL and (a <> NULL or a <= NULL);
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # Bug#47925: regression of range optimizer and date comparison in 5.1.39!
--echo #
CREATE TABLE t1 ( a DATE, KEY ( a ) );
CREATE TABLE t2 ( a DATETIME, KEY ( a ) );
--echo # Make optimizer choose range scan
INSERT INTO t1 VALUES ('2009-09-22'), ('2009-09-22'), ('2009-09-22');
INSERT INTO t1 VALUES ('2009-09-23'), ('2009-09-23'), ('2009-09-23');
INSERT INTO t2 VALUES ('2009-09-22 12:00:00'), ('2009-09-22 12:00:00'),
('2009-09-22 12:00:00');
INSERT INTO t2 VALUES ('2009-09-23 12:00:00'), ('2009-09-23 12:00:00'),
('2009-09-23 12:00:00');
--echo # DATE vs DATE
--replace_column 1 X 2 X 3 X 7 X 8 X 9 X 10 X
EXPLAIN
SELECT * FROM t1 WHERE a >= '2009/09/23';
SELECT * FROM t1 WHERE a >= '2009/09/23';
SELECT * FROM t1 WHERE a >= '20090923';
SELECT * FROM t1 WHERE a >= 20090923;
SELECT * FROM t1 WHERE a >= '2009-9-23';
SELECT * FROM t1 WHERE a >= '2009.09.23';
SELECT * FROM t1 WHERE a >= '2009:09:23';
--echo # DATE vs DATETIME
--replace_column 1 X 2 X 3 X 7 X 8 X 9 X 10 X
EXPLAIN
SELECT * FROM t2 WHERE a >= '2009/09/23';
SELECT * FROM t2 WHERE a >= '2009/09/23';
SELECT * FROM t2 WHERE a >= '2009/09/23';
SELECT * FROM t2 WHERE a >= '20090923';
SELECT * FROM t2 WHERE a >= 20090923;
SELECT * FROM t2 WHERE a >= '2009-9-23';
SELECT * FROM t2 WHERE a >= '2009.09.23';
SELECT * FROM t2 WHERE a >= '2009:09:23';
--echo # DATETIME vs DATETIME
--replace_column 1 X 2 X 3 X 7 X 8 X 9 X 10 X
EXPLAIN
SELECT * FROM t2 WHERE a >= '2009/09/23 12:00:00';
SELECT * FROM t2 WHERE a >= '2009/09/23 12:00:00';
SELECT * FROM t2 WHERE a >= '20090923120000';
SELECT * FROM t2 WHERE a >= 20090923120000;
SELECT * FROM t2 WHERE a >= '2009-9-23 12:00:00';
SELECT * FROM t2 WHERE a >= '2009.09.23 12:00:00';
SELECT * FROM t2 WHERE a >= '2009:09:23 12:00:00';
--echo # DATETIME vs DATE
--replace_column 1 X 2 X 3 X 7 X 8 X 9 X 10 X
EXPLAIN
SELECT * FROM t1 WHERE a >= '2009/09/23 00:00:00';
SELECT * FROM t1 WHERE a >= '2009/09/23 00:00:00';
SELECT * FROM t1 WHERE a >= '2009/09/23 00:00:00';
SELECT * FROM t1 WHERE a >= '20090923000000';
SELECT * FROM t1 WHERE a >= 20090923000000;
SELECT * FROM t1 WHERE a >= '2009-9-23 00:00:00';
SELECT * FROM t1 WHERE a >= '2009.09.23 00:00:00';
SELECT * FROM t1 WHERE a >= '2009:09:23 00:00:00';
--echo # Test of the new get_date_from_str implementation
--echo # Behavior differs slightly between the trunk and mysql-pe.
--echo # The former may give errors for the truncated values, while the latter
--echo # gives warnings. The purpose of this test is not to interfere, and only
--echo # preserve existing behavior.
SELECT str_to_date('2007-10-00', '%Y-%m-%d') >= '' AND
str_to_date('2007-10-00', '%Y-%m-%d') <= '2007/10/20';
SELECT str_to_date('2007-20-00', '%Y-%m-%d') >= '2007/10/20' AND
str_to_date('2007-20-00', '%Y-%m-%d') <= '';
SELECT str_to_date('2007-10-00', '%Y-%m-%d') BETWEEN '' AND '2007/10/20';
SELECT str_to_date('2007-20-00', '%Y-%m-%d') BETWEEN '2007/10/20' AND '';
SELECT str_to_date('', '%Y-%m-%d');
DROP TABLE t1, t2;
--echo End of 5.1 tests --echo End of 5.1 tests

View File

@ -6866,72 +6866,61 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
} }
/** /**
Compare the value stored in field, with the original item. Compare the value stored in field with the expression from the query.
@param field field which the item is converted and stored in @param field Field which the Item is stored in after conversion
@param item original item @param item Original expression from query
@return Return an integer greater than, equal to, or less than 0 if @return Returns an integer greater than, equal to, or less than 0 if
the value stored in the field is greater than, equal to, the value stored in the field is greater than, equal to,
or less than the original item or less than the original Item. A 0 may also be returned if
out of memory.
@note We only use this on the range optimizer/partition pruning, @note We only use this on the range optimizer/partition pruning,
because in some cases we can't store the value in the field because in some cases we can't store the value in the field
without some precision/character loss. without some precision/character loss.
*/ */
int stored_field_cmp_to_item(Field *field, Item *item) int stored_field_cmp_to_item(THD *thd, Field *field, Item *item)
{ {
Item_result res_type=item_cmp_type(field->result_type(), Item_result res_type=item_cmp_type(field->result_type(),
item->result_type()); item->result_type());
if (res_type == STRING_RESULT) if (res_type == STRING_RESULT)
{ {
char item_buff[MAX_FIELD_WIDTH]; char item_buff[MAX_FIELD_WIDTH];
char field_buff[MAX_FIELD_WIDTH]; char field_buff[MAX_FIELD_WIDTH];
String item_tmp(item_buff,sizeof(item_buff),&my_charset_bin),*item_result;
String item_tmp(item_buff,sizeof(item_buff),&my_charset_bin);
String field_tmp(field_buff,sizeof(field_buff),&my_charset_bin); String field_tmp(field_buff,sizeof(field_buff),&my_charset_bin);
enum_field_types field_type; String *item_result= item->val_str(&item_tmp);
item_result=item->val_str(&item_tmp); /*
Some implementations of Item::val_str(String*) actually modify
the field Item::null_value, hence we can't check it earlier.
*/
if (item->null_value) if (item->null_value)
return 0; return 0;
field->val_str(&field_tmp); String *field_result= field->val_str(&field_tmp);
/* enum_field_types field_type= field->type();
If comparing DATE with DATETIME, append the time-part to the DATE.
So that the strings are equally formatted. if (field_type == MYSQL_TYPE_DATE || field_type == MYSQL_TYPE_DATETIME)
A DATE converted to string is 10 (MAX_DATE_WIDTH) characters,
and a DATETIME converted to string is 19 (MAX_DATETIME_WIDTH) characters.
*/
field_type= field->type();
uint32 item_length= item_result->length();
if (field_type == MYSQL_TYPE_DATE &&
item_length == MAX_DATETIME_WIDTH)
field_tmp.append(" 00:00:00");
else if (field_type == MYSQL_TYPE_DATETIME)
{ {
if (item_length == MAX_DATE_WIDTH) enum_mysql_timestamp_type type= MYSQL_TIMESTAMP_ERROR;
item_result->append(" 00:00:00");
else if (item_length > MAX_DATETIME_WIDTH) if (field_type == MYSQL_TYPE_DATE)
{ type= MYSQL_TIMESTAMP_DATE;
/*
We don't store microsecond part of DATETIME in field if (field_type == MYSQL_TYPE_DATETIME)
but item_result contains it. As we compare DATETIMEs as strings type= MYSQL_TIMESTAMP_DATETIME;
we must trim trailing 0's in item_result's microsecond part
to ensure "YYYY-MM-DD HH:MM:SS" == "YYYY-MM-DD HH:MM:SS.0000" const char *field_name= field->field_name;
*/ MYSQL_TIME field_time, item_time;
char *end= (char *) item_result->ptr() + item_length - 1; get_mysql_time_from_str(thd, field_result, type, field_name, &field_time);
/* Trim trailing 0's */ get_mysql_time_from_str(thd, item_result, type, field_name, &item_time);
while (*end == '0')
end--; return my_time_compare(&field_time, &item_time);
/* Trim '.' if no microseconds */
if (*end == '.')
end--;
DBUG_ASSERT(end - item_result->ptr() + 1 >= MAX_DATETIME_WIDTH);
item_result->length(end - item_result->ptr() + 1);
} }
} return stringcmp(field_result, item_result);
return stringcmp(&field_tmp,item_result);
} }
if (res_type == INT_RESULT) if (res_type == INT_RESULT)
return 0; // Both are of type int return 0; // Both are of type int

View File

@ -3125,4 +3125,4 @@ void mark_select_range_as_dependent(THD *thd,
extern Cached_item *new_Cached_item(THD *thd, Item *item); extern Cached_item *new_Cached_item(THD *thd, Item *item);
extern Item_result item_cmp_type(Item_result a,Item_result b); extern Item_result item_cmp_type(Item_result a,Item_result b);
extern void resolve_const_item(THD *thd, Item **ref, Item *cmp_item); extern void resolve_const_item(THD *thd, Item **ref, Item *cmp_item);
extern int stored_field_cmp_to_item(Field *field, Item *item); extern int stored_field_cmp_to_item(THD *thd, Field *field, Item *item);

View File

@ -636,6 +636,62 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
return 0; return 0;
} }
/**
Parse date provided in a string to a MYSQL_TIME.
@param[in] thd Thread handle
@param[in] str A string to convert
@param[in] warn_type Type of the timestamp for issuing the warning
@param[in] warn_name Field name for issuing the warning
@param[out] l_time The MYSQL_TIME objects is initialized.
Parses a date provided in the string str into a MYSQL_TIME object. If the
string contains an incorrect date or doesn't correspond to a date at all
then a warning is issued. The warn_type and the warn_name arguments are used
as the name and the type of the field when issuing the warning. If any input
was discarded (trailing or non-timestamp-y characters), return value will be
TRUE.
@return Status flag
@retval FALSE Success.
@retval True Indicates failure.
*/
bool get_mysql_time_from_str(THD *thd, String *str, timestamp_type warn_type,
const char *warn_name, MYSQL_TIME *l_time)
{
bool value;
int error;
enum_mysql_timestamp_type timestamp_type;
timestamp_type=
str_to_datetime(str->ptr(), str->length(), l_time,
(TIME_FUZZY_DATE | MODE_INVALID_DATES |
(thd->variables.sql_mode &
(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE))),
&error);
if (timestamp_type == MYSQL_TIMESTAMP_DATETIME ||
timestamp_type == MYSQL_TIMESTAMP_DATE)
/*
Do not return yet, we may still want to throw a "trailing garbage"
warning.
*/
value= FALSE;
else
{
value= TRUE;
error= 1; /* force warning */
}
if (error > 0)
make_truncated_value_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
str->ptr(), str->length(),
warn_type, warn_name);
return value;
}
/** /**
@brief Convert date provided in a string to the int representation. @brief Convert date provided in a string to the int representation.
@ -650,51 +706,21 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
representation. If the string contains wrong date or doesn't representation. If the string contains wrong date or doesn't
contain it at all then a warning is issued. The warn_type and contain it at all then a warning is issued. The warn_type and
the warn_name arguments are used as the name and the type of the the warn_name arguments are used as the name and the type of the
field when issuing the warning. If any input was discarded field when issuing the warning.
(trailing or non-timestampy characters), was_cut will be non-zero.
was_type will return the type str_to_datetime() could correctly
extract.
@return @return
converted value. 0 on error and on zero-dates -- check 'failure' converted value. 0 on error and on zero-dates -- check 'failure'
*/ */
static ulonglong get_date_from_str(THD *thd, String *str,
static ulonglong timestamp_type warn_type,
get_date_from_str(THD *thd, String *str, timestamp_type warn_type, const char *warn_name, bool *error_arg)
char *warn_name, bool *error_arg)
{ {
ulonglong value= 0;
int error;
MYSQL_TIME l_time; MYSQL_TIME l_time;
enum_mysql_timestamp_type ret; *error_arg= get_mysql_time_from_str(thd, str, warn_type, warn_name, &l_time);
ret= str_to_datetime(str->ptr(), str->length(), &l_time, if (*error_arg)
(TIME_FUZZY_DATE | MODE_INVALID_DATES | return 0;
(thd->variables.sql_mode & return TIME_to_ulonglong_datetime(&l_time);
(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE))),
&error);
if (ret == MYSQL_TIMESTAMP_DATETIME || ret == MYSQL_TIMESTAMP_DATE)
{
/*
Do not return yet, we may still want to throw a "trailing garbage"
warning.
*/
*error_arg= FALSE;
value= TIME_to_ulonglong_datetime(&l_time);
}
else
{
*error_arg= TRUE;
error= 1; /* force warning */
}
if (error > 0)
make_truncated_value_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
str->ptr(), str->length(),
warn_type, warn_name);
return value;
} }

View File

@ -1721,3 +1721,6 @@ inline Item *and_conds(Item *a, Item *b)
} }
Item *and_expressions(Item *a, Item *b, Item **org_item); Item *and_expressions(Item *a, Item *b, Item **org_item);
bool get_mysql_time_from_str(THD *thd, String *str, timestamp_type warn_type,
const char *warn_name, MYSQL_TIME *l_time);

View File

@ -5968,7 +5968,7 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
switch (type) { switch (type) {
case Item_func::LT_FUNC: case Item_func::LT_FUNC:
if (stored_field_cmp_to_item(field,value) == 0) if (stored_field_cmp_to_item(param->thd, field, value) == 0)
tree->max_flag=NEAR_MAX; tree->max_flag=NEAR_MAX;
/* fall through */ /* fall through */
case Item_func::LE_FUNC: case Item_func::LE_FUNC:
@ -5983,14 +5983,14 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
case Item_func::GT_FUNC: case Item_func::GT_FUNC:
/* Don't use open ranges for partial key_segments */ /* Don't use open ranges for partial key_segments */
if ((!(key_part->flag & HA_PART_KEY_SEG)) && if ((!(key_part->flag & HA_PART_KEY_SEG)) &&
(stored_field_cmp_to_item(field, value) <= 0)) (stored_field_cmp_to_item(param->thd, field, value) <= 0))
tree->min_flag=NEAR_MIN; tree->min_flag=NEAR_MIN;
tree->max_flag= NO_MAX_RANGE; tree->max_flag= NO_MAX_RANGE;
break; break;
case Item_func::GE_FUNC: case Item_func::GE_FUNC:
/* Don't use open ranges for partial key_segments */ /* Don't use open ranges for partial key_segments */
if ((!(key_part->flag & HA_PART_KEY_SEG)) && if ((!(key_part->flag & HA_PART_KEY_SEG)) &&
(stored_field_cmp_to_item(field,value) < 0)) (stored_field_cmp_to_item(param->thd, field, value) < 0))
tree->min_flag= NEAR_MIN; tree->min_flag= NEAR_MIN;
tree->max_flag=NO_MAX_RANGE; tree->max_flag=NO_MAX_RANGE;
break; break;

View File

@ -84,7 +84,7 @@ static int read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
bool ignore_check_option_errors); bool ignore_check_option_errors);
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex, static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex,
const char* db_arg, const char* db_arg, /* table's database */
const char* table_name_arg, const char* table_name_arg,
enum enum_duplicates duplicates, enum enum_duplicates duplicates,
bool ignore, bool ignore,
@ -501,7 +501,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
if (thd->transaction.stmt.modified_non_trans_table) if (thd->transaction.stmt.modified_non_trans_table)
write_execute_load_query_log_event(thd, ex, write_execute_load_query_log_event(thd, ex,
tdb, table_list->table_name, table_list->db,
table_list->table_name,
handle_duplicates, ignore, handle_duplicates, ignore,
transactional_table, transactional_table,
errcode); errcode);
@ -548,7 +549,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
{ {
int errcode= query_error_code(thd, killed_status == THD::NOT_KILLED); int errcode= query_error_code(thd, killed_status == THD::NOT_KILLED);
write_execute_load_query_log_event(thd, ex, write_execute_load_query_log_event(thd, ex,
tdb, table_list->table_name, table_list->db, table_list->table_name,
handle_duplicates, ignore, handle_duplicates, ignore,
transactional_table, transactional_table,
errcode); errcode);
@ -573,7 +574,7 @@ err:
/* Not a very useful function; just to avoid duplication of code */ /* Not a very useful function; just to avoid duplication of code */
static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex, static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex,
const char* db_arg, const char* db_arg, /* table's database */
const char* table_name_arg, const char* table_name_arg,
enum enum_duplicates duplicates, enum enum_duplicates duplicates,
bool ignore, bool ignore,
@ -590,8 +591,27 @@ static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex,
Item *item, *val; Item *item, *val;
String pfield, pfields; String pfield, pfields;
int n; int n;
const char *tbl= table_name_arg;
const char *tdb= (thd->db != NULL ? thd->db : db_arg);
String string_buf;
Load_log_event lle(thd, ex, db_arg, table_name_arg, fv, duplicates, if (!thd->db || strcmp(db_arg, thd->db))
{
/*
If used database differs from table's database,
prefix table name with database name so that it
becomes a FQ name.
*/
string_buf.set_charset(system_charset_info);
string_buf.append(db_arg);
string_buf.append("`");
string_buf.append(".");
string_buf.append("`");
string_buf.append(table_name_arg);
tbl= string_buf.c_ptr_safe();
}
Load_log_event lle(thd, ex, tdb, tbl, fv, duplicates,
ignore, transactional_table); ignore, transactional_table);
/* /*

View File

@ -965,20 +965,22 @@ calc_time_diff(MYSQL_TIME *l_time1, MYSQL_TIME *l_time2, int l_sign, longlong *s
0 - a == b 0 - a == b
1 - a > b 1 - a > b
NOTES
TIME.second_part is not considered during comparison
*/ */
int int my_time_compare(MYSQL_TIME *a, MYSQL_TIME *b)
my_time_compare(MYSQL_TIME *a, MYSQL_TIME *b)
{ {
my_ulonglong a_t= TIME_to_ulonglong_datetime(a); ulonglong a_t= TIME_to_ulonglong_datetime(a);
my_ulonglong b_t= TIME_to_ulonglong_datetime(b); ulonglong b_t= TIME_to_ulonglong_datetime(b);
if (a_t < b_t)
return -1;
if (a_t > b_t) if (a_t > b_t)
return 1; return 1;
else if (a_t < b_t)
if (a->second_part < b->second_part)
return -1; return -1;
if (a->second_part > b->second_part)
return 1;
return 0; return 0;
} }

View File

@ -14831,7 +14831,7 @@ void Dblqh::srLogLimits(Signal* signal)
while(true) { while(true) {
ndbrequire(tmbyte < clogFileSize); ndbrequire(tmbyte < clogFileSize);
if (logPartPtr.p->logExecState == LogPartRecord::LES_SEARCH_STOP) { if (logPartPtr.p->logExecState == LogPartRecord::LES_SEARCH_STOP) {
if (logFilePtr.p->logMaxGciCompleted[tmbyte] < logPartPtr.p->logLastGci) { if (logFilePtr.p->logMaxGciCompleted[tmbyte] <= logPartPtr.p->logLastGci) {
jam(); jam();
/* -------------------------------------------------------------------- /* --------------------------------------------------------------------
* WE ARE STEPPING BACKWARDS FROM MBYTE TO MBYTE. THIS IS THE FIRST * WE ARE STEPPING BACKWARDS FROM MBYTE TO MBYTE. THIS IS THE FIRST