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));
|
insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a));
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1265 Data truncated for column 'v' at row 1
|
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;
|
select concat('*',v,'*',c,'*',t,'*') from t1;
|
||||||
concat('*',v,'*',c,'*',t,'*')
|
concat('*',v,'*',c,'*',t,'*')
|
||||||
*+ *+*+ *
|
*+ *+*+ *
|
||||||
|
@ -1901,6 +1901,7 @@ set @a=repeat(' ',20);
|
|||||||
insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a));
|
insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a));
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1265 Data truncated for column 'v' at row 1
|
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;
|
select concat('*',v,'*',c,'*',t,'*') from t1;
|
||||||
concat('*',v,'*',c,'*',t,'*')
|
concat('*',v,'*',c,'*',t,'*')
|
||||||
*+ *+*+ *
|
*+ *+*+ *
|
||||||
|
@ -1104,6 +1104,7 @@ set @a=repeat(' ',20);
|
|||||||
insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a));
|
insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a));
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1265 Data truncated for column 'v' at row 1
|
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;
|
select concat('*',v,'*',c,'*',t,'*') from t1;
|
||||||
concat('*',v,'*',c,'*',t,'*')
|
concat('*',v,'*',c,'*',t,'*')
|
||||||
*+ *+*+ *
|
*+ *+*+ *
|
||||||
|
@ -934,6 +934,8 @@ NULL NULL
|
|||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
CREATE TABLE t1 (col1 CHAR(5), col2 VARCHAR(6));
|
CREATE TABLE t1 (col1 CHAR(5), col2 VARCHAR(6));
|
||||||
INSERT INTO t1 VALUES ('hello', 'hello'),('he', 'he'),('hello ', 'hello ');
|
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');
|
INSERT INTO t1 (col1) VALUES ('hellobob');
|
||||||
ERROR 22001: Data too long for column 'col1' at row 1
|
ERROR 22001: Data too long for column 'col1' at row 1
|
||||||
INSERT INTO t1 (col2) VALUES ('hellobob');
|
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(0x4120, 0x4120);
|
||||||
insert into t1 values(0x412020, 0x412020);
|
insert into t1 values(0x412020, 0x412020);
|
||||||
Warnings:
|
Warnings:
|
||||||
|
Note 1265 Data truncated for column 'c' at row 1
|
||||||
Note 1265 Data truncated for column 'vc' at row 1
|
Note 1265 Data truncated for column 'vc' at row 1
|
||||||
drop table t1;
|
drop table t1;
|
||||||
set @old_sql_mode= @@sql_mode, sql_mode= 'traditional';
|
set @old_sql_mode= @@sql_mode, sql_mode= 'traditional';
|
||||||
|
@ -298,4 +298,42 @@ DROP TABLE t3;
|
|||||||
DROP PROCEDURE sp1;
|
DROP PROCEDURE sp1;
|
||||||
DROP PROCEDURE sp2;
|
DROP PROCEDURE sp2;
|
||||||
DROP PROCEDURE sp3;
|
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
|
End of 5.0 tests
|
||||||
|
@ -212,4 +212,37 @@ DROP PROCEDURE sp1;
|
|||||||
DROP PROCEDURE sp2;
|
DROP PROCEDURE sp2;
|
||||||
DROP PROCEDURE sp3;
|
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
|
--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
|
Check if we lost any important data and send a truncation error/warning
|
||||||
after storing a too long character string info a field.
|
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
report_data_too_long()
|
Field_longstr::report_if_important_data()
|
||||||
field - Field
|
ptr - Truncated rest of string
|
||||||
|
end - End of truncated string
|
||||||
|
|
||||||
RETURN
|
RETURN VALUES
|
||||||
N/A
|
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
|
int
|
||||||
report_data_too_long(Field_str *field)
|
Field_longstr::report_if_important_data(const char *ptr, const char *end)
|
||||||
{
|
{
|
||||||
if (field->table->in_use->abort_on_warning)
|
if ((ptr < end) && table->in_use->count_cuted_fields)
|
||||||
field->set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1);
|
{
|
||||||
else
|
if (test_if_important_data(field_charset, ptr, end))
|
||||||
field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
|
{
|
||||||
|
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))
|
cannot_convert_error_pos, from + length))
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
/*
|
return report_if_important_data(from_end_pos, from + length);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -6385,16 +6388,7 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
|
|||||||
cannot_convert_error_pos, from + length))
|
cannot_convert_error_pos, from + length))
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
// Check if we lost something other than just trailing spaces
|
return report_if_important_data(from_end_pos, from + length);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -7030,13 +7024,7 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
|
|||||||
cannot_convert_error_pos, from + length))
|
cannot_convert_error_pos, from + length))
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
if (from_end_pos < from + length)
|
return report_if_important_data(from_end_pos, from + length);
|
||||||
{
|
|
||||||
report_data_too_long(this);
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
oom_error:
|
oom_error:
|
||||||
/* Fatal OOM error */
|
/* Fatal OOM error */
|
||||||
|
@ -454,6 +454,8 @@ public:
|
|||||||
|
|
||||||
class Field_longstr :public Field_str
|
class Field_longstr :public Field_str
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
|
int report_if_important_data(const char *ptr, const char *end);
|
||||||
public:
|
public:
|
||||||
Field_longstr(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
|
Field_longstr(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
|
||||||
uchar null_bit_arg, utype unireg_check_arg,
|
uchar null_bit_arg, utype unireg_check_arg,
|
||||||
|
Reference in New Issue
Block a user