PostgreSQL Source Code  git master
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/builtins.h"
#include "utils/lsyscache.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 32 of file blvalidate.c.

References AMOPSTRATEGY, AMPROCNUM, BLOOM_HASH_PROC, BLOOM_NPROC, BLOOM_NSTRATEGIES, check_amop_signature(), check_amproc_signature(), CLAOID, 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, OPFAMILYOID, ReleaseCatCacheList(), ReleaseSysCache(), OpFamilyOpFuncGroup::righttype, SearchSysCache1(), SearchSysCacheList1, and catctup::tuple.

Referenced by blhandler().

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