Skip to content

Commit ff783fb

Browse files
committed
here is a patch fixing today's bug report:
> Date: Thu, 14 Dec 2000 12:44:47 +0100 (CET) > From: Kovacs Zoltan Sandor <tip@pc10.radnoti-szeged.sulinet.hu> > To: pgsql-bugs@postgresql.org > Subject: [BUGS] to_char() causes backend to close connection > > Hi, this query gives different strange results: > > select to_char(now()::abstime,'YYMMDDHH24MI'); > > I get e.g. a "backend closed the channel unexpectedly..." error with > successful or failed resetting attempt (indeterministic) Again thanks Kovacs, you found really designing bug, that appear if anyone write bad format template to "number" version of to_char() (as you with 'DD'). Karel
1 parent 0cf3765 commit ff783fb

File tree

1 file changed

+71
-10
lines changed

1 file changed

+71
-10
lines changed

src/backend/utils/adt/formatting.c

Lines changed: 71 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* -----------------------------------------------------------------------
22
* formatting.c
33
*
4-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.26 2000/12/03 20:45:35 tgl Exp $
4+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.27 2000/12/15 19:15:09 momjian Exp $
55
*
66
*
77
* Portions Copyright (c) 1999-2000, PostgreSQL, Inc
@@ -44,6 +44,17 @@
4444
*
4545
* Karel Zak
4646
*
47+
* TODO (7.2):
48+
* - replace some global values by struct that handle it
49+
* - check last used entry in the cache_search
50+
* - better number building (formatting)
51+
* - add support for abstime
52+
* - add support for roman number to standard number conversion
53+
* - add support for number spelling
54+
* - add support for string to string formatting (we must be better
55+
* than Oracle :-),
56+
* to_char('Hello', 'X X X X X') -> 'H e l l o'
57+
*
4758
* -----------------------------------------------------------------------
4859
*/
4960

@@ -334,11 +345,12 @@ static int DCHCounter = 0;
334345

335346
/* global cache for --- number part */
336347
static NUMCacheEntry NUMCache[NUM_CACHE_FIELDS + 1];
348+
static NUMCacheEntry *last_NUMCacheEntry;
337349

338350
static int n_NUMCache = 0; /* number of entries */
339351
static int NUMCounter = 0;
340352

341-
#define MAX_INT32 (2147483640)
353+
#define MAX_INT32 (2147483600)
342354

343355
/* ----------
344356
* For char->date/time conversion
@@ -850,8 +862,10 @@ static char *NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *nu
850862
int plen, int sign, int type);
851863
static DCHCacheEntry *DCH_cache_search(char *str);
852864
static DCHCacheEntry *DCH_cache_getnew(char *str);
865+
853866
static NUMCacheEntry *NUM_cache_search(char *str);
854867
static NUMCacheEntry *NUM_cache_getnew(char *str);
868+
static void NUM_cache_remove(NUMCacheEntry *ent);
855869

856870

857871
/* ----------
@@ -917,8 +931,10 @@ NUMDesc_prepare(NUMDesc *num, FormatNode *n)
917931

918932
case NUM_9:
919933
if (IS_BRACKET(num))
934+
{
935+
NUM_cache_remove(last_NUMCacheEntry);
920936
elog(ERROR, "to_char/to_number(): '9' must be ahead of 'PR'.");
921-
937+
}
922938
if (IS_MULTI(num))
923939
{
924940
++num->multi;
@@ -932,8 +948,10 @@ NUMDesc_prepare(NUMDesc *num, FormatNode *n)
932948

933949
case NUM_0:
934950
if (IS_BRACKET(num))
951+
{
952+
NUM_cache_remove(last_NUMCacheEntry);
935953
elog(ERROR, "to_char/to_number(): '0' must be ahead of 'PR'.");
936-
954+
}
937955
if (!IS_ZERO(num) && !IS_DECIMAL(num))
938956
{
939957
num->flag |= NUM_F_ZERO;
@@ -957,9 +975,15 @@ NUMDesc_prepare(NUMDesc *num, FormatNode *n)
957975
num->need_locale = TRUE;
958976
case NUM_DEC:
959977
if (IS_DECIMAL(num))
978+
{
979+
NUM_cache_remove(last_NUMCacheEntry);
960980
elog(ERROR, "to_char/to_number(): not unique decimal poit.");
981+
}
961982
if (IS_MULTI(num))
983+
{
984+
NUM_cache_remove(last_NUMCacheEntry);
962985
elog(ERROR, "to_char/to_number(): can't use 'V' and decimal poin together.");
986+
}
963987
num->flag |= NUM_F_DECIMAL;
964988
break;
965989

@@ -969,11 +993,15 @@ NUMDesc_prepare(NUMDesc *num, FormatNode *n)
969993

970994
case NUM_S:
971995
if (IS_LSIGN(num))
996+
{
997+
NUM_cache_remove(last_NUMCacheEntry);
972998
elog(ERROR, "to_char/to_number(): not unique 'S'.");
973-
999+
}
9741000
if (IS_PLUS(num) || IS_MINUS(num) || IS_BRACKET(num))
1001+
{
1002+
NUM_cache_remove(last_NUMCacheEntry);
9751003
elog(ERROR, "to_char/to_number(): can't use 'S' and 'PL'/'MI'/'SG'/'PR' together.");
976-
1004+
}
9771005
if (!IS_DECIMAL(num))
9781006
{
9791007
num->lsign = NUM_LSIGN_PRE;
@@ -992,29 +1020,38 @@ NUMDesc_prepare(NUMDesc *num, FormatNode *n)
9921020

9931021
case NUM_MI:
9941022
if (IS_LSIGN(num))
1023+
{
1024+
NUM_cache_remove(last_NUMCacheEntry);
9951025
elog(ERROR, "to_char/to_number(): can't use 'S' and 'MI' together.");
996-
1026+
}
9971027
num->flag |= NUM_F_MINUS;
9981028
break;
9991029

10001030
case NUM_PL:
10011031
if (IS_LSIGN(num))
1032+
{
1033+
NUM_cache_remove(last_NUMCacheEntry);
10021034
elog(ERROR, "to_char/to_number(): can't use 'S' and 'PL' together.");
1003-
1035+
}
10041036
num->flag |= NUM_F_PLUS;
10051037
break;
10061038

10071039
case NUM_SG:
10081040
if (IS_LSIGN(num))
1041+
{
1042+
NUM_cache_remove(last_NUMCacheEntry);
10091043
elog(ERROR, "to_char/to_number(): can't use 'S' and 'SG' together.");
1010-
1044+
}
10111045
num->flag |= NUM_F_MINUS;
10121046
num->flag |= NUM_F_PLUS;
10131047
break;
10141048

10151049
case NUM_PR:
10161050
if (IS_LSIGN(num) || IS_PLUS(num) || IS_MINUS(num))
1051+
{
1052+
NUM_cache_remove(last_NUMCacheEntry);
10171053
elog(ERROR, "to_char/to_number(): can't use 'PR' and 'S'/'PL'/'MI'/'SG' together.");
1054+
}
10181055
num->flag |= NUM_F_BRACKET;
10191056
break;
10201057

@@ -1030,11 +1067,15 @@ NUMDesc_prepare(NUMDesc *num, FormatNode *n)
10301067

10311068
case NUM_V:
10321069
if (IS_DECIMAL(num))
1070+
{
1071+
NUM_cache_remove(last_NUMCacheEntry);
10331072
elog(ERROR, "to_char/to_number(): can't use 'V' and decimal poin together.");
1073+
}
10341074
num->flag |= NUM_F_MULTI;
10351075
break;
10361076

10371077
case NUM_E:
1078+
NUM_cache_remove(last_NUMCacheEntry);
10381079
elog(ERROR, "to_char/to_number(): 'E' is not supported.");
10391080
}
10401081

@@ -2988,6 +3029,14 @@ NUM_cache_getnew(char *str)
29883029

29893030
for (ent = NUMCache; ent <= (NUMCache + NUM_CACHE_FIELDS); ent++)
29903031
{
3032+
/* entry removed via NUM_cache_remove()
3033+
* can be used here
3034+
*/
3035+
if (*ent->str == '\0')
3036+
{
3037+
old = ent;
3038+
break;
3039+
}
29913040
if (ent->age < old->age)
29923041
old = ent;
29933042
}
@@ -3015,6 +3064,7 @@ NUM_cache_getnew(char *str)
30153064

30163065
zeroize_NUM(&ent->Num);
30173066

3067+
last_NUMCacheEntry = ent;
30183068
return ent; /* never */
30193069
}
30203070

@@ -3040,6 +3090,7 @@ NUM_cache_search(char *str)
30403090
if (strcmp(ent->str, str) == 0)
30413091
{
30423092
ent->age = (++NUMCounter);
3093+
last_NUMCacheEntry = ent;
30433094
return ent;
30443095
}
30453096
i++;
@@ -3048,6 +3099,16 @@ NUM_cache_search(char *str)
30483099
return (NUMCacheEntry *) NULL;
30493100
}
30503101

3102+
static void
3103+
NUM_cache_remove(NUMCacheEntry *ent)
3104+
{
3105+
#ifdef DEBUG_TO_FROM_CHAR
3106+
elog(DEBUG_elog_output, "REMOVING ENTRY (%s)", ent->str);
3107+
#endif
3108+
*ent->str = '\0';
3109+
ent->age = 0;
3110+
}
3111+
30513112
/* ----------
30523113
* Cache routine for NUM to_char version
30533114
* ----------
@@ -3070,7 +3131,7 @@ NUM_cache(int len, NUMDesc *Num, char *pars_str, int *flag)
30703131
* Allocate new memory if format picture is bigger than static cache
30713132
* and not use cache (call parser always) - flag=1 show this variant
30723133
* ----------
3073-
*/
3134+
*/
30743135
if (len > NUM_CACHE_SIZE)
30753136
{
30763137

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy