Skip to content

Commit 57e3c51

Browse files
committed
Add bool GiST opclass to btree_gist
Adds bool opclass to btree_gist extension, to allow creating GiST indexes on bool columns. GiST indexes on a single bool column don't seem particularly useful, but this allows defining exclusion constraings involving a bool column, for example. Author: Emre Hasegeli Reviewed-by: Andrey Borodin Discussion: https://postgr.es/m/CAE2gYzyDKJBZngssR84VGZEN=Ux=V9FV23QfPgo+7-yYnKKg4g@mail.gmail.com
1 parent dafcf88 commit 57e3c51

File tree

8 files changed

+382
-3
lines changed

8 files changed

+382
-3
lines changed

contrib/btree_gist/Makefile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ MODULE_big = btree_gist
55
OBJS = \
66
$(WIN32RES) \
77
btree_bit.o \
8+
btree_bool.o \
89
btree_bytea.o \
910
btree_cash.o \
1011
btree_date.o \
@@ -32,12 +33,12 @@ EXTENSION = btree_gist
3233
DATA = btree_gist--1.0--1.1.sql \
3334
btree_gist--1.1--1.2.sql btree_gist--1.2.sql btree_gist--1.2--1.3.sql \
3435
btree_gist--1.3--1.4.sql btree_gist--1.4--1.5.sql \
35-
btree_gist--1.5--1.6.sql
36+
btree_gist--1.5--1.6.sql btree_gist--1.6--1.7.sql
3637
PGFILEDESC = "btree_gist - B-tree equivalent GiST operator classes"
3738

3839
REGRESS = init int2 int4 int8 float4 float8 cash oid timestamp timestamptz \
3940
time timetz date interval macaddr macaddr8 inet cidr text varchar char \
40-
bytea bit varbit numeric uuid not_equal enum
41+
bytea bit varbit numeric uuid not_equal enum bool
4142

4243
SHLIB_LINK += $(filter -lm, $(LIBS))
4344

contrib/btree_gist/btree_bool.c

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
/*
2+
* contrib/btree_gist/btree_bool.c
3+
*/
4+
#include "postgres.h"
5+
6+
#include "btree_gist.h"
7+
#include "btree_utils_num.h"
8+
#include "common/int.h"
9+
10+
typedef struct boolkey
11+
{
12+
bool lower;
13+
bool upper;
14+
} boolKEY;
15+
16+
/*
17+
** bool ops
18+
*/
19+
PG_FUNCTION_INFO_V1(gbt_bool_compress);
20+
PG_FUNCTION_INFO_V1(gbt_bool_fetch);
21+
PG_FUNCTION_INFO_V1(gbt_bool_union);
22+
PG_FUNCTION_INFO_V1(gbt_bool_picksplit);
23+
PG_FUNCTION_INFO_V1(gbt_bool_consistent);
24+
PG_FUNCTION_INFO_V1(gbt_bool_penalty);
25+
PG_FUNCTION_INFO_V1(gbt_bool_same);
26+
27+
static bool
28+
gbt_boolgt(const void *a, const void *b, FmgrInfo *flinfo)
29+
{
30+
return (*((const bool *) a) > *((const bool *) b));
31+
}
32+
static bool
33+
gbt_boolge(const void *a, const void *b, FmgrInfo *flinfo)
34+
{
35+
return (*((const bool *) a) >= *((const bool *) b));
36+
}
37+
static bool
38+
gbt_booleq(const void *a, const void *b, FmgrInfo *flinfo)
39+
{
40+
return (*((const bool *) a) == *((const bool *) b));
41+
}
42+
static bool
43+
gbt_boolle(const void *a, const void *b, FmgrInfo *flinfo)
44+
{
45+
return (*((const bool *) a) <= *((const bool *) b));
46+
}
47+
static bool
48+
gbt_boollt(const void *a, const void *b, FmgrInfo *flinfo)
49+
{
50+
return (*((const bool *) a) < *((const bool *) b));
51+
}
52+
53+
static int
54+
gbt_boolkey_cmp(const void *a, const void *b, FmgrInfo *flinfo)
55+
{
56+
boolKEY *ia = (boolKEY *) (((const Nsrt *) a)->t);
57+
boolKEY *ib = (boolKEY *) (((const Nsrt *) b)->t);
58+
59+
if (ia->lower == ib->lower)
60+
{
61+
if (ia->upper == ib->upper)
62+
return 0;
63+
64+
return (ia->upper > ib->upper) ? 1 : -1;
65+
}
66+
67+
return (ia->lower > ib->lower) ? 1 : -1;
68+
}
69+
70+
71+
static const gbtree_ninfo tinfo =
72+
{
73+
gbt_t_bool,
74+
sizeof(bool),
75+
4, /* sizeof(gbtreekey4) */
76+
gbt_boolgt,
77+
gbt_boolge,
78+
gbt_booleq,
79+
gbt_boolle,
80+
gbt_boollt,
81+
gbt_boolkey_cmp,
82+
};
83+
84+
85+
/**************************************************
86+
* bool ops
87+
**************************************************/
88+
89+
90+
Datum
91+
gbt_bool_compress(PG_FUNCTION_ARGS)
92+
{
93+
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
94+
95+
PG_RETURN_POINTER(gbt_num_compress(entry, &tinfo));
96+
}
97+
98+
Datum
99+
gbt_bool_fetch(PG_FUNCTION_ARGS)
100+
{
101+
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
102+
103+
PG_RETURN_POINTER(gbt_num_fetch(entry, &tinfo));
104+
}
105+
106+
Datum
107+
gbt_bool_consistent(PG_FUNCTION_ARGS)
108+
{
109+
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
110+
bool query = PG_GETARG_INT16(1);
111+
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
112+
113+
/* Oid subtype = PG_GETARG_OID(3); */
114+
bool *recheck = (bool *) PG_GETARG_POINTER(4);
115+
boolKEY *kkk = (boolKEY *) DatumGetPointer(entry->key);
116+
GBT_NUMKEY_R key;
117+
118+
/* All cases served by this function are exact */
119+
*recheck = false;
120+
121+
key.lower = (GBT_NUMKEY *) &kkk->lower;
122+
key.upper = (GBT_NUMKEY *) &kkk->upper;
123+
124+
PG_RETURN_BOOL(gbt_num_consistent(&key, (void *) &query, &strategy,
125+
GIST_LEAF(entry), &tinfo, fcinfo->flinfo));
126+
}
127+
128+
129+
Datum
130+
gbt_bool_union(PG_FUNCTION_ARGS)
131+
{
132+
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
133+
void *out = palloc(sizeof(boolKEY));
134+
135+
*(int *) PG_GETARG_POINTER(1) = sizeof(boolKEY);
136+
PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo));
137+
}
138+
139+
140+
Datum
141+
gbt_bool_penalty(PG_FUNCTION_ARGS)
142+
{
143+
boolKEY *origentry = (boolKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
144+
boolKEY *newentry = (boolKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
145+
float *result = (float *) PG_GETARG_POINTER(2);
146+
147+
penalty_num(result, origentry->lower, origentry->upper, newentry->lower, newentry->upper);
148+
149+
PG_RETURN_POINTER(result);
150+
}
151+
152+
Datum
153+
gbt_bool_picksplit(PG_FUNCTION_ARGS)
154+
{
155+
PG_RETURN_POINTER(gbt_num_picksplit((GistEntryVector *) PG_GETARG_POINTER(0),
156+
(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
157+
&tinfo, fcinfo->flinfo));
158+
}
159+
160+
Datum
161+
gbt_bool_same(PG_FUNCTION_ARGS)
162+
{
163+
boolKEY *b1 = (boolKEY *) PG_GETARG_POINTER(0);
164+
boolKEY *b2 = (boolKEY *) PG_GETARG_POINTER(1);
165+
bool *result = (bool *) PG_GETARG_POINTER(2);
166+
167+
*result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
168+
PG_RETURN_POINTER(result);
169+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/* contrib/btree_gist/btree_gist--1.6--1.7.sql */
2+
3+
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
4+
\echo Use "ALTER EXTENSION btree_gist UPDATE TO '1.7'" to load this file. \quit
5+
6+
-- This upgrade scripts add support for bool.
7+
8+
-- Define the GiST support methods
9+
CREATE FUNCTION gbt_bool_consistent(internal,bool,int2,oid,internal)
10+
RETURNS bool
11+
AS 'MODULE_PATHNAME'
12+
LANGUAGE C IMMUTABLE STRICT;
13+
14+
CREATE FUNCTION gbt_bool_compress(internal)
15+
RETURNS internal
16+
AS 'MODULE_PATHNAME'
17+
LANGUAGE C IMMUTABLE STRICT;
18+
19+
CREATE FUNCTION gbt_bool_fetch(internal)
20+
RETURNS internal
21+
AS 'MODULE_PATHNAME'
22+
LANGUAGE C IMMUTABLE STRICT;
23+
24+
CREATE FUNCTION gbt_bool_penalty(internal,internal,internal)
25+
RETURNS internal
26+
AS 'MODULE_PATHNAME'
27+
LANGUAGE C IMMUTABLE STRICT;
28+
29+
CREATE FUNCTION gbt_bool_picksplit(internal, internal)
30+
RETURNS internal
31+
AS 'MODULE_PATHNAME'
32+
LANGUAGE C IMMUTABLE STRICT;
33+
34+
CREATE FUNCTION gbt_bool_union(internal, internal)
35+
RETURNS gbtreekey8
36+
AS 'MODULE_PATHNAME'
37+
LANGUAGE C IMMUTABLE STRICT;
38+
39+
CREATE FUNCTION gbt_bool_same(gbtreekey8, gbtreekey8, internal)
40+
RETURNS internal
41+
AS 'MODULE_PATHNAME'
42+
LANGUAGE C IMMUTABLE STRICT;
43+
44+
-- Create the operator class
45+
CREATE OPERATOR CLASS gist_bool_ops
46+
DEFAULT FOR TYPE bool USING gist
47+
AS
48+
OPERATOR 1 < ,
49+
OPERATOR 2 <= ,
50+
OPERATOR 3 = ,
51+
OPERATOR 4 >= ,
52+
OPERATOR 5 > ,
53+
OPERATOR 6 <> ,
54+
FUNCTION 1 gbt_bool_consistent (internal, bool, int2, oid, internal),
55+
FUNCTION 2 gbt_bool_union (internal, internal),
56+
FUNCTION 3 gbt_bool_compress (internal),
57+
FUNCTION 4 gbt_decompress (internal),
58+
FUNCTION 5 gbt_bool_penalty (internal, internal, internal),
59+
FUNCTION 6 gbt_bool_picksplit (internal, internal),
60+
FUNCTION 7 gbt_bool_same (gbtreekey8, gbtreekey8, internal),
61+
FUNCTION 9 gbt_bool_fetch (internal),
62+
STORAGE gbtreekey8;

contrib/btree_gist/btree_gist.control

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# btree_gist extension
22
comment = 'support for indexing common datatypes in GiST'
3-
default_version = '1.6'
3+
default_version = '1.7'
44
module_pathname = '$libdir/btree_gist'
55
relocatable = true
66
trusted = true

contrib/btree_gist/btree_gist.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ enum gbtree_type
3232
gbt_t_bpchar,
3333
gbt_t_bytea,
3434
gbt_t_bit,
35+
gbt_t_bool,
3536
gbt_t_inet,
3637
gbt_t_uuid,
3738
gbt_t_enum

contrib/btree_gist/btree_utils_num.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ gbt_num_compress(GISTENTRY *entry, const gbtree_ninfo *tinfo)
1919
{
2020
union
2121
{
22+
bool bo;
2223
int16 i2;
2324
int32 i4;
2425
int64 i8;
@@ -35,6 +36,10 @@ gbt_num_compress(GISTENTRY *entry, const gbtree_ninfo *tinfo)
3536

3637
switch (tinfo->t)
3738
{
39+
case gbt_t_bool:
40+
v.bo = DatumGetBool(entry->key);
41+
leaf = &v.bo;
42+
break;
3843
case gbt_t_int2:
3944
v.i2 = DatumGetInt16(entry->key);
4045
leaf = &v.i2;
@@ -113,6 +118,9 @@ gbt_num_fetch(GISTENTRY *entry, const gbtree_ninfo *tinfo)
113118
*/
114119
switch (tinfo->t)
115120
{
121+
case gbt_t_bool:
122+
datum = BoolGetDatum(*(bool *) entry->key);
123+
break;
116124
case gbt_t_int2:
117125
datum = Int16GetDatum(*(int16 *) entry->key);
118126
break;

contrib/btree_gist/expected/bool.out

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
-- bool check
2+
CREATE TABLE booltmp (a bool);
3+
INSERT INTO booltmp VALUES (false), (true);
4+
SET enable_seqscan=on;
5+
SELECT count(*) FROM booltmp WHERE a < true;
6+
count
7+
-------
8+
1
9+
(1 row)
10+
11+
SELECT count(*) FROM booltmp WHERE a <= true;
12+
count
13+
-------
14+
2
15+
(1 row)
16+
17+
SELECT count(*) FROM booltmp WHERE a = true;
18+
count
19+
-------
20+
1
21+
(1 row)
22+
23+
SELECT count(*) FROM booltmp WHERE a >= true;
24+
count
25+
-------
26+
1
27+
(1 row)
28+
29+
SELECT count(*) FROM booltmp WHERE a > true;
30+
count
31+
-------
32+
0
33+
(1 row)
34+
35+
CREATE INDEX boolidx ON booltmp USING gist ( a );
36+
SET enable_seqscan=off;
37+
SELECT count(*) FROM booltmp WHERE a < true;
38+
count
39+
-------
40+
1
41+
(1 row)
42+
43+
SELECT count(*) FROM booltmp WHERE a <= true;
44+
count
45+
-------
46+
2
47+
(1 row)
48+
49+
SELECT count(*) FROM booltmp WHERE a = true;
50+
count
51+
-------
52+
1
53+
(1 row)
54+
55+
SELECT count(*) FROM booltmp WHERE a >= true;
56+
count
57+
-------
58+
1
59+
(1 row)
60+
61+
SELECT count(*) FROM booltmp WHERE a > true;
62+
count
63+
-------
64+
0
65+
(1 row)
66+
67+
-- Test index-only scans
68+
SET enable_bitmapscan=off;
69+
EXPLAIN (COSTS OFF)
70+
SELECT * FROM booltmp WHERE a;
71+
QUERY PLAN
72+
------------------------------------------
73+
Index Only Scan using boolidx on booltmp
74+
Filter: a
75+
(2 rows)
76+
77+
SELECT * FROM booltmp WHERE a;
78+
a
79+
---
80+
t
81+
(1 row)
82+
83+
EXPLAIN (COSTS OFF)
84+
SELECT * FROM booltmp WHERE NOT a;
85+
QUERY PLAN
86+
------------------------------------------
87+
Index Only Scan using boolidx on booltmp
88+
Filter: (NOT a)
89+
(2 rows)
90+
91+
SELECT * FROM booltmp WHERE NOT a;
92+
a
93+
---
94+
f
95+
(1 row)
96+

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy