PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
blvalidate.c File Reference
#include "postgres.h"
#include "access/amvalidate.h"
#include "access/htup_details.h"
#include "bloom.h"
#include "catalog/pg_amop.h"
#include "catalog/pg_amproc.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_opfamily.h"
#include "catalog/pg_type.h"
#include "utils/regproc.h"
#include "utils/syscache.h"
Include dependency graph for blvalidate.c:

Go to the source code of this file.

Functions

bool blvalidate (Oid opclassoid)
 

Function Documentation

◆ blvalidate()

bool blvalidate ( Oid  opclassoid)

Definition at line 30 of file blvalidate.c.

31{
32 bool result = true;
33 HeapTuple classtup;
34 Form_pg_opclass classform;
35 Oid opfamilyoid;
36 Oid opcintype;
37 Oid opckeytype;
38 char *opclassname;
39 HeapTuple familytup;
40 Form_pg_opfamily familyform;
41 char *opfamilyname;
42 CatCList *proclist,
43 *oprlist;
44 List *grouplist;
45 OpFamilyOpFuncGroup *opclassgroup;
46 int i;
47 ListCell *lc;
48
49 /* Fetch opclass information */
50 classtup = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclassoid));
51 if (!HeapTupleIsValid(classtup))
52 elog(ERROR, "cache lookup failed for operator class %u", opclassoid);
53 classform = (Form_pg_opclass) GETSTRUCT(classtup);
54
55 opfamilyoid = classform->opcfamily;
56 opcintype = classform->opcintype;
57 opckeytype = classform->opckeytype;
58 if (!OidIsValid(opckeytype))
59 opckeytype = opcintype;
60 opclassname = NameStr(classform->opcname);
61
62 /* Fetch opfamily information */
63 familytup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfamilyoid));
64 if (!HeapTupleIsValid(familytup))
65 elog(ERROR, "cache lookup failed for operator family %u", opfamilyoid);
66 familyform = (Form_pg_opfamily) GETSTRUCT(familytup);
67
68 opfamilyname = NameStr(familyform->opfname);
69
70 /* Fetch all operators and support functions of the opfamily */
71 oprlist = SearchSysCacheList1(AMOPSTRATEGY, ObjectIdGetDatum(opfamilyoid));
72 proclist = SearchSysCacheList1(AMPROCNUM, ObjectIdGetDatum(opfamilyoid));
73
74 /* Check individual support functions */
75 for (i = 0; i < proclist->n_members; i++)
76 {
77 HeapTuple proctup = &proclist->members[i]->tuple;
78 Form_pg_amproc procform = (Form_pg_amproc) GETSTRUCT(proctup);
79 bool ok;
80
81 /*
82 * All bloom support functions should be registered with matching
83 * left/right types
84 */
85 if (procform->amproclefttype != procform->amprocrighttype)
86 {
88 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
89 errmsg("bloom opfamily %s contains support procedure %s with cross-type registration",
90 opfamilyname,
91 format_procedure(procform->amproc))));
92 result = false;
93 }
94
95 /*
96 * We can't check signatures except within the specific opclass, since
97 * we need to know the associated opckeytype in many cases.
98 */
99 if (procform->amproclefttype != opcintype)
100 continue;
101
102 /* Check procedure numbers and function signatures */
103 switch (procform->amprocnum)
104 {
105 case BLOOM_HASH_PROC:
106 ok = check_amproc_signature(procform->amproc, INT4OID, false,
107 1, 1, opckeytype);
108 break;
110 ok = check_amoptsproc_signature(procform->amproc);
111 break;
112 default:
114 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
115 errmsg("bloom opfamily %s contains function %s with invalid support number %d",
116 opfamilyname,
117 format_procedure(procform->amproc),
118 procform->amprocnum)));
119 result = false;
120 continue; /* don't want additional message */
121 }
122
123 if (!ok)
124 {
126 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
127 errmsg("gist opfamily %s contains function %s with wrong signature for support number %d",
128 opfamilyname,
129 format_procedure(procform->amproc),
130 procform->amprocnum)));
131 result = false;
132 }
133 }
134
135 /* Check individual operators */
136 for (i = 0; i < oprlist->n_members; i++)
137 {
138 HeapTuple oprtup = &oprlist->members[i]->tuple;
139 Form_pg_amop oprform = (Form_pg_amop) GETSTRUCT(oprtup);
140
141 /* Check it's allowed strategy for bloom */
142 if (oprform->amopstrategy < 1 ||
143 oprform->amopstrategy > BLOOM_NSTRATEGIES)
144 {
146 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
147 errmsg("bloom opfamily %s contains operator %s with invalid strategy number %d",
148 opfamilyname,
149 format_operator(oprform->amopopr),
150 oprform->amopstrategy)));
151 result = false;
152 }
153
154 /* bloom doesn't support ORDER BY operators */
155 if (oprform->amoppurpose != AMOP_SEARCH ||
156 OidIsValid(oprform->amopsortfamily))
157 {
159 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
160 errmsg("bloom opfamily %s contains invalid ORDER BY specification for operator %s",
161 opfamilyname,
162 format_operator(oprform->amopopr))));
163 result = false;
164 }
165
166 /* Check operator signature --- same for all bloom strategies */
167 if (!check_amop_signature(oprform->amopopr, BOOLOID,
168 oprform->amoplefttype,
169 oprform->amoprighttype))
170 {
172 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
173 errmsg("bloom opfamily %s contains operator %s with wrong signature",
174 opfamilyname,
175 format_operator(oprform->amopopr))));
176 result = false;
177 }
178 }
179
180 /* Now check for inconsistent groups of operators/functions */
181 grouplist = identify_opfamily_groups(oprlist, proclist);
182 opclassgroup = NULL;
183 foreach(lc, grouplist)
184 {
186
187 /* Remember the group exactly matching the test opclass */
188 if (thisgroup->lefttype == opcintype &&
189 thisgroup->righttype == opcintype)
190 opclassgroup = thisgroup;
191
192 /*
193 * There is not a lot we can do to check the operator sets, since each
194 * bloom opclass is more or less a law unto itself, and some contain
195 * only operators that are binary-compatible with the opclass datatype
196 * (meaning that empty operator sets can be OK). That case also means
197 * that we shouldn't insist on nonempty function sets except for the
198 * opclass's own group.
199 */
200 }
201
202 /* Check that the originally-named opclass is complete */
203 for (i = 1; i <= BLOOM_NPROC; i++)
204 {
205 if (opclassgroup &&
206 (opclassgroup->functionset & (((uint64) 1) << i)) != 0)
207 continue; /* got it */
208 if (i == BLOOM_OPTIONS_PROC)
209 continue; /* optional method */
211 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
212 errmsg("bloom opclass %s is missing support function %d",
213 opclassname, i)));
214 result = false;
215 }
216
217 ReleaseCatCacheList(proclist);
218 ReleaseCatCacheList(oprlist);
219 ReleaseSysCache(familytup);
220 ReleaseSysCache(classtup);
221
222 return result;
223}
bool check_amproc_signature(Oid funcid, Oid restype, bool exact, int minargs, int maxargs,...)
Definition: amvalidate.c:152
bool check_amop_signature(Oid opno, Oid restype, Oid lefttype, Oid righttype)
Definition: amvalidate.c:206
List * identify_opfamily_groups(CatCList *oprlist, CatCList *proclist)
Definition: amvalidate.c:43
bool check_amoptsproc_signature(Oid funcid)
Definition: amvalidate.c:192
#define BLOOM_HASH_PROC
Definition: bloom.h:24
#define BLOOM_NPROC
Definition: bloom.h:26
#define BLOOM_NSTRATEGIES
Definition: bloom.h:30
#define BLOOM_OPTIONS_PROC
Definition: bloom.h:25
#define NameStr(name)
Definition: c.h:700
uint64_t uint64
Definition: c.h:486
#define OidIsValid(objectId)
Definition: c.h:729
void ReleaseCatCacheList(CatCList *list)
Definition: catcache.c:1985
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define INFO
Definition: elog.h:34
#define ereport(elevel,...)
Definition: elog.h:149
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
int i
Definition: isn.c:72
FormData_pg_amop * Form_pg_amop
Definition: pg_amop.h:88
FormData_pg_amproc * Form_pg_amproc
Definition: pg_amproc.h:68
#define lfirst(lc)
Definition: pg_list.h:172
FormData_pg_opclass * Form_pg_opclass
Definition: pg_opclass.h:83
FormData_pg_opfamily * Form_pg_opfamily
Definition: pg_opfamily.h:51
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
unsigned int Oid
Definition: postgres_ext.h:31
char * format_procedure(Oid procedure_oid)
Definition: regproc.c:299
char * format_operator(Oid operator_oid)
Definition: regproc.c:793
Definition: pg_list.h:54
CatCTup * members[FLEXIBLE_ARRAY_MEMBER]
Definition: catcache.h:180
int n_members
Definition: catcache.h:178
HeapTupleData tuple
Definition: catcache.h:123
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221
#define SearchSysCacheList1(cacheId, key1)
Definition: syscache.h:127

References BLOOM_HASH_PROC, BLOOM_NPROC, BLOOM_NSTRATEGIES, BLOOM_OPTIONS_PROC, check_amop_signature(), check_amoptsproc_signature(), check_amproc_signature(), elog, ereport, errcode(), errmsg(), ERROR, format_operator(), format_procedure(), OpFamilyOpFuncGroup::functionset, GETSTRUCT, HeapTupleIsValid, i, identify_opfamily_groups(), INFO, OpFamilyOpFuncGroup::lefttype, lfirst, catclist::members, catclist::n_members, NameStr, ObjectIdGetDatum(), OidIsValid, ReleaseCatCacheList(), ReleaseSysCache(), OpFamilyOpFuncGroup::righttype, SearchSysCache1(), SearchSysCacheList1, and catctup::tuple.

Referenced by blhandler().