diff options
author | Bruce Momjian <bruce@momjian.us> | 2007-02-08 18:19:33 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 2007-02-08 18:19:33 +0000 |
commit | b577aa9ebc780c5095f213d36253f63580b2a067 (patch) | |
tree | ec39e6caab7d1e4fa72803eb22d27e3642d6f927 /src/backend/utils/adt/formatting.c | |
parent | a37b006d89b85c4b8ca92ee53580a1c3ea385be7 (diff) | |
download | postgresql-b577aa9ebc780c5095f213d36253f63580b2a067.tar.gz postgresql-b577aa9ebc780c5095f213d36253f63580b2a067.zip |
Fix bug when localized to_char() day or month names were incorectly
trnasformed to lower or upper string.
Pavel Stehule
Diffstat (limited to 'src/backend/utils/adt/formatting.c')
-rw-r--r-- | src/backend/utils/adt/formatting.c | 145 |
1 files changed, 129 insertions, 16 deletions
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c index cbc10964995..91ef1ea9dca 100644 --- a/src/backend/utils/adt/formatting.c +++ b/src/backend/utils/adt/formatting.c @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------- * formatting.c * - * $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.119 2007/02/08 03:22:28 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.120 2007/02/08 18:19:33 momjian Exp $ * * * Portions Copyright (c) 1999-2007, PostgreSQL Global Development Group @@ -82,6 +82,7 @@ #include "utils/int8.h" #include "utils/numeric.h" #include "utils/pg_locale.h" +#include "mb/pg_wchar.h" #define _(x) gettext((x)) @@ -113,6 +114,7 @@ #define MAXFLOATWIDTH 64 #define MAXDOUBLEWIDTH 128 + /* ---------- * External (defined in PgSQL datetime.c (timestamp utils)) * ---------- @@ -946,6 +948,20 @@ static char *localize_month(int index); static char *localize_day_full(int index); static char *localize_day(int index); +/* + * External (defined in oracle_compat.c + */ +#if defined(HAVE_WCSTOMBS) && defined(HAVE_TOWLOWER) +#define USE_WIDE_UPPER_LOWER +extern char *wstring_upper(char *str); +extern char *wstring_lower(char *str); +static char *localized_str_toupper(char *buff); +static char *localized_str_tolower(char *buff); +#else +#define localized_str_toupper str_toupper +#define localized_str_tolower str_tolower +#endif + /* ---------- * Fast sequential search, use index for data selection which * go to seq. cycle (it is very fast for unwanted strings) @@ -1500,6 +1516,7 @@ str_toupper(char *buff) *p_buff = pg_toupper((unsigned char) *p_buff); ++p_buff; } + return buff; } @@ -1523,6 +1540,61 @@ str_tolower(char *buff) return buff; } + +#ifdef USE_WIDE_UPPER_LOWER +/* ---------- + * Convert localized string to upper string. Input string is modified in place. + * ---------- + */ +static char * +localized_str_toupper(char *buff) +{ + if (!buff) + return NULL; + + if (pg_database_encoding_max_length() > 1 && !lc_ctype_is_c()) + return wstring_upper(buff); + else + { + char *p_buff = buff; + + while (*p_buff) + { + *p_buff = pg_toupper((unsigned char) *p_buff); + ++p_buff; + } + } + + return buff; +} + +/* ---------- + * Convert localized string to upper string. Input string is modified in place. + * ---------- + */ +static char * +localized_str_tolower(char *buff) +{ + if (!buff) + return NULL; + + if (pg_database_encoding_max_length() > 1 && !lc_ctype_is_c()) + return wstring_lower(buff); + else + { + char *p_buff = buff; + + while (*p_buff) + { + *p_buff = pg_tolower((unsigned char) *p_buff); + ++p_buff; + } + } + + return buff; +} +#endif /* USE_WIDE_UPPER_LOWER */ + /* ---------- * Sequential search with to upper/lower conversion * ---------- @@ -2182,10 +2254,15 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval, if (!tm->tm_mon) return -1; if (S_TM(suf)) + { strcpy(workbuff, localize_month_full(tm->tm_mon - 1)); + sprintf(inout, "%*s", 0, localized_str_toupper(workbuff)); + } else + { strcpy(workbuff, months_full[tm->tm_mon - 1]); - sprintf(inout, "%*s", (S_FM(suf) || S_TM(suf)) ? 0 : -9, str_toupper(workbuff)); + sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, str_toupper(workbuff)); + } return strlen(p_inout); case DCH_Month: @@ -2203,10 +2280,15 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval, if (!tm->tm_mon) return -1; if (S_TM(suf)) - sprintf(inout, "%*s", 0, localize_month_full(tm->tm_mon - 1)); + { + strcpy(workbuff, localize_month_full(tm->tm_mon - 1)); + sprintf(inout, "%*s", 0, localized_str_tolower(workbuff)); + } else + { sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, months_full[tm->tm_mon - 1]); - *inout = pg_tolower((unsigned char) *inout); + *inout = pg_tolower((unsigned char) *inout); + } return strlen(p_inout); case DCH_MON: @@ -2214,10 +2296,15 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval, if (!tm->tm_mon) return -1; if (S_TM(suf)) - strcpy(inout, localize_month(tm->tm_mon - 1)); + { + strcpy(workbuff, localize_month(tm->tm_mon - 1)); + strcpy(inout, localized_str_toupper(workbuff)); + } else + { strcpy(inout, months[tm->tm_mon - 1]); - str_toupper(inout); + str_toupper(inout); + } return strlen(p_inout); case DCH_Mon: @@ -2235,10 +2322,15 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval, if (!tm->tm_mon) return -1; if (S_TM(suf)) - strcpy(inout, localize_month(tm->tm_mon - 1)); + { + strcpy(workbuff, localize_month(tm->tm_mon - 1)); + strcpy(inout, localized_str_tolower(workbuff)); + } else + { strcpy(inout, months[tm->tm_mon - 1]); - *inout = pg_tolower((unsigned char) *inout); + *inout = pg_tolower((unsigned char) *inout); + } return strlen(p_inout); case DCH_MM: @@ -2266,16 +2358,21 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval, case DCH_DAY: INVALID_FOR_INTERVAL; if (S_TM(suf)) + { strcpy(workbuff, localize_day_full(tm->tm_wday)); + sprintf(inout, "%*s", 0, localized_str_toupper(workbuff)); + } else + { strcpy(workbuff, days[tm->tm_wday]); - sprintf(inout, "%*s", (S_FM(suf) || S_TM(suf)) ? 0 : -9, str_toupper(workbuff)); + sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, str_toupper(workbuff)); + } return strlen(p_inout); case DCH_Day: INVALID_FOR_INTERVAL; if (S_TM(suf)) - sprintf(inout, "%*s", 0, localize_day_full(tm->tm_wday)); + sprintf(inout, "%*s", 0, localize_day_full(tm->tm_wday)); else sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, days[tm->tm_wday]); return strlen(p_inout); @@ -2283,19 +2380,30 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval, case DCH_day: INVALID_FOR_INTERVAL; if (S_TM(suf)) - sprintf(inout, "%*s", 0, localize_day_full(tm->tm_wday)); + { + strcpy(workbuff, localize_day_full(tm->tm_wday)); + sprintf(inout, "%*s", 0, localized_str_tolower(workbuff)); + } else + { sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, days[tm->tm_wday]); - *inout = pg_tolower((unsigned char) *inout); + *inout = pg_tolower((unsigned char) *inout); + } return strlen(p_inout); case DCH_DY: INVALID_FOR_INTERVAL; if (S_TM(suf)) - strcpy(inout, localize_day(tm->tm_wday)); + { + strcpy(workbuff, localize_day(tm->tm_wday)); + strcpy(inout, localized_str_toupper(workbuff)); + } else + { strcpy(inout, days_short[tm->tm_wday]); - str_toupper(inout); + str_toupper(inout); + } + return strlen(p_inout); case DCH_Dy: @@ -2309,10 +2417,15 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval, case DCH_dy: INVALID_FOR_INTERVAL; if (S_TM(suf)) - strcpy(inout, localize_day(tm->tm_wday)); + { + strcpy(workbuff, localize_day(tm->tm_wday)); + strcpy(inout, localized_str_tolower(workbuff)); + } else + { strcpy(inout, days_short[tm->tm_wday]); - *inout = pg_tolower((unsigned char) *inout); + *inout = pg_tolower((unsigned char) *inout); + } return strlen(p_inout); case DCH_DDD: |