mirror of
				https://github.com/MariaDB/server.git
				synced 2025-11-03 14:33:32 +03:00 
			
		
		
		
	Merge bk-internal.mysql.com:/data0/bk/mysql-5.1
into bk-internal.mysql.com:/data0/bk/mysql-5.1-opt
This commit is contained in:
		@@ -474,6 +474,7 @@ CREATE TABLE t4 (a DATE);
 | 
			
		||||
INSERT INTO t4 VALUES ('1972-02-06'), ('1972-07-29');
 | 
			
		||||
SELECT * FROM t4 WHERE a IN ('1972-02-06','19772-07-29');
 | 
			
		||||
a
 | 
			
		||||
1972-02-06
 | 
			
		||||
Warnings:
 | 
			
		||||
Warning	1292	Incorrect date value: '19772-07-29' for column 'a' at row 1
 | 
			
		||||
DROP TABLE t1,t2,t3,t4;
 | 
			
		||||
 
 | 
			
		||||
@@ -336,3 +336,25 @@ id	f1
 | 
			
		||||
0	test1
 | 
			
		||||
DROP TABLE t1;
 | 
			
		||||
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
 | 
			
		||||
2
 | 
			
		||||
SET @@SQL_MODE=@OLD_SQL_MODE;
 | 
			
		||||
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);
 | 
			
		||||
INSERT INTO t1 VALUES (1);
 | 
			
		||||
SET NAMES latin1;
 | 
			
		||||
 
 | 
			
		||||
@@ -264,6 +264,52 @@ f2
 | 
			
		||||
SELECT 1 from dual where NOW() BETWEEN CURRENT_DATE() - INTERVAL 1 DAY AND CURRENT_DATE();
 | 
			
		||||
1
 | 
			
		||||
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');
 | 
			
		||||
least(cast('01-01-01' as date), '01-01-02')
 | 
			
		||||
2001-01-01
 | 
			
		||||
@@ -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;
 | 
			
		||||
least(cast('01-01-01' as datetime), '01-01-02') + 0
 | 
			
		||||
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 ;
 | 
			
		||||
CREATE PROCEDURE test27759()
 | 
			
		||||
BEGIN
 | 
			
		||||
 
 | 
			
		||||
@@ -247,3 +247,20 @@ REPLACE INTO t1 VALUES (0,"test1",null);
 | 
			
		||||
SELECT id, f1 FROM t1;
 | 
			
		||||
DROP TABLE t1;
 | 
			
		||||
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;
 | 
			
		||||
--exec rm $MYSQLTEST_VARDIR/tmp/t1
 | 
			
		||||
SET @@SQL_MODE=@OLD_SQL_MODE;
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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();
 | 
			
		||||
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.
 | 
			
		||||
#
 | 
			
		||||
@@ -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 greatest(cast('01-01-01' as date), '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
 | 
			
		||||
DROP PROCEDURE IF EXISTS test27759 ;
 | 
			
		||||
--enable_warnings
 | 
			
		||||
 
 | 
			
		||||
@@ -2830,7 +2830,6 @@ in_row::in_row(uint elements, Item * item)
 | 
			
		||||
  base= (char*) new cmp_item_row[count= elements];
 | 
			
		||||
  size= sizeof(cmp_item_row);
 | 
			
		||||
  compare= (qsort2_cmp) cmp_row;
 | 
			
		||||
  tmp.store_value(item);
 | 
			
		||||
  /*
 | 
			
		||||
    We need to reset these as otherwise we will call sort() with
 | 
			
		||||
    uninitialized (even if not used) elements
 | 
			
		||||
@@ -2882,6 +2881,27 @@ byte *in_longlong::get_value(Item *item)
 | 
			
		||||
  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_vector(elements,sizeof(double),(qsort2_cmp) cmp_double, 0)
 | 
			
		||||
{}
 | 
			
		||||
@@ -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)
 | 
			
		||||
{
 | 
			
		||||
  DBUG_ENTER("cmp_item_row::store_value");
 | 
			
		||||
  n= item->cols();
 | 
			
		||||
  if (!comparators)
 | 
			
		||||
    comparators= (cmp_item **) current_thd->calloc(sizeof(cmp_item *)*n);
 | 
			
		||||
  alloc_comparators();
 | 
			
		||||
  if (comparators)
 | 
			
		||||
  {
 | 
			
		||||
    item->bring_value();
 | 
			
		||||
@@ -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()
 | 
			
		||||
{
 | 
			
		||||
  Item **arg,**arg_end;
 | 
			
		||||
@@ -3178,6 +3234,10 @@ void Item_func_in::fix_length_and_dec()
 | 
			
		||||
  Item **arg, **arg_end;
 | 
			
		||||
  bool const_itm= 1;
 | 
			
		||||
  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 type_cnt= 0, i;
 | 
			
		||||
  Item_result cmp_type= STRING_RESULT;
 | 
			
		||||
@@ -3209,16 +3269,103 @@ void Item_func_in::fix_length_and_dec()
 | 
			
		||||
      return;
 | 
			
		||||
    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 =>
 | 
			
		||||
    they can't be processed as static
 | 
			
		||||
  */
 | 
			
		||||
  if (type_cnt == 1 && const_itm && !nulls_in_row())
 | 
			
		||||
  {
 | 
			
		||||
    if (compare_as_datetime)
 | 
			
		||||
      array= new in_datetime(date_arg, arg_count - 1);
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
      /*
 | 
			
		||||
      IN must compare INT/DATE/DATETIME/TIMESTAMP columns and constants
 | 
			
		||||
      as int values (the same way as equality does).
 | 
			
		||||
        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.
 | 
			
		||||
@@ -3243,17 +3390,22 @@ void Item_func_in::fix_length_and_dec()
 | 
			
		||||
      }
 | 
			
		||||
      switch (cmp_type) {
 | 
			
		||||
      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);
 | 
			
		||||
        break;
 | 
			
		||||
      case INT_RESULT:
 | 
			
		||||
      array= new in_longlong(arg_count - 1);
 | 
			
		||||
        array= new in_longlong(arg_count-1);
 | 
			
		||||
        break;
 | 
			
		||||
      case REAL_RESULT:
 | 
			
		||||
      array= new in_double(arg_count - 1);
 | 
			
		||||
        array= new in_double(arg_count-1);
 | 
			
		||||
        break;
 | 
			
		||||
      case ROW_RESULT:
 | 
			
		||||
      array= new in_row(arg_count - 1, args[0]);
 | 
			
		||||
        /*
 | 
			
		||||
          The row comparator was created at the beginning but only DATETIME
 | 
			
		||||
          items comparators were initialized. Call store_value() to setup
 | 
			
		||||
          others.
 | 
			
		||||
        */
 | 
			
		||||
        ((in_row*)array)->tmp.store_value(args[0]);
 | 
			
		||||
        break;
 | 
			
		||||
      case DECIMAL_RESULT:
 | 
			
		||||
        array= new in_decimal(arg_count - 1);
 | 
			
		||||
@@ -3262,6 +3414,7 @@ void Item_func_in::fix_length_and_dec()
 | 
			
		||||
        DBUG_ASSERT(0);
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (array && !(thd->is_fatal_error))		// If not EOM
 | 
			
		||||
    {
 | 
			
		||||
      uint j=0;
 | 
			
		||||
@@ -3278,21 +3431,27 @@ void Item_func_in::fix_length_and_dec()
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    if (compare_as_datetime)
 | 
			
		||||
      cmp_items[STRING_RESULT]= new cmp_item_datetime(date_arg);
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
      for (i= 0; i <= (uint) DECIMAL_RESULT; i++)
 | 
			
		||||
      {
 | 
			
		||||
        if (found_types & (1 << i) && !cmp_items[i])
 | 
			
		||||
        {
 | 
			
		||||
          if ((Item_result)i == STRING_RESULT &&
 | 
			
		||||
            agg_arg_charsets(cmp_collation, args, arg_count, MY_COLL_CMP_CONV, 1))
 | 
			
		||||
              agg_arg_charsets(cmp_collation, args, arg_count,
 | 
			
		||||
                               MY_COLL_CMP_CONV, 1))
 | 
			
		||||
            return;
 | 
			
		||||
        if (!(cmp_items[i]=
 | 
			
		||||
          if (!cmp_items[i] && !(cmp_items[i]=
 | 
			
		||||
              cmp_item::get_comparator((Item_result)i,
 | 
			
		||||
                                       cmp_collation.collation)))
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  max_length= 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -798,6 +798,7 @@ public:
 | 
			
		||||
 | 
			
		||||
class in_longlong :public in_vector
 | 
			
		||||
{
 | 
			
		||||
protected:
 | 
			
		||||
  /*
 | 
			
		||||
    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 
 | 
			
		||||
@@ -832,6 +833,30 @@ public:
 | 
			
		||||
  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
 | 
			
		||||
{
 | 
			
		||||
  double tmp;
 | 
			
		||||
@@ -964,6 +989,30 @@ public:
 | 
			
		||||
  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
 | 
			
		||||
{
 | 
			
		||||
  double value;
 | 
			
		||||
@@ -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
 | 
			
		||||
   be changed)
 | 
			
		||||
@@ -1163,7 +1186,7 @@ public:
 | 
			
		||||
  */
 | 
			
		||||
  bool arg_types_compatible;
 | 
			
		||||
  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;
 | 
			
		||||
 | 
			
		||||
  Item_func_in(List<Item> &list)
 | 
			
		||||
@@ -1184,7 +1207,7 @@ public:
 | 
			
		||||
    Item_int_func::cleanup();
 | 
			
		||||
    delete array;
 | 
			
		||||
    array= 0;
 | 
			
		||||
    for (i= 0; i <= (uint)DECIMAL_RESULT; i++)
 | 
			
		||||
    for (i= 0; i <= (uint)DECIMAL_RESULT + 1; i++)
 | 
			
		||||
    {
 | 
			
		||||
      delete cmp_items[i];
 | 
			
		||||
      cmp_items[i]= 0;
 | 
			
		||||
@@ -1202,6 +1225,35 @@ public:
 | 
			
		||||
  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 */
 | 
			
		||||
 | 
			
		||||
class Item_func_isnull :public Item_bool_func
 | 
			
		||||
 
 | 
			
		||||
@@ -2344,7 +2344,7 @@ double Item_func_min_max::val_real()
 | 
			
		||||
  double value=0.0;
 | 
			
		||||
  if (compare_as_dates)
 | 
			
		||||
  {
 | 
			
		||||
    ulonglong result;
 | 
			
		||||
    ulonglong result= 0;
 | 
			
		||||
    (void)cmp_datetimes(&result);
 | 
			
		||||
    return (double)result;
 | 
			
		||||
  }
 | 
			
		||||
@@ -2371,7 +2371,7 @@ longlong Item_func_min_max::val_int()
 | 
			
		||||
  longlong value=0;
 | 
			
		||||
  if (compare_as_dates)
 | 
			
		||||
  {
 | 
			
		||||
    ulonglong result;
 | 
			
		||||
    ulonglong result= 0;
 | 
			
		||||
    (void)cmp_datetimes(&result);
 | 
			
		||||
    return (longlong)result;
 | 
			
		||||
  }
 | 
			
		||||
@@ -2400,7 +2400,7 @@ my_decimal *Item_func_min_max::val_decimal(my_decimal *dec)
 | 
			
		||||
 | 
			
		||||
  if (compare_as_dates)
 | 
			
		||||
  {
 | 
			
		||||
    ulonglong value;
 | 
			
		||||
    ulonglong value= 0;
 | 
			
		||||
    (void)cmp_datetimes(&value);
 | 
			
		||||
    ulonglong2decimal(value, dec);
 | 
			
		||||
    return dec;
 | 
			
		||||
 
 | 
			
		||||
@@ -724,6 +724,7 @@ public:
 | 
			
		||||
  my_decimal *val_decimal(my_decimal *);
 | 
			
		||||
  void fix_length_and_dec();
 | 
			
		||||
  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;}
 | 
			
		||||
  uint cmp_datetimes(ulonglong *value);
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -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, 
 | 
			
		||||
                            ER_WARN_TOO_FEW_RECORDS, 
 | 
			
		||||
                            ER(ER_WARN_TOO_FEW_RECORDS), thd->row_count);
 | 
			
		||||
        if (!field->maybe_null() && field->type() == FIELD_TYPE_TIMESTAMP)
 | 
			
		||||
            ((Field_timestamp*) field)->set_time();
 | 
			
		||||
      }
 | 
			
		||||
      else
 | 
			
		||||
      {
 | 
			
		||||
@@ -782,6 +784,8 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
 | 
			
		||||
                     thd->row_count);
 | 
			
		||||
            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.
 | 
			
		||||
            But how about intention to always have the same number
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user