diff --git a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result index b5ad1fd31ea..2211c8ac9df 100644 --- a/mysql-test/r/type_blob.result +++ b/mysql-test/r/type_blob.result @@ -894,9 +894,13 @@ Warnings: Warning 1287 The syntax 'TIMESTAMP(4294967294)' is deprecated and will be removed in MySQL 5.2. Please use 'TIMESTAMP' instead DROP TABLE b15776; CREATE TABLE b15776 (a timestamp(4294967295)); -ERROR 42000: Display width out of range for column 'a' (max = 255) +Warnings: +Warning 1287 'TIMESTAMP(4294967295)' is deprecated; use 'TIMESTAMP' instead +DROP TABLE b15776; CREATE TABLE b15776 (a timestamp(4294967296)); ERROR 42000: Display width out of range for column 'a' (max = 4294967295) +CREATE TABLE b15776 (a timestamp(-1)); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-1))' at line 1 CREATE TABLE b15776 (a timestamp(-2)); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-2))' at line 1 CREATE TABLE b15776 (a int(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999)); diff --git a/mysql-test/t/type_blob.test b/mysql-test/t/type_blob.test index fdcd85c1b4b..35e5b30ecb8 100644 --- a/mysql-test/t/type_blob.test +++ b/mysql-test/t/type_blob.test @@ -537,11 +537,13 @@ CREATE TABLE b15776 (a year(-2)); ## For timestamp, we silently rewrite widths to 14 or 19. CREATE TABLE b15776 (a timestamp(4294967294)); DROP TABLE b15776; ---error ER_TOO_BIG_DISPLAYWIDTH CREATE TABLE b15776 (a timestamp(4294967295)); +DROP TABLE b15776; --error ER_TOO_BIG_DISPLAYWIDTH CREATE TABLE b15776 (a timestamp(4294967296)); --error ER_PARSE_ERROR +CREATE TABLE b15776 (a timestamp(-1)); +--error ER_PARSE_ERROR CREATE TABLE b15776 (a timestamp(-2)); diff --git a/sql/field.cc b/sql/field.cc index c8645aa5a4f..7357389c794 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -7568,6 +7568,7 @@ uint32 Field_blob::get_length(const uchar *pos, uint packlength_arg, bool low_by return (uint32) tmp; } } + /* When expanding this, see also MAX_FIELD_BLOBLENGTH. */ return 0; // Impossible } @@ -9449,11 +9450,11 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, (fld_type_modifier & NOT_NULL_FLAG) && fld_type != MYSQL_TYPE_TIMESTAMP) flags|= NO_DEFAULT_VALUE_FLAG; - if (fld_length != 0) + if (fld_length != NULL) { errno= 0; length= strtoul(fld_length, NULL, 10); - if (errno != 0) + if ((errno != 0) || (length > MAX_FIELD_BLOBLENGTH)) { my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), fld_name, MAX_FIELD_BLOBLENGTH); DBUG_RETURN(TRUE); @@ -9610,7 +9611,7 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, } break; case MYSQL_TYPE_TIMESTAMP: - if (!fld_length) + if (fld_length == NULL) { /* Compressed date YYYYMMDDHHMMSS */ length= MAX_DATETIME_COMPRESSED_WIDTH; @@ -9619,12 +9620,21 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, { /* We support only even TIMESTAMP lengths less or equal than 14 - and 19 as length of 4.1 compatible representation. + and 19 as length of 4.1 compatible representation. Silently + shrink it to MAX_DATETIME_COMPRESSED_WIDTH. */ - length= ((length+1)/2)*2; /* purecov: inspected */ - length= min(length, MAX_DATETIME_COMPRESSED_WIDTH); /* purecov: inspected */ + DBUG_ASSERT(MAX_DATETIME_COMPRESSED_WIDTH < UINT_MAX); + if (length != UINT_MAX) /* avoid overflow; is safe because of min() */ + length= ((length+1)/2)*2; + length= min(length, MAX_DATETIME_COMPRESSED_WIDTH); } flags|= ZEROFILL_FLAG | UNSIGNED_FLAG; + /* + Since we silently rewrite down to MAX_DATETIME_COMPRESSED_WIDTH bytes, + the parser should not raise errors unless bizzarely large. + */ + max_field_charlength= UINT_MAX; + if (fld_default_value) { /* Grammar allows only NOW() value for ON UPDATE clause */ @@ -9731,7 +9741,7 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, ((length > max_field_charlength && fld_type != MYSQL_TYPE_SET && fld_type != MYSQL_TYPE_ENUM && (fld_type != MYSQL_TYPE_VARCHAR || fld_default_value)) || - (!length && + ((length == 0) && fld_type != MYSQL_TYPE_STRING && fld_type != MYSQL_TYPE_VARCHAR && fld_type != MYSQL_TYPE_GEOMETRY))) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index e479d5e4136..0e5240fea10 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4657,12 +4657,12 @@ type: } | BOOL_SYM { - Lex->length=(char*) "1"; + Lex->length= (char*) "1"; $$=MYSQL_TYPE_TINY; } | BOOLEAN_SYM { - Lex->length=(char*) "1"; + Lex->length= (char*) "1"; $$=MYSQL_TYPE_TINY; } | char field_length opt_binary @@ -4671,7 +4671,7 @@ type: } | char opt_binary { - Lex->length=(char*) "1"; + Lex->length= (char*) "1"; $$=MYSQL_TYPE_STRING; } | nchar field_length opt_bin_mod @@ -4681,7 +4681,7 @@ type: } | nchar opt_bin_mod { - Lex->length=(char*) "1"; + Lex->length= (char*) "1"; $$=MYSQL_TYPE_STRING; Lex->charset=national_charset_info; } @@ -4902,7 +4902,6 @@ field_length: opt_field_length: /* empty */ { Lex->length=(char*) 0; /* use default length */ } | field_length { } - ; opt_precision: /* empty */ {} diff --git a/sql/unireg.h b/sql/unireg.h index c1c0e11e113..6f9c44d98f9 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -63,7 +63,7 @@ #define MAX_MBWIDTH 3 /* Max multibyte sequence */ #define MAX_FIELD_CHARLENGTH 255 #define MAX_FIELD_VARCHARLENGTH 65535 -#define MAX_FIELD_BLOBLENGTH UINT_MAX +#define MAX_FIELD_BLOBLENGTH UINT_MAX32 /* cf field_blob::get_length() */ #define CONVERT_IF_BIGGER_TO_BLOB 512 /* Used for CREATE ... SELECT */ /* Max column width +1 */