Commit 21be389b authored by unknown's avatar unknown
Browse files

Merge rurik.mysql.com:/home/igor/mysql-5.0-opt

into  rurik.mysql.com:/home/igor/dev-opt/mysql-5.0-opt-bug21698


sql/sql_select.cc:
  Auto merged
parents 3a8cdfc3 87166702
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -1113,4 +1113,39 @@ conv("18383815659218730760",10,10) + 0
select "18383815659218730760" + 0;
"18383815659218730760" + 0
1.8383815659219e+19
CREATE TABLE t1 (code varchar(10));
INSERT INTO t1 VALUES ('a12'), ('A12'), ('a13');
SELECT ASCII(code), code FROM t1 WHERE code='A12';
ASCII(code)	code
97	a12
65	A12
SELECT ASCII(code), code FROM t1 WHERE code='A12' AND ASCII(code)=65;
ASCII(code)	code
65	A12
INSERT INTO t1 VALUES ('a12 '), ('A12  ');
SELECT LENGTH(code), code FROM t1 WHERE code='A12';
LENGTH(code)	code
3	a12
3	A12
4	a12 
5	A12  
SELECT LENGTH(code), code FROM t1 WHERE code='A12' AND LENGTH(code)=5;
LENGTH(code)	code
5	A12  
ALTER TABLE t1 ADD INDEX (code);
CREATE TABLE t2 (id varchar(10) PRIMARY KEY);
INSERT INTO t2 VALUES ('a11'), ('a12'), ('a13'), ('a14');
SELECT * FROM t1 INNER JOIN t2 ON t1.code=t2.id 
WHERE t2.id='a12' AND (code < 'a00' OR LENGTH(code)=5);
code	id
A12  	a12
EXPLAIN EXTENDED 
SELECT * FROM t1 INNER JOIN t2 ON code=id 
WHERE id='a12' AND (code < 'a00' OR LENGTH(code)=5);
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	ref	code	code	13	const	3	Using where; Using index
1	SIMPLE	t2	ref	PRIMARY	PRIMARY	12	const	1	Using where; Using index
Warnings:
Note	1003	select `test`.`t1`.`code` AS `code`,`test`.`t2`.`id` AS `id` from `test`.`t1` join `test`.`t2` where ((`test`.`t1`.`code` = _latin1'a12') and (`test`.`t2`.`id` = _latin1'a12') and (length(`test`.`t1`.`code`) = 5))
DROP TABLE t1,t2;
End of 5.0 tests
+1 −1
Original line number Diff line number Diff line
@@ -354,7 +354,7 @@ t3 1 a 2 b NULL 13 NULL NULL HASH
explain select * from t1 ignore key(btree_idx), t3 where t1.name='matt' and t3.a = concat('',t1.name) and t3.b=t1.name;
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	ref	heap_idx	heap_idx	22	const	7	Using where
1	SIMPLE	t3	ref	a	a	44	const,const	7	Using where
1	SIMPLE	t3	ref	a	a	44	func,const	7	Using where
drop table t1, t2, t3;
create temporary table t1 ( a int, index (a) ) engine=memory;
insert into t1 values (1),(2),(3),(4),(5);
+27 −0
Original line number Diff line number Diff line
@@ -753,4 +753,31 @@ select cast(rtrim(ltrim(' 20.06 ')) as decimal(19,2));
select conv("18383815659218730760",10,10) + 0;
select "18383815659218730760" + 0;

#
# Bug #21698: substitution of a string field for a constant under a function 
#

CREATE TABLE t1 (code varchar(10));
INSERT INTO t1 VALUES ('a12'), ('A12'), ('a13');

SELECT ASCII(code), code FROM t1 WHERE code='A12';
SELECT ASCII(code), code FROM t1 WHERE code='A12' AND ASCII(code)=65;

INSERT INTO t1 VALUES ('a12 '), ('A12  ');

SELECT LENGTH(code), code FROM t1 WHERE code='A12';
SELECT LENGTH(code), code FROM t1 WHERE code='A12' AND LENGTH(code)=5;

ALTER TABLE t1 ADD INDEX (code);
CREATE TABLE t2 (id varchar(10) PRIMARY KEY);
INSERT INTO t2 VALUES ('a11'), ('a12'), ('a13'), ('a14');

SELECT * FROM t1 INNER JOIN t2 ON t1.code=t2.id 
  WHERE t2.id='a12' AND (code < 'a00' OR LENGTH(code)=5);
EXPLAIN EXTENDED 
SELECT * FROM t1 INNER JOIN t2 ON code=id 
  WHERE id='a12' AND (code < 'a00' OR LENGTH(code)=5);

DROP TABLE t1,t2;

--echo End of 5.0 tests
+38 −3
Original line number Diff line number Diff line
@@ -3745,6 +3745,41 @@ Item_equal *Item_field::find_item_equal(COND_EQUAL *cond_equal)
}


/*
  Check whether a field can be substituted by an equal item

  SYNOPSIS
    equal_fields_propagator()
      arg - *arg != NULL <-> the field is in the context where
            substitution for an equal item is valid
   
  DESCRIPTION
    The function checks whether a substitution of the field
    occurrence for an equal item is valid.

  NOTES
    The following statement is not always true:
    x=y => F(x)=F(x/y).
    This means substitution of an item for an equal item not always
    yields an equavalent condition.
    Here's an example:
      'a'='a '
      (LENGTH('a')=1) != (LENGTH('a ')=2)
    Such a substitution is surely valid if either the substituted
    field is not of a STRING type or if it is an argument of
    a comparison  predicate.  

  RETURN
    TRUE   substitution is valid
    FALSE  otherwise
*/

bool Item_field::subst_argument_checker(byte **arg)
{
  return (result_type() != STRING_RESULT) || (*arg);
}


/*
  Set a pointer to the multiple equality the field reference belongs to
  (if any)
@@ -3764,7 +3799,7 @@ Item_equal *Item_field::find_item_equal(COND_EQUAL *cond_equal)

  NOTES
    This function is supposed to be called as a callback parameter in calls
    of the transform method.  
    of the compile method.  

  RETURN VALUES
    pointer to the replacing constant item, if the field item was substituted 
+17 −1
Original line number Diff line number Diff line
@@ -411,6 +411,7 @@ class Settable_routine_parameter


typedef bool (Item::*Item_processor) (byte *arg);
typedef bool (Item::*Item_analyzer) (byte **argp);
typedef Item* (Item::*Item_transformer) (byte *arg);
typedef void (*Cond_traverser) (const Item *item, void *arg);

@@ -739,6 +740,14 @@ class Item {
    return (this->*transformer)(arg);
  }

  virtual Item* compile(Item_analyzer analyzer, byte **arg_p,
                        Item_transformer transformer, byte *arg_t)
  {
    if ((this->*analyzer) (arg_p))
      return ((this->*transformer) (arg_t));
    return 0;
  }

   virtual void traverse_cond(Cond_traverser traverser,
                              void *arg, traverse_order order)
   {
@@ -753,6 +762,12 @@ class Item {
  virtual bool change_context_processor(byte *context) { return 0; }
  virtual bool reset_query_id_processor(byte *query_id) { return 0; }
  virtual bool is_expensive_processor(byte *arg) { return 0; }
  virtual bool subst_argument_checker(byte **arg)
  { 
    if (*arg)
      *arg= NULL; 
    return TRUE;     
  }

  virtual Item *equal_fields_propagator(byte * arg) { return this; }
  virtual Item *set_no_const_sub(byte *arg) { return this; }
@@ -1254,6 +1269,7 @@ class Item_field :public Item_ident
    return field->can_be_compared_as_longlong();
  }
  Item_equal *find_item_equal(COND_EQUAL *cond_equal);
  bool subst_argument_checker(byte **arg);
  Item *equal_fields_propagator(byte *arg);
  Item *set_no_const_sub(byte *arg);
  Item *replace_equal_field(byte *arg);
Loading