diff options
author | Alexander Barkov <bar@mariadb.org> | 2017-03-03 15:02:08 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.org> | 2017-04-05 15:02:59 +0400 |
commit | 1b8a0c879d80733e3c684080b8c7719c35642e0d (patch) | |
tree | 1a98d1e701ddde368b1b1b7c76346a76a2328f9e /sql/sp_rcontext.cc | |
parent | 400de202792246bc1f6f5cb8813ecd35dc923200 (diff) | |
download | mariadb-git-1b8a0c879d80733e3c684080b8c7719c35642e0d.tar.gz |
MDEV-12133 sql_mode=ORACLE: table%ROWTYPE in variable declarations
Diffstat (limited to 'sql/sp_rcontext.cc')
-rw-r--r-- | sql/sp_rcontext.cc | 79 |
1 files changed, 70 insertions, 9 deletions
diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index 3ae455e00c9..b631ad71e49 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -132,13 +132,11 @@ bool sp_rcontext::init_var_table(THD *thd, */ static inline bool check_column_grant_for_type_ref(THD *thd, TABLE_LIST *table_list, - const Qualified_column_ident *col) + const char *str, size_t length) { #ifndef NO_EMBEDDED_ACCESS_CHECKS table_list->table->grant.want_privilege= SELECT_ACL; - return check_column_grant_in_table_ref(thd, table_list, - col->m_column.str, - col->m_column.length); + return check_column_grant_in_table_ref(thd, table_list, str, length); #else return false; #endif @@ -175,7 +173,9 @@ bool sp_rcontext::resolve_type_ref(THD *thd, Column_definition *def, { if ((src= lex.query_tables->table->find_field_by_name(ref->m_column.str))) { - if (!(rc= check_column_grant_for_type_ref(thd, table_list, ref))) + if (!(rc= check_column_grant_for_type_ref(thd, table_list, + ref->m_column.str, + ref->m_column.length))) { *def= Column_definition(thd, src, NULL/*No defaults,no constraints*/); def->flags&= (uint) ~NOT_NULL_FLAG; @@ -195,6 +195,54 @@ bool sp_rcontext::resolve_type_ref(THD *thd, Column_definition *def, } +bool sp_rcontext::resolve_table_rowtype_ref(THD *thd, + Row_definition_list &defs, + Table_ident *ref) +{ + Open_tables_backup open_tables_state_backup; + thd->reset_n_backup_open_tables_state(&open_tables_state_backup); + + TABLE_LIST *table_list; + LEX *save_lex= thd->lex; + bool rc= true; + + sp_lex_local lex(thd, thd->lex); + thd->lex= &lex; + + lex.context_analysis_only= CONTEXT_ANALYSIS_ONLY_VIEW; + // Make %ROWTYPE variables see temporary tables that shadow permanent tables + thd->temporary_tables= open_tables_state_backup.temporary_tables; + + if ((table_list= lex.select_lex.add_table_to_list(thd, ref, NULL, 0, + TL_READ_NO_INSERT, + MDL_SHARED_READ)) && + !check_table_access(thd, SELECT_ACL, table_list, TRUE, UINT_MAX, FALSE) && + !open_tables_only_view_structure(thd, table_list, + thd->mdl_context.has_locks())) + { + for (Field **src= lex.query_tables->table->field; *src; src++) + { + if ((rc= check_column_grant_for_type_ref(thd, table_list, + src[0]->field_name, + strlen(src[0]->field_name)))) + break; + Spvar_definition *def= new (thd->mem_root) Spvar_definition(thd, *src); + def->flags&= (uint) ~NOT_NULL_FLAG; + if ((rc= def->sp_prepare_create_field(thd, thd->mem_root))) + break; + defs.push_back(def, thd->mem_root); + } + } + + lex.unit.cleanup(); + thd->temporary_tables= NULL; // Avoid closing temporary tables + close_thread_tables(thd); + thd->lex= save_lex; + thd->restore_backup_open_tables_state(&open_tables_state_backup); + return rc; +} + + bool sp_rcontext::resolve_type_refs(THD *thd, List<Spvar_definition> &defs) { List_iterator<Spvar_definition> it(defs); @@ -229,7 +277,16 @@ bool sp_rcontext::init_var_items(THD *thd, for (uint idx= 0; idx < num_vars; ++idx, def= it++) { Field *field= m_var_table->field[idx]; - if (def->is_row()) + if (def->is_table_rowtype_ref()) + { + Row_definition_list defs; + Item_field_row *item= new (thd->mem_root) Item_field_row(thd, field); + if (!(m_var_items[idx]= item) || + resolve_table_rowtype_ref(thd, defs, def->table_rowtype_ref()) || + item->row_create_items(thd, &defs)) + return true; + } + else if (def->is_row()) { Item_field_row *item= new (thd->mem_root) Item_field_row(thd, field); if (!(m_var_items[idx]= item) || @@ -706,7 +763,8 @@ int sp_cursor::fetch(THD *thd, List<sp_variable> *vars) } if (vars->elements != result.get_field_count() && (vars->elements != 1 || - !vars->head()->field_def.is_row(result.get_field_count()))) + result.get_field_count() != + thd->spcont->get_item(vars->head()->offset)->cols())) { my_message(ER_SP_WRONG_NO_OF_FETCH_ARGS, ER_THD(thd, ER_SP_WRONG_NO_OF_FETCH_ARGS), MYF(0)); @@ -787,8 +845,11 @@ bool sp_cursor::Select_fetch_into_spvars:: int sp_cursor::Select_fetch_into_spvars::send_data(List<Item> &items) { - return (spvar_list->elements == 1 && - (spvar_list->head())->field_def.is_row(items.elements)) ? + Item *item; + return spvar_list->elements == 1 && + (item= thd->spcont->get_item(spvar_list->head()->offset)) && + item->type_handler() == &type_handler_row && + item->cols() == items.elements ? thd->spcont->set_variable_row(thd, spvar_list->head()->offset, items) : send_data_to_variable_list(*spvar_list, items); } |