mirror of
https://github.com/postgres/postgres.git
synced 2025-04-24 10:47:04 +03:00
Convert datetime input functions to use "soft" error reporting.
This patch converts the input functions for date, time, timetz, timestamp, timestamptz, and interval to the new soft-error style. There's some related stuff in formatting.c that remains to be cleaned up, but that seems like a separable project. Discussion: https://postgr.es/m/3bbbb0df-7382-bf87-9737-340ba096e034@postgrespro.ru
This commit is contained in:
parent
2661469d86
commit
c60488b474
@ -111,6 +111,7 @@ Datum
|
|||||||
date_in(PG_FUNCTION_ARGS)
|
date_in(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
char *str = PG_GETARG_CSTRING(0);
|
char *str = PG_GETARG_CSTRING(0);
|
||||||
|
Node *escontext = fcinfo->context;
|
||||||
DateADT date;
|
DateADT date;
|
||||||
fsec_t fsec;
|
fsec_t fsec;
|
||||||
struct pg_tm tt,
|
struct pg_tm tt,
|
||||||
@ -130,7 +131,10 @@ date_in(PG_FUNCTION_ARGS)
|
|||||||
dterr = DecodeDateTime(field, ftype, nf,
|
dterr = DecodeDateTime(field, ftype, nf,
|
||||||
&dtype, tm, &fsec, &tzp, &extra);
|
&dtype, tm, &fsec, &tzp, &extra);
|
||||||
if (dterr != 0)
|
if (dterr != 0)
|
||||||
DateTimeParseError(dterr, &extra, str, "date");
|
{
|
||||||
|
DateTimeParseError(dterr, &extra, str, "date", escontext);
|
||||||
|
PG_RETURN_NULL();
|
||||||
|
}
|
||||||
|
|
||||||
switch (dtype)
|
switch (dtype)
|
||||||
{
|
{
|
||||||
@ -150,13 +154,13 @@ date_in(PG_FUNCTION_ARGS)
|
|||||||
PG_RETURN_DATEADT(date);
|
PG_RETURN_DATEADT(date);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DateTimeParseError(DTERR_BAD_FORMAT, &extra, str, "date");
|
DateTimeParseError(DTERR_BAD_FORMAT, &extra, str, "date", escontext);
|
||||||
break;
|
PG_RETURN_NULL();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prevent overflow in Julian-day routines */
|
/* Prevent overflow in Julian-day routines */
|
||||||
if (!IS_VALID_JULIAN(tm->tm_year, tm->tm_mon, tm->tm_mday))
|
if (!IS_VALID_JULIAN(tm->tm_year, tm->tm_mon, tm->tm_mday))
|
||||||
ereport(ERROR,
|
ereturn(escontext, (Datum) 0,
|
||||||
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
||||||
errmsg("date out of range: \"%s\"", str)));
|
errmsg("date out of range: \"%s\"", str)));
|
||||||
|
|
||||||
@ -164,7 +168,7 @@ date_in(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
/* Now check for just-out-of-range dates */
|
/* Now check for just-out-of-range dates */
|
||||||
if (!IS_VALID_DATE(date))
|
if (!IS_VALID_DATE(date))
|
||||||
ereport(ERROR,
|
ereturn(escontext, (Datum) 0,
|
||||||
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
||||||
errmsg("date out of range: \"%s\"", str)));
|
errmsg("date out of range: \"%s\"", str)));
|
||||||
|
|
||||||
@ -1384,11 +1388,11 @@ Datum
|
|||||||
time_in(PG_FUNCTION_ARGS)
|
time_in(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
char *str = PG_GETARG_CSTRING(0);
|
char *str = PG_GETARG_CSTRING(0);
|
||||||
|
|
||||||
#ifdef NOT_USED
|
#ifdef NOT_USED
|
||||||
Oid typelem = PG_GETARG_OID(1);
|
Oid typelem = PG_GETARG_OID(1);
|
||||||
#endif
|
#endif
|
||||||
int32 typmod = PG_GETARG_INT32(2);
|
int32 typmod = PG_GETARG_INT32(2);
|
||||||
|
Node *escontext = fcinfo->context;
|
||||||
TimeADT result;
|
TimeADT result;
|
||||||
fsec_t fsec;
|
fsec_t fsec;
|
||||||
struct pg_tm tt,
|
struct pg_tm tt,
|
||||||
@ -1408,7 +1412,10 @@ time_in(PG_FUNCTION_ARGS)
|
|||||||
dterr = DecodeTimeOnly(field, ftype, nf,
|
dterr = DecodeTimeOnly(field, ftype, nf,
|
||||||
&dtype, tm, &fsec, &tz, &extra);
|
&dtype, tm, &fsec, &tz, &extra);
|
||||||
if (dterr != 0)
|
if (dterr != 0)
|
||||||
DateTimeParseError(dterr, &extra, str, "time");
|
{
|
||||||
|
DateTimeParseError(dterr, &extra, str, "time", escontext);
|
||||||
|
PG_RETURN_NULL();
|
||||||
|
}
|
||||||
|
|
||||||
tm2time(tm, fsec, &result);
|
tm2time(tm, fsec, &result);
|
||||||
AdjustTimeForTypmod(&result, typmod);
|
AdjustTimeForTypmod(&result, typmod);
|
||||||
@ -2272,11 +2279,11 @@ Datum
|
|||||||
timetz_in(PG_FUNCTION_ARGS)
|
timetz_in(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
char *str = PG_GETARG_CSTRING(0);
|
char *str = PG_GETARG_CSTRING(0);
|
||||||
|
|
||||||
#ifdef NOT_USED
|
#ifdef NOT_USED
|
||||||
Oid typelem = PG_GETARG_OID(1);
|
Oid typelem = PG_GETARG_OID(1);
|
||||||
#endif
|
#endif
|
||||||
int32 typmod = PG_GETARG_INT32(2);
|
int32 typmod = PG_GETARG_INT32(2);
|
||||||
|
Node *escontext = fcinfo->context;
|
||||||
TimeTzADT *result;
|
TimeTzADT *result;
|
||||||
fsec_t fsec;
|
fsec_t fsec;
|
||||||
struct pg_tm tt,
|
struct pg_tm tt,
|
||||||
@ -2296,7 +2303,11 @@ timetz_in(PG_FUNCTION_ARGS)
|
|||||||
dterr = DecodeTimeOnly(field, ftype, nf,
|
dterr = DecodeTimeOnly(field, ftype, nf,
|
||||||
&dtype, tm, &fsec, &tz, &extra);
|
&dtype, tm, &fsec, &tz, &extra);
|
||||||
if (dterr != 0)
|
if (dterr != 0)
|
||||||
DateTimeParseError(dterr, &extra, str, "time with time zone");
|
{
|
||||||
|
DateTimeParseError(dterr, &extra, str, "time with time zone",
|
||||||
|
escontext);
|
||||||
|
PG_RETURN_NULL();
|
||||||
|
}
|
||||||
|
|
||||||
result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
|
result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
|
||||||
tm2timetz(tm, fsec, tz, result);
|
tm2timetz(tm, fsec, tz, result);
|
||||||
@ -3071,7 +3082,7 @@ timetz_zone(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
dterr = DecodeTimezoneAbbrev(0, lowzone, &type, &val, &tzp, &extra);
|
dterr = DecodeTimezoneAbbrev(0, lowzone, &type, &val, &tzp, &extra);
|
||||||
if (dterr)
|
if (dterr)
|
||||||
DateTimeParseError(dterr, &extra, NULL, NULL);
|
DateTimeParseError(dterr, &extra, NULL, NULL, NULL);
|
||||||
|
|
||||||
if (type == TZ || type == DTZ)
|
if (type == TZ || type == DTZ)
|
||||||
{
|
{
|
||||||
|
@ -4031,50 +4031,54 @@ DecodeUnits(int field, const char *lowtoken, int *val)
|
|||||||
* we were trying to accept. (For some DTERR codes, these are not used and
|
* we were trying to accept. (For some DTERR codes, these are not used and
|
||||||
* can be NULL.)
|
* can be NULL.)
|
||||||
*
|
*
|
||||||
|
* If escontext points to an ErrorSaveContext node, that is filled instead
|
||||||
|
* of throwing an error.
|
||||||
|
*
|
||||||
* Note: it might seem useless to distinguish DTERR_INTERVAL_OVERFLOW and
|
* Note: it might seem useless to distinguish DTERR_INTERVAL_OVERFLOW and
|
||||||
* DTERR_TZDISP_OVERFLOW from DTERR_FIELD_OVERFLOW, but SQL99 mandates three
|
* DTERR_TZDISP_OVERFLOW from DTERR_FIELD_OVERFLOW, but SQL99 mandates three
|
||||||
* separate SQLSTATE codes, so ...
|
* separate SQLSTATE codes, so ...
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
DateTimeParseError(int dterr, DateTimeErrorExtra *extra,
|
DateTimeParseError(int dterr, DateTimeErrorExtra *extra,
|
||||||
const char *str, const char *datatype)
|
const char *str, const char *datatype,
|
||||||
|
Node *escontext)
|
||||||
{
|
{
|
||||||
switch (dterr)
|
switch (dterr)
|
||||||
{
|
{
|
||||||
case DTERR_FIELD_OVERFLOW:
|
case DTERR_FIELD_OVERFLOW:
|
||||||
ereport(ERROR,
|
errsave(escontext,
|
||||||
(errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
|
(errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
|
||||||
errmsg("date/time field value out of range: \"%s\"",
|
errmsg("date/time field value out of range: \"%s\"",
|
||||||
str)));
|
str)));
|
||||||
break;
|
break;
|
||||||
case DTERR_MD_FIELD_OVERFLOW:
|
case DTERR_MD_FIELD_OVERFLOW:
|
||||||
/* <nanny>same as above, but add hint about DateStyle</nanny> */
|
/* <nanny>same as above, but add hint about DateStyle</nanny> */
|
||||||
ereport(ERROR,
|
errsave(escontext,
|
||||||
(errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
|
(errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
|
||||||
errmsg("date/time field value out of range: \"%s\"",
|
errmsg("date/time field value out of range: \"%s\"",
|
||||||
str),
|
str),
|
||||||
errhint("Perhaps you need a different \"datestyle\" setting.")));
|
errhint("Perhaps you need a different \"datestyle\" setting.")));
|
||||||
break;
|
break;
|
||||||
case DTERR_INTERVAL_OVERFLOW:
|
case DTERR_INTERVAL_OVERFLOW:
|
||||||
ereport(ERROR,
|
errsave(escontext,
|
||||||
(errcode(ERRCODE_INTERVAL_FIELD_OVERFLOW),
|
(errcode(ERRCODE_INTERVAL_FIELD_OVERFLOW),
|
||||||
errmsg("interval field value out of range: \"%s\"",
|
errmsg("interval field value out of range: \"%s\"",
|
||||||
str)));
|
str)));
|
||||||
break;
|
break;
|
||||||
case DTERR_TZDISP_OVERFLOW:
|
case DTERR_TZDISP_OVERFLOW:
|
||||||
ereport(ERROR,
|
errsave(escontext,
|
||||||
(errcode(ERRCODE_INVALID_TIME_ZONE_DISPLACEMENT_VALUE),
|
(errcode(ERRCODE_INVALID_TIME_ZONE_DISPLACEMENT_VALUE),
|
||||||
errmsg("time zone displacement out of range: \"%s\"",
|
errmsg("time zone displacement out of range: \"%s\"",
|
||||||
str)));
|
str)));
|
||||||
break;
|
break;
|
||||||
case DTERR_BAD_TIMEZONE:
|
case DTERR_BAD_TIMEZONE:
|
||||||
ereport(ERROR,
|
errsave(escontext,
|
||||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||||
errmsg("time zone \"%s\" not recognized",
|
errmsg("time zone \"%s\" not recognized",
|
||||||
extra->dtee_timezone)));
|
extra->dtee_timezone)));
|
||||||
break;
|
break;
|
||||||
case DTERR_BAD_ZONE_ABBREV:
|
case DTERR_BAD_ZONE_ABBREV:
|
||||||
ereport(ERROR,
|
errsave(escontext,
|
||||||
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
||||||
errmsg("time zone \"%s\" not recognized",
|
errmsg("time zone \"%s\" not recognized",
|
||||||
extra->dtee_timezone),
|
extra->dtee_timezone),
|
||||||
@ -4083,7 +4087,7 @@ DateTimeParseError(int dterr, DateTimeErrorExtra *extra,
|
|||||||
break;
|
break;
|
||||||
case DTERR_BAD_FORMAT:
|
case DTERR_BAD_FORMAT:
|
||||||
default:
|
default:
|
||||||
ereport(ERROR,
|
errsave(escontext,
|
||||||
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
|
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
|
||||||
errmsg("invalid input syntax for type %s: \"%s\"",
|
errmsg("invalid input syntax for type %s: \"%s\"",
|
||||||
datatype, str)));
|
datatype, str)));
|
||||||
@ -5026,7 +5030,7 @@ pg_timezone_abbrevs(PG_FUNCTION_ARGS)
|
|||||||
tzp = FetchDynamicTimeZone(zoneabbrevtbl, tp, &extra);
|
tzp = FetchDynamicTimeZone(zoneabbrevtbl, tp, &extra);
|
||||||
if (tzp == NULL)
|
if (tzp == NULL)
|
||||||
DateTimeParseError(DTERR_BAD_ZONE_ABBREV, &extra,
|
DateTimeParseError(DTERR_BAD_ZONE_ABBREV, &extra,
|
||||||
NULL, NULL);
|
NULL, NULL, NULL);
|
||||||
now = GetCurrentTransactionStartTimestamp();
|
now = GetCurrentTransactionStartTimestamp();
|
||||||
gmtoffset = -DetermineTimeZoneAbbrevOffsetTS(now,
|
gmtoffset = -DetermineTimeZoneAbbrevOffsetTS(now,
|
||||||
tp->token,
|
tp->token,
|
||||||
|
@ -4251,7 +4251,7 @@ to_timestamp(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
if (dterr)
|
if (dterr)
|
||||||
DateTimeParseError(dterr, &extra, text_to_cstring(date_txt),
|
DateTimeParseError(dterr, &extra, text_to_cstring(date_txt),
|
||||||
"timestamptz");
|
"timestamptz", NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
tz = DetermineTimeZoneOffset(&tm, session_timezone);
|
tz = DetermineTimeZoneOffset(&tm, session_timezone);
|
||||||
@ -4263,7 +4263,7 @@ to_timestamp(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
/* Use the specified fractional precision, if any. */
|
/* Use the specified fractional precision, if any. */
|
||||||
if (fprec)
|
if (fprec)
|
||||||
AdjustTimestampForTypmod(&result, fprec);
|
AdjustTimestampForTypmod(&result, fprec, NULL);
|
||||||
|
|
||||||
PG_RETURN_TIMESTAMP(result);
|
PG_RETURN_TIMESTAMP(result);
|
||||||
}
|
}
|
||||||
@ -4351,7 +4351,7 @@ parse_datetime(text *date_txt, text *fmt, Oid collid, bool strict,
|
|||||||
if (dterr)
|
if (dterr)
|
||||||
DateTimeParseError(dterr, &extra,
|
DateTimeParseError(dterr, &extra,
|
||||||
text_to_cstring(date_txt),
|
text_to_cstring(date_txt),
|
||||||
"timestamptz");
|
"timestamptz", NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -4372,7 +4372,7 @@ parse_datetime(text *date_txt, text *fmt, Oid collid, bool strict,
|
|||||||
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
||||||
errmsg("timestamptz out of range"))));
|
errmsg("timestamptz out of range"))));
|
||||||
|
|
||||||
AdjustTimestampForTypmod(&result, *typmod);
|
AdjustTimestampForTypmod(&result, *typmod, NULL); /* XXX */
|
||||||
|
|
||||||
*typid = TIMESTAMPTZOID;
|
*typid = TIMESTAMPTZOID;
|
||||||
return TimestampTzGetDatum(result);
|
return TimestampTzGetDatum(result);
|
||||||
@ -4386,7 +4386,7 @@ parse_datetime(text *date_txt, text *fmt, Oid collid, bool strict,
|
|||||||
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
||||||
errmsg("timestamp out of range"))));
|
errmsg("timestamp out of range"))));
|
||||||
|
|
||||||
AdjustTimestampForTypmod(&result, *typmod);
|
AdjustTimestampForTypmod(&result, *typmod, NULL); /* XXX */
|
||||||
|
|
||||||
*typid = TIMESTAMPOID;
|
*typid = TIMESTAMPOID;
|
||||||
return TimestampGetDatum(result);
|
return TimestampGetDatum(result);
|
||||||
@ -4440,7 +4440,7 @@ parse_datetime(text *date_txt, text *fmt, Oid collid, bool strict,
|
|||||||
if (dterr)
|
if (dterr)
|
||||||
RETURN_ERROR(DateTimeParseError(dterr, &extra,
|
RETURN_ERROR(DateTimeParseError(dterr, &extra,
|
||||||
text_to_cstring(date_txt),
|
text_to_cstring(date_txt),
|
||||||
"timetz"));
|
"timetz", NULL));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -4789,7 +4789,8 @@ 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
|
* said DTERR_MD_FIELD_OVERFLOW, because we don't want to print an
|
||||||
* irrelevant hint about datestyle.
|
* irrelevant hint about datestyle.
|
||||||
*/
|
*/
|
||||||
RETURN_ERROR(DateTimeParseError(DTERR_FIELD_OVERFLOW, NULL, date_str, "timestamp"));
|
RETURN_ERROR(DateTimeParseError(DTERR_FIELD_OVERFLOW, NULL,
|
||||||
|
date_str, "timestamp", NULL));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4799,7 +4800,8 @@ do_to_timestamp(text *date_txt, text *fmt, Oid collid, bool std,
|
|||||||
tm->tm_sec < 0 || tm->tm_sec >= SECS_PER_MINUTE ||
|
tm->tm_sec < 0 || tm->tm_sec >= SECS_PER_MINUTE ||
|
||||||
*fsec < INT64CONST(0) || *fsec >= USECS_PER_SEC)
|
*fsec < INT64CONST(0) || *fsec >= USECS_PER_SEC)
|
||||||
{
|
{
|
||||||
RETURN_ERROR(DateTimeParseError(DTERR_FIELD_OVERFLOW, NULL, date_str, "timestamp"));
|
RETURN_ERROR(DateTimeParseError(DTERR_FIELD_OVERFLOW, NULL,
|
||||||
|
date_str, "timestamp", NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save parsed time-zone into tm->tm_zone if it was specified */
|
/* Save parsed time-zone into tm->tm_zone if it was specified */
|
||||||
@ -4810,7 +4812,8 @@ do_to_timestamp(text *date_txt, text *fmt, Oid collid, bool std,
|
|||||||
if (tmfc.tzh < 0 || tmfc.tzh > MAX_TZDISP_HOUR ||
|
if (tmfc.tzh < 0 || tmfc.tzh > MAX_TZDISP_HOUR ||
|
||||||
tmfc.tzm < 0 || tmfc.tzm >= MINS_PER_HOUR)
|
tmfc.tzm < 0 || tmfc.tzm >= MINS_PER_HOUR)
|
||||||
{
|
{
|
||||||
RETURN_ERROR(DateTimeParseError(DTERR_TZDISP_OVERFLOW, NULL, date_str, "timestamp"));
|
RETURN_ERROR(DateTimeParseError(DTERR_TZDISP_OVERFLOW, NULL,
|
||||||
|
date_str, "timestamp", NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
tz = psprintf("%c%02d:%02d",
|
tz = psprintf("%c%02d:%02d",
|
||||||
|
@ -74,7 +74,8 @@ typedef struct
|
|||||||
|
|
||||||
static TimeOffset time2t(const int hour, const int min, const int sec, const fsec_t fsec);
|
static TimeOffset time2t(const int hour, const int min, const int sec, const fsec_t fsec);
|
||||||
static Timestamp dt2local(Timestamp dt, int timezone);
|
static Timestamp dt2local(Timestamp dt, int timezone);
|
||||||
static void AdjustIntervalForTypmod(Interval *interval, int32 typmod);
|
static bool AdjustIntervalForTypmod(Interval *interval, int32 typmod,
|
||||||
|
Node *escontext);
|
||||||
static TimestampTz timestamp2timestamptz(Timestamp timestamp);
|
static TimestampTz timestamp2timestamptz(Timestamp timestamp);
|
||||||
static Timestamp timestamptz2timestamp(TimestampTz timestamp);
|
static Timestamp timestamptz2timestamp(TimestampTz timestamp);
|
||||||
|
|
||||||
@ -145,11 +146,11 @@ Datum
|
|||||||
timestamp_in(PG_FUNCTION_ARGS)
|
timestamp_in(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
char *str = PG_GETARG_CSTRING(0);
|
char *str = PG_GETARG_CSTRING(0);
|
||||||
|
|
||||||
#ifdef NOT_USED
|
#ifdef NOT_USED
|
||||||
Oid typelem = PG_GETARG_OID(1);
|
Oid typelem = PG_GETARG_OID(1);
|
||||||
#endif
|
#endif
|
||||||
int32 typmod = PG_GETARG_INT32(2);
|
int32 typmod = PG_GETARG_INT32(2);
|
||||||
|
Node *escontext = fcinfo->context;
|
||||||
Timestamp result;
|
Timestamp result;
|
||||||
fsec_t fsec;
|
fsec_t fsec;
|
||||||
struct pg_tm tt,
|
struct pg_tm tt,
|
||||||
@ -169,13 +170,16 @@ timestamp_in(PG_FUNCTION_ARGS)
|
|||||||
dterr = DecodeDateTime(field, ftype, nf,
|
dterr = DecodeDateTime(field, ftype, nf,
|
||||||
&dtype, tm, &fsec, &tz, &extra);
|
&dtype, tm, &fsec, &tz, &extra);
|
||||||
if (dterr != 0)
|
if (dterr != 0)
|
||||||
DateTimeParseError(dterr, &extra, str, "timestamp");
|
{
|
||||||
|
DateTimeParseError(dterr, &extra, str, "timestamp", escontext);
|
||||||
|
PG_RETURN_NULL();
|
||||||
|
}
|
||||||
|
|
||||||
switch (dtype)
|
switch (dtype)
|
||||||
{
|
{
|
||||||
case DTK_DATE:
|
case DTK_DATE:
|
||||||
if (tm2timestamp(tm, fsec, NULL, &result) != 0)
|
if (tm2timestamp(tm, fsec, NULL, &result) != 0)
|
||||||
ereport(ERROR,
|
ereturn(escontext, (Datum) 0,
|
||||||
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
||||||
errmsg("timestamp out of range: \"%s\"", str)));
|
errmsg("timestamp out of range: \"%s\"", str)));
|
||||||
break;
|
break;
|
||||||
@ -198,7 +202,7 @@ timestamp_in(PG_FUNCTION_ARGS)
|
|||||||
TIMESTAMP_NOEND(result);
|
TIMESTAMP_NOEND(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
AdjustTimestampForTypmod(&result, typmod);
|
AdjustTimestampForTypmod(&result, typmod, escontext);
|
||||||
|
|
||||||
PG_RETURN_TIMESTAMP(result);
|
PG_RETURN_TIMESTAMP(result);
|
||||||
}
|
}
|
||||||
@ -257,7 +261,7 @@ timestamp_recv(PG_FUNCTION_ARGS)
|
|||||||
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
||||||
errmsg("timestamp out of range")));
|
errmsg("timestamp out of range")));
|
||||||
|
|
||||||
AdjustTimestampForTypmod(×tamp, typmod);
|
AdjustTimestampForTypmod(×tamp, typmod, NULL);
|
||||||
|
|
||||||
PG_RETURN_TIMESTAMP(timestamp);
|
PG_RETURN_TIMESTAMP(timestamp);
|
||||||
}
|
}
|
||||||
@ -328,17 +332,20 @@ timestamp_scale(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
result = timestamp;
|
result = timestamp;
|
||||||
|
|
||||||
AdjustTimestampForTypmod(&result, typmod);
|
AdjustTimestampForTypmod(&result, typmod, NULL);
|
||||||
|
|
||||||
PG_RETURN_TIMESTAMP(result);
|
PG_RETURN_TIMESTAMP(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AdjustTimestampForTypmodError --- round off a timestamp to suit given typmod
|
* AdjustTimestampForTypmod --- round off a timestamp to suit given typmod
|
||||||
* Works for either timestamp or timestamptz.
|
* Works for either timestamp or timestamptz.
|
||||||
|
*
|
||||||
|
* Returns true on success, false on failure (if escontext points to an
|
||||||
|
* ErrorSaveContext; otherwise errors are thrown).
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
AdjustTimestampForTypmodError(Timestamp *time, int32 typmod, bool *error)
|
AdjustTimestampForTypmod(Timestamp *time, int32 typmod, Node *escontext)
|
||||||
{
|
{
|
||||||
static const int64 TimestampScales[MAX_TIMESTAMP_PRECISION + 1] = {
|
static const int64 TimestampScales[MAX_TIMESTAMP_PRECISION + 1] = {
|
||||||
INT64CONST(1000000),
|
INT64CONST(1000000),
|
||||||
@ -364,18 +371,10 @@ AdjustTimestampForTypmodError(Timestamp *time, int32 typmod, bool *error)
|
|||||||
&& (typmod != -1) && (typmod != MAX_TIMESTAMP_PRECISION))
|
&& (typmod != -1) && (typmod != MAX_TIMESTAMP_PRECISION))
|
||||||
{
|
{
|
||||||
if (typmod < 0 || typmod > MAX_TIMESTAMP_PRECISION)
|
if (typmod < 0 || typmod > MAX_TIMESTAMP_PRECISION)
|
||||||
{
|
ereturn(escontext, false,
|
||||||
if (error)
|
|
||||||
{
|
|
||||||
*error = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||||
errmsg("timestamp(%d) precision must be between %d and %d",
|
errmsg("timestamp(%d) precision must be between %d and %d",
|
||||||
typmod, 0, MAX_TIMESTAMP_PRECISION)));
|
typmod, 0, MAX_TIMESTAMP_PRECISION)));
|
||||||
}
|
|
||||||
|
|
||||||
if (*time >= INT64CONST(0))
|
if (*time >= INT64CONST(0))
|
||||||
{
|
{
|
||||||
@ -392,12 +391,6 @@ AdjustTimestampForTypmodError(Timestamp *time, int32 typmod, bool *error)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
AdjustTimestampForTypmod(Timestamp *time, int32 typmod)
|
|
||||||
{
|
|
||||||
(void) AdjustTimestampForTypmodError(time, typmod, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* timestamptz_in()
|
/* timestamptz_in()
|
||||||
* Convert a string to internal form.
|
* Convert a string to internal form.
|
||||||
*/
|
*/
|
||||||
@ -405,11 +398,11 @@ Datum
|
|||||||
timestamptz_in(PG_FUNCTION_ARGS)
|
timestamptz_in(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
char *str = PG_GETARG_CSTRING(0);
|
char *str = PG_GETARG_CSTRING(0);
|
||||||
|
|
||||||
#ifdef NOT_USED
|
#ifdef NOT_USED
|
||||||
Oid typelem = PG_GETARG_OID(1);
|
Oid typelem = PG_GETARG_OID(1);
|
||||||
#endif
|
#endif
|
||||||
int32 typmod = PG_GETARG_INT32(2);
|
int32 typmod = PG_GETARG_INT32(2);
|
||||||
|
Node *escontext = fcinfo->context;
|
||||||
TimestampTz result;
|
TimestampTz result;
|
||||||
fsec_t fsec;
|
fsec_t fsec;
|
||||||
struct pg_tm tt,
|
struct pg_tm tt,
|
||||||
@ -429,13 +422,17 @@ timestamptz_in(PG_FUNCTION_ARGS)
|
|||||||
dterr = DecodeDateTime(field, ftype, nf,
|
dterr = DecodeDateTime(field, ftype, nf,
|
||||||
&dtype, tm, &fsec, &tz, &extra);
|
&dtype, tm, &fsec, &tz, &extra);
|
||||||
if (dterr != 0)
|
if (dterr != 0)
|
||||||
DateTimeParseError(dterr, &extra, str, "timestamp with time zone");
|
{
|
||||||
|
DateTimeParseError(dterr, &extra, str, "timestamp with time zone",
|
||||||
|
escontext);
|
||||||
|
PG_RETURN_NULL();
|
||||||
|
}
|
||||||
|
|
||||||
switch (dtype)
|
switch (dtype)
|
||||||
{
|
{
|
||||||
case DTK_DATE:
|
case DTK_DATE:
|
||||||
if (tm2timestamp(tm, fsec, &tz, &result) != 0)
|
if (tm2timestamp(tm, fsec, &tz, &result) != 0)
|
||||||
ereport(ERROR,
|
ereturn(escontext, (Datum) 0,
|
||||||
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
||||||
errmsg("timestamp out of range: \"%s\"", str)));
|
errmsg("timestamp out of range: \"%s\"", str)));
|
||||||
break;
|
break;
|
||||||
@ -458,7 +455,7 @@ timestamptz_in(PG_FUNCTION_ARGS)
|
|||||||
TIMESTAMP_NOEND(result);
|
TIMESTAMP_NOEND(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
AdjustTimestampForTypmod(&result, typmod);
|
AdjustTimestampForTypmod(&result, typmod, escontext);
|
||||||
|
|
||||||
PG_RETURN_TIMESTAMPTZ(result);
|
PG_RETURN_TIMESTAMPTZ(result);
|
||||||
}
|
}
|
||||||
@ -525,7 +522,7 @@ parse_sane_timezone(struct pg_tm *tm, text *zone)
|
|||||||
false);
|
false);
|
||||||
dterr = DecodeTimezoneAbbrev(0, lowzone, &type, &val, &tzp, &extra);
|
dterr = DecodeTimezoneAbbrev(0, lowzone, &type, &val, &tzp, &extra);
|
||||||
if (dterr)
|
if (dterr)
|
||||||
DateTimeParseError(dterr, &extra, NULL, NULL);
|
DateTimeParseError(dterr, &extra, NULL, NULL, NULL);
|
||||||
|
|
||||||
if (type == TZ || type == DTZ)
|
if (type == TZ || type == DTZ)
|
||||||
{
|
{
|
||||||
@ -824,7 +821,7 @@ timestamptz_recv(PG_FUNCTION_ARGS)
|
|||||||
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
||||||
errmsg("timestamp out of range")));
|
errmsg("timestamp out of range")));
|
||||||
|
|
||||||
AdjustTimestampForTypmod(×tamp, typmod);
|
AdjustTimestampForTypmod(×tamp, typmod, NULL);
|
||||||
|
|
||||||
PG_RETURN_TIMESTAMPTZ(timestamp);
|
PG_RETURN_TIMESTAMPTZ(timestamp);
|
||||||
}
|
}
|
||||||
@ -873,7 +870,7 @@ timestamptz_scale(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
result = timestamp;
|
result = timestamp;
|
||||||
|
|
||||||
AdjustTimestampForTypmod(&result, typmod);
|
AdjustTimestampForTypmod(&result, typmod, NULL);
|
||||||
|
|
||||||
PG_RETURN_TIMESTAMPTZ(result);
|
PG_RETURN_TIMESTAMPTZ(result);
|
||||||
}
|
}
|
||||||
@ -889,11 +886,11 @@ Datum
|
|||||||
interval_in(PG_FUNCTION_ARGS)
|
interval_in(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
char *str = PG_GETARG_CSTRING(0);
|
char *str = PG_GETARG_CSTRING(0);
|
||||||
|
|
||||||
#ifdef NOT_USED
|
#ifdef NOT_USED
|
||||||
Oid typelem = PG_GETARG_OID(1);
|
Oid typelem = PG_GETARG_OID(1);
|
||||||
#endif
|
#endif
|
||||||
int32 typmod = PG_GETARG_INT32(2);
|
int32 typmod = PG_GETARG_INT32(2);
|
||||||
|
Node *escontext = fcinfo->context;
|
||||||
Interval *result;
|
Interval *result;
|
||||||
struct pg_itm_in tt,
|
struct pg_itm_in tt,
|
||||||
*itm_in = &tt;
|
*itm_in = &tt;
|
||||||
@ -931,7 +928,8 @@ interval_in(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
if (dterr == DTERR_FIELD_OVERFLOW)
|
if (dterr == DTERR_FIELD_OVERFLOW)
|
||||||
dterr = DTERR_INTERVAL_OVERFLOW;
|
dterr = DTERR_INTERVAL_OVERFLOW;
|
||||||
DateTimeParseError(dterr, &extra, str, "interval");
|
DateTimeParseError(dterr, &extra, str, "interval", escontext);
|
||||||
|
PG_RETURN_NULL();
|
||||||
}
|
}
|
||||||
|
|
||||||
result = (Interval *) palloc(sizeof(Interval));
|
result = (Interval *) palloc(sizeof(Interval));
|
||||||
@ -940,7 +938,7 @@ interval_in(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
case DTK_DELTA:
|
case DTK_DELTA:
|
||||||
if (itmin2interval(itm_in, result) != 0)
|
if (itmin2interval(itm_in, result) != 0)
|
||||||
ereport(ERROR,
|
ereturn(escontext, (Datum) 0,
|
||||||
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
||||||
errmsg("interval out of range")));
|
errmsg("interval out of range")));
|
||||||
break;
|
break;
|
||||||
@ -950,7 +948,7 @@ interval_in(PG_FUNCTION_ARGS)
|
|||||||
dtype, str);
|
dtype, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
AdjustIntervalForTypmod(result, typmod);
|
AdjustIntervalForTypmod(result, typmod, escontext);
|
||||||
|
|
||||||
PG_RETURN_INTERVAL_P(result);
|
PG_RETURN_INTERVAL_P(result);
|
||||||
}
|
}
|
||||||
@ -994,7 +992,7 @@ interval_recv(PG_FUNCTION_ARGS)
|
|||||||
interval->day = pq_getmsgint(buf, sizeof(interval->day));
|
interval->day = pq_getmsgint(buf, sizeof(interval->day));
|
||||||
interval->month = pq_getmsgint(buf, sizeof(interval->month));
|
interval->month = pq_getmsgint(buf, sizeof(interval->month));
|
||||||
|
|
||||||
AdjustIntervalForTypmod(interval, typmod);
|
AdjustIntervalForTypmod(interval, typmod, NULL);
|
||||||
|
|
||||||
PG_RETURN_INTERVAL_P(interval);
|
PG_RETURN_INTERVAL_P(interval);
|
||||||
}
|
}
|
||||||
@ -1318,7 +1316,7 @@ interval_scale(PG_FUNCTION_ARGS)
|
|||||||
result = palloc(sizeof(Interval));
|
result = palloc(sizeof(Interval));
|
||||||
*result = *interval;
|
*result = *interval;
|
||||||
|
|
||||||
AdjustIntervalForTypmod(result, typmod);
|
AdjustIntervalForTypmod(result, typmod, NULL);
|
||||||
|
|
||||||
PG_RETURN_INTERVAL_P(result);
|
PG_RETURN_INTERVAL_P(result);
|
||||||
}
|
}
|
||||||
@ -1326,9 +1324,13 @@ interval_scale(PG_FUNCTION_ARGS)
|
|||||||
/*
|
/*
|
||||||
* Adjust interval for specified precision, in both YEAR to SECOND
|
* Adjust interval for specified precision, in both YEAR to SECOND
|
||||||
* range and sub-second precision.
|
* range and sub-second precision.
|
||||||
|
*
|
||||||
|
* Returns true on success, false on failure (if escontext points to an
|
||||||
|
* ErrorSaveContext; otherwise errors are thrown).
|
||||||
*/
|
*/
|
||||||
static void
|
static bool
|
||||||
AdjustIntervalForTypmod(Interval *interval, int32 typmod)
|
AdjustIntervalForTypmod(Interval *interval, int32 typmod,
|
||||||
|
Node *escontext)
|
||||||
{
|
{
|
||||||
static const int64 IntervalScales[MAX_INTERVAL_PRECISION + 1] = {
|
static const int64 IntervalScales[MAX_INTERVAL_PRECISION + 1] = {
|
||||||
INT64CONST(1000000),
|
INT64CONST(1000000),
|
||||||
@ -1468,7 +1470,7 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod)
|
|||||||
if (precision != INTERVAL_FULL_PRECISION)
|
if (precision != INTERVAL_FULL_PRECISION)
|
||||||
{
|
{
|
||||||
if (precision < 0 || precision > MAX_INTERVAL_PRECISION)
|
if (precision < 0 || precision > MAX_INTERVAL_PRECISION)
|
||||||
ereport(ERROR,
|
ereturn(escontext, false,
|
||||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||||
errmsg("interval(%d) precision must be between %d and %d",
|
errmsg("interval(%d) precision must be between %d and %d",
|
||||||
precision, 0, MAX_INTERVAL_PRECISION)));
|
precision, 0, MAX_INTERVAL_PRECISION)));
|
||||||
@ -1489,6 +1491,8 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1609,7 +1613,7 @@ current_timestamp(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
ts = GetCurrentTransactionStartTimestamp();
|
ts = GetCurrentTransactionStartTimestamp();
|
||||||
if (typmod >= 0)
|
if (typmod >= 0)
|
||||||
AdjustTimestampForTypmod(&ts, typmod);
|
AdjustTimestampForTypmod(&ts, typmod, NULL);
|
||||||
return TimestampTzGetDatum(ts);
|
return TimestampTzGetDatum(ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1630,7 +1634,7 @@ sql_localtimestamp(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
ts = timestamptz2timestamp(GetCurrentTransactionStartTimestamp());
|
ts = timestamptz2timestamp(GetCurrentTransactionStartTimestamp());
|
||||||
if (typmod >= 0)
|
if (typmod >= 0)
|
||||||
AdjustTimestampForTypmod(&ts, typmod);
|
AdjustTimestampForTypmod(&ts, typmod, NULL);
|
||||||
return TimestampGetDatum(ts);
|
return TimestampGetDatum(ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4324,7 +4328,7 @@ timestamptz_trunc_zone(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
dterr = DecodeTimezoneAbbrev(0, lowzone, &type, &val, &tzp, &extra);
|
dterr = DecodeTimezoneAbbrev(0, lowzone, &type, &val, &tzp, &extra);
|
||||||
if (dterr)
|
if (dterr)
|
||||||
DateTimeParseError(dterr, &extra, NULL, NULL);
|
DateTimeParseError(dterr, &extra, NULL, NULL, NULL);
|
||||||
|
|
||||||
if (type == TZ || type == DTZ)
|
if (type == TZ || type == DTZ)
|
||||||
{
|
{
|
||||||
@ -5452,7 +5456,7 @@ timestamp_zone(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
dterr = DecodeTimezoneAbbrev(0, lowzone, &type, &val, &tzp, &extra);
|
dterr = DecodeTimezoneAbbrev(0, lowzone, &type, &val, &tzp, &extra);
|
||||||
if (dterr)
|
if (dterr)
|
||||||
DateTimeParseError(dterr, &extra, NULL, NULL);
|
DateTimeParseError(dterr, &extra, NULL, NULL, NULL);
|
||||||
|
|
||||||
if (type == TZ || type == DTZ)
|
if (type == TZ || type == DTZ)
|
||||||
{
|
{
|
||||||
@ -5708,7 +5712,7 @@ timestamptz_zone(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
dterr = DecodeTimezoneAbbrev(0, lowzone, &type, &val, &tzp, &extra);
|
dterr = DecodeTimezoneAbbrev(0, lowzone, &type, &val, &tzp, &extra);
|
||||||
if (dterr)
|
if (dterr)
|
||||||
DateTimeParseError(dterr, &extra, NULL, NULL);
|
DateTimeParseError(dterr, &extra, NULL, NULL, NULL);
|
||||||
|
|
||||||
if (type == TZ || type == DTZ)
|
if (type == TZ || type == DTZ)
|
||||||
{
|
{
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
#ifndef DATETIME_H
|
#ifndef DATETIME_H
|
||||||
#define DATETIME_H
|
#define DATETIME_H
|
||||||
|
|
||||||
#include "nodes/nodes.h"
|
|
||||||
#include "utils/timestamp.h"
|
#include "utils/timestamp.h"
|
||||||
|
|
||||||
/* this struct is declared in utils/tzparser.h: */
|
/* this struct is declared in utils/tzparser.h: */
|
||||||
@ -318,8 +317,8 @@ extern int DecodeISO8601Interval(char *str,
|
|||||||
int *dtype, struct pg_itm_in *itm_in);
|
int *dtype, struct pg_itm_in *itm_in);
|
||||||
|
|
||||||
extern void DateTimeParseError(int dterr, DateTimeErrorExtra *extra,
|
extern void DateTimeParseError(int dterr, DateTimeErrorExtra *extra,
|
||||||
const char *str,
|
const char *str, const char *datatype,
|
||||||
const char *datatype) pg_attribute_noreturn();
|
struct Node *escontext);
|
||||||
|
|
||||||
extern int DetermineTimeZoneOffset(struct pg_tm *tm, pg_tz *tzp);
|
extern int DetermineTimeZoneOffset(struct pg_tm *tm, pg_tz *tzp);
|
||||||
extern int DetermineTimeZoneAbbrevOffset(struct pg_tm *tm, const char *abbr, pg_tz *tzp);
|
extern int DetermineTimeZoneAbbrevOffset(struct pg_tm *tm, const char *abbr, pg_tz *tzp);
|
||||||
@ -343,7 +342,7 @@ extern int DecodeUnits(int field, const char *lowtoken, int *val);
|
|||||||
|
|
||||||
extern int j2day(int date);
|
extern int j2day(int date);
|
||||||
|
|
||||||
extern Node *TemporalSimplify(int32 max_precis, Node *node);
|
extern struct Node *TemporalSimplify(int32 max_precis, struct Node *node);
|
||||||
|
|
||||||
extern bool CheckDateTokenTables(void);
|
extern bool CheckDateTokenTables(void);
|
||||||
|
|
||||||
@ -351,8 +350,7 @@ extern TimeZoneAbbrevTable *ConvertTimeZoneAbbrevs(struct tzEntry *abbrevs,
|
|||||||
int n);
|
int n);
|
||||||
extern void InstallTimeZoneAbbrevs(TimeZoneAbbrevTable *tbl);
|
extern void InstallTimeZoneAbbrevs(TimeZoneAbbrevTable *tbl);
|
||||||
|
|
||||||
extern void AdjustTimestampForTypmod(Timestamp *time, int32 typmod);
|
extern bool AdjustTimestampForTypmod(Timestamp *time, int32 typmod,
|
||||||
extern bool AdjustTimestampForTypmodError(Timestamp *time, int32 typmod,
|
struct Node *escontext);
|
||||||
bool *error);
|
|
||||||
|
|
||||||
#endif /* DATETIME_H */
|
#endif /* DATETIME_H */
|
||||||
|
@ -840,6 +840,37 @@ SELECT date '5874898-01-01'; -- out of range
|
|||||||
ERROR: date out of range: "5874898-01-01"
|
ERROR: date out of range: "5874898-01-01"
|
||||||
LINE 1: SELECT date '5874898-01-01';
|
LINE 1: SELECT date '5874898-01-01';
|
||||||
^
|
^
|
||||||
|
-- Test non-error-throwing API
|
||||||
|
SELECT pg_input_is_valid('now', 'date');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
t
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_is_valid('garbage', 'date');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_is_valid('6874898-01-01', 'date');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_error_message('garbage', 'date');
|
||||||
|
pg_input_error_message
|
||||||
|
-----------------------------------------------
|
||||||
|
invalid input syntax for type date: "garbage"
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_error_message('6874898-01-01', 'date');
|
||||||
|
pg_input_error_message
|
||||||
|
------------------------------------
|
||||||
|
date out of range: "6874898-01-01"
|
||||||
|
(1 row)
|
||||||
|
|
||||||
RESET datestyle;
|
RESET datestyle;
|
||||||
--
|
--
|
||||||
-- Simple math
|
-- Simple math
|
||||||
|
@ -72,6 +72,37 @@ INSERT INTO INTERVAL_TBL (f1) VALUES ('@ 30 eons ago');
|
|||||||
ERROR: invalid input syntax for type interval: "@ 30 eons ago"
|
ERROR: invalid input syntax for type interval: "@ 30 eons ago"
|
||||||
LINE 1: INSERT INTO INTERVAL_TBL (f1) VALUES ('@ 30 eons ago');
|
LINE 1: INSERT INTO INTERVAL_TBL (f1) VALUES ('@ 30 eons ago');
|
||||||
^
|
^
|
||||||
|
-- Test non-error-throwing API
|
||||||
|
SELECT pg_input_is_valid('1.5 weeks', 'interval');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
t
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_is_valid('garbage', 'interval');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_is_valid('@ 30 eons ago', 'interval');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_error_message('garbage', 'interval');
|
||||||
|
pg_input_error_message
|
||||||
|
---------------------------------------------------
|
||||||
|
invalid input syntax for type interval: "garbage"
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_error_message('@ 30 eons ago', 'interval');
|
||||||
|
pg_input_error_message
|
||||||
|
---------------------------------------------------------
|
||||||
|
invalid input syntax for type interval: "@ 30 eons ago"
|
||||||
|
(1 row)
|
||||||
|
|
||||||
-- test interval operators
|
-- test interval operators
|
||||||
SELECT * FROM INTERVAL_TBL;
|
SELECT * FROM INTERVAL_TBL;
|
||||||
f1
|
f1
|
||||||
|
@ -114,6 +114,37 @@ SELECT '25:00:00'::time; -- not allowed
|
|||||||
ERROR: date/time field value out of range: "25:00:00"
|
ERROR: date/time field value out of range: "25:00:00"
|
||||||
LINE 1: SELECT '25:00:00'::time;
|
LINE 1: SELECT '25:00:00'::time;
|
||||||
^
|
^
|
||||||
|
-- Test non-error-throwing API
|
||||||
|
SELECT pg_input_is_valid('12:00:00', 'time');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
t
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_is_valid('25:00:00', 'time');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_is_valid('15:36:39 America/New_York', 'time');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_error_message('25:00:00', 'time');
|
||||||
|
pg_input_error_message
|
||||||
|
------------------------------------------------
|
||||||
|
date/time field value out of range: "25:00:00"
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_error_message('15:36:39 America/New_York', 'time');
|
||||||
|
pg_input_error_message
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
invalid input syntax for type time: "15:36:39 America/New_York"
|
||||||
|
(1 row)
|
||||||
|
|
||||||
--
|
--
|
||||||
-- TIME simple math
|
-- TIME simple math
|
||||||
--
|
--
|
||||||
|
@ -119,6 +119,37 @@ INSERT INTO TIMESTAMP_TBL VALUES ('19970710 173201 America/Does_not_exist');
|
|||||||
ERROR: time zone "america/does_not_exist" not recognized
|
ERROR: time zone "america/does_not_exist" not recognized
|
||||||
LINE 1: INSERT INTO TIMESTAMP_TBL VALUES ('19970710 173201 America/D...
|
LINE 1: INSERT INTO TIMESTAMP_TBL VALUES ('19970710 173201 America/D...
|
||||||
^
|
^
|
||||||
|
-- Test non-error-throwing API
|
||||||
|
SELECT pg_input_is_valid('now', 'timestamp');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
t
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_is_valid('garbage', 'timestamp');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_is_valid('2001-01-01 00:00 Nehwon/Lankhmar', 'timestamp');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_error_message('garbage', 'timestamp');
|
||||||
|
pg_input_error_message
|
||||||
|
----------------------------------------------------
|
||||||
|
invalid input syntax for type timestamp: "garbage"
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_error_message('2001-01-01 00:00 Nehwon/Lankhmar', 'timestamp');
|
||||||
|
pg_input_error_message
|
||||||
|
--------------------------------------------
|
||||||
|
time zone "nehwon/lankhmar" not recognized
|
||||||
|
(1 row)
|
||||||
|
|
||||||
-- Check date conversion and date arithmetic
|
-- Check date conversion and date arithmetic
|
||||||
INSERT INTO TIMESTAMP_TBL VALUES ('1997-06-10 18:32:01 PDT');
|
INSERT INTO TIMESTAMP_TBL VALUES ('1997-06-10 18:32:01 PDT');
|
||||||
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 10 17:32:01 1997');
|
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 10 17:32:01 1997');
|
||||||
|
@ -170,6 +170,37 @@ SELECT '205000-01-10 17:32:01 Europe/Helsinki'::timestamptz; -- non-DST
|
|||||||
Fri Jan 10 07:32:01 205000 PST
|
Fri Jan 10 07:32:01 205000 PST
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
-- Test non-error-throwing API
|
||||||
|
SELECT pg_input_is_valid('now', 'timestamptz');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
t
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_is_valid('garbage', 'timestamptz');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_is_valid('2001-01-01 00:00 Nehwon/Lankhmar', 'timestamptz');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_error_message('garbage', 'timestamptz');
|
||||||
|
pg_input_error_message
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
invalid input syntax for type timestamp with time zone: "garbage"
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_error_message('2001-01-01 00:00 Nehwon/Lankhmar', 'timestamptz');
|
||||||
|
pg_input_error_message
|
||||||
|
--------------------------------------------
|
||||||
|
time zone "nehwon/lankhmar" not recognized
|
||||||
|
(1 row)
|
||||||
|
|
||||||
-- Check date conversion and date arithmetic
|
-- Check date conversion and date arithmetic
|
||||||
INSERT INTO TIMESTAMPTZ_TBL VALUES ('1997-06-10 18:32:01 PDT');
|
INSERT INTO TIMESTAMPTZ_TBL VALUES ('1997-06-10 18:32:01 PDT');
|
||||||
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 10 17:32:01 1997');
|
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 10 17:32:01 1997');
|
||||||
|
@ -131,6 +131,37 @@ SELECT '25:00:00 PDT'::timetz; -- not allowed
|
|||||||
ERROR: date/time field value out of range: "25:00:00 PDT"
|
ERROR: date/time field value out of range: "25:00:00 PDT"
|
||||||
LINE 1: SELECT '25:00:00 PDT'::timetz;
|
LINE 1: SELECT '25:00:00 PDT'::timetz;
|
||||||
^
|
^
|
||||||
|
-- Test non-error-throwing API
|
||||||
|
SELECT pg_input_is_valid('12:00:00 PDT', 'timetz');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
t
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_is_valid('25:00:00 PDT', 'timetz');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_is_valid('15:36:39 America/New_York', 'timetz');
|
||||||
|
pg_input_is_valid
|
||||||
|
-------------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_error_message('25:00:00 PDT', 'timetz');
|
||||||
|
pg_input_error_message
|
||||||
|
----------------------------------------------------
|
||||||
|
date/time field value out of range: "25:00:00 PDT"
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_input_error_message('15:36:39 America/New_York', 'timetz');
|
||||||
|
pg_input_error_message
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
invalid input syntax for type time with time zone: "15:36:39 America/New_York"
|
||||||
|
(1 row)
|
||||||
|
|
||||||
--
|
--
|
||||||
-- TIME simple math
|
-- TIME simple math
|
||||||
--
|
--
|
||||||
|
@ -193,6 +193,13 @@ SELECT date '4714-11-23 BC'; -- out of range
|
|||||||
SELECT date '5874897-12-31';
|
SELECT date '5874897-12-31';
|
||||||
SELECT date '5874898-01-01'; -- out of range
|
SELECT date '5874898-01-01'; -- out of range
|
||||||
|
|
||||||
|
-- Test non-error-throwing API
|
||||||
|
SELECT pg_input_is_valid('now', 'date');
|
||||||
|
SELECT pg_input_is_valid('garbage', 'date');
|
||||||
|
SELECT pg_input_is_valid('6874898-01-01', 'date');
|
||||||
|
SELECT pg_input_error_message('garbage', 'date');
|
||||||
|
SELECT pg_input_error_message('6874898-01-01', 'date');
|
||||||
|
|
||||||
RESET datestyle;
|
RESET datestyle;
|
||||||
|
|
||||||
--
|
--
|
||||||
|
@ -32,6 +32,13 @@ INSERT INTO INTERVAL_TBL (f1) VALUES ('5 months 12 hours');
|
|||||||
INSERT INTO INTERVAL_TBL (f1) VALUES ('badly formatted interval');
|
INSERT INTO INTERVAL_TBL (f1) VALUES ('badly formatted interval');
|
||||||
INSERT INTO INTERVAL_TBL (f1) VALUES ('@ 30 eons ago');
|
INSERT INTO INTERVAL_TBL (f1) VALUES ('@ 30 eons ago');
|
||||||
|
|
||||||
|
-- Test non-error-throwing API
|
||||||
|
SELECT pg_input_is_valid('1.5 weeks', 'interval');
|
||||||
|
SELECT pg_input_is_valid('garbage', 'interval');
|
||||||
|
SELECT pg_input_is_valid('@ 30 eons ago', 'interval');
|
||||||
|
SELECT pg_input_error_message('garbage', 'interval');
|
||||||
|
SELECT pg_input_error_message('@ 30 eons ago', 'interval');
|
||||||
|
|
||||||
-- test interval operators
|
-- test interval operators
|
||||||
|
|
||||||
SELECT * FROM INTERVAL_TBL;
|
SELECT * FROM INTERVAL_TBL;
|
||||||
|
@ -40,6 +40,13 @@ SELECT '23:59:60.01'::time; -- not allowed
|
|||||||
SELECT '24:01:00'::time; -- not allowed
|
SELECT '24:01:00'::time; -- not allowed
|
||||||
SELECT '25:00:00'::time; -- not allowed
|
SELECT '25:00:00'::time; -- not allowed
|
||||||
|
|
||||||
|
-- Test non-error-throwing API
|
||||||
|
SELECT pg_input_is_valid('12:00:00', 'time');
|
||||||
|
SELECT pg_input_is_valid('25:00:00', 'time');
|
||||||
|
SELECT pg_input_is_valid('15:36:39 America/New_York', 'time');
|
||||||
|
SELECT pg_input_error_message('25:00:00', 'time');
|
||||||
|
SELECT pg_input_error_message('15:36:39 America/New_York', 'time');
|
||||||
|
|
||||||
--
|
--
|
||||||
-- TIME simple math
|
-- TIME simple math
|
||||||
--
|
--
|
||||||
|
@ -94,6 +94,13 @@ INSERT INTO TIMESTAMP_TBL VALUES ('19970210 173201 America/New_York');
|
|||||||
-- this fails (even though TZ is a no-op, we still look it up)
|
-- this fails (even though TZ is a no-op, we still look it up)
|
||||||
INSERT INTO TIMESTAMP_TBL VALUES ('19970710 173201 America/Does_not_exist');
|
INSERT INTO TIMESTAMP_TBL VALUES ('19970710 173201 America/Does_not_exist');
|
||||||
|
|
||||||
|
-- Test non-error-throwing API
|
||||||
|
SELECT pg_input_is_valid('now', 'timestamp');
|
||||||
|
SELECT pg_input_is_valid('garbage', 'timestamp');
|
||||||
|
SELECT pg_input_is_valid('2001-01-01 00:00 Nehwon/Lankhmar', 'timestamp');
|
||||||
|
SELECT pg_input_error_message('garbage', 'timestamp');
|
||||||
|
SELECT pg_input_error_message('2001-01-01 00:00 Nehwon/Lankhmar', 'timestamp');
|
||||||
|
|
||||||
-- Check date conversion and date arithmetic
|
-- Check date conversion and date arithmetic
|
||||||
INSERT INTO TIMESTAMP_TBL VALUES ('1997-06-10 18:32:01 PDT');
|
INSERT INTO TIMESTAMP_TBL VALUES ('1997-06-10 18:32:01 PDT');
|
||||||
|
|
||||||
|
@ -107,6 +107,13 @@ SELECT '20500110 173201 Europe/Helsinki'::timestamptz; -- non-DST
|
|||||||
SELECT '205000-07-10 17:32:01 Europe/Helsinki'::timestamptz; -- DST
|
SELECT '205000-07-10 17:32:01 Europe/Helsinki'::timestamptz; -- DST
|
||||||
SELECT '205000-01-10 17:32:01 Europe/Helsinki'::timestamptz; -- non-DST
|
SELECT '205000-01-10 17:32:01 Europe/Helsinki'::timestamptz; -- non-DST
|
||||||
|
|
||||||
|
-- Test non-error-throwing API
|
||||||
|
SELECT pg_input_is_valid('now', 'timestamptz');
|
||||||
|
SELECT pg_input_is_valid('garbage', 'timestamptz');
|
||||||
|
SELECT pg_input_is_valid('2001-01-01 00:00 Nehwon/Lankhmar', 'timestamptz');
|
||||||
|
SELECT pg_input_error_message('garbage', 'timestamptz');
|
||||||
|
SELECT pg_input_error_message('2001-01-01 00:00 Nehwon/Lankhmar', 'timestamptz');
|
||||||
|
|
||||||
-- Check date conversion and date arithmetic
|
-- Check date conversion and date arithmetic
|
||||||
INSERT INTO TIMESTAMPTZ_TBL VALUES ('1997-06-10 18:32:01 PDT');
|
INSERT INTO TIMESTAMPTZ_TBL VALUES ('1997-06-10 18:32:01 PDT');
|
||||||
|
|
||||||
|
@ -45,6 +45,13 @@ SELECT '23:59:60.01 PDT'::timetz; -- not allowed
|
|||||||
SELECT '24:01:00 PDT'::timetz; -- not allowed
|
SELECT '24:01:00 PDT'::timetz; -- not allowed
|
||||||
SELECT '25:00:00 PDT'::timetz; -- not allowed
|
SELECT '25:00:00 PDT'::timetz; -- not allowed
|
||||||
|
|
||||||
|
-- Test non-error-throwing API
|
||||||
|
SELECT pg_input_is_valid('12:00:00 PDT', 'timetz');
|
||||||
|
SELECT pg_input_is_valid('25:00:00 PDT', 'timetz');
|
||||||
|
SELECT pg_input_is_valid('15:36:39 America/New_York', 'timetz');
|
||||||
|
SELECT pg_input_error_message('25:00:00 PDT', 'timetz');
|
||||||
|
SELECT pg_input_error_message('15:36:39 America/New_York', 'timetz');
|
||||||
|
|
||||||
--
|
--
|
||||||
-- TIME simple math
|
-- TIME simple math
|
||||||
--
|
--
|
||||||
|
Loading…
x
Reference in New Issue
Block a user