Age Owner Branch data TLA 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 : :
1663 michael@paquier.xyz 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 : :
57 : : /* Handler for index AM */
58 : 2 : PG_FUNCTION_INFO_V1(dihandler);
59 : :
60 : : /*
61 : : * Validation function for string relation options.
62 : : */
63 : : static void
64 : 30 : validate_string_option(const char *value)
65 : : {
66 [ + + + - ]: 30 : ereport(NOTICE,
67 : : (errmsg("new option value for string parameter %s",
68 : : value ? value : "NULL")));
69 : 30 : }
70 : :
71 : : /*
72 : : * This function creates a full set of relation option types,
73 : : * with various patterns.
74 : : */
75 : : static void
76 : 1 : create_reloptions_table(void)
77 : : {
78 : 1 : di_relopt_kind = add_reloption_kind();
79 : :
80 : 1 : add_int_reloption(di_relopt_kind, "option_int",
81 : : "Integer option for dummy_index_am",
82 : : 10, -10, 100, AccessExclusiveLock);
83 : 1 : di_relopt_tab[0].optname = "option_int";
84 : 1 : di_relopt_tab[0].opttype = RELOPT_TYPE_INT;
85 : 1 : di_relopt_tab[0].offset = offsetof(DummyIndexOptions, option_int);
86 : :
87 : 1 : add_real_reloption(di_relopt_kind, "option_real",
88 : : "Real option for dummy_index_am",
89 : : 3.1415, -10, 100, AccessExclusiveLock);
90 : 1 : di_relopt_tab[1].optname = "option_real";
91 : 1 : di_relopt_tab[1].opttype = RELOPT_TYPE_REAL;
92 : 1 : di_relopt_tab[1].offset = offsetof(DummyIndexOptions, option_real);
93 : :
94 : 1 : add_bool_reloption(di_relopt_kind, "option_bool",
95 : : "Boolean option for dummy_index_am",
96 : : true, AccessExclusiveLock);
97 : 1 : di_relopt_tab[2].optname = "option_bool";
98 : 1 : di_relopt_tab[2].opttype = RELOPT_TYPE_BOOL;
99 : 1 : di_relopt_tab[2].offset = offsetof(DummyIndexOptions, option_bool);
100 : :
alvherre@alvh.no-ip. 101 : 1 : 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 : 1 : di_relopt_tab[3].optname = "option_enum";
108 : 1 : di_relopt_tab[3].opttype = RELOPT_TYPE_ENUM;
109 : 1 : di_relopt_tab[3].offset = offsetof(DummyIndexOptions, option_enum);
110 : :
michael@paquier.xyz 111 : 1 : 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);
alvherre@alvh.no-ip. 115 : 1 : di_relopt_tab[4].optname = "option_string_val";
116 : 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 : : * description.
123 : : */
michael@paquier.xyz 124 : 1 : add_string_reloption(di_relopt_kind, "option_string_null",
125 : : NULL, /* description */
126 : : NULL, &validate_string_option,
127 : : AccessExclusiveLock);
alvherre@alvh.no-ip. 128 : 1 : di_relopt_tab[5].optname = "option_string_null";
129 : 1 : di_relopt_tab[5].opttype = RELOPT_TYPE_STRING;
130 : 1 : di_relopt_tab[5].offset = offsetof(DummyIndexOptions,
131 : : option_string_null_offset);
michael@paquier.xyz 132 : 1 : }
133 : :
134 : :
135 : : /*
136 : : * Build a new index.
137 : : */
138 : : static IndexBuildResult *
139 : 2 : dibuild(Relation heap, Relation index, IndexInfo *indexInfo)
140 : : {
141 : : IndexBuildResult *result;
142 : :
143 : 2 : result = (IndexBuildResult *) palloc(sizeof(IndexBuildResult));
144 : :
145 : : /* let's pretend that no tuples were scanned */
146 : 2 : result->heap_tuples = 0;
147 : : /* and no index tuples were created (that is true) */
148 : 2 : result->index_tuples = 0;
149 : :
150 : 2 : return result;
151 : : }
152 : :
153 : : /*
154 : : * Build an empty index for the initialization fork.
155 : : */
156 : : static void
1663 michael@paquier.xyz 157 :UBC 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 *
1663 michael@paquier.xyz 224 :CBC 69 : dioptions(Datum reloptions, bool validate)
225 : : {
1622 226 : 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 : : */
235 : : static bool
1663 michael@paquier.xyz 236 :UBC 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
1663 michael@paquier.xyz 279 :CBC 33 : dihandler(PG_FUNCTION_ARGS)
280 : : {
281 : 33 : IndexAmRoutine *amroutine = makeNode(IndexAmRoutine);
282 : :
283 : 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;
128 tomas.vondra@postgre 297 :GNC 33 : amroutine->amcanbuildparallel = false;
1663 michael@paquier.xyz 298 :CBC 33 : amroutine->amcaninclude = false;
1551 akapila@postgresql.o 299 : 33 : amroutine->amusemaintenanceworkmem = false;
391 tomas.vondra@postgre 300 : 33 : amroutine->amsummarizing = false;
1551 akapila@postgresql.o 301 : 33 : amroutine->amparallelvacuumoptions = VACUUM_OPTION_NO_PARALLEL;
1663 michael@paquier.xyz 302 : 33 : amroutine->amkeytype = InvalidOid;
303 : :
304 : 33 : amroutine->ambuild = dibuild;
305 : 33 : amroutine->ambuildempty = dibuildempty;
306 : 33 : amroutine->aminsert = diinsert;
307 : 33 : amroutine->ambulkdelete = dibulkdelete;
308 : 33 : amroutine->amvacuumcleanup = divacuumcleanup;
309 : 33 : amroutine->amcanreturn = NULL;
310 : 33 : amroutine->amcostestimate = dicostestimate;
311 : 33 : amroutine->amoptions = dioptions;
312 : 33 : amroutine->amproperty = NULL;
313 : 33 : amroutine->ambuildphasename = NULL;
314 : 33 : amroutine->amvalidate = divalidate;
315 : 33 : amroutine->ambeginscan = dibeginscan;
316 : 33 : amroutine->amrescan = direscan;
317 : 33 : amroutine->amgettuple = NULL;
318 : 33 : amroutine->amgetbitmap = NULL;
319 : 33 : amroutine->amendscan = diendscan;
320 : 33 : amroutine->ammarkpos = NULL;
321 : 33 : amroutine->amrestrpos = NULL;
322 : 33 : amroutine->amestimateparallelscan = NULL;
323 : 33 : amroutine->aminitparallelscan = NULL;
324 : 33 : amroutine->amparallelrescan = NULL;
325 : :
326 : 33 : PG_RETURN_POINTER(amroutine);
327 : : }
328 : :
329 : : void
330 : 1 : _PG_init(void)
331 : : {
332 : 1 : create_reloptions_table();
333 : 1 : }
|