41{
42 bool result = true;
47 char *opclassname;
48 char *opfamilyname;
50 *oprlist;
54 int usefulgroups;
57
58 /* Fetch opclass information */
61 elog(
ERROR,
"cache lookup failed for operator class %u", opclassoid);
63
64 opfamilyoid = classform->opcfamily;
65 opcintype = classform->opcintype;
66 opclassname =
NameStr(classform->opcname);
67
68 /* Fetch opfamily information */
70
71 /* Fetch all operators and support functions of the opfamily */
74
75 /* Check individual support functions */
77 {
80 bool ok;
81
82 /* Check procedure numbers and function signatures */
83 switch (procform->amprocnum)
84 {
87 2, 2, procform->amproclefttype,
88 procform->amprocrighttype);
89 break;
92 1, 1, INTERNALOID);
93 break;
96 5, 5,
97 procform->amproclefttype,
98 procform->amproclefttype,
99 procform->amprocrighttype,
100 BOOLOID, BOOLOID);
101 break;
104 1, 1, OIDOID);
105 break;
108 break;
111 1, 1, INTERNALOID);
112 break;
113 default:
115 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
116 errmsg(
"operator family \"%s\" of access method %s contains function %s with invalid support number %d",
117 opfamilyname, "btree",
119 procform->amprocnum)));
120 result = false;
121 continue; /* don't want additional message */
122 }
123
124 if (!ok)
125 {
127 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
128 errmsg(
"operator family \"%s\" of access method %s contains function %s with wrong signature for support number %d",
129 opfamilyname, "btree",
131 procform->amprocnum)));
132 result = false;
133 }
134 }
135
136 /* Check individual operators */
138 {
141
142 /* Check that only allowed strategy numbers exist */
143 if (oprform->amopstrategy < 1 ||
145 {
147 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
148 errmsg(
"operator family \"%s\" of access method %s contains operator %s with invalid strategy number %d",
149 opfamilyname, "btree",
151 oprform->amopstrategy)));
152 result = false;
153 }
154
155 /* btree doesn't support ORDER BY operators */
156 if (oprform->amoppurpose != AMOP_SEARCH ||
158 {
160 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
161 errmsg(
"operator family \"%s\" of access method %s contains invalid ORDER BY specification for operator %s",
162 opfamilyname, "btree",
164 result = false;
165 }
166
167 /* Check operator signature --- same for all btree strategies */
169 oprform->amoplefttype,
170 oprform->amoprighttype))
171 {
173 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
174 errmsg(
"operator family \"%s\" of access method %s contains operator %s with wrong signature",
175 opfamilyname, "btree",
177 result = false;
178 }
179 }
180
181 /* Now check for inconsistent groups of operators/functions */
183 usefulgroups = 0;
184 opclassgroup = NULL;
186 foreach(lc, grouplist)
187 {
189
190 /*
191 * It is possible for an in_range support function to have a RHS type
192 * that is otherwise irrelevant to the opfamily --- for instance, SQL
193 * requires the datetime_ops opclass to have range support with an
194 * interval offset. So, if this group appears to contain only an
195 * in_range function, ignore it: it doesn't represent a pair of
196 * supported types.
197 */
200 continue;
201
202 /* Else count it as a relevant group */
203 usefulgroups++;
204
205 /* Remember the group exactly matching the test opclass */
206 if (thisgroup->
lefttype == opcintype &&
208 opclassgroup = thisgroup;
209
210 /*
211 * Identify all distinct data types handled in this opfamily. This
212 * implementation is O(N^2), but there aren't likely to be enough
213 * types in the family for it to matter.
214 */
217
218 /*
219 * Complain if there seems to be an incomplete set of either operators
220 * or support functions for this datatype pair. The sortsupport,
221 * in_range, and equalimage functions are considered optional.
222 */
229 {
231 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
232 errmsg(
"operator family \"%s\" of access method %s is missing operator(s) for types %s and %s",
233 opfamilyname, "btree",
236 result = false;
237 }
239 {
241 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
242 errmsg(
"operator family \"%s\" of access method %s is missing support function for types %s and %s",
243 opfamilyname, "btree",
246 result = false;
247 }
248 }
249
250 /* Check that the originally-named opclass is supported */
251 /* (if group is there, we already checked it adequately above) */
252 if (!opclassgroup)
253 {
255 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
256 errmsg(
"operator class \"%s\" of access method %s is missing operator(s)",
257 opclassname, "btree")));
258 result = false;
259 }
260
261 /*
262 * Complain if the opfamily doesn't have entries for all possible
263 * combinations of its supported datatypes. While missing cross-type
264 * operators are not fatal, they do limit the planner's ability to derive
265 * additional qual clauses from equivalence classes, so it seems
266 * reasonable to insist that all built-in btree opfamilies be complete.
267 */
269 {
271 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
272 errmsg(
"operator family \"%s\" of access method %s is missing cross-type operator(s)",
273 opfamilyname, "btree")));
274 result = false;
275 }
276
280
281 return result;
282}
bool check_amproc_signature(Oid funcid, Oid restype, bool exact, int minargs, int maxargs,...)
bool check_amop_signature(Oid opno, Oid restype, Oid lefttype, Oid righttype)
List * identify_opfamily_groups(CatCList *oprlist, CatCList *proclist)
bool check_amoptsproc_signature(Oid funcid)
void ReleaseCatCacheList(CatCList *list)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
#define HeapTupleIsValid(tuple)
static void * GETSTRUCT(const HeapTupleData *tuple)
List * list_append_unique_oid(List *list, Oid datum)
char * get_opfamily_name(Oid opfid, bool missing_ok)
#define BTEQUALIMAGE_PROC
#define BTSKIPSUPPORT_PROC
#define BTSORTSUPPORT_PROC
FormData_pg_amop * Form_pg_amop
FormData_pg_amproc * Form_pg_amproc
static int list_length(const List *l)
FormData_pg_opclass * Form_pg_opclass
static Datum ObjectIdGetDatum(Oid X)
char * format_procedure(Oid procedure_oid)
char * format_operator(Oid operator_oid)
#define BTGreaterStrategyNumber
#define BTMaxStrategyNumber
#define BTLessStrategyNumber
#define BTEqualStrategyNumber
#define BTLessEqualStrategyNumber
#define BTGreaterEqualStrategyNumber
CatCTup * members[FLEXIBLE_ARRAY_MEMBER]
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
#define SearchSysCacheList1(cacheId, key1)