mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Fixed bug#30059.
Server handles truncation for assignment of too-long values into CHAR/VARCHAR/TEXT columns in a different ways when the truncated characters are spaces: 1. CHAR(N) columns silently ignore end-space truncation; 2. TEXT columns post a truncation warning/error in the non-strict/strict mode. 3. VARCHAR columns always post a truncation note in any mode. Space truncation processing has been synchronised over CHAR/VARCHAR/TEXT columns: current behavior of VARCHAR columns has been propagated as standard. Binary-encoded string/BLOB columns are not affected. mysql-test/r/heap.result: Updated test case for bug#30059. mysql-test/r/innodb.result: Updated test case for bug#30059. mysql-test/r/myisam.result: Updated test case for bug#30059. mysql-test/r/strict.result: Updated test case for bug#30059. mysql-test/r/type_binary.result: Updated test case for bug#30059. mysql-test/r/warnings.result: Added test case for bug#30059. mysql-test/t/warnings.test: Added test case for bug#30059. sql/field.cc: Fixed bug#30059. The report_data_too_long function was replaced with the Field_longstr::report_if_important_data method. The Field_string::store and the Field_blob::store methods was synchronized with the Field_varstring::store method. Changes: 1. to CHAR(N): posting of space truncation note has been added in both (strict and non-strict) modes; 2. to BLOBs: a check for space truncation has been added, a warning in the non-strict mode and an error message in the strict mode have been replaced with a truncation note. Similar parts of Field_string::store, Field_blob::store and Field_varstring::store have been moved to the Field_longstr::report_if_important_data method. sql/field.h: Fixed bug#30059. The Field_longstr::report_if_important_data method has been declared.
This commit is contained in:
@ -256,6 +256,7 @@ set @a=repeat(' ',20);
|
||||
insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a));
|
||||
Warnings:
|
||||
Note 1265 Data truncated for column 'v' at row 1
|
||||
Note 1265 Data truncated for column 'c' at row 1
|
||||
select concat('*',v,'*',c,'*',t,'*') from t1;
|
||||
concat('*',v,'*',c,'*',t,'*')
|
||||
*+ *+*+ *
|
||||
|
@ -1901,6 +1901,7 @@ set @a=repeat(' ',20);
|
||||
insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a));
|
||||
Warnings:
|
||||
Note 1265 Data truncated for column 'v' at row 1
|
||||
Note 1265 Data truncated for column 'c' at row 1
|
||||
select concat('*',v,'*',c,'*',t,'*') from t1;
|
||||
concat('*',v,'*',c,'*',t,'*')
|
||||
*+ *+*+ *
|
||||
|
@ -1104,6 +1104,7 @@ set @a=repeat(' ',20);
|
||||
insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a));
|
||||
Warnings:
|
||||
Note 1265 Data truncated for column 'v' at row 1
|
||||
Note 1265 Data truncated for column 'c' at row 1
|
||||
select concat('*',v,'*',c,'*',t,'*') from t1;
|
||||
concat('*',v,'*',c,'*',t,'*')
|
||||
*+ *+*+ *
|
||||
|
@ -934,6 +934,8 @@ NULL NULL
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (col1 CHAR(5), col2 VARCHAR(6));
|
||||
INSERT INTO t1 VALUES ('hello', 'hello'),('he', 'he'),('hello ', 'hello ');
|
||||
Warnings:
|
||||
Note 1265 Data truncated for column 'col1' at row 3
|
||||
INSERT INTO t1 (col1) VALUES ('hellobob');
|
||||
ERROR 22001: Data too long for column 'col1' at row 1
|
||||
INSERT INTO t1 (col2) VALUES ('hellobob');
|
||||
|
@ -125,6 +125,7 @@ create table t1 (c char(2), vc varchar(2));
|
||||
insert into t1 values(0x4120, 0x4120);
|
||||
insert into t1 values(0x412020, 0x412020);
|
||||
Warnings:
|
||||
Note 1265 Data truncated for column 'c' at row 1
|
||||
Note 1265 Data truncated for column 'vc' at row 1
|
||||
drop table t1;
|
||||
set @old_sql_mode= @@sql_mode, sql_mode= 'traditional';
|
||||
|
@ -298,4 +298,42 @@ DROP TABLE t3;
|
||||
DROP PROCEDURE sp1;
|
||||
DROP PROCEDURE sp2;
|
||||
DROP PROCEDURE sp3;
|
||||
create table t1 (c_char char(255), c_varchar varchar(255), c_tinytext tinytext);
|
||||
create table t2 (c_tinyblob tinyblob);
|
||||
set @c = repeat(' ', 256);
|
||||
set @q = repeat('q', 256);
|
||||
set sql_mode = '';
|
||||
insert into t1 values(@c, @c, @c);
|
||||
Warnings:
|
||||
Note 1265 Data truncated for column 'c_char' at row 1
|
||||
Note 1265 Data truncated for column 'c_varchar' at row 1
|
||||
Note 1265 Data truncated for column 'c_tinytext' at row 1
|
||||
insert into t2 values(@c);
|
||||
Warnings:
|
||||
Warning 1265 Data truncated for column 'c_tinyblob' at row 1
|
||||
insert into t1 values(@q, @q, @q);
|
||||
Warnings:
|
||||
Warning 1265 Data truncated for column 'c_char' at row 1
|
||||
Warning 1265 Data truncated for column 'c_varchar' at row 1
|
||||
Warning 1265 Data truncated for column 'c_tinytext' at row 1
|
||||
insert into t2 values(@q);
|
||||
Warnings:
|
||||
Warning 1265 Data truncated for column 'c_tinyblob' at row 1
|
||||
set sql_mode = 'traditional';
|
||||
insert into t1 values(@c, @c, @c);
|
||||
Warnings:
|
||||
Note 1265 Data truncated for column 'c_char' at row 1
|
||||
Note 1265 Data truncated for column 'c_varchar' at row 1
|
||||
Note 1265 Data truncated for column 'c_tinytext' at row 1
|
||||
insert into t2 values(@c);
|
||||
ERROR 22001: Data too long for column 'c_tinyblob' at row 1
|
||||
insert into t1 values(@q, NULL, NULL);
|
||||
ERROR 22001: Data too long for column 'c_char' at row 1
|
||||
insert into t1 values(NULL, @q, NULL);
|
||||
ERROR 22001: Data too long for column 'c_varchar' at row 1
|
||||
insert into t1 values(NULL, NULL, @q);
|
||||
ERROR 22001: Data too long for column 'c_tinytext' at row 1
|
||||
insert into t2 values(@q);
|
||||
ERROR 22001: Data too long for column 'c_tinyblob' at row 1
|
||||
drop table t1, t2;
|
||||
End of 5.0 tests
|
||||
|
@ -212,4 +212,37 @@ DROP PROCEDURE sp1;
|
||||
DROP PROCEDURE sp2;
|
||||
DROP PROCEDURE sp3;
|
||||
|
||||
|
||||
#
|
||||
# Bug#30059: End-space truncation warnings are inconsistent or incorrect
|
||||
#
|
||||
|
||||
create table t1 (c_char char(255), c_varchar varchar(255), c_tinytext tinytext);
|
||||
create table t2 (c_tinyblob tinyblob); # not affected by bug, for regression testing
|
||||
set @c = repeat(' ', 256);
|
||||
set @q = repeat('q', 256);
|
||||
|
||||
set sql_mode = '';
|
||||
|
||||
insert into t1 values(@c, @c, @c);
|
||||
insert into t2 values(@c);
|
||||
insert into t1 values(@q, @q, @q);
|
||||
insert into t2 values(@q);
|
||||
|
||||
set sql_mode = 'traditional';
|
||||
|
||||
insert into t1 values(@c, @c, @c);
|
||||
--error 1406
|
||||
insert into t2 values(@c);
|
||||
--error 1406
|
||||
insert into t1 values(@q, NULL, NULL);
|
||||
--error 1406
|
||||
insert into t1 values(NULL, @q, NULL);
|
||||
--error 1406
|
||||
insert into t1 values(NULL, NULL, @q);
|
||||
--error 1406
|
||||
insert into t2 values(@q);
|
||||
|
||||
drop table t1, t2;
|
||||
|
||||
--echo End of 5.0 tests
|
||||
|
74
sql/field.cc
74
sql/field.cc
@ -5861,26 +5861,41 @@ check_string_copy_error(Field_str *field,
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Send a truncation warning or a truncation error
|
||||
after storing a too long character string info a field.
|
||||
Check if we lost any important data and send a truncation error/warning
|
||||
|
||||
SYNOPSIS
|
||||
report_data_too_long()
|
||||
field - Field
|
||||
Field_longstr::report_if_important_data()
|
||||
ptr - Truncated rest of string
|
||||
end - End of truncated string
|
||||
|
||||
RETURN
|
||||
N/A
|
||||
RETURN VALUES
|
||||
0 - None was truncated (or we don't count cut fields)
|
||||
2 - Some bytes was truncated
|
||||
|
||||
NOTE
|
||||
Check if we lost any important data (anything in a binary string,
|
||||
or any non-space in others). If only trailing spaces was lost,
|
||||
send a truncation note, otherwise send a truncation error.
|
||||
*/
|
||||
|
||||
inline void
|
||||
report_data_too_long(Field_str *field)
|
||||
int
|
||||
Field_longstr::report_if_important_data(const char *ptr, const char *end)
|
||||
{
|
||||
if (field->table->in_use->abort_on_warning)
|
||||
field->set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1);
|
||||
else
|
||||
field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
|
||||
if ((ptr < end) && table->in_use->count_cuted_fields)
|
||||
{
|
||||
if (test_if_important_data(field_charset, ptr, end))
|
||||
{
|
||||
if (table->in_use->abort_on_warning)
|
||||
set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1);
|
||||
else
|
||||
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
|
||||
}
|
||||
else /* If we lost only spaces then produce a NOTE, not a WARNING */
|
||||
set_warning(MYSQL_ERROR::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1);
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -5914,19 +5929,7 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
|
||||
cannot_convert_error_pos, from + length))
|
||||
return 2;
|
||||
|
||||
/*
|
||||
Check if we lost any important data (anything in a binary string,
|
||||
or any non-space in others).
|
||||
*/
|
||||
if ((from_end_pos < from + length) && table->in_use->count_cuted_fields)
|
||||
{
|
||||
if (test_if_important_data(field_charset, from_end_pos, from + length))
|
||||
{
|
||||
report_data_too_long(this);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return report_if_important_data(from_end_pos, from + length);
|
||||
}
|
||||
|
||||
|
||||
@ -6385,16 +6388,7 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
|
||||
cannot_convert_error_pos, from + length))
|
||||
return 2;
|
||||
|
||||
// Check if we lost something other than just trailing spaces
|
||||
if ((from_end_pos < from + length) && table->in_use->count_cuted_fields)
|
||||
{
|
||||
if (test_if_important_data(field_charset, from_end_pos, from + length))
|
||||
report_data_too_long(this);
|
||||
else /* If we lost only spaces then produce a NOTE, not a WARNING */
|
||||
set_warning(MYSQL_ERROR::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1);
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
return report_if_important_data(from_end_pos, from + length);
|
||||
}
|
||||
|
||||
|
||||
@ -7030,13 +7024,7 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
|
||||
cannot_convert_error_pos, from + length))
|
||||
return 2;
|
||||
|
||||
if (from_end_pos < from + length)
|
||||
{
|
||||
report_data_too_long(this);
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return report_if_important_data(from_end_pos, from + length);
|
||||
|
||||
oom_error:
|
||||
/* Fatal OOM error */
|
||||
|
@ -454,6 +454,8 @@ public:
|
||||
|
||||
class Field_longstr :public Field_str
|
||||
{
|
||||
protected:
|
||||
int report_if_important_data(const char *ptr, const char *end);
|
||||
public:
|
||||
Field_longstr(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
|
||||
uchar null_bit_arg, utype unireg_check_arg,
|
||||
|
Reference in New Issue
Block a user