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