From 98ef4a166342a3ff3dca1634ac58e6506aea9781 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Sun, 29 Aug 2021 12:36:04 +1000 Subject: [PATCH] [odbc] Ensure repid field formatting matching Microsoft Access ODBC driver formatting of these fields (i.e. without surrounding {} braces) --- include/mdbtools.h.in | 10 +++++++++- src/libmdb/data.c | 18 ++++++++++++++---- src/libmdb/file.c | 4 +++- src/odbc/odbc.c | 2 ++ 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/include/mdbtools.h.in b/include/mdbtools.h.in index 86e2b53..acc9309 100644 --- a/include/mdbtools.h.in +++ b/include/mdbtools.h.in @@ -158,6 +158,11 @@ enum { MDB_NO_MEMO = 0x0080, /* don't follow memo fields */ }; +typedef enum { + MDB_BRACES_4_2_2_8, /* "{XXXX-XX-XX-XXXXXXXX}" format */ + MDB_NOBRACES_4_2_2_2_6, /* "XXXX-XX-XX-XX-XXXXXX" format (matches MS Access ODBC driver) */ +} MdbUuidFormat; + #define mdb_is_logical_op(x) (x == MDB_OR || \ x == MDB_AND || \ x == MDB_NOT ) @@ -300,6 +305,7 @@ typedef struct { size_t bind_size; char date_fmt[64]; char shortdate_fmt[64]; + MdbUuidFormat repid_fmt; const char *boolean_false_value; const char *boolean_true_value; unsigned int num_catalog; @@ -530,7 +536,8 @@ int mdb_bind_column_by_name(MdbTableDef *table, gchar *col_name, void *bind_ptr, void mdb_data_dump(MdbTableDef *table); void mdb_date_to_tm(double td, struct tm *t); void mdb_tm_to_date(struct tm *t, double *td); -char *mdb_uuid_to_string(const void *buf, int start); +char *mdb_uuid_to_string(const void *buf, int start); /* Uses default MDB_BRACES_4_2_2_8 format */ +char *mdb_uuid_to_string_fmt(const void *buf, int start, MdbUuidFormat format); int mdb_bind_column(MdbTableDef *table, int col_num, void *bind_ptr, int *len_ptr); int mdb_rewind_table(MdbTableDef *table); int mdb_fetch_row(MdbTableDef *table); @@ -547,6 +554,7 @@ void* mdb_ole_read_full(MdbHandle *mdb, MdbColumn *col, size_t *size); void mdb_set_bind_size(MdbHandle *mdb, size_t bind_size); void mdb_set_date_fmt(MdbHandle *mdb, const char *); void mdb_set_shortdate_fmt(MdbHandle *mdb, const char *); +void mdb_set_repid_fmt(MdbHandle *mdb, MdbUuidFormat format); void mdb_set_boolean_fmt_words(MdbHandle *mdb); void mdb_set_boolean_fmt_numbers(MdbHandle *mdb); int mdb_read_row(MdbTableDef *table, unsigned int row); diff --git a/src/libmdb/data.c b/src/libmdb/data.c index ce09bda..78c3e3b 100644 --- a/src/libmdb/data.c +++ b/src/libmdb/data.c @@ -68,6 +68,11 @@ void mdb_set_shortdate_fmt(MdbHandle *mdb, const char *fmt) snprintf(mdb->shortdate_fmt, sizeof(mdb->shortdate_fmt), "%s", fmt); } +void mdb_set_repid_fmt(MdbHandle *mdb, MdbUuidFormat format) +{ + mdb->repid_fmt = format; +} + void mdb_set_boolean_fmt_numbers(MdbHandle *mdb) { mdb->boolean_false_value = boolean_false_number; @@ -946,15 +951,20 @@ mdb_date_to_string(MdbHandle *mdb, const char *fmt, void *buf, int start) } char *mdb_uuid_to_string(const void *buf, int pos) +{ + return mdb_uuid_to_string_fmt(buf,pos,MDB_BRACES_4_2_2_8); +} + +char *mdb_uuid_to_string_fmt(const void *buf, int pos, MdbUuidFormat format) { const unsigned char *kkd = (const unsigned char *)buf; - return g_strdup_printf("{%02X%02X%02X%02X" "-" "%02X%02X" "-" "%02X%02X" - "-" "%02X%02X" "%02X%02X%02X%02X%02X%02X}", + return g_strdup_printf(format == MDB_BRACES_4_2_2_8 + ? "{%02X%02X%02X%02X" "-" "%02X%02X" "-" "%02X%02X" "-" "%02X%02X%02X%02X%02X%02X%02X%02X}" + : "%02X%02X%02X%02X" "-" "%02X%02X" "-" "%02X%02X" "-" "%02X%02X" "-" "%02X%02X%02X%02X%02X%02X", kkd[pos+3], kkd[pos+2], kkd[pos+1], kkd[pos], // little-endian kkd[pos+5], kkd[pos+4], // little-endian kkd[pos+7], kkd[pos+6], // little-endian kkd[pos+8], kkd[pos+9], // big-endian - kkd[pos+10], kkd[pos+11], kkd[pos+12], kkd[pos+13], kkd[pos+14], kkd[pos+15]); // big-endian @@ -1046,7 +1056,7 @@ char *mdb_col_to_string(MdbHandle *mdb, void *buf, int start, int datatype, int text = mdb_money_to_string(mdb, start); break; case MDB_REPID: - text = mdb_uuid_to_string(buf, start); + text = mdb_uuid_to_string_fmt(buf, start, mdb->repid_fmt); break; default: /* shouldn't happen. bools are handled specially diff --git a/src/libmdb/file.c b/src/libmdb/file.c index a3c892a..6ab1a9b 100644 --- a/src/libmdb/file.c +++ b/src/libmdb/file.c @@ -130,6 +130,7 @@ static MdbHandle *mdb_handle_from_stream(FILE *stream, MdbFileFlags flags) { mdb_set_shortdate_fmt(mdb, "%x"); mdb_set_bind_size(mdb, MDB_BIND_SIZE); mdb_set_boolean_fmt_numbers(mdb); + mdb_set_repid_fmt(mdb, MDB_BRACES_4_2_2_8); #ifdef HAVE_ICONV mdb->iconv_in = (iconv_t)-1; mdb->iconv_out = (iconv_t)-1; @@ -315,10 +316,11 @@ MdbHandle *mdb_clone_handle(MdbHandle *mdb) mdb_iconv_init(newmdb); mdb_set_default_backend(newmdb, mdb->backend_name); - // date formats for the source handle may have been changed from + // formats for the source handle may have been changed from // the backend's default formats, so we need to explicitly copy them here mdb_set_date_fmt(newmdb, mdb->date_fmt); mdb_set_shortdate_fmt(newmdb, mdb->shortdate_fmt); + mdb_set_repid_fmt(newmdb, mdb->repid_fmt); if (mdb->f) { mdb->f->refs++; diff --git a/src/odbc/odbc.c b/src/odbc/odbc.c index a378935..bb29249 100644 --- a/src/odbc/odbc.c +++ b/src/odbc/odbc.c @@ -108,6 +108,8 @@ static SQLRETURN do_connect ( // https://docs.microsoft.com/en-us/sql/relational-databases/native-client-odbc-date-time/datetime-data-type-conversions-odbc?view=sql-server-ver15 mdb_set_date_fmt( dbc->sqlconn->mdb, "%F %H:%M:%S" ); mdb_set_shortdate_fmt( dbc->sqlconn->mdb, "%F" ); + // Match formatting of REPID type values to MS Access ODBC driver + mdb_set_repid_fmt( dbc->sqlconn->mdb, MDB_NOBRACES_4_2_2_2_6 ); return SQL_SUCCESS; } else