Code

RRTimeslice: Added rrtimeslice_cmp().
authorSebastian Harl <sh@tokkee.org>
Wed, 7 Nov 2012 20:25:58 +0000 (21:25 +0100)
committerSebastian Harl <sh@tokkee.org>
Wed, 7 Nov 2012 20:25:58 +0000 (21:25 +0100)
This function compares two timeslices by timestamp. It returns values less
than zero, zero or greater than zero if the first timestamp is smaller than,
equal to or greater than the second.

Values -2 / 2 indicate that the sequence numbers don't match while values
-1 / 1 indicate that they do match.

src/postrr.h.in
src/postrr.sql.in
src/rrtimeslice.c

index 206c682374941d6f02701031df907db065bbf227..d9df4af255258897d55faecec38ffd68e73ae6eb 100644 (file)
@@ -83,6 +83,10 @@ rrtimeslice_to_timestamptz(PG_FUNCTION_ARGS);
 
 /* comparison operators */
 Datum
+rrtimeslice_cmp(PG_FUNCTION_ARGS);
+
+/* sequence comparison operators */
+Datum
 rrtimeslice_seq_eq(PG_FUNCTION_ARGS);
 Datum
 rrtimeslice_seq_ne(PG_FUNCTION_ARGS);
@@ -103,6 +107,27 @@ rrtimeslice_seq_hash(PG_FUNCTION_ARGS);
  * internal (not fmgr-callable) functions
  */
 
+/*
+ * compare two RRTimeslices
+ *
+ * returns:
+ *  - -2 if ts1 < ts2 (sequence numbers don't match)
+ *  - -1 if ts1 < ts2 (sequence numbers match)
+ *  -  0 if ts1 = ts2
+ *  -  1 if ts1 > ts2 (sequence numbers match)
+ *  -  2 if ts1 > ts2 (sequence numbers don't match)
+ */
+int
+rrtimeslice_cmp_internal(rrtimeslice_t *ts1, rrtimeslice_t *ts2);
+
+/*
+ * compare sequence numbers of two RRTimeslices
+ *
+ * returns:
+ *  - -1 if ts1 < ts2
+ *  -  0 if ts1 = ts2
+ *  -  1 if ts1 > ts2
+ */
 int
 rrtimeslice_seq_cmp_internal(rrtimeslice_t *ts1, rrtimeslice_t *ts2);
 
index fc32f43d7f64f2dabf65391f142349159211a66b..87ef9d36a3cabbe40450ef19c686b9e3bec5d126 100644 (file)
@@ -117,6 +117,11 @@ CREATE CAST (rrtimeslice AS timestamptz)
        WITH FUNCTION Tstamptz(rrtimeslice);
        -- EXPLICIT
 
+CREATE OR REPLACE FUNCTION rrtimeslice_cmp(rrtimeslice, rrtimeslice)
+       RETURNS integer
+       AS 'postrr-@POSTRR_MAJOR_VERSION@.@POSTRR_MINOR_VERSION@', 'rrtimeslice_cmp'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
 CREATE OR REPLACE FUNCTION rrtimeslice_seq_eq(rrtimeslice, rrtimeslice)
        RETURNS boolean
        AS 'postrr-@POSTRR_MAJOR_VERSION@.@POSTRR_MINOR_VERSION@', 'rrtimeslice_seq_eq'
index 25e9cb38c1ce2caf73eb3b7e5d5e476e4d4eda3b..7de9ed742244b8c30b7ec2e7266e3fb9ae3ed552 100644 (file)
@@ -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
  */
@@ -209,6 +246,8 @@ PG_FUNCTION_INFO_V1(rrtimeslice_typmodout);
 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);
@@ -490,26 +529,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 +636,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)