LCOV - code coverage report
Current view: top level - src/test/modules/index - test_indexscan.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 84.0 % 50 42
Test Date: 2026-09-04 06:15:53 Functions: 100.0 % 3 3
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 47.5 % 40 19

             Branch data     Line data    Source code
       1                 :             : /*--------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * test_indexscan.c
       4                 :             :  *      Test helpers for low-level index scan behavior.
       5                 :             :  *
       6                 :             :  * Copyright (c) 2026, PostgreSQL Global Development Group
       7                 :             :  *
       8                 :             :  * IDENTIFICATION
       9                 :             :  *      src/test/modules/index/test_indexscan.c
      10                 :             :  *
      11                 :             :  * -------------------------------------------------------------------------
      12                 :             :  */
      13                 :             : #include "postgres.h"
      14                 :             : 
      15                 :             : #include "access/amapi.h"
      16                 :             : #include "access/genam.h"
      17                 :             : #include "access/relscan.h"
      18                 :             : #include "access/table.h"
      19                 :             : #include "access/tableam.h"
      20                 :             : #include "catalog/index.h"
      21                 :             : #include "catalog/pg_class.h"
      22                 :             : #include "executor/tuptable.h"
      23                 :             : #include "fmgr.h"
      24                 :             : #include "funcapi.h"
      25                 :             : #include "miscadmin.h"
      26                 :             : #include "storage/itemptr.h"
      27                 :             : #include "utils/builtins.h"
      28                 :             : #include "utils/rel.h"
      29                 :             : #include "utils/snapmgr.h"
      30                 :             : #include "utils/tuplestore.h"
      31                 :             : 
      32                 :           1 : PG_MODULE_MAGIC;
      33                 :             : 
      34                 :           2 : PG_FUNCTION_INFO_V1(index_scan_tids);
      35                 :             : Datum
      36                 :           7 : index_scan_tids(PG_FUNCTION_ARGS)
      37                 :             : {
      38                 :           7 :     Oid         indexoid = PG_GETARG_OID(0);
      39                 :           7 :     char       *snaptype = text_to_cstring(PG_GETARG_TEXT_PP(1));
      40                 :           7 :     bool        forwardscan = PG_GETARG_BOOL(2);
      41                 :           7 :     ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
      42                 :             :     Oid         heapoid;
      43                 :             :     Relation    heaprel;
      44                 :             :     Relation    indexrel;
      45         [ +  + ]:           7 :     ScanDirection dir = forwardscan ? ForwardScanDirection : BackwardScanDirection;
      46                 :             :     SnapshotData snapdata;
      47                 :             :     Snapshot    snapshot;
      48                 :             :     IndexScanDesc scan;
      49                 :             :     TupleTableSlot *slot;
      50                 :             : 
      51         [ -  + ]:           7 :     if (!superuser())
      52         [ #  # ]:           0 :         ereport(ERROR,
      53                 :             :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
      54                 :             :                  errmsg("must be superuser to use index scan test functions")));
      55                 :             : 
      56                 :           7 :     InitMaterializedSRF(fcinfo, MAT_SRF_USE_EXPECTED_DESC);
      57                 :             : 
      58                 :             :     /*
      59                 :             :      * Lock the heap before the index to avoid deadlock.  IndexGetRelation()
      60                 :             :      * runs without a lock, so if the OID isn't an index it returns
      61                 :             :      * InvalidOid; defer the complaint to index_open() below, which gives a
      62                 :             :      * better message.
      63                 :             :      */
      64                 :           7 :     heapoid = IndexGetRelation(indexoid, true);
      65         [ +  - ]:           7 :     if (OidIsValid(heapoid))
      66                 :           7 :         heaprel = table_open(heapoid, AccessShareLock);
      67                 :             :     else
      68                 :           0 :         heaprel = NULL;
      69                 :             : 
      70                 :           7 :     indexrel = index_open(indexoid, AccessShareLock);
      71                 :             : 
      72                 :             :     /*
      73                 :             :      * Since the IndexGetRelation() call above ran without a lock, recheck now
      74                 :             :      * that both relations are locked: a concurrent drop and recreate could
      75                 :             :      * have left us with the wrong heap.
      76                 :             :      */
      77   [ +  -  -  + ]:           7 :     if (heaprel == NULL || heapoid != IndexGetRelation(indexoid, false))
      78         [ #  # ]:           0 :         ereport(ERROR,
      79                 :             :                 (errcode(ERRCODE_UNDEFINED_TABLE),
      80                 :             :                  errmsg("could not open parent table of index \"%s\"",
      81                 :             :                         RelationGetRelationName(indexrel))));
      82                 :             : 
      83         [ -  + ]:           7 :     if (indexrel->rd_rel->relkind != RELKIND_INDEX)
      84         [ #  # ]:           0 :         ereport(ERROR,
      85                 :             :                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
      86                 :             :                  errmsg("\"%s\" is not a regular index",
      87                 :             :                         RelationGetRelationName(indexrel))));
      88                 :             : 
      89         [ -  + ]:           7 :     if (indexrel->rd_indam->amgettuple == NULL)
      90         [ #  # ]:           0 :         ereport(ERROR,
      91                 :             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
      92                 :             :                  errmsg("index \"%s\" does not support plain index scans",
      93                 :             :                         RelationGetRelationName(indexrel))));
      94                 :             : 
      95         [ +  + ]:           7 :     if (strcmp(snaptype, "mvcc") == 0)
      96                 :           2 :         snapshot = GetActiveSnapshot();
      97         [ +  + ]:           5 :     else if (strcmp(snaptype, "any") == 0)
      98                 :           2 :         snapshot = SnapshotAny;
      99         [ -  + ]:           3 :     else if (strcmp(snaptype, "self") == 0)
     100                 :           0 :         snapshot = SnapshotSelf;
     101         [ +  + ]:           3 :     else if (strcmp(snaptype, "dirty") == 0)
     102                 :             :     {
     103                 :           1 :         InitDirtySnapshot(snapdata);
     104                 :           1 :         snapshot = &snapdata;
     105                 :             :     }
     106         [ +  - ]:           2 :     else if (strcmp(snaptype, "nonvacuumable") == 0)
     107                 :             :     {
     108                 :           2 :         InitNonVacuumableSnapshot(snapdata, GlobalVisTestFor(heaprel));
     109                 :           2 :         snapshot = &snapdata;
     110                 :             :     }
     111                 :             :     else
     112         [ #  # ]:           0 :         ereport(ERROR,
     113                 :             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     114                 :             :                  errmsg("invalid snapshot type \"%s\"", snaptype)));
     115                 :             : 
     116                 :           7 :     slot = table_slot_create(heaprel, NULL);
     117                 :             : 
     118                 :           7 :     scan = index_beginscan(heaprel, indexrel, snapshot, NULL,
     119                 :             :                            0, 0, SO_NONE);
     120                 :           7 :     index_rescan(scan, NULL, 0, NULL, 0);
     121                 :             : 
     122         [ +  + ]:          30 :     while (index_getnext_slot(scan, dir, slot))
     123                 :             :     {
     124                 :          23 :         ItemPointerData tid = slot->tts_tid;
     125                 :             :         Datum       values[1];
     126                 :             :         bool        nulls[1];
     127                 :             : 
     128         [ -  + ]:          23 :         if (scan->xs_recheck)
     129         [ #  # ]:           0 :             elog(ERROR, "unexpected recheck request");
     130                 :             : 
     131                 :          23 :         values[0] = ItemPointerGetDatum(&tid);
     132                 :          23 :         nulls[0] = false;
     133                 :          23 :         tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
     134                 :             :                              values, nulls);
     135                 :             :     }
     136                 :             : 
     137                 :           7 :     index_endscan(scan);
     138                 :           7 :     ExecDropSingleTupleTableSlot(slot);
     139                 :           7 :     index_close(indexrel, AccessShareLock);
     140                 :           7 :     table_close(heaprel, AccessShareLock);
     141                 :             : 
     142                 :           7 :     return (Datum) 0;
     143                 :             : }
        

Generated by: LCOV version 2.0-1