PostgreSQL Source Code git master
Loading...
Searching...
No Matches
amutils.c File Reference
#include "postgres.h"
#include "access/amapi.h"
#include "access/htup_details.h"
#include "catalog/pg_class.h"
#include "catalog/pg_index.h"
#include "utils/builtins.h"
#include "utils/syscache.h"
Include dependency graph for amutils.c:

Go to the source code of this file.

Data Structures

struct  am_propname
 

Functions

static IndexAMProperty lookup_prop_name (const char *name)
 
static bool test_indoption (HeapTuple tuple, int attno, bool guard, int16 iopt_mask, int16 iopt_expect, bool *res)
 
static Datum indexam_property (FunctionCallInfo fcinfo, const char *propname, Oid amoid, Oid index_oid, int attno)
 
Datum pg_indexam_has_property (PG_FUNCTION_ARGS)
 
Datum pg_index_has_property (PG_FUNCTION_ARGS)
 
Datum pg_index_column_has_property (PG_FUNCTION_ARGS)
 
Datum pg_indexam_progress_phasename (PG_FUNCTION_ARGS)
 

Variables

static const struct am_propname am_propnames []
 

Function Documentation

◆ indexam_property()

static Datum indexam_property ( FunctionCallInfo  fcinfo,
const char propname,
Oid  amoid,
Oid  index_oid,
int  attno 
)
static

Definition at line 149 of file amutils.c.

152{
153 bool res = false;
154 bool isnull = false;
155 int natts = 0;
156 IndexAMProperty prop;
157 const IndexAmRoutine *routine;
158
159 /* Try to convert property name to enum (no error if not known) */
161
162 /* If we have an index OID, look up the AM, and get # of columns too */
164 {
165 HeapTuple tuple;
166 Form_pg_class rd_rel;
167
170 if (!HeapTupleIsValid(tuple))
172 rd_rel = (Form_pg_class) GETSTRUCT(tuple);
173 if (rd_rel->relkind != RELKIND_INDEX &&
174 rd_rel->relkind != RELKIND_PARTITIONED_INDEX)
175 {
176 ReleaseSysCache(tuple);
178 }
179 amoid = rd_rel->relam;
180 natts = rd_rel->relnatts;
181 ReleaseSysCache(tuple);
182 }
183
184 /*
185 * At this point, either index_oid == InvalidOid or it's a valid index
186 * OID. Also, after this test and the one below, either attno == 0 for
187 * index-wide or AM-wide tests, or it's a valid column number in a valid
188 * index.
189 */
190 if (attno < 0 || attno > natts)
192
193 /*
194 * Get AM information. If we don't have a valid AM OID, return NULL.
195 */
196 routine = GetIndexAmRoutineByAmId(amoid, true);
197 if (routine == NULL)
199
200 /*
201 * If there's an AM property routine, give it a chance to override the
202 * generic logic. Proceed if it returns false.
203 */
204 if (routine->amproperty &&
205 routine->amproperty(index_oid, attno, prop, propname,
206 &res, &isnull))
207 {
208 if (isnull)
210 PG_RETURN_BOOL(res);
211 }
212
213 if (attno > 0)
214 {
215 HeapTuple tuple;
216 Form_pg_index rd_index;
217 bool iskey = true;
218
219 /*
220 * Handle column-level properties. Many of these need the pg_index row
221 * (which we also need to use to check for nonkey atts) so we fetch
222 * that first.
223 */
225 if (!HeapTupleIsValid(tuple))
227 rd_index = (Form_pg_index) GETSTRUCT(tuple);
228
229 Assert(index_oid == rd_index->indexrelid);
231
232 isnull = true;
233
234 /*
235 * If amcaninclude, we might be looking at an attno for a nonkey
236 * column, for which we (generically) assume that most properties are
237 * null.
238 */
239 if (routine->amcaninclude
240 && attno > rd_index->indnkeyatts)
241 iskey = false;
242
243 switch (prop)
244 {
245 case AMPROP_ASC:
246 if (iskey &&
247 test_indoption(tuple, attno, routine->amcanorder,
248 INDOPTION_DESC, 0, &res))
249 isnull = false;
250 break;
251
252 case AMPROP_DESC:
253 if (iskey &&
254 test_indoption(tuple, attno, routine->amcanorder,
256 isnull = false;
257 break;
258
260 if (iskey &&
261 test_indoption(tuple, attno, routine->amcanorder,
263 isnull = false;
264 break;
265
267 if (iskey &&
268 test_indoption(tuple, attno, routine->amcanorder,
269 INDOPTION_NULLS_FIRST, 0, &res))
270 isnull = false;
271 break;
272
273 case AMPROP_ORDERABLE:
274
275 /*
276 * generic assumption is that nonkey columns are not orderable
277 */
278 res = iskey ? routine->amcanorder : false;
279 isnull = false;
280 break;
281
283
284 /*
285 * The conditions for whether a column is distance-orderable
286 * are really up to the AM (at time of writing, only GiST
287 * supports it at all). The planner has its own idea based on
288 * whether it finds an operator with amoppurpose 'o', but
289 * getting there from just the index column type seems like a
290 * lot of work. So instead we expect the AM to handle this in
291 * its amproperty routine. The generic result is to return
292 * false if the AM says it never supports this, or if this is
293 * a nonkey column, and null otherwise (meaning we don't
294 * know).
295 */
296 if (!iskey || !routine->amcanorderbyop)
297 {
298 res = false;
299 isnull = false;
300 }
301 break;
302
304
305 /* note that we ignore iskey for this property */
306
307 isnull = false;
308 res = false;
309
310 if (routine->amcanreturn)
311 {
312 /*
313 * If possible, the AM should handle this test in its
314 * amproperty function without opening the rel. But this
315 * is the generic fallback if it does not.
316 */
318
319 res = index_can_return(indexrel, attno);
320 index_close(indexrel, AccessShareLock);
321 }
322 break;
323
325 if (iskey)
326 {
327 res = routine->amsearcharray;
328 isnull = false;
329 }
330 break;
331
333 if (iskey)
334 {
335 res = routine->amsearchnulls;
336 isnull = false;
337 }
338 break;
339
340 default:
341 break;
342 }
343
344 ReleaseSysCache(tuple);
345
346 if (!isnull)
347 PG_RETURN_BOOL(res);
349 }
350
352 {
353 /*
354 * Handle index-level properties. Currently, these only depend on the
355 * AM, but that might not be true forever, so we make users name an
356 * index not just an AM.
357 */
358 switch (prop)
359 {
362
364 PG_RETURN_BOOL(routine->amgettuple ? true : false);
365
367 PG_RETURN_BOOL(routine->amgetbitmap ? true : false);
368
371
372 default:
374 }
375 }
376
377 /*
378 * Handle AM-level properties (those that control what you can say in
379 * CREATE INDEX).
380 */
381 switch (prop)
382 {
383 case AMPROP_CAN_ORDER:
384 PG_RETURN_BOOL(routine->amcanorder);
385
387 PG_RETURN_BOOL(routine->amcanunique);
388
391
393 PG_RETURN_BOOL(routine->amgettuple ? true : false);
394
397
398 default:
400 }
401}
const IndexAmRoutine * GetIndexAmRoutineByAmId(Oid amoid, bool noerror)
Definition amapi.c:69
IndexAMProperty
Definition amapi.h:39
@ AMPROP_BACKWARD_SCAN
Definition amapi.h:53
@ AMPROP_SEARCH_ARRAY
Definition amapi.h:48
@ AMPROP_CAN_MULTI_COL
Definition amapi.h:56
@ AMPROP_CAN_ORDER
Definition amapi.h:54
@ AMPROP_ORDERABLE
Definition amapi.h:45
@ AMPROP_ASC
Definition amapi.h:41
@ AMPROP_DISTANCE_ORDERABLE
Definition amapi.h:46
@ AMPROP_CAN_INCLUDE
Definition amapi.h:58
@ AMPROP_SEARCH_NULLS
Definition amapi.h:49
@ AMPROP_CAN_EXCLUDE
Definition amapi.h:57
@ AMPROP_CAN_UNIQUE
Definition amapi.h:55
@ AMPROP_DESC
Definition amapi.h:42
@ AMPROP_NULLS_LAST
Definition amapi.h:44
@ AMPROP_INDEX_SCAN
Definition amapi.h:51
@ AMPROP_NULLS_FIRST
Definition amapi.h:43
@ AMPROP_CLUSTERABLE
Definition amapi.h:50
@ AMPROP_RETURNABLE
Definition amapi.h:47
@ AMPROP_BITMAP_SCAN
Definition amapi.h:52
static IndexAMProperty lookup_prop_name(const char *name)
Definition amutils.c:90
static bool test_indoption(HeapTuple tuple, int attno, bool guard, int16 iopt_mask, int16 iopt_expect, bool *res)
Definition amutils.c:115
#define Assert(condition)
Definition c.h:1002
#define OidIsValid(objectId)
Definition c.h:917
#define PG_RETURN_NULL()
Definition fmgr.h:346
#define PG_RETURN_BOOL(x)
Definition fmgr.h:360
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
#define false
void index_close(Relation relation, LOCKMODE lockmode)
Definition indexam.c:178
bool index_can_return(Relation indexRelation, int attno)
Definition indexam.c:813
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition indexam.c:134
#define AccessShareLock
Definition lockdefs.h:36
FormData_pg_class * Form_pg_class
Definition pg_class.h:160
END_CATALOG_STRUCT typedef FormData_pg_index * Form_pg_index
Definition pg_index.h:74
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
static int fb(int x)
bool amclusterable
Definition amapi.h:271
bool amcanorderbyop
Definition amapi.h:249
amgettuple_function amgettuple
Definition amapi.h:312
amcanreturn_function amcanreturn
Definition amapi.h:302
bool amcanunique
Definition amapi.h:259
amgetbitmap_function amgetbitmap
Definition amapi.h:313
amproperty_function amproperty
Definition amapi.h:306
bool amsearcharray
Definition amapi.h:265
bool amcanmulticol
Definition amapi.h:261
bool amcanorder
Definition amapi.h:247
bool amcanbackward
Definition amapi.h:257
bool amcaninclude
Definition amapi.h:279
bool amsearchnulls
Definition amapi.h:267
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:265
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:221

References AccessShareLock, IndexAmRoutine::amcanbackward, IndexAmRoutine::amcaninclude, IndexAmRoutine::amcanmulticol, IndexAmRoutine::amcanorder, IndexAmRoutine::amcanorderbyop, IndexAmRoutine::amcanreturn, IndexAmRoutine::amcanunique, IndexAmRoutine::amclusterable, IndexAmRoutine::amgetbitmap, IndexAmRoutine::amgettuple, AMPROP_ASC, AMPROP_BACKWARD_SCAN, AMPROP_BITMAP_SCAN, AMPROP_CAN_EXCLUDE, AMPROP_CAN_INCLUDE, AMPROP_CAN_MULTI_COL, AMPROP_CAN_ORDER, AMPROP_CAN_UNIQUE, AMPROP_CLUSTERABLE, AMPROP_DESC, AMPROP_DISTANCE_ORDERABLE, AMPROP_INDEX_SCAN, AMPROP_NULLS_FIRST, AMPROP_NULLS_LAST, AMPROP_ORDERABLE, AMPROP_RETURNABLE, AMPROP_SEARCH_ARRAY, AMPROP_SEARCH_NULLS, IndexAmRoutine::amproperty, IndexAmRoutine::amsearcharray, IndexAmRoutine::amsearchnulls, Assert, fb(), Form_pg_index, GetIndexAmRoutineByAmId(), GETSTRUCT(), HeapTupleIsValid, index_can_return(), index_close(), index_open(), lookup_prop_name(), ObjectIdGetDatum(), OidIsValid, PG_RETURN_BOOL, PG_RETURN_NULL, am_propname::prop, ReleaseSysCache(), SearchSysCache1(), and test_indoption().

Referenced by pg_index_column_has_property(), pg_index_has_property(), and pg_indexam_has_property().

◆ lookup_prop_name()

static IndexAMProperty lookup_prop_name ( const char name)
static

Definition at line 90 of file amutils.c.

91{
92 for (size_t i = 0; i < lengthof(am_propnames); i++)
93 {
95 return am_propnames[i].prop;
96 }
97
98 /* We do not throw an error, so that AMs can define their own properties */
99 return AMPROP_UNKNOWN;
100}
@ AMPROP_UNKNOWN
Definition amapi.h:40
static const struct am_propname am_propnames[]
Definition amutils.c:31
#define lengthof(array)
Definition c.h:932
int i
Definition isn.c:77
int pg_strcasecmp(const char *s1, const char *s2)
const char * name

References am_propnames, AMPROP_UNKNOWN, i, lengthof, name, pg_strcasecmp(), and am_propname::prop.

Referenced by indexam_property().

◆ pg_index_column_has_property()

Datum pg_index_column_has_property ( PG_FUNCTION_ARGS  )

Definition at line 431 of file amutils.c.

432{
433 Oid relid = PG_GETARG_OID(0);
434 int32 attno = PG_GETARG_INT32(1);
436
437 /* Reject attno 0 immediately, so that attno > 0 identifies this case */
438 if (attno <= 0)
440
441 return indexam_property(fcinfo, propname, InvalidOid, relid, attno);
442}
static Datum indexam_property(FunctionCallInfo fcinfo, const char *propname, Oid amoid, Oid index_oid, int attno)
Definition amutils.c:149
int32_t int32
Definition c.h:679
#define PG_GETARG_OID(n)
Definition fmgr.h:275
#define PG_GETARG_TEXT_PP(n)
Definition fmgr.h:310
#define PG_GETARG_INT32(n)
Definition fmgr.h:269
#define InvalidOid
unsigned int Oid
char * text_to_cstring(const text *t)
Definition varlena.c:217

References fb(), indexam_property(), InvalidOid, PG_GETARG_INT32, PG_GETARG_OID, PG_GETARG_TEXT_PP, PG_RETURN_NULL, and text_to_cstring().

◆ pg_index_has_property()

Datum pg_index_has_property ( PG_FUNCTION_ARGS  )

Definition at line 419 of file amutils.c.

420{
421 Oid relid = PG_GETARG_OID(0);
423
424 return indexam_property(fcinfo, propname, InvalidOid, relid, 0);
425}

References fb(), indexam_property(), InvalidOid, PG_GETARG_OID, PG_GETARG_TEXT_PP, and text_to_cstring().

◆ pg_indexam_has_property()

Datum pg_indexam_has_property ( PG_FUNCTION_ARGS  )

Definition at line 407 of file amutils.c.

408{
411
412 return indexam_property(fcinfo, propname, amoid, InvalidOid, 0);
413}

References fb(), indexam_property(), InvalidOid, PG_GETARG_OID, PG_GETARG_TEXT_PP, and text_to_cstring().

◆ pg_indexam_progress_phasename()

Datum pg_indexam_progress_phasename ( PG_FUNCTION_ARGS  )

Definition at line 449 of file amutils.c.

450{
453 const IndexAmRoutine *routine;
454 char *name;
455
456 routine = GetIndexAmRoutineByAmId(amoid, true);
457 if (routine == NULL || !routine->ambuildphasename)
459
460 name = routine->ambuildphasename(phasenum);
461 if (!name)
463
465}
#define CStringGetTextDatum(s)
Definition builtins.h:98
#define PG_RETURN_DATUM(x)
Definition fmgr.h:354
ambuildphasename_function ambuildphasename
Definition amapi.h:307

References IndexAmRoutine::ambuildphasename, CStringGetTextDatum, fb(), GetIndexAmRoutineByAmId(), name, PG_GETARG_INT32, PG_GETARG_OID, PG_RETURN_DATUM, and PG_RETURN_NULL.

◆ test_indoption()

static bool test_indoption ( HeapTuple  tuple,
int  attno,
bool  guard,
int16  iopt_mask,
int16  iopt_expect,
bool res 
)
static

Definition at line 115 of file amutils.c.

118{
119 Datum datum;
122
123 if (!guard)
124 {
125 *res = false;
126 return true;
127 }
128
130
131 indoption = ((int2vector *) DatumGetPointer(datum));
132 indoption_val = indoption->values[attno - 1];
133
134 *res = (indoption_val & iopt_mask) == iopt_expect;
135
136 return true;
137}
int16_t int16
Definition c.h:678
uint64_t Datum
Definition postgres.h:70
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:332
Datum SysCacheGetAttrNotNull(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition syscache.c:626

References DatumGetPointer(), fb(), and SysCacheGetAttrNotNull().

Referenced by indexam_property().

Variable Documentation

◆ am_propnames

const struct am_propname am_propnames[]
static

Definition at line 31 of file amutils.c.

32{
33 {
34 "asc", AMPROP_ASC
35 },
36 {
37 "desc", AMPROP_DESC
38 },
39 {
40 "nulls_first", AMPROP_NULLS_FIRST
41 },
42 {
43 "nulls_last", AMPROP_NULLS_LAST
44 },
45 {
46 "orderable", AMPROP_ORDERABLE
47 },
48 {
49 "distance_orderable", AMPROP_DISTANCE_ORDERABLE
50 },
51 {
52 "returnable", AMPROP_RETURNABLE
53 },
54 {
55 "search_array", AMPROP_SEARCH_ARRAY
56 },
57 {
58 "search_nulls", AMPROP_SEARCH_NULLS
59 },
60 {
61 "clusterable", AMPROP_CLUSTERABLE
62 },
63 {
64 "index_scan", AMPROP_INDEX_SCAN
65 },
66 {
67 "bitmap_scan", AMPROP_BITMAP_SCAN
68 },
69 {
70 "backward_scan", AMPROP_BACKWARD_SCAN
71 },
72 {
73 "can_order", AMPROP_CAN_ORDER
74 },
75 {
76 "can_unique", AMPROP_CAN_UNIQUE
77 },
78 {
79 "can_multi_col", AMPROP_CAN_MULTI_COL
80 },
81 {
82 "can_exclude", AMPROP_CAN_EXCLUDE
83 },
84 {
85 "can_include", AMPROP_CAN_INCLUDE
86 },
87};

Referenced by lookup_prop_name().