Hello,
I am sorry for preview chotic mails. My web email client is stupid (I am
too).
This patch correct bug, when localized day or month names was incorectly
trnasformed to lower or upper string.
Regards
Pavel Stehule
_________________________________________________________________
Najdete si svou lasku a nove pratele na Match.com. http://www.msn.cz/
*** ./adt/formatting.c.orig 2007-02-04 13:09:09.000000000 +0100
--- ./adt/formatting.c 2007-02-04 15:58:52.000000000 +0100
***************
*** 82,87 ****
--- 82,88 ----
#include "utils/int8.h"
#include "utils/numeric.h"
#include "utils/pg_locale.h"
+ #include "mb/pg_wchar.h"
#define _(x) gettext((x))
***************
*** 113,118 ****
--- 114,128 ----
#define MAXFLOATWIDTH 64
#define MAXDOUBLEWIDTH 128
+ /*
+ * External (defined in oracle_compat.c
+ */
+ #if defined(HAVE_WCSTOMBS) && defined(HAVE_TOWLOWER)
+ #define USE_WIDE_UPPER_LOWER
+ extern int upper_str(char *str);
+ extern int lower_str(char *str);
+ #endif
+
/* ----------
* External (defined in PgSQL datetime.c (timestamp utils))
* ----------
***************
*** 946,951 ****
--- 956,970 ----
static char *localize_day_full(int index);
static char *localize_day(int index);
+ #ifdef USE_WIDE_UPPER_LOWER
+ 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 /* USE_WIDE_UPPER_LOWER */
+
+
/* ----------
* Fast sequential search, use index for data selection which
* go to seq. cycle (it is very fast for unwanted strings)
***************
*** 1500,1505 ****
--- 1519,1525 ----
*p_buff = pg_toupper((unsigned char) *p_buff);
++p_buff;
}
+
return buff;
}
***************
*** 1523,1528 ****
--- 1543,1603 ----
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())
+ upper_str(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())
+ lower_str(buff);
+ else
+ {
+ char *p_buff = buff;
+
+ while (*p_buff)
+ {
+ *p_buff = pg_toupper((unsigned char) *p_buff);
+ ++p_buff;
+ }
+ }
+
+ return buff;
+ }
+ #endif /* USE_WIDE_UPPER_LOWER */
+
/* ----------
* Sequential search with to upper/lower conversion
* ----------
***************
*** 2188,2197 ****
if (!tm->tm_mon)
return -1;
if (S_TM(suf))
strcpy(workbuff, localize_month_full(tm->tm_mon - 1));
else
strcpy(workbuff, months_full[tm->tm_mon - 1]);
! sprintf(inout, "%*s", (S_FM(suf) || S_TM(suf)) ? 0 : -9, str_toupper(workbuff));
return strlen(p_inout);
case DCH_Month:
--- 2263,2278 ----
if (!tm->tm_mon)
return -1;
if (S_TM(suf))
+ {
strcpy(workbuff, localize_month_full(tm->tm_mon - 1));
+ localized_str_toupper(workbuff);
+ }
else
+ {
strcpy(workbuff, months_full[tm->tm_mon - 1]);
! str_toupper(workbuff);
! }
! sprintf(inout, "%*s", (S_FM(suf) || S_TM(suf)) ? 0 : -9, workbuff);
return strlen(p_inout);
case DCH_Month:
***************
*** 2209,2218 ****
if (!tm->tm_mon)
return -1;
if (S_TM(suf))
! sprintf(inout, "%*s", 0, localize_month_full(tm->tm_mon - 1));
else
sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, months_full[tm->tm_mon - 1]);
! *inout = pg_tolower((unsigned char) *inout);
return strlen(p_inout);
case DCH_MON:
--- 2290,2305 ----
if (!tm->tm_mon)
return -1;
if (S_TM(suf))
! {
! strcpy(workbuff, localize_month_full(tm->tm_mon - 1));
! localized_str_tolower(workbuff);
! sprintf(inout, "%*s", 0, workbuff);
! }
else
+ {
sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, months_full[tm->tm_mon - 1]);
! *inout = pg_tolower((unsigned char) *inout);
! }
return strlen(p_inout);
case DCH_MON:
***************
*** 2220,2229 ****
if (!tm->tm_mon)
return -1;
if (S_TM(suf))
strcpy(inout, localize_month(tm->tm_mon - 1));
else
strcpy(inout, months[tm->tm_mon - 1]);
! str_toupper(inout);
return strlen(p_inout);
case DCH_Mon:
--- 2307,2321 ----
if (!tm->tm_mon)
return -1;
if (S_TM(suf))
+ {
strcpy(inout, localize_month(tm->tm_mon - 1));
+ localized_str_toupper(inout);
+ }
else
+ {
strcpy(inout, months[tm->tm_mon - 1]);
! str_toupper(inout);
! }
return strlen(p_inout);
case DCH_Mon:
***************
*** 2241,2250 ****
if (!tm->tm_mon)
return -1;
if (S_TM(suf))
strcpy(inout, localize_month(tm->tm_mon - 1));
else
strcpy(inout, months[tm->tm_mon - 1]);
! *inout = pg_tolower((unsigned char) *inout);
return strlen(p_inout);
case DCH_MM:
--- 2333,2347 ----
if (!tm->tm_mon)
return -1;
if (S_TM(suf))
+ {
strcpy(inout, localize_month(tm->tm_mon - 1));
+ localized_str_tolower(inout);
+ }
else
+ {
strcpy(inout, months[tm->tm_mon - 1]);
! *inout = pg_tolower((unsigned char) *inout);
! }
return strlen(p_inout);
case DCH_MM:
***************
*** 2272,2287 ****
case DCH_DAY:
INVALID_FOR_INTERVAL;
if (S_TM(suf))
strcpy(workbuff, localize_day_full(tm->tm_wday));
else
strcpy(workbuff, days[tm->tm_wday]);
! sprintf(inout, "%*s", (S_FM(suf) || S_TM(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));
else
sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, days[tm->tm_wday]);
return strlen(p_inout);
--- 2369,2390 ----
case DCH_DAY:
INVALID_FOR_INTERVAL;
if (S_TM(suf))
+ {
strcpy(workbuff, localize_day_full(tm->tm_wday));
+ localized_str_toupper(workbuff);
+ }
else
+ {
strcpy(workbuff, days[tm->tm_wday]);
! str_toupper(workbuff);
! }
! sprintf(inout, "%*s", (S_FM(suf) || S_TM(suf)) ? 0 : -9, 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));
else
sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, days[tm->tm_wday]);
return strlen(p_inout);
***************
*** 2289,2307 ****
case DCH_day:
INVALID_FOR_INTERVAL;
if (S_TM(suf))
! sprintf(inout, "%*s", 0, localize_day_full(tm->tm_wday));
else
sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, days[tm->tm_wday]);
! *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));
else
strcpy(inout, days_short[tm->tm_wday]);
! str_toupper(inout);
return strlen(p_inout);
case DCH_Dy:
--- 2392,2423 ----
case DCH_day:
INVALID_FOR_INTERVAL;
if (S_TM(suf))
! {
! strcpy(workbuff, localize_day_full(tm->tm_wday));
! localized_str_tolower(workbuff);
! sprintf(inout, "%*s", 0, workbuff);
!
! }
else
+ {
sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, days[tm->tm_wday]);
! *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));
+ localized_str_toupper(inout);
+ }
else
+ {
strcpy(inout, days_short[tm->tm_wday]);
! str_toupper(inout);
! }
!
return strlen(p_inout);
case DCH_Dy:
***************
*** 2315,2324 ****
case DCH_dy:
INVALID_FOR_INTERVAL;
if (S_TM(suf))
strcpy(inout, localize_day(tm->tm_wday));
else
strcpy(inout, days_short[tm->tm_wday]);
! *inout = pg_tolower((unsigned char) *inout);
return strlen(p_inout);
case DCH_DDD:
--- 2431,2446 ----
case DCH_dy:
INVALID_FOR_INTERVAL;
if (S_TM(suf))
+ {
strcpy(inout, localize_day(tm->tm_wday));
+ localized_str_tolower(inout);
+
+ }
else
+ {
strcpy(inout, days_short[tm->tm_wday]);
! *inout = pg_tolower((unsigned char) *inout);
! }
return strlen(p_inout);
case DCH_DDD:
*** ./adt/oracle_compat.c.orig 2007-02-04 12:35:14.000000000 +0100
--- ./adt/oracle_compat.c 2007-02-04 16:06:18.000000000 +0100
***************
*** 46,51 ****
--- 46,53 ----
*/
#if defined(HAVE_WCSTOMBS) && defined(HAVE_TOWLOWER)
#define USE_WIDE_UPPER_LOWER
+ int upper_str(char *str);
+ int lower_str(char *str);
#endif
static text *dotrim(const char *string, int stringlen,
***************
*** 258,263 ****
--- 260,333 ----
#define wcstotext win32_wcstotext
#endif /* WIN32 */
+ #ifdef USE_WIDE_UPPER_LOWER
+ /*
+ * upper_text is used for correct multibyte upper function str_toupper.
+ * Expected safety long buffer (used only for internal purpouse).
+ * Returns length of converted string. lower_str is similar.
+ */
+ int
+ upper_str(char *str)
+ {
+ wchar_t *workspace;
+ text *txt;
+ text *result;
+ int nbytes = strlen(str);
+ int i;
+
+ txt = palloc(nbytes + VARHDRSZ);
+ memcpy(VARDATA(txt), str, nbytes);
+ VARATT_SIZEP(txt) = nbytes + VARHDRSZ;
+
+ workspace = texttowcs(txt);
+
+ for (i = 0; workspace[i] != 0; i++)
+ workspace[i] = towupper(workspace[i]);
+
+ result = wcstotext(workspace, i);
+
+ /* copy back result */
+ nbytes = VARSIZE(result) - VARHDRSZ;
+ memcpy(str, VARDATA(result), nbytes);
+ str[nbytes] = '\0';
+
+ pfree(workspace);
+ pfree(result);
+
+ return nbytes;
+ }
+
+ int
+ lower_str(char *str)
+ {
+ wchar_t *workspace;
+ text *txt;
+ text *result;
+ int nbytes = strlen(str);
+ int i;
+
+ txt = palloc(nbytes + VARHDRSZ);
+ memcpy(VARDATA(txt), str, nbytes);
+ VARATT_SIZEP(txt) = nbytes + VARHDRSZ;
+
+ workspace = texttowcs(txt);
+
+ for (i = 0; workspace[i] != 0; i++)
+ workspace[i] = towlower(workspace[i]);
+
+ result = wcstotext(workspace, i);
+
+ /* copy back result */
+ nbytes = VARSIZE(result) - VARHDRSZ;
+ memcpy(str, VARDATA(result), nbytes);
+ str[nbytes] = '\0';
+
+ pfree(workspace);
+ pfree(result);
+
+ return nbytes;
+ }
+ #endif /* USE_WIDE_UPPER_LOWER */
/********************************************************************
*
---------------------------(end of broadcast)---------------------------
TIP 6: explain analyze is your friend