Skip to content

Commit

Permalink
Fix pr_cmp() and have pr_lt() and pr_gt() use it rather than the othe…
Browse files Browse the repository at this point in the history
…r way round
  • Loading branch information
dim committed Jun 14, 2009
1 parent 9955a4c commit c027c8a
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 86 deletions.
16 changes: 8 additions & 8 deletions README.txt
Expand Up @@ -162,22 +162,22 @@ The operators <=, <, =, <>, >= and > are read as usual, @> is read
*contains*, <@ is read *is contained by*, && is read *overlaps*, and | is
"union" and "&" is "intersect".

prefix=# select a, b,
a <= b as "<=", a < b as "<", a = b as "=", a <> b as "<>", a >= b as ">=", a > b as ">",
a @> b as "@>", a <@ b as "<@", a && b as "&&"
prefix=# select a, b,
a <= b as "<=", a < b as "<", a = b as "=", a <> b as "<>", a >= b as ">=", a > b as ">",
a @> b as "@>", a <@ b as "<@", a && b as "&&"
from (select a::prefix_range, b::prefix_range
from (values('123', '123'),
('123', '124'),
('123', '123[4-5]'),
('123[4-5]', '123[2-7]'),
from (values('123', '123'),
('123', '124'),
('123', '123[4-5]'),
('123[4-5]', '123[2-7]'),
('123', '[2-3]')) as t(a, b)
) as x;
a | b | <= | < | = | <> | >= | > | @> | <@ | &&
----------+----------+----+---+---+----+----+---+----+----+----
123 | 123 | t | f | t | f | t | f | t | t | t
123 | 124 | t | t | f | t | f | f | f | f | f
123 | 123[4-5] | t | t | f | t | f | f | t | f | t
123[4-5] | 123[2-7] | f | f | f | t | f | f | f | t | t
123[4-5] | 123[2-7] | f | f | f | t | t | t | f | t | t
123 | [2-3] | t | t | f | t | f | f | f | f | f
(5 rows)

Expand Down
120 changes: 42 additions & 78 deletions prefix.c
Expand Up @@ -9,7 +9,7 @@
* writting of this opclass, on the PostgreSQL internals, GiST inner
* working and prefix search analyses.
*
* $Id: prefix.c,v 1.50 2009/06/05 21:05:23 dim Exp $
* $Id: prefix.c,v 1.51 2009/06/14 23:13:46 dim Exp $
*/

#include <stdio.h>
Expand Down Expand Up @@ -447,112 +447,76 @@ bool pr_eq(prefix_range *a, prefix_range *b) {
*
* Baring bug, the constraint is to have non-overlapping data.
*/
static inline

/*static inline
bool pr_lt(prefix_range *a, prefix_range *b, bool eqval) {
*/

static inline
int pr_cmp(prefix_range *a, prefix_range *b) {
int cmp = 0;
int alen = strlen(a->prefix);
int blen = strlen(b->prefix);
int mlen = alen; /* minimum length */
char *p = a->prefix;
char *q = b->prefix;

/*
* First case, common prefix length
*/
if( alen == blen ) {
cmp = memcmp(p, q, alen);

if( cmp < 0 )
return true;
/* Uncommon prefix, easy to compare */
if( cmp != 0 )
return cmp;

else if( cmp == 0 ) {
if( a->first == 0 ) {
if( b->first == 0 )
return eqval;
return true;
}
else
return (eqval ? a->first <= b->first : a->first < b->first);
}
/* Common prefix, check for (sub)ranges */
else
return false;
return (a->first == b->first) ? (a->last - b->last) : (a->first - b->first);
}

/* For memcmp() safety, we need the minimum length */
if( mlen > blen )
mlen = blen;

/*
* Don't forget we may have [x-y] prefix style, that's empty prefix, only range.
*/
if( alen == 0 && a->first != 0 ) {
return (eqval ? (a->first <= q[0]) : (a->first < q[0]));
/* return (eqval ? (a->first <= q[0]) : (a->first < q[0])); */
return a->first - q[0];
}
else if( blen == 0 && b->first != 0 ) {
return (eqval ? (p[0] <= b->first) : (p[0] < b->first));
/* return (eqval ? (p[0] <= b->first) : (p[0] < b->first)); */
return p[0] - b->first;
}
else {
/*
* When memcmp() on the shorter of p and q returns 0, that means they
* share a common prefix: avoid to say that '93' < '9377' and '9377' <
* '93'.
*/
cmp = memcmp(p, q, mlen);

if( cmp == 0 )
return (eqval ? alen <= blen : alen < blen);
/*
* General case
*
* When memcmp() on the shorter of p and q returns 0, that means they
* share a common prefix: avoid to say that '93' < '9377' and '9377' <
* '93'.
*/
cmp = memcmp(p, q, mlen);

if( cmp == 0 )
return (a->first == b->first) ? (a->last - b->last) : (a->first - b->first);

return (eqval ? cmp <= 0 : cmp < 0);
}
return cmp;
}

static inline
bool pr_gt(prefix_range *a, prefix_range *b, bool eqval) {
int cmp = 0;
int alen = strlen(a->prefix);
int blen = strlen(b->prefix);
int mlen = alen;
char *p = a->prefix;
char *q = b->prefix;

if( alen == blen ) {
cmp = memcmp(p, q, alen);

if( cmp > 0 )
return true;

else if( cmp == 0 ) {
if( a->last == 0 ) {
if( b->last == 0 )
return eqval;
return false;
}
else
return (eqval ? a->last >= b->last : a->last > b->last);
}
else
return false;
}
if( mlen > blen )
mlen = blen;

if( alen == 0 && a->last != 0 ) {
return (eqval ? (a->last >= q[0]) : (a->last > q[0]));
}
else if( blen == 0 && b->first != 0 ) {
return (eqval ? (p[0] >= b->last) : (p[0] > b->last));
}
else {
cmp = memcmp(p, q, mlen);

if( cmp == 0 )
return (eqval ? alen >= blen : alen > blen);

return (eqval ? cmp >= 0 : cmp > 0);
}
bool pr_lt(prefix_range *a, prefix_range *b, bool eqval) {
int cmp = pr_cmp(a, b);
return eqval ? cmp <= 0 : cmp < 0;
}

static inline
int pr_cmp(prefix_range *a, prefix_range *b) {
if( pr_eq(a, b) )
return 0;

if( pr_lt(a, b, false) )
return -1;

return 1;
bool pr_gt(prefix_range *a, prefix_range *b, bool eqval) {
int cmp = pr_cmp(a, b);
return eqval ? cmp >= 0 : cmp > 0;
}

static inline
Expand Down
29 changes: 29 additions & 0 deletions queries.sql
@@ -0,0 +1,29 @@
select a, b,
a <= b as "<=", a < b as "<", a = b as "=", a <> b as "<>", a >= b as ">=", a > b as ">",
a @> b as "@>", a <@ b as "<@", a && b as "&&"
from (select a::prefix_range, b::prefix_range
from (values('123', '123'),
('123', '124'),
('123', '123[4-5]'),
('123[4-5]', '123[2-7]'),
('123', '[2-3]')) as t(a, b)
) as x;

select a, b, c, a <= b as "a <= b", b <= c as "b <= c", a <= c as "a <= c"
from (select a::prefix_range, b::prefix_range, c::prefix_range
from (values('123', '123', '123'),
('123', '124', '125'),
('123', '123[4-5]', '123[4-6]'),
('123[4-5]', '123[2-7]', '123[1-8]'),
('123', '[2-3]', '4')) as t(a, b, c)
) as x;

select a, b, a | b as union, a & b as intersect
from (select a::prefix_range, b::prefix_range
from (values('123', '123'),
('123', '124'),
('123', '123[4-5]'),
('123[4-5]', '123[2-7]'),
('123', '[2-3]')) as t(a, b)
) as x;

0 comments on commit c027c8a

Please sign in to comment.