Commit e1b9be54 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-9319 ALTER from a bigger to a smaller blob type truncates too much data

parent e126baaf
...@@ -5804,5 +5804,21 @@ c0 c1 c2 c3 c4 ...@@ -5804,5 +5804,21 @@ c0 c1 c2 c3 c4
2012-06-11 15:18:24 2012-06-11 15:18:24 2012-06-11 15:18:24 2012-06-11 15:18:24 2012-06-11 15:18:24 2012-06-11 15:18:24 2012-06-11 15:18:24 2012-06-11 15:18:24 2012-06-11 15:18:24 2012-06-11 15:18:24
DROP TABLE t2, t1; DROP TABLE t2, t1;
# #
# MDEV-9319 ALTER from a bigger to a smaller blob type truncates too much data
#
SET NAMES utf8;
CREATE TABLE t1 (a TEXT CHARACTER SET utf8);
INSERT INTO t1 VALUES (REPEAT('A',100));
SELECT OCTET_LENGTH(a) FROM t1;
OCTET_LENGTH(a)
300
ALTER TABLE t1 MODIFY a TINYTEXT CHARACTER SET utf8;
Warnings:
Warning 1265 Data truncated for column 'a' at row 1
SELECT OCTET_LENGTH(a),a FROM t1;
OCTET_LENGTH(a) a
255 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
DROP TABLE t1;
#
# End of 5.5 tests # End of 5.5 tests
# #
...@@ -2606,6 +2606,22 @@ Warning 1292 Truncated incorrect INTEGER value: 'a' ...@@ -2606,6 +2606,22 @@ Warning 1292 Truncated incorrect INTEGER value: 'a'
DROP TABLE t1; DROP TABLE t1;
# End of test for Bug#13581962,Bug#14096619 # End of test for Bug#13581962,Bug#14096619
# #
# MDEV-9319 ALTER from a bigger to a smaller blob type truncates too much data
#
SET NAMES utf8mb4;
CREATE TABLE t1 (a TEXT CHARACTER SET utf8mb4);
INSERT INTO t1 VALUES (REPEAT('😎',100));
SELECT OCTET_LENGTH(a) FROM t1;
OCTET_LENGTH(a)
400
ALTER TABLE t1 MODIFY a TINYTEXT CHARACTER SET utf8mb4;
Warnings:
Warning 1265 Data truncated for column 'a' at row 1
SELECT OCTET_LENGTH(a),a FROM t1;
OCTET_LENGTH(a) a
252 😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎
DROP TABLE t1;
#
# End of 5.5 tests # End of 5.5 tests
# #
# #
......
...@@ -29,9 +29,11 @@ select length(data) from t1; ...@@ -29,9 +29,11 @@ select length(data) from t1;
length(data) length(data)
18874368 18874368
alter table t1 modify data blob; alter table t1 modify data blob;
Warnings:
Warning 1265 Data truncated for column 'data' at row 1
select length(data) from t1; select length(data) from t1;
length(data) length(data)
0 65535
drop table t1; drop table t1;
CREATE TABLE t1 (data BLOB) ENGINE=myisam; CREATE TABLE t1 (data BLOB) ENGINE=myisam;
INSERT INTO t1 (data) VALUES (NULL); INSERT INTO t1 (data) VALUES (NULL);
......
...@@ -1000,9 +1000,42 @@ COUNT(*) ...@@ -1000,9 +1000,42 @@ COUNT(*)
DROP FUNCTION f1; DROP FUNCTION f1;
DROP TABLE t1; DROP TABLE t1;
End of 5.1 tests End of 5.1 tests
#
# Start of 5.5 tests
#
CREATE TABLE t1 ( f1 blob, f2 blob ); CREATE TABLE t1 ( f1 blob, f2 blob );
INSERT INTO t1 VALUES ('',''); INSERT INTO t1 VALUES ('','');
SELECT f1,f2,"found row" FROM t1 WHERE f1 = f2 ; SELECT f1,f2,"found row" FROM t1 WHERE f1 = f2 ;
f1 f2 found row f1 f2 found row
found row found row
DROP TABLE t1; DROP TABLE t1;
#
# MDEV-9319 ALTER from a bigger to a smaller blob type truncates too much data
#
CREATE TABLE t1 (a MEDIUMBLOB);
INSERT INTO t1 VALUES (REPEAT(0x61,128000));
SELECT LENGTH(a) FROM t1;
LENGTH(a)
128000
ALTER TABLE t1 MODIFY a BLOB;
Warnings:
Warning 1265 Data truncated for column 'a' at row 1
SELECT LENGTH(a) FROM t1;
LENGTH(a)
65535
DROP TABLE t1;
CREATE TABLE t1 (a BLOB);
INSERT INTO t1 VALUES (REPEAT(0x61,65000));
SELECT LENGTH(a) FROM t1;
LENGTH(a)
65000
ALTER TABLE t1 MODIFY a TINYBLOB;
Warnings:
Warning 1265 Data truncated for column 'a' at row 1
SELECT LENGTH(a) FROM t1;
LENGTH(a)
255
DROP TABLE t1;
#
# End of 5.5 tests
#
...@@ -1648,6 +1648,17 @@ SHOW CREATE TABLE t2; ...@@ -1648,6 +1648,17 @@ SHOW CREATE TABLE t2;
SELECT * FROM t2; SELECT * FROM t2;
DROP TABLE t2, t1; DROP TABLE t2, t1;
--echo #
--echo # MDEV-9319 ALTER from a bigger to a smaller blob type truncates too much data
--echo #
SET NAMES utf8;
CREATE TABLE t1 (a TEXT CHARACTER SET utf8);
INSERT INTO t1 VALUES (REPEAT('A',100));
SELECT OCTET_LENGTH(a) FROM t1;
ALTER TABLE t1 MODIFY a TINYTEXT CHARACTER SET utf8;
SELECT OCTET_LENGTH(a),a FROM t1;
DROP TABLE t1;
--echo # --echo #
--echo # End of 5.5 tests --echo # End of 5.5 tests
--echo # --echo #
...@@ -1826,6 +1826,18 @@ DROP TABLE t1; ...@@ -1826,6 +1826,18 @@ DROP TABLE t1;
--echo # End of test for Bug#13581962,Bug#14096619 --echo # End of test for Bug#13581962,Bug#14096619
--echo #
--echo # MDEV-9319 ALTER from a bigger to a smaller blob type truncates too much data
--echo #
SET NAMES utf8mb4;
CREATE TABLE t1 (a TEXT CHARACTER SET utf8mb4);
INSERT INTO t1 VALUES (REPEAT('😎',100));
SELECT OCTET_LENGTH(a) FROM t1;
ALTER TABLE t1 MODIFY a TINYTEXT CHARACTER SET utf8mb4;
SELECT OCTET_LENGTH(a),a FROM t1;
DROP TABLE t1;
--echo # --echo #
--echo # End of 5.5 tests --echo # End of 5.5 tests
--echo # --echo #
......
...@@ -643,6 +643,10 @@ DROP TABLE t1; ...@@ -643,6 +643,10 @@ DROP TABLE t1;
--echo End of 5.1 tests --echo End of 5.1 tests
--echo #
--echo # Start of 5.5 tests
--echo #
# #
# Problem when comparing blobs #778901 # Problem when comparing blobs #778901
# #
...@@ -651,3 +655,24 @@ CREATE TABLE t1 ( f1 blob, f2 blob ); ...@@ -651,3 +655,24 @@ CREATE TABLE t1 ( f1 blob, f2 blob );
INSERT INTO t1 VALUES ('',''); INSERT INTO t1 VALUES ('','');
SELECT f1,f2,"found row" FROM t1 WHERE f1 = f2 ; SELECT f1,f2,"found row" FROM t1 WHERE f1 = f2 ;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # MDEV-9319 ALTER from a bigger to a smaller blob type truncates too much data
--echo #
CREATE TABLE t1 (a MEDIUMBLOB);
INSERT INTO t1 VALUES (REPEAT(0x61,128000));
SELECT LENGTH(a) FROM t1;
ALTER TABLE t1 MODIFY a BLOB;
SELECT LENGTH(a) FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a BLOB);
INSERT INTO t1 VALUES (REPEAT(0x61,65000));
SELECT LENGTH(a) FROM t1;
ALTER TABLE t1 MODIFY a TINYBLOB;
SELECT LENGTH(a) FROM t1;
DROP TABLE t1;
--echo #
--echo # End of 5.5 tests
--echo #
...@@ -7068,6 +7068,35 @@ uint32 Field_blob::get_length(const uchar *pos, uint packlength_arg) ...@@ -7068,6 +7068,35 @@ uint32 Field_blob::get_length(const uchar *pos, uint packlength_arg)
} }
/**
Copy a value from another BLOB field of the same character set.
This method is used by Copy_field, e.g. during ALTER TABLE.
*/
int Field_blob::copy_value(Field_blob *from)
{
DBUG_ASSERT(field_charset == from->charset());
int rc= 0;
uint32 length= from->get_length();
uchar *data;
from->get_ptr(&data);
if (packlength < from->packlength)
{
int well_formed_errors;
set_if_smaller(length, Field_blob::max_data_length());
length= field_charset->cset->well_formed_len(field_charset,
(const char *) data,
(const char *) data + length,
length, &well_formed_errors);
rc= report_if_important_data((const char *) data + length,
(const char *) data + from->get_length(),
true);
}
store_length(length);
bmove(ptr + packlength, (uchar*) &data, sizeof(char*));
return rc;
}
int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
{ {
ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED; ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
......
...@@ -1830,6 +1830,11 @@ protected: ...@@ -1830,6 +1830,11 @@ protected:
*/ */
String value; String value;
void store_length(uchar *i_ptr, uint i_packlength, uint32 i_number);
inline void store_length(uint32 number)
{
store_length(ptr, packlength, number);
}
public: public:
Field_blob(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, Field_blob(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg, enum utype unireg_check_arg, const char *field_name_arg,
...@@ -1902,11 +1907,6 @@ public: ...@@ -1902,11 +1907,6 @@ public:
int reset(void) { bzero(ptr, packlength+sizeof(uchar*)); return 0; } int reset(void) { bzero(ptr, packlength+sizeof(uchar*)); return 0; }
void reset_fields() { bzero((uchar*) &value,sizeof(value)); } void reset_fields() { bzero((uchar*) &value,sizeof(value)); }
uint32 get_field_buffer_size(void) { return value.alloced_length(); } uint32 get_field_buffer_size(void) { return value.alloced_length(); }
void store_length(uchar *i_ptr, uint i_packlength, uint32 i_number);
inline void store_length(uint32 number)
{
store_length(ptr, packlength, number);
}
inline uint32 get_length(uint row_offset= 0) inline uint32 get_length(uint row_offset= 0)
{ return get_length(ptr+row_offset, this->packlength); } { return get_length(ptr+row_offset, this->packlength); }
uint32 get_length(const uchar *ptr, uint packlength); uint32 get_length(const uchar *ptr, uint packlength);
...@@ -1935,6 +1935,7 @@ public: ...@@ -1935,6 +1935,7 @@ public:
{ {
set_ptr_offset(0, length, data); set_ptr_offset(0, length, data);
} }
int copy_value(Field_blob *from);
uint get_key_image(uchar *buff,uint length, imagetype type); uint get_key_image(uchar *buff,uint length, imagetype type);
void set_key_image(const uchar *buff,uint length); void set_key_image(const uchar *buff,uint length);
void sql_type(String &str) const; void sql_type(String &str) const;
......
...@@ -332,9 +332,7 @@ static void do_copy_next_number(Copy_field *copy) ...@@ -332,9 +332,7 @@ static void do_copy_next_number(Copy_field *copy)
static void do_copy_blob(Copy_field *copy) static void do_copy_blob(Copy_field *copy)
{ {
ulong length=((Field_blob*) copy->from_field)->get_length(); ((Field_blob*) copy->to_field)->copy_value(((Field_blob*) copy->from_field));
((Field_blob*) copy->to_field)->store_length(length);
memcpy(copy->to_ptr, copy->from_ptr, sizeof(char*));
} }
static void do_conv_blob(Copy_field *copy) static void do_conv_blob(Copy_field *copy)
...@@ -709,12 +707,7 @@ Copy_field::get_copy_func(Field *to,Field *from) ...@@ -709,12 +707,7 @@ Copy_field::get_copy_func(Field *to,Field *from)
if (!(from->flags & BLOB_FLAG) || from->charset() != to->charset()) if (!(from->flags & BLOB_FLAG) || from->charset() != to->charset())
return do_conv_blob; return do_conv_blob;
if (from_length != to_length) if (from_length != to_length)
{
// Correct pointer to point at char pointer
to_ptr+= to_length - to->table->s->blob_ptr_size;
from_ptr+= from_length- from->table->s->blob_ptr_size;
return do_copy_blob; return do_copy_blob;
}
} }
else else
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment