From dc21d9ba98924d80753194ca4bd8c00aafbdec6e Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Thu, 22 Aug 2024 12:52:40 +0900 Subject: [PATCH] Handle better the hint table if the extension is not created An environment enabling pg_hint_plan.enable_hint_table while pg_hint_plan has not been created as an extension would fail all its queries as the table created by the extension does not exist. This commit adds a check at the top of get_hints_from_table() to check if the extension is installed before attempting to use the hint table, generating a WARNING. We have discussed about a few options, but a WARNING is more consistent with how duplicated hints or compute_query_id disabled are handled. This does not completely close the failure hole, though, as it is still possible to see the table lookup failure for the CREATE EXTENSION command enabling pg_hint_plan as an extension if enable_hint_table is enabled. In terms of code simplicity, I am not really convinced that we need to do more just for that. This commit relies on 490f869d92e5 that has introduced syscache entries for pg_extension. On stable branches, we will need a different logic with a check on the table itself with its namespace. Idea based on some feedback from Julien Rouhaud. The tests are from me. Author: Sami Imseih, Michael Paquier Backpatch-through: 12 Per issue #191. --- Makefile | 2 +- expected/hint_table.out | 24 ++++++++++++++++++++++++ pg_hint_plan.c | 20 ++++++++++++++++++++ sql/hint_table.sql | 14 ++++++++++++++ 4 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 expected/hint_table.out create mode 100644 sql/hint_table.sql diff --git a/Makefile b/Makefile index 0c3c664..a4c3be6 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ MODULES = pg_hint_plan HINTPLANVER = 1.3.10 REGRESS = init base_plan pg_hint_plan ut-init ut-A ut-S ut-J ut-L ut-G ut-R \ - ut-fdw ut-W ut-T ut-fini plpgsql oldextversions + ut-fdw ut-W ut-T ut-fini plpgsql hint_table oldextversions REGRESS_OPTS = --encoding=UTF8 EXTENSION = pg_hint_plan diff --git a/expected/hint_table.out b/expected/hint_table.out new file mode 100644 index 0000000..4379726 --- /dev/null +++ b/expected/hint_table.out @@ -0,0 +1,24 @@ +-- Tests for the hint table +LOAD 'pg_hint_plan'; +-- Attempting to use the hint table without the extension created +-- emits a WARNING. +SET pg_hint_plan.enable_hint_table TO on; +SELECT 1; +WARNING: cannot use the hint table +HINT: Run "CREATE EXTENSION pg_hint_plan" to create the hint table. + ?column? +---------- + 1 +(1 row) + +SET pg_hint_plan.enable_hint_table TO off; +CREATE EXTENSION pg_hint_plan; +SET pg_hint_plan.enable_hint_table TO on; +SELECT 1; + ?column? +---------- + 1 +(1 row) + +SET pg_hint_plan.enable_hint_table TO off; +DROP EXTENSION pg_hint_plan; diff --git a/pg_hint_plan.c b/pg_hint_plan.c index 0411d36..bb5e67a 100644 --- a/pg_hint_plan.c +++ b/pg_hint_plan.c @@ -13,6 +13,7 @@ #include "access/genam.h" #include "access/heapam.h" #include "access/relation.h" +#include "catalog/namespace.h" #include "catalog/pg_collation.h" #include "catalog/pg_index.h" #include "commands/prepare.h" @@ -1774,6 +1775,25 @@ get_hints_from_table(const char *client_query, const char *client_application) char nulls[2] = {' ', ' '}; text *qry; text *app; + Oid namespaceId; + bool hints_table_found = false; + + /* + * Make sure that hint_plan.hints is found before we attempt to look for + * a hint. + */ + namespaceId = LookupExplicitNamespace("hint_plan", true); + if (OidIsValid(namespaceId) && + OidIsValid(get_relname_relid("hints", namespaceId))) + hints_table_found = true; + + if (!hints_table_found) + { + ereport(WARNING, + (errmsg ("cannot use the hint table"), + errhint("Run \"CREATE EXTENSION pg_hint_plan\" to create the hint table."))); + return NULL; + } PG_TRY(); { diff --git a/sql/hint_table.sql b/sql/hint_table.sql new file mode 100644 index 0000000..5f8af93 --- /dev/null +++ b/sql/hint_table.sql @@ -0,0 +1,14 @@ +-- Tests for the hint table +LOAD 'pg_hint_plan'; + +-- Attempting to use the hint table without the extension created +-- emits a WARNING. +SET pg_hint_plan.enable_hint_table TO on; +SELECT 1; +SET pg_hint_plan.enable_hint_table TO off; + +CREATE EXTENSION pg_hint_plan; +SET pg_hint_plan.enable_hint_table TO on; +SELECT 1; +SET pg_hint_plan.enable_hint_table TO off; +DROP EXTENSION pg_hint_plan;