Commit 7a2ce399 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-34959 Add an OUTFILE option to dump binary data using HEX encoding

parent 0a5e4a01
......@@ -4047,6 +4047,9 @@ static void dump_table(const char *table, const char *db, const uchar *hash_key,
default_charset);
dynstr_append_checked(&query_string, " */");
if (opt_hex_blob)
dynstr_append_checked(&query_string, " BINARY ENCODED USING hex");
if (fields_terminated || enclosed || opt_enclosed || escaped)
dynstr_append_checked(&query_string, " FIELDS");
......
......@@ -23,3 +23,17 @@ SELECT * FROM t1;
id a
1 NULL
DROP TABLE t1;
#
# MDEV-34959 Add an OUTFILE option to dump binary data using HEX encoding
#
CREATE TABLE t1 (
name VARCHAR(10),
p point NOT NULL
) CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE t2 LIKE t1;
INSERT INTO t1 VALUES ('point1', GeomFromText('POINT(37.646944 -75.761111)'));
point1 \X000000000101000000F52B9D0FCFD242400E68E90AB6F052C0
SELECT AsText(p) FROM t2;
AsText(p)
POINT(37.646944 -75.761111)
DROP TABLE t1, t2;
......@@ -19,3 +19,25 @@ TRUNCATE TABLE t1;
LOAD DATA INFILE '../../std_data/loaddata/mdev-15497.txt' INTO TABLE t1 FIELDS TERMINATED BY '';
SELECT * FROM t1;
DROP TABLE t1;
--echo #
--echo # MDEV-34959 Add an OUTFILE option to dump binary data using HEX encoding
--echo #
CREATE TABLE t1 (
name VARCHAR(10),
p point NOT NULL
) CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE t2 LIKE t1;
INSERT INTO t1 VALUES ('point1', GeomFromText('POINT(37.646944 -75.761111)'));
--disable_query_log
eval SELECT * INTO OUTFILE '$MYSQLTEST_VARDIR/tmp/t1' BINARY ENCODED USING HEX FROM t1;
eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/t1' INTO TABLE t2;
--enable_query_log
--cat_file $MYSQLTEST_VARDIR/tmp/t1
SELECT AsText(p) FROM t2;
DROP TABLE t1, t2;
remove_file $MYSQLTEST_VARDIR/tmp/t1;
#
# MDEV-34959 Add an OUTFILE option to dump binary data using HEX encoding
#
SET NAMES utf8mb3;
CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET utf8mb3, b BLOB);
INSERT INTO t1 VALUES ('тест', 0xEE5C095C0A);
CREATE TABLE t2 LIKE t1;
тест \XEE5C095C0A
SELECT a, hex(b) FROM t2;
a hex(b)
тест EE5C095C0A
DROP TABLE t2;
CREATE TABLE t2 LIKE t1;
тест +XEE5C095C0A
SELECT a, hex(b) FROM t2;
a hex(b)
тест EE5C095C0A
DROP TABLE t2;
# Empty FIELDS ESCAPED BY
ERROR HY000: Conflicting declarations: 'BINARY ENCODED USING HEX' and 'FIELDS ESCAPED BY '''
тест \XEE5C095C0A
тест +XEE5C095C0A
DROP TABLE t1;
--echo #
--echo # MDEV-34959 Add an OUTFILE option to dump binary data using HEX encoding
--echo #
SET NAMES utf8mb3;
CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET utf8mb3, b BLOB);
INSERT INTO t1 VALUES ('тест', 0xEE5C095C0A);
CREATE TABLE t2 LIKE t1;
--disable_query_log
eval SELECT * INTO OUTFILE '$MYSQLTEST_VARDIR/tmp/t1' BINARY ENCODED USING HEX FROM t1;
eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/t1' INTO TABLE t2 CHARACTER SET utf8mb3;
--enable_query_log
--cat_file $MYSQLTEST_VARDIR/tmp/t1
SELECT a, hex(b) FROM t2;
DROP TABLE t2;
remove_file $MYSQLTEST_VARDIR/tmp/t1;
CREATE TABLE t2 LIKE t1;
--disable_query_log
eval SELECT * INTO OUTFILE '$MYSQLTEST_VARDIR/tmp/t1' BINARY ENCODED USING HEX FIELDS ESCAPED BY '+' FROM t1;
eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/t1' INTO TABLE t2 CHARACTER SET utf8mb3 FIELDS ESCAPED BY '+';
--enable_query_log
--cat_file $MYSQLTEST_VARDIR/tmp/t1
SELECT a, hex(b) FROM t2;
DROP TABLE t2;
remove_file $MYSQLTEST_VARDIR/tmp/t1;
--echo # Empty FIELDS ESCAPED BY
--disable_query_log
--error ER_CONFLICTING_DECLARATIONS
eval SELECT * INTO OUTFILE '$MYSQLTEST_VARDIR/tmp/t1' BINARY ENCODED USING HEX FIELDS ESCAPED BY '' FROM t1;
remove_file $MYSQLTEST_VARDIR/tmp/t1;
--enable_query_log
--exec $MYSQL_DUMP --default-character-set=utf8mb4 --hex-blob --skip-comments --tab=$MYSQLTEST_VARDIR/tmp/ test
--cat_file $MYSQLTEST_VARDIR/tmp/t1.txt
--remove_file $MYSQLTEST_VARDIR/tmp/t1.sql
--remove_file $MYSQLTEST_VARDIR/tmp/t1.txt
--exec $MYSQL_DUMP --default-character-set=utf8mb4 --hex-blob --fields-escaped-by=+ --skip-comments --tab=$MYSQLTEST_VARDIR/tmp/ test
--cat_file $MYSQLTEST_VARDIR/tmp/t1.txt
--remove_file $MYSQLTEST_VARDIR/tmp/t1.sql
--remove_file $MYSQLTEST_VARDIR/tmp/t1.txt
DROP TABLE t1;
......@@ -5398,6 +5398,16 @@ select astext(g) from t2;
astext(g)
POINT(1 1)
POINT(2 2)
truncate t2;
##################################################
\X000000000101000000000000000000F03F000000000000F03F
\X00000000010100000000000000000000400000000000000040
##################################################
LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/t1.txt' INTO TABLE t2 CHARACTER SET koi8r;
select astext(g) from t2;
astext(g)
POINT(1 1)
POINT(2 2)
drop table t1, t2;
#
# End of 5.1 tests
......
......@@ -2448,6 +2448,16 @@ SET @@global.general_log= @old_general_log_state;
create table t1 (g GEOMETRY) CHARSET koi8r;
create table t2 (g GEOMETRY) CHARSET koi8r;
insert into t1 values (point(1,1)), (point(2,2));
--exec $MYSQL_DUMP --disable-default-character-set --character-sets-dir=$MYSQL_SHAREDIR/charsets --tab=$MYSQLTEST_VARDIR/tmp/ test t1
--echo ##################################################
--cat_file $file
--echo ##################################################
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
--eval LOAD DATA INFILE '$file' INTO TABLE t2 CHARACTER SET koi8r
--remove_file $file
select astext(g) from t2;
truncate t2;
--exec $MYSQL_DUMP --disable-default-character-set --hex-blob --character-sets-dir=$MYSQL_SHAREDIR/charsets --tab=$MYSQLTEST_VARDIR/tmp/ test t1
--echo ##################################################
--cat_file $file
......
......@@ -191,17 +191,17 @@ SELECT SCHEMA_NAME, DIGEST, DIGEST_TEXT, COUNT_STAR
FROM performance_schema.events_statements_summary_by_digest
ORDER BY DIGEST_TEXT;
SCHEMA_NAME DIGEST DIGEST_TEXT COUNT_STAR
test eae5046a9d01df1163966c0bfeaebe2f EXPLAIN SELECT * FROM `test` . `v1` 1
test f1894d73004034fde99d25abd8416ffa EXPLAIN SELECT * FROM `test` . `v1` WHERE `a` = ? 1
test b1ddddcfd89c9c5e1326e0c520d03d87 EXPLAIN SELECT * FROM `test` . `v1` WHERE `b` > ? 1
test 4dd37d9265144f5232d4d4f52ba2191c EXPLAIN SELECT `a` , `b` FROM `test` . `v1` 1
test 38faf7d85ad1e905a0da57f4806cea9d EXPLAIN SELECT `b` , `a` FROM `test` . `v1` 1
test 927ed567fda67d2c992421529099860a SELECT * FROM `test` . `v1` 1
test ca236012aba4eb3ffdaf69abec7e9366 SELECT * FROM `test` . `v1` WHERE `a` = ? 1
test 525ea4996ecb5a00ee0e61f331a08305 SELECT * FROM `test` . `v1` WHERE `b` > ? 1
test 499aba5b6baca6e30c5d13efc9e616ba SELECT `a` , `b` FROM `test` . `v1` 1
test 3b6fbf35b223db3b2651f2accf6424d2 SELECT `b` , `a` FROM `test` . `v1` 1
test c552920371a4c5745ba299a89382e036 TRUNCATE TABLE `performance_schema` . `events_statements_summary_by_digest` 1
test bc007e8d3f588fc0099ceeb707b50e7a EXPLAIN SELECT * FROM `test` . `v1` 1
test b79844714b44b6dbd245272e7c9e46b1 EXPLAIN SELECT * FROM `test` . `v1` WHERE `a` = ? 1
test 5372ae885cc8e7bf93598b756fe5ac2a EXPLAIN SELECT * FROM `test` . `v1` WHERE `b` > ? 1
test 36d0eb0eb755bdf2cc18b0bdab6c67b5 EXPLAIN SELECT `a` , `b` FROM `test` . `v1` 1
test 545051df39de13279b4088ac94f54e4f EXPLAIN SELECT `b` , `a` FROM `test` . `v1` 1
test 4cf22eda8d41b78a5b6573010cd882f8 SELECT * FROM `test` . `v1` 1
test 4957bc8697872ebb224fa81fac92b461 SELECT * FROM `test` . `v1` WHERE `a` = ? 1
test 021f34631bccb638a641a71eb33f30ef SELECT * FROM `test` . `v1` WHERE `b` > ? 1
test 37f9a0c707746354acead03b9aa35688 SELECT `a` , `b` FROM `test` . `v1` 1
test bd73fe57a6a17f7341c2acf445e459fe SELECT `b` , `a` FROM `test` . `v1` 1
test 8cbee21c5c16d7162a0569e1f95221af TRUNCATE TABLE `performance_schema` . `events_statements_summary_by_digest` 1
DROP TABLE test.v1;
CREATE VIEW test.v1 AS SELECT * FROM test.t1;
EXPLAIN SELECT * from test.v1;
......@@ -248,19 +248,19 @@ SELECT SCHEMA_NAME, DIGEST, DIGEST_TEXT, COUNT_STAR
FROM performance_schema.events_statements_summary_by_digest
ORDER BY DIGEST_TEXT;
SCHEMA_NAME DIGEST DIGEST_TEXT COUNT_STAR
test 93b87bd4ebcbb5ae9bf2dba94c509fb9 CREATE VIEW `test` . `v1` AS SELECT * FROM `test` . `t1` 1
test 57cb0a39892c46938cd83aafa3908811 DROP TABLE `test` . `v1` 1
test eae5046a9d01df1163966c0bfeaebe2f EXPLAIN SELECT * FROM `test` . `v1` 2
test f1894d73004034fde99d25abd8416ffa EXPLAIN SELECT * FROM `test` . `v1` WHERE `a` = ? 2
test b1ddddcfd89c9c5e1326e0c520d03d87 EXPLAIN SELECT * FROM `test` . `v1` WHERE `b` > ? 2
test 4dd37d9265144f5232d4d4f52ba2191c EXPLAIN SELECT `a` , `b` FROM `test` . `v1` 2
test 38faf7d85ad1e905a0da57f4806cea9d EXPLAIN SELECT `b` , `a` FROM `test` . `v1` 2
test 927ed567fda67d2c992421529099860a SELECT * FROM `test` . `v1` 2
test ca236012aba4eb3ffdaf69abec7e9366 SELECT * FROM `test` . `v1` WHERE `a` = ? 2
test 525ea4996ecb5a00ee0e61f331a08305 SELECT * FROM `test` . `v1` WHERE `b` > ? 2
test 3bc8d25c6199783091cf96f3908727ca SELECT SCHEMA_NAME , `DIGEST` , `DIGEST_TEXT` , `COUNT_STAR` FROM `performance_schema` . `events_statements_summary_by_digest` ORDER BY `DIGEST_TEXT` 1
test 499aba5b6baca6e30c5d13efc9e616ba SELECT `a` , `b` FROM `test` . `v1` 2
test 3b6fbf35b223db3b2651f2accf6424d2 SELECT `b` , `a` FROM `test` . `v1` 2
test c552920371a4c5745ba299a89382e036 TRUNCATE TABLE `performance_schema` . `events_statements_summary_by_digest` 1
test 0bcd643de80604cb37c2e0253933ba3c CREATE VIEW `test` . `v1` AS SELECT * FROM `test` . `t1` 1
test 8ca8b8a7efb8f8b97478fec6030a1631 DROP TABLE `test` . `v1` 1
test bc007e8d3f588fc0099ceeb707b50e7a EXPLAIN SELECT * FROM `test` . `v1` 2
test b79844714b44b6dbd245272e7c9e46b1 EXPLAIN SELECT * FROM `test` . `v1` WHERE `a` = ? 2
test 5372ae885cc8e7bf93598b756fe5ac2a EXPLAIN SELECT * FROM `test` . `v1` WHERE `b` > ? 2
test 36d0eb0eb755bdf2cc18b0bdab6c67b5 EXPLAIN SELECT `a` , `b` FROM `test` . `v1` 2
test 545051df39de13279b4088ac94f54e4f EXPLAIN SELECT `b` , `a` FROM `test` . `v1` 2
test 4cf22eda8d41b78a5b6573010cd882f8 SELECT * FROM `test` . `v1` 2
test 4957bc8697872ebb224fa81fac92b461 SELECT * FROM `test` . `v1` WHERE `a` = ? 2
test 021f34631bccb638a641a71eb33f30ef SELECT * FROM `test` . `v1` WHERE `b` > ? 2
test d18d02d907eceaf4c41a943306e6d998 SELECT SCHEMA_NAME , `DIGEST` , `DIGEST_TEXT` , `COUNT_STAR` FROM `performance_schema` . `events_statements_summary_by_digest` ORDER BY `DIGEST_TEXT` 1
test 37f9a0c707746354acead03b9aa35688 SELECT `a` , `b` FROM `test` . `v1` 2
test bd73fe57a6a17f7341c2acf445e459fe SELECT `b` , `a` FROM `test` . `v1` 2
test 8cbee21c5c16d7162a0569e1f95221af TRUNCATE TABLE `performance_schema` . `events_statements_summary_by_digest` 1
DROP VIEW test.v1;
DROP TABLE test.t1;
......@@ -8,5 +8,5 @@ SELECT 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1
####################################
SELECT event_name, digest, digest_text, sql_text FROM events_statements_history_long;
event_name digest digest_text sql_text
statement/sql/select 230fd11f009a87fecbb87c9fc7361475 SELECT ? + ? + SELECT ...
statement/sql/truncate 19da7becacbb87bb3794bf9f77138fb5 TRUNCATE TABLE truncat...
statement/sql/select faee27453a15862c26b6d5d39456ff74 SELECT ? + ? + SELECT ...
statement/sql/truncate faf6cefb662b443f05e97b5c5ab14a59 TRUNCATE TABLE truncat...
......@@ -3802,40 +3802,19 @@ String *Item_func_hex::val_str_ascii_from_val_int(String *str)
String *Item_func_unhex::val_str(String *str)
{
const char *from, *end;
char *to;
String *res;
uint length;
DBUG_ASSERT(fixed == 1);
res= args[0]->val_str(&tmp_value);
if (!res || str->alloc(length= (1+res->length())/2))
if (!res)
{
null_value=1;
return 0;
}
from= res->ptr();
null_value= 0;
str->set_charset(&my_charset_bin);
str->length(length);
to= (char*) str->ptr();
if (res->length() % 2)
{
int hex_char;
*to++= hex_char= hexchar_to_int(*from++);
if ((null_value= (hex_char == -1)))
return 0;
}
for (end=res->ptr()+res->length(); from < end ; from+=2, to++)
{
int hex_char1, hex_char2;
hex_char1= hexchar_to_int(from[0]);
hex_char2= hexchar_to_int(from[1]);
if ((null_value= (hex_char1 == -1 || hex_char2 == -1)))
return 0;
*to= (char) ((hex_char1 << 4) | hex_char2);
}
if ((null_value= str->set_unhex(res->ptr(), res->length())))
return 0;
return str;
}
......
......@@ -213,6 +213,7 @@ SYMBOL symbols[] = {
{ "ELSIF", SYM(ELSIF_MARIADB_SYM)},
{ "ENABLE", SYM(ENABLE_SYM)},
{ "ENCLOSED", SYM(ENCLOSED)},
{ "ENCODED", SYM(ENCODED)},
{ "END", SYM(END)},
{ "ENDS", SYM(ENDS_SYM)},
{ "ENGINE", SYM(ENGINE_SYM)},
......
......@@ -3088,7 +3088,8 @@ static String default_xml_row_term("<row>", default_charset_info);
sql_exchange::sql_exchange(const char *name, bool flag,
enum enum_filetype filetype_arg)
:file_name(name), opt_enclosed(0), dumpfile(flag), skip_lines(0)
:file_name(name), opt_enclosed(0), dumpfile(flag), skip_lines(0),
opt_hexblob(false)
{
filetype= filetype_arg;
field_term= &default_field_term;
......@@ -3340,6 +3341,13 @@ select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
non_string_results= TRUE;
}
}
if (exchange->opt_hexblob && !exchange->escaped->length())
{
my_error(ER_CONFLICTING_DECLARATIONS, MYF(0),
"BINARY ENCODED USING HEX", "",
"FIELDS ESCAPED BY ''", "");
return true;
}
if (exchange->escaped->numchars() > 1 || exchange->enclosed->numchars() > 1)
{
my_error(ER_WRONG_FIELD_TERMINATORS, MYF(0));
......@@ -3435,6 +3443,21 @@ int select_export::send_data(List<Item> &items)
bool enclosed = (exchange->enclosed->length() &&
(!exchange->opt_enclosed || result_type == STRING_RESULT));
res=item->str_result(&tmp);
bool using_hex= escape_char != -1 && exchange->opt_hexblob &&
res && res->charset() == &my_charset_bin &&
result_type == STRING_RESULT;
if (res && res->length() && using_hex)
{
StringBuffer<256> tmp;
tmp.set_hex(res->ptr(), res->length());
uchar escape_ch= (uchar) escape_char;
if (my_b_write(&cache, &escape_ch, 1) ||
my_b_write(&cache, (const uchar *) "X", 1) ||
my_b_write(&cache, (uchar*) tmp.ptr(), tmp.length()))
goto err;
goto end_of_field;
}
if (res && !my_charset_same(write_cs, res->charset()) &&
!my_charset_same(write_cs, &my_charset_bin))
{
......@@ -3635,6 +3658,7 @@ int select_export::send_data(List<Item> &items)
exchange->enclosed->length()))
goto err;
}
end_of_field:
if (--items_left)
{
if (my_b_write(&cache, (uchar*) exchange->field_term->ptr(),
......
......@@ -5535,6 +5535,7 @@ class sql_exchange :public Sql_alloc
bool dumpfile;
ulong skip_lines;
CHARSET_INFO *cs;
bool opt_hexblob;
sql_exchange(const char *name, bool dumpfile_flag,
enum_filetype filetype_arg= FILETYPE_CSV);
bool escaped_given(void) const;
......
......@@ -276,6 +276,10 @@ class READ_INFO: public Load_data_param
while (GET != my_b_EOF)
;
}
int get_escape_char() const
{
return escape_char;
}
};
static int read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
......@@ -1148,8 +1152,22 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
else
{
read_info.row_end[0]= 0; // Safe to change end marker
if (dst->load_data_set_value(thd, (const char *) pos, length, &read_info))
DBUG_RETURN(1);
if (length > 3 &&
pos[0] == read_info.get_escape_char() &&
pos[1] == 'X')
{
StringBuffer<256> tmp;
if (tmp.set_unhex((const char*) pos + 2, length - 2) ||
dst->load_data_set_value(thd, tmp.ptr(), tmp.length(),
&read_info))
DBUG_RETURN(1);
}
else
{
if (dst->load_data_set_value(thd, (const char *) pos, length,
&read_info))
DBUG_RETURN(1);
}
}
}
......@@ -1499,7 +1517,7 @@ inline bool READ_INFO::terminator(const uchar *ptr, uint length)
int READ_INFO::read_field()
{
int chr,found_enclosed_char;
int chr,found_enclosed_char= INT_MAX;
found_null=0;
if (found_end_of_line)
......@@ -1524,9 +1542,22 @@ int READ_INFO::read_field()
found_enclosed_char=enclosed_char;
data.append(chr); // If error
}
else if (chr == escape_char)
{
int chr2= GET;
if (chr2 == 'X')
{
data.append(chr);
data.append(chr2);
}
else
{
PUSH(chr2);
PUSH(chr);
}
}
else
{
found_enclosed_char= INT_MAX;
PUSH(chr);
}
......
......@@ -403,20 +403,6 @@ extern void turn_parser_debug_on_ORAparse();
#endif
/**
convert a hex digit into number.
*/
inline int hexchar_to_int(char c)
{
if (c <= '9' && c >= '0')
return c-'0';
c|=32;
if (c <= 'f' && c >= 'a')
return c-'a'+10;
return -1;
}
/* This must match the path length limit in the ER_NOT_RW_DIR error msg. */
#define ER_NOT_RW_DIR_PATHSIZE 200
......
......@@ -26,6 +26,7 @@
#include <mysql_com.h>
#include "sql_string.h"
#include "strfunc.h" // hexchar_to_int
/*****************************************************************************
** String functions
......@@ -194,6 +195,42 @@ bool Binary_string::set_hex(const char *str, uint32 len)
}
bool Binary_string::set_unhex(const char *from, uint32 from_length)
{
uint32 dst_length= from_length / 2 + 1;
if (alloc(dst_length))
return true;
length(0);
return qs_append_unhex(from, from_length);
}
bool Static_binary_string::qs_append_unhex(const char *from, uint32 from_length)
{
char *to= Ptr + str_length;
const char *from_end= from + from_length;
if (from_length % 2)
{
int hex_char;
*to++= hex_char= hexchar_to_int(*from++);
if ((hex_char == -1))
return true;
}
for ( ; from < from_end ; from+= 2, to++)
{
int hex_char1, hex_char2;
hex_char1= hexchar_to_int(from[0]);
hex_char2= hexchar_to_int(from[1]);
if (hex_char1 == -1 || hex_char2 == -1)
return true;
*to= (char) ((hex_char1 << 4) | hex_char2);
}
str_length= (uint32) (to - Ptr);
return false;
}
bool Binary_string::set_fcvt(double num, uint decimals)
{
// Assert that `decimals` is small enough to fit into FLOATING_POINT_BUFFER
......
......@@ -440,6 +440,7 @@ class Static_binary_string : public Sql_alloc
void qs_append(const char *str, size_t len);
void qs_append_hex(const char *str, uint32 len);
void qs_append_hex_uint32(uint32 num);
bool qs_append_unhex(const char *str, uint32 len);
void qs_append(double d);
void qs_append(const double *d);
inline void qs_append(const char c)
......@@ -625,6 +626,7 @@ class Binary_string: public Static_binary_string
bool set_hex(ulonglong num);
bool set_hex(const char *str, uint32 len);
bool set_unhex(const char *str, uint32 len);
bool set_fcvt(double num, uint decimals);
bool copy(); // Alloc string if not alloced
......
......@@ -501,6 +501,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%token <kwd> ELSE /* SQL-2003-R */
%token <kwd> ELSIF_ORACLE_SYM /* PLSQL-R */
%token <kwd> ENCLOSED
%token <kwd> ENCODED
%token <kwd> ESCAPED
%token <kwd> EXCEPT_SYM /* SQL-2003-R */
%token <kwd> EXISTS /* SQL-2003-R */
......@@ -1404,6 +1405,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
case_stmt_body opt_bin_mod opt_for_system_time_clause
opt_if_exists_table_element opt_if_not_exists_table_element
opt_recursive opt_format_xid opt_for_portion_of_time_clause
opt_hexblob
%type <object_ddl_options>
create_or_replace
......@@ -6826,6 +6828,19 @@ opt_load_data_charset:
| charset charset_name_or_default { $$= $2; }
;
opt_hexblob:
/* Empty */ { $$= false; }
| BINARY ENCODED USING ident
{
if ($4.length != 3 || strncasecmp($4.str, "hex", 3))
my_yyabort_error((ER_BAD_OPTION_VALUE, MYF(0),
ErrConvString($4.str, $4.length,
system_charset_info).ptr(),
"ENCODED"));
$$= true;
}
;
old_or_new_charset_name:
ident_or_text
{
......@@ -12784,6 +12799,8 @@ into_destination:
}
opt_load_data_charset
{ Lex->exchange->cs= $4; }
opt_hexblob
{ Lex->exchange->opt_hexblob= $6; }
opt_field_term opt_line_term
| DUMPFILE TEXT_STRING_filesystem
{
......@@ -16131,6 +16148,7 @@ reserved_keyword_udt_not_param_type:
| ELSEIF_MARIADB_SYM
| ELSIF_ORACLE_SYM
| ENCLOSED
| ENCODED
| ESCAPED
| EXCEPT_SYM
| EXISTS
......
......@@ -16,6 +16,21 @@
#ifndef STRFUNC_INCLUDED
#define STRFUNC_INCLUDED
/**
convert a hex digit into number.
*/
inline int hexchar_to_int(char c)
{
if (c <= '9' && c >= '0')
return c-'0';
c|=32;
if (c <= 'f' && c >= 'a')
return c-'a'+10;
return -1;
}
typedef struct st_typelib TYPELIB;
ulonglong find_set(const TYPELIB *lib,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment