Skip to content

Commit f7946a9

Browse files
committed
Add btree_gist support for enum types.
This will allow enums to be used in exclusion constraints. The code uses the new CallerFInfoFunctionCall infrastructure in fmgr, and the support for it added to btree_gist in commit 393bb504d7. Reviewed by Tom Lane and Anastasia Lubennikova Discussion: http://postgr.es/m/56EA8A71.8060107@dunslane.net
1 parent 65a9138 commit f7946a9

File tree

10 files changed

+991
-7
lines changed

10 files changed

+991
-7
lines changed

contrib/btree_gist/Makefile

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,19 @@ MODULE_big = btree_gist
55
OBJS = btree_gist.o btree_utils_num.o btree_utils_var.o btree_int2.o \
66
btree_int4.o btree_int8.o btree_float4.o btree_float8.o btree_cash.o \
77
btree_oid.o btree_ts.o btree_time.o btree_date.o btree_interval.o \
8-
btree_macaddr.o btree_macaddr8.o btree_inet.o btree_text.o btree_bytea.o \
9-
btree_bit.o btree_numeric.o btree_uuid.o $(WIN32RES)
8+
btree_macaddr.o btree_macaddr8.o btree_inet.o btree_text.o \
9+
btree_bytea.o btree_bit.o btree_numeric.o btree_uuid.o \
10+
btree_enum.o $(WIN32RES)
1011

1112
EXTENSION = btree_gist
1213
DATA = btree_gist--unpackaged--1.0.sql btree_gist--1.0--1.1.sql \
1314
btree_gist--1.1--1.2.sql btree_gist--1.2.sql btree_gist--1.2--1.3.sql \
14-
btree_gist--1.3--1.4.sql
15+
btree_gist--1.3--1.4.sql btree_gist--1.4--1.5.sql
1516
PGFILEDESC = "btree_gist - B-tree equivalent GiST operator classes"
1617

1718
REGRESS = init int2 int4 int8 float4 float8 cash oid timestamp timestamptz \
1819
time timetz date interval macaddr macaddr8 inet cidr text varchar char \
19-
bytea bit varbit numeric uuid not_equal
20+
bytea bit varbit numeric uuid not_equal enum
2021

2122
SHLIB_LINK += $(filter -lm, $(LIBS))
2223

contrib/btree_gist/btree_enum.c

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
/*
2+
* contrib/btree_gist/btree_enum.c
3+
*/
4+
#include "postgres.h"
5+
#include "fmgr.h"
6+
#include "utils/builtins.h"
7+
8+
#include "btree_gist.h"
9+
#include "btree_utils_num.h"
10+
11+
/* enums are really Oids, so we just use the same structure */
12+
13+
typedef struct
14+
{
15+
Oid lower;
16+
Oid upper;
17+
} oidKEY;
18+
19+
/*
20+
** enum ops
21+
*/
22+
PG_FUNCTION_INFO_V1(gbt_enum_compress);
23+
PG_FUNCTION_INFO_V1(gbt_enum_fetch);
24+
PG_FUNCTION_INFO_V1(gbt_enum_union);
25+
PG_FUNCTION_INFO_V1(gbt_enum_picksplit);
26+
PG_FUNCTION_INFO_V1(gbt_enum_consistent);
27+
PG_FUNCTION_INFO_V1(gbt_enum_penalty);
28+
PG_FUNCTION_INFO_V1(gbt_enum_same);
29+
30+
31+
static bool
32+
gbt_enumgt(const void *a, const void *b, FmgrInfo *flinfo)
33+
{
34+
return DatumGetBool(
35+
CallerFInfoFunctionCall2(enum_gt, flinfo, InvalidOid, ObjectIdGetDatum(*((const Oid *) a)), ObjectIdGetDatum(*((const Oid *) b)))
36+
);
37+
}
38+
static bool
39+
gbt_enumge(const void *a, const void *b, FmgrInfo *flinfo)
40+
{
41+
return DatumGetBool(
42+
CallerFInfoFunctionCall2(enum_ge, flinfo, InvalidOid, ObjectIdGetDatum(*((const Oid *) a)), ObjectIdGetDatum(*((const Oid *) b)))
43+
);
44+
}
45+
static bool
46+
gbt_enumeq(const void *a, const void *b, FmgrInfo *flinfo)
47+
{
48+
return (*((const Oid *) a) == *((const Oid *) b));
49+
}
50+
static bool
51+
gbt_enumle(const void *a, const void *b, FmgrInfo *flinfo)
52+
{
53+
return DatumGetBool(
54+
CallerFInfoFunctionCall2(enum_le, flinfo, InvalidOid, ObjectIdGetDatum(*((const Oid *) a)), ObjectIdGetDatum(*((const Oid *) b)))
55+
);
56+
}
57+
static bool
58+
gbt_enumlt(const void *a, const void *b, FmgrInfo *flinfo)
59+
{
60+
return DatumGetBool(
61+
CallerFInfoFunctionCall2(enum_lt, flinfo, InvalidOid, ObjectIdGetDatum(*((const Oid *) a)), ObjectIdGetDatum(*((const Oid *) b)))
62+
);
63+
}
64+
65+
static int
66+
gbt_enumkey_cmp(const void *a, const void *b, FmgrInfo *flinfo)
67+
{
68+
oidKEY *ia = (oidKEY *) (((const Nsrt *) a)->t);
69+
oidKEY *ib = (oidKEY *) (((const Nsrt *) b)->t);
70+
71+
if (ia->lower == ib->lower)
72+
{
73+
if (ia->upper == ib->upper)
74+
return 0;
75+
76+
return DatumGetInt32(
77+
CallerFInfoFunctionCall2(enum_cmp, flinfo, InvalidOid, ObjectIdGetDatum(ia->upper), ObjectIdGetDatum(ib->upper))
78+
);
79+
}
80+
81+
return DatumGetInt32(
82+
CallerFInfoFunctionCall2(enum_cmp, flinfo, InvalidOid, ObjectIdGetDatum(ia->lower), ObjectIdGetDatum(ib->lower))
83+
);
84+
}
85+
86+
static const gbtree_ninfo tinfo =
87+
{
88+
gbt_t_enum,
89+
sizeof(Oid),
90+
8, /* sizeof(gbtreekey8) */
91+
gbt_enumgt,
92+
gbt_enumge,
93+
gbt_enumeq,
94+
gbt_enumle,
95+
gbt_enumlt,
96+
gbt_enumkey_cmp,
97+
NULL /* no KNN support at least for now */
98+
};
99+
100+
101+
/**************************************************
102+
* Enum ops
103+
**************************************************/
104+
105+
106+
Datum
107+
gbt_enum_compress(PG_FUNCTION_ARGS)
108+
{
109+
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
110+
111+
PG_RETURN_POINTER(gbt_num_compress(entry, &tinfo));
112+
}
113+
114+
Datum
115+
gbt_enum_fetch(PG_FUNCTION_ARGS)
116+
{
117+
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
118+
119+
PG_RETURN_POINTER(gbt_num_fetch(entry, &tinfo));
120+
}
121+
122+
Datum
123+
gbt_enum_consistent(PG_FUNCTION_ARGS)
124+
{
125+
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
126+
Oid query = PG_GETARG_OID(1);
127+
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
128+
129+
/* Oid subtype = PG_GETARG_OID(3); */
130+
bool *recheck = (bool *) PG_GETARG_POINTER(4);
131+
oidKEY *kkk = (oidKEY *) DatumGetPointer(entry->key);
132+
GBT_NUMKEY_R key;
133+
134+
/* All cases served by this function are exact */
135+
*recheck = false;
136+
137+
key.lower = (GBT_NUMKEY *) &kkk->lower;
138+
key.upper = (GBT_NUMKEY *) &kkk->upper;
139+
140+
PG_RETURN_BOOL(
141+
gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
142+
);
143+
}
144+
145+
Datum
146+
gbt_enum_union(PG_FUNCTION_ARGS)
147+
{
148+
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
149+
void *out = palloc(sizeof(oidKEY));
150+
151+
*(int *) PG_GETARG_POINTER(1) = sizeof(oidKEY);
152+
PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo));
153+
}
154+
155+
156+
Datum
157+
gbt_enum_penalty(PG_FUNCTION_ARGS)
158+
{
159+
oidKEY *origentry = (oidKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
160+
oidKEY *newentry = (oidKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
161+
float *result = (float *) PG_GETARG_POINTER(2);
162+
163+
penalty_num(result, origentry->lower, origentry->upper, newentry->lower, newentry->upper);
164+
165+
PG_RETURN_POINTER(result);
166+
}
167+
168+
Datum
169+
gbt_enum_picksplit(PG_FUNCTION_ARGS)
170+
{
171+
PG_RETURN_POINTER(gbt_num_picksplit(
172+
(GistEntryVector *) PG_GETARG_POINTER(0),
173+
(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
174+
&tinfo, fcinfo->flinfo
175+
));
176+
}
177+
178+
Datum
179+
gbt_enum_same(PG_FUNCTION_ARGS)
180+
{
181+
oidKEY *b1 = (oidKEY *) PG_GETARG_POINTER(0);
182+
oidKEY *b2 = (oidKEY *) PG_GETARG_POINTER(1);
183+
bool *result = (bool *) PG_GETARG_POINTER(2);
184+
185+
*result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
186+
PG_RETURN_POINTER(result);
187+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/* contrib/btree_gist/btree_gist--1.4--1.5.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.5'" to load this file. \quit
5+
6+
--
7+
--
8+
--
9+
-- enum ops
10+
--
11+
--
12+
--
13+
-- define the GiST support methods
14+
CREATE FUNCTION gbt_enum_consistent(internal,anyenum,int2,oid,internal)
15+
RETURNS bool
16+
AS 'MODULE_PATHNAME'
17+
LANGUAGE C IMMUTABLE STRICT;
18+
19+
CREATE FUNCTION gbt_enum_compress(internal)
20+
RETURNS internal
21+
AS 'MODULE_PATHNAME'
22+
LANGUAGE C IMMUTABLE STRICT;
23+
24+
CREATE FUNCTION gbt_enum_fetch(internal)
25+
RETURNS internal
26+
AS 'MODULE_PATHNAME'
27+
LANGUAGE C IMMUTABLE STRICT;
28+
29+
CREATE FUNCTION gbt_enum_penalty(internal,internal,internal)
30+
RETURNS internal
31+
AS 'MODULE_PATHNAME'
32+
LANGUAGE C IMMUTABLE STRICT;
33+
34+
CREATE FUNCTION gbt_enum_picksplit(internal, internal)
35+
RETURNS internal
36+
AS 'MODULE_PATHNAME'
37+
LANGUAGE C IMMUTABLE STRICT;
38+
39+
CREATE FUNCTION gbt_enum_union(internal, internal)
40+
RETURNS gbtreekey8
41+
AS 'MODULE_PATHNAME'
42+
LANGUAGE C IMMUTABLE STRICT;
43+
44+
CREATE FUNCTION gbt_enum_same(gbtreekey8, gbtreekey8, internal)
45+
RETURNS internal
46+
AS 'MODULE_PATHNAME'
47+
LANGUAGE C IMMUTABLE STRICT;
48+
49+
-- Create the operator class
50+
CREATE OPERATOR CLASS gist_enum_ops
51+
DEFAULT FOR TYPE anyenum USING gist
52+
AS
53+
OPERATOR 1 < ,
54+
OPERATOR 2 <= ,
55+
OPERATOR 3 = ,
56+
OPERATOR 4 >= ,
57+
OPERATOR 5 > ,
58+
FUNCTION 1 gbt_enum_consistent (internal, anyenum, int2, oid, internal),
59+
FUNCTION 2 gbt_enum_union (internal, internal),
60+
FUNCTION 3 gbt_enum_compress (internal),
61+
FUNCTION 4 gbt_decompress (internal),
62+
FUNCTION 5 gbt_enum_penalty (internal, internal, internal),
63+
FUNCTION 6 gbt_enum_picksplit (internal, internal),
64+
FUNCTION 7 gbt_enum_same (gbtreekey8, gbtreekey8, internal),
65+
STORAGE gbtreekey8;
66+
67+
ALTER OPERATOR FAMILY gist_enum_ops USING gist ADD
68+
OPERATOR 6 <> (anyenum, anyenum) ,
69+
FUNCTION 9 (anyenum, anyenum) gbt_enum_fetch (internal) ;

contrib/btree_gist/btree_gist.control

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

contrib/btree_gist/btree_gist.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ enum gbtree_type
3333
gbt_t_bytea,
3434
gbt_t_bit,
3535
gbt_t_inet,
36-
gbt_t_uuid
36+
gbt_t_uuid,
37+
gbt_t_enum
3738
};
3839

3940
#endif

contrib/btree_gist/btree_utils_num.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ gbt_num_compress(GISTENTRY *entry, const gbtree_ninfo *tinfo)
4848
leaf = &v.i8;
4949
break;
5050
case gbt_t_oid:
51+
case gbt_t_enum:
5152
v.i4 = DatumGetObjectId(entry->key);
5253
leaf = &v.i4;
5354
break;
@@ -122,6 +123,7 @@ gbt_num_fetch(GISTENTRY *entry, const gbtree_ninfo *tinfo)
122123
datum = Int64GetDatum(*(int64 *) entry->key);
123124
break;
124125
case gbt_t_oid:
126+
case gbt_t_enum:
125127
datum = ObjectIdGetDatum(*(Oid *) entry->key);
126128
break;
127129
case gbt_t_float4:

0 commit comments

Comments
 (0)