Fixed bug #29442.
The SELECT INTO OUTFILE FIELDS ENCLOSED BY digit or minus sign, followed by the same LOAD DATA INFILE statement, used wrond encoding of non-string fields contained the enclosed character in their text representation. Example: SELECT 15, 9 INTO OUTFILE 'text' FIELDS ENCLOSED BY '5'; Old encoded result in the text file: 5155 595 ^ was decoded as the 1st enclosing character of the 2nd field; ^ was skipped as garbage; ^ ^ was decoded as a pair of englosing characters of the 1st field; ^ was decoded as traling space of the first field; ^^ was decoded as a doubled enclosed character. New encoded result in the text file: 51\55 595 ^ ^ pair of enclosing characters of the 1st field; ^^ escaped enclosed character. sql/sql_class.h: Fixed bug #29442. The NUMERIC_CHARS macro constant has been defined to enumerate all possible characters of a numeric value text representation. The select_export::is_unsafe_field_sep boolean flag has been added to apply the encoding algorithm to non-string values when it is necessary. sql/sql_class.cc: Fixed bug #29442. The select_export::send_data method has been modified to encode text representation of fields of all data types like string fields. mysql-test/t/loaddata.test: Updated test case for bug #29442. mysql-test/r/loaddata.result: Updated test case for bug #29442.
This commit is contained in:
parent
e0f93ca8c1
commit
725b49716b
@ -238,3 +238,17 @@ f1
|
||||
1
|
||||
2
|
||||
drop table t1,t2;
|
||||
CREATE TABLE t1 (c1 INT, c2 TIMESTAMP, c3 REAL, c4 DOUBLE);
|
||||
INSERT INTO t1 (c1, c2, c3, c4) VALUES (10, '1970-02-01 01:02:03', 1.1E-100, 1.1E+100);
|
||||
SELECT * FROM t1;
|
||||
c1 c2 c3 c4
|
||||
10 1970-02-01 01:02:03 1.1e-100 1.1e+100
|
||||
SELECT * INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/t1' FIELDS ENCLOSED BY '-' FROM t1;
|
||||
-10- -1970\-02\-01 01:02:03- -1.1e\-100- -1.1e+100-
|
||||
EOF
|
||||
TRUNCATE t1;
|
||||
LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/t1' INTO TABLE t1 FIELDS ENCLOSED BY '-';
|
||||
SELECT * FROM t1;
|
||||
c1 c2 c3 c4
|
||||
10 1970-02-01 01:02:03 1.1e-100 1.1e+100
|
||||
DROP TABLE t1;
|
||||
|
@ -213,4 +213,29 @@ select f1 from t1 where f2 <> '0000-00-00 00:00:00' order by f1;
|
||||
--exec rm $MYSQLTEST_VARDIR/tmp/t2
|
||||
drop table t1,t2;
|
||||
|
||||
#
|
||||
# Bug#29442: SELECT INTO OUTFILE FIELDS ENCLOSED BY digit, minus sign etc
|
||||
# corrupts non-string fields containing this character.
|
||||
#
|
||||
|
||||
CREATE TABLE t1 (c1 INT, c2 TIMESTAMP, c3 REAL, c4 DOUBLE);
|
||||
|
||||
INSERT INTO t1 (c1, c2, c3, c4) VALUES (10, '1970-02-01 01:02:03', 1.1E-100, 1.1E+100);
|
||||
SELECT * FROM t1;
|
||||
|
||||
--exec rm -f $MYSQLTEST_VARDIR/tmp/t1
|
||||
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||
eval SELECT * INTO OUTFILE '$MYSQLTEST_VARDIR/tmp/t1' FIELDS ENCLOSED BY '-' FROM t1;
|
||||
--exec cat $MYSQLTEST_VARDIR/tmp/t1
|
||||
--exec echo EOF
|
||||
|
||||
TRUNCATE t1;
|
||||
|
||||
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||
eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/t1' INTO TABLE t1 FIELDS ENCLOSED BY '-';
|
||||
SELECT * FROM t1;
|
||||
|
||||
--exec rm $MYSQLTEST_VARDIR/tmp/t1
|
||||
DROP TABLE t1;
|
||||
|
||||
# End of 5.0 tests
|
||||
|
@ -1210,6 +1210,7 @@ select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
|
||||
field_term_length ? (*exchange->field_term)[0] : INT_MAX);
|
||||
escape_char= (exchange->escaped->length() ? (*exchange->escaped)[0] : -1);
|
||||
is_ambiguous_field_sep= test(strchr(ESCAPE_CHARS, field_sep_char));
|
||||
is_unsafe_field_sep= test(strchr(NUMERIC_CHARS, field_sep_char));
|
||||
line_sep_char= (exchange->line_term->length() ?
|
||||
(*exchange->line_term)[0] : INT_MAX);
|
||||
if (!field_term_length)
|
||||
@ -1284,7 +1285,8 @@ bool select_export::send_data(List<Item> &items)
|
||||
used_length=min(res->length(),item->max_length);
|
||||
else
|
||||
used_length=res->length();
|
||||
if (result_type == STRING_RESULT && escape_char != -1)
|
||||
if ((result_type == STRING_RESULT || is_unsafe_field_sep) &&
|
||||
escape_char != -1)
|
||||
{
|
||||
char *pos, *start, *end;
|
||||
CHARSET_INFO *res_charset= res->charset();
|
||||
|
@ -1929,6 +1929,12 @@ public:
|
||||
#define ESCAPE_CHARS "ntrb0ZN" // keep synchronous with READ_INFO::unescape
|
||||
|
||||
|
||||
/*
|
||||
List of all possible characters of a numeric value text representation.
|
||||
*/
|
||||
#define NUMERIC_CHARS ".0123456789e+-"
|
||||
|
||||
|
||||
class select_export :public select_to_file {
|
||||
uint field_term_length;
|
||||
int field_sep_char,escape_char,line_sep_char;
|
||||
@ -1938,6 +1944,12 @@ class select_export :public select_to_file {
|
||||
(see the READ_INFO::unescape method and the ESCAPE_CHARS constant value).
|
||||
*/
|
||||
bool is_ambiguous_field_sep;
|
||||
/*
|
||||
The is_unsafe_field_sep field is true if a value of the field_sep_char
|
||||
field is one of the '0'..'9', '+', '-', '.' and 'e' characters
|
||||
(see the NUMERIC_CHARS constant value).
|
||||
*/
|
||||
bool is_unsafe_field_sep;
|
||||
bool fixed_row_size;
|
||||
public:
|
||||
select_export(sql_exchange *ex) :select_to_file(ex) {}
|
||||
|
Loading…
x
Reference in New Issue
Block a user