Commit 129fbca2 authored by holyfoot/hf@mysql.com/deer.(none)'s avatar holyfoot/hf@mysql.com/deer.(none)

Merge bk@192.168.21.1:mysql-5.0-opt

into  mysql.com:/home/hf/work/8663/my50-8663
parents 2942ab3f 1a8204f2
......@@ -135,6 +135,12 @@ test-force-pl:
./mysql-test-run.pl --force && \
./mysql-test-run.pl --ps-protocol --force
#used by autopush.pl to run memory based tests
test-force-mem:
cd mysql-test; \
./mysql-test-run.pl --force --mem && \
./mysql-test-run.pl --ps-protocol --force --mem
# Don't update the files from bitkeeper
%::SCCS/s.%
......@@ -854,6 +854,33 @@ b a
20 1
10 2
DROP TABLE t1;
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(2);
SELECT a + 1 AS num FROM t1 ORDER BY 30 - num;
num
3
2
SELECT CONCAT('test', a) AS str FROM t1 ORDER BY UPPER(str);
str
test1
test2
SELECT a + 1 AS num FROM t1 GROUP BY 30 - num;
num
3
2
SELECT a + 1 AS num FROM t1 HAVING 30 - num;
num
2
3
SELECT a + 1 AS num, num + 1 FROM t1;
ERROR 42S22: Unknown column 'num' in 'field list'
SELECT a + 1 AS num, (select num + 2 FROM t1 LIMIT 1) FROM t1;
num (select num + 2 FROM t1 LIMIT 1)
2 4
3 5
SELECT a.a + 1 AS num FROM t1 a JOIN t1 b ON num = b.a;
ERROR 42S22: Unknown column 'num' in 'on clause'
DROP TABLE t1;
CREATE TABLE t1 (a int, b int, PRIMARY KEY (a));
INSERT INTO t1 VALUES (1,1), (2,2), (3,3);
explain SELECT t1.b as a, t2.b as c FROM
......
......@@ -3017,6 +3017,23 @@ a a IN (SELECT a FROM t1)
2 NULL
3 1
DROP TABLE t1,t2;
CREATE TABLE t1 (a DATETIME);
INSERT INTO t1 VALUES ('1998-09-23'), ('2003-03-25');
CREATE TABLE t2 AS SELECT
(SELECT a FROM t1 WHERE a < '2000-01-01') AS sub_a
FROM t1 WHERE a > '2000-01-01';
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`sub_a` datetime default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
CREATE TABLE t3 AS (SELECT a FROM t1 WHERE a < '2000-01-01') UNION (SELECT a FROM t1 WHERE a > '2000-01-01');
SHOW CREATE TABLE t3;
Table Create Table
t3 CREATE TABLE `t3` (
`a` datetime default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1,t2,t3;
create table t1 (df decimal(5,1));
insert into t1 values(1.1);
insert into t1 values(2.2);
......
......@@ -577,6 +577,22 @@ INSERT INTO t1 VALUES (1,30), (2,20), (1,10), (2,30), (1,20), (2,10);
DROP TABLE t1;
#
# Bug #22457: Column alias in ORDER BY works, but not if in an expression
#
CREATE TABLE t1 (a INT); INSERT INTO t1 VALUES (1),(2);
SELECT a + 1 AS num FROM t1 ORDER BY 30 - num;
SELECT CONCAT('test', a) AS str FROM t1 ORDER BY UPPER(str);
SELECT a + 1 AS num FROM t1 GROUP BY 30 - num;
SELECT a + 1 AS num FROM t1 HAVING 30 - num;
--error 1054
SELECT a + 1 AS num, num + 1 FROM t1;
SELECT a + 1 AS num, (select num + 2 FROM t1 LIMIT 1) FROM t1;
--error 1054
SELECT a.a + 1 AS num FROM t1 a JOIN t1 b ON num = b.a;
DROP TABLE t1;
# End of 4.1 tests
#
......
......@@ -1972,6 +1972,22 @@ SELECT a, a IN (SELECT a FROM t1) FROM t2;
DROP TABLE t1,t2;
#
# Bug #11302: getObject() returns a String for a sub-query of type datetime
#
CREATE TABLE t1 (a DATETIME);
INSERT INTO t1 VALUES ('1998-09-23'), ('2003-03-25');
CREATE TABLE t2 AS SELECT
(SELECT a FROM t1 WHERE a < '2000-01-01') AS sub_a
FROM t1 WHERE a > '2000-01-01';
SHOW CREATE TABLE t2;
CREATE TABLE t3 AS (SELECT a FROM t1 WHERE a < '2000-01-01') UNION (SELECT a FROM t1 WHERE a > '2000-01-01');
SHOW CREATE TABLE t3;
DROP TABLE t1,t2,t3;
# End of 4.1 tests
#
......
......@@ -5639,7 +5639,7 @@ int Field_datetime::store_time(TIME *ltime,timestamp_type type)
(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
MODE_INVALID_DATES))), &error))
{
char buff[12];
char buff[19];
String str(buff, sizeof(buff), &my_charset_latin1);
make_datetime((DATE_TIME_FORMAT *) 0, ltime, &str);
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED,
......
......@@ -3707,10 +3707,37 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
Item** res= find_item_in_list(this, thd->lex->current_select->item_list,
&counter, REPORT_EXCEPT_NOT_FOUND,
&not_used);
if (res != (Item **)not_found_item && (*res)->type() == Item::FIELD_ITEM)
if (res != (Item **)not_found_item)
{
set_field((*((Item_field**)res))->field);
return 0;
if ((*res)->type() == Item::FIELD_ITEM)
{
/*
It's an Item_field referencing another Item_field in the select
list.
use the field from the Item_field in the select list and leave
the Item_field instance in place.
*/
set_field((*((Item_field**)res))->field);
return 0;
}
else
{
/*
It's not an Item_field in the select list so we must make a new
Item_ref to point to the Item in the select list and replace the
Item_field created by the parser with the new Item_ref.
*/
Item_ref *rf= new Item_ref(context, db_name,table_name,field_name);
if (!rf)
return 1;
thd->change_item_tree(reference, rf);
/*
Because Item_ref never substitutes itself with other items
in Item_ref::fix_fields(), we can safely use the original
pointer to it even after fix_fields()
*/
return rf->fix_fields(thd, reference) || rf->check_cols(1);
}
}
}
if ((ret= fix_outer_field(thd, &from_field, reference)) < 0)
......
......@@ -391,6 +391,15 @@ enum Item_result Item_singlerow_subselect::result_type() const
return engine->type();
}
/*
Don't rely on the result type to calculate field type.
Ask the engine instead.
*/
enum_field_types Item_singlerow_subselect::field_type() const
{
return engine->field_type();
}
void Item_singlerow_subselect::fix_length_and_dec()
{
if ((max_columns= engine->cols()) == 1)
......@@ -1613,32 +1622,36 @@ bool subselect_single_select_engine::no_rows()
}
static Item_result set_row(List<Item> &item_list, Item *item,
Item_cache **row, bool *maybe_null)
/*
makes storage for the output values for the subquery and calcuates
their data and column types and their nullability.
*/
void subselect_engine::set_row(List<Item> &item_list, Item_cache **row)
{
Item_result res_type= STRING_RESULT;
Item *sel_item;
List_iterator_fast<Item> li(item_list);
res_type= STRING_RESULT;
res_field_type= FIELD_TYPE_VAR_STRING;
for (uint i= 0; (sel_item= li++); i++)
{
item->max_length= sel_item->max_length;
res_type= sel_item->result_type();
res_field_type= sel_item->field_type();
item->decimals= sel_item->decimals;
item->unsigned_flag= sel_item->unsigned_flag;
*maybe_null= sel_item->maybe_null;
maybe_null= sel_item->maybe_null;
if (!(row[i]= Item_cache::get_cache(res_type)))
return STRING_RESULT; // we should return something
return;
row[i]->setup(sel_item);
}
if (item_list.elements > 1)
res_type= ROW_RESULT;
return res_type;
}
void subselect_single_select_engine::fix_length_and_dec(Item_cache **row)
{
DBUG_ASSERT(row || select_lex->item_list.elements==1);
res_type= set_row(select_lex->item_list, item, row, &maybe_null);
set_row(select_lex->item_list, row);
item->collation.set(row[0]->collation);
if (cols() != 1)
maybe_null= 0;
......@@ -1650,13 +1663,14 @@ void subselect_union_engine::fix_length_and_dec(Item_cache **row)
if (unit->first_select()->item_list.elements == 1)
{
res_type= set_row(unit->types, item, row, &maybe_null);
set_row(unit->types, row);
item->collation.set(row[0]->collation);
}
else
{
bool fake= 0;
res_type= set_row(unit->types, item, row, &fake);
bool maybe_null_saved= maybe_null;
set_row(unit->types, row);
maybe_null= maybe_null_saved;
}
}
......
......@@ -159,6 +159,7 @@ public:
my_decimal *val_decimal(my_decimal *);
bool val_bool();
enum Item_result result_type() const;
enum_field_types field_type() const;
void fix_length_and_dec();
uint cols();
......@@ -311,6 +312,7 @@ protected:
THD *thd; /* pointer to current THD */
Item_subselect *item; /* item, that use this engine */
enum Item_result res_type; /* type of results */
enum_field_types res_field_type; /* column type of the results */
bool maybe_null; /* may be null (first item in select) */
public:
......@@ -320,6 +322,7 @@ public:
result= res;
item= si;
res_type= STRING_RESULT;
res_field_type= FIELD_TYPE_VAR_STRING;
maybe_null= 0;
}
virtual ~subselect_engine() {}; // to satisfy compiler
......@@ -358,6 +361,7 @@ public:
virtual uint cols()= 0; /* return number of columns in select */
virtual uint8 uncacheable()= 0; /* query is uncacheable */
enum Item_result type() { return res_type; }
enum_field_types field_type() { return res_field_type; }
virtual void exclude()= 0;
bool may_be_null() { return maybe_null; };
virtual table_map upper_select_const_tables()= 0;
......@@ -368,6 +372,9 @@ public:
virtual bool is_executed() const { return FALSE; }
/* Check if subquery produced any rows during last query execution */
virtual bool no_rows() = 0;
protected:
void set_row(List<Item> &item_list, Item_cache **row);
};
......
......@@ -2951,10 +2951,12 @@ add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level,
join->unit->item->substype() == Item_subselect::IN_SUBS &&
!join->unit->first_select()->next_select())
{
KEY_FIELD *save= *key_fields;
add_key_fields(join, key_fields, and_level, cond, usable_tables,
sargables);
// Indicate that this ref access candidate is for subquery lookup:
(*key_fields)[-1].outer_ref= TRUE;
for (; save != *key_fields; save++)
save->outer_ref= TRUE;
}
return;
}
......
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