From 1f2a4d378dc7f540d05f12a20e84547132ae2e02 Mon Sep 17 00:00:00 2001
From: Nishant Sharma <nishant.sharma@enterprisedb.com>
Date: Thu, 19 Dec 2024 16:11:07 +0530
Subject: [PATCH v4] Disallow empty Foreign Table column_name, schema_name,
 table_name options for postgres_fdw.

---
 contrib/postgres_fdw/expected/postgres_fdw.out | 24 ++++++++++++++++++++++++
 contrib/postgres_fdw/option.c                  | 16 ++++++++++++++++
 contrib/postgres_fdw/sql/postgres_fdw.sql      | 21 +++++++++++++++++++++
 3 files changed, 61 insertions(+)

diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out
index bf32219..ef5d93e 100644
--- a/contrib/postgres_fdw/expected/postgres_fdw.out
+++ b/contrib/postgres_fdw/expected/postgres_fdw.out
@@ -139,6 +139,24 @@ CREATE FOREIGN TABLE ft7 (
 	c2 int NOT NULL,
 	c3 text
 ) SERVER loopback3 OPTIONS (schema_name 'S 1', table_name 'T 4');
+CREATE FOREIGN TABLE ft8 (
+	c1 int OPTIONS (column_name '') NOT NULL,
+	c2 int NOT NULL,
+	c3 text
+) SERVER loopback3 OPTIONS (schema_name 'S 1', table_name 'T 4');
+ERROR:  value for option "column_name" must not be empty string
+CREATE FOREIGN TABLE ft8 (
+	c1 int NOT NULL,
+	c2 int NOT NULL,
+	c3 text
+) SERVER loopback3 OPTIONS (schema_name '', table_name 'T 4');
+ERROR:  value for option "schema_name" must not be empty string
+CREATE FOREIGN TABLE ft8 (
+	c1 int NOT NULL,
+	c2 int NOT NULL,
+	c3 text
+) SERVER loopback3 OPTIONS (schema_name 'S 1', table_name '');
+ERROR:  value for option "table_name" must not be empty string
 -- ===================================================================
 -- tests for validator
 -- ===================================================================
@@ -196,10 +214,16 @@ ALTER USER MAPPING FOR public SERVER testserver1
 -- permitted to check validation.
 ALTER USER MAPPING FOR public SERVER testserver1
 	OPTIONS (ADD sslkey 'value', ADD sslcert 'value');
+ALTER FOREIGN TABLE ft1 OPTIONS (schema_name '', table_name 'T 1');
+ERROR:  value for option "schema_name" must not be empty string
+ALTER FOREIGN TABLE ft1 OPTIONS (schema_name 'S 1', table_name '');
+ERROR:  value for option "table_name" must not be empty string
 ALTER FOREIGN TABLE ft1 OPTIONS (schema_name 'S 1', table_name 'T 1');
 ALTER FOREIGN TABLE ft2 OPTIONS (schema_name 'S 1', table_name 'T 1');
 ALTER FOREIGN TABLE ft1 ALTER COLUMN c1 OPTIONS (column_name 'C 1');
 ALTER FOREIGN TABLE ft2 ALTER COLUMN c1 OPTIONS (column_name 'C 1');
+ALTER FOREIGN TABLE ft2 ALTER COLUMN c2 OPTIONS (column_name '');
+ERROR:  value for option "column_name" must not be empty string
 \det+
                               List of foreign tables
  Schema | Table |  Server   |              FDW options              | Description 
diff --git a/contrib/postgres_fdw/option.c b/contrib/postgres_fdw/option.c
index 232d853..63bbd88 100644
--- a/contrib/postgres_fdw/option.c
+++ b/contrib/postgres_fdw/option.c
@@ -227,6 +227,22 @@ postgres_fdw_validator(PG_FUNCTION_ARGS)
 						 errmsg("invalid value for string option \"%s\": %s",
 								def->defname, value)));
 		}
+		else if (strcmp(def->defname, "column_name") == 0 ||
+				 strcmp(def->defname, "schema_name") == 0 ||
+				 strcmp(def->defname, "table_name") == 0)
+		{
+			char	   *obj_name_opt = defGetString(def);
+
+			/*
+			 * PostgreSQL follows SQL syntax, so we do not allow empty
+			 * column_name, schema_name & table_name options.
+			 */
+			if (obj_name_opt && obj_name_opt[0] == '\0')
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+						 errmsg("value for option \"%s\" must not be empty string",
+								def->defname)));
+		}
 	}
 
 	PG_RETURN_VOID();
diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql
index 3900522..477a58a 100644
--- a/contrib/postgres_fdw/sql/postgres_fdw.sql
+++ b/contrib/postgres_fdw/sql/postgres_fdw.sql
@@ -153,6 +153,24 @@ CREATE FOREIGN TABLE ft7 (
 	c3 text
 ) SERVER loopback3 OPTIONS (schema_name 'S 1', table_name 'T 4');
 
+CREATE FOREIGN TABLE ft8 (
+	c1 int OPTIONS (column_name '') NOT NULL,
+	c2 int NOT NULL,
+	c3 text
+) SERVER loopback3 OPTIONS (schema_name 'S 1', table_name 'T 4');
+
+CREATE FOREIGN TABLE ft8 (
+	c1 int NOT NULL,
+	c2 int NOT NULL,
+	c3 text
+) SERVER loopback3 OPTIONS (schema_name '', table_name 'T 4');
+
+CREATE FOREIGN TABLE ft8 (
+	c1 int NOT NULL,
+	c2 int NOT NULL,
+	c3 text
+) SERVER loopback3 OPTIONS (schema_name 'S 1', table_name '');
+
 -- ===================================================================
 -- tests for validator
 -- ===================================================================
@@ -213,10 +231,13 @@ ALTER USER MAPPING FOR public SERVER testserver1
 ALTER USER MAPPING FOR public SERVER testserver1
 	OPTIONS (ADD sslkey 'value', ADD sslcert 'value');
 
+ALTER FOREIGN TABLE ft1 OPTIONS (schema_name '', table_name 'T 1');
+ALTER FOREIGN TABLE ft1 OPTIONS (schema_name 'S 1', table_name '');
 ALTER FOREIGN TABLE ft1 OPTIONS (schema_name 'S 1', table_name 'T 1');
 ALTER FOREIGN TABLE ft2 OPTIONS (schema_name 'S 1', table_name 'T 1');
 ALTER FOREIGN TABLE ft1 ALTER COLUMN c1 OPTIONS (column_name 'C 1');
 ALTER FOREIGN TABLE ft2 ALTER COLUMN c1 OPTIONS (column_name 'C 1');
+ALTER FOREIGN TABLE ft2 ALTER COLUMN c2 OPTIONS (column_name '');
 \det+
 
 -- Test that alteration of server options causes reconnection
-- 
1.8.3.1

