LCOV - differential code coverage report
Current view: top level - src/backend/access/table - tableamapi.c (source / functions) Coverage Total Hit LBC UIC GIC GNC CBC EUB ECB
Current: Differential Code Coverage HEAD vs 15 Lines: 93.1 % 58 54 1 3 26 1 27 4 26
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 2 2 2 2
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  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-2023, 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/heapam.h"
      15                 : #include "access/htup_details.h"
      16                 : #include "access/tableam.h"
      17                 : #include "access/xact.h"
      18                 : #include "catalog/pg_am.h"
      19                 : #include "catalog/pg_proc.h"
      20                 : #include "commands/defrem.h"
      21                 : #include "miscadmin.h"
      22                 : #include "utils/fmgroids.h"
      23                 : #include "utils/guc_hooks.h"
      24                 : #include "utils/memutils.h"
      25                 : #include "utils/syscache.h"
      26                 : 
      27                 : 
      28                 : /*
      29                 :  * GetTableAmRoutine
      30                 :  *      Call the specified access method handler routine to get its
      31                 :  *      TableAmRoutine struct, which will be palloc'd in the caller's
      32                 :  *      memory context.
      33                 :  */
      34                 : const TableAmRoutine *
      35 GIC      881910 : GetTableAmRoutine(Oid amhandler)
      36 ECB             : {
      37                 :     Datum       datum;
      38                 :     const TableAmRoutine *routine;
      39                 : 
      40 GIC      881910 :     datum = OidFunctionCall0(amhandler);
      41 CBC      881910 :     routine = (TableAmRoutine *) DatumGetPointer(datum);
      42 ECB             : 
      43 GIC      881910 :     if (routine == NULL || !IsA(routine, TableAmRoutine))
      44 LBC           0 :         elog(ERROR, "table access method handler %u did not return a TableAmRoutine struct",
      45 EUB             :              amhandler);
      46                 : 
      47                 :     /*
      48                 :      * Assert that all required callbacks are present. That makes it a bit
      49                 :      * easier to keep AMs up to date, e.g. when forward porting them to a new
      50                 :      * major version.
      51                 :      */
      52 GIC      881910 :     Assert(routine->scan_begin != NULL);
      53 CBC      881910 :     Assert(routine->scan_end != NULL);
      54          881910 :     Assert(routine->scan_rescan != NULL);
      55          881910 :     Assert(routine->scan_getnextslot != NULL);
      56 ECB             : 
      57 GIC      881910 :     Assert(routine->parallelscan_estimate != NULL);
      58 CBC      881910 :     Assert(routine->parallelscan_initialize != NULL);
      59          881910 :     Assert(routine->parallelscan_reinitialize != NULL);
      60 ECB             : 
      61 GIC      881910 :     Assert(routine->index_fetch_begin != NULL);
      62 CBC      881910 :     Assert(routine->index_fetch_reset != NULL);
      63          881910 :     Assert(routine->index_fetch_end != NULL);
      64          881910 :     Assert(routine->index_fetch_tuple != NULL);
      65 ECB             : 
      66 GIC      881910 :     Assert(routine->tuple_fetch_row_version != NULL);
      67 CBC      881910 :     Assert(routine->tuple_tid_valid != NULL);
      68          881910 :     Assert(routine->tuple_get_latest_tid != NULL);
      69          881910 :     Assert(routine->tuple_satisfies_snapshot != NULL);
      70          881910 :     Assert(routine->index_delete_tuples != NULL);
      71 ECB             : 
      72 GIC      881910 :     Assert(routine->tuple_insert != NULL);
      73 ECB             : 
      74                 :     /*
      75                 :      * Could be made optional, but would require throwing error during
      76                 :      * parse-analysis.
      77                 :      */
      78 GIC      881910 :     Assert(routine->tuple_insert_speculative != NULL);
      79 CBC      881910 :     Assert(routine->tuple_complete_speculative != NULL);
      80 ECB             : 
      81 GIC      881910 :     Assert(routine->multi_insert != NULL);
      82 CBC      881910 :     Assert(routine->tuple_delete != NULL);
      83          881910 :     Assert(routine->tuple_update != NULL);
      84          881910 :     Assert(routine->tuple_lock != NULL);
      85 ECB             : 
      86 GNC      881910 :     Assert(routine->relation_set_new_filelocator != NULL);
      87 CBC      881910 :     Assert(routine->relation_nontransactional_truncate != NULL);
      88          881910 :     Assert(routine->relation_copy_data != NULL);
      89          881910 :     Assert(routine->relation_copy_for_cluster != NULL);
      90          881910 :     Assert(routine->relation_vacuum != NULL);
      91          881910 :     Assert(routine->scan_analyze_next_block != NULL);
      92          881910 :     Assert(routine->scan_analyze_next_tuple != NULL);
      93          881910 :     Assert(routine->index_build_range_scan != NULL);
      94          881910 :     Assert(routine->index_validate_scan != NULL);
      95 ECB             : 
      96 GIC      881910 :     Assert(routine->relation_size != NULL);
      97 CBC      881910 :     Assert(routine->relation_needs_toast_table != NULL);
      98 ECB             : 
      99 GIC      881910 :     Assert(routine->relation_estimate_size != NULL);
     100 ECB             : 
     101                 :     /* optional, but one callback implies presence of the other */
     102 GIC      881910 :     Assert((routine->scan_bitmap_next_block == NULL) ==
     103 ECB             :            (routine->scan_bitmap_next_tuple == NULL));
     104 GIC      881910 :     Assert(routine->scan_sample_next_block != NULL);
     105 CBC      881910 :     Assert(routine->scan_sample_next_tuple != NULL);
     106 ECB             : 
     107 GIC      881910 :     return routine;
     108 ECB             : }
     109                 : 
     110                 : /* check_hook: validate new default_table_access_method */
     111                 : bool
     112 GIC        1888 : check_default_table_access_method(char **newval, void **extra, GucSource source)
     113 ECB             : {
     114 GIC        1888 :     if (**newval == '\0')
     115 ECB             :     {
     116 GIC           3 :         GUC_check_errdetail("%s cannot be empty.",
     117 ECB             :                             "default_table_access_method");
     118 GIC           3 :         return false;
     119 ECB             :     }
     120                 : 
     121 GIC        1885 :     if (strlen(*newval) >= NAMEDATALEN)
     122 ECB             :     {
     123 UIC           0 :         GUC_check_errdetail("%s is too long (maximum %d characters).",
     124 EUB             :                             "default_table_access_method", NAMEDATALEN - 1);
     125 UIC           0 :         return false;
     126 EUB             :     }
     127                 : 
     128                 :     /*
     129                 :      * If we aren't inside a transaction, or not connected to a database, we
     130                 :      * cannot do the catalog access necessary to verify the method.  Must
     131                 :      * accept the value on faith.
     132                 :      */
     133 GIC        1885 :     if (IsTransactionState() && MyDatabaseId != InvalidOid)
     134 ECB             :     {
     135 GIC          28 :         if (!OidIsValid(get_table_am_oid(*newval, true)))
     136 ECB             :         {
     137                 :             /*
     138                 :              * When source == PGC_S_TEST, don't throw a hard error for a
     139                 :              * nonexistent table access method, only a NOTICE. See comments in
     140                 :              * guc.h.
     141                 :              */
     142 GIC           3 :             if (source == PGC_S_TEST)
     143 ECB             :             {
     144 UIC           0 :                 ereport(NOTICE,
     145 EUB             :                         (errcode(ERRCODE_UNDEFINED_OBJECT),
     146                 :                          errmsg("table access method \"%s\" does not exist",
     147                 :                                 *newval)));
     148                 :             }
     149                 :             else
     150                 :             {
     151 GIC           3 :                 GUC_check_errdetail("Table access method \"%s\" does not exist.",
     152 ECB             :                                     *newval);
     153 GIC           3 :                 return false;
     154 ECB             :             }
     155                 :         }
     156                 :     }
     157                 : 
     158 GIC        1879 :     return true;
     159 ECB             : }
        

Generated by: LCOV version v1.16-55-g56c0a2a