Permalink
Browse files

build_pr cleanup, now takes (prefix, first, last) as arguments

  • Loading branch information...
1 parent 2428090 commit d66fb113003725e6d4498a51cebe2d7b4ccdc553 dim committed Apr 23, 2008
Showing with 70 additions and 50 deletions.
  1. +44 −50 prefix.c
  2. +26 −0 ranges.sql
View
@@ -9,7 +9,7 @@
* writting of this opclass, on the PostgreSQL internals, GiST inner
* working and prefix search analyses.
*
- * $Id: prefix.c,v 1.41 2008/04/23 10:32:44 dim Exp $
+ * $Id: prefix.c,v 1.42 2008/04/23 15:13:43 dim Exp $
*/
#include <stdio.h>
@@ -152,20 +152,16 @@ char *__greater_prefix(char *a, char *b, int alen, int blen)
}
/**
- * First, the input reader. A prefix range will have to respect the
- * following regular expression: .*([[].-.[]])?
- *
- * examples : 123[4-6], [1-3], 234, 01[] --- last one not covered by
- * regexp.
+ * Helper function which builds a prefix_range from a prefix, a first
+ * and a last component, making a copy of the prefix string.
*/
-
static inline
-prefix_range *build_pr(const char *prefix) {
+prefix_range *build_pr(const char *prefix, char first, char last) {
int s = strlen(prefix) + 1;
prefix_range *pr = palloc(sizeof(prefix_range) + s);
memcpy(pr->prefix, prefix, s);
- pr->first = 0;
- pr->last = 0;
+ pr->first = first;
+ pr->last = last;
#ifdef DEBUG_PR_IN
elog(NOTICE,
@@ -176,14 +172,18 @@ prefix_range *build_pr(const char *prefix) {
return pr;
}
+/**
+ * Normalize a prefix_range. Two cases are handled:
+ *
+ * abc[x-x] is rewritten abcx
+ * abc[x-y] is rewritten abc[y-x] when y < x
+ */
static inline
prefix_range *pr_normalize(prefix_range *a) {
char tmpswap;
char *prefix;
- prefix_range *pr = build_pr(a->prefix);
- pr->first = a->first;
- pr->last = a->last;
+ prefix_range *pr = build_pr(a->prefix, a->first, a->last);
if( pr->first == pr->last ) {
int s = strlen(pr->prefix)+2;
@@ -197,7 +197,7 @@ prefix_range *pr_normalize(prefix_range *a) {
#endif
pfree(pr);
- pr = build_pr(prefix);
+ pr = build_pr(prefix, 0, 0);
}
else if( pr->first > pr->last ) {
tmpswap = pr->first;
@@ -207,6 +207,14 @@ prefix_range *pr_normalize(prefix_range *a) {
return pr;
}
+/**
+ * First, the input reader. A prefix range will have to respect the
+ * following regular expression: .*([[].-.[]])?
+ *
+ * examples : 123[4-6], [1-3], 234, 01[] --- last one not covered by
+ * regexp.
+ */
+
static inline
prefix_range *pr_from_str(char *str) {
prefix_range *pr = NULL;
@@ -243,7 +251,7 @@ prefix_range *pr_from_str(char *str) {
}
opened = true;
- pr = build_pr(prefix);
+ pr = build_pr(prefix, 0, 0);
break;
case PR_SEP:
@@ -321,7 +329,7 @@ prefix_range *pr_from_str(char *str) {
}
if( ! opened ) {
- pr = build_pr(prefix);
+ pr = build_pr(prefix, 0, 0);
}
if( opened && !closed ) {
@@ -544,17 +552,17 @@ prefix_range *pr_union(prefix_range *a, prefix_range *b) {
char min, max;
if( 0 == alen && 0 == blen ) {
- res = build_pr("");
- res->first = a->first <= b->first ? a->first : b->first;
- res->last = a->last >= b->last ? a->last : b->last;
+ res = build_pr("",
+ a->first <= b->first ? a->first : b->first,
+ a->last >= b->last ? a->last : b->last);
return pr_normalize(res);
}
gp = __greater_prefix(a->prefix, b->prefix, alen, blen);
gplen = strlen(gp);
if( gplen == 0 ) {
- res = build_pr("");
+ res = build_pr("", 0, 0);
if( alen > 0 && blen > 0 ) {
res->first = a->prefix[0];
res->last = b->prefix[0];
@@ -569,7 +577,7 @@ prefix_range *pr_union(prefix_range *a, prefix_range *b) {
}
}
else {
- res = build_pr(gp);
+ res = build_pr(gp, 0, 0);
if( gplen == alen && alen == blen ) {
res->first = a->first <= b->first ? a->first : b->first;
@@ -610,53 +618,45 @@ prefix_range *pr_inter(prefix_range *a, prefix_range *b) {
int gplen;
if( 0 == alen && 0 == blen ) {
- res = build_pr("");
- res->first = a->first > b->first ? a->first : b->first;
- res->last = a->last < b->last ? a->last : b->last;
+ res = build_pr("",
+ a->first > b->first ? a->first : b->first,
+ a->last < b->last ? a->last : b->last);
return pr_normalize(res);
}
gp = __greater_prefix(a->prefix, b->prefix, alen, blen);
gplen = strlen(gp);
if( gplen != alen && gplen != blen ) {
- return build_pr("");
+ return build_pr("", 0, 0);
}
if( gplen == alen && 0 == alen ) {
if( a->first <= b->prefix[0] && b->prefix[0] <= a->last ) {
- res = build_pr(b->prefix);
- res->first = b->first;
- res->last = b->last;
+ res = build_pr(b->prefix, b->first, b->last);
}
else
- res = build_pr("");
+ res = build_pr("", 0, 0);
}
else if( gplen == blen && 0 == blen ) {
if( b->first <= a->prefix[0] && a->prefix[0] <= b->last ) {
- res = build_pr(a->prefix);
- res->first = a->first;
- res->last = a->last;
+ res = build_pr(a->prefix, a->first, a->last);
}
else
- res = build_pr("");
+ res = build_pr("", 0, 0);
}
else if( gplen == alen && alen == blen ) {
- res = build_pr(gp);
- res->first = a->first > b->first ? a->first : b->first;
- res->last = a->last < b->last ? a->last : b->last;
+ res = build_pr(gp,
+ a->first > b->first ? a->first : b->first,
+ a->last < b->last ? a->last : b->last);
}
else if( gplen == alen ) {
Assert(gplen < blen);
- res = build_pr(b->prefix);
- res->first = b->first;
- res->last = b->last;
+ res = build_pr(b->prefix, b->first, b->last);
}
else if( gplen == blen ) {
Assert(gplen < alen);
- res = build_pr(a->prefix);
- res->first = a->first;
- res->last = a->last;
+ res = build_pr(a->prefix, a->first, a->last);
}
return pr_normalize(res);
@@ -717,13 +717,9 @@ prefix_range_recv(PG_FUNCTION_ARGS)
const char *first = pq_getmsgbytes(buf, 1);
const char *last = pq_getmsgbytes(buf, 1);
const char *prefix = pq_getmsgstring(buf);
- prefix_range *pr = build_pr(prefix);
+ prefix_range *pr = build_pr(prefix, *first, *last);
pq_getmsgend(buf);
-
- pr->first = *first;
- pr->last = *last;
-
PG_RETURN_PREFIX_RANGE_P(pr);
}
@@ -1696,9 +1692,7 @@ gpr_union(PG_FUNCTION_ARGS)
out = tmp;
if( numranges == 1 ) {
- out = build_pr(tmp->prefix);
- out->first = tmp->first;
- out->last = tmp->last;
+ out = build_pr(tmp->prefix, tmp->first, tmp->last);
PG_RETURN_PREFIX_RANGE_P(out);
}
View
@@ -0,0 +1,26 @@
+\timing
+
+drop table if exists ranges_presort ;
+create table ranges_presort as select prefix::prefix_range, name, shortname, state from prefixes ;
+create index idx_prefix_presort on ranges_presort using gist(prefix gist_prefix_range_presort_ops);
+
+drop table if exists ranges_jordan ;
+create table ranges_jordan as select prefix::prefix_range, name, shortname, state from prefixes ;
+create index idx_prefix_jordan on ranges_jordan using gist(prefix gist_prefix_range_jordan_ops);
+
+drop table if exists ranges;
+create table ranges as select prefix::prefix_range, name, shortname, state from prefixes ;
+create index idx_prefix on ranges using gist(prefix gist_prefix_range_ops);
+
+\echo
+\echo select * from numbers n join ranges_presort r on r.prefix @> n.number;
+explain analyze select * from numbers n join ranges_presort r on r.prefix @> n.number;
+\echo
+
+\echo select * from numbers n join ranges_jordan r on r.prefix @> n.number;
+explain analyze select * from numbers n join ranges_jordan r on r.prefix @> n.number;
+\echo
+
+\echo select * from numbers n join ranges r on r.prefix @> n.number;
+explain analyze select * from numbers n join ranges r on r.prefix @> n.number;
+\echo

0 comments on commit d66fb11

Please sign in to comment.