1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

Merge remote-tracking branch 'origin/bb-10.2-ext' into 10.3

TODO: enable MDEV-13049 optimization for 10.3
This commit is contained in:
Alexander Barkov
2017-10-30 20:47:39 +04:00
644 changed files with 35267 additions and 4099 deletions

View File

@ -2386,6 +2386,30 @@ st_select_lex_node *st_select_lex_node:: insert_chain_before(
return this;
}
/*
Detach the node from its master and attach it to a new master
*/
void st_select_lex_node::move_as_slave(st_select_lex_node *new_master)
{
exclude_from_tree();
if (new_master->slave)
{
st_select_lex_node *curr= new_master->slave;
for ( ; curr->next ; curr= curr->next) ;
prev= &curr->next;
}
else
{
prev= &new_master->slave;
new_master->slave= this;
}
next= 0;
master= new_master;
}
/*
Exclude a node from the tree lex structure, but leave it in the global
list of nodes.
@ -4495,7 +4519,8 @@ void st_select_lex::set_explain_type(bool on_the_fly)
pos_in_table_list=NULL for e.g. post-join aggregation JOIN_TABs.
*/
if (tab->table && tab->table->pos_in_table_list &&
tab->table->pos_in_table_list->with)
tab->table->pos_in_table_list->with &&
tab->table->pos_in_table_list->with->is_recursive)
{
uses_cte= true;
break;
@ -5208,15 +5233,73 @@ void LEX::sp_variable_declarations_init(THD *thd, int nvars)
thd->variables.collation_database);
}
bool LEX::sp_variable_declarations_finalize(THD *thd, int nvars,
const Column_definition *cdef,
Row_definition_list *row,
Item *dflt_value_item)
bool LEX::sp_variable_declarations_set_default(THD *thd, int nvars,
Item *dflt_value_item)
{
if (!dflt_value_item &&
!(dflt_value_item= new (thd->mem_root) Item_null(thd)))
return true;
for (uint i= 0 ; i < (uint) nvars ; i++)
{
sp_variable *spvar= spcont->get_last_context_variable((uint) nvars - 1 - i);
bool last= i + 1 == (uint) nvars;
spvar->default_value= dflt_value_item;
/* The last instruction is responsible for freeing LEX. */
sp_instr_set *is= new (this->thd->mem_root)
sp_instr_set(sphead->instructions(),
spcont, spvar->offset, dflt_value_item,
this, last);
if (is == NULL || sphead->add_instr(is))
return true;
}
return false;
}
bool
LEX::sp_variable_declarations_copy_type_finalize(THD *thd, int nvars,
const Column_definition &ref,
Row_definition_list *fields,
Item *default_value)
{
for (uint i= 0 ; i < (uint) nvars; i++)
{
sp_variable *spvar= spcont->get_last_context_variable((uint) nvars - 1 - i);
spvar->field_def.set_type(ref);
if (fields)
{
DBUG_ASSERT(ref.type_handler() == &type_handler_row);
spvar->field_def.set_row_field_definitions(fields);
}
spvar->field_def.field_name= spvar->name;
}
if (sp_variable_declarations_set_default(thd, nvars, default_value))
return true;
spcont->declare_var_boundary(0);
return sphead->restore_lex(thd);
}
bool LEX::sp_variable_declarations_finalize(THD *thd, int nvars,
const Column_definition *cdef,
Item *dflt_value_item)
{
DBUG_ASSERT(cdef);
Column_definition tmp(*cdef);
if (sphead->fill_spvar_definition(thd, &tmp))
return true;
return sp_variable_declarations_copy_type_finalize(thd, nvars, tmp, NULL,
dflt_value_item);
}
bool LEX::sp_variable_declarations_row_finalize(THD *thd, int nvars,
Row_definition_list *row,
Item *dflt_value_item)
{
DBUG_ASSERT(row);
/*
Prepare all row fields.
Note, we do it only one time outside of the below loop.
@ -5229,37 +5312,19 @@ bool LEX::sp_variable_declarations_finalize(THD *thd, int nvars,
...
END;
*/
if (row && sphead->row_fill_field_definitions(thd, row))
if (sphead->row_fill_field_definitions(thd, row))
return true;
for (uint i= 0 ; i < (uint) nvars ; i++)
{
sp_variable *spvar= spcont->get_last_context_variable((uint) nvars - 1 - i);
bool last= i + 1 == (uint) nvars;
if (!spvar)
return true;
spvar->default_value= dflt_value_item;
if (cdef)
{
if (!last)
spvar->field_def.set_column_definition(cdef);
}
if (sphead->fill_spvar_definition(thd, &spvar->field_def, &spvar->name))
return true;
spvar->field_def.set_row_field_definitions(row);
/* The last instruction is responsible for freeing LEX. */
sp_instr_set *is= new (this->thd->mem_root)
sp_instr_set(sphead->instructions(),
spcont, spvar->offset, dflt_value_item,
this, last);
if (is == NULL || sphead->add_instr(is))
if (sphead->fill_spvar_definition(thd, &spvar->field_def, &spvar->name))
return true;
}
if (sp_variable_declarations_set_default(thd, nvars, dflt_value_item))
return true;
spcont->declare_var_boundary(0);
return sphead->restore_lex(thd);
}
@ -5283,57 +5348,45 @@ LEX::sp_variable_declarations_rowtype_finalize(THD *thd, int nvars,
const sp_pcursor *pcursor= ref->table.str && ref->db.str ? NULL :
spcont->find_cursor(&ref->m_column, &coffp,
false);
if (pcursor)
return sp_variable_declarations_cursor_rowtype_finalize(thd, nvars,
coffp, def);
/*
When parsing a qualified identifier chain, the parser does not know yet
if it's going to be a qualified column name (for %TYPE),
or a qualified table name (for %ROWTYPE). So it collects the chain
into Qualified_column_ident.
Now we know that it was actually a qualified table name (%ROWTYPE).
Create a new Table_ident from Qualified_column_ident,
shifting fields as follows:
- ref->m_column becomes table_ref->table
- ref->table becomes table_ref->db
*/
return sp_variable_declarations_table_rowtype_finalize(thd, nvars,
ref->table,
ref->m_column,
def);
}
if (!def && !(def= new (thd->mem_root) Item_null(thd)))
bool
LEX::sp_variable_declarations_table_rowtype_finalize(THD *thd, int nvars,
const LEX_CSTRING &db,
const LEX_CSTRING &table,
Item *def)
{
Table_ident *table_ref;
if (!(table_ref= new (thd->mem_root) Table_ident(thd, &db, &table, false)))
return true;
// Loop through all variables in the same declaration
for (uint i= 0 ; i < (uint) nvars; i++)
{
bool last= i + 1 == (uint) nvars;
sp_variable *spvar= spcont->get_last_context_variable((uint) nvars - 1 - i);
if (pcursor)
{
spvar->field_def.set_cursor_rowtype_ref(true);
sp_instr_cursor_copy_struct *instr=
new (thd->mem_root) sp_instr_cursor_copy_struct(sphead->instructions(),
spcont, pcursor->lex(),
spvar->offset);
if (instr == NULL || sphead->add_instr(instr))
return true;
}
else
{
/*
When parsing a qualified identifier chain, the parser does not know yet
if it's going to be a qualified column name (for %TYPE),
or a qualified table name (for %ROWTYPE). So it collects the chain
into Qualified_column_ident.
Now we know that it was actually a qualified table name (%ROWTYPE).
Create a new Table_ident from Qualified_column_ident,
shifting fields as follows:
- ref->m_column becomes table_ref->table
- ref->table becomes table_ref->db
*/
Table_ident *table_ref;
if (!(table_ref= new (thd->mem_root) Table_ident(thd,
&ref->table,
&ref->m_column,
false)))
return true;
spvar->field_def.set_table_rowtype_ref(table_ref);
}
spvar->field_def.set_table_rowtype_ref(table_ref);
sphead->fill_spvar_definition(thd, &spvar->field_def, &spvar->name);
spvar->default_value= def;
/* The last instruction is responsible for freeing LEX. */
sp_instr_set *is= new (this->thd->mem_root)
sp_instr_set(sphead->instructions(),
spcont, spvar->offset, def,
this, last);
if (is == NULL || sphead->add_instr(is))
return true;
}
if (sp_variable_declarations_set_default(thd, nvars, def))
return true;
// Make sure sp_rcontext is created using the invoker security context:
sphead->m_flags|= sp_head::HAS_COLUMN_TYPE_REFS;
spcont->declare_var_boundary(0);
@ -5341,10 +5394,58 @@ LEX::sp_variable_declarations_rowtype_finalize(THD *thd, int nvars,
}
bool
LEX::sp_variable_declarations_cursor_rowtype_finalize(THD *thd, int nvars,
uint offset,
Item *def)
{
const sp_pcursor *pcursor= spcont->find_cursor(offset);
// Loop through all variables in the same declaration
for (uint i= 0 ; i < (uint) nvars; i++)
{
sp_variable *spvar= spcont->get_last_context_variable((uint) nvars - 1 - i);
spvar->field_def.set_cursor_rowtype_ref(offset);
sp_instr_cursor_copy_struct *instr=
new (thd->mem_root) sp_instr_cursor_copy_struct(sphead->instructions(),
spcont, pcursor->lex(),
spvar->offset);
if (instr == NULL || sphead->add_instr(instr))
return true;
sphead->fill_spvar_definition(thd, &spvar->field_def, &spvar->name);
}
if (sp_variable_declarations_set_default(thd, nvars, def))
return true;
// Make sure sp_rcontext is created using the invoker security context:
sphead->m_flags|= sp_head::HAS_COLUMN_TYPE_REFS;
spcont->declare_var_boundary(0);
return sphead->restore_lex(thd);
}
/*
Add declarations for table column and SP variable anchor types:
- DECLARE spvar1 TYPE OF db1.table1.column1;
- DECLARE spvar1 TYPE OF table1.column1;
- DECLARE spvar1 TYPE OF spvar0;
*/
bool
LEX::sp_variable_declarations_with_ref_finalize(THD *thd, int nvars,
Qualified_column_ident *ref,
Item *def)
{
return ref->db.length == 0 && ref->table.length == 0 ?
sp_variable_declarations_vartype_finalize(thd, nvars, ref->m_column, def) :
sp_variable_declarations_column_type_finalize(thd, nvars, ref, def);
}
bool
LEX::sp_variable_declarations_column_type_finalize(THD *thd, int nvars,
Qualified_column_ident *ref,
Item *def)
{
for (uint i= 0 ; i < (uint) nvars; i++)
{
@ -5353,7 +5454,55 @@ LEX::sp_variable_declarations_with_ref_finalize(THD *thd, int nvars,
spvar->field_def.field_name= spvar->name;
}
sphead->m_flags|= sp_head::HAS_COLUMN_TYPE_REFS;
return sp_variable_declarations_finalize(thd, nvars, NULL, NULL, def);
if (sp_variable_declarations_set_default(thd, nvars, def))
return true;
spcont->declare_var_boundary(0);
return sphead->restore_lex(thd);
}
bool
LEX::sp_variable_declarations_vartype_finalize(THD *thd, int nvars,
const LEX_CSTRING &ref,
Item *default_value)
{
sp_variable *t;
if (!spcont || !(t= spcont->find_variable(&ref, false)))
{
my_error(ER_SP_UNDECLARED_VAR, MYF(0), ref.str);
return true;
}
if (t->field_def.is_cursor_rowtype_ref())
{
uint offset= t->field_def.cursor_rowtype_offset();
return sp_variable_declarations_cursor_rowtype_finalize(thd, nvars,
offset,
default_value);
}
if (t->field_def.is_column_type_ref())
{
Qualified_column_ident *tmp= t->field_def.column_type_ref();
return sp_variable_declarations_column_type_finalize(thd, nvars, tmp,
default_value);
}
if (t->field_def.is_table_rowtype_ref())
{
const Table_ident *tmp= t->field_def.table_rowtype_ref();
return sp_variable_declarations_table_rowtype_finalize(thd, nvars,
tmp->db,
tmp->table,
default_value);
}
// A reference to a scalar or a row variable with an explicit data type
return sp_variable_declarations_copy_type_finalize(thd, nvars,
t->field_def,
t->field_def.
row_field_definitions(),
default_value);
}
@ -5421,7 +5570,7 @@ LEX::sp_add_for_loop_cursor_variable(THD *thd,
if (!(spvar->default_value= new (thd->mem_root) Item_null(thd)))
return NULL;
spvar->field_def.set_cursor_rowtype_ref(true);
spvar->field_def.set_cursor_rowtype_ref(coffset);
if (sphead->add_for_loop_open_cursor(thd, spcont, spvar, pcursor, coffset,
param_lex, parameters))
@ -5445,7 +5594,7 @@ bool LEX::sp_for_loop_condition(THD *thd, const Lex_for_loop_st &loop)
{
sp_variable *src= i == 0 ? loop.m_index : loop.m_upper_bound;
args[i]= new (thd->mem_root)
Item_splocal(thd, &src->name, src->offset, src->sql_type());
Item_splocal(thd, &src->name, src->offset, src->type_handler());
if (args[i] == NULL)
return true;
#ifdef DBUG_ASSERT_EXISTS
@ -5579,7 +5728,7 @@ bool LEX::sp_for_loop_increment(THD *thd, const Lex_for_loop_st &loop)
{
Item_splocal *splocal= new (thd->mem_root)
Item_splocal(thd, &loop.m_index->name, loop.m_index->offset,
loop.m_index->sql_type());
loop.m_index->type_handler());
if (splocal == NULL)
return true;
#ifdef DBUG_ASSERT_EXISTS
@ -6350,7 +6499,7 @@ Item_splocal *LEX::create_item_spvar_row_field(THD *thd,
{
if (!(item= new (thd->mem_root)
Item_splocal_row_field_by_name(thd, a, b, spv->offset,
MYSQL_TYPE_NULL,
&type_handler_null,
pos.pos(), pos.length())))
return NULL;
}
@ -6364,7 +6513,7 @@ Item_splocal *LEX::create_item_spvar_row_field(THD *thd,
if (!(item= new (thd->mem_root)
Item_splocal_row_field(thd, a, b,
spv->offset, row_field_offset,
def->real_field_type(),
def->type_handler(),
pos.pos(), pos.length())))
return NULL;
}
@ -6533,7 +6682,7 @@ Item *LEX::create_item_limit(THD *thd,
Query_fragment pos(thd, sphead, start, end);
Item_splocal *item;
if (!(item= new (thd->mem_root) Item_splocal(thd, a,
spv->offset, spv->sql_type(),
spv->offset, spv->type_handler(),
pos.pos(), pos.length())))
return NULL;
#ifdef DBUG_ASSERT_EXISTS
@ -6652,11 +6801,8 @@ Item *LEX::create_item_ident_sp(THD *thd, LEX_CSTRING *name,
spv->offset,
pos.pos(),
pos.length()) :
spv->field_def.is_row() || spv->field_def.is_table_rowtype_ref() ?
new (thd->mem_root) Item_splocal_row(thd, name, spv->offset,
pos.pos(), pos.length()) :
new (thd->mem_root) Item_splocal(thd, name,
spv->offset, spv->sql_type(),
spv->offset, spv->type_handler(),
pos.pos(), pos.length());
if (splocal == NULL)
return NULL;
@ -7186,6 +7332,22 @@ bool LEX::add_grant_command(THD *thd, enum_sql_command sql_command_arg,
}
Item *LEX::make_item_func_substr(THD *thd, Item *a, Item *b, Item *c)
{
return (thd->variables.sql_mode & MODE_ORACLE) ?
new (thd->mem_root) Item_func_substr_oracle(thd, a, b, c) :
new (thd->mem_root) Item_func_substr(thd, a, b, c);
}
Item *LEX::make_item_func_substr(THD *thd, Item *a, Item *b)
{
return (thd->variables.sql_mode & MODE_ORACLE) ?
new (thd->mem_root) Item_func_substr_oracle(thd, a, b) :
new (thd->mem_root) Item_func_substr(thd, a, b);
}
Item *LEX::make_item_func_replace(THD *thd,
Item *org,
Item *find,