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.
This commit is contained in:
parent
77acba320d
commit
cf1ca923fc
@ -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;
|
|||||||
|
|
||||||
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
|
|||||||
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()
|
|||||||
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)
|
|||||||
|
|
||||||
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:
|
|||||||
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:
|
|||||||
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:
|
|||||||
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:
|
|||||||
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:
|
|||||||
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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user