From 5fedf7417b69295294b154a219edd8a26eaa6ab6 Mon Sep 17 00:00:00 2001 From: Fujii Masao Date: Wed, 27 Oct 2021 00:46:52 +0900 Subject: [PATCH] Improve HINT message that FDW reports when there are no valid options. The foreign data wrapper's validator function provides a HINT message with list of valid options for the object specified in CREATE or ALTER command, when the option given in the command is invalid. Previously postgresql_fdw_validator() and the validator functions for postgres_fdw and dblink_fdw worked in that way even there were no valid options in the object, which could lead to the HINT message with empty list (because there were no valid options). For example, ALTER FOREIGN DATA WRAPPER postgres_fdw OPTIONS (format 'csv') reported the following ERROR and HINT messages. This behavior was confusing. ERROR: invalid option "format" HINT: Valid options in this context are: There is no such issue in file_fdw. The validator function for file_fdw reports the HINT message "There are no valid options in this context." instead in that case. This commit improves postgresql_fdw_validator() and the validator functions for postgres_fdw and dblink_fdw so that they do likewise. For example, this change causes the above ALTER FOREIGN DATA WRAPPER command to report the following messages. ERROR: invalid option "nonexistent" HINT: There are no valid options in this context. Author: Kosei Masumura Reviewed-by: Bharath Rupireddy, Fujii Masao Discussion: https://postgr.es/m/557d06cebe19081bfcc83ee2affc98d3@oss.nttdata.com --- contrib/dblink/dblink.c | 6 ++++-- contrib/dblink/expected/dblink.out | 4 ++++ contrib/dblink/sql/dblink.sql | 3 +++ contrib/postgres_fdw/expected/postgres_fdw.out | 6 +++++- contrib/postgres_fdw/option.c | 6 ++++-- contrib/postgres_fdw/sql/postgres_fdw.sql | 5 ++++- src/backend/foreign/foreign.c | 6 ++++-- src/test/regress/expected/foreign_data.out | 3 +++ src/test/regress/sql/foreign_data.sql | 2 ++ 9 files changed, 33 insertions(+), 8 deletions(-) diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c index 3a0beaa88e7..c8b0b4ff3fa 100644 --- a/contrib/dblink/dblink.c +++ b/contrib/dblink/dblink.c @@ -2054,8 +2054,10 @@ dblink_fdw_validator(PG_FUNCTION_ARGS) ereport(ERROR, (errcode(ERRCODE_FDW_OPTION_NAME_NOT_FOUND), errmsg("invalid option \"%s\"", def->defname), - errhint("Valid options in this context are: %s", - buf.data))); + buf.len > 0 + ? errhint("Valid options in this context are: %s", + buf.data) + : errhint("There are no valid options in this context."))); } } diff --git a/contrib/dblink/expected/dblink.out b/contrib/dblink/expected/dblink.out index 6516d4f1313..91cbd744a99 100644 --- a/contrib/dblink/expected/dblink.out +++ b/contrib/dblink/expected/dblink.out @@ -917,6 +917,10 @@ REVOKE EXECUTE ON FUNCTION dblink_connect_u(text, text) FROM regress_dblink_user DROP USER regress_dblink_user; DROP USER MAPPING FOR public SERVER fdtest; DROP SERVER fdtest; +-- should fail +ALTER FOREIGN DATA WRAPPER dblink_fdw OPTIONS (nonexistent 'fdw'); +ERROR: invalid option "nonexistent" +HINT: There are no valid options in this context. -- test asynchronous notifications SELECT dblink_connect(connection_parameters()); dblink_connect diff --git a/contrib/dblink/sql/dblink.sql b/contrib/dblink/sql/dblink.sql index 3e96b985712..7a71817d65b 100644 --- a/contrib/dblink/sql/dblink.sql +++ b/contrib/dblink/sql/dblink.sql @@ -463,6 +463,9 @@ DROP USER regress_dblink_user; DROP USER MAPPING FOR public SERVER fdtest; DROP SERVER fdtest; +-- should fail +ALTER FOREIGN DATA WRAPPER dblink_fdw OPTIONS (nonexistent 'fdw'); + -- test asynchronous notifications SELECT dblink_connect(connection_parameters()); diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out index 44c4367b8f9..fd141a0fa5c 100644 --- a/contrib/postgres_fdw/expected/postgres_fdw.out +++ b/contrib/postgres_fdw/expected/postgres_fdw.out @@ -10746,7 +10746,7 @@ DROP TABLE join_tbl; ALTER SERVER loopback OPTIONS (DROP async_capable); ALTER SERVER loopback2 OPTIONS (DROP async_capable); -- =================================================================== --- test invalid server and foreign table options +-- test invalid server, foreign table and foreign data wrapper options -- =================================================================== -- Invalid fdw_startup_cost option CREATE SERVER inv_scst FOREIGN DATA WRAPPER postgres_fdw @@ -10764,3 +10764,7 @@ ERROR: invalid value for integer option "fetch_size": 100$%$#$# CREATE FOREIGN TABLE inv_bsz (c1 int ) SERVER loopback OPTIONS (batch_size '100$%$#$#'); ERROR: invalid value for integer option "batch_size": 100$%$#$# +-- No option is allowed to be specified at foreign data wrapper level +ALTER FOREIGN DATA WRAPPER postgres_fdw OPTIONS (nonexistent 'fdw'); +ERROR: invalid option "nonexistent" +HINT: There are no valid options in this context. diff --git a/contrib/postgres_fdw/option.c b/contrib/postgres_fdw/option.c index 5bb1af4084a..48c7417e6ec 100644 --- a/contrib/postgres_fdw/option.c +++ b/contrib/postgres_fdw/option.c @@ -107,8 +107,10 @@ postgres_fdw_validator(PG_FUNCTION_ARGS) ereport(ERROR, (errcode(ERRCODE_FDW_INVALID_OPTION_NAME), errmsg("invalid option \"%s\"", def->defname), - errhint("Valid options in this context are: %s", - buf.data))); + buf.len > 0 + ? errhint("Valid options in this context are: %s", + buf.data) + : errhint("There are no valid options in this context."))); } /* diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql index e7b869f8cea..43c30d492da 100644 --- a/contrib/postgres_fdw/sql/postgres_fdw.sql +++ b/contrib/postgres_fdw/sql/postgres_fdw.sql @@ -3409,7 +3409,7 @@ ALTER SERVER loopback OPTIONS (DROP async_capable); ALTER SERVER loopback2 OPTIONS (DROP async_capable); -- =================================================================== --- test invalid server and foreign table options +-- test invalid server, foreign table and foreign data wrapper options -- =================================================================== -- Invalid fdw_startup_cost option CREATE SERVER inv_scst FOREIGN DATA WRAPPER postgres_fdw @@ -3423,3 +3423,6 @@ CREATE FOREIGN TABLE inv_fsz (c1 int ) -- Invalid batch_size option CREATE FOREIGN TABLE inv_bsz (c1 int ) SERVER loopback OPTIONS (batch_size '100$%$#$#'); + +-- No option is allowed to be specified at foreign data wrapper level +ALTER FOREIGN DATA WRAPPER postgres_fdw OPTIONS (nonexistent 'fdw'); diff --git a/src/backend/foreign/foreign.c b/src/backend/foreign/foreign.c index 5564dc3a1e2..e07cc574312 100644 --- a/src/backend/foreign/foreign.c +++ b/src/backend/foreign/foreign.c @@ -670,8 +670,10 @@ postgresql_fdw_validator(PG_FUNCTION_ARGS) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("invalid option \"%s\"", def->defname), - errhint("Valid options in this context are: %s", - buf.data))); + buf.len > 0 + ? errhint("Valid options in this context are: %s", + buf.data) + : errhint("There are no valid options in this context."))); PG_RETURN_BOOL(false); } diff --git a/src/test/regress/expected/foreign_data.out b/src/test/regress/expected/foreign_data.out index 426080ae39b..a6a68d1fa2a 100644 --- a/src/test/regress/expected/foreign_data.out +++ b/src/test/regress/expected/foreign_data.out @@ -100,6 +100,9 @@ LINE 1: ...GN DATA WRAPPER test_fdw HANDLER test_fdw_handler HANDLER in... CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler; DROP FOREIGN DATA WRAPPER test_fdw; -- ALTER FOREIGN DATA WRAPPER +ALTER FOREIGN DATA WRAPPER foo OPTIONS (nonexistent 'fdw'); -- ERROR +ERROR: invalid option "nonexistent" +HINT: There are no valid options in this context. ALTER FOREIGN DATA WRAPPER foo; -- ERROR ERROR: syntax error at or near ";" LINE 1: ALTER FOREIGN DATA WRAPPER foo; diff --git a/src/test/regress/sql/foreign_data.sql b/src/test/regress/sql/foreign_data.sql index 73f9f621d8f..a65f4ffdca1 100644 --- a/src/test/regress/sql/foreign_data.sql +++ b/src/test/regress/sql/foreign_data.sql @@ -59,6 +59,8 @@ CREATE FOREIGN DATA WRAPPER test_fdw HANDLER test_fdw_handler; DROP FOREIGN DATA WRAPPER test_fdw; -- ALTER FOREIGN DATA WRAPPER +ALTER FOREIGN DATA WRAPPER foo OPTIONS (nonexistent 'fdw'); -- ERROR + ALTER FOREIGN DATA WRAPPER foo; -- ERROR ALTER FOREIGN DATA WRAPPER foo VALIDATOR bar; -- ERROR ALTER FOREIGN DATA WRAPPER foo NO VALIDATOR;