Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
75370a58
Commit
75370a58
authored
Sep 04, 2017
by
Galina Shalygina
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
New tests on errors added. Comments corrected. Some procedures corrected.
parent
6bce8e14
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
190 additions
and
90 deletions
+190
-90
mysql-test/r/table_value_constr.result
mysql-test/r/table_value_constr.result
+18
-0
mysql-test/t/table_value_constr.test
mysql-test/t/table_value_constr.test
+21
-0
sql/item_subselect.cc
sql/item_subselect.cc
+7
-5
sql/share/errmsg-utf8.txt
sql/share/errmsg-utf8.txt
+2
-4
sql/sql_tvc.cc
sql/sql_tvc.cc
+142
-81
No files found.
mysql-test/r/table_value_constr.result
View file @
75370a58
...
...
@@ -1630,4 +1630,22 @@ ANALYZE
}
}
}
# different number of values in TVC
values (1,2),(3,4,5);
ERROR HY000: The used table value constructor has a different number of values
# subquery that uses VALUES structure(s)
select * from t1
where a in (values (1));
ERROR HY000: Table value constructor can't be used as specification of subquery isn't implemented yet
select * from t1
where a in (select 2 union values (1));
ERROR HY000: Table value constructor can't be used as specification of subquery isn't implemented yet
select * from t1
where a in (values (1) union select 2);
ERROR HY000: Table value constructor can't be used as specification of subquery isn't implemented yet
# illegal parameter data types in TVC
values (1,point(1,1)),(1,1);
ERROR HY000: Illegal parameter data types geometry and int for operation 'TABLE VALUE CONSTRUCTOR'
values (1,point(1,1)+1);
ERROR HY000: Illegal parameter data types geometry and int for operation '+'
drop table t1;
mysql-test/t/table_value_constr.test
View file @
75370a58
...
...
@@ -852,4 +852,25 @@ values (3,4)
union
all
values
(
1
,
2
);
--
echo
# different number of values in TVC
--
error
ER_WRONG_NUMBER_OF_VALUES_IN_TVC
values
(
1
,
2
),(
3
,
4
,
5
);
--
echo
# subquery that uses VALUES structure(s)
--
error
ER_TVC_IN_SUBQUERY
select
*
from
t1
where
a
in
(
values
(
1
));
--
error
ER_TVC_IN_SUBQUERY
select
*
from
t1
where
a
in
(
select
2
union
values
(
1
));
--
error
ER_TVC_IN_SUBQUERY
select
*
from
t1
where
a
in
(
values
(
1
)
union
select
2
);
--
echo
# illegal parameter data types in TVC
--
error
ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
values
(
1
,
point
(
1
,
1
)),(
1
,
1
);
--
error
ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
values
(
1
,
point
(
1
,
1
)
+
1
);
drop
table
t1
;
\ No newline at end of file
sql/item_subselect.cc
View file @
75370a58
...
...
@@ -265,13 +265,15 @@ bool Item_subselect::fix_fields(THD *thd_param, Item **ref)
if
(
check_stack_overrun
(
thd
,
STACK_MIN_SIZE
,
(
uchar
*
)
&
res
))
return
TRUE
;
if
(
unit
->
first_select
()
&&
unit
->
first_select
()
->
tvc
)
for
(
SELECT_LEX
*
sl
=
unit
->
first_select
();
sl
;
sl
=
sl
->
next_select
())
{
if
(
sl
->
tvc
)
{
my_error
(
ER_NO
_TVC_IN_SUBQUERY
,
MYF
(
0
));
my_error
(
ER
_TVC_IN_SUBQUERY
,
MYF
(
0
));
res
=
1
;
goto
end
;
}
}
if
(
!
(
res
=
engine
->
prepare
(
thd
)))
{
...
...
sql/share/errmsg-utf8.txt
View file @
75370a58
...
...
@@ -7492,7 +7492,5 @@ ER_SP_STACK_TRACE
eng "At line %u in %s"
ER_WRONG_NUMBER_OF_VALUES_IN_TVC
eng "The used table value constructor has a different number of values"
ER_UNKNOWN_VALUE_IN_TVC
eng "Unknown value '%d' in table values constructor definition"
ER_NO_TVC_IN_SUBQUERY
eng "The usage of table value constructor as specification of subselect isn't implemented yet"
\ No newline at end of file
ER_TVC_IN_SUBQUERY
eng "Table value constructor can't be used as specification of subquery isn't implemented yet"
\ No newline at end of file
sql/sql_tvc.cc
View file @
75370a58
...
...
@@ -6,13 +6,51 @@
#include "sql_explain.h"
#include "sql_parse.h"
/**
@brief
Fix fields for TVC values
@param
@param thd The context of the statement
@param li The iterator on the list of lists
@details
Call fix_fields procedure for TVC values.
@retval
true if an error was reported
false otherwise
*/
bool
fix_fields_for_tvc
(
THD
*
thd
,
List_iterator_fast
<
List_item
>
&
li
)
{
DBUG_ENTER
(
"fix_fields_for_tvc"
);
List_item
*
lst
;
li
.
rewind
();
while
((
lst
=
li
++
))
{
List_iterator_fast
<
Item
>
it
(
*
lst
);
Item
*
item
;
while
((
item
=
it
++
))
{
if
(
item
->
fix_fields
(
thd
,
0
))
DBUG_RETURN
(
true
);
}
}
DBUG_RETURN
(
false
);
}
/**
@brief
Defines types of matrix columns elements where matrix rows are defined by
some lists of values.
@param
@param thd
_arg
The context of the statement
@param thd The context of the statement
@param li The iterator on the list of lists
@param holders The structure where types of matrix columns are stored
@param first_list_el_count Count of the list values that should be. It should
...
...
@@ -31,7 +69,7 @@
false otherwise
*/
bool
join_type_handlers_for_tvc
(
THD
*
thd
_arg
,
List_iterator_fast
<
List_item
>
&
li
,
bool
join_type_handlers_for_tvc
(
THD
*
thd
,
List_iterator_fast
<
List_item
>
&
li
,
Type_holder
*
holders
,
uint
first_list_el_count
)
{
DBUG_ENTER
(
"join_type_handlers_for_tvc"
);
...
...
@@ -39,7 +77,7 @@ bool join_type_handlers_for_tvc(THD *thd_arg, List_iterator_fast<List_item> &li,
li
.
rewind
();
bool
first
=
true
;
while
((
lst
=
li
++
))
while
((
lst
=
li
++
))
{
List_iterator_fast
<
Item
>
it
(
*
lst
);
Item
*
item
;
...
...
@@ -47,19 +85,12 @@ bool join_type_handlers_for_tvc(THD *thd_arg, List_iterator_fast<List_item> &li,
if
(
first_list_el_count
!=
lst
->
elements
)
{
my_message
(
ER_WRONG_NUMBER_OF_VALUES_IN_TVC
,
ER_THD
(
thd
_arg
,
ER_WRONG_NUMBER_OF_VALUES_IN_TVC
),
ER_THD
(
thd
,
ER_WRONG_NUMBER_OF_VALUES_IN_TVC
),
MYF
(
0
));
DBUG_RETURN
(
true
);
}
for
(
uint
pos
=
0
;
(
item
=
it
++
);
pos
++
)
{
if
(
item
->
type
()
==
Item
::
FIELD_ITEM
)
{
my_error
(
ER_UNKNOWN_VALUE_IN_TVC
,
MYF
(
0
),
((
Item_field
*
)
item
)
->
full_name
(),
MYF
(
0
));
DBUG_RETURN
(
true
);
}
const
Type_handler
*
item_type_handler
=
item
->
real_type_handler
();
if
(
first
)
holders
[
pos
].
set_handler
(
item_type_handler
);
...
...
@@ -80,11 +111,11 @@ bool join_type_handlers_for_tvc(THD *thd_arg, List_iterator_fast<List_item> &li,
/**
@brief
Define
s
attributes of matrix columns elements where matrix rows are defined by
Define attributes of matrix columns elements where matrix rows are defined by
some lists of values.
@param
@param thd
_arg
The context of the statement
@param thd
The context of the statement
@param li The iterator on the list of lists
@param holders The structure where names of matrix columns are stored
@param count_of_lists Count of list of lists elements
...
...
@@ -102,7 +133,7 @@ bool join_type_handlers_for_tvc(THD *thd_arg, List_iterator_fast<List_item> &li,
false otherwise
*/
bool
get_type_attributes_for_tvc
(
THD
*
thd
_arg
,
bool
get_type_attributes_for_tvc
(
THD
*
thd
,
List_iterator_fast
<
List_item
>
&
li
,
Type_holder
*
holders
,
uint
count_of_lists
,
uint
first_list_el_count
)
...
...
@@ -113,11 +144,11 @@ bool get_type_attributes_for_tvc(THD *thd_arg,
for
(
uint
pos
=
0
;
pos
<
first_list_el_count
;
pos
++
)
{
if
(
holders
[
pos
].
alloc_arguments
(
thd
_arg
,
count_of_lists
))
if
(
holders
[
pos
].
alloc_arguments
(
thd
,
count_of_lists
))
DBUG_RETURN
(
true
);
}
while
((
lst
=
li
++
))
while
((
lst
=
li
++
))
{
List_iterator_fast
<
Item
>
it
(
*
lst
);
Item
*
item
;
...
...
@@ -130,7 +161,7 @@ bool get_type_attributes_for_tvc(THD *thd_arg,
for
(
uint
pos
=
0
;
pos
<
first_list_el_count
;
pos
++
)
{
if
(
holders
[
pos
].
aggregate_attributes
(
thd
_arg
))
if
(
holders
[
pos
].
aggregate_attributes
(
thd
))
DBUG_RETURN
(
true
);
}
DBUG_RETURN
(
false
);
...
...
@@ -142,10 +173,10 @@ bool get_type_attributes_for_tvc(THD *thd_arg,
Prepare of TVC
@param
@param thd
_arg
The context of the statement
@param thd
The context of the statement
@param sl The select where this TVC is defined
@param tmp_result Structure that contains the information
about where
result of the query should be sent
about where
to send the result of the query
@param unit_arg The union where sl is defined
@details
...
...
@@ -159,7 +190,7 @@ bool get_type_attributes_for_tvc(THD *thd_arg,
false otherwise
*/
bool
table_value_constr
::
prepare
(
THD
*
thd
_arg
,
SELECT_LEX
*
sl
,
bool
table_value_constr
::
prepare
(
THD
*
thd
,
SELECT_LEX
*
sl
,
select_result
*
tmp_result
,
st_select_lex_unit
*
unit_arg
)
{
...
...
@@ -170,11 +201,14 @@ bool table_value_constr::prepare(THD *thd_arg, SELECT_LEX *sl,
uint
cnt
=
first_elem
->
elements
;
Type_holder
*
holders
;
if
(
!
(
holders
=
new
(
thd_arg
->
mem_root
)
if
(
fix_fields_for_tvc
(
thd
,
li
))
DBUG_RETURN
(
true
);
if
(
!
(
holders
=
new
(
thd
->
mem_root
)
Type_holder
[
cnt
])
||
join_type_handlers_for_tvc
(
thd
_arg
,
li
,
holders
,
join_type_handlers_for_tvc
(
thd
,
li
,
holders
,
cnt
)
||
get_type_attributes_for_tvc
(
thd
_arg
,
li
,
holders
,
get_type_attributes_for_tvc
(
thd
,
li
,
holders
,
lists_of_values
.
elements
,
cnt
))
DBUG_RETURN
(
true
);
...
...
@@ -185,17 +219,17 @@ bool table_value_constr::prepare(THD *thd_arg, SELECT_LEX *sl,
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_type_holder
*
new_holder
=
new
(
thd
->
mem_root
)
Item_type_holder
(
thd
,
&
item
->
name
,
holders
[
pos
].
type_handler
(),
&
holders
[
pos
]
/*Type_all_attributes*/
,
holders
[
pos
].
get_maybe_null
());
new_holder
->
fix_fields
(
thd
_arg
,
0
);
new_holder
->
fix_fields
(
thd
,
0
);
sl
->
item_list
.
push_back
(
new_holder
);
}
if
(
thd
_arg
->
is_fatal_error
)
if
(
thd
->
is_fatal_error
)
DBUG_RETURN
(
true
);
// out of memory
result
=
tmp_result
;
...
...
@@ -211,7 +245,7 @@ bool table_value_constr::prepare(THD *thd_arg, SELECT_LEX *sl,
Save Query Plan Footprint
*/
int
table_value_constr
::
save_explain_data_intern
(
THD
*
thd
_arg
,
int
table_value_constr
::
save_explain_data_intern
(
THD
*
thd
,
Explain_query
*
output
)
{
const
char
*
message
=
"No tables used"
;
...
...
@@ -227,7 +261,7 @@ int table_value_constr::save_explain_data_intern(THD *thd_arg,
select_lex
->
master_unit
()
->
derived
->
is_with_table
());
explain
=
new
(
output
->
mem_root
)
Explain_select
(
output
->
mem_root
,
thd
_arg
->
lex
->
analyze_stmt
);
thd
->
lex
->
analyze_stmt
);
select_lex
->
set_explain_type
(
true
);
explain
->
select_id
=
select_lex
->
select_number
;
...
...
@@ -254,18 +288,18 @@ int table_value_constr::save_explain_data_intern(THD *thd_arg,
Optimization of TVC
*/
void
table_value_constr
::
optimize
(
THD
*
thd
_arg
)
void
table_value_constr
::
optimize
(
THD
*
thd
)
{
create_explain_query_if_not_exists
(
thd
_arg
->
lex
,
thd_arg
->
mem_root
);
create_explain_query_if_not_exists
(
thd
->
lex
,
thd
->
mem_root
);
have_query_plan
=
QEP_AVAILABLE
;
if
(
select_lex
->
select_number
!=
UINT_MAX
&&
select_lex
->
select_number
!=
INT_MAX
/* this is not a UNION's "fake select */
&&
have_query_plan
!=
QEP_NOT_PRESENT_YET
&&
thd
_arg
->
lex
->
explain
&&
// for "SET" command in SPs.
(
!
thd
_arg
->
lex
->
explain
->
get_select
(
select_lex
->
select_number
)))
thd
->
lex
->
explain
&&
// for "SET" command in SPs.
(
!
thd
->
lex
->
explain
->
get_select
(
select_lex
->
select_number
)))
{
save_explain_data_intern
(
thd
_arg
,
thd_arg
->
lex
->
explain
);
save_explain_data_intern
(
thd
,
thd
->
lex
->
explain
);
}
}
...
...
@@ -290,7 +324,7 @@ bool table_value_constr::exec(SELECT_LEX *sl)
DBUG_RETURN
(
true
);
}
while
((
elem
=
li
++
))
while
((
elem
=
li
++
))
{
result
->
send_data
(
*
elem
);
}
...
...
@@ -301,52 +335,40 @@ bool table_value_constr::exec(SELECT_LEX *sl)
DBUG_RETURN
(
false
);
}
/**
@brief
Print list
of lists
Print list
@param str Where to print to
@param str The reference on the string representation of the list
@param list The list that needed to be print
@param query_type The mode of printing
@param values List of lists that needed to be print
@details
The method
prints a string representation of list of lists
in the
string str.
The parameter query_type specifies the mode of printing.
The method
saves a string representation of list
in the
string str.
*/
void
print_list_of_lists
(
String
*
str
,
enum_query_type
query_type
,
List
<
List_item
>
*
values
)
void
print_list_item
(
String
*
str
,
List_item
*
list
,
enum_query_type
query_type
)
{
str
->
append
(
STRING_WITH_LEN
(
"values "
));
bool
first
=
1
;
List_iterator_fast
<
List_item
>
li
(
*
values
);
List_item
*
list
;
while
((
list
=
li
++
))
{
if
(
first
)
first
=
0
;
else
str
->
append
(
','
);
str
->
append
(
'('
);
bool
is_first_elem
=
true
;
List_iterator_fast
<
Item
>
it
(
*
list
);
Item
*
item
;
first
=
1
;
while
((
item
=
it
++
))
str
->
append
(
'('
);
while
((
item
=
it
++
))
{
if
(
first
)
first
=
0
;
if
(
is_first_elem
)
is_first_elem
=
false
;
else
str
->
append
(
','
);
item
->
print
(
str
,
query_type
);
}
str
->
append
(
')'
);
}
}
...
...
@@ -354,21 +376,35 @@ void print_list_of_lists(String *str,
@brief
Print this TVC
@param thd
_arg
The context of the statement
@param str
Where to print to
@param thd
The context of the statement
@param str
The reference on the string representation of this TVC
@param query_type The mode of printing
@details
The method
print
s a string representation of this TVC in the
string str.
The parameter query_type specifies the mode of printing.
The method
save
s a string representation of this TVC in the
string str.
*/
void
table_value_constr
::
print
(
THD
*
thd
_arg
,
String
*
str
,
void
table_value_constr
::
print
(
THD
*
thd
,
String
*
str
,
enum_query_type
query_type
)
{
DBUG_ASSERT
(
thd_arg
);
DBUG_ASSERT
(
thd
);
str
->
append
(
STRING_WITH_LEN
(
"values "
));
bool
is_first_elem
=
true
;
List_iterator_fast
<
List_item
>
li
(
lists_of_values
);
List_item
*
list
;
while
((
list
=
li
++
))
{
if
(
is_first_elem
)
is_first_elem
=
false
;
else
str
->
append
(
','
);
print_list_of_lists
(
str
,
query_type
,
&
lists_of_values
);
print_list_item
(
str
,
list
,
query_type
);
}
}
...
...
@@ -428,6 +464,23 @@ bool Item_func_in::create_value_list_for_tvc(THD *thd,
}
/**
@brief
Create name for the derived table defined by TVC
@param thd The context of the statement
@param parent_select The SELECT where derived table is used
@param alias The returned created name
@details
Create name for the derived table using current TVC number
for this parent_select stored in parent_select
@retval
true if creation fails
false otherwise
*/
static
bool
create_tvc_name
(
THD
*
thd
,
st_select_lex
*
parent_select
,
LEX_CSTRING
*
alias
)
{
...
...
@@ -442,6 +495,7 @@ static bool create_tvc_name(THD *thd, st_select_lex *parent_select,
return
false
;
}
/**
@brief
Transform IN predicate into IN subquery
...
...
@@ -579,18 +633,19 @@ Item *Item_func_in::in_predicate_to_in_subs_transformer(THD *thd,
thd
->
restore_active_arena
(
arena
,
&
backup
);
lex
->
derived_tables
=
save_derived_tables
;
thd
->
lex
->
current_select
=
parent_select
;
return
this
;
return
NULL
;
}
/**
@brief
Check
s
if this IN-predicate can be transformed in IN-subquery
Check if this IN-predicate can be transformed in IN-subquery
with TVC
@param thd The context of the statement
@details
Compare
s
the number of elements in the list of
Compare the number of elements in the list of
values in this IN-predicate with the
in_subquery_conversion_threshold special variable
...
...
@@ -601,17 +656,18 @@ Item *Item_func_in::in_predicate_to_in_subs_transformer(THD *thd,
bool
Item_func_in
::
to_be_transformed_into_in_subq
(
THD
*
thd
)
{
uint
opt_can_be_used
=
arg_count
-
1
;
uint
values_count
=
arg_count
-
1
;
if
(
args
[
1
]
->
type
()
==
Item
::
ROW_ITEM
)
opt_can_be_used
*=
((
Item_row
*
)(
args
[
1
]))
->
cols
();
values_count
*=
((
Item_row
*
)(
args
[
1
]))
->
cols
();
if
(
opt_can_be_used
<
thd
->
variables
.
in_subquery_conversion_threshold
)
if
(
values_count
<
thd
->
variables
.
in_subquery_conversion_threshold
)
return
false
;
return
true
;
}
/**
@brief
Transform IN predicates into IN subqueries in WHERE and ON expressions
...
...
@@ -629,8 +685,9 @@ bool Item_func_in::to_be_transformed_into_in_subq(THD *thd)
bool
JOIN
::
transform_in_predicates_into_in_subq
(
THD
*
thd
)
{
DBUG_ENTER
(
"JOIN::transform_in_predicates_into_in_subq"
);
if
(
!
select_lex
->
in_funcs
.
elements
)
return
false
;
DBUG_RETURN
(
false
)
;
SELECT_LEX
*
save_current_select
=
thd
->
lex
->
current_select
;
enum_parsing_place
save_parsing_place
=
select_lex
->
parsing_place
;
...
...
@@ -642,6 +699,8 @@ bool JOIN::transform_in_predicates_into_in_subq(THD *thd)
conds
->
transform
(
thd
,
&
Item
::
in_predicate_to_in_subs_transformer
,
(
uchar
*
)
0
);
if
(
!
conds
)
DBUG_RETURN
(
true
);
select_lex
->
prep_where
=
conds
?
conds
->
copy_andor_structure
(
thd
)
:
0
;
select_lex
->
where
=
conds
;
}
...
...
@@ -660,6 +719,8 @@ bool JOIN::transform_in_predicates_into_in_subq(THD *thd)
table
->
on_expr
->
transform
(
thd
,
&
Item
::
in_predicate_to_in_subs_transformer
,
(
uchar
*
)
0
);
if
(
!
table
->
on_expr
)
DBUG_RETURN
(
true
);
table
->
prep_on_expr
=
table
->
on_expr
?
table
->
on_expr
->
copy_andor_structure
(
thd
)
:
0
;
}
...
...
@@ -669,5 +730,5 @@ bool JOIN::transform_in_predicates_into_in_subq(THD *thd)
select_lex
->
in_funcs
.
empty
();
select_lex
->
parsing_place
=
save_parsing_place
;
thd
->
lex
->
current_select
=
save_current_select
;
return
false
;
DBUG_RETURN
(
false
)
;
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment