aboutsummaryrefslogtreecommitdiff
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.c102
1 files changed, 80 insertions, 22 deletions
diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c
index 06d0e3abe95..4b9d0f15e6d 100644
--- a/src/backend/utils/adt/date.c
+++ b/src/backend/utils/adt/date.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.69 2002/06/20 20:29:36 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.70 2002/08/04 06:44:47 thomas Exp $
*
*-------------------------------------------------------------------------
*/
@@ -57,6 +57,9 @@ date_in(PG_FUNCTION_ARGS)
int ftype[MAXDATEFIELDS];
char lowstr[MAXDATELEN + 1];
+ if (strlen(str) >= sizeof(lowstr))
+ elog(ERROR, "Bad date external representation (too long) '%s'", str);
+
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
|| (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tzp) != 0))
elog(ERROR, "Bad date external representation '%s'", str);
@@ -518,6 +521,9 @@ time_in(PG_FUNCTION_ARGS)
int dtype;
int ftype[MAXDATEFIELDS];
+ if (strlen(str) >= sizeof(lowstr))
+ elog(ERROR, "Bad time external representation (too long) '%s'", str);
+
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
|| (DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec, NULL) != 0))
elog(ERROR, "Bad time external representation '%s'", str);
@@ -606,37 +612,85 @@ time_scale(PG_FUNCTION_ARGS)
PG_RETURN_TIMEADT(result);
}
+/* AdjustTimeForTypmod()
+ * Force the precision of the time value to a specified value.
+ * Uses *exactly* the same code as in AdjustTimestampForTypemod()
+ * but we make a separate copy because those types do not
+ * have a fundamental tie together but rather a coincidence of
+ * implementation. - thomas
+ */
static void
AdjustTimeForTypmod(TimeADT *time, int32 typmod)
{
- if ((typmod >= 0) && (typmod <= MAX_TIME_PRECISION))
- {
#ifdef HAVE_INT64_TIMESTAMP
- static int64 TimeScale = INT64CONST(1000000);
+ static const int64 TimeScales[MAX_TIMESTAMP_PRECISION+1] = {
+ INT64CONST(1000000),
+ INT64CONST(100000),
+ INT64CONST(10000),
+ INT64CONST(1000),
+ INT64CONST(100),
+ INT64CONST(10),
+ INT64CONST(1)
+ };
+
+ static const int64 TimeOffsets[MAX_TIMESTAMP_PRECISION+1] = {
+ INT64CONST(-500000),
+ INT64CONST(-50000),
+ INT64CONST(-5000),
+ INT64CONST(-500),
+ INT64CONST(-50),
+ INT64CONST(-5),
+ INT64CONST(0)
+ };
#else
- static double TimeScale = 1;
+ static const double TimeScales[MAX_TIMESTAMP_PRECISION+1] = {
+ 1,
+ 10,
+ 100,
+ 1000,
+ 10000,
+ 100000,
+ 1000000
+ };
+
+ static const double TimeOffsets[MAX_TIMESTAMP_PRECISION+1] = {
+ 0.5,
+ 0.05,
+ 0.005,
+ 0.0005,
+ 0.00005,
+ 0.000005,
+ 0.0000005
+ };
#endif
- static int32 TimeTypmod = 0;
- if (typmod != TimeTypmod)
- {
+ if ((typmod >= 0) && (typmod <= MAX_TIME_PRECISION))
+ {
#ifdef HAVE_INT64_TIMESTAMP
- TimeScale = pow(10.0, (MAX_TIME_PRECISION-typmod));
-#else
- TimeScale = pow(10.0, typmod);
-#endif
- TimeTypmod = typmod;
+ /* we have different truncation behavior depending on sign */
+ if (*time >= INT64CONST(0))
+ {
+ *time = ((*time / TimeScales[typmod])
+ * TimeScales[typmod]);
+ }
+ else
+ {
+ *time = (((*time + TimeOffsets[typmod]) / TimeScales[typmod])
+ * TimeScales[typmod]);
}
-
-#ifdef HAVE_INT64_TIMESTAMP
- *time = ((*time / TimeScale) * TimeScale);
- if (*time >= INT64CONST(86400000000))
- *time -= INT64CONST(86400000000);
#else
- *time = (rint(((double) *time) * TimeScale) / TimeScale);
-
- if (*time >= 86400)
- *time -= 86400;
+ /* we have different truncation behavior depending on sign */
+ if (*time >= 0)
+ {
+ *time = (rint(((double) *time) * TimeScales[typmod])
+ / TimeScales[typmod]);
+ }
+ else
+ {
+ /* Scale and truncate first, then add to help the rounding behavior */
+ *time = (rint((((double) *time) * TimeScales[typmod]) + TimeOffsets[typmod])
+ / TimeScales[typmod]);
+ }
#endif
}
@@ -1269,6 +1323,10 @@ timetz_in(PG_FUNCTION_ARGS)
int dtype;
int ftype[MAXDATEFIELDS];
+ if (strlen(str) >= sizeof(lowstr))
+ elog(ERROR, "Bad time with time zone"
+ " external representation (too long) '%s'", str);
+
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
|| (DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec, &tz) != 0))
elog(ERROR, "Bad time external representation '%s'", str);