Commit 615da8f7 authored by Galina Shalygina's avatar Galina Shalygina

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.
parent 0fe7d8a2
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 @@ class ErrConvDQName: public ErrConv
};
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 @@ class st_select_lex: public st_select_lex_node
/* it is for correct printing SELECT options */
thr_lock_type lock_type;
table_value_constr *tvc;
void init_query();
void init_select();
......
#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;
}
\ No newline at end of file
#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 */
\ No newline at end of file
......@@ -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
......
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