PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
amapi.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * amapi.c
4  * Support routines for API for Postgres index access methods.
5  *
6  * Copyright (c) 2015-2016, PostgreSQL Global Development Group
7  *
8  *
9  * IDENTIFICATION
10  * src/backend/access/index/amapi.c
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include "postgres.h"
15 
16 #include "access/amapi.h"
17 #include "access/htup_details.h"
18 #include "catalog/pg_am.h"
19 #include "catalog/pg_opclass.h"
20 #include "utils/syscache.h"
21 
22 
23 /*
24  * GetIndexAmRoutine - call the specified access method handler routine to get
25  * its IndexAmRoutine struct, which will be palloc'd in the caller's context.
26  *
27  * Note that if the amhandler function is built-in, this will not involve
28  * any catalog access. It's therefore safe to use this while bootstrapping
29  * indexes for the system catalogs. relcache.c relies on that.
30  */
33 {
34  Datum datum;
35  IndexAmRoutine *routine;
36 
37  datum = OidFunctionCall0(amhandler);
38  routine = (IndexAmRoutine *) DatumGetPointer(datum);
39 
40  if (routine == NULL || !IsA(routine, IndexAmRoutine))
41  elog(ERROR, "index access method handler function %u did not return an IndexAmRoutine struct",
42  amhandler);
43 
44  return routine;
45 }
46 
47 /*
48  * GetIndexAmRoutineByAmId - look up the handler of the index access method
49  * with the given OID, and get its IndexAmRoutine struct.
50  */
53 {
54  HeapTuple tuple;
55  Form_pg_am amform;
56  regproc amhandler;
57 
58  /* Get handler function OID for the access method */
59  tuple = SearchSysCache1(AMOID, ObjectIdGetDatum(amoid));
60  if (!HeapTupleIsValid(tuple))
61  elog(ERROR, "cache lookup failed for access method %u",
62  amoid);
63  amform = (Form_pg_am) GETSTRUCT(tuple);
64 
65  /* Check if it's index access method */
66  if (amform->amtype != AMTYPE_INDEX)
67  ereport(ERROR,
68  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
69  errmsg("access method \"%s\" is not of type %s",
70  NameStr(amform->amname), "INDEX")));
71 
72  amhandler = amform->amhandler;
73 
74  /* Complain if handler OID is invalid */
75  if (!RegProcedureIsValid(amhandler))
76  ereport(ERROR,
77  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
78  errmsg("index access method \"%s\" does not have a handler",
79  NameStr(amform->amname))));
80 
81  ReleaseSysCache(tuple);
82 
83  /* And finally, call the handler function to get the API struct. */
84  return GetIndexAmRoutine(amhandler);
85 }
86 
87 
88 /*
89  * Ask appropriate access method to validate the specified opclass.
90  */
91 Datum
93 {
94  Oid opclassoid = PG_GETARG_OID(0);
95  bool result;
96  HeapTuple classtup;
97  Form_pg_opclass classform;
98  Oid amoid;
99  IndexAmRoutine *amroutine;
100 
101  classtup = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclassoid));
102  if (!HeapTupleIsValid(classtup))
103  elog(ERROR, "cache lookup failed for operator class %u", opclassoid);
104  classform = (Form_pg_opclass) GETSTRUCT(classtup);
105 
106  amoid = classform->opcmethod;
107 
108  ReleaseSysCache(classtup);
109 
110  amroutine = GetIndexAmRoutineByAmId(amoid);
111 
112  if (amroutine->amvalidate == NULL)
113  elog(ERROR, "function amvalidate is not defined for index access method %u",
114  amoid);
115 
116  result = amroutine->amvalidate(opclassoid);
117 
118  pfree(amroutine);
119 
120  PG_RETURN_BOOL(result);
121 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:542
#define GETSTRUCT(TUP)
Definition: htup_details.h:631
Definition: syscache.h:36
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
IndexAmRoutine * GetIndexAmRoutineByAmId(Oid amoid)
Definition: amapi.c:52
amvalidate_function amvalidate
Definition: amapi.h:157
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:141
void pfree(void *pointer)
Definition: mcxt.c:995
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
Datum amvalidate(PG_FUNCTION_ARGS)
Definition: amapi.c:92
IndexAmRoutine * GetIndexAmRoutine(Oid amhandler)
Definition: amapi.c:32
#define PG_GETARG_OID(n)
Definition: fmgr.h:231
#define RegProcedureIsValid(p)
Definition: c.h:532
#define ereport(elevel, rest)
Definition: elog.h:122
#define AMTYPE_INDEX
Definition: pg_am.h:61
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:303
uintptr_t Datum
Definition: postgres.h:374
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:990
#define OidFunctionCall0(functionId)
Definition: fmgr.h:584
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define DatumGetPointer(X)
Definition: postgres.h:557
Oid regproc
Definition: c.h:390
FormData_pg_am * Form_pg_am
Definition: pg_am.h:46
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define NameStr(name)
Definition: c.h:494
#define PG_FUNCTION_ARGS
Definition: fmgr.h:150
#define elog
Definition: elog.h:218
FormData_pg_opclass * Form_pg_opclass
Definition: pg_opclass.h:68