11/* -----------------------------------------------------------------------
22 * formatting.c
33 *
4- * $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.119 2007/02/0803:22:28 momjian Exp $
4+ * $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.120 2007/02/0818:19:33 momjian Exp $
55 *
66 *
77 * Portions Copyright (c) 1999-2007, PostgreSQL Global Development Group
8282#include "utils/int8.h"
8383#include "utils/numeric.h"
8484#include "utils/pg_locale.h"
85+ #include "mb/pg_wchar.h"
8586
8687#define _ (x )gettext((x))
8788
113114#define MAXFLOATWIDTH 64
114115#define MAXDOUBLEWIDTH 128
115116
117+
116118/* ----------
117119 * External (defined in PgSQL datetime.c (timestamp utils))
118120 * ----------
@@ -946,6 +948,20 @@ static char *localize_month(int index);
946948static char * localize_day_full (int index );
947949static char * localize_day (int index );
948950
951+ /*
952+ * External (defined in oracle_compat.c
953+ */
954+ #if defined(HAVE_WCSTOMBS )&& defined(HAVE_TOWLOWER )
955+ #define USE_WIDE_UPPER_LOWER
956+ extern char * wstring_upper (char * str );
957+ extern char * wstring_lower (char * str );
958+ static char * localized_str_toupper (char * buff );
959+ static char * localized_str_tolower (char * buff );
960+ #else
961+ #define localized_str_toupper str_toupper
962+ #define localized_str_tolower str_tolower
963+ #endif
964+
949965/* ----------
950966 * Fast sequential search, use index for data selection which
951967 * go to seq. cycle (it is very fast for unwanted strings)
@@ -1500,6 +1516,7 @@ str_toupper(char *buff)
15001516* p_buff = pg_toupper ((unsignedchar )* p_buff );
15011517++ p_buff ;
15021518}
1519+
15031520return buff ;
15041521}
15051522
@@ -1523,6 +1540,61 @@ str_tolower(char *buff)
15231540return buff ;
15241541}
15251542
1543+
1544+ #ifdef USE_WIDE_UPPER_LOWER
1545+ /* ----------
1546+ * Convert localized string to upper string. Input string is modified in place.
1547+ * ----------
1548+ */
1549+ static char *
1550+ localized_str_toupper (char * buff )
1551+ {
1552+ if (!buff )
1553+ return NULL ;
1554+
1555+ if (pg_database_encoding_max_length ()> 1 && !lc_ctype_is_c ())
1556+ return wstring_upper (buff );
1557+ else
1558+ {
1559+ char * p_buff = buff ;
1560+
1561+ while (* p_buff )
1562+ {
1563+ * p_buff = pg_toupper ((unsignedchar )* p_buff );
1564+ ++ p_buff ;
1565+ }
1566+ }
1567+
1568+ return buff ;
1569+ }
1570+
1571+ /* ----------
1572+ * Convert localized string to upper string. Input string is modified in place.
1573+ * ----------
1574+ */
1575+ static char *
1576+ localized_str_tolower (char * buff )
1577+ {
1578+ if (!buff )
1579+ return NULL ;
1580+
1581+ if (pg_database_encoding_max_length ()> 1 && !lc_ctype_is_c ())
1582+ return wstring_lower (buff );
1583+ else
1584+ {
1585+ char * p_buff = buff ;
1586+
1587+ while (* p_buff )
1588+ {
1589+ * p_buff = pg_tolower ((unsignedchar )* p_buff );
1590+ ++ p_buff ;
1591+ }
1592+ }
1593+
1594+ return buff ;
1595+ }
1596+ #endif /* USE_WIDE_UPPER_LOWER */
1597+
15261598/* ----------
15271599 * Sequential search with to upper/lower conversion
15281600 * ----------
@@ -2182,10 +2254,15 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
21822254if (!tm -> tm_mon )
21832255return -1 ;
21842256if (S_TM (suf ))
2257+ {
21852258strcpy (workbuff ,localize_month_full (tm -> tm_mon - 1 ));
2259+ sprintf (inout ,"%*s" ,0 ,localized_str_toupper (workbuff ));
2260+ }
21862261else
2262+ {
21872263strcpy (workbuff ,months_full [tm -> tm_mon - 1 ]);
2188- sprintf (inout ,"%*s" , (S_FM (suf )|| S_TM (suf )) ?0 :-9 ,str_toupper (workbuff ));
2264+ sprintf (inout ,"%*s" ,S_FM (suf ) ?0 :-9 ,str_toupper (workbuff ));
2265+ }
21892266return strlen (p_inout );
21902267
21912268case DCH_Month :
@@ -2203,21 +2280,31 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
22032280if (!tm -> tm_mon )
22042281return -1 ;
22052282if (S_TM (suf ))
2206- sprintf (inout ,"%*s" ,0 ,localize_month_full (tm -> tm_mon - 1 ));
2283+ {
2284+ strcpy (workbuff ,localize_month_full (tm -> tm_mon - 1 ));
2285+ sprintf (inout ,"%*s" ,0 ,localized_str_tolower (workbuff ));
2286+ }
22072287else
2288+ {
22082289sprintf (inout ,"%*s" ,S_FM (suf ) ?0 :-9 ,months_full [tm -> tm_mon - 1 ]);
2209- * inout = pg_tolower ((unsignedchar )* inout );
2290+ * inout = pg_tolower ((unsignedchar )* inout );
2291+ }
22102292return strlen (p_inout );
22112293
22122294case DCH_MON :
22132295INVALID_FOR_INTERVAL ;
22142296if (!tm -> tm_mon )
22152297return -1 ;
22162298if (S_TM (suf ))
2217- strcpy (inout ,localize_month (tm -> tm_mon - 1 ));
2299+ {
2300+ strcpy (workbuff ,localize_month (tm -> tm_mon - 1 ));
2301+ strcpy (inout ,localized_str_toupper (workbuff ));
2302+ }
22182303else
2304+ {
22192305strcpy (inout ,months [tm -> tm_mon - 1 ]);
2220- str_toupper (inout );
2306+ str_toupper (inout );
2307+ }
22212308return strlen (p_inout );
22222309
22232310case DCH_Mon :
@@ -2235,10 +2322,15 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
22352322if (!tm -> tm_mon )
22362323return -1 ;
22372324if (S_TM (suf ))
2238- strcpy (inout ,localize_month (tm -> tm_mon - 1 ));
2325+ {
2326+ strcpy (workbuff ,localize_month (tm -> tm_mon - 1 ));
2327+ strcpy (inout ,localized_str_tolower (workbuff ));
2328+ }
22392329else
2330+ {
22402331strcpy (inout ,months [tm -> tm_mon - 1 ]);
2241- * inout = pg_tolower ((unsignedchar )* inout );
2332+ * inout = pg_tolower ((unsignedchar )* inout );
2333+ }
22422334return strlen (p_inout );
22432335
22442336case DCH_MM :
@@ -2266,36 +2358,52 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
22662358case DCH_DAY :
22672359INVALID_FOR_INTERVAL ;
22682360if (S_TM (suf ))
2361+ {
22692362strcpy (workbuff ,localize_day_full (tm -> tm_wday ));
2363+ sprintf (inout ,"%*s" ,0 ,localized_str_toupper (workbuff ));
2364+ }
22702365else
2366+ {
22712367strcpy (workbuff ,days [tm -> tm_wday ]);
2272- sprintf (inout ,"%*s" , (S_FM (suf )|| S_TM (suf )) ?0 :-9 ,str_toupper (workbuff ));
2368+ sprintf (inout ,"%*s" ,S_FM (suf ) ?0 :-9 ,str_toupper (workbuff ));
2369+ }
22732370return strlen (p_inout );
22742371
22752372case DCH_Day :
22762373INVALID_FOR_INTERVAL ;
22772374if (S_TM (suf ))
2278- sprintf (inout ,"%*s" ,0 ,localize_day_full (tm -> tm_wday ));
2375+ sprintf (inout ,"%*s" ,0 ,localize_day_full (tm -> tm_wday ));
22792376else
22802377sprintf (inout ,"%*s" ,S_FM (suf ) ?0 :-9 ,days [tm -> tm_wday ]);
22812378return strlen (p_inout );
22822379
22832380case DCH_day :
22842381INVALID_FOR_INTERVAL ;
22852382if (S_TM (suf ))
2286- sprintf (inout ,"%*s" ,0 ,localize_day_full (tm -> tm_wday ));
2383+ {
2384+ strcpy (workbuff ,localize_day_full (tm -> tm_wday ));
2385+ sprintf (inout ,"%*s" ,0 ,localized_str_tolower (workbuff ));
2386+ }
22872387else
2388+ {
22882389sprintf (inout ,"%*s" ,S_FM (suf ) ?0 :-9 ,days [tm -> tm_wday ]);
2289- * inout = pg_tolower ((unsignedchar )* inout );
2390+ * inout = pg_tolower ((unsignedchar )* inout );
2391+ }
22902392return strlen (p_inout );
22912393
22922394case DCH_DY :
22932395INVALID_FOR_INTERVAL ;
22942396if (S_TM (suf ))
2295- strcpy (inout ,localize_day (tm -> tm_wday ));
2397+ {
2398+ strcpy (workbuff ,localize_day (tm -> tm_wday ));
2399+ strcpy (inout ,localized_str_toupper (workbuff ));
2400+ }
22962401else
2402+ {
22972403strcpy (inout ,days_short [tm -> tm_wday ]);
2298- str_toupper (inout );
2404+ str_toupper (inout );
2405+ }
2406+
22992407return strlen (p_inout );
23002408
23012409case DCH_Dy :
@@ -2309,10 +2417,15 @@ dch_date(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
23092417case DCH_dy :
23102418INVALID_FOR_INTERVAL ;
23112419if (S_TM (suf ))
2312- strcpy (inout ,localize_day (tm -> tm_wday ));
2420+ {
2421+ strcpy (workbuff ,localize_day (tm -> tm_wday ));
2422+ strcpy (inout ,localized_str_tolower (workbuff ));
2423+ }
23132424else
2425+ {
23142426strcpy (inout ,days_short [tm -> tm_wday ]);
2315- * inout = pg_tolower ((unsignedchar )* inout );
2427+ * inout = pg_tolower ((unsignedchar )* inout );
2428+ }
23162429return strlen (p_inout );
23172430
23182431case DCH_DDD :