Produce a "truncated" warning if a value cannot be converted
into the column character set on INSERT/UPDATE. sql/sql_string.cc: New argument to report an error. sql/sql_string.h: New argument to report an error.
This commit is contained in:
parent
9b041682cc
commit
5be6c328f5
@ -349,6 +349,7 @@ alter table t1 change a a char(10) character set koi8r;
|
|||||||
select a,hex(a) from t1;
|
select a,hex(a) from t1;
|
||||||
a hex(a)
|
a hex(a)
|
||||||
ÔĹÓÔ D4C5D3D4
|
ÔĹÓÔ D4C5D3D4
|
||||||
|
delete from t1;
|
||||||
show create table t1;
|
show create table t1;
|
||||||
Table Create Table
|
Table Create Table
|
||||||
t1 CREATE TABLE `t1` (
|
t1 CREATE TABLE `t1` (
|
||||||
|
@ -166,3 +166,11 @@ ERROR HY000: Invalid utf8 character string: '
|
|||||||
SET NAMES utf8;
|
SET NAMES utf8;
|
||||||
CREATE TABLE `goodÐÌÏÈÏ` (a int);
|
CREATE TABLE `goodÐÌÏÈÏ` (a int);
|
||||||
ERROR HY000: Invalid utf8 character string: 'ÐÌÏÈÏ` (a int)'
|
ERROR HY000: Invalid utf8 character string: 'ÐÌÏÈÏ` (a int)'
|
||||||
|
set names latin1;
|
||||||
|
create table t1 (a char(10) character set koi8r, b text character set koi8r);
|
||||||
|
insert into t1 values ('test','test');
|
||||||
|
insert into t1 values ('ÊÃÕË','ÊÃÕË');
|
||||||
|
Warnings:
|
||||||
|
Warning 1265 Data truncated for column 'a' at row 1
|
||||||
|
Warning 1265 Data truncated for column 'b' at row 1
|
||||||
|
drop table t1;
|
||||||
|
@ -356,6 +356,11 @@ SELECT t, collation(t),MATCH t AGAINST ('Osnabruck') FROM t1 WHERE MATCH t AGAIN
|
|||||||
t collation(t) MATCH t AGAINST ('Osnabruck')
|
t collation(t) MATCH t AGAINST ('Osnabruck')
|
||||||
aus Osnabrück utf8_general_ci 1.591139793396
|
aus Osnabrück utf8_general_ci 1.591139793396
|
||||||
alter table t1 modify t varchar(200) collate latin1_german2_ci not null;
|
alter table t1 modify t varchar(200) collate latin1_german2_ci not null;
|
||||||
|
Warnings:
|
||||||
|
Warning 1265 Data truncated for column 't' at row 3
|
||||||
|
Warning 1265 Data truncated for column 't' at row 4
|
||||||
|
Warning 1265 Data truncated for column 't' at row 5
|
||||||
|
Warning 1265 Data truncated for column 't' at row 6
|
||||||
SELECT t, collation(t) FROM t1 WHERE MATCH t AGAINST ('Osnabrück');
|
SELECT t, collation(t) FROM t1 WHERE MATCH t AGAINST ('Osnabrück');
|
||||||
t collation(t)
|
t collation(t)
|
||||||
aus Osnabrück latin1_german2_ci
|
aus Osnabrück latin1_german2_ci
|
||||||
|
@ -207,6 +207,7 @@ alter table t1 change a a text character set cp1251;
|
|||||||
select a,hex(a) from t1;
|
select a,hex(a) from t1;
|
||||||
alter table t1 change a a char(10) character set koi8r;
|
alter table t1 change a a char(10) character set koi8r;
|
||||||
select a,hex(a) from t1;
|
select a,hex(a) from t1;
|
||||||
|
delete from t1;
|
||||||
|
|
||||||
#
|
#
|
||||||
# Test ALTER TABLE .. CHARACTER SET ..
|
# Test ALTER TABLE .. CHARACTER SET ..
|
||||||
|
@ -121,3 +121,13 @@ CREATE TABLE `good
|
|||||||
SET NAMES utf8;
|
SET NAMES utf8;
|
||||||
--error 1300
|
--error 1300
|
||||||
CREATE TABLE `goodÐÌÏÈÏ` (a int);
|
CREATE TABLE `goodÐÌÏÈÏ` (a int);
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test that we produce a warnign when conversion loses data.
|
||||||
|
#
|
||||||
|
set names latin1;
|
||||||
|
create table t1 (a char(10) character set koi8r, b text character set koi8r);
|
||||||
|
insert into t1 values ('test','test');
|
||||||
|
insert into t1 values ('ÊÃÕË','ÊÃÕË');
|
||||||
|
drop table t1;
|
||||||
|
32
sql/field.cc
32
sql/field.cc
@ -4275,9 +4275,12 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
|
|||||||
/* Convert character set if nesessary */
|
/* Convert character set if nesessary */
|
||||||
if (String::needs_conversion(length, cs, field_charset, ¬_used))
|
if (String::needs_conversion(length, cs, field_charset, ¬_used))
|
||||||
{
|
{
|
||||||
tmpstr.copy(from, length, cs, field_charset);
|
uint conv_errors;
|
||||||
|
tmpstr.copy(from, length, cs, field_charset, &conv_errors);
|
||||||
from= tmpstr.ptr();
|
from= tmpstr.ptr();
|
||||||
length= tmpstr.length();
|
length= tmpstr.length();
|
||||||
|
if (conv_errors)
|
||||||
|
error= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -4300,11 +4303,11 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
|
|||||||
from+= field_charset->cset->scan(field_charset, from, end,
|
from+= field_charset->cset->scan(field_charset, from, end,
|
||||||
MY_SEQ_SPACES);
|
MY_SEQ_SPACES);
|
||||||
if (from != end)
|
if (from != end)
|
||||||
{
|
error= 1;
|
||||||
|
}
|
||||||
|
if (error)
|
||||||
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
|
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
|
||||||
error=1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4528,16 +4531,20 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
|
|||||||
/* Convert character set if nesessary */
|
/* Convert character set if nesessary */
|
||||||
if (String::needs_conversion(length, cs, field_charset, ¬_used))
|
if (String::needs_conversion(length, cs, field_charset, ¬_used))
|
||||||
{
|
{
|
||||||
tmpstr.copy(from, length, cs, field_charset);
|
uint conv_errors;
|
||||||
|
tmpstr.copy(from, length, cs, field_charset, &conv_errors);
|
||||||
from= tmpstr.ptr();
|
from= tmpstr.ptr();
|
||||||
length= tmpstr.length();
|
length= tmpstr.length();
|
||||||
|
if (conv_errors)
|
||||||
|
error= 1;
|
||||||
}
|
}
|
||||||
if (length > field_length)
|
if (length > field_length)
|
||||||
{
|
{
|
||||||
length=field_length;
|
length=field_length;
|
||||||
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
|
|
||||||
error= 1;
|
error= 1;
|
||||||
}
|
}
|
||||||
|
if (error)
|
||||||
|
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
|
||||||
memcpy(ptr+HA_KEY_BLOB_LENGTH,from,length);
|
memcpy(ptr+HA_KEY_BLOB_LENGTH,from,length);
|
||||||
int2store(ptr, length);
|
int2store(ptr, length);
|
||||||
return error;
|
return error;
|
||||||
@ -4865,6 +4872,7 @@ void Field_blob::put_length(char *pos, uint32 length)
|
|||||||
|
|
||||||
int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
|
int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
|
||||||
{
|
{
|
||||||
|
int error= 0;
|
||||||
if (!length)
|
if (!length)
|
||||||
{
|
{
|
||||||
bzero(ptr,Field_blob::pack_length());
|
bzero(ptr,Field_blob::pack_length());
|
||||||
@ -4881,9 +4889,12 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
|
|||||||
if ((was_conversion= String::needs_conversion(length, cs, field_charset,
|
if ((was_conversion= String::needs_conversion(length, cs, field_charset,
|
||||||
¬_used)))
|
¬_used)))
|
||||||
{
|
{
|
||||||
tmpstr.copy(from, length, cs, field_charset);
|
uint conv_errors;
|
||||||
|
tmpstr.copy(from, length, cs, field_charset, &conv_errors);
|
||||||
from= tmpstr.ptr();
|
from= tmpstr.ptr();
|
||||||
length= tmpstr.length();
|
length= tmpstr.length();
|
||||||
|
if (conv_errors)
|
||||||
|
error= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
copy_length= max_data_length();
|
copy_length= max_data_length();
|
||||||
@ -4897,8 +4908,7 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
|
|||||||
min(length, copy_length),
|
min(length, copy_length),
|
||||||
copy_length);
|
copy_length);
|
||||||
if (copy_length < length)
|
if (copy_length < length)
|
||||||
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
|
error= 1;
|
||||||
|
|
||||||
Field_blob::store_length(copy_length);
|
Field_blob::store_length(copy_length);
|
||||||
if (was_conversion || table->copy_blobs || copy_length <= MAX_FIELD_WIDTH)
|
if (was_conversion || table->copy_blobs || copy_length <= MAX_FIELD_WIDTH)
|
||||||
{ // Must make a copy
|
{ // Must make a copy
|
||||||
@ -4910,6 +4920,8 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
|
|||||||
}
|
}
|
||||||
bmove(ptr+packlength,(char*) &from,sizeof(char*));
|
bmove(ptr+packlength,(char*) &from,sizeof(char*));
|
||||||
}
|
}
|
||||||
|
if (error)
|
||||||
|
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,19 +331,26 @@ bool String::set_or_copy_aligned(const char *str,uint32 arg_length,
|
|||||||
/* Copy with charset convertion */
|
/* Copy with charset convertion */
|
||||||
|
|
||||||
bool String::copy(const char *str, uint32 arg_length,
|
bool String::copy(const char *str, uint32 arg_length,
|
||||||
CHARSET_INFO *from_cs, CHARSET_INFO *to_cs)
|
CHARSET_INFO *from_cs, CHARSET_INFO *to_cs, uint *errors)
|
||||||
{
|
{
|
||||||
uint32 offset;
|
uint32 offset;
|
||||||
if (!needs_conversion(arg_length, from_cs, to_cs, &offset))
|
if (!needs_conversion(arg_length, from_cs, to_cs, &offset))
|
||||||
|
{
|
||||||
|
if (errors)
|
||||||
|
*errors= 0;
|
||||||
return copy(str, arg_length, to_cs);
|
return copy(str, arg_length, to_cs);
|
||||||
|
}
|
||||||
if ((from_cs == &my_charset_bin) && offset)
|
if ((from_cs == &my_charset_bin) && offset)
|
||||||
|
{
|
||||||
|
if (errors)
|
||||||
|
*errors= 0;
|
||||||
return copy_aligned(str, arg_length, offset, to_cs);
|
return copy_aligned(str, arg_length, offset, to_cs);
|
||||||
|
}
|
||||||
uint32 new_length= to_cs->mbmaxlen*arg_length;
|
uint32 new_length= to_cs->mbmaxlen*arg_length;
|
||||||
if (alloc(new_length))
|
if (alloc(new_length))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
str_length=copy_and_convert((char*) Ptr, new_length, to_cs,
|
str_length=copy_and_convert((char*) Ptr, new_length, to_cs,
|
||||||
str, arg_length, from_cs);
|
str, arg_length, from_cs, errors);
|
||||||
str_charset=to_cs;
|
str_charset=to_cs;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -769,7 +776,8 @@ String *copy_if_not_alloced(String *to,String *from,uint32 from_length)
|
|||||||
|
|
||||||
uint32
|
uint32
|
||||||
copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs,
|
copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs,
|
||||||
const char *from, uint32 from_length, CHARSET_INFO *from_cs)
|
const char *from, uint32 from_length, CHARSET_INFO *from_cs,
|
||||||
|
uint *errors)
|
||||||
{
|
{
|
||||||
int cnvres;
|
int cnvres;
|
||||||
my_wc_t wc;
|
my_wc_t wc;
|
||||||
@ -780,6 +788,7 @@ copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs,
|
|||||||
const uchar *) = from_cs->cset->mb_wc;
|
const uchar *) = from_cs->cset->mb_wc;
|
||||||
int (*wc_mb)(struct charset_info_st *, my_wc_t, uchar *s, uchar *e)=
|
int (*wc_mb)(struct charset_info_st *, my_wc_t, uchar *s, uchar *e)=
|
||||||
to_cs->cset->wc_mb;
|
to_cs->cset->wc_mb;
|
||||||
|
uint error_count= 0;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
@ -788,6 +797,7 @@ copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs,
|
|||||||
from+= cnvres;
|
from+= cnvres;
|
||||||
else if (cnvres == MY_CS_ILSEQ)
|
else if (cnvres == MY_CS_ILSEQ)
|
||||||
{
|
{
|
||||||
|
error_count++;
|
||||||
from++;
|
from++;
|
||||||
wc= '?';
|
wc= '?';
|
||||||
}
|
}
|
||||||
@ -799,12 +809,15 @@ outp:
|
|||||||
to+= cnvres;
|
to+= cnvres;
|
||||||
else if (cnvres == MY_CS_ILUNI && wc != '?')
|
else if (cnvres == MY_CS_ILUNI && wc != '?')
|
||||||
{
|
{
|
||||||
|
error_count++;
|
||||||
wc= '?';
|
wc= '?';
|
||||||
goto outp;
|
goto outp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (errors)
|
||||||
|
*errors= error_count;
|
||||||
return (uint32) (to - to_start);
|
return (uint32) (to - to_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ int sortcmp(const String *a,const String *b, CHARSET_INFO *cs);
|
|||||||
String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
|
String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
|
||||||
uint32 copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs,
|
uint32 copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs,
|
||||||
const char *from, uint32 from_length,
|
const char *from, uint32 from_length,
|
||||||
CHARSET_INFO *from_cs);
|
CHARSET_INFO *from_cs, uint *errors= 0);
|
||||||
|
|
||||||
class String
|
class String
|
||||||
{
|
{
|
||||||
@ -199,7 +199,7 @@ public:
|
|||||||
CHARSET_INFO *cs);
|
CHARSET_INFO *cs);
|
||||||
bool set_or_copy_aligned(const char *s, uint32 arg_length, CHARSET_INFO *cs);
|
bool set_or_copy_aligned(const char *s, uint32 arg_length, CHARSET_INFO *cs);
|
||||||
bool copy(const char*s,uint32 arg_length, CHARSET_INFO *csfrom,
|
bool copy(const char*s,uint32 arg_length, CHARSET_INFO *csfrom,
|
||||||
CHARSET_INFO *csto);
|
CHARSET_INFO *csto, uint *errors= 0);
|
||||||
bool append(const String &s);
|
bool append(const String &s);
|
||||||
bool append(const char *s);
|
bool append(const char *s);
|
||||||
bool append(const char *s,uint32 arg_length);
|
bool append(const char *s,uint32 arg_length);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user