Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * dummy_index_am.c
4 : * Index AM template main file.
5 : *
6 : * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : * IDENTIFICATION
10 : * src/test/modules/dummy_index_am/dummy_index_am.c
11 : *
12 : *-------------------------------------------------------------------------
13 : */
14 : #include "postgres.h"
15 :
16 : #include "access/amapi.h"
17 : #include "access/reloptions.h"
18 : #include "catalog/index.h"
19 : #include "commands/vacuum.h"
20 : #include "nodes/pathnodes.h"
21 : #include "utils/guc.h"
22 : #include "utils/rel.h"
23 :
24 2 : PG_MODULE_MAGIC;
25 :
26 : /* parse table for fillRelOptions */
27 : relopt_parse_elt di_relopt_tab[6];
28 :
29 : /* Kind of relation options for dummy index */
30 : relopt_kind di_relopt_kind;
31 :
32 : typedef enum DummyAmEnum
33 : {
34 : DUMMY_AM_ENUM_ONE,
35 : DUMMY_AM_ENUM_TWO,
36 : } DummyAmEnum;
37 :
38 : /* Dummy index options */
39 : typedef struct DummyIndexOptions
40 : {
41 : int32 vl_len_; /* varlena header (do not touch directly!) */
42 : int option_int;
43 : double option_real;
44 : bool option_bool;
45 : DummyAmEnum option_enum;
46 : int option_string_val_offset;
47 : int option_string_null_offset;
48 : } DummyIndexOptions;
49 :
50 : relopt_enum_elt_def dummyAmEnumValues[] =
51 : {
52 : {"one", DUMMY_AM_ENUM_ONE},
53 : {"two", DUMMY_AM_ENUM_TWO},
54 : {(const char *) NULL} /* list terminator */
55 : };
56 :
57 : /* Handler for index AM */
58 4 : PG_FUNCTION_INFO_V1(dihandler);
59 :
60 : /*
61 : * Validation function for string relation options.
62 : */
63 : static void
64 60 : validate_string_option(const char *value)
65 : {
66 60 : ereport(NOTICE,
67 : (errmsg("new option value for string parameter %s",
68 : value ? value : "NULL")));
69 60 : }
70 :
71 : /*
72 : * This function creates a full set of relation option types,
73 : * with various patterns.
74 : */
75 : static void
76 2 : create_reloptions_table(void)
77 : {
78 2 : di_relopt_kind = add_reloption_kind();
79 :
80 2 : add_int_reloption(di_relopt_kind, "option_int",
81 : "Integer option for dummy_index_am",
82 : 10, -10, 100, AccessExclusiveLock);
83 2 : di_relopt_tab[0].optname = "option_int";
84 2 : di_relopt_tab[0].opttype = RELOPT_TYPE_INT;
85 2 : di_relopt_tab[0].offset = offsetof(DummyIndexOptions, option_int);
86 :
87 2 : add_real_reloption(di_relopt_kind, "option_real",
88 : "Real option for dummy_index_am",
89 : 3.1415, -10, 100, AccessExclusiveLock);
90 2 : di_relopt_tab[1].optname = "option_real";
91 2 : di_relopt_tab[1].opttype = RELOPT_TYPE_REAL;
92 2 : di_relopt_tab[1].offset = offsetof(DummyIndexOptions, option_real);
93 :
94 2 : add_bool_reloption(di_relopt_kind, "option_bool",
95 : "Boolean option for dummy_index_am",
96 : true, AccessExclusiveLock);
97 2 : di_relopt_tab[2].optname = "option_bool";
98 2 : di_relopt_tab[2].opttype = RELOPT_TYPE_BOOL;
99 2 : di_relopt_tab[2].offset = offsetof(DummyIndexOptions, option_bool);
100 :
101 2 : add_enum_reloption(di_relopt_kind, "option_enum",
102 : "Enum option for dummy_index_am",
103 : dummyAmEnumValues,
104 : DUMMY_AM_ENUM_ONE,
105 : "Valid values are \"one\" and \"two\".",
106 : AccessExclusiveLock);
107 2 : di_relopt_tab[3].optname = "option_enum";
108 2 : di_relopt_tab[3].opttype = RELOPT_TYPE_ENUM;
109 2 : di_relopt_tab[3].offset = offsetof(DummyIndexOptions, option_enum);
110 :
111 2 : add_string_reloption(di_relopt_kind, "option_string_val",
112 : "String option for dummy_index_am with non-NULL default",
113 : "DefaultValue", &validate_string_option,
114 : AccessExclusiveLock);
115 2 : di_relopt_tab[4].optname = "option_string_val";
116 2 : di_relopt_tab[4].opttype = RELOPT_TYPE_STRING;
117 2 : di_relopt_tab[4].offset = offsetof(DummyIndexOptions,
118 : option_string_val_offset);
119 :
120 : /*
121 : * String option for dummy_index_am with NULL default, and without
122 : * description.
123 : */
124 2 : add_string_reloption(di_relopt_kind, "option_string_null",
125 : NULL, /* description */
126 : NULL, &validate_string_option,
127 : AccessExclusiveLock);
128 2 : di_relopt_tab[5].optname = "option_string_null";
129 2 : di_relopt_tab[5].opttype = RELOPT_TYPE_STRING;
130 2 : di_relopt_tab[5].offset = offsetof(DummyIndexOptions,
131 : option_string_null_offset);
132 2 : }
133 :
134 :
135 : /*
136 : * Build a new index.
137 : */
138 : static IndexBuildResult *
139 4 : dibuild(Relation heap, Relation index, IndexInfo *indexInfo)
140 : {
141 : IndexBuildResult *result;
142 :
143 4 : result = (IndexBuildResult *) palloc(sizeof(IndexBuildResult));
144 :
145 : /* let's pretend that no tuples were scanned */
146 4 : result->heap_tuples = 0;
147 : /* and no index tuples were created (that is true) */
148 4 : result->index_tuples = 0;
149 :
150 4 : return result;
151 : }
152 :
153 : /*
154 : * Build an empty index for the initialization fork.
155 : */
156 : static void
157 0 : dibuildempty(Relation index)
158 : {
159 : /* No need to build an init fork for a dummy index */
160 0 : }
161 :
162 : /*
163 : * Insert new tuple to index AM.
164 : */
165 : static bool
166 0 : diinsert(Relation index, Datum *values, bool *isnull,
167 : ItemPointer ht_ctid, Relation heapRel,
168 : IndexUniqueCheck checkUnique,
169 : bool indexUnchanged,
170 : IndexInfo *indexInfo)
171 : {
172 : /* nothing to do */
173 0 : return false;
174 : }
175 :
176 : /*
177 : * Bulk deletion of all index entries pointing to a set of table tuples.
178 : */
179 : static IndexBulkDeleteResult *
180 0 : dibulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
181 : IndexBulkDeleteCallback callback, void *callback_state)
182 : {
183 : /*
184 : * There is nothing to delete. Return NULL as there is nothing to pass to
185 : * amvacuumcleanup.
186 : */
187 0 : return NULL;
188 : }
189 :
190 : /*
191 : * Post-VACUUM cleanup for index AM.
192 : */
193 : static IndexBulkDeleteResult *
194 0 : divacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
195 : {
196 : /* Index has not been modified, so returning NULL is fine */
197 0 : return NULL;
198 : }
199 :
200 : /*
201 : * Estimate cost of index AM.
202 : */
203 : static void
204 0 : dicostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
205 : Cost *indexStartupCost, Cost *indexTotalCost,
206 : Selectivity *indexSelectivity, double *indexCorrelation,
207 : double *indexPages)
208 : {
209 : /* Tell planner to never use this index! */
210 0 : *indexStartupCost = 1.0e10;
211 0 : *indexTotalCost = 1.0e10;
212 :
213 : /* Do not care about the rest */
214 0 : *indexSelectivity = 1;
215 0 : *indexCorrelation = 0;
216 0 : *indexPages = 1;
217 0 : }
218 :
219 : /*
220 : * Parse relation options for index AM, returning a DummyIndexOptions
221 : * structure filled with option values.
222 : */
223 : static bytea *
224 138 : dioptions(Datum reloptions, bool validate)
225 : {
226 138 : return (bytea *) build_reloptions(reloptions, validate,
227 : di_relopt_kind,
228 : sizeof(DummyIndexOptions),
229 : di_relopt_tab, lengthof(di_relopt_tab));
230 : }
231 :
232 : /*
233 : * Validator for index AM.
234 : */
235 : static bool
236 0 : divalidate(Oid opclassoid)
237 : {
238 : /* Index is dummy so we are happy with any opclass */
239 0 : return true;
240 : }
241 :
242 : /*
243 : * Begin scan of index AM.
244 : */
245 : static IndexScanDesc
246 0 : dibeginscan(Relation r, int nkeys, int norderbys)
247 : {
248 : IndexScanDesc scan;
249 :
250 : /* Let's pretend we are doing something */
251 0 : scan = RelationGetIndexScan(r, nkeys, norderbys);
252 0 : return scan;
253 : }
254 :
255 : /*
256 : * Rescan of index AM.
257 : */
258 : static void
259 0 : direscan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
260 : ScanKey orderbys, int norderbys)
261 : {
262 : /* nothing to do */
263 0 : }
264 :
265 : /*
266 : * End scan of index AM.
267 : */
268 : static void
269 0 : diendscan(IndexScanDesc scan)
270 : {
271 : /* nothing to do */
272 0 : }
273 :
274 : /*
275 : * Index AM handler function: returns IndexAmRoutine with access method
276 : * parameters and callbacks.
277 : */
278 : Datum
279 66 : dihandler(PG_FUNCTION_ARGS)
280 : {
281 66 : IndexAmRoutine *amroutine = makeNode(IndexAmRoutine);
282 :
283 66 : amroutine->amstrategies = 0;
284 66 : amroutine->amsupport = 1;
285 66 : amroutine->amcanorder = false;
286 66 : amroutine->amcanorderbyop = false;
287 66 : amroutine->amcanbackward = false;
288 66 : amroutine->amcanunique = false;
289 66 : amroutine->amcanmulticol = false;
290 66 : amroutine->amoptionalkey = false;
291 66 : amroutine->amsearcharray = false;
292 66 : amroutine->amsearchnulls = false;
293 66 : amroutine->amstorage = false;
294 66 : amroutine->amclusterable = false;
295 66 : amroutine->ampredlocks = false;
296 66 : amroutine->amcanparallel = false;
297 66 : amroutine->amcanbuildparallel = false;
298 66 : amroutine->amcaninclude = false;
299 66 : amroutine->amusemaintenanceworkmem = false;
300 66 : amroutine->amsummarizing = false;
301 66 : amroutine->amparallelvacuumoptions = VACUUM_OPTION_NO_PARALLEL;
302 66 : amroutine->amkeytype = InvalidOid;
303 :
304 66 : amroutine->ambuild = dibuild;
305 66 : amroutine->ambuildempty = dibuildempty;
306 66 : amroutine->aminsert = diinsert;
307 66 : amroutine->ambulkdelete = dibulkdelete;
308 66 : amroutine->amvacuumcleanup = divacuumcleanup;
309 66 : amroutine->amcanreturn = NULL;
310 66 : amroutine->amcostestimate = dicostestimate;
311 66 : amroutine->amoptions = dioptions;
312 66 : amroutine->amproperty = NULL;
313 66 : amroutine->ambuildphasename = NULL;
314 66 : amroutine->amvalidate = divalidate;
315 66 : amroutine->ambeginscan = dibeginscan;
316 66 : amroutine->amrescan = direscan;
317 66 : amroutine->amgettuple = NULL;
318 66 : amroutine->amgetbitmap = NULL;
319 66 : amroutine->amendscan = diendscan;
320 66 : amroutine->ammarkpos = NULL;
321 66 : amroutine->amrestrpos = NULL;
322 66 : amroutine->amestimateparallelscan = NULL;
323 66 : amroutine->aminitparallelscan = NULL;
324 66 : amroutine->amparallelrescan = NULL;
325 :
326 66 : PG_RETURN_POINTER(amroutine);
327 : }
328 :
329 : void
330 2 : _PG_init(void)
331 : {
332 2 : create_reloptions_table();
333 2 : }
|