From a980d73447c2e664ca694bb2693b027b48deb5d0 Mon Sep 17 00:00:00 2001 From: James Woodcock Date: Wed, 3 Feb 2021 19:48:56 +0000 Subject: [PATCH] mdb-export: handle MySQL blobs (#250) * Refactor code so BLOBs are always correctly exported Previously, BLOBs weren't exported from mdb-export correctly if the backend had MDB_SHEXP_BULK_INSERT set. * Export MySQL BLOBs correctly MySQL BLOBs should be in the form 0x[hex values] when inserting them with the mysql command line tool. * MySQL needs a BLOB to store exported MDB_OLE values MDB_OLE size always comes out as 256 bytes, but varbinary(256) is insufficient to hold all possible OLE data. --- src/libmdb/backend.c | 2 +- src/util/mdb-export.c | 64 +++++++++++++++++++++++++++++-------------- 2 files changed, 45 insertions(+), 21 deletions(-) diff --git a/src/libmdb/backend.c b/src/libmdb/backend.c index 8853630..b46c71a 100644 --- a/src/libmdb/backend.c +++ b/src/libmdb/backend.c @@ -114,7 +114,7 @@ static const MdbBackendType mdb_mysql_types[] = { [MDB_DATETIME] = { .name = "datetime" }, [MDB_BINARY] = { .name = "blob" }, [MDB_TEXT] = { .name = "varchar", .needs_char_length = 1 }, - [MDB_OLE] = { .name = "varbinary", .needs_byte_length = 1 }, + [MDB_OLE] = { .name = "blob" }, [MDB_MEMO] = { .name = "text" }, [MDB_REPID] = { .name = "char(38)" }, [MDB_NUMERIC] = { .name = "numeric", .needs_precision = 1, .needs_scale = 1 }, diff --git a/src/util/mdb-export.c b/src/util/mdb-export.c index eaeff51..ef3a20d 100755 --- a/src/util/mdb-export.c +++ b/src/util/mdb-export.c @@ -24,6 +24,7 @@ #define is_binary_type(x) (x==MDB_OLE || x==MDB_BINARY || x==MDB_REPID) static char *escapes(char *s); +static void format_value(FILE *outfile, char *value, size_t length, int quote_text, int col_type, char *escape_char, char *quote_char, int bin_mode, int export_flags, char *backend_name); int main(int argc, char **argv) @@ -256,7 +257,11 @@ main(int argc, char **argv) value = bound_values[i]; length = bound_lens[i]; } - mdb_print_col(outfile, value, quote_text, col->col_type, length, quote_char, escape_char, bin_mode | export_flags); + format_value(outfile, value, length, + quote_text, col->col_type, + escape_char, quote_char, + bin_mode, export_flags, + mdb->backend_name); if (col->col_type == MDB_OLE) free(value); } @@ -308,25 +313,11 @@ main(int argc, char **argv) value = bound_values[i]; length = bound_lens[i]; } - /* Correctly handle insertion of binary blobs into SQLite using the string literal notation of X'1234ABCD...' */ - if (!strcmp(mdb->backend_name, "sqlite") && is_binary_type(col->col_type) - && bin_mode == MDB_BINEXPORT_HEXADECIMAL) { - char *quote_char_binary_sqlite = (char *) g_strdup("'"); - fputs("X", outfile); - mdb_print_col(outfile, value, quote_text, col->col_type, length, quote_char_binary_sqlite, escape_char, bin_mode | export_flags); - g_free (quote_char_binary_sqlite); - /* Correctly handle insertion of binary blobs into PostgreSQL using the notation of decode('1234ABCD...', 'hex') */ - } else if (!strcmp(mdb->backend_name, "postgres") && is_binary_type(col->col_type) - && bin_mode == MDB_BINEXPORT_HEXADECIMAL) { - char *quote_char_binary_postgres = (char *) g_strdup("'"); - fputs("decode(", outfile); - mdb_print_col(outfile, value, quote_text, col->col_type, length, quote_char_binary_postgres, escape_char, bin_mode | export_flags); - fputs(", 'hex')", outfile); - g_free (quote_char_binary_postgres); - /* No special treatment for other backends or when hexadecimal notation hasn't been selected with the -b hex command line option */ - } else { - mdb_print_col(outfile, value, quote_text, col->col_type, length, quote_char, escape_char, bin_mode | export_flags); - } + format_value(outfile, value, length, + quote_text, col->col_type, + escape_char, quote_char, + bin_mode, export_flags, + mdb->backend_name); if (col->col_type == MDB_OLE) free(value); } @@ -360,6 +351,39 @@ main(int argc, char **argv) return 0; } +static void format_value(FILE *outfile, char *value, size_t length, int quote_text, int col_type, char *escape_char, char *quote_char, int bin_mode, int export_flags, char *backend_name) +{ + /* Correctly handle insertion of binary blobs into sqlite3 using the notation of X'1234ABCD...') */ + if (!strcmp(backend_name, "sqlite") + && is_binary_type(col_type) + && bin_mode == MDB_BINEXPORT_HEXADECIMAL) { + char *quote_char_binary_sqlite = (char *) g_strdup("'"); + fputs("X", outfile); + mdb_print_col(outfile, value, quote_text, col_type, length, quote_char_binary_sqlite, escape_char, bin_mode | export_flags); + g_free (quote_char_binary_sqlite); + /* Correctly handle insertion of binary blobs into MySQL using the notation of 0x1234ABCD...) */ + } else if (!strcmp(backend_name, "mysql") + && is_binary_type(col_type) + && bin_mode == MDB_BINEXPORT_HEXADECIMAL) { + char *quote_char_binary_sqlite = (char *) g_strdup(""); + fputs("0x", outfile); + mdb_print_col(outfile, value, quote_text, col_type, length, quote_char_binary_sqlite, escape_char, bin_mode | export_flags); + g_free (quote_char_binary_sqlite); + /* Correctly handle insertion of binary blobs into PostgreSQL using the notation of decode('1234ABCD...', 'hex') */ + } else if (!strcmp(backend_name, "postgres") + && is_binary_type(col_type) + && bin_mode == MDB_BINEXPORT_HEXADECIMAL) { + char *quote_char_binary_postgres = (char *) g_strdup("'"); + fputs("decode(", outfile); + mdb_print_col(outfile, value, quote_text, col_type, length, quote_char_binary_postgres, escape_char, bin_mode | export_flags); + fputs(", 'hex')", outfile); + g_free (quote_char_binary_postgres); + /* No special treatment for other backends or when hexadecimal notation hasn't been selected with the -b hex command line option */ + } else { + mdb_print_col(outfile, value, quote_text, col_type, length, quote_char, escape_char, bin_mode | export_flags); + } +} + static char *escapes(char *s) { char *d = (char *) g_strdup(s);