summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <cmiller@zippy.cornsilk.net>2008-04-09 12:27:30 -0400
committerunknown <cmiller@zippy.cornsilk.net>2008-04-09 12:27:30 -0400
commit2bc7179d2d0019fd2b4666de0990faf3f19b9582 (patch)
treecc737f27b6e9b0186e0c967c48f6c8c4d57ee754
parenta9e658408fd40ed9485654539b334b92272361c0 (diff)
downloadmariadb-git-2bc7179d2d0019fd2b4666de0990faf3f19b9582.tar.gz
Follow-up to B-g#15776, test failures on 64-bit linux.
Make maximum blob size to be 2**32-1, regardless of word size. Fix failure of timestamp with size of 2**31-1. The method of rounding up to the nearest even number would overflow. mysql-test/r/type_blob.result: 2**32-1 is not a special case for timestamp. Test 2**32-1 and 2**64 as the reliable test points for both 32- and 64-bit machines. I'd like to test 2**32, but that would make tests that vary between architectures. I'd like to generalize the tests by pulling the max blob size from the server, and then "eval"ing N-1, N, and N+1 instead of all these literal numbers, but I have not found a way to get UINT_MAX. mysql-test/t/type_blob.test: 2**32-1 is not a special case for timestamp. Test 2**32-1 and 2**64 as the reliable test points for both 32- and 64-bit machines. I'd like to test 2**32, but that would make tests that vary between architectures. I'd like to generalize the tests by pulling the max blob size from the server, and then "eval"ing N-1, N, and N+1 instead of all these literal numbers, but I have not found a way to get UINT_MAX. sql/field.cc: Fix a bug where the round-to-even code for TIMESTAMP fields failed where the size would overflow the size to zero and then fail. Also, since we silently truncate the size of TIMESTAMP fields, set the maximum size we report is allowable to be the largest parsable number. sql/unireg.h: Make BLOB size the maximum that the packed value in field_blob::get_length() allows.
-rw-r--r--mysql-test/r/type_blob.result6
-rw-r--r--mysql-test/t/type_blob.test4
-rw-r--r--sql/field.cc24
-rw-r--r--sql/unireg.h2
4 files changed, 26 insertions, 10 deletions
diff --git a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result
index 84f2d815bdd..4c9ee9b84e3 100644
--- a/mysql-test/r/type_blob.result
+++ b/mysql-test/r/type_blob.result
@@ -880,9 +880,13 @@ Warnings:
Warning 1287 'TIMESTAMP(4294967294)' is deprecated; 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 ad578a18979..d7af7c40d23 100644
--- a/mysql-test/t/type_blob.test
+++ b/mysql-test/t/type_blob.test
@@ -528,11 +528,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 2950f349580..99b61ec1ee0 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -6848,6 +6848,7 @@ uint32 Field_blob::get_length(const char *pos)
return (uint32) tmp;
}
}
+ /* When expanding this, see also MAX_FIELD_BLOBLENGTH. */
return 0; // Impossible
}
@@ -8395,11 +8396,11 @@ bool create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
(fld_type_modifier & NOT_NULL_FLAG) && fld_type != FIELD_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);
@@ -8556,7 +8557,7 @@ bool create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
}
break;
case FIELD_TYPE_TIMESTAMP:
- if (!fld_length)
+ if (fld_length == NULL)
{
/* Compressed date YYYYMMDDHHMMSS */
length= MAX_DATETIME_COMPRESSED_WIDTH;
@@ -8565,12 +8566,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 */
@@ -8677,7 +8687,7 @@ bool create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
((length > max_field_charlength && fld_type != FIELD_TYPE_SET &&
fld_type != FIELD_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 != FIELD_TYPE_GEOMETRY)))
{
diff --git a/sql/unireg.h b/sql/unireg.h
index 0ab2a40048b..24e57b4e584 100644
--- a/sql/unireg.h
+++ b/sql/unireg.h
@@ -60,7 +60,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 */