Skip to content

Commit 7218aab

Browse files
committed
Adjust not-too-sane calculation of DDD value for to_char(interval).
Per gripe from Chris Matheson.
1 parent 8130cbc commit 7218aab

File tree

1 file changed

+34
-28
lines changed

1 file changed

+34
-28
lines changed

src/backend/utils/adt/formatting.c

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* -----------------------------------------------------------------------
22
* formatting.c
33
*
4-
* $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.100 2005/10/15 02:49:28 momjian Exp $
4+
* $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.101 2005/10/20 15:59:46 tgl Exp $
55
*
66
*
77
* Portions Copyright (c) 1999-2005, PostgreSQL Global Development Group
@@ -2724,15 +2724,12 @@ static text *
27242724
datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval)
27252725
{
27262726
FormatNode *format;
2727-
struct pg_tm *tm = NULL;
27282727
char *fmt_str,
27292728
*result;
27302729
bool incache;
27312730
int fmt_len = VARSIZE(fmt) - VARHDRSZ;
2732-
2733-
tm = tmtcTm(tmtc);
2734-
tm->tm_wday = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) + 1) % 7;
2735-
tm->tm_yday = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(tm->tm_year, 1, 1) + 1;
2731+
int reslen;
2732+
text *res;
27362733

27372734
/*
27382735
* Convert fmt to C string
@@ -2742,9 +2739,10 @@ datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval)
27422739
*(fmt_str + fmt_len) = '\0';
27432740

27442741
/*
2745-
* Allocate result
2742+
* Allocate workspace for result as C string
27462743
*/
27472744
result = palloc((fmt_len * DCH_MAX_ITEM_SIZ) + 1);
2745+
*result = '\0';
27482746

27492747
/*
27502748
* Allocate new memory if format picture is bigger than static cache and
@@ -2790,33 +2788,22 @@ datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval)
27902788
format = ent->format;
27912789
}
27922790

2791+
/* The real work is here */
27932792
DCH_processor(format, result, true, is_interval, (void *) tmtc);
27942793

27952794
if (!incache)
27962795
pfree(format);
27972796

27982797
pfree(fmt_str);
27992798

2800-
/*
2801-
* for result is allocated max memory, which current format-picture needs,
2802-
* now it allocate result with real size
2803-
*/
2804-
if (result && *result)
2805-
{
2806-
int len = strlen(result);
2807-
2808-
if (len)
2809-
{
2810-
text *res = (text *) palloc(len + 1 + VARHDRSZ);
2799+
/* convert C-string result to TEXT format */
2800+
reslen = strlen(result);
2801+
res = (text *) palloc(reslen + VARHDRSZ);
2802+
memcpy(VARDATA(res), result, reslen);
2803+
VARATT_SIZEP(res) = reslen + VARHDRSZ;
28112804

2812-
memcpy(VARDATA(res), result, len);
2813-
VARATT_SIZEP(res) = len + VARHDRSZ;
2814-
pfree(result);
2815-
return res;
2816-
}
2817-
}
28182805
pfree(result);
2819-
return NULL;
2806+
return res;
28202807
}
28212808

28222809
/****************************************************************************
@@ -2834,17 +2821,24 @@ timestamp_to_char(PG_FUNCTION_ARGS)
28342821
text *fmt = PG_GETARG_TEXT_P(1),
28352822
*res;
28362823
TmToChar tmtc;
2824+
struct pg_tm *tm;
2825+
int thisdate;
28372826

28382827
if ((VARSIZE(fmt) - VARHDRSZ) <= 0 || TIMESTAMP_NOT_FINITE(dt))
28392828
PG_RETURN_NULL();
28402829

28412830
ZERO_tmtc(&tmtc);
2831+
tm = tmtcTm(&tmtc);
28422832

2843-
if (timestamp2tm(dt, NULL, tmtcTm(&tmtc), &tmtcFsec(&tmtc), NULL, NULL) != 0)
2833+
if (timestamp2tm(dt, NULL, tm, &tmtcFsec(&tmtc), NULL, NULL) != 0)
28442834
ereport(ERROR,
28452835
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
28462836
errmsg("timestamp out of range")));
28472837

2838+
thisdate = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
2839+
tm->tm_wday = (thisdate + 1) % 7;
2840+
tm->tm_yday = thisdate - date2j(tm->tm_year, 1, 1) + 1;
2841+
28482842
if (!(res = datetime_to_char_body(&tmtc, fmt, false)))
28492843
PG_RETURN_NULL();
28502844

@@ -2859,17 +2853,24 @@ timestamptz_to_char(PG_FUNCTION_ARGS)
28592853
*res;
28602854
TmToChar tmtc;
28612855
int tz;
2856+
struct pg_tm *tm;
2857+
int thisdate;
28622858

28632859
if ((VARSIZE(fmt) - VARHDRSZ) <= 0 || TIMESTAMP_NOT_FINITE(dt))
28642860
PG_RETURN_NULL();
28652861

28662862
ZERO_tmtc(&tmtc);
2863+
tm = tmtcTm(&tmtc);
28672864

2868-
if (timestamp2tm(dt, &tz, tmtcTm(&tmtc), &tmtcFsec(&tmtc), &tmtcTzn(&tmtc), NULL) != 0)
2865+
if (timestamp2tm(dt, &tz, tm, &tmtcFsec(&tmtc), &tmtcTzn(&tmtc), NULL) != 0)
28692866
ereport(ERROR,
28702867
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
28712868
errmsg("timestamp out of range")));
28722869

2870+
thisdate = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
2871+
tm->tm_wday = (thisdate + 1) % 7;
2872+
tm->tm_yday = thisdate - date2j(tm->tm_year, 1, 1) + 1;
2873+
28732874
if (!(res = datetime_to_char_body(&tmtc, fmt, false)))
28742875
PG_RETURN_NULL();
28752876

@@ -2888,15 +2889,20 @@ interval_to_char(PG_FUNCTION_ARGS)
28882889
text *fmt = PG_GETARG_TEXT_P(1),
28892890
*res;
28902891
TmToChar tmtc;
2892+
struct pg_tm *tm;
28912893

28922894
if ((VARSIZE(fmt) - VARHDRSZ) <= 0)
28932895
PG_RETURN_NULL();
28942896

28952897
ZERO_tmtc(&tmtc);
2898+
tm = tmtcTm(&tmtc);
28962899

2897-
if (interval2tm(*it, tmtcTm(&tmtc), &tmtcFsec(&tmtc)) != 0)
2900+
if (interval2tm(*it, tm, &tmtcFsec(&tmtc)) != 0)
28982901
PG_RETURN_NULL();
28992902

2903+
/* wday is meaningless, yday approximates the total span in days */
2904+
tm->tm_yday = (tm->tm_year * MONTHS_PER_YEAR + tm->tm_mon) * DAYS_PER_MONTH + tm->tm_mday;
2905+
29002906
if (!(res = datetime_to_char_body(&tmtc, fmt, true)))
29012907
PG_RETURN_NULL();
29022908

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