Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite3269ca

Browse files
committed
Make PGLC_setlocale() static, and document that it can't be used safely
for any other purpose than PGLC_localeconv()'s internal save/restore oflocale settings. Fix cash.c to call PGLC_localeconv() rather thanmaking a direct call to localeconv() --- the old way, if PGLC_localeconv()had already cached a locale result, it would be overwritten by the firstcash_in or cash_out operation, leading to wrong-locale results later.Probably no demonstrable bug today, since we only appear to be lookingat the LC_MONETARY results which should be the same anyway, but definitelya gotcha waiting to strike.
1 parent74dc04a commite3269ca

File tree

3 files changed

+64
-53
lines changed

3 files changed

+64
-53
lines changed

‎src/backend/utils/adt/cash.c

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,23 @@
99
* workings can be found in the book "Software Solutions in C" by
1010
* Dale Schumacher, Academic Press, ISBN: 0-12-632360-7.
1111
*
12-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/cash.c,v 1.47 2000/11/2520:33:52 tgl Exp $
12+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/cash.c,v 1.48 2000/11/2522:43:08 tgl Exp $
1313
*/
1414

15+
#include"postgres.h"
16+
1517
#include<limits.h>
1618
#include<ctype.h>
1719
#include<math.h>
20+
#ifdefUSE_LOCALE
1821
#include<locale.h>
22+
#endif
1923

20-
#include"postgres.h"
2124
#include"miscadmin.h"
2225
#include"utils/builtins.h"
2326
#include"utils/cash.h"
27+
#include"utils/pg_locale.h"
28+
2429

2530
staticconstchar*num_word(Cashvalue);
2631

@@ -31,11 +36,6 @@ static const char *num_word(Cash value);
3136
#defineLAST_PAREN(TERMINATOR - 1)
3237
#defineLAST_DIGIT(LAST_PAREN - 1)
3338

34-
#ifdefUSE_LOCALE
35-
staticstructlconv*lconvert=NULL;
36-
37-
#endif
38-
3939

4040
/*
4141
* Cash is a pass-by-ref SQL type, so we must pass and return pointers.
@@ -82,11 +82,11 @@ cash_in(PG_FUNCTION_ARGS)
8282
ssymbol,
8383
psymbol,
8484
*nsymbol;
85-
8685
#ifdefUSE_LOCALE
87-
if (lconvert==NULL)
88-
lconvert=localeconv();
86+
structlconv*lconvert=PGLC_localeconv();
87+
#endif
8988

89+
#ifdefUSE_LOCALE
9090
/*
9191
* frac_digits will be CHAR_MAX in some locales, notably C. However,
9292
* just testing for == CHAR_MAX is risky, because of compilers like
@@ -238,11 +238,11 @@ cash_out(PG_FUNCTION_ARGS)
238238
dsymbol,
239239
*nsymbol;
240240
charconvention;
241-
242241
#ifdefUSE_LOCALE
243-
if (lconvert==NULL)
244-
lconvert=localeconv();
242+
structlconv*lconvert=PGLC_localeconv();
243+
#endif
245244

245+
#ifdefUSE_LOCALE
246246
/* see comments about frac_digits in cash_in() */
247247
points=lconvert->frac_digits;
248248
if (points<0||points>10)

‎src/backend/utils/adt/pg_locale.c

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,18 @@
1-
21
/* -----------------------------------------------------------------------
32
* pg_locale.c
43
*
5-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/pg_locale.c,v 1.6 2000/08/29 04:41:47 momjian Exp $
4+
* The PostgreSQL locale utils.
65
*
76
*
8-
* Portions Copyright (c) 1999-2000, PostgreSQL, Inc
7+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/pg_locale.c,v 1.72000/11/25 22:43:08 tgl Exp $
98
*
10-
*The PostgreSQL locale utils.
9+
*Portions Copyright (c) 1999-2000, PostgreSQL, Inc
1110
*
1211
*Karel Zak - Zakkr
1312
*
1413
* -----------------------------------------------------------------------
1514
*/
1615

17-
#include<stdio.h>
18-
1916
#include"postgres.h"
2017

2118
#ifdefUSE_LOCALE
@@ -28,11 +25,13 @@
2825

2926
staticstructlconv*CurrentLocaleConv=NULL;
3027

28+
staticvoidPGLC_setlocale(PG_LocaleCategories*lc);
29+
3130
/*------
32-
* Return in PG_LocaleCategories current localesetting
31+
* Return in PG_LocaleCategoriesthecurrent localesettings
3332
*------
3433
*/
35-
PG_LocaleCategories*
34+
void
3635
PGLC_current(PG_LocaleCategories*lc)
3736
{
3837
lc->lang=getenv("LANG");
@@ -45,7 +44,6 @@ PGLC_current(PG_LocaleCategories * lc)
4544
#ifdefLC_MESSAGES
4645
lc->lc_messages=setlocale(LC_MESSAGES,NULL);
4746
#endif
48-
returnlc;
4947
}
5048

5149

@@ -55,7 +53,7 @@ PGLC_current(PG_LocaleCategories * lc)
5553
* Print a PG_LocaleCategories struct as DEBUG
5654
*------
5755
*/
58-
PG_LocaleCategories*
56+
staticvoid
5957
PGLC_debug_lc(PG_LocaleCategories*lc)
6058
{
6159
#ifdefLC_MESSAGES
@@ -73,72 +71,86 @@ PGLC_debug_lc(PG_LocaleCategories * lc)
7371
,lc->lc_messages
7472
#endif
7573
);
76-
77-
returnlc;
7874
}
7975

8076
#endif
8177

8278
/*------
8379
* Set locales via a PG_LocaleCategories struct
80+
*
81+
* NB: it would be very dangerous to set the locale values to any random
82+
* choice of locale, since that could cause indexes to become corrupt, etc.
83+
* Therefore this routine is NOT exported from this module. It should be
84+
* used only to restore previous locale settings during PGLC_localeconv.
8485
*------
8586
*/
86-
PG_LocaleCategories*
87+
staticvoid
8788
PGLC_setlocale(PG_LocaleCategories*lc)
8889
{
90+
if (!setlocale(LC_COLLATE,lc->lc_collate))
91+
elog(NOTICE,"pg_setlocale(): 'LC_COLLATE=%s' cannot be honored.",
92+
lc->lc_collate);
93+
8994
if (!setlocale(LC_CTYPE,lc->lc_ctype))
90-
elog(NOTICE,"pg_setlocale(): 'LC_CTYPE=%s' cannot be honored.",lc->lc_ctype);
95+
elog(NOTICE,"pg_setlocale(): 'LC_CTYPE=%s' cannot be honored.",
96+
lc->lc_ctype);
9197

9298
if (!setlocale(LC_NUMERIC,lc->lc_numeric))
93-
elog(NOTICE,"pg_setlocale(): 'LC_NUMERIC=%s' cannot be honored.",lc->lc_numeric);
99+
elog(NOTICE,"pg_setlocale(): 'LC_NUMERIC=%s' cannot be honored.",
100+
lc->lc_numeric);
94101

95102
if (!setlocale(LC_TIME,lc->lc_time))
96-
elog(NOTICE,"pg_setlocale(): 'LC_TIME=%s' cannot be honored.",lc->lc_time);
97-
98-
if (!setlocale(LC_COLLATE,lc->lc_collate))
99-
elog(NOTICE,"pg_setlocale(): 'LC_COLLATE=%s' cannot be honored.",lc->lc_collate);
103+
elog(NOTICE,"pg_setlocale(): 'LC_TIME=%s' cannot be honored.",
104+
lc->lc_time);
100105

101106
if (!setlocale(LC_MONETARY,lc->lc_monetary))
102-
elog(NOTICE,"pg_setlocale(): 'LC_MONETARY=%s' cannot be honored.",lc->lc_monetary);
107+
elog(NOTICE,"pg_setlocale(): 'LC_MONETARY=%s' cannot be honored.",
108+
lc->lc_monetary);
109+
103110
#ifdefLC_MESSAGES
104111
if (!setlocale(LC_MESSAGES,lc->lc_messages))
105-
elog(NOTICE,"pg_setlocale(): 'LC_MESSAGE=%s' cannot be honored.",lc->lc_messages);
112+
elog(NOTICE,"pg_setlocale(): 'LC_MESSAGE=%s' cannot be honored.",
113+
lc->lc_messages);
106114
#endif
107-
returnlc;
108115
}
109116

110117
/*------
111118
* Return the POSIX lconv struct (contains number/money formatting information)
112-
* with locale information for *all* categories.
113-
* => Returned lconv is *independent* on current locale catogories setting - in
114-
* contrast to standard localeconv().
119+
* with locale information for all categories. Note that returned lconv
120+
* does not depend on currently active category settings, but on external
121+
* environment variables for locale.
122+
*
123+
* XXX we assume that restoring old category settings via setlocale() will
124+
* not immediately corrupt the static data returned by localeconv().
125+
* How portable is this?
115126
*
116-
* ! libc prepare memory space for lconv itself and all returned strings in
117-
* lconv are *static strings*.
127+
* XXX in any case, there certainly must not be any other calls to
128+
* localeconv() anywhere in the backend, else the values reported here
129+
* will be overwritten with the Postgres-internal locale settings.
118130
*------
119131
*/
120132
structlconv*
121133
PGLC_localeconv(void)
122134
{
123135
PG_LocaleCategorieslc;
124-
136+
137+
/* Did we do it already? */
125138
if (CurrentLocaleConv)
126139
returnCurrentLocaleConv;
127140

128141
/* Save current locale setting to lc */
129142
PGLC_current(&lc);
130143

131-
/* Set all localecategory for current lang */
144+
/* Set all localecategories based on postmaster's environment vars */
132145
setlocale(LC_ALL,"");
133146

134-
/* Getnumericformatting information */
147+
/* Get formatting information for the external environment */
135148
CurrentLocaleConv=localeconv();
136149

137-
/*Set previous original locale */
150+
/*Restore Postgres' internal locale settings */
138151
PGLC_setlocale(&lc);
139152

140153
returnCurrentLocaleConv;
141154
}
142155

143-
144156
#endif/* USE_LOCALE */

‎src/include/utils/pg_locale.h

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
21
/* -----------------------------------------------------------------------
32
* pg_locale.h
43
*
5-
* $Header: /cvsroot/pgsql/src/include/utils/pg_locale.h,v 1.4 2000/04/12 17:16:55 momjian Exp $
4+
* The PostgreSQL locale utils.
65
*
76
*
8-
* Portions Copyright (c) 1999-2000, PostgreSQL, Inc
7+
* $Id: pg_locale.h,v 1.52000/11/25 22:43:07 tgl Exp $
98
*
10-
*The PostgreSQL locale utils.
9+
*Portions Copyright (c) 1999-2000, PostgreSQL, Inc
1110
*
1211
*Karel Zak - Zakkr
1312
*
@@ -35,13 +34,13 @@ typedef struct PG_LocaleCategories
3534
}PG_LocaleCategories;
3635

3736

38-
externPG_LocaleCategories*PGLC_current(PG_LocaleCategories*lc);
39-
externPG_LocaleCategories*PGLC_setlocale(PG_LocaleCategories*lc);
37+
externvoidPGLC_current(PG_LocaleCategories*lc);
4038

4139
/*------
4240
* Return the POSIX lconv struct (contains number/money formatting information)
43-
* with locale information for *all* categories. Returned lconv is *independent*
44-
* on current locale catogories setting - in contrast to standard localeconv().
41+
* with locale information for all categories. Note that returned lconv
42+
* does not depend on currently active category settings, but on external
43+
* environment variables for locale.
4544
*------
4645
*/
4746
externstructlconv*PGLC_localeconv(void);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp