New structure Table Value Constructor added in grammar.
TVC can be used in UNION-statement, in view and in subquery. Files where TVC is defined and its methods are stored added. Methods exec and prepare for TVC added. Tests for TVC added.
This commit is contained in:
parent
0fe7d8a2a2
commit
615da8f70b
30
mysql-test/t/table_value_const.test
Normal file
30
mysql-test/t/table_value_const.test
Normal file
@ -0,0 +1,30 @@
|
||||
values (1,2);
|
||||
|
||||
select 1,2 union values (1,2);
|
||||
|
||||
values (1,2) union select (1,2);
|
||||
|
||||
select * from t1 where (t1.a,t1.b) in (select 5,7 union values (1,2),(2,3));
|
||||
|
||||
select * from t1 where (t1.a,t1.b) in (values (1,2),(2,3) union select 5,7);
|
||||
|
||||
let $drop_view= drop view v1;
|
||||
|
||||
create view v1 as values (1,2);
|
||||
|
||||
eval $drop_view;
|
||||
|
||||
create view v1 as values (1,2) union select 3,4;
|
||||
|
||||
eval $drop_view;
|
||||
|
||||
create view v1 as select 1,2 union values (3,4);
|
||||
|
||||
eval $drop_view;
|
||||
|
||||
create view v1 as select 1,2 union values (3,4),(5,6);
|
||||
|
||||
eval $drop_view;
|
||||
|
||||
|
||||
|
@ -145,6 +145,7 @@ SET (SQL_SOURCE
|
||||
item_windowfunc.cc sql_window.cc
|
||||
sql_cte.cc
|
||||
sql_sequence.cc sql_sequence.h ha_sequence.h
|
||||
sql_tvc.cc sql_tvc.h
|
||||
${WSREP_SOURCES}
|
||||
table_cache.cc encryption.cc temporary_tables.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/sql_builtin.cc
|
||||
|
@ -6034,6 +6034,64 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class Type_holder: public Sql_alloc,
|
||||
public Item_args,
|
||||
public Type_handler_hybrid_field_type,
|
||||
public Type_all_attributes,
|
||||
public Type_geometry_attributes
|
||||
{
|
||||
TYPELIB *m_typelib;
|
||||
bool m_maybe_null;
|
||||
public:
|
||||
Type_holder()
|
||||
:m_typelib(NULL),
|
||||
m_maybe_null(false)
|
||||
{ }
|
||||
|
||||
void set_maybe_null(bool maybe_null_arg) { m_maybe_null= maybe_null_arg; }
|
||||
bool get_maybe_null() const { return m_maybe_null; }
|
||||
|
||||
uint decimal_precision() const
|
||||
{
|
||||
/*
|
||||
Type_holder is not used directly to create fields, so
|
||||
its virtual decimal_precision() is never called.
|
||||
We should eventually extend create_result_table() to accept
|
||||
an array of Type_holders directly, without having to allocate
|
||||
Item_type_holder's and put them into List<Item>.
|
||||
*/
|
||||
DBUG_ASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
void set_geometry_type(uint type)
|
||||
{
|
||||
Type_geometry_attributes::set_geometry_type(type);
|
||||
}
|
||||
uint uint_geometry_type() const
|
||||
{
|
||||
return Type_geometry_attributes::get_geometry_type();
|
||||
}
|
||||
void set_typelib(TYPELIB *typelib)
|
||||
{
|
||||
m_typelib= typelib;
|
||||
}
|
||||
TYPELIB *get_typelib() const
|
||||
{
|
||||
return m_typelib;
|
||||
}
|
||||
|
||||
bool aggregate_attributes(THD *thd)
|
||||
{
|
||||
for (uint i= 0; i < arg_count; i++)
|
||||
m_maybe_null|= args[i]->maybe_null;
|
||||
return
|
||||
type_handler()->Item_hybrid_func_fix_attributes(thd,
|
||||
"UNION", this, this,
|
||||
args, arg_count);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif /* MYSQL_SERVER */
|
||||
|
||||
#endif /* SQL_CLASS_INCLUDED */
|
||||
|
@ -31,7 +31,7 @@
|
||||
#include "sql_window.h"
|
||||
#include "sql_trigger.h"
|
||||
#include "sp.h" // enum stored_procedure_type
|
||||
|
||||
#include "sql_tvc.h"
|
||||
|
||||
/* YACC and LEX Definitions */
|
||||
|
||||
@ -999,6 +999,8 @@ public:
|
||||
|
||||
/* it is for correct printing SELECT options */
|
||||
thr_lock_type lock_type;
|
||||
|
||||
table_value_constr *tvc;
|
||||
|
||||
void init_query();
|
||||
void init_select();
|
||||
|
128
sql/sql_tvc.cc
Normal file
128
sql/sql_tvc.cc
Normal file
@ -0,0 +1,128 @@
|
||||
#include "sql_list.h"
|
||||
#include "sql_tvc.h"
|
||||
#include "sql_class.h"
|
||||
|
||||
/**
|
||||
The method searches types of columns for temporary table where values from TVC will be stored
|
||||
*/
|
||||
|
||||
bool join_type_handlers_for_tvc(List_iterator_fast<List_item> &li,
|
||||
Type_holder *holders, uint cnt)
|
||||
{
|
||||
List_item *lst;
|
||||
li.rewind();
|
||||
bool first= true;
|
||||
|
||||
while ((lst=li++))
|
||||
{
|
||||
List_iterator_fast<Item> it(*lst);
|
||||
Item *item;
|
||||
|
||||
if (cnt != lst->elements)
|
||||
{
|
||||
/*error wrong number of values*/
|
||||
return true;
|
||||
}
|
||||
for (uint pos= 0; (item=it++); pos++)
|
||||
{
|
||||
const Type_handler *item_type_handler= item->real_type_handler();
|
||||
if (first)
|
||||
holders[pos].set_handler(item_type_handler);
|
||||
else if (holders[pos].aggregate_for_result(item_type_handler))
|
||||
{
|
||||
/*error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION*/
|
||||
return true;
|
||||
}
|
||||
}
|
||||
first= false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
The method searches names of columns for temporary table where values from TVC will be stored
|
||||
*/
|
||||
|
||||
bool get_type_attributes_for_tvc(THD *thd_arg,
|
||||
List_iterator_fast<List_item> &li,
|
||||
Type_holder *holders, uint count)
|
||||
{
|
||||
List_item *lst;
|
||||
li.rewind();
|
||||
|
||||
lst= li++;
|
||||
uint first_list_el_count= lst->elements;
|
||||
|
||||
for (uint pos= 0; pos < first_list_el_count; pos++)
|
||||
{
|
||||
if (holders[pos].alloc_arguments(thd_arg, count))
|
||||
return true;
|
||||
}
|
||||
|
||||
List_iterator_fast<Item> it(*lst);
|
||||
Item *item;
|
||||
|
||||
for (uint holder_pos= 0 ; (item= it++); holder_pos++)
|
||||
{
|
||||
DBUG_ASSERT(item->fixed);
|
||||
holders[holder_pos].add_argument(item);
|
||||
}
|
||||
|
||||
for (uint pos= 0; pos < first_list_el_count; pos++)
|
||||
{
|
||||
if (holders[pos].aggregate_attributes(thd_arg))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool table_value_constr::prepare(THD *thd_arg, SELECT_LEX *sl, select_result *tmp_result)
|
||||
{
|
||||
List_iterator_fast<List_item> li(lists_of_values);
|
||||
|
||||
List_item *first_elem= li++;
|
||||
uint cnt= first_elem->elements;
|
||||
Type_holder *holders;
|
||||
|
||||
if (!(holders= new (thd_arg->mem_root)
|
||||
Type_holder[cnt]) ||
|
||||
join_type_handlers_for_tvc(li, holders, cnt) ||
|
||||
get_type_attributes_for_tvc(thd_arg, li, holders, cnt))
|
||||
return true;
|
||||
|
||||
List_iterator_fast<Item> it(*first_elem);
|
||||
Item *item;
|
||||
|
||||
sl->item_list.empty();
|
||||
for (uint pos= 0; (item= it++); pos++)
|
||||
{
|
||||
/* Error's in 'new' will be detected after loop */
|
||||
Item_type_holder *new_holder= new (thd_arg->mem_root)
|
||||
Item_type_holder(thd_arg,
|
||||
&item->name,
|
||||
holders[pos].type_handler(),
|
||||
&holders[pos]/*Type_all_attributes*/,
|
||||
holders[pos].get_maybe_null());
|
||||
new_holder->fix_fields(thd_arg, 0);
|
||||
sl->item_list.push_back(new_holder);
|
||||
}
|
||||
|
||||
if (thd_arg->is_fatal_error)
|
||||
return true; // out of memory
|
||||
|
||||
result= tmp_result;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool table_value_constr::exec()
|
||||
{
|
||||
List_iterator_fast<List_item> li(lists_of_values);
|
||||
List_item *elem;
|
||||
|
||||
while ((elem=li++))
|
||||
{
|
||||
result->send_data(*elem);
|
||||
}
|
||||
return false;
|
||||
}
|
27
sql/sql_tvc.h
Normal file
27
sql/sql_tvc.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef SQL_TVC_INCLUDED
|
||||
#define SQL_TVC_INCLUDED
|
||||
#include "sql_type.h"
|
||||
#include "item.h"
|
||||
|
||||
typedef List<Item> List_item;
|
||||
class select_result;
|
||||
|
||||
/**
|
||||
@class table_value_constr
|
||||
@brief Definition of a Table Value Construction(TVC)
|
||||
|
||||
It contains a list of lists of values that this TVC contains.
|
||||
*/
|
||||
|
||||
class table_value_constr : public Sql_alloc
|
||||
{
|
||||
public:
|
||||
List<List_item> lists_of_values;
|
||||
select_result *result;
|
||||
|
||||
bool prepare(THD *thd_arg, SELECT_LEX *sl,
|
||||
select_result *tmp_result);
|
||||
bool exec();
|
||||
};
|
||||
|
||||
#endif /* SQL_TVC_INCLUDED */
|
@ -692,64 +692,6 @@ bool st_select_lex_unit::prepare_join(THD *thd_arg, SELECT_LEX *sl,
|
||||
}
|
||||
|
||||
|
||||
class Type_holder: public Sql_alloc,
|
||||
public Item_args,
|
||||
public Type_handler_hybrid_field_type,
|
||||
public Type_all_attributes,
|
||||
public Type_geometry_attributes
|
||||
{
|
||||
TYPELIB *m_typelib;
|
||||
bool m_maybe_null;
|
||||
public:
|
||||
Type_holder()
|
||||
:m_typelib(NULL),
|
||||
m_maybe_null(false)
|
||||
{ }
|
||||
|
||||
void set_maybe_null(bool maybe_null_arg) { m_maybe_null= maybe_null_arg; }
|
||||
bool get_maybe_null() const { return m_maybe_null; }
|
||||
|
||||
uint decimal_precision() const
|
||||
{
|
||||
/*
|
||||
Type_holder is not used directly to create fields, so
|
||||
its virtual decimal_precision() is never called.
|
||||
We should eventually extend create_result_table() to accept
|
||||
an array of Type_holders directly, without having to allocate
|
||||
Item_type_holder's and put them into List<Item>.
|
||||
*/
|
||||
DBUG_ASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
void set_geometry_type(uint type)
|
||||
{
|
||||
Type_geometry_attributes::set_geometry_type(type);
|
||||
}
|
||||
uint uint_geometry_type() const
|
||||
{
|
||||
return Type_geometry_attributes::get_geometry_type();
|
||||
}
|
||||
void set_typelib(TYPELIB *typelib)
|
||||
{
|
||||
m_typelib= typelib;
|
||||
}
|
||||
TYPELIB *get_typelib() const
|
||||
{
|
||||
return m_typelib;
|
||||
}
|
||||
|
||||
bool aggregate_attributes(THD *thd)
|
||||
{
|
||||
for (uint i= 0; i < arg_count; i++)
|
||||
m_maybe_null|= args[i]->maybe_null;
|
||||
return
|
||||
type_handler()->Item_hybrid_func_fix_attributes(thd,
|
||||
"UNION", this, this,
|
||||
args, arg_count);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Aggregate data type handlers for the "count" leftmost UNION parts.
|
||||
*/
|
||||
@ -978,7 +920,12 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
||||
|
||||
if (!is_union_select && !is_recursive)
|
||||
{
|
||||
if (prepare_join(thd_arg, first_sl, tmp_result, additional_options,
|
||||
if (sl->tvc)
|
||||
{
|
||||
if (sl->tvc->prepare(thd_arg, sl, tmp_result))
|
||||
goto err;
|
||||
}
|
||||
else if (prepare_join(thd_arg, first_sl, tmp_result, additional_options,
|
||||
is_union_select))
|
||||
goto err;
|
||||
types= first_sl->item_list;
|
||||
@ -987,8 +934,13 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
||||
|
||||
for (;sl; sl= sl->next_select(), union_part_count++)
|
||||
{
|
||||
if (prepare_join(thd_arg, sl, tmp_result, additional_options,
|
||||
is_union_select))
|
||||
if (sl->tvc)
|
||||
{
|
||||
if (sl->tvc->prepare(thd_arg, sl, tmp_result))
|
||||
goto err;
|
||||
}
|
||||
else if (prepare_join(thd_arg, sl, tmp_result, additional_options,
|
||||
is_union_select))
|
||||
goto err;
|
||||
|
||||
/*
|
||||
@ -1296,6 +1248,8 @@ bool st_select_lex_unit::optimize()
|
||||
}
|
||||
for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select())
|
||||
{
|
||||
if (sl->tvc)
|
||||
continue;
|
||||
thd->lex->current_select= sl;
|
||||
|
||||
if (optimized)
|
||||
@ -1411,6 +1365,8 @@ bool st_select_lex_unit::exec()
|
||||
if (!saved_error)
|
||||
{
|
||||
records_at_start= table->file->stats.records;
|
||||
if (sl->tvc)
|
||||
sl->tvc->exec();
|
||||
sl->join->exec();
|
||||
if (sl == union_distinct && !(with_element && with_element->is_recursive))
|
||||
{
|
||||
|
@ -1822,11 +1822,13 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||
|
||||
%type <select_lex> subselect
|
||||
get_select_lex get_select_lex_derived
|
||||
simple_table
|
||||
query_specification
|
||||
query_term_union_not_ready
|
||||
query_term_union_ready
|
||||
query_expression_body
|
||||
select_paren_derived
|
||||
table_value_constructor
|
||||
|
||||
%type <boolfunc2creator> comp_op
|
||||
|
||||
@ -8467,6 +8469,9 @@ select:
|
||||
|
||||
select_init:
|
||||
SELECT_SYM select_options_and_item_list select_init3
|
||||
| table_value_constructor
|
||||
| table_value_constructor union_list
|
||||
| table_value_constructor union_order_or_limit
|
||||
| '(' select_paren ')'
|
||||
| '(' select_paren ')' union_list
|
||||
| '(' select_paren ')' union_order_or_limit
|
||||
@ -8474,12 +8479,23 @@ select_init:
|
||||
|
||||
union_list_part2:
|
||||
SELECT_SYM select_options_and_item_list select_init3_union_query_term
|
||||
| table_value_constructor
|
||||
| table_value_constructor union_list
|
||||
| table_value_constructor union_order_or_limit
|
||||
| '(' select_paren_union_query_term ')'
|
||||
| '(' select_paren_union_query_term ')' union_list
|
||||
| '(' select_paren_union_query_term ')' union_order_or_limit
|
||||
;
|
||||
|
||||
select_paren:
|
||||
{
|
||||
Lex->current_select->set_braces(true);
|
||||
}
|
||||
table_value_constructor
|
||||
{
|
||||
DBUG_ASSERT(Lex->current_select->braces);
|
||||
}
|
||||
|
|
||||
{
|
||||
/*
|
||||
In order to correctly parse UNION's global ORDER BY we need to
|
||||
@ -9443,7 +9459,7 @@ column_default_non_parenthesized_expr:
|
||||
if ($$ == NULL)
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
| VALUES '(' simple_ident_nospvar ')'
|
||||
| VALUE_SYM '(' simple_ident_nospvar ')'
|
||||
{
|
||||
$$= new (thd->mem_root) Item_insert_value(thd, Lex->current_context(),
|
||||
$3);
|
||||
@ -16250,6 +16266,21 @@ union_option:
|
||||
| ALL { $$=0; }
|
||||
;
|
||||
|
||||
simple_table:
|
||||
query_specification { $$= $1; }
|
||||
| table_value_constructor { $$= $1; }
|
||||
;
|
||||
|
||||
table_value_constructor:
|
||||
VALUES values_list
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
$$= Lex->current_select;
|
||||
mysql_init_select(Lex);
|
||||
$$->tvc->lists_of_values= lex->many_values;
|
||||
}
|
||||
;
|
||||
|
||||
/*
|
||||
Corresponds to the SQL Standard
|
||||
<query specification> ::=
|
||||
@ -16267,12 +16298,12 @@ query_specification:
|
||||
;
|
||||
|
||||
query_term_union_not_ready:
|
||||
query_specification order_or_limit opt_select_lock_type { $$= $1; }
|
||||
simple_table order_or_limit opt_select_lock_type { $$= $1; }
|
||||
| '(' select_paren_derived ')' union_order_or_limit { $$= $2; }
|
||||
;
|
||||
|
||||
query_term_union_ready:
|
||||
query_specification opt_select_lock_type { $$= $1; }
|
||||
simple_table opt_select_lock_type { $$= $1; }
|
||||
| '(' select_paren_derived ')' { $$= $2; }
|
||||
;
|
||||
|
||||
@ -16534,6 +16565,9 @@ view_select:
|
||||
*/
|
||||
query_expression_body_view:
|
||||
SELECT_SYM select_options_and_item_list select_init3_view
|
||||
| table_value_constructor
|
||||
| table_value_constructor union_order_or_limit
|
||||
| table_value_constructor union_list_view
|
||||
| '(' select_paren_view ')'
|
||||
| '(' select_paren_view ')' union_order_or_limit
|
||||
| '(' select_paren_view ')' union_list_view
|
||||
|
Loading…
x
Reference in New Issue
Block a user