Commit b32473a3 authored by unknown's avatar unknown

Merge bk-internal.mysql.com:/data0/bk/mysql-5.1

into  bk-internal.mysql.com:/data0/bk/mysql-5.1-opt


sql/handler.cc:
  Auto merged
sql/item_func.cc:
  Auto merged
sql/sql_class.h:
  Auto merged
parents 3a065ffa 80a36692
...@@ -474,6 +474,7 @@ CREATE TABLE t4 (a DATE); ...@@ -474,6 +474,7 @@ CREATE TABLE t4 (a DATE);
INSERT INTO t4 VALUES ('1972-02-06'), ('1972-07-29'); INSERT INTO t4 VALUES ('1972-02-06'), ('1972-07-29');
SELECT * FROM t4 WHERE a IN ('1972-02-06','19772-07-29'); SELECT * FROM t4 WHERE a IN ('1972-02-06','19772-07-29');
a a
1972-02-06
Warnings: Warnings:
Warning 1292 Incorrect date value: '19772-07-29' for column 'a' at row 1 Warning 1292 Incorrect date value: '19772-07-29' for column 'a' at row 1
DROP TABLE t1,t2,t3,t4; DROP TABLE t1,t2,t3,t4;
......
...@@ -336,3 +336,25 @@ id f1 ...@@ -336,3 +336,25 @@ id f1
0 test1 0 test1
DROP TABLE t1; DROP TABLE t1;
SET SQL_MODE=''; SET SQL_MODE='';
CREATE TABLE t1 (
id INT AUTO_INCREMENT PRIMARY KEY,
c1 CHAR(1) UNIQUE KEY,
cnt INT DEFAULT 1
);
INSERT INTO t1 (c1) VALUES ('A'), ('B'), ('C');
SELECT * FROM t1;
id c1 cnt
1 A 1
2 B 1
3 C 1
INSERT INTO t1 (c1) VALUES ('A'), ('X'), ('Y'), ('Z')
ON DUPLICATE KEY UPDATE cnt=cnt+1;
SELECT * FROM t1;
id c1 cnt
1 A 2
2 B 1
3 C 1
4 X 1
5 Y 1
6 Z 1
DROP TABLE t1;
...@@ -174,6 +174,25 @@ f2 ...@@ -174,6 +174,25 @@ f2
2 2
SET @@SQL_MODE=@OLD_SQL_MODE; SET @@SQL_MODE=@OLD_SQL_MODE;
drop table t1,t2; drop table t1,t2;
create table t1(f1 int, f2 timestamp not null default current_timestamp);
create table t2(f1 int);
insert into t2 values(1),(2);
Warnings:
Warning 1261 Row 1 doesn't contain data for all columns
Warning 1261 Row 2 doesn't contain data for all columns
select f1 from t1 where f2 <> '0000-00-00 00:00:00' order by f1;
f1
1
2
delete from t1;
Warnings:
Warning 1261 Row 1 doesn't contain data for all columns
Warning 1261 Row 2 doesn't contain data for all columns
select f1 from t1 where f2 <> '0000-00-00 00:00:00' order by f1;
f1
1
2
drop table t1,t2;
CREATE TABLE t1 (a int); CREATE TABLE t1 (a int);
INSERT INTO t1 VALUES (1); INSERT INTO t1 VALUES (1);
SET NAMES latin1; SET NAMES latin1;
......
...@@ -264,6 +264,52 @@ f2 ...@@ -264,6 +264,52 @@ f2
SELECT 1 from dual where NOW() BETWEEN CURRENT_DATE() - INTERVAL 1 DAY AND CURRENT_DATE(); SELECT 1 from dual where NOW() BETWEEN CURRENT_DATE() - INTERVAL 1 DAY AND CURRENT_DATE();
1 1
drop table t1; drop table t1;
create table t1 (f1 date);
insert into t1 values('01-01-01'),('01-01-02'),('01-01-03');
select * from t1 where f1 in ('01-01-01','2001-01-02','2001-01-03 00:00:00');
f1
2001-01-01
2001-01-02
2001-01-03
create table t2(f2 datetime);
insert into t2 values('01-01-01 00:00:00'),('01-02-03 12:34:56'),('02-04-06 11:22:33');
select * from t2 where f2 in ('01-01-01','01-02-03 12:34:56','01-02-03');
f2
2001-01-01 00:00:00
2001-02-03 12:34:56
select * from t1,t2 where '01-01-02' in (f1, cast(f2 as date));
f1 f2
2001-01-02 2001-01-01 00:00:00
2001-01-02 2001-02-03 12:34:56
2001-01-02 2002-04-06 11:22:33
select * from t1,t2 where '01-01-01' in (f1, '01-02-03');
f1 f2
2001-01-01 2001-01-01 00:00:00
2001-01-01 2001-02-03 12:34:56
2001-01-01 2002-04-06 11:22:33
select * from t1,t2 where if(1,'01-02-03 12:34:56','') in (f1, f2);
f1 f2
2001-01-01 2001-02-03 12:34:56
2001-01-02 2001-02-03 12:34:56
2001-01-03 2001-02-03 12:34:56
create table t3(f3 varchar(20));
insert into t3 select * from t2;
select * from t2,t3 where f2 in (f3,'03-04-05');
f2 f3
2001-01-01 00:00:00 2001-01-01 00:00:00
2001-02-03 12:34:56 2001-02-03 12:34:56
2002-04-06 11:22:33 2002-04-06 11:22:33
select f1,f2,f3 from t1,t2,t3 where (f1,'1') in ((f2,'1'),(f3,'1'));
f1 f2 f3
2001-01-01 2001-01-01 00:00:00 2001-01-01 00:00:00
2001-01-01 2001-02-03 12:34:56 2001-01-01 00:00:00
2001-01-01 2002-04-06 11:22:33 2001-01-01 00:00:00
2001-01-01 2001-01-01 00:00:00 2001-02-03 12:34:56
2001-01-01 2001-01-01 00:00:00 2002-04-06 11:22:33
select f1 from t1 where ('1',f1) in (('1','01-01-01'),('1','2001-1-1 0:0:0'),('1','02-02-02'));
f1
2001-01-01
drop table t1,t2,t3;
select least(cast('01-01-01' as date), '01-01-02'); select least(cast('01-01-01' as date), '01-01-02');
least(cast('01-01-01' as date), '01-01-02') least(cast('01-01-01' as date), '01-01-02')
2001-01-01 2001-01-01
...@@ -279,6 +325,12 @@ greatest(cast('01-01-01' as date), '01-01-02') + 0 ...@@ -279,6 +325,12 @@ greatest(cast('01-01-01' as date), '01-01-02') + 0
select least(cast('01-01-01' as datetime), '01-01-02') + 0; select least(cast('01-01-01' as datetime), '01-01-02') + 0;
least(cast('01-01-01' as datetime), '01-01-02') + 0 least(cast('01-01-01' as datetime), '01-01-02') + 0
20010101000000 20010101000000
select cast(least(cast('01-01-01' as datetime), '01-01-02') as signed);
cast(least(cast('01-01-01' as datetime), '01-01-02') as signed)
20010101000000
select cast(least(cast('01-01-01' as datetime), '01-01-02') as decimal(16,2));
cast(least(cast('01-01-01' as datetime), '01-01-02') as decimal(16,2))
20010101000000.00
DROP PROCEDURE IF EXISTS test27759 ; DROP PROCEDURE IF EXISTS test27759 ;
CREATE PROCEDURE test27759() CREATE PROCEDURE test27759()
BEGIN BEGIN
......
...@@ -247,3 +247,20 @@ REPLACE INTO t1 VALUES (0,"test1",null); ...@@ -247,3 +247,20 @@ REPLACE INTO t1 VALUES (0,"test1",null);
SELECT id, f1 FROM t1; SELECT id, f1 FROM t1;
DROP TABLE t1; DROP TABLE t1;
SET SQL_MODE=''; SET SQL_MODE='';
#
# Bug#27954: multi-row INSERT ... ON DUPLICATE with duplicated
# row at the first place into table with AUTO_INCREMENT and
# additional UNIQUE key.
#
CREATE TABLE t1 (
id INT AUTO_INCREMENT PRIMARY KEY,
c1 CHAR(1) UNIQUE KEY,
cnt INT DEFAULT 1
);
INSERT INTO t1 (c1) VALUES ('A'), ('B'), ('C');
SELECT * FROM t1;
INSERT INTO t1 (c1) VALUES ('A'), ('X'), ('Y'), ('Z')
ON DUPLICATE KEY UPDATE cnt=cnt+1;
SELECT * FROM t1;
DROP TABLE t1;
...@@ -156,6 +156,32 @@ select * from t2; ...@@ -156,6 +156,32 @@ select * from t2;
--exec rm $MYSQLTEST_VARDIR/tmp/t1 --exec rm $MYSQLTEST_VARDIR/tmp/t1
SET @@SQL_MODE=@OLD_SQL_MODE; SET @@SQL_MODE=@OLD_SQL_MODE;
drop table t1,t2; drop table t1,t2;
#
# Bug#27670: LOAD DATA does not set CURRENT_TIMESTAMP default value for a
# TIMESTAMP field when no value has been provided.
#
create table t1(f1 int, f2 timestamp not null default current_timestamp);
create table t2(f1 int);
insert into t2 values(1),(2);
disable_query_log;
eval select * into outfile '$MYSQLTEST_VARDIR/tmp/t2' from t2;
eval load data infile '$MYSQLTEST_VARDIR/tmp/t2' into table t1;
enable_query_log;
select f1 from t1 where f2 <> '0000-00-00 00:00:00' order by f1;
--exec rm $MYSQLTEST_VARDIR/tmp/t2
delete from t1;
disable_query_log;
eval SELECT * INTO OUTFILE '$MYSQLTEST_VARDIR/tmp/t2'
FIELDS TERMINATED BY '' OPTIONALLY ENCLOSED BY '' LINES TERMINATED BY '\r\n'
FROM t2;
eval load data infile '$MYSQLTEST_VARDIR/tmp/t2' into table t1
FIELDS TERMINATED BY '' OPTIONALLY ENCLOSED BY '' LINES TERMINATED BY '\r\n';
enable_query_log;
select f1 from t1 where f2 <> '0000-00-00 00:00:00' order by f1;
--exec rm $MYSQLTEST_VARDIR/tmp/t2
drop table t1,t2;
# End of 5.0 tests # End of 5.0 tests
......
...@@ -179,6 +179,25 @@ select f2 from t1 where DATE(f2) between "2001-4-15" AND "01-4-15"; ...@@ -179,6 +179,25 @@ select f2 from t1 where DATE(f2) between "2001-4-15" AND "01-4-15";
SELECT 1 from dual where NOW() BETWEEN CURRENT_DATE() - INTERVAL 1 DAY AND CURRENT_DATE(); SELECT 1 from dual where NOW() BETWEEN CURRENT_DATE() - INTERVAL 1 DAY AND CURRENT_DATE();
drop table t1; drop table t1;
#
# Bug#28133: Wrong DATE/DATETIME comparison in IN() function.
#
create table t1 (f1 date);
insert into t1 values('01-01-01'),('01-01-02'),('01-01-03');
select * from t1 where f1 in ('01-01-01','2001-01-02','2001-01-03 00:00:00');
create table t2(f2 datetime);
insert into t2 values('01-01-01 00:00:00'),('01-02-03 12:34:56'),('02-04-06 11:22:33');
select * from t2 where f2 in ('01-01-01','01-02-03 12:34:56','01-02-03');
select * from t1,t2 where '01-01-02' in (f1, cast(f2 as date));
select * from t1,t2 where '01-01-01' in (f1, '01-02-03');
select * from t1,t2 where if(1,'01-02-03 12:34:56','') in (f1, f2);
create table t3(f3 varchar(20));
insert into t3 select * from t2;
select * from t2,t3 where f2 in (f3,'03-04-05');
select f1,f2,f3 from t1,t2,t3 where (f1,'1') in ((f2,'1'),(f3,'1'));
select f1 from t1 where ('1',f1) in (('1','01-01-01'),('1','2001-1-1 0:0:0'),('1','02-02-02'));
drop table t1,t2,t3;
# #
# Bug#27759: Wrong DATE/DATETIME comparison in LEAST()/GREATEST() functions. # Bug#27759: Wrong DATE/DATETIME comparison in LEAST()/GREATEST() functions.
# #
...@@ -187,6 +206,8 @@ select greatest(cast('01-01-01' as date), '01-01-02'); ...@@ -187,6 +206,8 @@ select greatest(cast('01-01-01' as date), '01-01-02');
select least(cast('01-01-01' as date), '01-01-02') + 0; select least(cast('01-01-01' as date), '01-01-02') + 0;
select greatest(cast('01-01-01' as date), '01-01-02') + 0; select greatest(cast('01-01-01' as date), '01-01-02') + 0;
select least(cast('01-01-01' as datetime), '01-01-02') + 0; select least(cast('01-01-01' as datetime), '01-01-02') + 0;
select cast(least(cast('01-01-01' as datetime), '01-01-02') as signed);
select cast(least(cast('01-01-01' as datetime), '01-01-02') as decimal(16,2));
--disable_warnings --disable_warnings
DROP PROCEDURE IF EXISTS test27759 ; DROP PROCEDURE IF EXISTS test27759 ;
--enable_warnings --enable_warnings
......
...@@ -2830,7 +2830,6 @@ in_row::in_row(uint elements, Item * item) ...@@ -2830,7 +2830,6 @@ in_row::in_row(uint elements, Item * item)
base= (char*) new cmp_item_row[count= elements]; base= (char*) new cmp_item_row[count= elements];
size= sizeof(cmp_item_row); size= sizeof(cmp_item_row);
compare= (qsort2_cmp) cmp_row; compare= (qsort2_cmp) cmp_row;
tmp.store_value(item);
/* /*
We need to reset these as otherwise we will call sort() with We need to reset these as otherwise we will call sort() with
uninitialized (even if not used) elements uninitialized (even if not used) elements
...@@ -2882,6 +2881,27 @@ byte *in_longlong::get_value(Item *item) ...@@ -2882,6 +2881,27 @@ byte *in_longlong::get_value(Item *item)
return (byte*) &tmp; return (byte*) &tmp;
} }
void in_datetime::set(uint pos,Item *item)
{
Item **tmp= &item;
bool is_null;
struct packed_longlong *buff= &((packed_longlong*) base)[pos];
buff->val= get_datetime_value(thd, &tmp, 0, warn_item, &is_null);
buff->unsigned_flag= 1L;
}
byte *in_datetime::get_value(Item *item)
{
bool is_null;
Item **tmp_item= lval_cache ? &lval_cache : &item;
tmp.val= get_datetime_value(thd, &tmp_item, &lval_cache, warn_item, &is_null);
if (item->null_value)
return 0;
tmp.unsigned_flag= 1L;
return (byte*) &tmp;
}
in_double::in_double(uint elements) in_double::in_double(uint elements)
:in_vector(elements,sizeof(double),(qsort2_cmp) cmp_double, 0) :in_vector(elements,sizeof(double),(qsort2_cmp) cmp_double, 0)
{} {}
...@@ -2986,12 +3006,18 @@ cmp_item_row::~cmp_item_row() ...@@ -2986,12 +3006,18 @@ cmp_item_row::~cmp_item_row()
} }
void cmp_item_row::alloc_comparators()
{
if (!comparators)
comparators= (cmp_item **) current_thd->calloc(sizeof(cmp_item *)*n);
}
void cmp_item_row::store_value(Item *item) void cmp_item_row::store_value(Item *item)
{ {
DBUG_ENTER("cmp_item_row::store_value"); DBUG_ENTER("cmp_item_row::store_value");
n= item->cols(); n= item->cols();
if (!comparators) alloc_comparators();
comparators= (cmp_item **) current_thd->calloc(sizeof(cmp_item *)*n);
if (comparators) if (comparators)
{ {
item->bring_value(); item->bring_value();
...@@ -3103,6 +3129,36 @@ cmp_item* cmp_item_decimal::make_same() ...@@ -3103,6 +3129,36 @@ cmp_item* cmp_item_decimal::make_same()
} }
void cmp_item_datetime::store_value(Item *item)
{
bool is_null;
Item **tmp_item= lval_cache ? &lval_cache : &item;
value= get_datetime_value(thd, &tmp_item, &lval_cache, warn_item, &is_null);
}
int cmp_item_datetime::cmp(Item *arg)
{
bool is_null;
Item **tmp_item= &arg;
return value !=
get_datetime_value(thd, &tmp_item, 0, warn_item, &is_null);
}
int cmp_item_datetime::compare(cmp_item *ci)
{
cmp_item_datetime *l_cmp= (cmp_item_datetime *)ci;
return (value < l_cmp->value) ? -1 : ((value == l_cmp->value) ? 0 : 1);
}
cmp_item *cmp_item_datetime::make_same()
{
return new cmp_item_datetime(warn_item);
}
bool Item_func_in::nulls_in_row() bool Item_func_in::nulls_in_row()
{ {
Item **arg,**arg_end; Item **arg,**arg_end;
...@@ -3178,6 +3234,10 @@ void Item_func_in::fix_length_and_dec() ...@@ -3178,6 +3234,10 @@ void Item_func_in::fix_length_and_dec()
Item **arg, **arg_end; Item **arg, **arg_end;
bool const_itm= 1; bool const_itm= 1;
THD *thd= current_thd; THD *thd= current_thd;
bool datetime_found= FALSE;
/* TRUE <=> arguments values will be compared as DATETIMEs. */
bool compare_as_datetime= FALSE;
Item *date_arg= 0;
uint found_types= 0; uint found_types= 0;
uint type_cnt= 0, i; uint type_cnt= 0, i;
Item_result cmp_type= STRING_RESULT; Item_result cmp_type= STRING_RESULT;
...@@ -3209,58 +3269,151 @@ void Item_func_in::fix_length_and_dec() ...@@ -3209,58 +3269,151 @@ void Item_func_in::fix_length_and_dec()
return; return;
arg_types_compatible= TRUE; arg_types_compatible= TRUE;
} }
if (type_cnt == 1)
{
/*
When comparing rows create the row comparator object beforehand to ease
the DATETIME comparison detection procedure.
*/
if (cmp_type == ROW_RESULT)
{
cmp_item_row *cmp= 0;
if (const_itm && !nulls_in_row())
{
array= new in_row(arg_count-1, 0);
cmp= &((in_row*)array)->tmp;
}
else
{
if (!(cmp= new cmp_item_row))
return;
cmp_items[ROW_RESULT]= cmp;
}
cmp->n= args[0]->cols();
cmp->alloc_comparators();
}
/* All DATE/DATETIME fields/functions has the STRING result type. */
if (cmp_type == STRING_RESULT || cmp_type == ROW_RESULT)
{
uint col, cols= args[0]->cols();
for (col= 0; col < cols; col++)
{
bool skip_column= FALSE;
/*
Check that all items to be compared has the STRING result type and at
least one of them is a DATE/DATETIME item.
*/
for (arg= args, arg_end= args + arg_count; arg != arg_end ; arg++)
{
Item *itm= ((cmp_type == STRING_RESULT) ? arg[0] :
arg[0]->element_index(col));
if (itm->result_type() != STRING_RESULT)
{
skip_column= TRUE;
break;
}
else if (itm->is_datetime())
{
datetime_found= TRUE;
/*
Internally all DATE/DATETIME values are converted to the DATETIME
type. So try to find a DATETIME item to issue correct warnings.
*/
if (!date_arg)
date_arg= itm;
else if (itm->field_type() == MYSQL_TYPE_DATETIME)
{
date_arg= itm;
/* All arguments are already checked to have the STRING result. */
if (cmp_type == STRING_RESULT)
break;
}
}
}
if (skip_column)
continue;
if (datetime_found)
{
if (cmp_type == ROW_RESULT)
{
cmp_item **cmp= 0;
if (array)
cmp= ((in_row*)array)->tmp.comparators + col;
else
cmp= ((cmp_item_row*)cmp_items[ROW_RESULT])->comparators + col;
*cmp= new cmp_item_datetime(date_arg);
/* Reset variables for the next column. */
date_arg= 0;
datetime_found= FALSE;
}
else
compare_as_datetime= TRUE;
}
}
}
}
/* /*
Row item with NULLs inside can return NULL or FALSE => Row item with NULLs inside can return NULL or FALSE =>
they can't be processed as static they can't be processed as static
*/ */
if (type_cnt == 1 && const_itm && !nulls_in_row()) if (type_cnt == 1 && const_itm && !nulls_in_row())
{ {
/* if (compare_as_datetime)
IN must compare INT/DATE/DATETIME/TIMESTAMP columns and constants array= new in_datetime(date_arg, arg_count - 1);
as int values (the same way as equality does). else
So we must check here if the column on the left and all the constant
values on the right can be compared as integers and adjust the
comparison type accordingly.
*/
if (args[0]->real_item()->type() == FIELD_ITEM &&
thd->lex->sql_command != SQLCOM_CREATE_VIEW &&
thd->lex->sql_command != SQLCOM_SHOW_CREATE &&
cmp_type != INT_RESULT)
{ {
Field *field= ((Item_field*) (args[0]->real_item()))->field; /*
if (field->can_be_compared_as_longlong()) IN must compare INT columns and constants as int values (the same
way as equality does).
So we must check here if the column on the left and all the constant
values on the right can be compared as integers and adjust the
comparison type accordingly.
*/
if (args[0]->real_item()->type() == FIELD_ITEM &&
thd->lex->sql_command != SQLCOM_CREATE_VIEW &&
thd->lex->sql_command != SQLCOM_SHOW_CREATE &&
cmp_type != INT_RESULT)
{ {
bool all_converted= TRUE; Field *field= ((Item_field*) (args[0]->real_item()))->field;
for (arg=args+1, arg_end=args+arg_count; arg != arg_end ; arg++) if (field->can_be_compared_as_longlong())
{ {
if (!convert_constant_item (thd, field, &arg[0])) bool all_converted= TRUE;
all_converted= FALSE; for (arg=args+1, arg_end=args+arg_count; arg != arg_end ; arg++)
{
if (!convert_constant_item (thd, field, &arg[0]))
all_converted= FALSE;
}
if (all_converted)
cmp_type= INT_RESULT;
} }
if (all_converted)
cmp_type= INT_RESULT;
} }
} switch (cmp_type) {
switch (cmp_type) { case STRING_RESULT:
case STRING_RESULT: array=new in_string(arg_count-1,(qsort2_cmp) srtcmp_in,
array=new in_string(arg_count - 1,(qsort2_cmp) srtcmp_in, cmp_collation.collation);
cmp_collation.collation); break;
break; case INT_RESULT:
case INT_RESULT: array= new in_longlong(arg_count-1);
array= new in_longlong(arg_count - 1); break;
break; case REAL_RESULT:
case REAL_RESULT: array= new in_double(arg_count-1);
array= new in_double(arg_count - 1); break;
break; case ROW_RESULT:
case ROW_RESULT: /*
array= new in_row(arg_count - 1, args[0]); The row comparator was created at the beginning but only DATETIME
break; items comparators were initialized. Call store_value() to setup
case DECIMAL_RESULT: others.
array= new in_decimal(arg_count - 1); */
break; ((in_row*)array)->tmp.store_value(args[0]);
default: break;
DBUG_ASSERT(0); case DECIMAL_RESULT:
return; array= new in_decimal(arg_count - 1);
break;
default:
DBUG_ASSERT(0);
return;
}
} }
if (array && !(thd->is_fatal_error)) // If not EOM if (array && !(thd->is_fatal_error)) // If not EOM
{ {
...@@ -3279,17 +3432,23 @@ void Item_func_in::fix_length_and_dec() ...@@ -3279,17 +3432,23 @@ void Item_func_in::fix_length_and_dec()
} }
else else
{ {
for (i= 0; i <= (uint) DECIMAL_RESULT; i++) if (compare_as_datetime)
cmp_items[STRING_RESULT]= new cmp_item_datetime(date_arg);
else
{ {
if (found_types & (1 << i) && !cmp_items[i]) for (i= 0; i <= (uint) DECIMAL_RESULT; i++)
{ {
if ((Item_result)i == STRING_RESULT && if (found_types & (1 << i) && !cmp_items[i])
agg_arg_charsets(cmp_collation, args, arg_count, MY_COLL_CMP_CONV, 1)) {
return; if ((Item_result)i == STRING_RESULT &&
if (!(cmp_items[i]= agg_arg_charsets(cmp_collation, args, arg_count,
cmp_item::get_comparator((Item_result)i, MY_COLL_CMP_CONV, 1))
cmp_collation.collation))) return;
return; if (!cmp_items[i] && !(cmp_items[i]=
cmp_item::get_comparator((Item_result)i,
cmp_collation.collation)))
return;
}
} }
} }
} }
......
...@@ -798,6 +798,7 @@ public: ...@@ -798,6 +798,7 @@ public:
class in_longlong :public in_vector class in_longlong :public in_vector
{ {
protected:
/* /*
Here we declare a temporary variable (tmp) of the same type as the Here we declare a temporary variable (tmp) of the same type as the
elements of this vector. tmp is used in finding if a given value is in elements of this vector. tmp is used in finding if a given value is in
...@@ -832,6 +833,30 @@ public: ...@@ -832,6 +833,30 @@ public:
friend int cmp_longlong(void *cmp_arg, packed_longlong *a,packed_longlong *b); friend int cmp_longlong(void *cmp_arg, packed_longlong *a,packed_longlong *b);
}; };
/*
Class to represent a vector of constant DATE/DATETIME values.
Values are obtained with help of the get_datetime_value() function.
If the left item is a constant one then its value is cached in the
lval_cache variable.
*/
class in_datetime :public in_longlong
{
public:
THD *thd;
/* An item used to issue warnings. */
Item *warn_item;
/* Cache for the left item. */
Item *lval_cache;
in_datetime(Item *warn_item_arg, uint elements)
:in_longlong(elements), thd(current_thd), warn_item(warn_item_arg),
lval_cache(0) {};
void set(uint pos,Item *item);
byte *get_value(Item *item);
friend int cmp_longlong(void *cmp_arg, packed_longlong *a,packed_longlong *b);
};
class in_double :public in_vector class in_double :public in_vector
{ {
double tmp; double tmp;
...@@ -964,6 +989,30 @@ public: ...@@ -964,6 +989,30 @@ public:
cmp_item *make_same(); cmp_item *make_same();
}; };
/*
Compare items in the DATETIME context.
Values are obtained with help of the get_datetime_value() function.
If the left item is a constant one then its value is cached in the
lval_cache variable.
*/
class cmp_item_datetime :public cmp_item
{
ulonglong value;
public:
THD *thd;
/* Item used for issuing warnings. */
Item *warn_item;
/* Cache for the left item. */
Item *lval_cache;
cmp_item_datetime(Item *warn_item_arg)
:thd(current_thd), warn_item(warn_item_arg), lval_cache(0) {}
void store_value(Item *item);
int cmp(Item *arg);
int compare(cmp_item *ci);
cmp_item *make_same();
};
class cmp_item_real :public cmp_item class cmp_item_real :public cmp_item
{ {
double value; double value;
...@@ -998,32 +1047,6 @@ public: ...@@ -998,32 +1047,6 @@ public:
}; };
class cmp_item_row :public cmp_item
{
cmp_item **comparators;
uint n;
public:
cmp_item_row(): comparators(0), n(0) {}
~cmp_item_row();
void store_value(Item *item);
int cmp(Item *arg);
int compare(cmp_item *arg);
cmp_item *make_same();
void store_value_by_template(cmp_item *tmpl, Item *);
};
class in_row :public in_vector
{
cmp_item_row tmp;
public:
in_row(uint elements, Item *);
~in_row();
void set(uint pos,Item *item);
byte *get_value(Item *item);
Item_result result_type() { return ROW_RESULT; }
};
/* /*
cmp_item for optimized IN with row (right part string, which never cmp_item for optimized IN with row (right part string, which never
be changed) be changed)
...@@ -1163,7 +1186,7 @@ public: ...@@ -1163,7 +1186,7 @@ public:
*/ */
bool arg_types_compatible; bool arg_types_compatible;
Item_result left_result_type; Item_result left_result_type;
cmp_item *cmp_items[5]; /* One cmp_item for each result type */ cmp_item *cmp_items[6]; /* One cmp_item for each result type */
DTCollation cmp_collation; DTCollation cmp_collation;
Item_func_in(List<Item> &list) Item_func_in(List<Item> &list)
...@@ -1184,7 +1207,7 @@ public: ...@@ -1184,7 +1207,7 @@ public:
Item_int_func::cleanup(); Item_int_func::cleanup();
delete array; delete array;
array= 0; array= 0;
for (i= 0; i <= (uint)DECIMAL_RESULT; i++) for (i= 0; i <= (uint)DECIMAL_RESULT + 1; i++)
{ {
delete cmp_items[i]; delete cmp_items[i];
cmp_items[i]= 0; cmp_items[i]= 0;
...@@ -1202,6 +1225,35 @@ public: ...@@ -1202,6 +1225,35 @@ public:
bool check_partition_func_processor(byte *int_arg) {return FALSE;} bool check_partition_func_processor(byte *int_arg) {return FALSE;}
}; };
class cmp_item_row :public cmp_item
{
cmp_item **comparators;
uint n;
public:
cmp_item_row(): comparators(0), n(0) {}
~cmp_item_row();
void store_value(Item *item);
inline void alloc_comparators();
int cmp(Item *arg);
int compare(cmp_item *arg);
cmp_item *make_same();
void store_value_by_template(cmp_item *tmpl, Item *);
friend void Item_func_in::fix_length_and_dec();
};
class in_row :public in_vector
{
cmp_item_row tmp;
public:
in_row(uint elements, Item *);
~in_row();
void set(uint pos,Item *item);
byte *get_value(Item *item);
friend void Item_func_in::fix_length_and_dec();
Item_result result_type() { return ROW_RESULT; };
};
/* Functions used by where clause */ /* Functions used by where clause */
class Item_func_isnull :public Item_bool_func class Item_func_isnull :public Item_bool_func
......
...@@ -2344,7 +2344,7 @@ double Item_func_min_max::val_real() ...@@ -2344,7 +2344,7 @@ double Item_func_min_max::val_real()
double value=0.0; double value=0.0;
if (compare_as_dates) if (compare_as_dates)
{ {
ulonglong result; ulonglong result= 0;
(void)cmp_datetimes(&result); (void)cmp_datetimes(&result);
return (double)result; return (double)result;
} }
...@@ -2371,7 +2371,7 @@ longlong Item_func_min_max::val_int() ...@@ -2371,7 +2371,7 @@ longlong Item_func_min_max::val_int()
longlong value=0; longlong value=0;
if (compare_as_dates) if (compare_as_dates)
{ {
ulonglong result; ulonglong result= 0;
(void)cmp_datetimes(&result); (void)cmp_datetimes(&result);
return (longlong)result; return (longlong)result;
} }
...@@ -2400,7 +2400,7 @@ my_decimal *Item_func_min_max::val_decimal(my_decimal *dec) ...@@ -2400,7 +2400,7 @@ my_decimal *Item_func_min_max::val_decimal(my_decimal *dec)
if (compare_as_dates) if (compare_as_dates)
{ {
ulonglong value; ulonglong value= 0;
(void)cmp_datetimes(&value); (void)cmp_datetimes(&value);
ulonglong2decimal(value, dec); ulonglong2decimal(value, dec);
return dec; return dec;
......
...@@ -724,6 +724,7 @@ public: ...@@ -724,6 +724,7 @@ public:
my_decimal *val_decimal(my_decimal *); my_decimal *val_decimal(my_decimal *);
void fix_length_and_dec(); void fix_length_and_dec();
enum Item_result result_type () const { return cmp_type; } enum Item_result result_type () const { return cmp_type; }
bool result_as_longlong() { return compare_as_dates; };
bool check_partition_func_processor(byte *int_arg) {return FALSE;} bool check_partition_func_processor(byte *int_arg) {return FALSE;}
uint cmp_datetimes(ulonglong *value); uint cmp_datetimes(ulonglong *value);
}; };
......
...@@ -605,6 +605,8 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, ...@@ -605,6 +605,8 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_TOO_FEW_RECORDS, ER_WARN_TOO_FEW_RECORDS,
ER(ER_WARN_TOO_FEW_RECORDS), thd->row_count); ER(ER_WARN_TOO_FEW_RECORDS), thd->row_count);
if (!field->maybe_null() && field->type() == FIELD_TYPE_TIMESTAMP)
((Field_timestamp*) field)->set_time();
} }
else else
{ {
...@@ -782,6 +784,8 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, ...@@ -782,6 +784,8 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
thd->row_count); thd->row_count);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
if (!field->maybe_null() && field->type() == FIELD_TYPE_TIMESTAMP)
((Field_timestamp*) field)->set_time();
/* /*
QQ: We probably should not throw warning for each field. QQ: We probably should not throw warning for each field.
But how about intention to always have the same number But how about intention to always have the same number
......
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