diff --git a/src/rrtimeslice.c b/src/rrtimeslice.c
index 25e9cb38c1ce2caf73eb3b7e5d5e476e4d4eda3b..7de9ed742244b8c30b7ec2e7266e3fb9ae3ed552 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_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);
} /* 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)