PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
blvalidate.c File Reference
#include "postgres.h"
#include "access/amvalidate.h"
#include "access/htup_details.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 "bloom.h"
Include dependency graph for blvalidate.c:

Go to the source code of this file.

Functions

bool blvalidate (Oid opclassoid)
 

Function Documentation

bool blvalidate ( Oid  opclassoid)

Definition at line 33 of file blvalidate.c.

References AMOP_SEARCH, AMOPSTRATEGY, AMPROCNUM, BLOOM_HASH_PROC, BLOOM_NPROC, BLOOM_NSTRATEGIES, BOOLOID, 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, INT4OID, OpFamilyOpFuncGroup::lefttype, lfirst, catclist::members, catclist::n_members, NameStr, ObjectIdGetDatum, OidIsValid, OPFAMILYOID, ReleaseCatCacheList(), ReleaseSysCache(), OpFamilyOpFuncGroup::righttype, SearchSysCache1, SearchSysCacheList1, and catctup::tuple.

Referenced by blhandler().

34 {
35  bool result = true;
36  HeapTuple classtup;
37  Form_pg_opclass classform;
38  Oid opfamilyoid;
39  Oid opcintype;
40  Oid opckeytype;
41  char *opclassname;
42  HeapTuple familytup;
43  Form_pg_opfamily familyform;
44  char *opfamilyname;
45  CatCList *proclist,
46  *oprlist;
47  List *grouplist;
48  OpFamilyOpFuncGroup *opclassgroup;
49  int i;
50  ListCell *lc;
51 
52  /* Fetch opclass information */
53  classtup = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclassoid));
54  if (!HeapTupleIsValid(classtup))
55  elog(ERROR, "cache lookup failed for operator class %u", opclassoid);
56  classform = (Form_pg_opclass) GETSTRUCT(classtup);
57 
58  opfamilyoid = classform->opcfamily;
59  opcintype = classform->opcintype;
60  opckeytype = classform->opckeytype;
61  if (!OidIsValid(opckeytype))
62  opckeytype = opcintype;
63  opclassname = NameStr(classform->opcname);
64 
65  /* Fetch opfamily information */
66  familytup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfamilyoid));
67  if (!HeapTupleIsValid(familytup))
68  elog(ERROR, "cache lookup failed for operator family %u", opfamilyoid);
69  familyform = (Form_pg_opfamily) GETSTRUCT(familytup);
70 
71  opfamilyname = NameStr(familyform->opfname);
72 
73  /* Fetch all operators and support functions of the opfamily */
74  oprlist = SearchSysCacheList1(AMOPSTRATEGY, ObjectIdGetDatum(opfamilyoid));
75  proclist = SearchSysCacheList1(AMPROCNUM, ObjectIdGetDatum(opfamilyoid));
76 
77  /* Check individual support functions */
78  for (i = 0; i < proclist->n_members; i++)
79  {
80  HeapTuple proctup = &proclist->members[i]->tuple;
81  Form_pg_amproc procform = (Form_pg_amproc) GETSTRUCT(proctup);
82  bool ok;
83 
84  /*
85  * All bloom support functions should be registered with matching
86  * left/right types
87  */
88  if (procform->amproclefttype != procform->amprocrighttype)
89  {
90  ereport(INFO,
91  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
92  errmsg("bloom opfamily %s contains support procedure %s with cross-type registration",
93  opfamilyname,
94  format_procedure(procform->amproc))));
95  result = false;
96  }
97 
98  /*
99  * We can't check signatures except within the specific opclass, since
100  * we need to know the associated opckeytype in many cases.
101  */
102  if (procform->amproclefttype != opcintype)
103  continue;
104 
105  /* Check procedure numbers and function signatures */
106  switch (procform->amprocnum)
107  {
108  case BLOOM_HASH_PROC:
109  ok = check_amproc_signature(procform->amproc, INT4OID, false,
110  1, 1, opckeytype);
111  break;
112  default:
113  ereport(INFO,
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  {
125  ereport(INFO,
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  {
145  ereport(INFO,
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  {
158  ereport(INFO,
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  {
171  ereport(INFO,
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  {
185  OpFamilyOpFuncGroup *thisgroup = (OpFamilyOpFuncGroup *) lfirst(lc);
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  ereport(INFO,
209  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
210  errmsg("bloom opclass %s is missing support function %d",
211  opclassname, i)));
212  result = false;
213  }
214 
215  ReleaseCatCacheList(proclist);
216  ReleaseCatCacheList(oprlist);
217  ReleaseSysCache(familytup);
218  ReleaseSysCache(classtup);
219 
220  return result;
221 }
int n_members
Definition: catcache.h:154
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define AMOP_SEARCH
Definition: pg_amop.h:69
FormData_pg_amproc * Form_pg_amproc
Definition: pg_amproc.h:59
#define BLOOM_NPROC
Definition: bloom.h:25
#define INT4OID
Definition: pg_type.h:316
int errcode(int sqlerrcode)
Definition: elog.c:575
#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:532
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:159
void ReleaseCatCacheList(CatCList *list)
Definition: catcache.c:1601
CatCTup * members[FLEXIBLE_ARRAY_MEMBER]
Definition: catcache.h:155
bool check_amproc_signature(Oid funcid, Oid restype, bool exact, int minargs, int maxargs,...)
Definition: amvalidate.c:150
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#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:204
#define ereport(elevel, rest)
Definition: elog.h:122
#define BLOOM_NSTRATEGIES
Definition: bloom.h:29
FormData_pg_opfamily * Form_pg_opfamily
Definition: pg_opfamily.h:44
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
char * format_procedure(Oid procedure_oid)
Definition: regproc.c:323
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define lfirst(lc)
Definition: pg_list.h:106
bool check_amop_signature(Oid opno, Oid restype, Oid lefttype, Oid righttype)
Definition: amvalidate.c:194
#define BOOLOID
Definition: pg_type.h:288
int errmsg(const char *fmt,...)
Definition: elog.c:797
FormData_pg_amop * Form_pg_amop
Definition: pg_amop.h:77
int i
#define NameStr(name)
Definition: c.h:493
HeapTupleData tuple
Definition: catcache.h:116
#define elog
Definition: elog.h:219
FormData_pg_opclass * Form_pg_opclass
Definition: pg_opclass.h:68
Definition: pg_list.h:45
#define BLOOM_HASH_PROC
Definition: bloom.h:24