mirror of
https://github.com/postgres/postgres.git
synced 2025-04-22 23:02:54 +03:00
Adjust not-too-sane calculation of DDD value for to_char(interval).
Per gripe from Chris Matheson.
This commit is contained in:
parent
8130cbce96
commit
7218aab7a2
@ -1,7 +1,7 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
* formatting.c
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.100 2005/10/15 02:49:28 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.101 2005/10/20 15:59:46 tgl Exp $
|
||||
*
|
||||
*
|
||||
* Portions Copyright (c) 1999-2005, PostgreSQL Global Development Group
|
||||
@ -2724,15 +2724,12 @@ static text *
|
||||
datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval)
|
||||
{
|
||||
FormatNode *format;
|
||||
struct pg_tm *tm = NULL;
|
||||
char *fmt_str,
|
||||
*result;
|
||||
bool incache;
|
||||
int fmt_len = VARSIZE(fmt) - VARHDRSZ;
|
||||
|
||||
tm = tmtcTm(tmtc);
|
||||
tm->tm_wday = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) + 1) % 7;
|
||||
tm->tm_yday = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(tm->tm_year, 1, 1) + 1;
|
||||
int reslen;
|
||||
text *res;
|
||||
|
||||
/*
|
||||
* Convert fmt to C string
|
||||
@ -2742,9 +2739,10 @@ datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval)
|
||||
*(fmt_str + fmt_len) = '\0';
|
||||
|
||||
/*
|
||||
* Allocate result
|
||||
* Allocate workspace for result as C string
|
||||
*/
|
||||
result = palloc((fmt_len * DCH_MAX_ITEM_SIZ) + 1);
|
||||
*result = '\0';
|
||||
|
||||
/*
|
||||
* Allocate new memory if format picture is bigger than static cache and
|
||||
@ -2790,6 +2788,7 @@ datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval)
|
||||
format = ent->format;
|
||||
}
|
||||
|
||||
/* The real work is here */
|
||||
DCH_processor(format, result, true, is_interval, (void *) tmtc);
|
||||
|
||||
if (!incache)
|
||||
@ -2797,27 +2796,15 @@ datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval)
|
||||
|
||||
pfree(fmt_str);
|
||||
|
||||
/*
|
||||
* for result is allocated max memory, which current format-picture needs,
|
||||
* now it allocate result with real size
|
||||
*/
|
||||
if (result && *result)
|
||||
{
|
||||
int len = strlen(result);
|
||||
/* convert C-string result to TEXT format */
|
||||
reslen = strlen(result);
|
||||
res = (text *) palloc(reslen + VARHDRSZ);
|
||||
memcpy(VARDATA(res), result, reslen);
|
||||
VARATT_SIZEP(res) = reslen + VARHDRSZ;
|
||||
|
||||
if (len)
|
||||
{
|
||||
text *res = (text *) palloc(len + 1 + VARHDRSZ);
|
||||
|
||||
memcpy(VARDATA(res), result, len);
|
||||
VARATT_SIZEP(res) = len + VARHDRSZ;
|
||||
pfree(result);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
pfree(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public routines
|
||||
@ -2834,17 +2821,24 @@ timestamp_to_char(PG_FUNCTION_ARGS)
|
||||
text *fmt = PG_GETARG_TEXT_P(1),
|
||||
*res;
|
||||
TmToChar tmtc;
|
||||
struct pg_tm *tm;
|
||||
int thisdate;
|
||||
|
||||
if ((VARSIZE(fmt) - VARHDRSZ) <= 0 || TIMESTAMP_NOT_FINITE(dt))
|
||||
PG_RETURN_NULL();
|
||||
|
||||
ZERO_tmtc(&tmtc);
|
||||
tm = tmtcTm(&tmtc);
|
||||
|
||||
if (timestamp2tm(dt, NULL, tmtcTm(&tmtc), &tmtcFsec(&tmtc), NULL, NULL) != 0)
|
||||
if (timestamp2tm(dt, NULL, tm, &tmtcFsec(&tmtc), NULL, NULL) != 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
||||
errmsg("timestamp out of range")));
|
||||
|
||||
thisdate = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
|
||||
tm->tm_wday = (thisdate + 1) % 7;
|
||||
tm->tm_yday = thisdate - date2j(tm->tm_year, 1, 1) + 1;
|
||||
|
||||
if (!(res = datetime_to_char_body(&tmtc, fmt, false)))
|
||||
PG_RETURN_NULL();
|
||||
|
||||
@ -2859,17 +2853,24 @@ timestamptz_to_char(PG_FUNCTION_ARGS)
|
||||
*res;
|
||||
TmToChar tmtc;
|
||||
int tz;
|
||||
struct pg_tm *tm;
|
||||
int thisdate;
|
||||
|
||||
if ((VARSIZE(fmt) - VARHDRSZ) <= 0 || TIMESTAMP_NOT_FINITE(dt))
|
||||
PG_RETURN_NULL();
|
||||
|
||||
ZERO_tmtc(&tmtc);
|
||||
tm = tmtcTm(&tmtc);
|
||||
|
||||
if (timestamp2tm(dt, &tz, tmtcTm(&tmtc), &tmtcFsec(&tmtc), &tmtcTzn(&tmtc), NULL) != 0)
|
||||
if (timestamp2tm(dt, &tz, tm, &tmtcFsec(&tmtc), &tmtcTzn(&tmtc), NULL) != 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
||||
errmsg("timestamp out of range")));
|
||||
|
||||
thisdate = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
|
||||
tm->tm_wday = (thisdate + 1) % 7;
|
||||
tm->tm_yday = thisdate - date2j(tm->tm_year, 1, 1) + 1;
|
||||
|
||||
if (!(res = datetime_to_char_body(&tmtc, fmt, false)))
|
||||
PG_RETURN_NULL();
|
||||
|
||||
@ -2888,15 +2889,20 @@ interval_to_char(PG_FUNCTION_ARGS)
|
||||
text *fmt = PG_GETARG_TEXT_P(1),
|
||||
*res;
|
||||
TmToChar tmtc;
|
||||
struct pg_tm *tm;
|
||||
|
||||
if ((VARSIZE(fmt) - VARHDRSZ) <= 0)
|
||||
PG_RETURN_NULL();
|
||||
|
||||
ZERO_tmtc(&tmtc);
|
||||
tm = tmtcTm(&tmtc);
|
||||
|
||||
if (interval2tm(*it, tmtcTm(&tmtc), &tmtcFsec(&tmtc)) != 0)
|
||||
if (interval2tm(*it, tm, &tmtcFsec(&tmtc)) != 0)
|
||||
PG_RETURN_NULL();
|
||||
|
||||
/* wday is meaningless, yday approximates the total span in days */
|
||||
tm->tm_yday = (tm->tm_year * MONTHS_PER_YEAR + tm->tm_mon) * DAYS_PER_MONTH + tm->tm_mday;
|
||||
|
||||
if (!(res = datetime_to_char_body(&tmtc, fmt, true)))
|
||||
PG_RETURN_NULL();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user