mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Auto-merge from mysql-5.1.
This commit is contained in:
@ -557,6 +557,16 @@ unsigned long STDCALL mysql_real_escape_string(MYSQL *mysql,
|
||||
char *to,const char *from,
|
||||
unsigned long length);
|
||||
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);
|
||||
unsigned int STDCALL mysql_thread_safe(void);
|
||||
my_bool STDCALL mysql_embedded(void);
|
||||
|
@ -518,6 +518,16 @@ unsigned long mysql_real_escape_string(MYSQL *mysql,
|
||||
char *to,const char *from,
|
||||
unsigned long length);
|
||||
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);
|
||||
unsigned int mysql_thread_safe(void);
|
||||
my_bool mysql_embedded(void);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
myodbc_remove_escape(MYSQL *mysql,char *name)
|
||||
{
|
||||
|
@ -78,6 +78,7 @@ EXPORTS
|
||||
mysql_next_result
|
||||
mysql_num_fields
|
||||
mysql_num_rows
|
||||
mysql_odbc_escape_string
|
||||
mysql_options
|
||||
mysql_stmt_param_count
|
||||
mysql_stmt_param_metadata
|
||||
|
@ -50,6 +50,7 @@ EXPORTS
|
||||
mysql_next_result
|
||||
mysql_num_fields
|
||||
mysql_num_rows
|
||||
mysql_odbc_escape_string
|
||||
mysql_options
|
||||
mysql_ping
|
||||
mysql_query
|
||||
|
@ -158,4 +158,65 @@ LOAD DATA INFILE "../../std_data/words.dat" INTO TABLE 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
|
||||
|
@ -1406,4 +1406,201 @@ INSERT INTO t1 VALUES (1), (NULL);
|
||||
SELECT * FROM t1 WHERE a <> NULL and (a <> NULL or a <= NULL);
|
||||
a
|
||||
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
|
||||
|
@ -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;
|
||||
ERROR 23000: Duplicate entry 'Aarhus' for key 'PRIMARY'
|
||||
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;
|
||||
|
@ -1181,4 +1181,83 @@ INSERT INTO t1 VALUES (1), (NULL);
|
||||
SELECT * FROM t1 WHERE a <> NULL and (a <> NULL or a <= NULL);
|
||||
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
|
||||
|
79
sql/item.cc
79
sql/item.cc
@ -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 item original item
|
||||
@param field Field which the Item is stored in after conversion
|
||||
@param item Original expression from query
|
||||
|
||||
@return Return an integer greater than, equal to, or less than 0 if
|
||||
the value stored in the field is greater than, equal to,
|
||||
or less than the original item
|
||||
@return Returns an integer greater than, equal to, or less than 0 if
|
||||
the value stored in the field is greater than, equal to,
|
||||
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,
|
||||
because in some cases we can't store the value in the field
|
||||
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_type());
|
||||
if (res_type == STRING_RESULT)
|
||||
{
|
||||
char item_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);
|
||||
enum_field_types field_type;
|
||||
item_result=item->val_str(&item_tmp);
|
||||
String *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)
|
||||
return 0;
|
||||
field->val_str(&field_tmp);
|
||||
String *field_result= field->val_str(&field_tmp);
|
||||
|
||||
/*
|
||||
If comparing DATE with DATETIME, append the time-part to the DATE.
|
||||
So that the strings are equally formatted.
|
||||
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)
|
||||
enum_field_types field_type= field->type();
|
||||
|
||||
if (field_type == MYSQL_TYPE_DATE || field_type == MYSQL_TYPE_DATETIME)
|
||||
{
|
||||
if (item_length == MAX_DATE_WIDTH)
|
||||
item_result->append(" 00:00:00");
|
||||
else if (item_length > MAX_DATETIME_WIDTH)
|
||||
{
|
||||
/*
|
||||
We don't store microsecond part of DATETIME in field
|
||||
but item_result contains it. As we compare DATETIMEs as strings
|
||||
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"
|
||||
*/
|
||||
char *end= (char *) item_result->ptr() + item_length - 1;
|
||||
/* Trim trailing 0's */
|
||||
while (*end == '0')
|
||||
end--;
|
||||
/* 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);
|
||||
}
|
||||
enum_mysql_timestamp_type type= MYSQL_TIMESTAMP_ERROR;
|
||||
|
||||
if (field_type == MYSQL_TYPE_DATE)
|
||||
type= MYSQL_TIMESTAMP_DATE;
|
||||
|
||||
if (field_type == MYSQL_TYPE_DATETIME)
|
||||
type= MYSQL_TIMESTAMP_DATETIME;
|
||||
|
||||
const char *field_name= field->field_name;
|
||||
MYSQL_TIME field_time, item_time;
|
||||
get_mysql_time_from_str(thd, field_result, type, field_name, &field_time);
|
||||
get_mysql_time_from_str(thd, item_result, type, field_name, &item_time);
|
||||
|
||||
return my_time_compare(&field_time, &item_time);
|
||||
}
|
||||
return stringcmp(&field_tmp,item_result);
|
||||
return stringcmp(field_result, item_result);
|
||||
}
|
||||
if (res_type == INT_RESULT)
|
||||
return 0; // Both are of type int
|
||||
|
@ -3125,4 +3125,4 @@ void mark_select_range_as_dependent(THD *thd,
|
||||
extern Cached_item *new_Cached_item(THD *thd, Item *item);
|
||||
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 int stored_field_cmp_to_item(Field *field, Item *item);
|
||||
extern int stored_field_cmp_to_item(THD *thd, Field *field, Item *item);
|
||||
|
@ -636,6 +636,62 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
|
||||
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.
|
||||
@ -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
|
||||
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
|
||||
field when issuing the warning. If any input was discarded
|
||||
(trailing or non-timestampy characters), was_cut will be non-zero.
|
||||
was_type will return the type str_to_datetime() could correctly
|
||||
extract.
|
||||
field when issuing the warning.
|
||||
|
||||
@return
|
||||
converted value. 0 on error and on zero-dates -- check 'failure'
|
||||
*/
|
||||
|
||||
static ulonglong
|
||||
get_date_from_str(THD *thd, String *str, timestamp_type warn_type,
|
||||
char *warn_name, bool *error_arg)
|
||||
static ulonglong get_date_from_str(THD *thd, String *str,
|
||||
timestamp_type warn_type,
|
||||
const char *warn_name, bool *error_arg)
|
||||
{
|
||||
ulonglong value= 0;
|
||||
int error;
|
||||
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,
|
||||
(TIME_FUZZY_DATE | MODE_INVALID_DATES |
|
||||
(thd->variables.sql_mode &
|
||||
(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;
|
||||
if (*error_arg)
|
||||
return 0;
|
||||
return TIME_to_ulonglong_datetime(&l_time);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1721,3 +1721,6 @@ inline Item *and_conds(Item *a, Item *b)
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -5968,7 +5968,7 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
|
||||
|
||||
switch (type) {
|
||||
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;
|
||||
/* fall through */
|
||||
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:
|
||||
/* Don't use open ranges for partial key_segments */
|
||||
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->max_flag= NO_MAX_RANGE;
|
||||
break;
|
||||
case Item_func::GE_FUNC:
|
||||
/* Don't use open ranges for partial key_segments */
|
||||
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->max_flag=NO_MAX_RANGE;
|
||||
break;
|
||||
|
@ -84,7 +84,7 @@ static int read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||
bool ignore_check_option_errors);
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
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,
|
||||
enum enum_duplicates duplicates,
|
||||
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)
|
||||
write_execute_load_query_log_event(thd, ex,
|
||||
tdb, table_list->table_name,
|
||||
table_list->db,
|
||||
table_list->table_name,
|
||||
handle_duplicates, ignore,
|
||||
transactional_table,
|
||||
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);
|
||||
write_execute_load_query_log_event(thd, ex,
|
||||
tdb, table_list->table_name,
|
||||
table_list->db, table_list->table_name,
|
||||
handle_duplicates, ignore,
|
||||
transactional_table,
|
||||
errcode);
|
||||
@ -573,7 +574,7 @@ err:
|
||||
|
||||
/* Not a very useful function; just to avoid duplication of code */
|
||||
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,
|
||||
enum enum_duplicates duplicates,
|
||||
bool ignore,
|
||||
@ -590,8 +591,27 @@ static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex,
|
||||
Item *item, *val;
|
||||
String pfield, pfields;
|
||||
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);
|
||||
|
||||
/*
|
||||
|
16
sql/time.cc
16
sql/time.cc
@ -965,20 +965,22 @@ calc_time_diff(MYSQL_TIME *l_time1, MYSQL_TIME *l_time2, int l_sign, longlong *s
|
||||
0 - a == b
|
||||
1 - a > b
|
||||
|
||||
NOTES
|
||||
TIME.second_part is not considered during comparison
|
||||
*/
|
||||
|
||||
int
|
||||
my_time_compare(MYSQL_TIME *a, MYSQL_TIME *b)
|
||||
int my_time_compare(MYSQL_TIME *a, MYSQL_TIME *b)
|
||||
{
|
||||
my_ulonglong a_t= TIME_to_ulonglong_datetime(a);
|
||||
my_ulonglong b_t= TIME_to_ulonglong_datetime(b);
|
||||
ulonglong a_t= TIME_to_ulonglong_datetime(a);
|
||||
ulonglong b_t= TIME_to_ulonglong_datetime(b);
|
||||
|
||||
if (a_t < b_t)
|
||||
return -1;
|
||||
if (a_t > b_t)
|
||||
return 1;
|
||||
else if (a_t < b_t)
|
||||
|
||||
if (a->second_part < b->second_part)
|
||||
return -1;
|
||||
if (a->second_part > b->second_part)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -14831,7 +14831,7 @@ void Dblqh::srLogLimits(Signal* signal)
|
||||
while(true) {
|
||||
ndbrequire(tmbyte < clogFileSize);
|
||||
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();
|
||||
/* --------------------------------------------------------------------
|
||||
* WE ARE STEPPING BACKWARDS FROM MBYTE TO MBYTE. THIS IS THE FIRST
|
||||
|
Reference in New Issue
Block a user