summaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/date.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/date.c')
-rw-r--r--src/backend/utils/adt/date.c89
1 files changed, 88 insertions, 1 deletions
diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c
index 9efc7125b1..e2781dec48 100644
--- a/src/backend/utils/adt/date.c
+++ b/src/backend/utils/adt/date.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.125 2006/07/14 14:52:23 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.126 2006/12/30 21:21:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -24,6 +24,7 @@
#include "libpq/pqformat.h"
#include "miscadmin.h"
#include "parser/scansup.h"
+#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/date.h"
#include "utils/nabstime.h"
@@ -43,6 +44,60 @@ static int tm2time(struct pg_tm * tm, fsec_t fsec, TimeADT *result);
static int tm2timetz(struct pg_tm * tm, fsec_t fsec, int tz, TimeTzADT *result);
static void AdjustTimeForTypmod(TimeADT *time, int32 typmod);
+
+/* common code for timetypmodin and timetztypmodin */
+static int32
+anytime_typmodin(bool istz, ArrayType *ta)
+{
+ int32 typmod;
+ int32 *tl;
+ int n;
+
+ tl = ArrayGetTypmods(ta, &n);
+
+ /*
+ * we're not too tense about good error message here because grammar
+ * shouldn't allow wrong number of modifiers for TIME
+ */
+ if (n != 1)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid type modifier")));
+
+ if (*tl < 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("TIME(%d)%s precision must not be negative",
+ *tl, (istz ? " WITH TIME ZONE" : ""))));
+ if (*tl > MAX_TIME_PRECISION)
+ {
+ ereport(WARNING,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("TIME(%d)%s precision reduced to maximum allowed, %d",
+ *tl, (istz ? " WITH TIME ZONE" : "" ),
+ MAX_TIME_PRECISION)));
+ typmod = MAX_TIME_PRECISION;
+ } else
+ typmod = *tl;
+
+ return typmod;
+}
+
+/* common code for timetypmodout and timetztypmodout */
+static char *
+anytime_typmodout(bool istz, int32 typmod)
+{
+ char *res = (char *) palloc(64);
+ const char *tz = istz ? " with time zone" : " without time zone";
+
+ if (typmod >= 0)
+ snprintf(res, 64, "(%d)%s", (int) typmod, tz);
+ else
+ snprintf(res, 64, "%s", tz);
+ return res;
+}
+
+
/*****************************************************************************
* Date ADT
*****************************************************************************/
@@ -1029,6 +1084,22 @@ time_send(PG_FUNCTION_ARGS)
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}
+Datum
+timetypmodin(PG_FUNCTION_ARGS)
+{
+ ArrayType *ta = PG_GETARG_ARRAYTYPE_P(0);
+
+ PG_RETURN_INT32(anytime_typmodin(false, ta));
+}
+
+Datum
+timetypmodout(PG_FUNCTION_ARGS)
+{
+ int32 typmod = PG_GETARG_INT32(0);
+
+ PG_RETURN_CSTRING(anytime_typmodout(false, typmod));
+}
+
/* time_scale()
* Adjust time type for specified scale factor.
@@ -1830,6 +1901,22 @@ timetz_send(PG_FUNCTION_ARGS)
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}
+Datum
+timetztypmodin(PG_FUNCTION_ARGS)
+{
+ ArrayType *ta = PG_GETARG_ARRAYTYPE_P(0);
+
+ PG_RETURN_INT32(anytime_typmodin(true, ta));
+}
+
+Datum
+timetztypmodout(PG_FUNCTION_ARGS)
+{
+ int32 typmod = PG_GETARG_INT32(0);
+
+ PG_RETURN_CSTRING(anytime_typmodout(true, typmod));
+}
+
/* timetz2tm()
* Convert TIME WITH TIME ZONE data type to POSIX time structure.