[API break] Make date/boolean formats thread safe

Store the preferred date and boolean formats in the MdbHandle rather
than in global memory.
This commit is contained in:
Evan Miller
2020-08-19 21:26:06 -04:00
parent 7b51824c89
commit 5d078838ed
4 changed files with 41 additions and 35 deletions

View File

@@ -277,6 +277,9 @@ typedef struct {
char *backend_name;
MdbFormatConstants *fmt;
MdbStatistics *stats;
char date_fmt[64];
const char *boolean_false_value;
const char *boolean_true_value;
#ifdef HAVE_ICONV
iconv_t iconv_in;
iconv_t iconv_out;
@@ -506,8 +509,9 @@ int mdb_col_disp_size(MdbColumn *col);
size_t mdb_ole_read_next(MdbHandle *mdb, MdbColumn *col, void *ole_ptr);
size_t mdb_ole_read(MdbHandle *mdb, MdbColumn *col, void *ole_ptr, size_t chunk_size);
void* mdb_ole_read_full(MdbHandle *mdb, MdbColumn *col, size_t *size);
void mdb_set_date_fmt(const char *);
void mdb_set_boolean_fmt_words(void);
void mdb_set_date_fmt(MdbHandle *mdb, const char *);
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);
/* dump.c */

View File

@@ -32,39 +32,39 @@ char *mdb_numeric_to_string(MdbHandle *mdb, int start, int prec, int scale);
static int _mdb_attempt_bind(MdbHandle *mdb,
MdbColumn *col, unsigned char isnull, int offset, int len);
static char *mdb_date_to_string(void *buf, int start);
static char *mdb_date_to_string(MdbHandle *mdb, void *buf, int start);
#ifdef MDB_COPY_OLE
static size_t mdb_copy_ole(MdbHandle *mdb, void *dest, int start, int size);
#endif
static char date_fmt[64] = "%x %X";
static int noleap_cal[] = {0,31,59,90,120,151,181,212,243,273,304,334,365};
static int leap_cal[] = {0,31,60,91,121,152,182,213,244,274,305,335,366};
void mdb_set_date_fmt(const char *fmt)
{
date_fmt[63] = 0;
strncpy(date_fmt, fmt, 63);
}
static const int noleap_cal[] = {0,31,59,90,120,151,181,212,243,273,304,334,365};
static const int leap_cal[] = {0,31,60,91,121,152,182,213,244,274,305,335,366};
/* Some databases (eg PostgreSQL) do not understand integer 0/1 values
* as TRUE/FALSE, so provide a means to override the values used to be
* the SQL Standard TRUE/FALSE values.
*/
static char boolean_false_number[] = "0";
static char boolean_true_number[] = "1";
static const char boolean_false_number[] = "0";
static const char boolean_true_number[] = "1";
static char boolean_false_word[] = "FALSE";
static char boolean_true_word[] = "TRUE";
static const char boolean_false_word[] = "FALSE";
static const char boolean_true_word[] = "TRUE";
static char *boolean_false_value = boolean_false_number;
static char *boolean_true_value = boolean_true_number;
void mdb_set_boolean_fmt_words()
void mdb_set_date_fmt(MdbHandle *mdb, const char *fmt)
{
boolean_false_value = boolean_false_word;
boolean_true_value = boolean_true_word;
snprintf(mdb->date_fmt, sizeof(mdb->date_fmt), "%s", fmt);
}
void mdb_set_boolean_fmt_numbers(MdbHandle *mdb)
{
mdb->boolean_false_value = boolean_false_number;
mdb->boolean_true_value = boolean_true_number;
}
void mdb_set_boolean_fmt_words(MdbHandle *mdb)
{
mdb->boolean_false_value = boolean_false_word;
mdb->boolean_true_value = boolean_true_word;
}
void mdb_bind_column(MdbTableDef *table, int col_num, void *bind_ptr, int *len_ptr)
@@ -200,7 +200,7 @@ mdb_xfer_bound_bool(MdbHandle *mdb, MdbColumn *col, int value)
col->cur_value_len = value;
if (col->bind_ptr) {
strcpy(col->bind_ptr,
value ? boolean_false_value : boolean_true_value);
value ? mdb->boolean_false_value : mdb->boolean_true_value);
}
if (col->len_ptr) {
*col->len_ptr = strlen(col->bind_ptr);
@@ -822,7 +822,7 @@ mdb_tm_to_date(struct tm *t, double *td)
{
short yr = t->tm_year + 1900;
char leap = ((yr & 3) == 0) && ((yr % 100) != 0 || (yr % 400) == 0);
int *cal = leap ? leap_cal : noleap_cal;
const int *cal = leap ? leap_cal : noleap_cal;
long int time = (yr*365+(yr/4)-(yr/100)+(yr/400)+cal[t->tm_mon]+t->tm_mday)-693959;
*td = (((long)t->tm_hour * 3600)+((long)t->tm_min * 60)+((long)t->tm_sec)) / 86400.0;
@@ -834,7 +834,7 @@ mdb_date_to_tm(double td, struct tm *t)
{
long int day, time;
int yr, q;
int *cal;
const int *cal;
day = (long int)(td);
time = (long int)(fabs(td - day) * 86400.0 + 0.5);
@@ -876,7 +876,7 @@ mdb_date_to_tm(double td, struct tm *t)
}
static char *
mdb_date_to_string(void *buf, int start)
mdb_date_to_string(MdbHandle *mdb, void *buf, int start)
{
struct tm t;
char *text = (char *) g_malloc(MDB_BIND_SIZE);
@@ -884,7 +884,7 @@ mdb_date_to_string(void *buf, int start)
mdb_date_to_tm(td, &t);
strftime(text, MDB_BIND_SIZE, date_fmt, &t);
strftime(text, MDB_BIND_SIZE, mdb->date_fmt, &t);
return text;
}
@@ -984,7 +984,7 @@ char *mdb_col_to_string(MdbHandle *mdb, void *buf, int start, int datatype, int
}
break;
case MDB_DATETIME:
text = mdb_date_to_string(buf, start);
text = mdb_date_to_string(mdb, buf, start);
break;
case MDB_MEMO:
text = mdb_memo_to_string(mdb, start, size);

View File

@@ -179,6 +179,8 @@ MdbHandle *mdb_open(const char *filename, MdbFileFlags flags)
mdb = (MdbHandle *) g_malloc0(sizeof(MdbHandle));
mdb_set_default_backend(mdb, "access");
mdb_set_date_fmt(mdb, "%x %X");
mdb_set_boolean_fmt_numbers(mdb);
#ifdef HAVE_ICONV
mdb->iconv_in = (iconv_t)-1;
mdb->iconv_out = (iconv_t)-1;

View File

@@ -159,17 +159,11 @@ main(int argc, char **argv)
if (insert_dialect)
header_row = 0;
if (date_fmt)
mdb_set_date_fmt(date_fmt);
if (null_text)
null_text = escapes(null_text);
else
null_text = g_strdup("");
if (boolean_words)
mdb_set_boolean_fmt_words();
if (str_bin_mode) {
if (!strcmp(str_bin_mode, "strip"))
bin_mode = MDB_BINEXPORT_STRIP;
@@ -189,6 +183,12 @@ main(int argc, char **argv)
exit(1);
}
if (date_fmt)
mdb_set_date_fmt(mdb, date_fmt);
if (boolean_words)
mdb_set_boolean_fmt_words(mdb);
if (insert_dialect)
if (!mdb_set_default_backend(mdb, insert_dialect)) {
fputs("Invalid backend type\n", stderr);