44 *
55 * Portions Copyright (c) 2002-2009, PostgreSQL Global Development Group
66 *
7- * $PostgreSQL: pgsql/src/backend/utils/adt/pg_locale.c,v 1.43 2009/01/01 17:23:49 momjian Exp $
7+ * $PostgreSQL: pgsql/src/backend/utils/adt/pg_locale.c,v 1.44 2009/01/09 13:03:55 mha Exp $
88 *
99 *-----------------------------------------------------------------------
1010 */
5151#include <time.h>
5252
5353#include "catalog/pg_control.h"
54+ #include "mb/pg_wchar.h"
5455#include "utils/memutils.h"
5556#include "utils/pg_locale.h"
5657
@@ -452,6 +453,57 @@ PGLC_localeconv(void)
452453 return & CurrentLocaleConv ;
453454}
454455
456+ #ifdef WIN32
457+ /*
458+ * On win32, strftime() returns the encoding in CP_ACP, which is likely
459+ * different from SERVER_ENCODING. This is especially important in Japanese
460+ * versions of Windows which will use SJIS encoding, which we don't support
461+ * as a server encoding.
462+ *
463+ * Replace strftime() with a version that gets the string in UTF16 and then
464+ * converts it to the appropriate encoding as necessary.
465+ *
466+ * Note that this only affects the calls to strftime() in this file, which are
467+ * used to get the locale-aware strings. Other parts of the backend use
468+ * pg_strftime(), which isn't locale-aware and does not need to be replaced.
469+ */
470+ static size_t
471+ strftime_win32 (char * dst , size_t dstlen , const wchar_t * format , const struct tm * tm )
472+ {
473+ size_t len ;
474+ wchar_t wbuf [MAX_L10N_DATA ];
475+ int encoding ;
476+
477+ encoding = GetDatabaseEncoding ();
478+
479+ len = wcsftime (wbuf , sizeof (wbuf ), format , tm );
480+ if (len == 0 )
481+ /* strftime call failed - return 0 with the contents of dst unspecified */
482+ return 0 ;
483+
484+ len = WideCharToMultiByte (CP_UTF8 , 0 , wbuf , len , dst , dstlen , NULL , NULL );
485+ if (len == 0 )
486+ elog (ERROR ,
487+ "could not convert string to UTF-8:error %lu" , GetLastError ());
488+
489+ dst [len ] = '\0' ;
490+ if (encoding != PG_UTF8 )
491+ {
492+ char * convstr = pg_do_encoding_conversion (dst , len , PG_UTF8 , encoding );
493+ if (dst != convstr )
494+ {
495+ StrNCpy (dst , convstr , dstlen );
496+ len = strlen (dst );
497+ }
498+ }
499+
500+ return len ;
501+ }
502+
503+ #define strftime (a ,b ,c ,d ) strftime_win32(a,b,L##c,d)
504+
505+ #endif /* WIN32 */
506+
455507
456508/*
457509 * Update the lc_time localization cache variables if needed.
@@ -465,13 +517,25 @@ cache_locale_time(void)
465517 char buf [MAX_L10N_DATA ];
466518 char * ptr ;
467519 int i ;
520+ #ifdef WIN32
521+ char * save_lc_ctype ;
522+ #endif
468523
469524 /* did we do this already? */
470525 if (CurrentLCTimeValid )
471526 return ;
472527
473528 elog (DEBUG3 , "cache_locale_time() executed; locale: \"%s\"" , locale_time );
474529
530+ #ifdef WIN32
531+ /* set user's value of ctype locale */
532+ save_lc_ctype = setlocale (LC_CTYPE , NULL );
533+ if (save_lc_ctype )
534+ save_lc_ctype = pstrdup (save_lc_ctype );
535+
536+ setlocale (LC_CTYPE , locale_time );
537+ #endif
538+
475539 /* set user's value of time locale */
476540 save_lc_time = setlocale (LC_TIME , NULL );
477541 if (save_lc_time )
@@ -524,5 +588,14 @@ cache_locale_time(void)
524588 pfree (save_lc_time );
525589 }
526590
591+ #ifdef WIN32
592+ /* try to restore internal ctype settings */
593+ if (save_lc_ctype )
594+ {
595+ setlocale (LC_CTYPE , save_lc_ctype );
596+ pfree (save_lc_ctype );
597+ }
598+ #endif
599+
527600 CurrentLCTimeValid = true;
528601}
0 commit comments