Commit 5af4fd25 authored by unknown's avatar unknown

Bug #11032: getObject() returns a String for a sub-query of type datetime

 - When returning metadata for scalar subqueries the actual type of the
   column was calculated based on the value type, which limits the actual
   type of a scalar subselect to the set of (currently) 3 basic types : 
   integer, double precision or string. This is the reason that columns
   of types other then the basic ones (e.g. date/time) are reported as
   being of the corresponding basic type.
   Fixed by storing/returning information for the column type in addition
   to the result type.


mysql-test/r/subselect.result:
  Bug #11032: getObject() returns a String for a sub-query of type datetime
   - test case
mysql-test/t/subselect.test:
  Bug #11032: getObject() returns a String for a sub-query of type datetime
   - test case
sql/item_subselect.cc:
  Bug #11032: getObject() returns a String for a sub-query of type datetime
   - store and return the field type as well in addition to result type for 
     single row subqueries
sql/item_subselect.h:
  Bug #11032: getObject() returns a String for a sub-query of type datetime
   - store and return the field type as well in addition to result type for 
     single row subqueries
parent c095f98f
...@@ -2997,3 +2997,20 @@ a a IN (SELECT a FROM t1) ...@@ -2997,3 +2997,20 @@ a a IN (SELECT a FROM t1)
2 NULL 2 NULL
3 1 3 1
DROP TABLE t1,t2; 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;
...@@ -1965,4 +1965,20 @@ SELECT a, a IN (SELECT a FROM t1) FROM t2; ...@@ -1965,4 +1965,20 @@ SELECT a, a IN (SELECT a FROM t1) FROM t2;
DROP TABLE t1,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 # End of 4.1 tests
...@@ -391,6 +391,15 @@ enum Item_result Item_singlerow_subselect::result_type() const ...@@ -391,6 +391,15 @@ enum Item_result Item_singlerow_subselect::result_type() const
return engine->type(); 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() void Item_singlerow_subselect::fix_length_and_dec()
{ {
if ((max_columns= engine->cols()) == 1) if ((max_columns= engine->cols()) == 1)
...@@ -1357,31 +1366,35 @@ int subselect_uniquesubquery_engine::prepare() ...@@ -1357,31 +1366,35 @@ int subselect_uniquesubquery_engine::prepare()
return 1; return 1;
} }
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; Item *sel_item;
List_iterator_fast<Item> li(item_list); 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++) for (uint i= 0; (sel_item= li++); i++)
{ {
item->max_length= sel_item->max_length; item->max_length= sel_item->max_length;
res_type= sel_item->result_type(); res_type= sel_item->result_type();
res_field_type= sel_item->field_type();
item->decimals= sel_item->decimals; item->decimals= sel_item->decimals;
*maybe_null= sel_item->maybe_null; maybe_null= sel_item->maybe_null;
if (!(row[i]= Item_cache::get_cache(res_type))) if (!(row[i]= Item_cache::get_cache(res_type)))
return STRING_RESULT; // we should return something return;
row[i]->setup(sel_item); row[i]->setup(sel_item);
} }
if (item_list.elements > 1) if (item_list.elements > 1)
res_type= ROW_RESULT; res_type= ROW_RESULT;
return res_type;
} }
void subselect_single_select_engine::fix_length_and_dec(Item_cache **row) void subselect_single_select_engine::fix_length_and_dec(Item_cache **row)
{ {
DBUG_ASSERT(row || select_lex->item_list.elements==1); 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); item->collation.set(row[0]->collation);
if (cols() != 1) if (cols() != 1)
maybe_null= 0; maybe_null= 0;
...@@ -1393,13 +1406,14 @@ void subselect_union_engine::fix_length_and_dec(Item_cache **row) ...@@ -1393,13 +1406,14 @@ void subselect_union_engine::fix_length_and_dec(Item_cache **row)
if (unit->first_select()->item_list.elements == 1) 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); item->collation.set(row[0]->collation);
} }
else else
{ {
bool fake= 0; bool maybe_null_saved= maybe_null;
res_type= set_row(unit->types, item, row, &fake); set_row(unit->types, row);
maybe_null= maybe_null_saved;
} }
} }
......
...@@ -142,6 +142,7 @@ public: ...@@ -142,6 +142,7 @@ public:
longlong val_int (); longlong val_int ();
String *val_str (String *); String *val_str (String *);
enum Item_result result_type() const; enum Item_result result_type() const;
enum_field_types field_type() const;
void fix_length_and_dec(); void fix_length_and_dec();
uint cols(); uint cols();
...@@ -273,6 +274,7 @@ protected: ...@@ -273,6 +274,7 @@ protected:
THD *thd; /* pointer to current THD */ THD *thd; /* pointer to current THD */
Item_subselect *item; /* item, that use this engine */ Item_subselect *item; /* item, that use this engine */
enum Item_result res_type; /* type of results */ 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) */ bool maybe_null; /* may be null (first item in select) */
public: public:
...@@ -282,6 +284,7 @@ public: ...@@ -282,6 +284,7 @@ public:
result= res; result= res;
item= si; item= si;
res_type= STRING_RESULT; res_type= STRING_RESULT;
res_field_type= FIELD_TYPE_VAR_STRING;
maybe_null= 0; maybe_null= 0;
} }
virtual ~subselect_engine() {}; // to satisfy compiler virtual ~subselect_engine() {}; // to satisfy compiler
...@@ -296,6 +299,7 @@ public: ...@@ -296,6 +299,7 @@ public:
virtual uint cols()= 0; /* return number of columnss in select */ virtual uint cols()= 0; /* return number of columnss in select */
virtual uint8 uncacheable()= 0; /* query is uncacheable */ virtual uint8 uncacheable()= 0; /* query is uncacheable */
enum Item_result type() { return res_type; } enum Item_result type() { return res_type; }
enum_field_types field_type() { return res_field_type; }
virtual void exclude()= 0; virtual void exclude()= 0;
bool may_be_null() { return maybe_null; }; bool may_be_null() { return maybe_null; };
virtual table_map upper_select_const_tables()= 0; virtual table_map upper_select_const_tables()= 0;
...@@ -303,6 +307,9 @@ public: ...@@ -303,6 +307,9 @@ public:
virtual void print(String *str)= 0; virtual void print(String *str)= 0;
virtual int change_item(Item_subselect *si, select_subselect *result)= 0; virtual int change_item(Item_subselect *si, select_subselect *result)= 0;
virtual bool no_tables()= 0; virtual bool no_tables()= 0;
protected:
void set_row(List<Item> &item_list, Item_cache **row);
}; };
......
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