From ad17ff95cf0d3df41aa2a7bbc03960d42b8da9f3 Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Mon, 2 Aug 2010 16:26:48 +0000 Subject: [PATCH] Add btree_gist support for searching on "not equals". Jeff Davis, with slight editorialization by me. --- contrib/btree_gist/btree_gist.h | 4 ++- contrib/btree_gist/btree_gist.sql.in | 24 +++++++++++++++++- contrib/btree_gist/btree_utils_num.c | 6 ++++- contrib/btree_gist/btree_utils_var.c | 5 +++- doc/src/sgml/btree-gist.sgml | 38 +++++++++++++++++++++++++++- 5 files changed, 72 insertions(+), 5 deletions(-) diff --git a/contrib/btree_gist/btree_gist.h b/contrib/btree_gist/btree_gist.h index 425ce8cff4..db5c5713b5 100644 --- a/contrib/btree_gist/btree_gist.h +++ b/contrib/btree_gist/btree_gist.h @@ -1,5 +1,5 @@ /* - * $PostgreSQL: pgsql/contrib/btree_gist/btree_gist.h,v 1.9 2009/06/11 14:48:50 momjian Exp $ + * $PostgreSQL: pgsql/contrib/btree_gist/btree_gist.h,v 1.10 2010/08/02 16:26:48 rhaas Exp $ */ #ifndef __BTREE_GIST_H__ #define __BTREE_GIST_H__ @@ -9,6 +9,8 @@ #include "access/itup.h" #include "access/nbtree.h" +#define BtreeGistNotEqualStrategyNumber 6 + /* indexed types */ enum gbtree_type diff --git a/contrib/btree_gist/btree_gist.sql.in b/contrib/btree_gist/btree_gist.sql.in index e78c83cdc2..0a285a71c1 100644 --- a/contrib/btree_gist/btree_gist.sql.in +++ b/contrib/btree_gist/btree_gist.sql.in @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/contrib/btree_gist/btree_gist.sql.in,v 1.21 2009/06/11 18:30:03 tgl Exp $ */ +/* $PostgreSQL: pgsql/contrib/btree_gist/btree_gist.sql.in,v 1.22 2010/08/02 16:26:48 rhaas Exp $ */ -- Adjust this setting to control where the objects get created. SET search_path = public; @@ -143,6 +143,7 @@ AS OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , + OPERATOR 6 <> , FUNCTION 1 gbt_oid_consistent (internal, oid, int2, oid, internal), FUNCTION 2 gbt_oid_union (bytea, internal), FUNCTION 3 gbt_oid_compress (internal), @@ -200,6 +201,7 @@ AS OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , + OPERATOR 6 <> , FUNCTION 1 gbt_int2_consistent (internal, int2, int2, oid, internal), FUNCTION 2 gbt_int2_union (bytea, internal), FUNCTION 3 gbt_int2_compress (internal), @@ -256,6 +258,7 @@ AS OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , + OPERATOR 6 <> , FUNCTION 1 gbt_int4_consistent (internal, int4, int2, oid, internal), FUNCTION 2 gbt_int4_union (bytea, internal), FUNCTION 3 gbt_int4_compress (internal), @@ -312,6 +315,7 @@ AS OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , + OPERATOR 6 <> , FUNCTION 1 gbt_int8_consistent (internal, int8, int2, oid, internal), FUNCTION 2 gbt_int8_union (bytea, internal), FUNCTION 3 gbt_int8_compress (internal), @@ -369,6 +373,7 @@ AS OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , + OPERATOR 6 <> , FUNCTION 1 gbt_float4_consistent (internal, float4, int2, oid, internal), FUNCTION 2 gbt_float4_union (bytea, internal), FUNCTION 3 gbt_float4_compress (internal), @@ -428,6 +433,7 @@ AS OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , + OPERATOR 6 <> , FUNCTION 1 gbt_float8_consistent (internal, float8, int2, oid, internal), FUNCTION 2 gbt_float8_union (bytea, internal), FUNCTION 3 gbt_float8_compress (internal), @@ -495,6 +501,7 @@ AS OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , + OPERATOR 6 <> , FUNCTION 1 gbt_ts_consistent (internal, timestamp, int2, oid, internal), FUNCTION 2 gbt_ts_union (bytea, internal), FUNCTION 3 gbt_ts_compress (internal), @@ -514,6 +521,7 @@ AS OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , + OPERATOR 6 <> , FUNCTION 1 gbt_tstz_consistent (internal, timestamptz, int2, oid, internal), FUNCTION 2 gbt_ts_union (bytea, internal), FUNCTION 3 gbt_tstz_compress (internal), @@ -581,6 +589,7 @@ AS OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , + OPERATOR 6 <> , FUNCTION 1 gbt_time_consistent (internal, time, int2, oid, internal), FUNCTION 2 gbt_time_union (bytea, internal), FUNCTION 3 gbt_time_compress (internal), @@ -598,6 +607,7 @@ AS OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , + OPERATOR 6 <> , FUNCTION 1 gbt_timetz_consistent (internal, timetz, int2, oid, internal), FUNCTION 2 gbt_time_union (bytea, internal), FUNCTION 3 gbt_timetz_compress (internal), @@ -655,6 +665,7 @@ AS OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , + OPERATOR 6 <> , FUNCTION 1 gbt_date_consistent (internal, date, int2, oid, internal), FUNCTION 2 gbt_date_union (bytea, internal), FUNCTION 3 gbt_date_compress (internal), @@ -717,6 +728,7 @@ AS OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , + OPERATOR 6 <> , FUNCTION 1 gbt_intv_consistent (internal, interval, int2, oid, internal), FUNCTION 2 gbt_intv_union (bytea, internal), FUNCTION 3 gbt_intv_compress (internal), @@ -773,6 +785,7 @@ AS OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , + OPERATOR 6 <> , FUNCTION 1 gbt_cash_consistent (internal, money, int2, oid, internal), FUNCTION 2 gbt_cash_union (bytea, internal), FUNCTION 3 gbt_cash_compress (internal), @@ -829,6 +842,7 @@ AS OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , + OPERATOR 6 <> , FUNCTION 1 gbt_macad_consistent (internal, macaddr, int2, oid, internal), FUNCTION 2 gbt_macad_union (bytea, internal), FUNCTION 3 gbt_macad_compress (internal), @@ -897,6 +911,7 @@ AS OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , + OPERATOR 6 <> , FUNCTION 1 gbt_text_consistent (internal, text, int2, oid, internal), FUNCTION 2 gbt_text_union (bytea, internal), FUNCTION 3 gbt_text_compress (internal), @@ -916,6 +931,7 @@ AS OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , + OPERATOR 6 <> , FUNCTION 1 gbt_bpchar_consistent (internal, bpchar , int2, oid, internal), FUNCTION 2 gbt_text_union (bytea, internal), FUNCTION 3 gbt_bpchar_compress (internal), @@ -973,6 +989,7 @@ AS OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , + OPERATOR 6 <> , FUNCTION 1 gbt_bytea_consistent (internal, bytea, int2, oid, internal), FUNCTION 2 gbt_bytea_union (bytea, internal), FUNCTION 3 gbt_bytea_compress (internal), @@ -1030,6 +1047,7 @@ AS OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , + OPERATOR 6 <> , FUNCTION 1 gbt_numeric_consistent (internal, numeric, int2, oid, internal), FUNCTION 2 gbt_numeric_union (bytea, internal), FUNCTION 3 gbt_numeric_compress (internal), @@ -1085,6 +1103,7 @@ AS OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , + OPERATOR 6 <> , FUNCTION 1 gbt_bit_consistent (internal, bit, int2, oid, internal), FUNCTION 2 gbt_bit_union (bytea, internal), FUNCTION 3 gbt_bit_compress (internal), @@ -1104,6 +1123,7 @@ AS OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , + OPERATOR 6 <> , FUNCTION 1 gbt_bit_consistent (internal, bit, int2, oid, internal), FUNCTION 2 gbt_bit_union (bytea, internal), FUNCTION 3 gbt_bit_compress (internal), @@ -1162,6 +1182,7 @@ AS OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , + OPERATOR 6 <> , FUNCTION 1 gbt_inet_consistent (internal, inet, int2, oid, internal), FUNCTION 2 gbt_inet_union (bytea, internal), FUNCTION 3 gbt_inet_compress (internal), @@ -1180,6 +1201,7 @@ AS OPERATOR 3 = (inet, inet) , OPERATOR 4 >= (inet, inet) , OPERATOR 5 > (inet, inet) , + OPERATOR 6 <> (inet, inet) , FUNCTION 1 gbt_inet_consistent (internal, inet, int2, oid, internal), FUNCTION 2 gbt_inet_union (bytea, internal), FUNCTION 3 gbt_inet_compress (internal), diff --git a/contrib/btree_gist/btree_utils_num.c b/contrib/btree_gist/btree_utils_num.c index ff206dcda8..e4b4824769 100644 --- a/contrib/btree_gist/btree_utils_num.c +++ b/contrib/btree_gist/btree_utils_num.c @@ -1,5 +1,5 @@ /* - * $PostgreSQL: pgsql/contrib/btree_gist/btree_utils_num.c,v 1.12 2009/06/11 14:48:50 momjian Exp $ + * $PostgreSQL: pgsql/contrib/btree_gist/btree_utils_num.c,v 1.13 2010/08/02 16:26:48 rhaas Exp $ */ #include "btree_gist.h" #include "btree_utils_num.h" @@ -225,6 +225,10 @@ gbt_num_consistent( case BTGreaterEqualStrategyNumber: retval = (*tinfo->f_le) (query, key->upper); break; + case BtreeGistNotEqualStrategyNumber: + retval = ! ((*tinfo->f_eq) (query, key->lower) && + (*tinfo->f_eq) (query, key->upper)); + break; default: retval = FALSE; } diff --git a/contrib/btree_gist/btree_utils_var.c b/contrib/btree_gist/btree_utils_var.c index 916706d8a4..447ba59efb 100644 --- a/contrib/btree_gist/btree_utils_var.c +++ b/contrib/btree_gist/btree_utils_var.c @@ -1,5 +1,5 @@ /* - * $PostgreSQL: pgsql/contrib/btree_gist/btree_utils_var.c,v 1.23 2010/02/26 02:00:32 momjian Exp $ + * $PostgreSQL: pgsql/contrib/btree_gist/btree_utils_var.c,v 1.24 2010/08/02 16:26:48 rhaas Exp $ */ #include "btree_gist.h" @@ -596,6 +596,9 @@ gbt_var_consistent( retval = (*tinfo->f_cmp) ((bytea *) query, key->upper) <= 0 || gbt_var_node_pf_match(key, query, tinfo); break; + case BtreeGistNotEqualStrategyNumber: + retval = ! ((*tinfo->f_eq) (query, key->lower) && (*tinfo->f_eq) (query, key->upper)); + break; default: retval = FALSE; } diff --git a/doc/src/sgml/btree-gist.sgml b/doc/src/sgml/btree-gist.sgml index 8264d5a219..d477f23a2e 100644 --- a/doc/src/sgml/btree-gist.sgml +++ b/doc/src/sgml/btree-gist.sgml @@ -1,4 +1,4 @@ - + btree_gist @@ -27,15 +27,51 @@ GiST operator classes. + + In addition to the typical btree search operators, btree_gist also + provides search operators for <> ("not + equals"). This may be useful in combination with an + Exclusion Constraint, + as descibed below. + + Example usage + + Simple example using btree_gist instead of btree: + + CREATE TABLE test (a int4); -- create index CREATE INDEX testidx ON test USING gist (a); -- query SELECT * FROM test WHERE a < 10; + + + + Example using an Exclusion + Constraint to enforce the constraint that a cage at a zoo + can contain only one kind of animal: + + + +=> CREATE TABLE zoo ( + cage INTEGER, + animal TEXT, + EXCLUDE USING gist (cage WITH =, animal WITH <>) +); + +=> INSERT INTO zoo VALUES(123, 'zebra'); +INSERT 0 1 +=> INSERT INTO zoo VALUES(123, 'zebra'); +INSERT 0 1 +=> INSERT INTO zoo VALUES(123, 'lion'); +ERROR: conflicting key value violates exclusion constraint "zoo_cage_animal_excl" +DETAIL: Key (cage, animal)=(123, lion) conflicts with existing key (cage, animal)=(123, zebra). +=> INSERT INTO zoo VALUES(124, 'lion'); +INSERT 0 1