Age Owner Branch data 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-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 *
2566 andres@anarazel.de 27 :CBC 1113270 : GetTableAmRoutine(Oid amhandler)
28 : : {
29 : : Datum datum;
30 : : const TableAmRoutine *routine;
31 : :
32 : 1113270 : datum = OidFunctionCall0(amhandler);
75 tgl@sss.pgh.pa.us 33 :GNC 1113270 : routine = (const TableAmRoutine *) DatumGetPointer(datum);
34 : :
2566 andres@anarazel.de 35 [ + - - + ]:CBC 1113270 : if (routine == NULL || !IsA(routine, TableAmRoutine))
2537 andres@anarazel.de 36 [ # # ]:UBC 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 : : */
2561 andres@anarazel.de 44 [ - + ]:CBC 1113270 : Assert(routine->scan_begin != NULL);
45 [ - + ]: 1113270 : Assert(routine->scan_end != NULL);
46 [ - + ]: 1113270 : Assert(routine->scan_rescan != NULL);
2444 akapila@postgresql.o 47 [ - + ]: 1113270 : Assert(routine->scan_getnextslot != NULL);
48 : :
2561 andres@anarazel.de 49 [ - + ]: 1113270 : Assert(routine->parallelscan_estimate != NULL);
50 [ - + ]: 1113270 : Assert(routine->parallelscan_initialize != NULL);
51 [ - + ]: 1113270 : Assert(routine->parallelscan_reinitialize != NULL);
52 : :
53 [ - + ]: 1113270 : Assert(routine->index_fetch_begin != NULL);
54 [ - + ]: 1113270 : Assert(routine->index_fetch_reset != NULL);
55 [ - + ]: 1113270 : Assert(routine->index_fetch_end != NULL);
56 [ - + ]: 1113270 : Assert(routine->index_fetch_tuple != NULL);
57 : :
2547 58 [ - + ]: 1113270 : Assert(routine->tuple_fetch_row_version != NULL);
2444 akapila@postgresql.o 59 [ - + ]: 1113270 : Assert(routine->tuple_tid_valid != NULL);
60 [ - + ]: 1113270 : Assert(routine->tuple_get_latest_tid != NULL);
2561 andres@anarazel.de 61 [ - + ]: 1113270 : Assert(routine->tuple_satisfies_snapshot != NULL);
1887 pg@bowt.ie 62 [ - + ]: 1113270 : Assert(routine->index_delete_tuples != NULL);
63 : :
2549 andres@anarazel.de 64 [ - + ]: 1113270 : Assert(routine->tuple_insert != NULL);
65 : :
66 : : /*
67 : : * Could be made optional, but would require throwing error during
68 : : * parse-analysis.
69 : : */
70 [ - + ]: 1113270 : Assert(routine->tuple_insert_speculative != NULL);
71 [ - + ]: 1113270 : Assert(routine->tuple_complete_speculative != NULL);
72 : :
2537 73 [ - + ]: 1113270 : Assert(routine->multi_insert != NULL);
2549 74 [ - + ]: 1113270 : Assert(routine->tuple_delete != NULL);
75 [ - + ]: 1113270 : Assert(routine->tuple_update != NULL);
76 [ - + ]: 1113270 : Assert(routine->tuple_lock != NULL);
77 : :
1348 rhaas@postgresql.org 78 [ - + ]: 1113270 : Assert(routine->relation_set_new_filelocator != NULL);
2542 andres@anarazel.de 79 [ - + ]: 1113270 : Assert(routine->relation_nontransactional_truncate != NULL);
80 [ - + ]: 1113270 : Assert(routine->relation_copy_data != NULL);
81 [ - + ]: 1113270 : Assert(routine->relation_copy_for_cluster != NULL);
82 [ - + ]: 1113270 : Assert(routine->relation_vacuum != NULL);
698 akorotkov@postgresql 83 [ - + ]: 1113270 : Assert(routine->scan_analyze_next_block != NULL);
84 [ - + ]: 1113270 : Assert(routine->scan_analyze_next_tuple != NULL);
2542 andres@anarazel.de 85 [ - + ]: 1113270 : Assert(routine->index_build_range_scan != NULL);
86 [ - + ]: 1113270 : Assert(routine->index_validate_scan != NULL);
87 : :
2494 88 [ - + ]: 1113270 : Assert(routine->relation_size != NULL);
2444 akapila@postgresql.o 89 [ - + ]: 1113270 : Assert(routine->relation_needs_toast_table != NULL);
90 : :
2542 andres@anarazel.de 91 [ - + ]: 1113270 : Assert(routine->relation_estimate_size != NULL);
92 : :
93 [ - + ]: 1113270 : Assert(routine->scan_sample_next_block != NULL);
94 [ - + ]: 1113270 : Assert(routine->scan_sample_next_tuple != NULL);
95 : :
2566 96 : 1113270 : return routine;
97 : : }
98 : :
99 : : /* check_hook: validate new default_table_access_method */
100 : : bool
101 : 1256 : check_default_table_access_method(char **newval, void **extra, GucSource source)
102 : : {
2537 103 [ + + ]: 1256 : if (**newval == '\0')
104 : : {
667 peter@eisentraut.org 105 : 3 : GUC_check_errdetail("\"%s\" cannot be empty.",
106 : : "default_table_access_method");
2537 andres@anarazel.de 107 : 3 : return false;
108 : : }
109 : :
110 [ - + ]: 1253 : if (strlen(*newval) >= NAMEDATALEN)
111 : : {
667 peter@eisentraut.org 112 :UBC 0 : GUC_check_errdetail("\"%s\" is too long (maximum %d characters).",
113 : : "default_table_access_method", NAMEDATALEN - 1);
2537 andres@anarazel.de 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 : : */
2470 andres@anarazel.de 122 [ + + + - ]:CBC 1253 : if (IsTransactionState() && MyDatabaseId != InvalidOid)
123 : : {
2537 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 : : */
2566 131 [ - + ]: 3 : if (source == PGC_S_TEST)
132 : : {
2566 andres@anarazel.de 133 [ # # ]:UBC 0 : ereport(NOTICE,
134 : : (errcode(ERRCODE_UNDEFINED_OBJECT),
135 : : errmsg("table access method \"%s\" does not exist",
136 : : *newval)));
137 : : }
138 : : else
139 : : {
2566 andres@anarazel.de 140 :CBC 3 : GUC_check_errdetail("Table access method \"%s\" does not exist.",
141 : : *newval);
142 : 3 : return false;
143 : : }
144 : : }
145 : : }
146 : :
147 : 1247 : return true;
148 : : }
|