summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2019-07-26 07:03:39 +0200
committerOleksandr Byelkin <sanja@mariadb.com>2019-07-26 07:03:39 +0200
commitcf8c2a3c3b2eb05df419ce014b98a71b1e75ad6b (patch)
tree0e9c8d48fda7b7494b5d3b220bc6af64e4f3e64a /sql
parentfc77a66c7eb1b8e90753814aa567daeaabd0dd90 (diff)
parent584d213235704113cf0d70319c0521d93b8744c6 (diff)
downloadmariadb-git-cf8c2a3c3b2eb05df419ce014b98a71b1e75ad6b.tar.gz
Merge branch '10.1' into 10.2
Diffstat (limited to 'sql')
-rw-r--r--sql/item.cc13
-rw-r--r--sql/item.h1
-rw-r--r--sql/item_func.cc1
-rw-r--r--sql/item_subselect.cc27
-rw-r--r--sql/item_xmlfunc.cc4
-rw-r--r--sql/item_xmlfunc.h3
-rw-r--r--sql/sql_acl.cc1
-rw-r--r--sql/sql_delete.cc3
-rw-r--r--sql/sql_insert.cc6
-rw-r--r--sql/sql_lex.cc5
-rw-r--r--sql/sql_lex.h25
-rw-r--r--sql/sql_parse.cc235
-rw-r--r--sql/sql_plugin.cc7
-rw-r--r--sql/sql_select.cc9
-rw-r--r--sql/sql_table.cc5
-rw-r--r--sql/sql_yacc.yy35
-rw-r--r--sql/table.h24
17 files changed, 348 insertions, 56 deletions
diff --git a/sql/item.cc b/sql/item.cc
index da4a3ee1e05..efedc1ec8d1 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -10697,11 +10697,14 @@ table_map Item_direct_view_ref::used_tables() const
table_map Item_direct_view_ref::not_null_tables() const
{
- return get_depended_from() ?
- 0 :
- ((view->is_merged_derived() || view->merged || !view->table) ?
- (*ref)->not_null_tables() :
- view->table->map);
+ if (get_depended_from())
+ return 0;
+ if (!( view->merged || !view->table))
+ return view->table->map;
+ TABLE *tab= get_null_ref_table();
+ if (tab == NO_NULL_TABLE || (*ref)->used_tables())
+ return (*ref)->not_null_tables();
+ return get_null_ref_table()->map;
}
/*
diff --git a/sql/item.h b/sql/item.h
index 326b1a0f867..49762d3326f 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -4832,6 +4832,7 @@ public:
void update_used_tables();
table_map not_null_tables() const;
bool const_item() const { return used_tables() == 0; }
+ TABLE *get_null_ref_table() const { return null_ref_table; }
bool walk(Item_processor processor, bool walk_subquery, void *arg)
{
return (*ref)->walk(processor, walk_subquery, arg) ||
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 6b3373f0795..5ff1b26d734 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -222,6 +222,7 @@ Item_func::fix_fields(THD *thd, Item **ref)
with_window_func= with_window_func || item->with_window_func;
with_field= with_field || item->with_field;
used_tables_and_const_cache_join(item);
+ not_null_tables_cache|= item->not_null_tables();
with_subselect|= item->has_subquery();
}
}
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 6140097891b..2e023658baf 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -1518,16 +1518,23 @@ bool Item_exists_subselect::fix_length_and_dec()
{
DBUG_ENTER("Item_exists_subselect::fix_length_and_dec");
init_length_and_dec();
- /*
- We need only 1 row to determine existence (i.e. any EXISTS that is not
- an IN always requires LIMIT 1)
- */
- Item *item= new (thd->mem_root) Item_int(thd, (int32) 1);
- if (!item)
- DBUG_RETURN(TRUE);
- thd->change_item_tree(&unit->global_parameters()->select_limit,
- item);
- DBUG_PRINT("info", ("Set limit to 1"));
+ // If limit is not set or it is constant more than 1
+ if (!unit->global_parameters()->select_limit ||
+ (unit->global_parameters()->select_limit->basic_const_item() &&
+ unit->global_parameters()->select_limit->val_int() > 1))
+ {
+ /*
+ We need only 1 row to determine existence (i.e. any EXISTS that is not
+ an IN always requires LIMIT 1)
+ */
+ Item *item= new (thd->mem_root) Item_int(thd, (int32) 1);
+ if (!item)
+ DBUG_RETURN(TRUE);
+ thd->change_item_tree(&unit->global_parameters()->select_limit,
+ item);
+ unit->global_parameters()->explicit_limit= 1; // we set the limit
+ DBUG_PRINT("info", ("Set limit to 1"));
+ }
DBUG_RETURN(FALSE);
}
diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc
index 7fa9f6a8c22..0e62e29bfe2 100644
--- a/sql/item_xmlfunc.cc
+++ b/sql/item_xmlfunc.cc
@@ -1,5 +1,5 @@
-/* Copyright (c) 2005, 2016, Oracle and/or its affiliates.
- Copyright (c) 2009, 2017, MariaDB
+/* Copyright (c) 2005, 2019, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2019, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/item_xmlfunc.h b/sql/item_xmlfunc.h
index 692b7a4249e..e00f071fc0c 100644
--- a/sql/item_xmlfunc.h
+++ b/sql/item_xmlfunc.h
@@ -1,8 +1,7 @@
#ifndef ITEM_XMLFUNC_INCLUDED
#define ITEM_XMLFUNC_INCLUDED
-/* Copyright (c) 2000-2007 MySQL AB, 2009 Sun Microsystems, Inc.
- Use is subject to license terms.
+/* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 6d339b81ce2..eb84368bf9f 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -12282,6 +12282,7 @@ static bool send_plugin_request_packet(MPVIO_EXT *mpvio,
((st_mysql_auth *) (plugin_decl(mpvio->plugin)->info))->client_auth_plugin;
DBUG_EXECUTE_IF("auth_disconnect", { DBUG_RETURN(1); });
+ DBUG_EXECUTE_IF("auth_invalid_plugin", client_auth_plugin="foo/bar"; );
DBUG_ASSERT(client_auth_plugin);
/*
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index b8e158d39c3..e2d4cd47580 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2010, Oracle and/or its affiliates.
+ Copyright (c) 2000, 2019, Oracle and/or its affiliates.
Copyright (c) 2010, 2019, MariaDB
This program is free software; you can redistribute it and/or modify
@@ -1330,6 +1330,7 @@ bool multi_delete::send_eof()
thd->clear_error();
else
errcode= query_error_code(thd, killed_status == NOT_KILLED);
+ thd->thread_specific_used= TRUE;
if (thd->binlog_query(THD::ROW_QUERY_TYPE,
thd->query(), thd->query_length(),
transactional_tables, FALSE, FALSE, errcode) &&
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index e2e7454803b..bc9567f9c67 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -3947,8 +3947,12 @@ void select_insert::abort_result_set() {
example), no table will have been opened and therefore 'table'
will be NULL. In that case, we still need to execute the rollback
and the end of the function.
+
+ If it fail due to inability to insert in multi-table view for example,
+ table will be assigned with view table structure, but that table will
+ not be opened really (it is dummy to check fields types & Co).
*/
- if (table)
+ if (table && table->file->get_table())
{
bool changed, transactional_table;
/*
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 53b1dd481c3..a6bc4e171da 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -2797,14 +2797,13 @@ void st_select_lex::print_limit(THD *thd,
if (item && unit->global_parameters() == this)
{
Item_subselect::subs_type subs_type= item->substype();
- if (subs_type == Item_subselect::EXISTS_SUBS ||
- subs_type == Item_subselect::IN_SUBS ||
+ if (subs_type == Item_subselect::IN_SUBS ||
subs_type == Item_subselect::ALL_SUBS)
{
return;
}
}
- if (explicit_limit)
+ if (explicit_limit && select_limit)
{
str->append(STRING_WITH_LEN(" limit "));
if (offset_limit)
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 9a49e4024fe..65bce5d2579 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -1,5 +1,5 @@
-/* Copyright (c) 2000, 2015, Oracle and/or its affiliates.
- Copyright (c) 2010, 2018, MariaDB Corporation
+/* Copyright (c) 2000, 2019, Oracle and/or its affiliates.
+ Copyright (c) 2010, 2019, MariaDB Corporation
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1023,6 +1023,8 @@ public:
TABLE_LIST *end_nested_join(THD *thd);
TABLE_LIST *nest_last_join(THD *thd);
void add_joined_table(TABLE_LIST *table);
+ bool add_cross_joined_table(TABLE_LIST *left_op, TABLE_LIST *right_op,
+ bool straight_fl);
TABLE_LIST *convert_right_join();
List<Item>* get_item_list();
ulong get_table_join_options();
@@ -3040,9 +3042,9 @@ public:
return context_stack.push_front(context, mem_root);
}
- void pop_context()
+ Name_resolution_context *pop_context()
{
- context_stack.pop();
+ return context_stack.pop();
}
bool copy_db_to(char **p_db, size_t *p_db_length) const;
@@ -3260,15 +3262,18 @@ public:
class Yacc_state
{
public:
- Yacc_state()
- {
- reset();
- }
+ Yacc_state() : yacc_yyss(NULL), yacc_yyvs(NULL) { reset(); }
void reset()
{
- yacc_yyss= NULL;
- yacc_yyvs= NULL;
+ if (yacc_yyss != NULL) {
+ my_free(yacc_yyss);
+ yacc_yyss = NULL;
+ }
+ if (yacc_yyvs != NULL) {
+ my_free(yacc_yyvs);
+ yacc_yyvs = NULL;
+ }
m_set_signal_info.clear();
m_lock_type= TL_READ_DEFAULT;
m_mdl_type= MDL_SHARED_READ;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 6e2c38ad053..bc3cd4c2bfd 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -8123,6 +8123,7 @@ TABLE_LIST *st_select_lex::end_nested_join(THD *thd)
join_list= ptr->join_list;
embedding= ptr->embedding;
nested_join= ptr->nested_join;
+ nested_join->nest_type= 0;
if (nested_join->join_list.elements == 1)
{
TABLE_LIST *embedded= nested_join->join_list.head();
@@ -8132,6 +8133,8 @@ TABLE_LIST *st_select_lex::end_nested_join(THD *thd)
join_list->push_front(embedded, thd->mem_root);
ptr= embedded;
embedded->lifted= 1;
+ if (embedded->nested_join)
+ embedded->nested_join->nest_type= 0;
}
else if (nested_join->join_list.elements == 0)
{
@@ -8162,6 +8165,16 @@ TABLE_LIST *st_select_lex::nest_last_join(THD *thd)
List<TABLE_LIST> *embedded_list;
DBUG_ENTER("nest_last_join");
+ TABLE_LIST *head= join_list->head();
+ if (head->nested_join && head->nested_join->nest_type & REBALANCED_NEST)
+ {
+ List_iterator<TABLE_LIST> li(*join_list);
+ li++;
+ while (li++)
+ li.remove();
+ DBUG_RETURN(head);
+ }
+
if (!(ptr= (TABLE_LIST*) thd->calloc(ALIGN_SIZE(sizeof(TABLE_LIST))+
sizeof(NESTED_JOIN))))
DBUG_RETURN(0);
@@ -8173,6 +8186,7 @@ TABLE_LIST *st_select_lex::nest_last_join(THD *thd)
ptr->alias= (char*) "(nest_last_join)";
embedded_list= &nested_join->join_list;
embedded_list->empty();
+ nested_join->nest_type= JOIN_OP_NEST;
for (uint i=0; i < 2; i++)
{
@@ -8224,6 +8238,227 @@ void st_select_lex::add_joined_table(TABLE_LIST *table)
/**
+ @brief
+ Create a node for JOIN/INNER JOIN/CROSS JOIN/STRAIGHT_JOIN operation
+
+ @param left_op the node for the left operand constructed by the parser
+ @param right_op the node for the right operand constructed by the parser
+ @param straight_fl TRUE if STRAIGHT_JOIN is used
+
+ @retval
+ false on success
+ true otherwise
+
+ @details
+
+ JOIN operator can be left-associative with other join operators in one
+ context and right-associative in another context.
+
+ In this query
+ SELECT * FROM t1 JOIN t2 LEFT JOIN t3 ON t2.a=t3.a (Q1)
+ JOIN is left-associative and the query Q1 is interpreted as
+ SELECT * FROM (t1 JOIN t2) LEFT JOIN t3 ON t2.a=t3.a.
+ While in this query
+ SELECT * FROM t1 JOIN t2 LEFT JOIN t3 ON t2.a=t3.a ON t1.b=t2.b (Q2)
+ JOIN is right-associative and the query Q2 is interpreted as
+ SELECT * FROM t1 JOIN (t2 LEFT JOIN t3 ON t2.a=t3.a) ON t1.b=t2.b
+
+ JOIN is right-associative if it is used with ON clause or with USING clause.
+ Otherwise it is left-associative.
+ When parsing a join expression with JOIN operator we can't determine
+ whether this operation left or right associative until either we read the
+ corresponding ON clause or we reach the end of the expression. This creates
+ a problem for the parser to build a proper internal representation of the
+ used join expression.
+
+ For Q1 and Q2 the trees representing the used join expressions look like
+
+ LJ - ON J - ON
+ / \ / \
+ J t3 (TQ1) t1 LJ - ON (TQ2)
+ / \ / \
+ t1 t2 t2 t3
+
+ To build TQ1 the parser has to reduce the expression for JOIN right after
+ it has read the reference to t2. To build TQ2 the parser reduces JOIN
+ when he has read the whole join expression. There is no way to determine
+ whether an early reduction is needed until the whole join expression is
+ read.
+ A solution here is always to do a late reduction. In this case the parser
+ first builds an incorrect tree TQ1* that has to be rebalanced right after
+ it has been constructed.
+
+ J LJ - ON
+ / \ / \
+ t1 LJ - ON (TQ1*) => J t3
+ / \ / \
+ t2 t3 t1 t2
+
+ Actually the transformation is performed over the nodes t1 and LJ before the
+ node for J is created in the function st_select_lex::add_cross_joined_table.
+ The function creates a node for J which replaces the node t2. Then it
+ attaches the nodes t1 and t2 to this newly created node. The node LJ becomes
+ the top node of the tree.
+
+ For the query
+ SELECT * FROM t1 JOIN t2 RIGHT JOIN t3 ON t2.a=t3.a (Q3)
+ the transformation looks slightly differently because the parser
+ replaces the RIGHT JOIN tree for an equivalent LEFT JOIN tree.
+
+ J LJ - ON
+ / \ / \
+ t1 LJ - ON (TQ3*) => J t2
+ / \ / \
+ t3 t2 t1 t3
+
+ With several left associative JOINs
+ SELECT * FROM t1 JOIN t2 JOIN t3 LEFT JOIN t4 ON t3.a=t4.a (Q4)
+ the newly created node for JOIN replaces the left most node of the tree:
+
+ J1 LJ - ON
+ / \ / \
+ t1 LJ - ON J2 t4
+ / \ => / \
+ J2 t4 J1 t3
+ / \ / \
+ t2 t3 t1 t2
+
+ Here's another example:
+ SELECT *
+ FROM t1 JOIN t2 LEFT JOIN t3 JOIN t4 ON t3.a=t4.a ON t2.b=t3.b (Q5)
+
+ J LJ - ON
+ / \ / \
+ t1 LJ - ON J J - ON
+ / \ => / \ / \
+ t2 J - ON t1 t2 t3 t4
+ / \
+ t3 t4
+
+ If the transformed nested join node node is a natural join node like in
+ the following query
+ SELECT * FROM t1 JOIN t2 LEFT JOIN t3 USING(a) (Q6)
+ the transformation additionally has to take care about setting proper
+ references in the field natural_join for both operands of the natural
+ join operation.
+ The function also has to change the name resolution context for ON
+ expressions used in the transformed join expression to take into
+ account the tables of the left_op node.
+*/
+
+bool st_select_lex::add_cross_joined_table(TABLE_LIST *left_op,
+ TABLE_LIST *right_op,
+ bool straight_fl)
+{
+ DBUG_ENTER("add_cross_joined_table");
+ THD *thd= parent_lex->thd;
+ if (!(right_op->nested_join &&
+ (right_op->nested_join->nest_type & JOIN_OP_NEST)))
+ {
+ /*
+ This handles the cases when the right operand is not a nested join.
+ like in queries
+ SELECT * FROM t1 JOIN t2;
+ SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.a JOIN t3
+ */
+ right_op->straight= straight_fl;
+ DBUG_RETURN(false);
+ }
+
+ TABLE_LIST *tbl;
+ List<TABLE_LIST> *jl= &right_op->nested_join->join_list;
+ TABLE_LIST *cj_nest;
+
+ /*
+ Create the node NJ for a new nested join for the future inclusion
+ of left_op in it. Initially the nest is empty.
+ */
+ if (unlikely(!(cj_nest=
+ (TABLE_LIST*) thd->calloc(ALIGN_SIZE(sizeof(TABLE_LIST))+
+ sizeof(NESTED_JOIN)))))
+ DBUG_RETURN(true);
+ cj_nest->nested_join=
+ ((NESTED_JOIN*) ((uchar*) cj_nest + ALIGN_SIZE(sizeof(TABLE_LIST))));
+ cj_nest->nested_join->nest_type= JOIN_OP_NEST;
+ List<TABLE_LIST> *cjl= &cj_nest->nested_join->join_list;
+ cjl->empty();
+
+ /* Look for the left most node tbl of the right_op tree */
+ for ( ; ; )
+ {
+ TABLE_LIST *pair_tbl= 0; /* useful only for operands of natural joins */
+
+ List_iterator<TABLE_LIST> li(*jl);
+ tbl= li++;
+
+ /* Expand name resolution context */
+ Name_resolution_context *on_context;
+ if ((on_context= tbl->on_context))
+ {
+ on_context->first_name_resolution_table=
+ left_op->first_leaf_for_name_resolution();
+ }
+
+ if (!(tbl->outer_join & JOIN_TYPE_RIGHT))
+ {
+ pair_tbl= tbl;
+ tbl= li++;
+ }
+ if (tbl->nested_join &&
+ tbl->nested_join->nest_type & JOIN_OP_NEST)
+ {
+ jl= &tbl->nested_join->join_list;
+ continue;
+ }
+
+ /* Replace the tbl node in the tree for the newly created NJ node */
+ cj_nest->outer_join= tbl->outer_join;
+ cj_nest->on_expr= tbl->on_expr;
+ cj_nest->embedding= tbl->embedding;
+ cj_nest->join_list= jl;
+ cj_nest->alias= (char*) "(nest_last_join)";
+ li.replace(cj_nest);
+
+ /*
+ If tbl is an operand of a natural join set properly the references
+ in the fields natural_join for both operands of the operation.
+ */
+ if(tbl->embedding && tbl->embedding->is_natural_join)
+ {
+ if (!pair_tbl)
+ pair_tbl= li++;
+ pair_tbl->natural_join= cj_nest;
+ cj_nest->natural_join= pair_tbl;
+ }
+ break;
+ }
+
+ /* Attach tbl as the right operand of NJ */
+ if (unlikely(cjl->push_back(tbl, thd->mem_root)))
+ DBUG_RETURN(true);
+ tbl->outer_join= 0;
+ tbl->on_expr= 0;
+ tbl->straight= straight_fl;
+ tbl->natural_join= 0;
+ tbl->embedding= cj_nest;
+ tbl->join_list= cjl;
+
+ /* Add left_op as the left operand of NJ */
+ if (unlikely(cjl->push_back(left_op, thd->mem_root)))
+ DBUG_RETURN(true);
+ left_op->embedding= cj_nest;
+ left_op->join_list= cjl;
+
+ /*
+ Mark right_op as a rebalanced nested join in order not to
+ create a new top level nested join node.
+ */
+ right_op->nested_join->nest_type|= REBALANCED_NEST;
+ DBUG_RETURN(false);
+}
+
+
+/**
Convert a right join into equivalent left join.
The function takes the current join list t[0],t[1] ... and
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index 19c0f508939..44b2a8220b3 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -748,9 +748,9 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
This is done to ensure that only approved libraries from the
plugin directory are used (to make this even remotely secure).
*/
- if (check_valid_path(dl->str, dl->length) ||
- check_string_char_length((LEX_STRING *) dl, 0, NAME_CHAR_LEN,
+ if (check_string_char_length((LEX_STRING *) dl, 0, NAME_CHAR_LEN,
system_charset_info, 1) ||
+ check_valid_path(dl->str, dl->length) ||
plugin_dir_len + dl->length + 1 >= FN_REFLEN)
{
report_error(report, ER_UDF_NO_PATHS);
@@ -1826,6 +1826,9 @@ static void plugin_load(MEM_ROOT *tmp_root)
LEX_STRING name= {(char *)str_name.ptr(), str_name.length()};
LEX_STRING dl= {(char *)str_dl.ptr(), str_dl.length()};
+ if (!name.length || !dl.length)
+ continue;
+
/*
there're no other threads running yet, so we don't need a mutex.
but plugin_add() before is designed to work in multi-threaded
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index a1685508d18..bdab9cf76cf 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1262,7 +1262,6 @@ JOIN::optimize_inner()
DBUG_RETURN(1); /* purecov: inspected */
/* dump_TABLE_LIST_graph(select_lex, select_lex->leaf_tables); */
select_lex->update_used_tables();
-
}
eval_select_list_used_tables();
@@ -1332,6 +1331,8 @@ JOIN::optimize_inner()
sel->where= conds;
+ select_lex->update_used_tables();
+
if (arena)
thd->restore_active_arena(arena, &backup);
}
@@ -13074,6 +13075,9 @@ static bool check_simple_equality(THD *thd, const Item::Context &ctx,
{
if (((Item_ref*)left_item)->get_depended_from())
return FALSE;
+ if (((Item_direct_view_ref*)left_item)->get_null_ref_table() !=
+ NO_NULL_TABLE && !left_item->real_item()->used_tables())
+ return FALSE;
left_item= left_item->real_item();
}
if (right_item->type() == Item::REF_ITEM &&
@@ -13081,6 +13085,9 @@ static bool check_simple_equality(THD *thd, const Item::Context &ctx,
{
if (((Item_ref*)right_item)->get_depended_from())
return FALSE;
+ if (((Item_direct_view_ref*)right_item)->get_null_ref_table() !=
+ NO_NULL_TABLE && !right_item->real_item()->used_tables())
+ return FALSE;
right_item= right_item->real_item();
}
if (left_item->type() == Item::FIELD_ITEM &&
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index bbc8cc4be01..fbd6622b1b2 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+ Copyright (c) 2000, 2019, Oracle and/or its affiliates.
Copyright (c) 2010, 2019, MariaDB
This program is free software; you can redistribute it and/or modify
@@ -2522,8 +2522,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
table->table ? table->table->s : NULL));
}
DEBUG_SYNC(thd, "rm_table_no_locks_before_binlog");
- thd->thread_specific_used|= (trans_tmp_table_deleted ||
- non_trans_tmp_table_deleted);
+ thd->thread_specific_used= TRUE;
error= 0;
err:
if (wrong_tables.length())
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 90acbb94f8c..b5cece45148 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1025,7 +1025,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
Currently there are 102 shift/reduce conflicts.
We should not introduce new conflicts any more.
*/
-%expect 102
+%expect 101
/*
Comments for TOKENS.
@@ -1714,9 +1714,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token IMPOSSIBLE_ACTION /* To avoid warning for yyerrlab1 */
-%left JOIN_SYM INNER_SYM STRAIGHT_JOIN CROSS LEFT RIGHT
/* A dummy token to force the priority of table_ref production in a join. */
-%left TABLE_REF_PRIORITY
+%left CONDITIONLESS_JOIN
+%left JOIN_SYM INNER_SYM STRAIGHT_JOIN CROSS LEFT RIGHT ON_SYM USING
%left SET_VAR
%left OR_OR_SYM OR_SYM OR2_SYM
%left XOR
@@ -10817,9 +10817,9 @@ join_table_list:
and are ignored.
*/
esc_table_ref:
- table_ref { $$=$1; }
- | '{' ident table_ref '}' { $$=$3; }
- ;
+ table_ref { $$=$1; }
+ | '{' ident table_ref '}' { $$=$3; }
+ ;
/* Equivalent to <table reference list> in the SQL:2003 standard. */
/* Warning - may return NULL in case of incomplete SELECT */
@@ -10832,11 +10832,9 @@ derived_table_list:
;
/*
- Notice that JOIN is a left-associative operation, and it must be parsed
- as such, that is, the parser must process first the left join operand
- then the right one. Such order of processing ensures that the parser
- produces correct join trees which is essential for semantic analysis
- and subsequent optimization phases.
+ Notice that JOIN can be a left-associative operator in one context and
+ a right-associative operator in another context (see the comment for
+ st_select_lex::add_cross_joined_table).
*/
join_table:
/* INNER JOIN variants */
@@ -10845,8 +10843,13 @@ join_table:
so that [INNER | CROSS] JOIN is properly nested as other
left-associative joins.
*/
- table_ref normal_join table_ref %prec TABLE_REF_PRIORITY
- { MYSQL_YYABORT_UNLESS($1 && ($$=$3)); $3->straight=$2; }
+ table_ref normal_join table_ref %prec CONDITIONLESS_JOIN
+ {
+ MYSQL_YYABORT_UNLESS($1 && ($$=$3));
+
+ if (unlikely(Select->add_cross_joined_table($1, $3, $2)))
+ MYSQL_YYABORT;
+ }
| table_ref normal_join table_ref
ON
{
@@ -10860,7 +10863,7 @@ join_table:
{
$3->straight=$2;
add_join_on(thd, $3, $6);
- Lex->pop_context();
+ $3->on_context= Lex->pop_context();
Select->parsing_place= NO_MATTER;
}
| table_ref normal_join table_ref
@@ -10894,7 +10897,7 @@ join_table:
expr
{
add_join_on(thd, $5, $8);
- Lex->pop_context();
+ $5->on_context= Lex->pop_context();
$5->outer_join|=JOIN_TYPE_LEFT;
$$=$5;
Select->parsing_place= NO_MATTER;
@@ -10933,7 +10936,7 @@ join_table:
if (!($$= lex->current_select->convert_right_join()))
MYSQL_YYABORT;
add_join_on(thd, $$, $8);
- Lex->pop_context();
+ $1->on_context= Lex->pop_context();
Select->parsing_place= NO_MATTER;
}
| table_ref RIGHT opt_outer JOIN_SYM table_factor
diff --git a/sql/table.h b/sql/table.h
index 444e1c5f00f..7786679982f 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -54,6 +54,7 @@ struct TDC_element;
class Virtual_column_info;
class Table_triggers_list;
class TMP_TABLE_PARAM;
+struct Name_resolution_context;
/*
Used to identify NESTED_JOIN structures within a join (applicable only to
@@ -1819,6 +1820,7 @@ struct TABLE_LIST
char *db, *alias, *table_name, *schema_table_name;
char *option; /* Used by cache index */
Item *on_expr; /* Used with outer join */
+ Name_resolution_context *on_context; /* For ON expressions */
Item *sj_on_expr;
/*
@@ -2563,9 +2565,31 @@ public:
};
+#define JOIN_OP_NEST 1
+#define REBALANCED_NEST 2
+
typedef struct st_nested_join
{
List<TABLE_LIST> join_list; /* list of elements in the nested join */
+ /*
+ Currently the valid values for nest type are:
+ JOIN_OP_NEST - for nest created for JOIN operation used as an operand in
+ a join expression, contains 2 elements;
+ JOIN_OP_NEST | REBALANCED_NEST - nest created after tree re-balancing
+ in st_select_lex::add_cross_joined_table(), contains 1 element;
+ 0 - for all other nests.
+ Examples:
+ 1. SELECT * FROM t1 JOIN t2 LEFT JOIN t3 ON t2.a=t3.a;
+ Here the nest created for LEFT JOIN at first has nest_type==JOIN_OP_NEST.
+ After re-balancing in st_select_lex::add_cross_joined_table() this nest
+ has nest_type==JOIN_OP_NEST | REBALANCED_NEST. The nest for JOIN created
+ in st_select_lex::add_cross_joined_table() has nest_type== JOIN_OP_NEST.
+ 2. SELECT * FROM t1 JOIN (t2 LEFT JOIN t3 ON t2.a=t3.a)
+ Here the nest created for LEFT JOIN has nest_type==0, because it's not
+ an operand in a join expression. The nest created for JOIN has nest_type
+ set to JOIN_OP_NEST.
+ */
+ uint nest_type;
/*
Bitmap of tables within this nested join (including those embedded within
its children), including tables removed by table elimination.