[Maria-developers] Review: MDEV-29075 Changing explicit_defaults_for_timestamp within stored procedure works inconsistently
29 Jul
2022
29 Jul
'22
7:36 a.m.
Hello Sergei, I have a couple of suggestions: > commit 7b8304045272111a6f4d44196d6b37cbfef06f37 > Author: Sergei Golubchik <serg@mariadb.org> > Date: Wed Jul 20 17:31:48 2022 +0200 > > MDEV-29075 Changing explicit_defaults_for_timestamp within stored procedure works inconsistently > > move the OPTION_EXPLICIT_DEF_TIMESTAMP check from the parsing step > to the execution > <cut> > > diff --git a/sql/field.cc b/sql/field.cc > index 2e0c70d3d13..23ebb07b7f7 100644 > --- a/sql/field.cc > +++ b/sql/field.cc > @@ -10824,6 +10824,7 @@ Column_definition::Column_definition(THD *thd, Field *old_field, > comment= old_field->comment; > vcol_info= old_field->vcol_info; > option_list= old_field->option_list; > + explicitly_nullable= !(old_field->flags & NOT_NULL_FLAG); This introduces asymmetry in how NULL and NOT NULL attributes are handled. I suggest considering these ways: 1. Change "bool explicitly_nullable" to "bool explicit_nullability", which will be: - false if nothing was specified - true if NULL or NOT NULL was specified. 2. Or don't store NOT_NULL_FLAG in Column_definition::flags at all. Add a new Column_definition enum member with three values for: - not specified - explicit NULL - explicit NOT NULL As discussed on slack, the latter will need some changes. But I think not that much, as only Column_definition needs changes, while Field does not seem to need at this point. > compression_method_ptr= 0; > versioning= VERSIONING_NOT_SET; > invisible= old_field->invisible; > diff --git a/sql/field.h b/sql/field.h > index 5d5be5204cd..87a30bd9f95 100644 > --- a/sql/field.h > +++ b/sql/field.h > @@ -5281,7 +5281,7 @@ class Column_definition: public Sql_alloc, > uint flags, pack_length; > List<String> interval_list; > engine_option_value *option_list; > - > + bool explicitly_nullable; > > /* > This is additinal data provided for any computed(virtual) field. > @@ -5303,7 +5303,7 @@ class Column_definition: public Sql_alloc, > comment(null_clex_str), > on_update(NULL), invisible(VISIBLE), char_length(0), > flags(0), pack_length(0), > - option_list(NULL), > + option_list(NULL), explicitly_nullable(false), > vcol_info(0), default_value(0), check_constraint(0), > versioning(VERSIONING_NOT_SET), period(NULL) > { > diff --git a/sql/sql_table.cc b/sql/sql_table.cc > index 3eeabe20c71..8c31f988a05 100644 > --- a/sql/sql_table.cc > +++ b/sql/sql_table.cc > @@ -2316,6 +2316,8 @@ void promote_first_timestamp_column(List<Create_field> *column_definitions) > if (column_definition.is_timestamp_type() || // TIMESTAMP > column_definition.unireg_check == Field::TIMESTAMP_OLD_FIELD) // Legacy > { > + if (!column_definition.explicitly_nullable) > + column_definition.flags|= NOT_NULL_FLAG; I think this does not work well with PS. On the very first execution the field becomes NOT NULL forever, if the current OPTION_EXPLICIT_DEF_TIMESTAMP says so. > DBUG_PRINT("info", ("field-ptr:%p", column_definition.field)); > if (first && > (column_definition.flags & NOT_NULL_FLAG) != 0 && // NOT NULL, > diff --git a/sql/sql_type.cc b/sql/sql_type.cc > index 44a51428280..dc0c0b1e0cf 100644 > --- a/sql/sql_type.cc > +++ b/sql/sql_type.cc > @@ -4258,18 +4258,6 @@ void Type_handler_temporal_with_date::Item_update_null_value(Item *item) const > (void) item->get_date(thd, <ime, Datetime::Options(thd)); > } > > -bool > -Type_handler_timestamp_common:: > -Column_definition_set_attributes(THD *thd, > - Column_definition *def, > - const Lex_field_type_st &attr, > - column_definition_type_t type) const > -{ > - Type_handler::Column_definition_set_attributes(thd, def, attr, type); > - if (!(thd->variables.option_bits & OPTION_EXPLICIT_DEF_TIMESTAMP)) > - def->flags|= NOT_NULL_FLAG; > - return false; > - > > void Type_handler_string_result::Item_update_null_value(Item *item) const > { > diff --git a/sql/sql_type.h b/sql/sql_type.h > index 7ff4bc64679..e5f54535ece 100644 > --- a/sql/sql_type.h > +++ b/sql/sql_type.h > @@ -6655,11 +6655,6 @@ class Type_handler_timestamp_common: public Type_handler_temporal_with_date > bool Item_func_min_max_get_date(THD *thd, Item_func_min_max*, > MYSQL_TIME *, date_mode_t fuzzydate) > const override; > - bool Column_definition_set_attributes(THD *thd, > - Column_definition *def, > - const Lex_field_type_st &attr, > - column_definition_type_t type) > - const override; > }; > > > diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy > index 5416cec49b5..f326d8c0cc5 100644 > --- a/sql/sql_yacc.yy > +++ b/sql/sql_yacc.yy > @@ -5831,7 +5831,6 @@ field_def: > | opt_generated_always AS virtual_column_func > { > Lex->last_field->vcol_info= $3; > - Lex->last_field->flags&= ~NOT_NULL_FLAG; // undo automatic NOT NULL for timestamps > } > vcol_opt_specifier vcol_opt_attribute > { > @@ -6313,7 +6312,12 @@ attribute_list: > ; > > attribute: > - NULL_SYM { Lex->last_field->flags&= ~ NOT_NULL_FLAG; $$.init(); } > + NULL_SYM > + { > + Lex->last_field->flags&= ~NOT_NULL_FLAG; > + Lex->last_field->explicitly_nullable= true; > + $$.init(); > + } > | DEFAULT column_default_expr { Lex->last_field->default_value= $2; $$.init(); } > | ON UPDATE_SYM NOW_SYM opt_default_time_precision > {
30 Jul
30 Jul
12:34 p.m.
Hi, Alexander, On Jul 29, Alexander Barkov wrote: > Hello Sergei, > > I have a couple of suggestions: > > > commit 7b8304045272111a6f4d44196d6b37cbfef06f37 > > Author: Sergei Golubchik <serg@mariadb.org> > > Date: Wed Jul 20 17:31:48 2022 +0200 > > > > MDEV-29075 Changing explicit_defaults_for_timestamp within stored procedure works inconsistently > > > > move the OPTION_EXPLICIT_DEF_TIMESTAMP check from the parsing step > > to the execution > > > > diff --git a/sql/field.cc b/sql/field.cc > > index 2e0c70d3d13..23ebb07b7f7 100644 > > --- a/sql/field.cc > > +++ b/sql/field.cc > > @@ -10824,6 +10824,7 @@ Column_definition::Column_definition( > > comment= old_field->comment; > > vcol_info= old_field->vcol_info; > > option_list= old_field->option_list; > > + explicitly_nullable= !(old_field->flags & NOT_NULL_FLAG); > > This introduces asymmetry in how NULL and NOT NULL attributes are handled. > > I suggest considering these ways: > > 1. Change "bool explicitly_nullable" to "bool explicit_nullability", > which will be: > > - false if nothing was specified > - true if NULL or NOT NULL was specified. I've done that, see commit 7120195ac1c, but I don't like how it looks. When NOT_NULL_FLAG is set, the value is redundant, it's not used anywhere and only adds few pointless assignments to sql_yacc.yy. We only need to know how to interpret the case when NOT_NULL_FLAG is not set, that's what explicitly_nullable was doing. > 2. Or don't store NOT_NULL_FLAG in Column_definition::flags at all. > > Add a new Column_definition enum member with three values for: > - not specified > - explicit NULL > - explicit NOT NULL > > As discussed on slack, the latter will need some changes. > But I think not that much, as only Column_definition needs changes, > while Field does not seem to need at this point. I don't know how to do it in a robust way. Column_definition and Field have both the same flags member, one typically just copies it back and forth. Having just one bit out of Column_definition::flags is very error-prone, I'd prefer all flags to be stored very differently in Column_definition, so that one couldn't just copy them. But this explicitly_nullable thing cannot justify such a big change. Regards, Sergei VP of MariaDB Server Engineering and security@mariadb.org
1 Aug
1 Aug
11:21 a.m.
Hello Sergei, On 7/30/22 14:34, Sergei Golubchik wrote: > Hi, Alexander, > > On Jul 29, Alexander Barkov wrote: >> Hello Sergei, >> >> I have a couple of suggestions: >> >>> commit 7b8304045272111a6f4d44196d6b37cbfef06f37 >>> Author: Sergei Golubchik <serg@mariadb.org> >>> Date: Wed Jul 20 17:31:48 2022 +0200 >>> >>> MDEV-29075 Changing explicit_defaults_for_timestamp within stored procedure works inconsistently >>> >>> move the OPTION_EXPLICIT_DEF_TIMESTAMP check from the parsing step >>> to the execution >> >>>> diff --git a/sql/field.cc b/sql/field.cc >>> index 2e0c70d3d13..23ebb07b7f7 100644 >>> --- a/sql/field.cc >>> +++ b/sql/field.cc >>> @@ -10824,6 +10824,7 @@ Column_definition::Column_definition( >>> comment= old_field->comment; >>> vcol_info= old_field->vcol_info; >>> option_list= old_field->option_list; >>> + explicitly_nullable= !(old_field->flags & NOT_NULL_FLAG); >> >> This introduces asymmetry in how NULL and NOT NULL attributes are handled. >> >> I suggest considering these ways: >> >> 1. Change "bool explicitly_nullable" to "bool explicit_nullability", >> which will be: >> >> - false if nothing was specified >> - true if NULL or NOT NULL was specified. > > I've done that, see commit 7120195ac1c, > but I don't like how it looks. When NOT_NULL_FLAG is set, the value is > redundant, it's not used anywhere and only adds few pointless > assignments to sql_yacc.yy. > > We only need to know how to interpret the case when NOT_NULL_FLAG is not > set, that's what explicitly_nullable was doing. I checked 7120195ac1c. Indeed the new version does not look better. I won't insist. > >> 2. Or don't store NOT_NULL_FLAG in Column_definition::flags at all. >> >> Add a new Column_definition enum member with three values for: >> - not specified >> - explicit NULL >> - explicit NOT NULL >> >> As discussed on slack, the latter will need some changes. >> But I think not that much, as only Column_definition needs changes, >> while Field does not seem to need at this point. > > I don't know how to do it in a robust way. Column_definition and Field > have both the same flags member, one typically just copies it back and > forth. Having just one bit out of Column_definition::flags is very > error-prone, I'd prefer all flags to be stored very differently in > Column_definition, so that one couldn't just copy them. But this > explicitly_nullable thing cannot justify such a big change. I agreed. I have no other suggestion. Thanks for your explanation. > > Regards, > Sergei > VP of MariaDB Server Engineering > and security@mariadb.org
1:11 p.m.
Hi! On Fri, 29 Jul 2022, 07:43 Alexander Barkov, <bar@mariadb.com> wrote:
Hello Sergei,
I have a couple of suggestions:
<cut>
I suggest considering these ways:
1. Change "bool explicitly_nullable" to "bool explicit_nullability", which will be:
- false if nothing was specified - true if NULL or NOT NULL was specified.
2. Or don't store NOT_NULL_FLAG in Column_definition::flags at all.
Add a new Column_definition enum member with three values for: - not specified - explicit NULL - explicit NOT NULL
This would require 4 or 8 bytes extra per field (and each field definition is stored twice per table), so this is probably not a good idea.
Regards, Monty
856
Age (days ago)
859
Last active (days ago)
3 comments
3 participants
participants (3)
-
Alexander Barkov
-
Michael Widenius
-
Sergei Golubchik