X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Frrtimeslice.c;h=d9b82753227026e75713c55ec53f12d627385ef1;hb=5ff45cf49816b4839224edf89c59a5c77ceba4b5;hp=25e9cb38c1ce2caf73eb3b7e5d5e476e4d4eda3b;hpb=d55ee0b5c9e698724cc1048849542ca7fbd13d52;p=postrr.git diff --git a/src/rrtimeslice.c b/src/rrtimeslice.c index 25e9cb3..d9b8275 100644 --- a/src/rrtimeslice.c +++ b/src/rrtimeslice.c @@ -195,6 +195,43 @@ rrtimeslice_apply_typmod(rrtimeslice_t *tslice, int32 typmod) return 0; } /* rrtimeslice_apply_typmod */ +/* + * rrtimeslice_cmp_unify: + * Unify two RRTimeslices in order to prepare them for comparison. That is, if + * either one of the arguments does not have any typmod applied, then apply + * the typmod of the other argument. Throws an error if the typmods don't + * match. + * + * Returns: + * - 0 if the arguments could be unified + * - 1 if only the first argument is NULL + * - 2 if both arguments are NULL + * - 3 if only the second argument is NULL + */ +static int +rrtimeslice_cmp_unify(rrtimeslice_t *ts1, rrtimeslice_t *ts2) +{ + if ((! ts1) && (! ts2)) + return 0; + else if (! ts1) + return -1; + else if (! ts2) + return 1; + + if (ts1->tsid && (! ts2->tsid)) + rrtimeslice_apply_typmod(ts2, ts1->tsid); + else if ((! ts1->tsid) && ts2->tsid) + rrtimeslice_apply_typmod(ts1, ts2->tsid); + + if (ts1->tsid != ts2->tsid) /* XXX: compare len/num */ + ereport(ERROR, ( + errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid comparison: cannot compare " + "rrtimeslices with different typmods (yet)") + )); + return 0; +} /* rrtimeslice_cmp_unify */ + /* * prototypes for PostgreSQL functions */ @@ -207,8 +244,11 @@ PG_FUNCTION_INFO_V1(rrtimeslice_typmodin); PG_FUNCTION_INFO_V1(rrtimeslice_typmodout); PG_FUNCTION_INFO_V1(rrtimeslice_to_rrtimeslice); +PG_FUNCTION_INFO_V1(timestamptz_to_rrtimeslice); PG_FUNCTION_INFO_V1(rrtimeslice_to_timestamptz); +PG_FUNCTION_INFO_V1(rrtimeslice_cmp); + PG_FUNCTION_INFO_V1(rrtimeslice_seq_eq); PG_FUNCTION_INFO_V1(rrtimeslice_seq_ne); PG_FUNCTION_INFO_V1(rrtimeslice_seq_lt); @@ -334,7 +374,7 @@ rrtimeslice_out(PG_FUNCTION_ARGS) fsec_t fsec = 0; int tz = 0; - char *tz_str = NULL; + const char *tz_str = NULL; char ts_str[MAXDATELEN + 1]; char buf_l[MAXDATELEN + 1]; @@ -359,7 +399,7 @@ rrtimeslice_out(PG_FUNCTION_ARGS) errmsg("invalid (non-finite) timestamp") )); - EncodeDateTime(&tm, fsec, &tz, &tz_str, DateStyle, buf_u); + EncodeDateTime(&tm, fsec, 1, tz, tz_str, DateStyle, buf_u); if (! rrtimeslice_get_spec(tslice->tsid, &len, &num)) { TimestampTz lower = tslice->tstamp - (len * USECS_PER_SEC); @@ -370,7 +410,7 @@ rrtimeslice_out(PG_FUNCTION_ARGS) errmsg("invalid (non-finite) lower timestamp") )); - EncodeDateTime(&tm, fsec, &tz, &tz_str, DateStyle, buf_l); + EncodeDateTime(&tm, fsec, 1, tz, tz_str, DateStyle, buf_l); } else { strncpy(buf_l, "ERR", sizeof(buf_l)); @@ -472,6 +512,34 @@ rrtimeslice_to_rrtimeslice(PG_FUNCTION_ARGS) PG_RETURN_RRTIMESLICE_P(tslice); } /* rrtimeslice_to_rrtimeslice */ +Datum +timestamptz_to_rrtimeslice(PG_FUNCTION_ARGS) +{ + TimestampTz tstamp; + int32 typmod; + + rrtimeslice_t *tslice; + + if (PG_NARGS() != 3) + ereport(ERROR, ( + errmsg("timestamptz_to_rrtimeslice() " + "expects three arguments"), + errhint("Usage: timestamptz_to_rrtimeslice" + "(timestamptz, typmod, is_explicit)") + )); + + tstamp = PG_GETARG_TIMESTAMPTZ(0); + typmod = PG_GETARG_INT32(1); + + tslice = (rrtimeslice_t *)palloc0(sizeof(*tslice)); + + tslice->tstamp = tstamp; + if (typmod >= 0) + rrtimeslice_apply_typmod(tslice, typmod); + + PG_RETURN_RRTIMESLICE_P(tslice); +} /* timestamptz_to_rrtimeslice */ + Datum rrtimeslice_to_timestamptz(PG_FUNCTION_ARGS) { @@ -490,26 +558,43 @@ rrtimeslice_to_timestamptz(PG_FUNCTION_ARGS) } /* rrtimeslice_to_timestamptz */ int -rrtimeslice_seq_cmp_internal(rrtimeslice_t *ts1, rrtimeslice_t *ts2) +rrtimeslice_cmp_internal(rrtimeslice_t *ts1, rrtimeslice_t *ts2) { - if ((! ts1) && (! ts2)) + int status; + + status = rrtimeslice_cmp_unify(ts1, ts2); + if (status) /* [1, 3] -> [-1, 1] */ + return status - 2; + + if (ts1->tstamp == ts2->tstamp) return 0; - else if (! ts1) + else if ((ts1->seq == ts2->seq) && (ts1->tstamp < ts2->tstamp)) return -1; - else if (! ts2) + else if (ts1->tstamp < ts2->tstamp) + return -2; + else if ((ts1->seq == ts2->seq) && (ts1->tstamp > ts2->tstamp)) return 1; + else + return 2; +} /* rrtimeslice_cmp_internal */ - if (ts1->tsid && (! ts2->tsid)) - rrtimeslice_apply_typmod(ts2, ts1->tsid); - else if ((! ts1->tsid) && ts2->tsid) - rrtimeslice_apply_typmod(ts1, ts2->tsid); +Datum +rrtimeslice_cmp(PG_FUNCTION_ARGS) +{ + rrtimeslice_t *ts1 = PG_GETARG_RRTIMESLICE_P(0); + rrtimeslice_t *ts2 = PG_GETARG_RRTIMESLICE_P(1); - if (ts1->tsid != ts2->tsid) /* XXX: compare len/num */ - ereport(ERROR, ( - errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid comparison: cannot compare " - "rrtimeslices with different typmods (yet)") - )); + PG_RETURN_INT32(rrtimeslice_cmp_internal(ts1, ts2)); +} /* rrtimeslice_cmp */ + +int +rrtimeslice_seq_cmp_internal(rrtimeslice_t *ts1, rrtimeslice_t *ts2) +{ + int status; + + status = rrtimeslice_cmp_unify(ts1, ts2); + if (status) /* [1, 3] -> [-1, 1] */ + return status - 2; if (ts1->seq < ts2->seq) return -1; @@ -580,7 +665,7 @@ rrtimeslice_seq_cmp(PG_FUNCTION_ARGS) rrtimeslice_t *ts2 = PG_GETARG_RRTIMESLICE_P(1); PG_RETURN_INT32(rrtimeslice_seq_cmp_internal(ts1, ts2)); -} /* rrtimeslice_seq_ge */ +} /* rrtimeslice_seq_cmp */ Datum rrtimeslice_seq_hash(PG_FUNCTION_ARGS)