I wrote:
> The validator is run for the generic options specified to CREATE/ALTER FDW,
> SERVER and USER MAPPING (+ possible future SQL/MED objects). In this case the
> catalog is always known. Also we can assume that the catalog is known, if a 
> user
> runs the validator directly. So yes, AFAICS there is no case for the "or 
> zero".
> 

Updated patch attached. This now also removes the "or zero" note from
the documentation and modifies postgresql_fdw_validator() to assume that
a valid catalog oid is always passed.

regards,
Martin

*** a/doc/src/sgml/ref/create_foreign_data_wrapper.sgml
--- b/doc/src/sgml/ref/create_foreign_data_wrapper.sgml
***************
*** 74,83 **** CREATE FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable>
        take two arguments: one of type <type>text[]</type>, which will
        contain the array of options as stored in the system catalogs,
        and one of type <type>oid</type>, which will be the OID of the
!       system catalog containing the options, or zero if the context is
!       not known.  The return type is ignored; the function should
!       indicate invalid options using
!       the <function>ereport()</function> function.
       </para>
      </listitem>
     </varlistentry>
--- 74,82 ----
        take two arguments: one of type <type>text[]</type>, which will
        contain the array of options as stored in the system catalogs,
        and one of type <type>oid</type>, which will be the OID of the
!       system catalog containing the options. The return type is ignored;
!       the function should indicate invalid options using the
!       <function>ereport()</function> function.
       </para>
      </listitem>
     </varlistentry>
*** a/src/backend/commands/foreigncmds.c
--- b/src/backend/commands/foreigncmds.c
***************
*** 88,94 **** optionListToArray(List *options)
   * This is used by CREATE/ALTER of FOREIGN DATA WRAPPER/SERVER/USER MAPPING.
   */
  static Datum
! transformGenericOptions(Datum oldOptions,
  						List *options,
  						Oid fdwvalidator)
  {
--- 88,95 ----
   * This is used by CREATE/ALTER of FOREIGN DATA WRAPPER/SERVER/USER MAPPING.
   */
  static Datum
! transformGenericOptions(Oid catalogId,
! 						Datum oldOptions,
  						List *options,
  						Oid fdwvalidator)
  {
***************
*** 162,168 **** transformGenericOptions(Datum oldOptions,
  	result = optionListToArray(resultOptions);
  
  	if (fdwvalidator)
! 		OidFunctionCall2(fdwvalidator, result, (Datum) 0);
  
  	return result;
  }
--- 163,169 ----
  	result = optionListToArray(resultOptions);
  
  	if (fdwvalidator)
! 		OidFunctionCall2(fdwvalidator, result, ObjectIdGetDatum(catalogId));
  
  	return result;
  }
***************
*** 384,390 **** CreateForeignDataWrapper(CreateFdwStmt *stmt)
  
  	nulls[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true;
  
! 	fdwoptions = transformGenericOptions(PointerGetDatum(NULL), stmt->options,
  										 fdwvalidator);
  
  	if (PointerIsValid(DatumGetPointer(fdwoptions)))
--- 385,393 ----
  
  	nulls[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true;
  
! 	fdwoptions = transformGenericOptions(ForeignDataWrapperRelationId,
! 										 PointerGetDatum(NULL),
! 										 stmt->options,
  										 fdwvalidator);
  
  	if (PointerIsValid(DatumGetPointer(fdwoptions)))
***************
*** 501,507 **** AlterForeignDataWrapper(AlterFdwStmt *stmt)
  			datum = PointerGetDatum(NULL);
  
  		/* Transform the options */
! 		datum = transformGenericOptions(datum, stmt->options, fdwvalidator);
  
  		if (PointerIsValid(DatumGetPointer(datum)))
  			repl_val[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = datum;
--- 504,513 ----
  			datum = PointerGetDatum(NULL);
  
  		/* Transform the options */
! 		datum = transformGenericOptions(ForeignDataWrapperRelationId,
! 										datum,
! 										stmt->options,
! 										fdwvalidator);
  
  		if (PointerIsValid(DatumGetPointer(datum)))
  			repl_val[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = datum;
***************
*** 667,673 **** CreateForeignServer(CreateForeignServerStmt *stmt)
  	nulls[Anum_pg_foreign_server_srvacl - 1] = true;
  
  	/* Add server options */
! 	srvoptions = transformGenericOptions(PointerGetDatum(NULL), stmt->options,
  										 fdw->fdwvalidator);
  
  	if (PointerIsValid(DatumGetPointer(srvoptions)))
--- 673,681 ----
  	nulls[Anum_pg_foreign_server_srvacl - 1] = true;
  
  	/* Add server options */
! 	srvoptions = transformGenericOptions(ForeignServerRelationId,
! 										 PointerGetDatum(NULL),
! 										 stmt->options,
  										 fdw->fdwvalidator);
  
  	if (PointerIsValid(DatumGetPointer(srvoptions)))
***************
*** 765,771 **** AlterForeignServer(AlterForeignServerStmt *stmt)
  			datum = PointerGetDatum(NULL);
  
  		/* Prepare the options array */
! 		datum = transformGenericOptions(datum, stmt->options,
  										fdw->fdwvalidator);
  
  		if (PointerIsValid(DatumGetPointer(datum)))
--- 773,781 ----
  			datum = PointerGetDatum(NULL);
  
  		/* Prepare the options array */
! 		datum = transformGenericOptions(ForeignServerRelationId,
! 										datum,
! 										stmt->options,
  										fdw->fdwvalidator);
  
  		if (PointerIsValid(DatumGetPointer(datum)))
***************
*** 936,942 **** CreateUserMapping(CreateUserMappingStmt *stmt)
  	values[Anum_pg_user_mapping_umserver - 1] = ObjectIdGetDatum(srv->serverid);
  
  	/* Add user options */
! 	useoptions = transformGenericOptions(PointerGetDatum(NULL), stmt->options,
  										 fdw->fdwvalidator);
  
  	if (PointerIsValid(DatumGetPointer(useoptions)))
--- 946,954 ----
  	values[Anum_pg_user_mapping_umserver - 1] = ObjectIdGetDatum(srv->serverid);
  
  	/* Add user options */
! 	useoptions = transformGenericOptions(UserMappingRelationId,
! 										 PointerGetDatum(NULL),
! 										 stmt->options,
  										 fdw->fdwvalidator);
  
  	if (PointerIsValid(DatumGetPointer(useoptions)))
***************
*** 1031,1037 **** AlterUserMapping(AlterUserMappingStmt *stmt)
  			datum = PointerGetDatum(NULL);
  
  		/* Prepare the options array */
! 		datum = transformGenericOptions(datum, stmt->options,
  										fdw->fdwvalidator);
  
  		if (PointerIsValid(DatumGetPointer(datum)))
--- 1043,1051 ----
  			datum = PointerGetDatum(NULL);
  
  		/* Prepare the options array */
! 		datum = transformGenericOptions(UserMappingRelationId,
! 										datum,
! 										stmt->options,
  										fdw->fdwvalidator);
  
  		if (PointerIsValid(DatumGetPointer(datum)))
*** a/src/backend/foreign/foreign.c
--- b/src/backend/foreign/foreign.c
***************
*** 372,378 **** is_conninfo_option(const char *option, Oid context)
  	struct ConnectionOption *opt;
  
  	for (opt = libpq_conninfo_options; opt->optname; opt++)
! 		if ((context == opt->optcontext || context == InvalidOid) && strcmp(opt->optname, option) == 0)
  			return true;
  	return false;
  }
--- 372,378 ----
  	struct ConnectionOption *opt;
  
  	for (opt = libpq_conninfo_options; opt->optname; opt++)
! 		if (context == opt->optcontext && strcmp(opt->optname, option) == 0)
  			return true;
  	return false;
  }
***************
*** 409,415 **** postgresql_fdw_validator(PG_FUNCTION_ARGS)
  			 */
  			initStringInfo(&buf);
  			for (opt = libpq_conninfo_options; opt->optname; opt++)
! 				if (catalog == InvalidOid || catalog == opt->optcontext)
  					appendStringInfo(&buf, "%s%s", (buf.len > 0) ? ", " : "",
  									 opt->optname);
  
--- 409,415 ----
  			 */
  			initStringInfo(&buf);
  			for (opt = libpq_conninfo_options; opt->optname; opt++)
! 				if (catalog == opt->optcontext)
  					appendStringInfo(&buf, "%s%s", (buf.len > 0) ? ", " : "",
  									 opt->optname);
  
*** a/src/test/regress/expected/foreign_data.out
--- b/src/test/regress/expected/foreign_data.out
***************
*** 284,290 **** CREATE SERVER s6 VERSION '16.0' FOREIGN DATA WRAPPER foo OPTIONS (host 'a', dbna
  CREATE SERVER s7 TYPE 'oracle' VERSION '17.0' FOREIGN DATA WRAPPER foo OPTIONS (host 'a', dbname 'b');
  CREATE SERVER s8 FOREIGN DATA WRAPPER postgresql OPTIONS (foo '1'); -- ERROR
  ERROR:  invalid option "foo"
! HINT:  Valid options in this context are: authtype, service, user, password, connect_timeout, dbname, host, hostaddr, port, tty, options, requiressl, sslmode, gsslib
  CREATE SERVER s8 FOREIGN DATA WRAPPER postgresql OPTIONS (host 'localhost', dbname 's8db');
  \des+
                                                  List of foreign servers
--- 284,290 ----
  CREATE SERVER s7 TYPE 'oracle' VERSION '17.0' FOREIGN DATA WRAPPER foo OPTIONS (host 'a', dbname 'b');
  CREATE SERVER s8 FOREIGN DATA WRAPPER postgresql OPTIONS (foo '1'); -- ERROR
  ERROR:  invalid option "foo"
! HINT:  Valid options in this context are: authtype, service, connect_timeout, dbname, host, hostaddr, port, tty, options, requiressl, sslmode, gsslib
  CREATE SERVER s8 FOREIGN DATA WRAPPER postgresql OPTIONS (host 'localhost', dbname 's8db');
  \des+
                                                  List of foreign servers
***************
*** 395,401 **** ERROR:  permission denied for foreign-data wrapper foo
  RESET ROLE;
  ALTER SERVER s8 OPTIONS (foo '1');                          -- ERROR option validation
  ERROR:  invalid option "foo"
! HINT:  Valid options in this context are: authtype, service, user, password, connect_timeout, dbname, host, hostaddr, port, tty, options, requiressl, sslmode, gsslib
  ALTER SERVER s8 OPTIONS (connect_timeout '30', SET dbname 'db1', DROP host);
  SET ROLE regress_test_role;
  ALTER SERVER s1 OWNER TO regress_test_indirect;             -- ERROR
--- 395,401 ----
  RESET ROLE;
  ALTER SERVER s8 OPTIONS (foo '1');                          -- ERROR option validation
  ERROR:  invalid option "foo"
! HINT:  Valid options in this context are: authtype, service, connect_timeout, dbname, host, hostaddr, port, tty, options, requiressl, sslmode, gsslib
  ALTER SERVER s8 OPTIONS (connect_timeout '30', SET dbname 'db1', DROP host);
  SET ROLE regress_test_role;
  ALTER SERVER s1 OWNER TO regress_test_indirect;             -- ERROR
***************
*** 534,540 **** ERROR:  user mapping "foreign_data_user" already exists for server s4
  CREATE USER MAPPING FOR public SERVER s4 OPTIONS (mapping 'is public');
  CREATE USER MAPPING FOR user SERVER s8 OPTIONS (username 'test', password 'secret');    -- ERROR
  ERROR:  invalid option "username"
! HINT:  Valid options in this context are: authtype, service, user, password, connect_timeout, dbname, host, hostaddr, port, tty, options, requiressl, sslmode, gsslib
  CREATE USER MAPPING FOR user SERVER s8 OPTIONS (user 'test', password 'secret');
  ALTER SERVER s5 OWNER TO regress_test_role;
  ALTER SERVER s6 OWNER TO regress_test_indirect;
--- 534,540 ----
  CREATE USER MAPPING FOR public SERVER s4 OPTIONS (mapping 'is public');
  CREATE USER MAPPING FOR user SERVER s8 OPTIONS (username 'test', password 'secret');    -- ERROR
  ERROR:  invalid option "username"
! HINT:  Valid options in this context are: user, password
  CREATE USER MAPPING FOR user SERVER s8 OPTIONS (user 'test', password 'secret');
  ALTER SERVER s5 OWNER TO regress_test_role;
  ALTER SERVER s6 OWNER TO regress_test_indirect;
***************
*** 573,579 **** ALTER USER MAPPING FOR public SERVER s5 OPTIONS (gotcha 'true');            -- E
  ERROR:  user mapping "public" does not exist for the server
  ALTER USER MAPPING FOR current_user SERVER s8 OPTIONS (username 'test');    -- ERROR
  ERROR:  invalid option "username"
! HINT:  Valid options in this context are: authtype, service, user, password, connect_timeout, dbname, host, hostaddr, port, tty, options, requiressl, sslmode, gsslib
  ALTER USER MAPPING FOR current_user SERVER s8 OPTIONS (DROP user, SET password 'public');
  SET ROLE regress_test_role;
  ALTER USER MAPPING FOR current_user SERVER s5 OPTIONS (ADD modified '1');
--- 573,579 ----
  ERROR:  user mapping "public" does not exist for the server
  ALTER USER MAPPING FOR current_user SERVER s8 OPTIONS (username 'test');    -- ERROR
  ERROR:  invalid option "username"
! HINT:  Valid options in this context are: user, password
  ALTER USER MAPPING FOR current_user SERVER s8 OPTIONS (DROP user, SET password 'public');
  SET ROLE regress_test_role;
  ALTER USER MAPPING FOR current_user SERVER s5 OPTIONS (ADD modified '1');
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to