diff options
38 files changed, 564 insertions, 489 deletions
diff --git a/include/m_ctype.h b/include/m_ctype.h index 85397796e73..7f4a13f0fae 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -134,7 +134,7 @@ typedef struct charset_info_st ulong (*strntoul)(struct charset_info_st *, const char *s, uint l, char **e, int base); longlong (*strntoll)(struct charset_info_st *, const char *s, uint l, char **e, int base); ulonglong (*strntoull)(struct charset_info_st *, const char *s, uint l, char **e, int base); - double (*strntod)(struct charset_info_st *, const char *s, uint l, char **e); + double (*strntod)(struct charset_info_st *, char *s, uint l, char **e); } CHARSET_INFO; @@ -178,7 +178,7 @@ long my_strntol_8bit(CHARSET_INFO *, const char *s, uint l,char **e, int ulong my_strntoul_8bit(CHARSET_INFO *, const char *s, uint l,char **e, int base); longlong my_strntoll_8bit(CHARSET_INFO *, const char *s, uint l,char **e, int base); ulonglong my_strntoull_8bit(CHARSET_INFO *, const char *s, uint l,char **e, int base); -double my_strntod_8bit(CHARSET_INFO *, const char *s, uint l,char **e); +double my_strntod_8bit(CHARSET_INFO *, char *s, uint l,char **e); int my_l10tostr_8bit(CHARSET_INFO *, char *to, uint l, int radix, long int val); int my_ll10tostr_8bit(CHARSET_INFO *, char *to, uint l, int radix, longlong val); diff --git a/include/m_string.h b/include/m_string.h index c6943613b1a..fabd6c9bb59 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -238,6 +238,12 @@ extern ulonglong strtoull(const char *str, char **ptr, int base); #endif #endif +/* my_vsnprintf.c */ + +extern int my_vsnprintf( char *str, size_t n, + const char *format, va_list ap ); +extern int my_snprintf(char* to, size_t n, const char* fmt, ...); + #if defined(__cplusplus) && !defined(OS2) } #endif diff --git a/include/my_sys.h b/include/my_sys.h index 975990ca7fc..3d81a9e9219 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -569,9 +569,6 @@ extern int my_error _VARARGS((int nr,myf MyFlags, ...)); extern int my_printf_error _VARARGS((uint my_err, const char *format, myf MyFlags, ...) __attribute__ ((format (printf, 2, 4)))); -extern int my_vsnprintf( char *str, size_t n, - const char *format, va_list ap ); -extern int my_snprintf(char* to, size_t n, const char* fmt, ...); extern int my_message(uint my_err, const char *str,myf MyFlags); extern int my_message_no_curses(uint my_err, const char *str,myf MyFlags); extern int my_message_curses(uint my_err, const char *str,myf MyFlags); diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared index 4d8b703fb2d..08128b3936d 100644 --- a/libmysql/Makefile.shared +++ b/libmysql/Makefile.shared @@ -37,7 +37,7 @@ mystringsobjects = strmov.lo strxmov.lo strxnmov.lo strnmov.lo \ int2str.lo str2int.lo strinstr.lo strcont.lo \ strcend.lo bcmp.lo \ bchange.lo bmove.lo bmove_upp.lo longlong2str.lo \ - strtoull.lo strtoll.lo llstr.lo \ + strtoull.lo strtoll.lo llstr.lo my_vsnprintf.lo \ ctype.lo ctype-simple.lo ctype-bin.lo ctype-mb.lo \ ctype-big5.lo ctype-czech.lo ctype-euc_kr.lo \ ctype-win1250ch.lo ctype-utf8.lo \ @@ -60,7 +60,7 @@ mysysobjects1 = my_init.lo my_static.lo my_malloc.lo my_realloc.lo \ my_compress.lo array.lo my_once.lo list.lo my_net.lo \ charset.lo xml.lo hash.lo mf_iocache.lo \ mf_iocache2.lo my_seek.lo \ - my_pread.lo mf_cache.lo my_vsnprintf.lo md5.lo sha1.lo\ + my_pread.lo mf_cache.lo md5.lo sha1.lo\ my_getopt.lo my_gethostbyname.lo my_port.lo sqlobjects = net.lo diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index a4be4195ac8..456dfa860df 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -53,7 +53,7 @@ SHOW FULL COLUMNS FROM t1; Field Type Collation Null Key Default Extra Privileges Comment GROUP_ID int(10) unsigned binary PRI 0 select,insert,update,references LANG_ID smallint(5) unsigned binary PRI 0 select,insert,update,references -NAME char(80) character set latin1 latin1 MUL select,insert,update,references +NAME char(80) latin1 MUL select,insert,update,references DROP TABLE t1; create table t1 (n int); insert into t1 values(9),(3),(12),(10); @@ -120,5 +120,5 @@ alter table t2 rename t1, add c char(10) comment "no comment"; show columns from t1; Field Type Collation Null Key Default Extra i int(10) unsigned binary PRI NULL auto_increment -c char(10) character set latin1 latin1 YES NULL +c char(10) latin1 YES NULL drop table t1; diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index affda14b4ba..88b9bfce51a 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -76,10 +76,10 @@ create table t1(x varchar(50) ); create table t2 select x from t1 where 1=2; describe t1; Field Type Collation Null Key Default Extra -x varchar(50) character set latin1 latin1 YES NULL +x varchar(50) latin1 YES NULL describe t2; Field Type Collation Null Key Default Extra -x char(50) character set latin1 latin1 YES NULL +x char(50) latin1 YES NULL drop table t2; create table t2 select now() as a , curtime() as b, curdate() as c , 1+1 as d , 1.0 + 1 as e , 33333333333333333 + 3 as f; describe t2; @@ -181,7 +181,7 @@ show create table t3; Table Create Table t3 CREATE TABLE `t3` ( `id` int(11) NOT NULL default '0', - `name` char(20) character set latin1 default NULL + `name` char(20) default NULL ) TYPE=MyISAM CHARSET=latin1 select * from t3; id name @@ -204,7 +204,7 @@ show create table t3; Table Create Table t3 CREATE TABLE `t3` ( `id` int(11) NOT NULL default '0', - `name` char(20) character set latin1 default NULL + `name` char(20) default NULL ) TYPE=MyISAM CHARSET=latin1 select * from t3; id name @@ -219,14 +219,14 @@ show create table t3; Table Create Table t3 CREATE TEMPORARY TABLE `t3` ( `id` int(11) NOT NULL default '0', - `name` char(20) character set latin1 default NULL + `name` char(20) default NULL ) TYPE=MyISAM CHARSET=latin1 create table t2 like t3; show create table t2; Table Create Table t2 CREATE TABLE `t2` ( `id` int(11) NOT NULL default '0', - `name` char(20) character set latin1 default NULL + `name` char(20) default NULL ) TYPE=MyISAM CHARSET=latin1 select * from t2; id name diff --git a/mysql-test/r/ctype_many.result b/mysql-test/r/ctype_many.result index 3a9d0ec5da5..91a43634bcb 100644 --- a/mysql-test/r/ctype_many.result +++ b/mysql-test/r/ctype_many.result @@ -22,23 +22,23 @@ Table Create Table t1 CREATE TABLE `t1` ( `comment` char(32) character set latin2 NOT NULL default '', `koi8_ru_f` char(32) character set koi8r NOT NULL default '', - `latin5_f` char(32) character set latin5 NOT NULL default '' + `latin5_f` char(32) NOT NULL default '' ) TYPE=MyISAM CHARSET=latin5 ALTER TABLE t1 CHARSET=latin2; ALTER TABLE t1 ADD latin2_f CHAR(32) NOT NULL; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `comment` char(32) character set latin2 NOT NULL default '', + `comment` char(32) NOT NULL default '', `koi8_ru_f` char(32) character set koi8r NOT NULL default '', `latin5_f` char(32) character set latin5 NOT NULL default '', - `latin2_f` char(32) character set latin2 NOT NULL default '' + `latin2_f` char(32) NOT NULL default '' ) TYPE=MyISAM CHARSET=latin2 ALTER TABLE t1 DROP latin2_f, DROP latin5_f; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `comment` char(32) character set latin2 NOT NULL default '', + `comment` char(32) NOT NULL default '', `koi8_ru_f` char(32) character set koi8r NOT NULL default '' ) TYPE=MyISAM CHARSET=latin2 INSERT INTO t1 (koi8_ru_f,comment) VALUES ('a','LAT SMALL A'); diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index 66aa7311542..1382c31d145 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -141,7 +141,7 @@ show create table t2; Table Create Table t2 CREATE TABLE `t2` ( `ticket` int(11) default NULL, - `inhalt` text character set latin1, + `inhalt` text, KEY `tig` (`ticket`), FULLTEXT KEY `tix` (`inhalt`) ) TYPE=MyISAM CHARSET=latin1 diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 110b8707bc8..f5bbf082730 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -805,7 +805,7 @@ create table t1 (a char(20), index (a(5))) type=innodb; show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` char(20) character set latin1 default NULL, + `a` char(20) default NULL, KEY `a` (`a`) ) TYPE=InnoDB CHARSET=latin1 drop table t1; diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index 772ed0349da..9199f291c08 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -172,7 +172,7 @@ show create table t3; Table Create Table t3 CREATE TABLE `t3` ( `a` int(11) NOT NULL default '0', - `b` char(20) character set latin1 default NULL, + `b` char(20) default NULL, KEY `a` (`a`) ) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(t1,t2) create table t4 (a int not null, b char(10), key(a)) type=MERGE UNION=(t1,t2); diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index bba10f408cb..9ed54f7c253 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -3221,17 +3221,17 @@ Field Type Collation Null Key Default Extra Privileges Comment auto int(11) binary PRI NULL auto_increment select,insert,update,references fld1 int(6) unsigned zerofill binary UNI 000000 select,insert,update,references companynr tinyint(2) unsigned zerofill binary 00 select,insert,update,references -fld3 char(30) character set latin1 latin1 MUL select,insert,update,references -fld4 char(35) character set latin1 latin1 select,insert,update,references -fld5 char(35) character set latin1 latin1 select,insert,update,references -fld6 char(4) character set latin1 latin1 select,insert,update,references +fld3 char(30) latin1 MUL select,insert,update,references +fld4 char(35) latin1 select,insert,update,references +fld5 char(35) latin1 select,insert,update,references +fld6 char(4) latin1 select,insert,update,references show full columns from t2 from test like 'f%'; Field Type Collation Null Key Default Extra Privileges Comment fld1 int(6) unsigned zerofill binary UNI 000000 select,insert,update,references -fld3 char(30) character set latin1 latin1 MUL select,insert,update,references -fld4 char(35) character set latin1 latin1 select,insert,update,references -fld5 char(35) character set latin1 latin1 select,insert,update,references -fld6 char(4) character set latin1 latin1 select,insert,update,references +fld3 char(30) latin1 MUL select,insert,update,references +fld4 char(35) latin1 select,insert,update,references +fld5 char(35) latin1 select,insert,update,references +fld6 char(4) latin1 select,insert,update,references show full columns from t2 from test like 's%'; Field Type Collation Null Key Default Extra Privileges Comment show keys from t2; diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index 94170638730..d2bdc4f9401 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -93,14 +93,14 @@ c int not null comment 'int column' show create table t1 ; Table Create Table t1 CREATE TABLE `t1` ( - `test_set` set('val1','val2','val3') character set latin1 NOT NULL default '', - `name` char(20) character set latin1 default 'O''Brien' COMMENT 'O''Brien as default', + `test_set` set('val1','val2','val3') NOT NULL default '', + `name` char(20) default 'O''Brien' COMMENT 'O''Brien as default', `c` int(11) NOT NULL default '0' COMMENT 'int column' ) TYPE=MyISAM CHARSET=latin1 COMMENT='it''s a table' show full columns from t1; Field Type Collation Null Key Default Extra Privileges Comment -test_set set('val1','val2','val3') character set latin1 latin1 select,insert,update,references -name char(20) character set latin1 latin1 YES O'Brien select,insert,update,references O'Brien as default +test_set set('val1','val2','val3') latin1 select,insert,update,references +name char(20) latin1 YES O'Brien select,insert,update,references O'Brien as default c int(11) binary 0 select,insert,update,references int column drop table t1; create table t1 (a int not null, unique aa (a)); @@ -133,7 +133,7 @@ show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL default '0', - `b` char(10) character set latin1 default NULL, + `b` char(10) default NULL, KEY `b` (`b`) ) TYPE=MyISAM CHARSET=latin1 MIN_ROWS=10 MAX_ROWS=100 AVG_ROW_LENGTH=10 PACK_KEYS=1 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=FIXED COMMENT='test' alter table t1 MAX_ROWS=200 ROW_FORMAT=dynamic PACK_KEYS=0; @@ -141,7 +141,7 @@ show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL default '0', - `b` varchar(10) character set latin1 default NULL, + `b` varchar(10) default NULL, KEY `b` (`b`) ) TYPE=MyISAM CHARSET=latin1 MIN_ROWS=10 MAX_ROWS=200 AVG_ROW_LENGTH=10 PACK_KEYS=0 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC COMMENT='test' ALTER TABLE t1 AVG_ROW_LENGTH=0 CHECKSUM=0 COMMENT="" MIN_ROWS=0 MAX_ROWS=0 PACK_KEYS=DEFAULT DELAY_KEY_WRITE=0 ROW_FORMAT=default; @@ -149,7 +149,7 @@ show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL default '0', - `b` varchar(10) character set latin1 default NULL, + `b` varchar(10) default NULL, KEY `b` (`b`) ) TYPE=MyISAM CHARSET=latin1 drop table t1; diff --git a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result index 3248e3c5c80..ba8e01d6319 100644 --- a/mysql-test/r/type_blob.result +++ b/mysql-test/r/type_blob.result @@ -3,10 +3,10 @@ CREATE TABLE t1 (a blob, b text, c blob(250), d text(70000), e text(70000000)); show columns from t1; Field Type Collation Null Key Default Extra a blob binary YES NULL -b text character set latin1 latin1 YES NULL +b text latin1 YES NULL c blob binary YES NULL -d mediumtext character set latin1 latin1 YES NULL -e longtext character set latin1 latin1 YES NULL +d mediumtext latin1 YES NULL +e longtext latin1 YES NULL CREATE TABLE t2 (a char(257), b varchar(70000) binary, c varchar(70000000)); Warnings: Warning 1244 Converting column 'a' from CHAR to TEXT @@ -14,14 +14,14 @@ Warning 1244 Converting column 'b' from CHAR to BLOB Warning 1244 Converting column 'c' from CHAR to TEXT show columns from t2; Field Type Collation Null Key Default Extra -a text character set latin1 latin1 YES NULL +a text latin1 YES NULL b mediumblob binary YES NULL -c longtext character set latin1 latin1 YES NULL +c longtext latin1 YES NULL create table t3 (a long, b long byte); show create TABLE t3; Table Create Table t3 CREATE TABLE `t3` ( - `a` mediumtext character set latin1, + `a` mediumtext, `b` mediumblob ) TYPE=MyISAM CHARSET=latin1 drop table t1,t2,t3 @@ -70,15 +70,15 @@ update t1 set c="",b=null where c="1"; lock tables t1 READ; show full fields from t1; Field Type Collation Null Key Default Extra Privileges Comment -t text character set latin1 latin1 YES NULL select,insert,update,references -c varchar(10) character set latin1 latin1 YES NULL select,insert,update,references +t text latin1 YES NULL select,insert,update,references +c varchar(10) latin1 YES NULL select,insert,update,references b blob binary YES NULL select,insert,update,references d varchar(10) binary binary YES NULL select,insert,update,references lock tables t1 WRITE; show full fields from t1; Field Type Collation Null Key Default Extra Privileges Comment -t text character set latin1 latin1 YES NULL select,insert,update,references -c varchar(10) character set latin1 latin1 YES NULL select,insert,update,references +t text latin1 YES NULL select,insert,update,references +c varchar(10) latin1 YES NULL select,insert,update,references b blob binary YES NULL select,insert,update,references d varchar(10) binary binary YES NULL select,insert,update,references unlock tables; diff --git a/mysql-test/r/type_enum.result b/mysql-test/r/type_enum.result index 51e11d259eb..c0f0be246c9 100644 --- a/mysql-test/r/type_enum.result +++ b/mysql-test/r/type_enum.result @@ -1626,13 +1626,13 @@ create table t1 (a enum (' ','a','b') not null); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` enum('','a','b') character set latin1 NOT NULL default '' + `a` enum('','a','b') NOT NULL default '' ) TYPE=MyISAM CHARSET=latin1 drop table t1; create table t1 (a enum (' ','a','b ') not null default 'b '); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` enum('','a','b') character set latin1 NOT NULL default 'b' + `a` enum('','a','b') NOT NULL default 'b' ) TYPE=MyISAM CHARSET=latin1 drop table t1; diff --git a/mysql-test/r/type_ranges.result b/mysql-test/r/type_ranges.result index b570513a5e7..19f1ac2b4d7 100644 --- a/mysql-test/r/type_ranges.result +++ b/mysql-test/r/type_ranges.result @@ -40,7 +40,7 @@ KEY (options,flags) show full fields from t1; Field Type Collation Null Key Default Extra Privileges Comment auto int(5) unsigned binary PRI NULL auto_increment select,insert,update,references -string varchar(10) character set latin1 latin1 YES hello select,insert,update,references +string varchar(10) latin1 YES hello select,insert,update,references tiny tinyint(4) binary MUL 0 select,insert,update,references short smallint(6) binary MUL 1 select,insert,update,references medium mediumint(8) binary MUL 0 select,insert,update,references @@ -61,8 +61,8 @@ blob_col blob binary YES NULL select,insert,update,references tinyblob_col tinyblob binary YES NULL select,insert,update,references mediumblob_col mediumblob binary select,insert,update,references longblob_col longblob binary select,insert,update,references -options enum('one','two','tree') character set latin1 latin1 MUL one select,insert,update,references -flags set('one','two','tree') character set latin1 latin1 select,insert,update,references +options enum('one','two','tree') latin1 MUL one select,insert,update,references +flags set('one','two','tree') latin1 select,insert,update,references show keys from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment t1 0 PRIMARY 1 auto A 0 NULL NULL BTREE @@ -170,7 +170,7 @@ update t2 set string="changed" where auto=16; show full columns from t1; Field Type Collation Null Key Default Extra Privileges Comment auto int(5) unsigned binary MUL NULL auto_increment select,insert,update,references -string varchar(10) character set latin1 latin1 YES new defaul select,insert,update,references +string varchar(10) latin1 YES new defaul select,insert,update,references tiny tinyint(4) binary MUL 0 select,insert,update,references short smallint(6) binary MUL 0 select,insert,update,references medium mediumint(8) binary MUL 0 select,insert,update,references @@ -184,19 +184,19 @@ umedium mediumint(8) unsigned binary MUL 0 select,insert,update,references ulong int(11) unsigned binary MUL 0 select,insert,update,references ulonglong bigint(13) unsigned binary MUL 0 select,insert,update,references time_stamp timestamp latin1 YES NULL select,insert,update,references -date_field varchar(10) character set latin1 latin1 YES NULL select,insert,update,references +date_field varchar(10) latin1 YES NULL select,insert,update,references time_field time latin1 YES NULL select,insert,update,references date_time datetime latin1 YES NULL select,insert,update,references -new_blob_col varchar(20) character set latin1 latin1 YES NULL select,insert,update,references +new_blob_col varchar(20) latin1 YES NULL select,insert,update,references tinyblob_col tinyblob binary YES NULL select,insert,update,references mediumblob_col mediumblob binary select,insert,update,references -options enum('one','two','tree') character set latin1 latin1 MUL one select,insert,update,references -flags set('one','two','tree') character set latin1 latin1 select,insert,update,references -new_field varchar(10) character set latin1 latin1 new select,insert,update,references +options enum('one','two','tree') latin1 MUL one select,insert,update,references +flags set('one','two','tree') latin1 select,insert,update,references +new_field varchar(10) latin1 new select,insert,update,references show full columns from t2; Field Type Collation Null Key Default Extra Privileges Comment auto int(5) unsigned binary 0 select,insert,update,references -string varchar(10) character set latin1 latin1 YES new defaul select,insert,update,references +string varchar(10) latin1 YES new defaul select,insert,update,references tiny tinyint(4) binary 0 select,insert,update,references short smallint(6) binary 0 select,insert,update,references medium mediumint(8) binary 0 select,insert,update,references @@ -210,15 +210,15 @@ umedium mediumint(8) unsigned binary 0 select,insert,update,references ulong int(11) unsigned binary 0 select,insert,update,references ulonglong bigint(13) unsigned binary 0 select,insert,update,references time_stamp timestamp latin1 YES NULL select,insert,update,references -date_field varchar(10) character set latin1 latin1 YES NULL select,insert,update,references +date_field varchar(10) latin1 YES NULL select,insert,update,references time_field time latin1 YES NULL select,insert,update,references date_time datetime latin1 YES NULL select,insert,update,references -new_blob_col varchar(20) character set latin1 latin1 YES NULL select,insert,update,references +new_blob_col varchar(20) latin1 YES NULL select,insert,update,references tinyblob_col tinyblob binary YES NULL select,insert,update,references mediumblob_col mediumblob binary select,insert,update,references -options enum('one','two','tree') character set latin1 latin1 one select,insert,update,references -flags set('one','two','tree') character set latin1 latin1 select,insert,update,references -new_field varchar(10) character set latin1 latin1 new select,insert,update,references +options enum('one','two','tree') latin1 one select,insert,update,references +flags set('one','two','tree') latin1 select,insert,update,references +new_field varchar(10) latin1 new select,insert,update,references select t1.auto,t2.auto from t1,t2 where t1.auto=t2.auto and ((t1.string<>t2.string and (t1.string is not null or t2.string is not null)) or (t1.tiny<>t2.tiny and (t1.tiny is not null or t2.tiny is not null)) or (t1.short<>t2.short and (t1.short is not null or t2.short is not null)) or (t1.medium<>t2.medium and (t1.medium is not null or t2.medium is not null)) or (t1.long_int<>t2.long_int and (t1.long_int is not null or t2.long_int is not null)) or (t1.longlong<>t2.longlong and (t1.longlong is not null or t2.longlong is not null)) or (t1.real_float<>t2.real_float and (t1.real_float is not null or t2.real_float is not null)) or (t1.real_double<>t2.real_double and (t1.real_double is not null or t2.real_double is not null)) or (t1.utiny<>t2.utiny and (t1.utiny is not null or t2.utiny is not null)) or (t1.ushort<>t2.ushort and (t1.ushort is not null or t2.ushort is not null)) or (t1.umedium<>t2.umedium and (t1.umedium is not null or t2.umedium is not null)) or (t1.ulong<>t2.ulong and (t1.ulong is not null or t2.ulong is not null)) or (t1.ulonglong<>t2.ulonglong and (t1.ulonglong is not null or t2.ulonglong is not null)) or (t1.time_stamp<>t2.time_stamp and (t1.time_stamp is not null or t2.time_stamp is not null)) or (t1.date_field<>t2.date_field and (t1.date_field is not null or t2.date_field is not null)) or (t1.time_field<>t2.time_field and (t1.time_field is not null or t2.time_field is not null)) or (t1.date_time<>t2.date_time and (t1.date_time is not null or t2.date_time is not null)) or (t1.new_blob_col<>t2.new_blob_col and (t1.new_blob_col is not null or t2.new_blob_col is not null)) or (t1.tinyblob_col<>t2.tinyblob_col and (t1.tinyblob_col is not null or t2.tinyblob_col is not null)) or (t1.mediumblob_col<>t2.mediumblob_col and (t1.mediumblob_col is not null or t2.mediumblob_col is not null)) or (t1.options<>t2.options and (t1.options is not null or t2.options is not null)) or (t1.flags<>t2.flags and (t1.flags is not null or t2.flags is not null)) or (t1.new_field<>t2.new_field and (t1.new_field is not null or t2.new_field is not null))); auto auto 16 16 @@ -231,8 +231,8 @@ show full columns from t2; Field Type Collation Null Key Default Extra Privileges Comment auto bigint(17) unsigned binary PRI 0 select,insert,update,references t1 bigint(1) binary 0 select,insert,update,references -t2 char(1) character set latin1 latin1 select,insert,update,references -t3 mediumtext character set latin1 latin1 select,insert,update,references +t2 char(1) latin1 select,insert,update,references +t3 mediumtext latin1 select,insert,update,references t4 mediumblob binary select,insert,update,references select * from t2; auto t1 t2 t3 t4 diff --git a/mysql-test/r/type_set.result b/mysql-test/r/type_set.result index 256937c586a..b0ea1b69e59 100644 --- a/mysql-test/r/type_set.result +++ b/mysql-test/r/type_set.result @@ -3,13 +3,13 @@ create table t1 (a set (' ','a','b') not null); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` set('','a','b') character set latin1 NOT NULL default '' + `a` set('','a','b') NOT NULL default '' ) TYPE=MyISAM CHARSET=latin1 drop table t1; create table t1 (a set (' ','a','b ') not null default 'b '); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` set('','a','b') character set latin1 NOT NULL default 'b' + `a` set('','a','b') NOT NULL default 'b' ) TYPE=MyISAM CHARSET=latin1 drop table t1; diff --git a/mysys/Makefile.am b/mysys/Makefile.am index c8b7987a506..a50dd51a174 100644 --- a/mysys/Makefile.am +++ b/mysys/Makefile.am @@ -50,7 +50,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c\ my_getopt.c my_mkdir.c \ default.c my_compress.c checksum.c raid.cc \ my_net.c my_semaphore.c my_port.c \ - my_vsnprintf.c charset.c xml.c my_bitmap.c my_bit.c md5.c \ + charset.c xml.c my_bitmap.c my_bit.c md5.c \ my_gethostbyname.c rijndael.c my_aes.c sha1.c \ my_handler.c EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \ diff --git a/sql/field.cc b/sql/field.cc index 21330a2ffaa..f81f72635b9 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -34,8 +34,6 @@ // Maximum allowed exponent value for converting string to decimal #define MAX_EXPONENT 1024 - - /***************************************************************************** Instansiate templates and static variables *****************************************************************************/ @@ -67,39 +65,44 @@ void Field_num::prepend_zeros(String *value) /* Test if given number is a int (or a fixed format float with .000) - This is only used to give warnings in ALTER TABLE or LOAD DATA... + + SYNOPSIS + test_if_int() + str String to test + end Pointer to char after last used digit + cs Character set + + NOTES + This is called after one has called my_strntol() or similar function. + This is only used to give warnings in ALTER TABLE or LOAD DATA... + + TODO + Make this multi-byte-character safe + + RETURN + 0 ok + 1 error */ -bool test_if_int(const char *str,int length, CHARSET_INFO *cs) +bool test_if_int(const char *str, int length, const char *int_end, + CHARSET_INFO *cs) { + if (str == int_end) + return 0; // Empty string const char *end=str+length; + if ((str= int_end) == end) + return 1; // All digits was used - cs=system_charset_info; // QQ move test_if_int into CHARSET_INFO struct - - // Allow start space - while (str != end && my_isspace(cs,*str)) - str++; /* purecov: inspected */ - if (str != end && (*str == '-' || *str == '+')) - str++; - if (str == end) - return 0; // Error: Empty string - for (; str != end ; str++) + /* Allow end .0000 */ + if (*str == '.') { - if (!my_isdigit(cs,*str)) - { - if (*str == '.') - { // Allow '.0000' - for (str++ ; str != end && *str == '0'; str++) ; - if (str == end) - return 1; - } - if (!my_isspace(cs,*str)) - return 0; - for (str++ ; str != end ; str++) - if (!my_isspace(cs,*str)) - return 0; - return 1; - } + for (str++ ; str != end && *str == '0'; str++) ; + } + /* Allow end space */ + for (str++ ; str != end ; str++) + { + if (!my_isspace(cs,*str)) + return 0; } return 1; } @@ -107,7 +110,7 @@ bool test_if_int(const char *str,int length, CHARSET_INFO *cs) static bool test_if_real(const char *str,int length, CHARSET_INFO *cs) { - cs=system_charset_info; // QQ move test_if_int into CHARSET_INFO struct + cs= system_charset_info; // QQ move test_if_real into CHARSET_INFO struct while (length && my_isspace(cs,*str)) { // Allow start space @@ -207,17 +210,10 @@ bool Field::send_binary(Protocol *protocol) void Field_num::add_zerofill_and_unsigned(String &res) const { - uint oldlen=res.length(); - if (oldlen < res.alloced_length()) - { - uint len=res.alloced_length()-oldlen; - char *end=(char*)(res.ptr()+oldlen); - CHARSET_INFO *cs=res.charset(); - len=cs->snprintf(cs,end,len,"%s%s", - unsigned_flag ? " unsigned" : "", - zerofill ? " zerofill" : ""); - res.length(len+oldlen); - } + if (unsigned_flag) + res.append(" unsigned"); + if (zerofill) + res.append(" zerofill"); } void Field_num::make_field(Send_field *field) @@ -247,19 +243,15 @@ void Field_str::make_field(Send_field *field) field->decimals=0; } + void Field_str::add_binary_or_charset(String &res) const { - uint oldlen=res.length(); - if (oldlen < res.alloced_length()) + if (binary()) + res.append(" binary"); + else if (field_charset != table->table_charset) { - CHARSET_INFO *cs=res.charset(); - uint len=res.alloced_length() - oldlen; - char *end=(char*)(res.ptr()+oldlen); - if (binary()) - len=cs->snprintf(cs,end,len," binary"); - else - len=cs->snprintf(cs,end,len," character set %s",field_charset->csname); - res.length(oldlen+len); + res.append(" character set "); + res.append(field_charset->csname); } } @@ -287,7 +279,7 @@ uint Field::fill_cache_field(CACHE_FIELD *copy) bool Field::get_date(TIME *ltime,bool fuzzydate) { char buff[40]; - String tmp(buff,sizeof(buff),my_charset_latin1),tmp2,*res; + String tmp(buff,sizeof(buff),my_charset_bin),tmp2,*res; if (!(res=val_str(&tmp,&tmp2)) || str_to_TIME(res->ptr(),res->length(),ltime,fuzzydate) == TIMESTAMP_NONE) return 1; @@ -297,7 +289,7 @@ bool Field::get_date(TIME *ltime,bool fuzzydate) bool Field::get_time(TIME *ltime) { char buff[40]; - String tmp(buff,sizeof(buff),my_charset_latin1),tmp2,*res; + String tmp(buff,sizeof(buff),my_charset_bin),tmp2,*res; if (!(res=val_str(&tmp,&tmp2)) || str_to_time(res->ptr(),res->length(),ltime)) return 1; @@ -311,23 +303,23 @@ void Field::store_time(TIME *ltime,timestamp_type type) char buff[25]; switch (type) { case TIMESTAMP_NONE: - store("",0,my_charset_latin1); // Probably an error + store("",0,my_charset_bin); // Probably an error break; case TIMESTAMP_DATE: sprintf(buff,"%04d-%02d-%02d", ltime->year,ltime->month,ltime->day); - store(buff,10,my_charset_latin1); + store(buff,10,my_charset_bin); break; case TIMESTAMP_FULL: sprintf(buff,"%04d-%02d-%02d %02d:%02d:%02d", ltime->year,ltime->month,ltime->day, ltime->hour,ltime->minute,ltime->second); - store(buff,19,my_charset_latin1); + store(buff,19,my_charset_bin); break; case TIMESTAMP_TIME: { ulong length= my_sprintf(buff, (buff, "%02d:%02d:%02d", ltime->hour,ltime->minute,ltime->second)); - store(buff,(uint) length, my_charset_latin1); + store(buff,(uint) length, my_charset_bin); break; } } @@ -340,15 +332,12 @@ bool Field::optimize_range(uint idx) } /**************************************************************************** - Functions for the Field_null + Field_null, a field that always return NULL ****************************************************************************/ void Field_null::sql_type(String &res) const { - CHARSET_INFO *cs=res.charset(); - uint len; - len=cs->snprintf(cs,(char*)res.ptr(),res.alloced_length(),"null"); - res.length(len); + res.set_latin1("null", 4); } @@ -360,7 +349,7 @@ void Field_null::sql_type(String &res) const void Field_decimal::reset(void) { - Field_decimal::store("0",1,my_charset_latin1); + Field_decimal::store("0",1,my_charset_bin); } void Field_decimal::overflow(bool negative) @@ -404,11 +393,16 @@ void Field_decimal::overflow(bool negative) int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) { - String l1from; + char buff[80]; + String tmp(buff,sizeof(buff), my_charset_bin); - l1from.copy(from,len,cs,my_charset_latin1); - from=l1from.ptr(); - len=l1from.length(); + /* Convert character set if the old one is multi byte */ + if (cs->mbmaxlen > 1) + { + tmp.copy(from, len, cs, my_charset_bin); + from= tmp.ptr(); + len= tmp.length(); + } const char *end= from+len; /* The pointer where the field value starts (i.e., "where to write") */ @@ -461,7 +455,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) There are three steps in this function : - parse the input string - modify the position of digits around the decimal dot '.' - according to the exponent value (if specified) + according to the exponent value (if specified) - write the formatted number */ @@ -469,7 +463,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) tmp_dec++; /* skip pre-space */ - while (from != end && my_isspace(my_charset_latin1,*from)) + while (from != end && my_isspace(my_charset_bin,*from)) from++; if (from == end) { @@ -506,13 +500,13 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) for (; from!=end && *from == '0'; from++) ; // Read prezeros pre_zeros_end=int_digits_from=from; /* Read non zero digits at the left of '.'*/ - for (; from != end && my_isdigit(my_charset_latin1, *from) ; from++) ; + for (; from != end && my_isdigit(my_charset_bin, *from) ; from++) ; int_digits_end=from; if (from!=end && *from == '.') // Some '.' ? from++; frac_digits_from= from; /* Read digits at the right of '.' */ - for (;from!=end && my_isdigit(my_charset_latin1, *from); from++) ; + for (;from!=end && my_isdigit(my_charset_bin, *from); from++) ; frac_digits_end=from; // Some exponentiation symbol ? if (from != end && (*from == 'e' || *from == 'E')) @@ -528,7 +522,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) exponents will become small (e.g. 1e4294967296 will become 1e0, and the field will finally contain 1 instead of its max possible value). */ - for (;from!=end && my_isdigit(my_charset_latin1, *from); from++) + for (;from!=end && my_isdigit(my_charset_bin, *from); from++) { exponent=10*exponent+(*from-'0'); if (exponent>MAX_EXPONENT) @@ -546,7 +540,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) if (current_thd->count_cuted_fields) { // Skip end spaces - for (;from != end && my_isspace(my_charset_latin1, *from); from++) ; + for (;from != end && my_isspace(my_charset_bin, *from); from++) ; if (from != end) // If still something left, warn { current_thd->cuted_fields++; @@ -838,30 +832,29 @@ int Field_decimal::store(longlong nr) double Field_decimal::val_real(void) { - CHARSET_INFO *cs=charset(); - return my_strntod(cs,ptr,field_length,NULL); + return my_strntod(my_charset_bin, ptr, field_length, NULL); } longlong Field_decimal::val_int(void) { - CHARSET_INFO *cs=charset(); if (unsigned_flag) - return my_strntoull(cs,ptr,field_length,NULL,10); + return my_strntoull(my_charset_bin, ptr, field_length, NULL, 10); else - return my_strntoll(cs,ptr,field_length,NULL,10); + return my_strntoll( my_charset_bin, ptr, field_length, NULL, 10); } + String *Field_decimal::val_str(String *val_buffer __attribute__((unused)), String *val_ptr) { char *str; - CHARSET_INFO *cs=current_thd->variables.thd_charset; for (str=ptr ; *str == ' ' ; str++) ; uint tmp_length=(uint) (str-ptr); + val_ptr->set_charset(my_charset_bin); if (field_length < tmp_length) // Error in data val_ptr->length(0); else - val_ptr->copy((const char*) str,field_length-tmp_length,my_charset_latin1,cs); + val_ptr->set_latin1((const char*) str, field_length-tmp_length); return val_ptr; } @@ -878,9 +871,9 @@ int Field_decimal::cmp(const char *a_ptr,const char *b_ptr) for (end=a_ptr+field_length; a_ptr != end && (*a_ptr == *b_ptr || - ((my_isspace(my_charset_latin1,*a_ptr) || *a_ptr == '+' || + ((my_isspace(my_charset_bin,*a_ptr) || *a_ptr == '+' || *a_ptr == '0') && - (my_isspace(my_charset_latin1,*b_ptr) || *b_ptr == '+' || + (my_isspace(my_charset_bin,*b_ptr) || *b_ptr == '+' || *b_ptr == '0'))); a_ptr++,b_ptr++) { @@ -908,7 +901,7 @@ void Field_decimal::sort_string(char *to,uint length) char *str,*end; for (str=ptr,end=ptr+length; str != end && - ((my_isspace(my_charset_latin1,*str) || *str == '+' || + ((my_isspace(my_charset_bin,*str) || *str == '+' || *str == '0')) ; str++) *to++=' '; @@ -920,7 +913,7 @@ void Field_decimal::sort_string(char *to,uint length) *to++=1; // Smaller than any number str++; while (str != end) - if (my_isdigit(my_charset_latin1,*str)) + if (my_isdigit(my_charset_bin,*str)) *to++= (char) ('9' - *str++); else *to++= *str++; @@ -933,14 +926,12 @@ void Field_decimal::sql_type(String &res) const { CHARSET_INFO *cs=res.charset(); uint tmp=field_length; - uint len; if (!unsigned_flag) tmp--; if (dec) tmp--; - len=cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), - "decimal(%d,%d)",tmp,dec); - res.length(len); + res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), + "decimal(%d,%d)",tmp,dec)); add_zerofill_and_unsigned(res); } @@ -951,7 +942,8 @@ void Field_decimal::sql_type(String &res) const int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs) { - long tmp= my_strntol(cs,from,len,(char **)NULL,10); + char *end; + long tmp= my_strntol(cs, from, len, &end,10); int error= 0; if (unsigned_flag) @@ -968,7 +960,7 @@ int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs) current_thd->cuted_fields++; error= 1; } - else if (current_thd->count_cuted_fields && !test_if_int(from,len,cs)) + else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs)) { current_thd->cuted_fields++; error= 1; @@ -988,7 +980,7 @@ int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs) current_thd->cuted_fields++; error= 1; } - else if (current_thd->count_cuted_fields && !test_if_int(from,len,cs)) + else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs)) { current_thd->cuted_fields++; error= 1; @@ -1098,7 +1090,7 @@ longlong Field_tiny::val_int(void) String *Field_tiny::val_str(String *val_buffer, String *val_ptr __attribute__((unused))) { - CHARSET_INFO *cs=current_thd->variables.thd_charset; + CHARSET_INFO *cs= my_charset_bin; uint length; uint mlength=max(field_length+1,5*cs->mbmaxlen); val_buffer->alloc(mlength); @@ -1140,22 +1132,19 @@ void Field_tiny::sort_string(char *to,uint length __attribute__((unused))) void Field_tiny::sql_type(String &res) const { CHARSET_INFO *cs=res.charset(); - uint len=cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), - "tinyint(%d)",(int) field_length); - res.length(len); + res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), + "tinyint(%d)",(int) field_length)); add_zerofill_and_unsigned(res); } /**************************************************************************** -** short int + Field type short int (2 byte) ****************************************************************************/ - -// Note: Sometimes this should be fixed to check for garbage after number. - int Field_short::store(const char *from,uint len,CHARSET_INFO *cs) { - long tmp= my_strntol(cs,from,len,NULL,10); + char *end; + long tmp= my_strntol(cs, from, len, &end, 10); int error= 0; if (unsigned_flag) { @@ -1171,7 +1160,7 @@ int Field_short::store(const char *from,uint len,CHARSET_INFO *cs) current_thd->cuted_fields++; error= 1; } - else if (current_thd->count_cuted_fields && !test_if_int(from,len,cs)) + else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs)) { current_thd->cuted_fields++; error= 1; @@ -1191,7 +1180,7 @@ int Field_short::store(const char *from,uint len,CHARSET_INFO *cs) current_thd->cuted_fields++; error= 1; } - else if (current_thd->count_cuted_fields && !test_if_int(from,len,cs)) + else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs)) { current_thd->cuted_fields++; error= 1; @@ -1337,7 +1326,7 @@ longlong Field_short::val_int(void) String *Field_short::val_str(String *val_buffer, String *val_ptr __attribute__((unused))) { - CHARSET_INFO *cs=current_thd->variables.thd_charset; + CHARSET_INFO *cs= my_charset_bin; uint length; uint mlength=max(field_length+1,7*cs->mbmaxlen); val_buffer->alloc(mlength); @@ -1351,9 +1340,9 @@ String *Field_short::val_str(String *val_buffer, shortget(j,ptr); if (unsigned_flag) - length=(uint) cs->l10tostr(cs,to,mlength, 10, (long) (uint16) j); + length=(uint) cs->l10tostr(cs, to, mlength, 10, (long) (uint16) j); else - length=(uint) cs->l10tostr(cs,to,mlength,-10, (long) j); + length=(uint) cs->l10tostr(cs, to, mlength,-10, (long) j); val_buffer->length(length); if (zerofill) prepend_zeros(val_buffer); @@ -1414,22 +1403,20 @@ void Field_short::sort_string(char *to,uint length __attribute__((unused))) void Field_short::sql_type(String &res) const { CHARSET_INFO *cs=res.charset(); - uint len=cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), - "smallint(%d)",(int) field_length); - res.length(len); + res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), + "smallint(%d)",(int) field_length)); add_zerofill_and_unsigned(res); } /**************************************************************************** -** medium int + Field type medium int (3 byte) ****************************************************************************/ -// Note: Sometimes this should be fixed to check for garbage after number. - int Field_medium::store(const char *from,uint len,CHARSET_INFO *cs) { - long tmp= my_strntol(cs,from,len,NULL,10); + char *end; + long tmp= my_strntol(cs, from, len, &end, 10); int error= 0; if (unsigned_flag) @@ -1446,7 +1433,7 @@ int Field_medium::store(const char *from,uint len,CHARSET_INFO *cs) current_thd->cuted_fields++; error= 1; } - else if (current_thd->count_cuted_fields && !test_if_int(from,len,cs)) + else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs)) { current_thd->cuted_fields++; error= 1; @@ -1466,7 +1453,7 @@ int Field_medium::store(const char *from,uint len,CHARSET_INFO *cs) current_thd->cuted_fields++; error= 1; } - else if (current_thd->count_cuted_fields && !test_if_int(from,len,cs)) + else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs)) { current_thd->cuted_fields++; error= 1; @@ -1572,16 +1559,18 @@ double Field_medium::val_real(void) return (double) j; } + longlong Field_medium::val_int(void) { long j= unsigned_flag ? (long) uint3korr(ptr) : sint3korr(ptr); return (longlong) j; } + String *Field_medium::val_str(String *val_buffer, String *val_ptr __attribute__((unused))) { - CHARSET_INFO *cs=current_thd->variables.thd_charset; + CHARSET_INFO *cs= my_charset_bin; uint length; uint mlength=max(field_length+1,10*cs->mbmaxlen); val_buffer->alloc(mlength); @@ -1632,9 +1621,8 @@ void Field_medium::sort_string(char *to,uint length __attribute__((unused))) void Field_medium::sql_type(String &res) const { CHARSET_INFO *cs=res.charset(); - uint len=cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), - "mediumint(%d)",(int) field_length); - res.length(len); + res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), + "mediumint(%d)",(int) field_length)); add_zerofill_and_unsigned(res); } @@ -1643,26 +1631,23 @@ void Field_medium::sql_type(String &res) const ****************************************************************************/ -// Note: Sometimes this should be fixed to check for garbage after number. - int Field_long::store(const char *from,uint len,CHARSET_INFO *cs) { + long tmp; + int error= 0; char *end; + /* TODO: Make multi-byte-character safe */ while (len && my_isspace(cs,*from)) { len--; from++; } - long tmp; - String tmp_str(from, len, cs); - from= tmp_str.c_ptr(); // Add end null if needed - int error= 0; - errno=0; + my_errno=0; if (unsigned_flag) { if (!len || *from == '-') { tmp=0; // Set negative to 0 - errno=ERANGE; + my_errno=ERANGE; error= 1; } else @@ -1670,9 +1655,9 @@ int Field_long::store(const char *from,uint len,CHARSET_INFO *cs) } else tmp=my_strntol(cs,from,len,&end,10); - if (errno || + if (my_errno || (from+len != end && current_thd->count_cuted_fields && - !test_if_int(from,len,cs))) + !test_if_int(from,len,end,cs))) { current_thd->cuted_fields++; error= 1; @@ -1817,7 +1802,7 @@ longlong Field_long::val_int(void) String *Field_long::val_str(String *val_buffer, String *val_ptr __attribute__((unused))) { - CHARSET_INFO *cs=current_thd->variables.thd_charset; + CHARSET_INFO *cs= my_charset_bin; uint length; uint mlength=max(field_length+1,12*cs->mbmaxlen); val_buffer->alloc(mlength); @@ -1896,34 +1881,32 @@ void Field_long::sort_string(char *to,uint length __attribute__((unused))) void Field_long::sql_type(String &res) const { CHARSET_INFO *cs=res.charset(); - uint len=cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), - "int(%d)",(int) field_length); - res.length(len); + res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), + "int(%d)",(int) field_length)); add_zerofill_and_unsigned(res); } /**************************************************************************** -** longlong int + Field type longlong int (8 bytes) ****************************************************************************/ int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs) { + longlong tmp; + int error= 0; char *end; + /* TODO: Make multi byte safe */ while (len && my_isspace(cs,*from)) { // For easy error check len--; from++; } - longlong tmp; - String tmp_str(from, len, cs); - from= tmp_str.c_ptr(); // Add end null if needed - int error= 0; - errno=0; + my_errno=0; if (unsigned_flag) { if (!len || *from == '-') { tmp=0; // Set negative to 0 - errno=ERANGE; + my_errno= ERANGE; error= 1; } else @@ -1931,9 +1914,9 @@ int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs) } else tmp=my_strntoll(cs,from,len,&end,10); - if (errno || + if (my_errno || (from+len != end && current_thd->count_cuted_fields && - !test_if_int(from,len,cs))) + !test_if_int(from,len,end,cs))) current_thd->cuted_fields++; #ifdef WORDS_BIGENDIAN if (table->db_low_byte_first) @@ -2042,7 +2025,7 @@ longlong Field_longlong::val_int(void) String *Field_longlong::val_str(String *val_buffer, String *val_ptr __attribute__((unused))) { - CHARSET_INFO *cs=current_thd->variables.thd_charset; + CHARSET_INFO *cs= my_charset_bin; uint length; uint mlength=max(field_length+1,22*cs->mbmaxlen); val_buffer->alloc(mlength); @@ -2128,9 +2111,8 @@ void Field_longlong::sort_string(char *to,uint length __attribute__((unused))) void Field_longlong::sql_type(String &res) const { CHARSET_INFO *cs=res.charset(); - uint len=cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), - "bigint(%d)",(int) field_length); - res.length(len); + res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), + "bigint(%d)",(int) field_length)); add_zerofill_and_unsigned(res); } @@ -2140,8 +2122,8 @@ void Field_longlong::sql_type(String &res) const int Field_float::store(const char *from,uint len,CHARSET_INFO *cs) { - errno=0; - Field_float::store(my_strntod(cs,from,len,(char**)NULL)); + errno=0; // my_strntod() changes errno + Field_float::store(my_strntod(cs,(char*) from,len,(char**)NULL)); if (errno || current_thd->count_cuted_fields && !test_if_real(from,len,cs)) { current_thd->cuted_fields++; @@ -2394,18 +2376,16 @@ bool Field_float::send_binary(Protocol *protocol) void Field_float::sql_type(String &res) const { - CHARSET_INFO *cs=res.charset(); - uint len; if (dec == NOT_FIXED_DEC) { - len=cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(),"float"); + res.set_latin1("float", 5); } else { - len=cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), - "float(%d,%d)",(int) field_length,dec); + CHARSET_INFO *cs= res.charset(); + res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), + "float(%d,%d)",(int) field_length,dec)); } - res.length(len); add_zerofill_and_unsigned(res); } @@ -2415,9 +2395,9 @@ void Field_float::sql_type(String &res) const int Field_double::store(const char *from,uint len,CHARSET_INFO *cs) { - errno=0; + errno=0; // my_strntod() changes errno int error= 0; - double j= my_strntod(cs,from,len,(char**)0); + double j= my_strntod(cs,(char*) from,len,(char**)0); if (errno || current_thd->count_cuted_fields && !test_if_real(from,len,cs)) { current_thd->cuted_fields++; @@ -2655,17 +2635,15 @@ void Field_double::sort_string(char *to,uint length __attribute__((unused))) void Field_double::sql_type(String &res) const { CHARSET_INFO *cs=res.charset(); - uint len; if (dec == NOT_FIXED_DEC) { - len=cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(),"double"); + res.set_latin1("double",6); } else { - len=cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), - "double(%d,%d)",(int) field_length,dec); + res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), + "double(%d,%d)",(int) field_length,dec)); } - res.length(len); add_zerofill_and_unsigned(res); } @@ -2722,9 +2700,9 @@ int Field_timestamp::store(double nr) /* -** Convert a datetime of formats YYMMDD, YYYYMMDD or YYMMDDHHMSS to -** YYYYMMDDHHMMSS. The high date '99991231235959' is checked before this -** function. + Convert a datetime of formats YYMMDD, YYYYMMDD or YYMMDDHHMSS to + YYYYMMDDHHMMSS. The high date '99991231235959' is checked before this + function. */ static longlong fix_datetime(longlong nr) @@ -2854,9 +2832,10 @@ String *Field_timestamp::val_str(String *val_buffer, if (temp == 0L) { /* Zero time is "000000" */ - strmov(to, "0000-00-00 00:00:00"); - return val_buffer; + val_ptr->set("0000-00-00 00:00:00", 19, my_charset_bin); + return val_ptr; } + val_buffer->set_charset(my_charset_bin); // Safety time_arg=(time_t) temp; localtime_r(&time_arg,&tm_tmp); l_time=&tm_tmp; @@ -2995,9 +2974,7 @@ void Field_timestamp::sort_string(char *to,uint length __attribute__((unused))) void Field_timestamp::sql_type(String &res) const { - CHARSET_INFO *cs=res.charset(); - uint len=cs->snprintf(cs,(char*)res.ptr(),res.alloced_length(),"timestamp"); - res.length(len); + res.set_latin1("timestamp", 9); } @@ -3125,6 +3102,12 @@ longlong Field_time::val_int(void) return (longlong) sint3korr(ptr); } + +/* + This function is multi-byte safe as the result string is always of type + my_charset_bin +*/ + String *Field_time::val_str(String *val_buffer, String *val_ptr __attribute__((unused))) { @@ -3189,9 +3172,7 @@ void Field_time::sort_string(char *to,uint length __attribute__((unused))) void Field_time::sql_type(String &res) const { - CHARSET_INFO *cs=res.charset(); - uint len=cs->snprintf(cs,(char*)res.ptr(),res.alloced_length(),"time"); - res.length(len); + res.set_latin1("time", 4); } /**************************************************************************** @@ -3202,7 +3183,8 @@ void Field_time::sql_type(String &res) const int Field_year::store(const char *from, uint len,CHARSET_INFO *cs) { - long nr= my_strntol(cs,from,len,NULL,10); + char *end; + long nr= my_strntol(cs, from, len, &end, 10); if (nr < 0 || nr >= 100 && nr <= 1900 || nr > 2155) { @@ -3210,7 +3192,7 @@ int Field_year::store(const char *from, uint len,CHARSET_INFO *cs) current_thd->cuted_fields++; return 1; } - else if (current_thd->count_cuted_fields && !test_if_int(from,len,cs)) + else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs)) current_thd->cuted_fields++; if (nr != 0 || len != 4) { @@ -3287,9 +3269,8 @@ String *Field_year::val_str(String *val_buffer, void Field_year::sql_type(String &res) const { CHARSET_INFO *cs=res.charset(); - ulong len=cs->snprintf(cs,(char*)res.ptr(),res.alloced_length(), - "year(%d)",(int) field_length); - res.length(len); + res.length(cs->snprintf(cs,(char*)res.ptr(),res.alloced_length(), + "year(%d)",(int) field_length)); } @@ -3375,6 +3356,7 @@ int Field_date::store(longlong nr) return error; } + bool Field_date::send_binary(Protocol *protocol) { longlong tmp= Field_date::val_int(); @@ -3469,9 +3451,7 @@ void Field_date::sort_string(char *to,uint length __attribute__((unused))) void Field_date::sql_type(String &res) const { - CHARSET_INFO *cs=res.charset(); - uint len=cs->snprintf(cs,(char*)res.ptr(),res.alloced_length(),"date"); - res.length(len); + res.set_latin1("date", 4); } /**************************************************************************** @@ -3639,9 +3619,7 @@ void Field_newdate::sort_string(char *to,uint length __attribute__((unused))) void Field_newdate::sql_type(String &res) const { - CHARSET_INFO *cs=res.charset(); - uint len=cs->snprintf(cs,(char*)res.ptr(),res.alloced_length(),"date"); - res.length(len); + res.set_latin1("date", 4); } @@ -3872,9 +3850,7 @@ void Field_datetime::sort_string(char *to,uint length __attribute__((unused))) void Field_datetime::sql_type(String &res) const { - CHARSET_INFO *cs=res.charset(); - uint len=cs->snprintf(cs,(char*)res.ptr(),res.alloced_length(),"datetime"); - res.length(len); + res.set_latin1("datetime", 8); } /**************************************************************************** @@ -3929,7 +3905,7 @@ int Field_string::store(double nr) int width=min(field_length,DBL_DIG+5); sprintf(buff,"%-*.*g",width,max(width-5,0),nr); end=strcend(buff,' '); - return Field_string::store(buff,(uint) (end - buff), my_charset_latin1); + return Field_string::store(buff,(uint) (end - buff), my_charset_bin); } @@ -4118,7 +4094,7 @@ int Field_varstring::store(double nr) int width=min(field_length,DBL_DIG+5); sprintf(buff,"%-*.*g",width,max(width-5,0),nr); end=strcend(buff,' '); - return Field_varstring::store(buff,(uint) (end - buff), my_charset_latin1); + return Field_varstring::store(buff,(uint) (end - buff), my_charset_bin); } @@ -4464,22 +4440,23 @@ int Field_blob::store(const char *from,uint len,CHARSET_INFO *cs) int Field_blob::store(double nr) { - value.set(nr,2,current_thd->variables.thd_charset); - return Field_blob::store(value.ptr(),(uint) value.length(), value.charset()); + CHARSET_INFO *cs=charset(); + value.set(nr, 2, cs); + return Field_blob::store(value.ptr(),(uint) value.length(), cs); } int Field_blob::store(longlong nr) { - value.set(nr,current_thd->variables.thd_charset); - return Field_blob::store(value.ptr(), (uint) value.length(), value.charset()); + CHARSET_INFO *cs=charset(); + value.set(nr, cs); + return Field_blob::store(value.ptr(), (uint) value.length(), cs); } double Field_blob::val_real(void) { char *blob; - memcpy_fixed(&blob,ptr+packlength,sizeof(char*)); if (!blob) return 0.0; @@ -4496,8 +4473,7 @@ longlong Field_blob::val_int(void) if (!blob) return 0; uint32 length=get_length(ptr); - CHARSET_INFO *cs=charset(); - return my_strntoll(cs,blob,length,NULL,10); + return my_strntoll(charset(),blob,length,NULL,10); } @@ -4507,9 +4483,9 @@ String *Field_blob::val_str(String *val_buffer __attribute__((unused)), char *blob; memcpy_fixed(&blob,ptr+packlength,sizeof(char*)); if (!blob) - val_ptr->set("",0,field_charset); // A bit safer than ->length(0) + val_ptr->set("",0,charset()); // A bit safer than ->length(0) else - val_ptr->set((const char*) blob,get_length(ptr),field_charset); + val_ptr->set((const char*) blob,get_length(ptr),charset()); return val_ptr; } @@ -4567,7 +4543,8 @@ int Field_blob::cmp_binary(const char *a_ptr, const char *b_ptr, /* The following is used only when comparing a key */ -void Field_blob::get_key_image(char *buff,uint length, CHARSET_INFO *cs,imagetype type) +void Field_blob::get_key_image(char *buff,uint length, + CHARSET_INFO *cs,imagetype type) { length-= HA_KEY_BLOB_LENGTH; uint32 blob_length= get_length(ptr); @@ -4695,22 +4672,26 @@ void Field_blob::sort_string(char *to,uint length) void Field_blob::sql_type(String &res) const { - CHARSET_INFO *cs=res.charset(); const char *str; - uint len; + uint length; switch (packlength) { - default: str="tiny"; break; - case 2: str=""; break; - case 3: str="medium"; break; - case 4: str="long"; break; + default: str="tiny"; length=4; break; + case 2: str=""; length=0; break; + case 3: str="medium"; length= 6; break; + case 4: str="long"; length=4; break; + } + res.set_latin1(str,length); + if (binary()) + res.append("blob"); + else + { + res.append("text"); + if (field_charset != table->table_charset) + { + res.append(" character set "); + res.append(field_charset->csname); + } } - - len=cs->snprintf(cs,(char*)res.ptr(),res.alloced_length(),"%s%s%s%s", - str, - binary() ? "blob" : "text", - binary() ? "" : " character set ", - binary() ? "" : field_charset->name); - res.length(len); } @@ -5452,8 +5433,7 @@ create_field::create_field(Field *old_field,Field *orig_field) orig_field) { char buff[MAX_FIELD_WIDTH],*pos; - CHARSET_INFO *field_charset= charset; - String tmp(buff,sizeof(buff),field_charset); + String tmp(buff,sizeof(buff), charset); /* Get the value from record[2] (the default value row) */ my_ptrdiff_t diff= (my_ptrdiff_t) (orig_field->table->rec_buff_length*2); @@ -5465,7 +5445,7 @@ create_field::create_field(Field *old_field,Field *orig_field) { pos= (char*) sql_memdup(tmp.ptr(),tmp.length()+1); pos[tmp.length()]=0; - def=new Item_string(pos,tmp.length(),field_charset); + def=new Item_string(pos,tmp.length(), charset); } } } diff --git a/sql/field.h b/sql/field.h index 67bae7302f9..06a9b534b16 100644 --- a/sql/field.h +++ b/sql/field.h @@ -133,7 +133,9 @@ public: tmp->unireg_check=Field::NONE; tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG | ZEROFILL_FLAG | BINARY_FLAG | ENUM_FLAG | SET_FLAG); +#ifdef PROBABLY_WRONG tmp->table_name= new_table->table_name; +#endif tmp->reset_fields(); } return tmp; @@ -1094,7 +1096,8 @@ bool set_field_to_null(Field *field); bool set_field_to_null_with_conversions(Field *field, bool no_conversions); uint find_enum(TYPELIB *typelib,const char *x, uint length); ulonglong find_set(TYPELIB *typelib,const char *x, uint length); -bool test_if_int(const char *str,int length,CHARSET_INFO *cs); +bool test_if_int(const char *str, int length, const char *int_end, + CHARSET_INFO *cs); /* The following are for the interface with the .frm file diff --git a/sql/item.cc b/sql/item.cc index b0b56bf9101..925ee9ac0f4 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -116,7 +116,7 @@ bool Item_string::eq(const Item *item, bool binary_cmp) const bool Item::get_date(TIME *ltime,bool fuzzydate) { char buff[40]; - String tmp(buff,sizeof(buff),NULL),*res; + String tmp(buff,sizeof(buff), my_charset_bin),*res; if (!(res=val_str(&tmp)) || str_to_TIME(res->ptr(),res->length(),ltime,fuzzydate) == TIMESTAMP_NONE) { @@ -134,7 +134,7 @@ bool Item::get_date(TIME *ltime,bool fuzzydate) bool Item::get_time(TIME *ltime) { char buff[40]; - String tmp(buff,sizeof(buff),NULL),*res; + String tmp(buff,sizeof(buff),my_charset_bin),*res; if (!(res=val_str(&tmp)) || str_to_time(res->ptr(),res->length(),ltime)) { @@ -380,7 +380,8 @@ double Item_param::val() { switch (item_result_type) { case STRING_RESULT: - return (double)my_strntod(str_value.charset(),str_value.ptr(),str_value.length(),(char**)0); + return (double) my_strntod(str_value.charset(), (char*) str_value.ptr(), + str_value.length(), (char**) 0); case INT_RESULT: return (double)int_value; default: @@ -1149,7 +1150,7 @@ Item *resolve_const_item(Item *item,Item *comp_item) if (res_type == STRING_RESULT) { char buff[MAX_FIELD_WIDTH]; - String tmp(buff,sizeof(buff),NULL),*result; + String tmp(buff,sizeof(buff),my_charset_bin),*result; result=item->val_str(&tmp); if (item->null_value) { @@ -1204,8 +1205,8 @@ bool field_is_equal_to_item(Field *field,Item *item) { char item_buff[MAX_FIELD_WIDTH]; char field_buff[MAX_FIELD_WIDTH]; - String item_tmp(item_buff,sizeof(item_buff),NULL),*item_result; - String field_tmp(field_buff,sizeof(field_buff),NULL); + String item_tmp(item_buff,sizeof(item_buff),my_charset_bin),*item_result; + String field_tmp(field_buff,sizeof(field_buff),my_charset_bin); item_result=item->val_str(&item_tmp); if (item->null_value) return 1; // This must be true @@ -1263,8 +1264,8 @@ void Item_cache_str::store(Item *item) double Item_cache_str::val() { if (value) - return my_strntod(value->charset(), value->ptr(), - value->length(), (char**)0); + return my_strntod(value->charset(), (char*) value->ptr(), + value->length(), (char**) 0); else return (double)0; } diff --git a/sql/item.h b/sql/item.h index 3decdc388eb..907c293d454 100644 --- a/sql/item.h +++ b/sql/item.h @@ -344,7 +344,7 @@ public: enum Type type() const { return STRING_ITEM; } double val() { - return my_strntod(str_value.charset(), str_value.ptr(), + return my_strntod(str_value.charset(), (char*) str_value.ptr(), str_value.length(), (char**) 0); } longlong val_int() @@ -598,7 +598,11 @@ public: enum Item_result result_type () const { return STRING_RESULT; } enum_field_types field_type() const { return cached_field_type; } double val() - { return null_value ? 0.0 : my_strntod(str_value.charset(),str_value.ptr(),str_value.length(),NULL); } + { + return (null_value ? 0.0 : + my_strntod(str_value.charset(), (char*) str_value.ptr(), + str_value.length(),NULL)); + } longlong val_int() { return null_value ? LL(0) : my_strntoll(str_value.charset(),str_value.ptr(),str_value.length(),(char**) 0,10); } String *val_str(String*); diff --git a/sql/item_func.cc b/sql/item_func.cc index dcf4638c48a..62cf4c0d291 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1893,7 +1893,7 @@ longlong Item_func_set_last_insert_id::val_int() longlong Item_func_benchmark::val_int() { char buff[MAX_FIELD_WIDTH]; - String tmp(buff,sizeof(buff), NULL); + String tmp(buff,sizeof(buff), my_charset_bin); THD *thd=current_thd; for (ulong loop=0 ; loop < loop_count && !thd->killed; loop++) @@ -2039,7 +2039,7 @@ Item_func_set_user_var::update() case STRING_RESULT: { char buffer[MAX_FIELD_WIDTH]; - String tmp(buffer,sizeof(buffer),NULL); + String tmp(buffer,sizeof(buffer),my_charset_bin); (void) val_str(&tmp); break; } @@ -2234,7 +2234,7 @@ longlong Item_func_inet_aton::val_int() char c = '.'; // we mark c to indicate invalid IP in case length is 0 char buff[36]; - String *s,tmp(buff,sizeof(buff),NULL); + String *s,tmp(buff,sizeof(buff),my_charset_bin); if (!(s = args[0]->val_str(&tmp))) // If null value goto err; null_value=0; @@ -2288,7 +2288,7 @@ void Item_func_match::init_search(bool no_order) String *ft_tmp= 0; char tmp1[FT_QUERY_MAXLEN]; - String tmp2(tmp1,sizeof(tmp1),NULL); + String tmp2(tmp1,sizeof(tmp1),default_charset_info); // MATCH ... AGAINST (NULL) is meaningless, but possible if (!(ft_tmp=key_item()->val_str(&tmp2))) diff --git a/sql/item_func.h b/sql/item_func.h index bf64412cab3..11793b11bdb 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -813,7 +813,7 @@ public: double val() { String *res; res=val_str(&str_value); - return res ? my_strntod(res->charset(),res->ptr(),res->length(),0) : 0.0; + return res ? my_strntod(res->charset(),(char*) res->ptr(),res->length(),0) : 0.0; } longlong val_int() { diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 7818a23fcd8..2292c6115a0 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -54,7 +54,8 @@ double Item_str_func::val() { String *res; res=val_str(&str_value); - return res ? my_strntod(res->charset(),res->ptr(),res->length(),NULL) : 0.0; + return res ? my_strntod(res->charset(), (char*) res->ptr(),res->length(), + NULL) : 0.0; } longlong Item_str_func::val_int() diff --git a/sql/item_sum.cc b/sql/item_sum.cc index d78e535010f..b15fceda686 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -341,7 +341,8 @@ double Item_sum_hybrid::val() switch (hybrid_type) { case STRING_RESULT: String *res; res=val_str(&str_value); - return res ? my_strntod(res->charset(),res->ptr(),res->length(),(char**)0) : 0.0; + return (res ? my_strntod(res->charset(), (char*) res->ptr(),res->length(), + (char**) 0) : 0.0); case INT_RESULT: if (unsigned_flag) return ulonglong2double(sum_int); diff --git a/sql/item_sum.h b/sql/item_sum.h index d16a1f2224e..ffc9558822d 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -484,7 +484,8 @@ public: double val() { String *res; res=val_str(&str_value); - return res ? my_strntod(res->charset(),res->ptr(),res->length(),(char**) 0) : 0.0; + return res ? my_strntod(res->charset(),(char*) res->ptr(),res->length(), + (char**) 0) : 0.0; } longlong val_int() { diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 796070acb8a..744c0c1fa49 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -529,7 +529,7 @@ void Item_func_now::fix_length_and_dec() { struct tm tm_tmp,*start; time_t query_start=current_thd->query_start(); - CHARSET_INFO *cs=thd_charset(); + CHARSET_INFO *cs=my_charset_bin; decimals=0; max_length=19*cs->mbmaxlen; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index f66122e72a6..27c7fb369a1 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4665,8 +4665,11 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), berkeley_lock_type=berkeley_lock_types[type-1]; else { - if (test_if_int(argument,(uint) strlen(argument), my_charset_latin1)) - berkeley_lock_scan_time=atoi(argument); + char *end; + uint length= strlen(argument); + long value= my_strntol(my_charset_latin1, argument, length, &end, 10); + if (test_if_int(argument,(uint) length, end, my_charset_latin1)) + berkeley_lock_scan_time= value; else { fprintf(stderr,"Unknown lock type: %s\n",argument); diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 0adde4d39e0..43066a29624 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -2796,7 +2796,7 @@ static void print_key(KEY_PART *key_part,const char *key,uint used_length) { char buff[1024]; - String tmp(buff,sizeof(buff),NULL); + String tmp(buff,sizeof(buff),my_charset_bin); for (uint length=0; length < used_length ; diff --git a/sql/procedure.h b/sql/procedure.h index bc1b6062e1d..bc77803230f 100644 --- a/sql/procedure.h +++ b/sql/procedure.h @@ -59,7 +59,7 @@ public: void set(double nr) { value=nr; } void set(longlong nr) { value=(double) nr; } void set(const char *str,uint length,CHARSET_INFO *cs) - { value=my_strntod(cs,str,length,(char**)0); } + { value=my_strntod(cs,(char*) str,length,(char**)0); } double val() { return value; } longlong val_int() { return (longlong) value; } String *val_str(String *s) { s->set(value,decimals,thd_charset()); return s; } @@ -99,7 +99,8 @@ public: double val() { CHARSET_INFO *cs=str_value.charset(); - return my_strntod(cs, str_value.ptr(), str_value.length(),(char**)0); + return my_strntod(cs, (char*) str_value.ptr(), str_value.length(), + (char**) 0); } longlong val_int() { diff --git a/sql/sql_class.cc b/sql/sql_class.cc index ab789370660..4416f5259bd 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -526,7 +526,7 @@ bool select_send::send_data(List<Item> &items) List_iterator_fast<Item> li(items); Protocol *protocol= thd->protocol; char buff[MAX_FIELD_WIDTH]; - String buffer(buff, sizeof(buff), NULL); + String buffer(buff, sizeof(buff), my_charset_bin); DBUG_ENTER("send_data"); protocol->prepare_for_resend(); @@ -649,7 +649,7 @@ bool select_export::send_data(List<Item> &items) DBUG_ENTER("send_data"); char buff[MAX_FIELD_WIDTH],null_buff[2],space[MAX_FIELD_WIDTH]; bool space_inited=0; - String tmp(buff,sizeof(buff),NULL),*res; + String tmp(buff,sizeof(buff),my_charset_bin),*res; tmp.length(0); if (unit->offset_limit_cnt) @@ -857,7 +857,7 @@ bool select_dump::send_data(List<Item> &items) { List_iterator_fast<Item> li(items); char buff[MAX_FIELD_WIDTH]; - String tmp(buff,sizeof(buff),NULL),*res; + String tmp(buff,sizeof(buff),my_charset_bin),*res; tmp.length(0); Item *item; DBUG_ENTER("send_data"); diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 5b84b86c277..4c499af8f9e 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -30,6 +30,9 @@ extern gptr sql_alloc(unsigned size); extern void sql_element_free(void *ptr); +static uint32 +copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs, + const char *from, uint32 from_length, CHARSET_INFO *from_cs); #include "sql_string.h" @@ -223,55 +226,51 @@ bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *cs) return FALSE; } -/* Copy with charset convertion */ -bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *from, CHARSET_INFO *to) -{ - uint32 new_length=to->mbmaxlen*arg_length; - int cnvres; - my_wc_t wc; - const uchar *s=(const uchar *)str; - const uchar *se=s+arg_length; - uchar *d, *de; + /* Copy with charset convertion */ +bool String::copy(const char *str, uint32 arg_length, + CHARSET_INFO *from_cs, CHARSET_INFO *to_cs) +{ + uint32 new_length= to_cs->mbmaxlen*arg_length; if (alloc(new_length)) return TRUE; + str_length=copy_and_convert((char*) Ptr, new_length, to_cs, + str, arg_length, from_cs); + str_charset=to_cs; + return FALSE; +} - d=(uchar *)Ptr; - de=d+new_length; + +/* + Set a string to the value of a latin1-string, keeping the original charset - for (str_length=new_length ; s < se && d < de ; ) - { - if ((cnvres=from->mb_wc(from,&wc,s,se)) > 0 ) - { - s+=cnvres; - } - else if (cnvres==MY_CS_ILSEQ) - { - s++; - wc='?'; - } - else - break; + SYNOPSIS + copy_or_set() + str String of a simple charset (latin1) + arg_length Length of string -outp: - if ((cnvres=to->wc_mb(to,wc,d,de)) >0 ) - { - d+=cnvres; - } - else if (cnvres==MY_CS_ILUNI && wc!='?') - { - wc='?'; - goto outp; - } - else - break; + IMPLEMENTATION + If string object is of a simple character set, set it to point to the + given string. + If not, make a copy and convert it to the new character set. + + RETURN + 0 ok + 1 Could not allocate result buffer + +*/ + +bool String::set_latin1(const char *str, uint32 arg_length) +{ + if (str_charset->mbmaxlen == 1) + { + set(str, arg_length, str_charset); + return 0; } - Ptr[new_length]=0; - length((uint32) (d-(uchar *)Ptr)); - str_charset=to; - return FALSE; + return copy(str, arg_length, my_charset_latin1, str_charset); } + /* This is used by mysql.cc */ bool String::fill(uint32 max_length,char fill_char) @@ -306,11 +305,26 @@ bool String::append(const String &s) return FALSE; } + +/* + Append a latin1 string to the a string of the current character set +*/ + + bool String::append(const char *s,uint32 arg_length) { if (!arg_length) // Default argument if (!(arg_length= (uint32) strlen(s))) return FALSE; + if (str_charset->mbmaxlen > 1) + { + uint32 add_length=arg_length * str_charset->mbmaxlen; + if (realloc(str_length+ add_length)) + return TRUE; + str_length+= copy_and_convert(Ptr+str_length, add_length, str_charset, + s, arg_length, my_charset_latin1); + return FALSE; + } if (realloc(str_length+arg_length)) return TRUE; memcpy(Ptr+str_length,s,arg_length); @@ -318,6 +332,7 @@ bool String::append(const char *s,uint32 arg_length) return FALSE; } + #ifdef TO_BE_REMOVED bool String::append(FILE* file, uint32 arg_length, myf my_flags) { @@ -658,4 +673,61 @@ String *copy_if_not_alloced(String *to,String *from,uint32 from_length) } +/**************************************************************************** + Help functions +****************************************************************************/ + +/* + copy a string from one character set to another + + SYNOPSIS + copy_and_convert() + to Store result here + to_cs Character set of result string + from Copy from here + from_length Length of from string + from_cs From character set + + NOTES + 'to' must be big enough as form_length * to_cs->mbmaxlen + + RETURN + length of bytes copied to 'to' +*/ + +static uint32 +copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs, + const char *from, uint32 from_length, CHARSET_INFO *from_cs) +{ + int cnvres; + my_wc_t wc; + const uchar *from_end= (const uchar*) from+from_length; + char *to_start= to; + uchar *to_end= (uchar*) to+to_length; + + while ((uchar*) from < from_end) + { + if ((cnvres=from_cs->mb_wc(from_cs, &wc, (uchar*) from, from_end)) > 0) + from+= cnvres; + else if (cnvres == MY_CS_ILSEQ) + { + from++; + wc= '?'; + } + else + break; // Impossible char. + +outp: + if ((cnvres= to_cs->wc_mb(to_cs, wc, (uchar*) to, to_end)) > 0) + to+= cnvres; + else if (cnvres == MY_CS_ILUNI && wc != '?') + { + wc= '?'; + goto outp; + } + else + break; + } + return (uint32) (to - to_start); +} diff --git a/sql/sql_string.h b/sql/sql_string.h index afcc3d74530..ad91b20f18c 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -115,6 +115,7 @@ public: Ptr=(char*) str; str_length=arg_length; Alloced_length=0 ; alloced=0; str_charset=cs; } + bool String::set_latin1(const char *str, uint32 arg_length); inline void set_quick(char *str,uint32 arg_length, CHARSET_INFO *cs) { if (!alloced) diff --git a/sql/sql_update.cc b/sql/sql_update.cc index bf98ab7f7cb..3aae6f6f411 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -233,6 +233,7 @@ int mysql_update(THD *thd, } } end_read_record(&info); + if (table->key_read) { table->key_read=0; diff --git a/strings/Makefile.am b/strings/Makefile.am index ac0b6d7f1e0..ac4a994872d 100644 --- a/strings/Makefile.am +++ b/strings/Makefile.am @@ -22,19 +22,19 @@ pkglib_LIBRARIES = libmystrings.a # Exact one of ASSEMBLER_X if ASSEMBLER_x86 ASRCS = strings-x86.s longlong2str-x86.s -CSRCS = bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-latin1_de.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-win1250ch.c ctype-bin.c +CSRCS = bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-latin1_de.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-win1250ch.c ctype-bin.c my_vsnprintf.c else if ASSEMBLER_sparc32 # These file MUST all be on the same line!! Otherwise automake # generats a very broken makefile ASRCS = bmove_upp-sparc.s strappend-sparc.s strend-sparc.s strinstr-sparc.s strmake-sparc.s strmov-sparc.s strnmov-sparc.s strstr-sparc.s -CSRCS = strcont.c strfill.c strcend.c is_prefix.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c strxmov.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-latin1_de.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-win1250ch.c ctype-bin.c +CSRCS = strcont.c strfill.c strcend.c is_prefix.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c strxmov.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-latin1_de.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-win1250ch.c ctype-bin.c my_vsnprintf.c else #no assembler ASRCS = # These file MUST all be on the same line!! Otherwise automake # generats a very broken makefile -CSRCS = strxmov.c bmove_upp.c strappend.c strcont.c strend.c strfill.c strcend.c is_prefix.c strstr.c strinstr.c strmake.c strnmov.c strmov.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-latin1_de.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-win1250ch.c ctype-bin.c +CSRCS = strxmov.c bmove_upp.c strappend.c strcont.c strend.c strfill.c strcend.c is_prefix.c strstr.c strinstr.c strmake.c strnmov.c strmov.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-latin1_de.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-win1250ch.c ctype-bin.c my_vsnprintf.c endif endif diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index 49801478504..9bcafa9f164 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -110,88 +110,40 @@ int my_mb_wc_8bit(CHARSET_INFO *cs,my_wc_t *wc, } int my_wc_mb_8bit(CHARSET_INFO *cs,my_wc_t wc, - unsigned char *s, - unsigned char *e __attribute__((unused))) + unsigned char *str, + unsigned char *end __attribute__((unused))) { MY_UNI_IDX *idx; - for(idx=cs->tab_from_uni; idx->tab ; idx++){ - if(idx->from<=wc && idx->to>=wc){ - s[0]=idx->tab[wc-idx->from]; - return (!s[0] && wc) ? MY_CS_ILUNI : 1; + for (idx=cs->tab_from_uni; idx->tab ; idx++) + { + if (idx->from <= wc && idx->to >= wc) + { + str[0]= idx->tab[wc - idx->from]; + return (!str[0] && wc) ? MY_CS_ILUNI : 1; } } return MY_CS_ILUNI; } -#ifdef NOT_USED -static int my_vsnprintf_8bit(char *to, size_t n, const char* fmt, va_list ap) -{ - char *start=to, *end=to+n-1; - for (; *fmt ; fmt++) - { - if (fmt[0] != '%') - { - if (to == end) /* End of buffer */ - break; - *to++= *fmt; /* Copy ordinary char */ - continue; - } - /* Skip if max size is used (to be compatible with printf) */ - fmt++; - while (my_isdigit(system_charset_info,*fmt) || *fmt == '.' || *fmt == '-') - fmt++; - if (*fmt == 'l') - fmt++; - if (*fmt == 's') /* String parameter */ - { - reg2 char *par = va_arg(ap, char *); - uint plen,left_len = (uint)(end-to); - if (!par) par = (char*)"(null)"; - plen = (uint) strlen(par); - if (left_len <= plen) - plen = left_len - 1; - to=strnmov(to,par,plen); - continue; - } - else if (*fmt == 'd' || *fmt == 'u') /* Integer parameter */ - { - register int iarg; - if ((uint) (end-to) < 16) - break; - iarg = va_arg(ap, int); - if (*fmt == 'd') - to=int10_to_str((long) iarg,to, -10); - else - to=int10_to_str((long) (uint) iarg,to,10); - continue; - } - /* We come here on '%%', unknown code or too long parameter */ - if (to == end) - break; - *to++='%'; /* % used as % or unknown code */ - } - DBUG_ASSERT(to <= end); - *to='\0'; /* End of errmessage */ - return (uint) (to - start); -} -#endif +/* + We can't use vsprintf here as it's not guaranteed to return + the length on all operating systems. + This function is also not called in a safe environment, so the + end buffer must be checked. +*/ int my_snprintf_8bit(CHARSET_INFO *cs __attribute__((unused)), char* to, uint n __attribute__((unused)), const char* fmt, ...) { va_list args; + int result; va_start(args,fmt); -#ifdef NOT_USED - return my_vsnprintf_8bit(to, n, fmt, args); -#endif - /* - FIXME: generally not safe, but it is OK for now - FIXME: as far as it's not called unsafely in the current code - */ - return vsprintf(to,fmt,args); /* FIXME */ + result= my_vsnprintf(to, n, fmt, args); + va_end(args); + return result; } @@ -690,28 +642,48 @@ noconv: return 0L; } -double my_strntod_8bit(CHARSET_INFO *cs __attribute__((unused)), - const char *s, uint l, char **e) +/* + Read double from string + + SYNOPSIS: + my_strntod_8bit() + cs Character set information + str String to convert to double + length Optional length for string. + end pointer to end of converted string + + NOTES: + If length is not INT_MAX32 or str[length] != 0 then the given str must + be writeable + If length == INT_MAX32 the str must be \0 terminated. + + It's implemented this way to save a buffer allocation and a memory copy. + + RETURN + value of number in string +*/ + + +double my_strntod_8bit(CHARSET_INFO *cs __attribute__((unused)), + char *str, uint length, char **end) { - char buf[256]; - double res; - if((l+1)>sizeof(buf)) - { - if (e) - memcpy(*e,s,sizeof(s)); - return 0; - } - strncpy(buf,s,l); - buf[l]='\0'; - res=strtod(buf,e); - if (e) - memcpy(*e,*e-buf+s,sizeof(s)); - return res; + char end_char; + double result; + + if (length == INT_MAX32 || str[length] == 0) + return strtod(str, end); + end_char= str[length]; + str[length]= 0; + result= strtod(str, end); + str[length]= end_char; /* Restore end char */ + return result; } /* This is a fast version optimized for the case of radix 10 / -10 + + Assume len >= 1 */ int my_l10tostr_8bit(CHARSET_INFO *cs __attribute__((unused)), @@ -720,18 +692,19 @@ int my_l10tostr_8bit(CHARSET_INFO *cs __attribute__((unused)), char buffer[66]; register char *p, *e; long int new_val; - int sl=0; - uint l; - + uint sign=0; + e = p = &buffer[sizeof(buffer)-1]; - *e='\0'; + *p= 0; if (radix < 0) { if (val < 0) { - sl = 1; - val = -val; + val= -val; + *dst++= '-'; + len--; + sign= 1; } } @@ -746,41 +719,38 @@ int my_l10tostr_8bit(CHARSET_INFO *cs __attribute__((unused)), val= new_val; } - if (sl) - { - *--p='-'; - } - - l=e-p; - l=(l>len)?len:l; - memcpy(dst,p,l); - return (int)l; + len= min(len, (uint) (e-p)); + memcpy(dst, p, len); + return (int) len+sign; } + int my_ll10tostr_8bit(CHARSET_INFO *cs __attribute__((unused)), char *dst, uint len, int radix, longlong val) { char buffer[65]; register char *p, *e; long long_val; - int sl=0; - uint l; + uint sign= 0; if (radix < 0) { if (val < 0) { - sl=1; val = -val; + *dst++= '-'; + len--; + sign= 1; } } e = p = &buffer[sizeof(buffer)-1]; - *p='\0'; + *p= 0; if (val == 0) { - *--p='0'; + *--p= '0'; + len= 1; goto cnv; } @@ -800,16 +770,10 @@ int my_ll10tostr_8bit(CHARSET_INFO *cs __attribute__((unused)), long_val= quo; } + len= min(len, (uint) (e-p)); cnv: - if (sl) - { - *--p='-'; - } - - l=e-p; - l=(l>len)?len:l; - memcpy(dst,p,l); - return (int)(e-p); + memcpy(dst, p, len); + return len+sign; } diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index 42a70731ab5..4f72a4c2334 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -2874,37 +2874,31 @@ bs: double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)), - const char *nptr, uint l, char **endptr) + char *nptr, uint length, char **endptr) { char buf[256]; double res; register char *b=buf; register const char *s=nptr; - register const char *e=nptr+l; + register const char *end; my_wc_t wc; int cnv; - if((l+1)>sizeof(buf)) - { - if (endptr) - *endptr=(char*)nptr; - my_errno=ERANGE; - return 0; - } - - while ((cnv=cs->mb_wc(cs,&wc,s,e))>0) + /* Cut too long strings */ + if (length >= sizeof(buf)) + length= sizeof(buf)-1; + end=nptr+length; + + while ((cnv=cs->mb_wc(cs,&wc,s,end)) > 0) { s+=cnv; - if (wc < 128) - { - *b++=wc; - } - else - break; + if (wc > (int) (uchar) 'e' || !wc) + break; /* Can't be part of double */ + *b++=wc; } - *b='\0'; + *b= 0; - res=strtod(buf,endptr); + res=strtod(buf, endptr); if (endptr) *endptr=(char*) (*endptr-buf+nptr); return res; diff --git a/mysys/my_vsnprintf.c b/strings/my_vsnprintf.c index f6c91c0c329..a67523af7bc 100644 --- a/mysys/my_vsnprintf.c +++ b/strings/my_vsnprintf.c @@ -14,13 +14,25 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "mysys_priv.h" -#include "mysys_err.h" +#include <my_global.h> #include <m_string.h> #include <stdarg.h> #include <m_ctype.h> #include <assert.h> +/* + Limited snprintf() implementations + + IMPLEMENTION: + Supports following formats: + %#d + %#u + %#.#s Note #.# is skiped + + RETURN + length of result string +*/ + int my_snprintf(char* to, size_t n, const char* fmt, ...) { va_list args; @@ -31,9 +43,12 @@ int my_snprintf(char* to, size_t n, const char* fmt, ...) return result; } + int my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap) { char *start=to, *end=to+n-1; + uint length, num_state, pre_zero; + for (; *fmt ; fmt++) { if (fmt[0] != '%') @@ -43,10 +58,27 @@ int my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap) *to++= *fmt; /* Copy ordinary char */ continue; } - /* Skip if max size is used (to be compatible with printf) */ - fmt++; - while (my_isdigit(system_charset_info,*fmt) || *fmt == '.' || *fmt == '-') + fmt++; /* skip '%' */ + /* Read max fill size (only used with %d and %u) */ + if (*fmt == '-') fmt++; + length= num_state= pre_zero= 0; + for (;; fmt++) + { + if (my_isdigit(system_charset_info,*fmt)) + { + if (!num_state) + { + length=length*10+ (uint) (*fmt-'0'); + if (!length) + pre_zero= 1; /* first digit was 0 */ + } + continue; + } + if (*fmt != '.' || num_state) + break; + num_state= 1; + } if (*fmt == 'l') fmt++; if (*fmt == 's') /* String parameter */ @@ -63,13 +95,26 @@ int my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap) else if (*fmt == 'd' || *fmt == 'u') /* Integer parameter */ { register int iarg; - if ((uint) (end-to) < 16) + char *to_start= to; + if ((uint) (end-to) < max(16,length)) break; iarg = va_arg(ap, int); if (*fmt == 'd') to=int10_to_str((long) iarg,to, -10); else to=int10_to_str((long) (uint) iarg,to,10); + /* If %#d syntax was used, we have to pre-zero/pre-space the string */ + if (length) + { + uint res_length= (uint) (to - to_start); + if (res_length < length) + { + uint diff= (length- res_length); + bmove_upp(to+diff, to, res_length); + bfill(to-res_length, diff, pre_zero ? '0' : ' '); + to+= diff; + } + } continue; } /* We come here on '%%', unknown code or too long parameter */ |