LCOV - code coverage report
Current view: top level - src/test/modules/dummy_index_am - dummy_index_am.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 70.0 % 80 56
Test Date: 2026-03-03 17:14:48 Functions: 47.1 % 17 8
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.0-1