Hi! On Wed, Jul 29, 2020 at 2:39 PM Sergei Golubchik <s...@mariadb.org> wrote:
> Hi, Oleksandr! > > On Jul 29, Oleksandr Byelkin wrote: > > revision-id: 7311586ca25 (mariadb-10.2.31-317-g7311586ca25) > > parent(s): a1e52e7f32c > > author: Oleksandr Byelkin <sa...@mariadb.com> > > committer: Oleksandr Byelkin <sa...@mariadb.com> > > timestamp: 2020-07-17 13:47:26 +0200 > > message: > > > > MDEV-15703 Crash in EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE t1 (a INT > DEFAULT ?)' USING DEFAULT > > > > Part 1: make better asserts. > > > > diff --git a/sql/field.cc b/sql/field.cc > > index 65bd9d22857..cf0cc655888 100644 > > --- a/sql/field.cc > > +++ b/sql/field.cc > > @@ -11138,6 +11138,16 @@ bool Field::save_in_field_default_value(bool > view_error_processing) > > { > > THD *thd= table->in_use; > > > > + if ( // table is not opened properly > > + table == NULL || table->pos_in_table_list == NULL || > > + table->pos_in_table_list->select_lex == NULL || > > + // we are in subquery/derived/CTE > > + > !table->pos_in_table_list->top_table()->select_lex->is_top_level_select()) > > + { > > + DBUG_ASSERT(0); // shoud not happened > > + my_error(ER_INVALID_DEFAULT_PARAM, MYF(0)); > > + return false; > > + } > > that's kind of questionable. if this condition can never be true, why do > you have my_error() there? Just do asserts, like > > DBUG_ASSERT(table); > DBUG_ASSERT(table->pos_in_table_list); > DBUG_ASSERT(table->pos_in_table_list->select_lex); > > DBUG_ASSERT(table->pos_in_table_list->top_table()->select_lex->is_top_level_select()); > It was the first solution to catch the problem on the low level, now we catch it earlier and in many places, but if we forget something on non-debug builds it will just work. > > > if (flags & NO_DEFAULT_VALUE_FLAG && > > real_type() != MYSQL_TYPE_ENUM) > > { > > @@ -11177,12 +11187,29 @@ bool Field::save_in_field_default_value(bool > view_error_processing) > > bool Field::save_in_field_ignore_value(bool view_error_processing) > > { > > enum_sql_command com= table->in_use->lex->sql_command; > > + > > + if ( // table is not opened properly > > + table == NULL || table->pos_in_table_list == NULL || > > + table->pos_in_table_list->select_lex == NULL || > > + // we are in subquery/derived/CTE > > + > !table->pos_in_table_list->top_table()->select_lex->is_top_level_select()) > > + { > > + DBUG_ASSERT(0); // shoud not happened > > + my_error(ER_INVALID_DEFAULT_PARAM, MYF(0)); > > + return false; > > + } > > ditto > the same as above > > > // All insert-like commands > > if (com == SQLCOM_INSERT || com == SQLCOM_REPLACE || > > com == SQLCOM_INSERT_SELECT || com == SQLCOM_REPLACE_SELECT || > > com == SQLCOM_LOAD) > > return save_in_field_default_value(view_error_processing); > > - return 0; // ignore > > + if (com == SQLCOM_UPDATE || com == SQLCOM_UPDATE_MULTI) > > + return 0; // ignore > > + > > + // unexpected command > > + DBUG_ASSERT(0); // shoud not happened > > ditto > > but why it should not happen? What if one does SELECT DEFAULT(f) FROM t? > we think that we caught all cases with: 1) calls of Item_(param|default|ignore)::val_* (it is old way, was here for long time) 2) checks Item::is_evaluable_expression() before save_in_fields() where it is possible > > > + my_error(ER_INVALID_DEFAULT_PARAM, MYF(0)); > > + return false; > > } > > > > > > diff --git a/sql/item.cc b/sql/item.cc > > index 9451d4203ca..382eb3ac47a 100644 > > --- a/sql/item.cc > > +++ b/sql/item.cc > > @@ -3930,13 +3930,19 @@ int Item_param::save_in_field(Field *field, bool > no_conversions) > > case NULL_VALUE: > > return set_field_to_null_with_conversions(field, no_conversions); > > case DEFAULT_VALUE: > > - return > field->save_in_field_default_value(field->table->pos_in_table_list-> > > + return field->save_in_field_default_value((field->table && > > + > field->table->pos_in_table_list)? > > in what case can field->table be NULL here? > probably impossible (I thought it is for fake fields in SP, but it looks like they have fake table also) > > + > field->table->pos_in_table_list-> > > top_table() != > > - > field->table->pos_in_table_list); > > + > field->table->pos_in_table_list: > > + FALSE); > > case IGNORE_VALUE: > > - return > field->save_in_field_ignore_value(field->table->pos_in_table_list-> > > + return field->save_in_field_ignore_value((field->table && > > + > field->table->pos_in_table_list)? > > + > field->table->pos_in_table_list-> > > top_table() != > > - > field->table->pos_in_table_list); > > + > field->table->pos_in_table_list: > > + FALSE); > > case NO_VALUE: > > DBUG_ASSERT(0); // Should not be possible > > return true; > > > Regards, > Sergei > VP of MariaDB Server Engineering > and secur...@mariadb.org >
_______________________________________________ Mailing list: https://launchpad.net/~maria-developers Post to : maria-developers@lists.launchpad.net Unsubscribe : https://launchpad.net/~maria-developers More help : https://help.launchpad.net/ListHelp