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-2024, 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 will be palloc'd in the caller's
25 : : * memory context.
26 : : */
27 : : const TableAmRoutine *
1866 andres@anarazel.de 28 :CBC 953690 : GetTableAmRoutine(Oid amhandler)
29 : : {
30 : : Datum datum;
31 : : const TableAmRoutine *routine;
32 : :
33 : 953690 : datum = OidFunctionCall0(amhandler);
34 : 953690 : routine = (TableAmRoutine *) DatumGetPointer(datum);
35 : :
36 [ + - - + ]: 953690 : if (routine == NULL || !IsA(routine, TableAmRoutine))
1837 andres@anarazel.de 37 [ # # ]:UBC 0 : elog(ERROR, "table access method handler %u did not return a TableAmRoutine struct",
38 : : amhandler);
39 : :
40 : : /*
41 : : * Assert that all required callbacks are present. That makes it a bit
42 : : * easier to keep AMs up to date, e.g. when forward porting them to a new
43 : : * major version.
44 : : */
1861 andres@anarazel.de 45 [ - + ]:CBC 953690 : Assert(routine->scan_begin != NULL);
46 [ - + ]: 953690 : Assert(routine->scan_end != NULL);
47 [ - + ]: 953690 : Assert(routine->scan_rescan != NULL);
1744 akapila@postgresql.o 48 [ - + ]: 953690 : Assert(routine->scan_getnextslot != NULL);
49 : :
1861 andres@anarazel.de 50 [ - + ]: 953690 : Assert(routine->parallelscan_estimate != NULL);
51 [ - + ]: 953690 : Assert(routine->parallelscan_initialize != NULL);
52 [ - + ]: 953690 : Assert(routine->parallelscan_reinitialize != NULL);
53 : :
54 [ - + ]: 953690 : Assert(routine->index_fetch_begin != NULL);
55 [ - + ]: 953690 : Assert(routine->index_fetch_reset != NULL);
56 [ - + ]: 953690 : Assert(routine->index_fetch_end != NULL);
57 [ - + ]: 953690 : Assert(routine->index_fetch_tuple != NULL);
58 : :
1847 59 [ - + ]: 953690 : Assert(routine->tuple_fetch_row_version != NULL);
1744 akapila@postgresql.o 60 [ - + ]: 953690 : Assert(routine->tuple_tid_valid != NULL);
61 [ - + ]: 953690 : Assert(routine->tuple_get_latest_tid != NULL);
1861 andres@anarazel.de 62 [ - + ]: 953690 : Assert(routine->tuple_satisfies_snapshot != NULL);
1187 pg@bowt.ie 63 [ - + ]: 953690 : Assert(routine->index_delete_tuples != NULL);
64 : :
1849 andres@anarazel.de 65 [ - + ]: 953690 : Assert(routine->tuple_insert != NULL);
66 : :
67 : : /*
68 : : * Could be made optional, but would require throwing error during
69 : : * parse-analysis.
70 : : */
71 [ - + ]: 953690 : Assert(routine->tuple_insert_speculative != NULL);
72 [ - + ]: 953690 : Assert(routine->tuple_complete_speculative != NULL);
73 : :
1837 74 [ - + ]: 953690 : Assert(routine->multi_insert != NULL);
1849 75 [ - + ]: 953690 : Assert(routine->tuple_delete != NULL);
76 [ - + ]: 953690 : Assert(routine->tuple_update != NULL);
77 [ - + ]: 953690 : Assert(routine->tuple_lock != NULL);
78 : :
648 rhaas@postgresql.org 79 [ - + ]: 953690 : Assert(routine->relation_set_new_filelocator != NULL);
1842 andres@anarazel.de 80 [ - + ]: 953690 : Assert(routine->relation_nontransactional_truncate != NULL);
81 [ - + ]: 953690 : Assert(routine->relation_copy_data != NULL);
82 [ - + ]: 953690 : Assert(routine->relation_copy_for_cluster != NULL);
83 [ - + ]: 953690 : Assert(routine->relation_vacuum != NULL);
84 [ - + ]: 953690 : Assert(routine->index_build_range_scan != NULL);
85 [ - + ]: 953690 : Assert(routine->index_validate_scan != NULL);
86 : :
1794 87 [ - + ]: 953690 : Assert(routine->relation_size != NULL);
1744 akapila@postgresql.o 88 [ - + ]: 953690 : Assert(routine->relation_needs_toast_table != NULL);
89 : :
1842 andres@anarazel.de 90 [ - + ]: 953690 : Assert(routine->relation_estimate_size != NULL);
91 : :
92 : : /* optional, but one callback implies presence of the other */
1841 93 [ - + ]: 953690 : Assert((routine->scan_bitmap_next_block == NULL) ==
94 : : (routine->scan_bitmap_next_tuple == NULL));
1842 95 [ - + ]: 953690 : Assert(routine->scan_sample_next_block != NULL);
96 [ - + ]: 953690 : Assert(routine->scan_sample_next_tuple != NULL);
97 : :
1866 98 : 953690 : return routine;
99 : : }
100 : :
101 : : /* check_hook: validate new default_table_access_method */
102 : : bool
103 : 985 : check_default_table_access_method(char **newval, void **extra, GucSource source)
104 : : {
1837 105 [ + + ]: 985 : if (**newval == '\0')
106 : : {
1774 alvherre@alvh.no-ip. 107 : 3 : GUC_check_errdetail("%s cannot be empty.",
108 : : "default_table_access_method");
1837 andres@anarazel.de 109 : 3 : return false;
110 : : }
111 : :
112 [ - + ]: 982 : if (strlen(*newval) >= NAMEDATALEN)
113 : : {
1811 alvherre@alvh.no-ip. 114 :UBC 0 : GUC_check_errdetail("%s is too long (maximum %d characters).",
115 : : "default_table_access_method", NAMEDATALEN - 1);
1837 andres@anarazel.de 116 : 0 : return false;
117 : : }
118 : :
119 : : /*
120 : : * If we aren't inside a transaction, or not connected to a database, we
121 : : * cannot do the catalog access necessary to verify the method. Must
122 : : * accept the value on faith.
123 : : */
1770 andres@anarazel.de 124 [ + + + - ]:CBC 982 : if (IsTransactionState() && MyDatabaseId != InvalidOid)
125 : : {
1837 126 [ + + ]: 54 : if (!OidIsValid(get_table_am_oid(*newval, true)))
127 : : {
128 : : /*
129 : : * When source == PGC_S_TEST, don't throw a hard error for a
130 : : * nonexistent table access method, only a NOTICE. See comments in
131 : : * guc.h.
132 : : */
1866 133 [ - + ]: 3 : if (source == PGC_S_TEST)
134 : : {
1866 andres@anarazel.de 135 [ # # ]:UBC 0 : ereport(NOTICE,
136 : : (errcode(ERRCODE_UNDEFINED_OBJECT),
137 : : errmsg("table access method \"%s\" does not exist",
138 : : *newval)));
139 : : }
140 : : else
141 : : {
1866 andres@anarazel.de 142 :CBC 3 : GUC_check_errdetail("Table access method \"%s\" does not exist.",
143 : : *newval);
144 : 3 : return false;
145 : : }
146 : : }
147 : : }
148 : :
149 : 976 : return true;
150 : : }
|