Hi, Aleksey, On Jun 27, Aleksey Midenkov wrote: > revision-id: 59aafa4ee46 (mariadb-10.6.22-50-g59aafa4ee46) > parent(s): 1221f49f312 > author: Aleksey Midenkov > committer: Aleksey Midenkov > timestamp: 2025-06-04 23:42:36 +0300 > message: > > MDEV-33633 Trigger tries to access already dropped view > > diff --git a/mysql-test/main/ps_ddl.result b/mysql-test/main/ps_ddl.result > index 35998c05dc9..ceb85835623 100644 > --- a/mysql-test/main/ps_ddl.result > +++ b/mysql-test/main/ps_ddl.result > @@ -333,7 +333,7 @@ a > drop view v1; > create view v1 as select a from t3; > insert into t1 (a) values (6); > -ERROR 42S02: Table 'test.t2' doesn't exist > +ERROR HY000: Table definition has changed, please retry transaction
Is it possible to the fallback and reopen here? This is a rather unexpected error, particularly when no transactions are involved. > diff --git a/sql/sql_base.cc b/sql/sql_base.cc > index 1a4fa315c3c..c89e88d0f03 100644 > --- a/sql/sql_base.cc > +++ b/sql/sql_base.cc > @@ -1737,6 +1737,18 @@ bool is_locked_view(THD *thd, TABLE_LIST *t) > DBUG_RETURN(FALSE); > } > > + Reprepare_observer reprepare_observer; > + auto scope_exit= make_scope_exit( > + [thd]() mutable { thd->m_reprepare_observer= NULL; }, > + false); > + if (!thd->m_reprepare_observer) > + { > + reprepare_observer.reset_reprepare_observer(); > + reprepare_observer.error_code= ER_TABLE_DEF_CHANGED; > + thd->m_reprepare_observer= &reprepare_observer; > + scope_exit.engage(); > + } And you didn't use SCOPE_EXIT to use a manual engage? Would be clearer, I'd say, to use SCOPE_EXIT and have an if() inside, like if (m_reprepare_observer == &reprepare_observer). But ok, as you like. > if (!tdc_open_view(thd, t, CHECK_METADATA_VERSION)) > { > DBUG_ASSERT(t->view != 0); > @@ -3059,9 +3071,7 @@ bool tdc_open_view(THD *thd, TABLE_LIST *table_list, > uint flags) > > DBUG_ASSERT(share->is_view); > > - err= mysql_make_view(thd, share, table_list, (flags & OPEN_VIEW_NO_PARSE)); > - > - if (!err && (flags & CHECK_METADATA_VERSION)) > + if (flags & CHECK_METADATA_VERSION) > { > /* > Check TABLE_SHARE-version of view only if we have been instructed to do > @@ -3076,6 +3086,8 @@ bool tdc_open_view(THD *thd, TABLE_LIST *table_list, > uint flags) > goto ret; > } > > + err= mysql_make_view(thd, share, table_list, (flags & OPEN_VIEW_NO_PARSE)); But this one - I don't understand how it works. mysql_make_view() reads the view frm which contains versions that are checked by check_and_update_table_version(). How can check_and_update_table_version() work before mysql_make_view()? > ret: > tdc_release_share(share); > > diff --git a/sql/table.cc b/sql/table.cc > index 9bbc29d4ecf..6d2a80aeace 100644 > --- a/sql/table.cc > +++ b/sql/table.cc > @@ -5799,6 +5799,12 @@ void TABLE::init(THD *thd, TABLE_LIST *tl) > DBUG_ASSERT(!auto_increment_field_not_null); > auto_increment_field_not_null= FALSE; > > + tl->view= NULL; > + tl->derived= NULL; > + tl->derived_type= VIEW_ALGORITHM_UNDEFINED; > + tl->updatable= true; > + tl->effective_with_check= VIEW_CHECK_NONE; > + I agree it's conceptually correct and for the new table these fields should be reset. But it's rather unexpected that TABLE::init() modifies its arguments. Could this reinitialization be done somewhere else? Regards, Sergei Chief Architect, MariaDB Server and secur...@mariadb.org _______________________________________________ developers mailing list -- developers@lists.mariadb.org To unsubscribe send an email to developers-le...@lists.mariadb.org