0002-check_default_table_access_method-hook-to-verify-the.patch
application/octet-stream
Filename: 0002-check_default_table_access_method-hook-to-verify-the.patch
Type: application/octet-stream
Part: 2
Patch
Format: format-patch
Series: patch 0002
Subject: check_default_table_access_method hook to verify the access method
| File | + | − |
|---|---|---|
| src/backend/access/table/tableamapi.c | 88 | 0 |
| src/backend/utils/misc/guc.c | 1 | 2 |
| src/include/access/tableam.h | 4 | 0 |
From 8df9ac913811220bbcbfefa57e2204362c481cb9 Mon Sep 17 00:00:00 2001
From: kommih <haribabuk@fast.au.fujitsu.com>
Date: Thu, 27 Sep 2018 15:54:49 +1000
Subject: [PATCH 2/3] check_default_table_access_method hook to verify the
access method
---
src/backend/access/table/tableamapi.c | 88 +++++++++++++++++++++++++++
src/backend/utils/misc/guc.c | 3 +-
src/include/access/tableam.h | 4 ++
3 files changed, 93 insertions(+), 2 deletions(-)
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index 7f08500ef4..d4eb889bd2 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -14,11 +14,14 @@
#include "access/htup_details.h"
#include "access/tableam.h"
+#include "access/xact.h"
#include "catalog/pg_am.h"
#include "catalog/pg_proc.h"
+#include "utils/fmgroids.h"
#include "utils/syscache.h"
#include "utils/memutils.h"
+static Oid get_table_am_oid(const char *tableamname, bool missing_ok);
TupleTableSlot*
table_gimmegimmeslot(Relation relation, List **reglist)
@@ -97,3 +100,88 @@ GetTableAmRoutineByAmId(Oid amoid)
/* And finally, call the handler function to get the API struct. */
return GetTableAmRoutine(amhandler);
}
+
+/*
+ * get_table_am_oid - given a table access method name, look up the OID
+ *
+ * If missing_ok is false, throw an error if table access method name not
+ * found. If true, just return InvalidOid.
+ */
+static Oid
+get_table_am_oid(const char *tableamname, bool missing_ok)
+{
+ Oid result;
+ Relation rel;
+ TableScanDesc scandesc;
+ HeapTuple tuple;
+ ScanKeyData entry[1];
+
+ /*
+ * Search pg_tablespace. We use a heapscan here even though there is an
+ * index on name, on the theory that pg_tablespace will usually have just
+ * a few entries and so an indexed lookup is a waste of effort.
+ */
+ rel = heap_open(AccessMethodRelationId, AccessShareLock);
+
+ ScanKeyInit(&entry[0],
+ Anum_pg_am_amname,
+ BTEqualStrategyNumber, F_NAMEEQ,
+ CStringGetDatum(tableamname));
+ scandesc = table_beginscan_catalog(rel, 1, entry);
+ tuple = heap_scan_getnext(scandesc, ForwardScanDirection);
+
+ /* We assume that there can be at most one matching tuple */
+ if (HeapTupleIsValid(tuple) &&
+ ((Form_pg_am) GETSTRUCT(tuple))->amtype == AMTYPE_TABLE)
+ result = HeapTupleGetOid(tuple);
+ else
+ result = InvalidOid;
+
+ table_endscan(scandesc);
+ heap_close(rel, AccessShareLock);
+
+ if (!OidIsValid(result) && !missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("table access method \"%s\" does not exist",
+ tableamname)));
+
+ return result;
+}
+
+/* check_hook: validate new default_table_access_method */
+bool
+check_default_table_access_method(char **newval, void **extra, GucSource source)
+{
+ /*
+ * If we aren't inside a transaction, we cannot do database access so
+ * cannot verify the name. Must accept the value on faith.
+ */
+ if (IsTransactionState())
+ {
+ if (**newval != '\0' &&
+ !OidIsValid(get_table_am_oid(*newval, true)))
+ {
+ /*
+ * When source == PGC_S_TEST, don't throw a hard error for a
+ * nonexistent table access method, only a NOTICE.
+ * See comments in guc.h.
+ */
+ if (source == PGC_S_TEST)
+ {
+ ereport(NOTICE,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("Table access method \"%s\" does not exist",
+ *newval)));
+ }
+ else
+ {
+ GUC_check_errdetail("Table access method \"%s\" does not exist.",
+ *newval);
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 3b996c8088..94b135a48b 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -3336,8 +3336,7 @@ static struct config_string ConfigureNamesString[] =
},
&default_table_access_method,
DEFAULT_TABLE_ACCESS_METHOD,
- /* PBORKED: a check hook would be good */
- NULL, NULL, NULL
+ check_default_table_access_method, NULL, NULL
},
{
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index d0a5f59aa9..691f687ade 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -23,6 +23,7 @@
#include "nodes/execnodes.h"
#include "nodes/nodes.h"
#include "fmgr.h"
+#include "utils/guc.h"
#include "utils/rel.h"
#include "utils/snapmgr.h"
#include "utils/snapshot.h"
@@ -714,4 +715,7 @@ extern const TableAmRoutine * GetTableAmRoutine(Oid amhandler);
extern const TableAmRoutine * GetTableAmRoutineByAmId(Oid amoid);
extern const TableAmRoutine * GetHeapamTableAmRoutine(void);
+extern bool check_default_table_access_method(char **newval, void **extra,
+ GucSource source);
+
#endif /* TABLEAM_H */
--
2.18.0.windows.1