summaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/timestamp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/timestamp.c')
-rw-r--r--src/backend/utils/adt/timestamp.c66
1 files changed, 49 insertions, 17 deletions
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index 2931bd58c0d..84bc97d40c3 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -329,11 +329,11 @@ timestamp_scale(PG_FUNCTION_ARGS)
}
/*
- * AdjustTimestampForTypmod --- round off a timestamp to suit given typmod
+ * AdjustTimestampForTypmodError --- round off a timestamp to suit given typmod
* Works for either timestamp or timestamptz.
*/
-void
-AdjustTimestampForTypmod(Timestamp *time, int32 typmod)
+bool
+AdjustTimestampForTypmodError(Timestamp *time, int32 typmod, bool *error)
{
static const int64 TimestampScales[MAX_TIMESTAMP_PRECISION + 1] = {
INT64CONST(1000000),
@@ -359,10 +359,18 @@ AdjustTimestampForTypmod(Timestamp *time, int32 typmod)
&& (typmod != -1) && (typmod != MAX_TIMESTAMP_PRECISION))
{
if (typmod < 0 || typmod > MAX_TIMESTAMP_PRECISION)
+ {
+ if (error)
+ {
+ *error = true;
+ return false;
+ }
+
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("timestamp(%d) precision must be between %d and %d",
typmod, 0, MAX_TIMESTAMP_PRECISION)));
+ }
if (*time >= INT64CONST(0))
{
@@ -375,8 +383,15 @@ AdjustTimestampForTypmod(Timestamp *time, int32 typmod)
* TimestampScales[typmod]);
}
}
+
+ return true;
}
+void
+AdjustTimestampForTypmod(Timestamp *time, int32 typmod)
+{
+ (void) AdjustTimestampForTypmodError(time, typmod, NULL);
+}
/* timestamptz_in()
* Convert a string to internal form.
@@ -5172,8 +5187,15 @@ timestamp_timestamptz(PG_FUNCTION_ARGS)
PG_RETURN_TIMESTAMPTZ(timestamp2timestamptz(timestamp));
}
-static TimestampTz
-timestamp2timestamptz(Timestamp timestamp)
+/*
+ * Convert timestamp to timestamp with time zone.
+ *
+ * If 'have_error' is NULL, then errors are thrown, else '*have_error' is set
+ * and zero is returned.
+ */
+
+TimestampTz
+timestamp2timestamptz_opt_error(Timestamp timestamp, bool *have_error)
{
TimestampTz result;
struct pg_tm tt,
@@ -5182,23 +5204,33 @@ timestamp2timestamptz(Timestamp timestamp)
int tz;
if (TIMESTAMP_NOT_FINITE(timestamp))
- result = timestamp;
- else
- {
- if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
- ereport(ERROR,
- (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
- errmsg("timestamp out of range")));
+ return timestamp;
+ if (!timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL))
+ {
tz = DetermineTimeZoneOffset(tm, session_timezone);
- if (tm2timestamp(tm, fsec, &tz, &result) != 0)
- ereport(ERROR,
- (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
- errmsg("timestamp out of range")));
+ if (!tm2timestamp(tm, fsec, &tz, &result))
+ return result;
}
- return result;
+ if (have_error)
+ *have_error = true;
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+ errmsg("timestamp out of range")));
+
+ return 0;
+}
+
+/*
+ * Single-argument version of timestamp2timestamptz_opt_error().
+ */
+static TimestampTz
+timestamp2timestamptz(Timestamp timestamp)
+{
+ return timestamp2timestamptz_opt_error(timestamp, NULL);
}
/* timestamptz_timestamp()