diff --git a/src/rrtimeslice.c b/src/rrtimeslice.c
index 6c135ec893ec865a6a18313d491e088c708dab71..1e8283c30235a0cced110368739c1cbb1b410407 100644 (file)
--- a/src/rrtimeslice.c
+++ b/src/rrtimeslice.c
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
*/
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);
buf_l[sizeof(buf_l) - 1] = '\0';
}
- snprintf(ts_str, sizeof(ts_str), "(%s, %s] #%i/%i",
+ snprintf(ts_str, sizeof(ts_str), "(\"%s\", \"%s\"] #%i/%i",
buf_l, buf_u, tslice->seq, num);
result = pstrdup(ts_str);
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)
{
} /* 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;
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)