LCOV - code coverage report
Current view: top level - src/backend/access/table - tableamapi.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 80.0 % 20 16
Test Date: 2026-03-01 20:14:47 Functions: 100.0 % 2 2
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*----------------------------------------------------------------------
       2              :  *
       3              :  * tableamapi.c
       4              :  *      Support routines for API for Postgres table access methods
       5              :  *
       6              :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       7              :  * Portions Copyright (c) 1994, Regents of the University of California
       8              :  *
       9              :  * src/backend/access/table/tableamapi.c
      10              :  *----------------------------------------------------------------------
      11              :  */
      12              : #include "postgres.h"
      13              : 
      14              : #include "access/tableam.h"
      15              : #include "access/xact.h"
      16              : #include "commands/defrem.h"
      17              : #include "miscadmin.h"
      18              : #include "utils/guc_hooks.h"
      19              : 
      20              : 
      21              : /*
      22              :  * GetTableAmRoutine
      23              :  *      Call the specified access method handler routine to get its
      24              :  *      TableAmRoutine struct, which we expect to be statically allocated.
      25              :  */
      26              : const TableAmRoutine *
      27      1276595 : GetTableAmRoutine(Oid amhandler)
      28              : {
      29              :     Datum       datum;
      30              :     const TableAmRoutine *routine;
      31              : 
      32      1276595 :     datum = OidFunctionCall0(amhandler);
      33      1276595 :     routine = (const TableAmRoutine *) DatumGetPointer(datum);
      34              : 
      35      1276595 :     if (routine == NULL || !IsA(routine, TableAmRoutine))
      36            0 :         elog(ERROR, "table access method handler %u did not return a TableAmRoutine struct",
      37              :              amhandler);
      38              : 
      39              :     /*
      40              :      * Assert that all required callbacks are present. That makes it a bit
      41              :      * easier to keep AMs up to date, e.g. when forward porting them to a new
      42              :      * major version.
      43              :      */
      44              :     Assert(routine->scan_begin != NULL);
      45              :     Assert(routine->scan_end != NULL);
      46              :     Assert(routine->scan_rescan != NULL);
      47              :     Assert(routine->scan_getnextslot != NULL);
      48              : 
      49              :     Assert(routine->parallelscan_estimate != NULL);
      50              :     Assert(routine->parallelscan_initialize != NULL);
      51              :     Assert(routine->parallelscan_reinitialize != NULL);
      52              : 
      53              :     Assert(routine->index_fetch_begin != NULL);
      54              :     Assert(routine->index_fetch_reset != NULL);
      55              :     Assert(routine->index_fetch_end != NULL);
      56              :     Assert(routine->index_fetch_tuple != NULL);
      57              : 
      58              :     Assert(routine->tuple_fetch_row_version != NULL);
      59              :     Assert(routine->tuple_tid_valid != NULL);
      60              :     Assert(routine->tuple_get_latest_tid != NULL);
      61              :     Assert(routine->tuple_satisfies_snapshot != NULL);
      62              :     Assert(routine->index_delete_tuples != NULL);
      63              : 
      64              :     Assert(routine->tuple_insert != NULL);
      65              : 
      66              :     /*
      67              :      * Could be made optional, but would require throwing error during
      68              :      * parse-analysis.
      69              :      */
      70              :     Assert(routine->tuple_insert_speculative != NULL);
      71              :     Assert(routine->tuple_complete_speculative != NULL);
      72              : 
      73              :     Assert(routine->multi_insert != NULL);
      74              :     Assert(routine->tuple_delete != NULL);
      75              :     Assert(routine->tuple_update != NULL);
      76              :     Assert(routine->tuple_lock != NULL);
      77              : 
      78              :     Assert(routine->relation_set_new_filelocator != NULL);
      79              :     Assert(routine->relation_nontransactional_truncate != NULL);
      80              :     Assert(routine->relation_copy_data != NULL);
      81              :     Assert(routine->relation_copy_for_cluster != NULL);
      82              :     Assert(routine->relation_vacuum != NULL);
      83              :     Assert(routine->scan_analyze_next_block != NULL);
      84              :     Assert(routine->scan_analyze_next_tuple != NULL);
      85              :     Assert(routine->index_build_range_scan != NULL);
      86              :     Assert(routine->index_validate_scan != NULL);
      87              : 
      88              :     Assert(routine->relation_size != NULL);
      89              :     Assert(routine->relation_needs_toast_table != NULL);
      90              : 
      91              :     Assert(routine->relation_estimate_size != NULL);
      92              : 
      93              :     Assert(routine->scan_sample_next_block != NULL);
      94              :     Assert(routine->scan_sample_next_tuple != NULL);
      95              : 
      96      1276595 :     return routine;
      97              : }
      98              : 
      99              : /* check_hook: validate new default_table_access_method */
     100              : bool
     101         1259 : check_default_table_access_method(char **newval, void **extra, GucSource source)
     102              : {
     103         1259 :     if (**newval == '\0')
     104              :     {
     105            3 :         GUC_check_errdetail("\"%s\" cannot be empty.",
     106              :                             "default_table_access_method");
     107            3 :         return false;
     108              :     }
     109              : 
     110         1256 :     if (strlen(*newval) >= NAMEDATALEN)
     111              :     {
     112            0 :         GUC_check_errdetail("\"%s\" is too long (maximum %d characters).",
     113              :                             "default_table_access_method", NAMEDATALEN - 1);
     114            0 :         return false;
     115              :     }
     116              : 
     117              :     /*
     118              :      * If we aren't inside a transaction, or not connected to a database, we
     119              :      * cannot do the catalog access necessary to verify the method.  Must
     120              :      * accept the value on faith.
     121              :      */
     122         1256 :     if (IsTransactionState() && MyDatabaseId != InvalidOid)
     123              :     {
     124           69 :         if (!OidIsValid(get_table_am_oid(*newval, true)))
     125              :         {
     126              :             /*
     127              :              * When source == PGC_S_TEST, don't throw a hard error for a
     128              :              * nonexistent table access method, only a NOTICE. See comments in
     129              :              * guc.h.
     130              :              */
     131            3 :             if (source == PGC_S_TEST)
     132              :             {
     133            0 :                 ereport(NOTICE,
     134              :                         (errcode(ERRCODE_UNDEFINED_OBJECT),
     135              :                          errmsg("table access method \"%s\" does not exist",
     136              :                                 *newval)));
     137              :             }
     138              :             else
     139              :             {
     140            3 :                 GUC_check_errdetail("Table access method \"%s\" does not exist.",
     141              :                                     *newval);
     142            3 :                 return false;
     143              :             }
     144              :         }
     145              :     }
     146              : 
     147         1250 :     return true;
     148              : }
        

Generated by: LCOV version 2.0-1