-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
MDEV-31053 UUID(size) should be disallowed #4287
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 10.11
Are you sure you want to change the base?
MDEV-31053 UUID(size) should be disallowed #4287
Conversation
Emits an error when creating a table with either a UUID or ipv4 column having a nonzero length. Specifying lengths has no effect for these types: CREATE TABLE t1 (id UUID(24), ..., ip ipv4(4), ... ); ipv6 columns having nonzero lengths are permitted, for example in the case of CREATE TABLE t1 (a INET6(6) DEFAULT '::10'); Specifying length zero for uuid, ipv4 has the same behavior as specifying no explicit length. Since these types are plugins, the lengths cannot be rejected by the grammar at lexing; rather they are rejected at a later parsing step if they are nonzero.
ee2cec2
to
0d29d7a
Compare
const Name& name) | ||
{ | ||
/* | ||
Inet6 support allows length at least, for the case |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why? what does it mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the code and our documentation, it has no meaning. Perhaps it did at one point in the past, for compatibility? The MySQL docs don't mention a specific inet6
type. Searching around online, it seems that varbinary(16)
is recommended for storing ipv6 in MySQL. So I wonder if we allowed a length here to ease a transition from MySQL to MariaDB (i.e. only change the type, not the values in parens)?
if (FbtImpl::allowed(attr, singleton()->name())) | ||
return true; | ||
return Type_handler::Column_definition_set_attributes(thd, def, | ||
attr, type); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do you need a new allowed()
method when you can put the check into Column_definition_set_attributes()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could've changed descendant types to implement their own Column_definition_set_attributes
overrides, but the Type_handler_fbt
class implements, and heavily depends on, a static singleton()
method which always returns type Type_handler_fbt
. Because that method, internally, declares a static Type_handler_fbt
instance, any descendant types from Type_handler_fbt
are not instantiated.
I tried changing this to be a non-static virtual method instead, but there's a lot that assumes it is a static method and that an object isn't needed. I attempted to supply a different implementation for the internals of the static singleton()
method via template parameters and std::enable_if
magic, but the simplest approach is to have an implied allowed
method (via template contracts) which the compiler can check. Unfortunately, at least at this point in time and like many template classes, there isn't a way to implicitly document in the language that allowed
should be implemented. This is true of the STL, too. We could document with a comment, but by "in the language" I mean in a way that the compiler can verify (like it does with virtual
methods and their overrides).
With this approach, we don't need to care about singleton()
and we can ask the FbtImpl
instance if the length/precision should be allowed. In the cases of this patch, FbtImpl
can be Inet4
, Inet6
, or UUID
.
@@ -10758,3 +10758,5 @@ ER_CM_OPTION_MISSING_REQUIREMENT | |||
eng "CHANGE MASTER TO option '%s=%s' is missing requirement %s" | |||
ER_SLAVE_STATEMENT_TIMEOUT 70100 | |||
eng "Slave log event execution was interrupted (slave_max_statement_time exceeded)" | |||
ER_NO_LENGTH_PRECISION_ALLOWED | |||
eng "Type '%s' does not accept length nor precision values" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dunno. A dedicated error, different from built-in types. Ideally plugin types should behave exactly the same as builtin types.
Perhaps you can move the check into the parser? Like
field_type_all_with_typedefs:
field_type_all_builtin
{
Lex->map_data_type(Lex_ident_sys(), &($$= $1));
}
| udt_name
{
/* copied from the known_storage_engines rule */
plugin_ref plugin;
if (!(plugin= ha_resolve_by_name(thd, &$1, false)))
my_yyabort_error((ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str));
/* check the options */
if (plugin->...->check_options(0))
{
thd->parse_error(ER_SYNTAX_ERROR, ...);
MYSQL_YYABORT;
}
if (unlikely(Lex->set_field_type_udt_or_typedef(&$$, $1, $2)))
MYSQL_YYABORT;
}
| udt_name field_length_str
{
/* copied from the known_storage_engines rule */
plugin_ref plugin;
if (!(plugin= ha_resolve_by_name(thd, &$1, false)))
my_yyabort_error((ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str));
/* check the options */
if (plugin->...->check_options(1))
{
thd->parse_error(ER_SYNTAX_ERROR, ...);
MYSQL_YYABORT;
}
if (unlikely(Lex->set_field_type_udt_or_typedef(&$$, $1, $2)))
MYSQL_YYABORT;
}
| udt_name precision
{
/* copied from the known_storage_engines rule */
plugin_ref plugin;
if (!(plugin= ha_resolve_by_name(thd, &$1, false)))
my_yyabort_error((ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str));
/* check the options */
if (plugin->...->check_options(2))
{
thd->parse_error(ER_SYNTAX_ERROR, ...);
MYSQL_YYABORT;
}
if (unlikely(Lex->set_field_type_udt_or_typedef(&$$, $1, $2)))
MYSQL_YYABORT;
}
;
but with less code duplication
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll try it out 👍
Emits an error when creating a table with either a UUID or ipv4 column having a nonzero length. Specifying lengths has no effect for these types:
ipv6 columns having nonzero lengths are permitted, for example in the case of
Specifying length zero for uuid, ipv4 has the same behavior as specifying no explicit length. Since these types are plugins, the lengths cannot be rejected by the grammar at lexing; rather they are rejected at a later parsing step if they are nonzero.