mirror of
https://github.com/postgres/postgres.git
synced 2025-07-31 22:04:40 +03:00
Allow DateTimeParseError to handle bad-timezone error messages.
Pay down some ancient technical debt (dating to commit 022fd9966
):
fix a couple of places in datetime parsing that were throwing
ereport's immediately instead of returning a DTERR code that could be
interpreted by DateTimeParseError. The reason for that was that there
was no mechanism for passing any auxiliary data (such as a zone name)
to DateTimeParseError, and these errors seemed to really need it.
Up to now it didn't matter that much just where the error got thrown,
but now we'd like to have a hard policy that datetime parse errors
get thrown from just the one place.
Hence, invent a "DateTimeErrorExtra" struct that can be used to
carry any extra values needed for specific DTERR codes. Perhaps
in the future somebody will be motivated to use this to improve
the specificity of other DateTimeParseError messages, but for now
just deal with the timezone-error cases.
This is on the way to making the datetime input functions report
parse errors softly; but it's really an independent change, so
commit separately.
Discussion: https://postgr.es/m/3bbbb0df-7382-bf87-9737-340ba096e034@postgrespro.ru
This commit is contained in:
@ -4246,10 +4246,12 @@ to_timestamp(PG_FUNCTION_ARGS)
|
||||
/* Use the specified time zone, if any. */
|
||||
if (tm.tm_zone)
|
||||
{
|
||||
DateTimeErrorExtra extra;
|
||||
int dterr = DecodeTimezone(tm.tm_zone, &tz);
|
||||
|
||||
if (dterr)
|
||||
DateTimeParseError(dterr, text_to_cstring(date_txt), "timestamptz");
|
||||
DateTimeParseError(dterr, &extra, text_to_cstring(date_txt),
|
||||
"timestamptz");
|
||||
}
|
||||
else
|
||||
tz = DetermineTimeZoneOffset(&tm, session_timezone);
|
||||
@ -4343,10 +4345,13 @@ parse_datetime(text *date_txt, text *fmt, Oid collid, bool strict,
|
||||
|
||||
if (tm.tm_zone)
|
||||
{
|
||||
DateTimeErrorExtra extra;
|
||||
int dterr = DecodeTimezone(tm.tm_zone, tz);
|
||||
|
||||
if (dterr)
|
||||
DateTimeParseError(dterr, text_to_cstring(date_txt), "timestamptz");
|
||||
DateTimeParseError(dterr, &extra,
|
||||
text_to_cstring(date_txt),
|
||||
"timestamptz");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -4429,10 +4434,13 @@ parse_datetime(text *date_txt, text *fmt, Oid collid, bool strict,
|
||||
|
||||
if (tm.tm_zone)
|
||||
{
|
||||
DateTimeErrorExtra extra;
|
||||
int dterr = DecodeTimezone(tm.tm_zone, tz);
|
||||
|
||||
if (dterr)
|
||||
RETURN_ERROR(DateTimeParseError(dterr, text_to_cstring(date_txt), "timetz"));
|
||||
RETURN_ERROR(DateTimeParseError(dterr, &extra,
|
||||
text_to_cstring(date_txt),
|
||||
"timetz"));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -4781,7 +4789,7 @@ do_to_timestamp(text *date_txt, text *fmt, Oid collid, bool std,
|
||||
* said DTERR_MD_FIELD_OVERFLOW, because we don't want to print an
|
||||
* irrelevant hint about datestyle.
|
||||
*/
|
||||
RETURN_ERROR(DateTimeParseError(DTERR_FIELD_OVERFLOW, date_str, "timestamp"));
|
||||
RETURN_ERROR(DateTimeParseError(DTERR_FIELD_OVERFLOW, NULL, date_str, "timestamp"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -4791,7 +4799,7 @@ do_to_timestamp(text *date_txt, text *fmt, Oid collid, bool std,
|
||||
tm->tm_sec < 0 || tm->tm_sec >= SECS_PER_MINUTE ||
|
||||
*fsec < INT64CONST(0) || *fsec >= USECS_PER_SEC)
|
||||
{
|
||||
RETURN_ERROR(DateTimeParseError(DTERR_FIELD_OVERFLOW, date_str, "timestamp"));
|
||||
RETURN_ERROR(DateTimeParseError(DTERR_FIELD_OVERFLOW, NULL, date_str, "timestamp"));
|
||||
}
|
||||
|
||||
/* Save parsed time-zone into tm->tm_zone if it was specified */
|
||||
@ -4802,7 +4810,7 @@ do_to_timestamp(text *date_txt, text *fmt, Oid collid, bool std,
|
||||
if (tmfc.tzh < 0 || tmfc.tzh > MAX_TZDISP_HOUR ||
|
||||
tmfc.tzm < 0 || tmfc.tzm >= MINS_PER_HOUR)
|
||||
{
|
||||
RETURN_ERROR(DateTimeParseError(DTERR_TZDISP_OVERFLOW, date_str, "timestamp"));
|
||||
RETURN_ERROR(DateTimeParseError(DTERR_TZDISP_OVERFLOW, NULL, date_str, "timestamp"));
|
||||
}
|
||||
|
||||
tz = psprintf("%c%02d:%02d",
|
||||
|
Reference in New Issue
Block a user