diff options
Diffstat (limited to 'sql/sql_class.cc')
-rw-r--r-- | sql/sql_class.cc | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 9db86214a6b..a9c399e15de 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1790,6 +1790,8 @@ select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u) if ((uint) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN) strmake(path,exchange->file_name,FN_REFLEN-1); + write_cs= exchange->cs ? exchange->cs : &my_charset_bin; + if ((file= create_file(thd, path, exchange, &cache)) < 0) return 1; /* Check if there is any blobs in data */ @@ -1809,6 +1811,31 @@ select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u) non_string_results= TRUE; } } + if (exchange->escaped->numchars() > 1 || exchange->enclosed->numchars() > 1) + { + my_error(ER_WRONG_FIELD_TERMINATORS, MYF(0)); + return TRUE; + } + if (exchange->escaped->length() > 1 || exchange->enclosed->length() > 1 || + !my_isascii(exchange->escaped->ptr()[0]) || + !my_isascii(exchange->enclosed->ptr()[0]) || + !exchange->field_term->is_ascii() || !exchange->line_term->is_ascii() || + !exchange->line_start->is_ascii()) + { + /* + Current LOAD DATA INFILE recognizes field/line separators "as is" without + converting from client charset to data file charset. So, it is supposed, + that input file of LOAD DATA INFILE consists of data in one charset and + separators in other charset. For the compatibility with that [buggy] + behaviour SELECT INTO OUTFILE implementation has been saved "as is" too, + but the new warning message has been added: + + Non-ASCII separator arguments are not fully supported + */ + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + WARN_NON_ASCII_SEPARATOR_NOT_IMPLEMENTED, + ER(WARN_NON_ASCII_SEPARATOR_NOT_IMPLEMENTED)); + } field_term_length=exchange->field_term->length(); field_term_char= field_term_length ? (int) (uchar) (*exchange->field_term)[0] : INT_MAX; @@ -1858,6 +1885,8 @@ bool select_export::send_data(List<Item> &items) DBUG_ENTER("select_export::send_data"); char buff[MAX_FIELD_WIDTH],null_buff[2],space[MAX_FIELD_WIDTH]; + char cvt_buff[MAX_FIELD_WIDTH]; + String cvt_str(cvt_buff, sizeof(cvt_buff), write_cs); bool space_inited=0; String tmp(buff,sizeof(buff),&my_charset_bin),*res; tmp.length(0); @@ -1881,6 +1910,37 @@ bool select_export::send_data(List<Item> &items) bool enclosed = (exchange->enclosed->length() && (!exchange->opt_enclosed || result_type == STRING_RESULT)); res=item->str_result(&tmp); + if (res && !my_charset_same(write_cs, res->charset()) && + !my_charset_same(write_cs, &my_charset_bin)) + { + const char *well_formed_error_pos; + const char *cannot_convert_error_pos; + const char *from_end_pos; + const char *error_pos; + uint32 bytes; + bytes= well_formed_copy_nchars(write_cs, cvt_buff, sizeof(cvt_buff), + res->charset(), res->ptr(), res->length(), + sizeof(cvt_buff), + &well_formed_error_pos, + &cannot_convert_error_pos, + &from_end_pos); + error_pos= well_formed_error_pos ? well_formed_error_pos + : cannot_convert_error_pos; + if (error_pos) + { + char printable_buff[32]; + convert_to_printable(printable_buff, sizeof(printable_buff), + error_pos, res->ptr() + res->length() - error_pos, + res->charset(), 6); + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_TRUNCATED_WRONG_VALUE_FOR_FIELD, + ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD), + "string", printable_buff, + item->name, row_count); + } + cvt_str.length(bytes); + res= &cvt_str; + } if (res && enclosed) { if (my_b_write(&cache,(uchar*) exchange->enclosed->ptr(), |