aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/include/pg_config.h.in6
-rw-r--r--src/include/pg_config.h.win326
-rw-r--r--src/interfaces/ecpg/ecpglib/descriptor.c37
-rw-r--r--src/interfaces/ecpg/ecpglib/execute.c42
-rw-r--r--src/interfaces/ecpg/ecpglib/extern.h11
5 files changed, 94 insertions, 8 deletions
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index a7c1874c226..3c82718bf99 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -644,6 +644,9 @@
/* Define to 1 if the system has the type `unsigned long long int'. */
#undef HAVE_UNSIGNED_LONG_LONG_INT
+/* Define to 1 if you have the `uselocale' function. */
+#undef HAVE_USELOCALE
+
/* Define to 1 if you have the `utime' function. */
#undef HAVE_UTIME
@@ -701,6 +704,9 @@
/* Define to 1 if your compiler understands __builtin_unreachable. */
#undef HAVE__BUILTIN_UNREACHABLE
+/* Define to 1 if you have the `_configthreadlocale' function. */
+#undef HAVE__CONFIGTHREADLOCALE
+
/* Define to 1 if you have __cpuid. */
#undef HAVE__CPUID
diff --git a/src/include/pg_config.h.win32 b/src/include/pg_config.h.win32
index a86261f5bbf..9c2d98f12fc 100644
--- a/src/include/pg_config.h.win32
+++ b/src/include/pg_config.h.win32
@@ -494,6 +494,9 @@
/* Define to 1 if you have the `unsetenv' function. */
/* #undef HAVE_UNSETENV */
+/* Define to 1 if you have the `uselocale' function. */
+/* #undef HAVE_USELOCALE */
+
/* Define to 1 if you have the `utime' function. */
#define HAVE_UTIME 1
@@ -536,6 +539,9 @@
/* Define to 1 if your compiler understands __builtin_unreachable. */
/* #undef HAVE__BUILTIN_UNREACHABLE */
+/* Define to 1 if you have the `_configthreadlocale' function. */
+#define HAVE__CONFIGTHREADLOCALE 1
+
/* Define to 1 if you have __cpuid. */
#define HAVE__CPUID 1
diff --git a/src/interfaces/ecpg/ecpglib/descriptor.c b/src/interfaces/ecpg/ecpglib/descriptor.c
index 72b0646aa6b..cf8657e9c00 100644
--- a/src/interfaces/ecpg/ecpglib/descriptor.c
+++ b/src/interfaces/ecpg/ecpglib/descriptor.c
@@ -482,22 +482,45 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...)
if (data_var.type != ECPGt_EORT)
{
struct statement stmt;
- char *oldlocale;
+
+ memset(&stmt, 0, sizeof stmt);
+ stmt.lineno = lineno;
/* Make sure we do NOT honor the locale for numeric input */
/* since the database gives the standard decimal point */
- oldlocale = ecpg_strdup(setlocale(LC_NUMERIC, NULL), lineno);
+ /* (see comments in execute.c) */
+#ifdef HAVE_USELOCALE
+ stmt.clocale = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
+ if (stmt.clocale != (locale_t) 0)
+ stmt.oldlocale = uselocale(stmt.clocale);
+#else
+#ifdef HAVE__CONFIGTHREADLOCALE
+ stmt.oldthreadlocale = _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
+#endif
+ stmt.oldlocale = ecpg_strdup(setlocale(LC_NUMERIC, NULL), lineno);
setlocale(LC_NUMERIC, "C");
-
- memset(&stmt, 0, sizeof stmt);
- stmt.lineno = lineno;
+#endif
/* desperate try to guess something sensible */
stmt.connection = ecpg_get_connection(NULL);
ecpg_store_result(ECPGresult, index, &stmt, &data_var);
- setlocale(LC_NUMERIC, oldlocale);
- ecpg_free(oldlocale);
+#ifdef HAVE_USELOCALE
+ if (stmt.oldlocale != (locale_t) 0)
+ uselocale(stmt.oldlocale);
+ if (stmt.clocale)
+ freelocale(stmt.clocale);
+#else
+ if (stmt.oldlocale)
+ {
+ setlocale(LC_NUMERIC, stmt.oldlocale);
+ ecpg_free(stmt.oldlocale);
+ }
+#ifdef HAVE__CONFIGTHREADLOCALE
+ if (stmt.oldthreadlocale != -1)
+ _configthreadlocale(stmt.oldthreadlocale);
+#endif
+#endif
}
else if (data_var.ind_type != ECPGt_NO_INDICATOR && data_var.ind_pointer != NULL)
diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c
index 6f20cc412a2..adc4470d9a2 100644
--- a/src/interfaces/ecpg/ecpglib/execute.c
+++ b/src/interfaces/ecpg/ecpglib/execute.c
@@ -103,7 +103,12 @@ free_statement(struct statement *stmt)
free_variable(stmt->outlist);
ecpg_free(stmt->command);
ecpg_free(stmt->name);
+#ifdef HAVE_USELOCALE
+ if (stmt->clocale)
+ freelocale(stmt->clocale);
+#else
ecpg_free(stmt->oldlocale);
+#endif
ecpg_free(stmt);
}
@@ -1778,8 +1783,32 @@ ecpg_do_prologue(int lineno, const int compat, const int force_indicator,
/*
* Make sure we do NOT honor the locale for numeric input/output since the
- * database wants the standard decimal point
+ * database wants the standard decimal point. If available, use
+ * uselocale() for this because it's thread-safe. Windows doesn't have
+ * that, but it usually does have _configthreadlocale().
*/
+#ifdef HAVE_USELOCALE
+ stmt->clocale = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
+ if (stmt->clocale == (locale_t) 0)
+ {
+ ecpg_do_epilogue(stmt);
+ return false;
+ }
+ stmt->oldlocale = uselocale(stmt->clocale);
+ if (stmt->oldlocale == (locale_t) 0)
+ {
+ ecpg_do_epilogue(stmt);
+ return false;
+ }
+#else
+#ifdef HAVE__CONFIGTHREADLOCALE
+ stmt->oldthreadlocale = _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
+ if (stmt->oldthreadlocale == -1)
+ {
+ ecpg_do_epilogue(stmt);
+ return false;
+ }
+#endif
stmt->oldlocale = ecpg_strdup(setlocale(LC_NUMERIC, NULL), lineno);
if (stmt->oldlocale == NULL)
{
@@ -1787,6 +1816,7 @@ ecpg_do_prologue(int lineno, const int compat, const int force_indicator,
return false;
}
setlocale(LC_NUMERIC, "C");
+#endif
#ifdef ENABLE_THREAD_SAFETY
ecpg_pthreads_init();
@@ -1989,8 +2019,18 @@ ecpg_do_epilogue(struct statement *stmt)
if (stmt == NULL)
return;
+#ifdef HAVE_USELOCALE
+ if (stmt->oldlocale != (locale_t) 0)
+ uselocale(stmt->oldlocale);
+#else
if (stmt->oldlocale)
+ {
setlocale(LC_NUMERIC, stmt->oldlocale);
+#ifdef HAVE__CONFIGTHREADLOCALE
+ _configthreadlocale(stmt->oldthreadlocale);
+#endif
+ }
+#endif
free_statement(stmt);
}
diff --git a/src/interfaces/ecpg/ecpglib/extern.h b/src/interfaces/ecpg/ecpglib/extern.h
index 91c7367b8b0..4a524392046 100644
--- a/src/interfaces/ecpg/ecpglib/extern.h
+++ b/src/interfaces/ecpg/ecpglib/extern.h
@@ -12,6 +12,9 @@
#ifndef CHAR_BIT
#include <limits.h>
#endif
+#ifdef LOCALE_T_IN_XLOCALE
+#include <xlocale.h>
+#endif
enum COMPAT_MODE
{
@@ -60,7 +63,15 @@ struct statement
bool questionmarks;
struct variable *inlist;
struct variable *outlist;
+#ifdef HAVE_USELOCALE
+ locale_t clocale;
+ locale_t oldlocale;
+#else
char *oldlocale;
+#ifdef HAVE__CONFIGTHREADLOCALE
+ int oldthreadlocale;
+#endif
+#endif
int nparams;
char **paramvalues;
PGresult *results;