77 *
88 *
99 * IDENTIFICATION
10- * $PostgreSQL: pgsql/src/backend/commands/foreigncmds.c,v 1.2 2008/12/2009:40:56 heikki Exp $
10+ * $PostgreSQL: pgsql/src/backend/commands/foreigncmds.c,v 1.3 2008/12/2015:51:28 tgl Exp $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
3535/*
3636 * Convert a DefElem list to the text array format that is used in
3737 * pg_foreign_data_wrapper, pg_foreign_server, and pg_user_mapping.
38+ * Returns the array in the form of a Datum, or PointerGetDatum(NULL)
39+ * if the list is empty.
3840 *
3941 * Note: The array is usually stored to database without further
4042 * processing, hence any validation should be done before this
@@ -45,13 +47,13 @@ optionListToArray(List *options)
4547{
4648ArrayBuildState * astate = NULL ;
4749ListCell * cell ;
48- text * t ;
4950
50- foreach (cell ,options )
51+ foreach (cell ,options )
5152{
5253DefElem * def = lfirst (cell );
53- const char * value = "" ;
54+ const char * value ;
5455Size len ;
56+ text * t ;
5557
5658value = defGetString (def );
5759len = VARHDRSZ + strlen (def -> defname )+ 1 + strlen (value );
@@ -76,6 +78,9 @@ optionListToArray(List *options)
7678 * The result is converted to array of text suitable for storing in
7779 * options.
7880 *
81+ * Returns the array in the form of a Datum, or PointerGetDatum(NULL)
82+ * if the list is empty.
83+ *
7984 * This is used by CREATE/ALTER of FOREIGN DATA WRAPPER/SERVER/USER
8085 * MAPPING. In the ALTER cases, oldOptions is the current text array
8186 * of options.
@@ -90,15 +95,15 @@ transformGenericOptions(Datum oldOptions,
9095List * resultOptions = untransformRelOptions (oldOptions );
9196ListCell * optcell ;
9297
93- foreach (optcell ,optionDefList )
98+ foreach (optcell ,optionDefList )
9499{
100+ OptionDefElem * od = lfirst (optcell );
95101ListCell * cell ;
96102ListCell * prev = NULL ;
97- OptionDefElem * od = lfirst (optcell );
98103
99104/*
100105 * Find the element in resultOptions. We need this for
101- * validation in all cases.
106+ * validation in all cases. Also identify the previous element.
102107 */
103108foreach (cell ,resultOptions )
104109{
@@ -190,7 +195,6 @@ AlterForeignDataWrapperOwner(const char *name, Oid newOwnerId)
190195HeapTuple tup ;
191196Relation rel ;
192197Oid fdwId ;
193-
194198Form_pg_foreign_data_wrapper form ;
195199
196200/* Must be a superuser to change a FDW owner */
@@ -345,7 +349,8 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
345349 */
346350rel = heap_open (ForeignDataWrapperRelationId ,RowExclusiveLock );
347351
348- MemSet (nulls , false,Natts_pg_foreign_data_wrapper );
352+ memset (values ,0 ,sizeof (values ));
353+ memset (nulls , false,sizeof (nulls ));
349354
350355values [Anum_pg_foreign_data_wrapper_fdwname - 1 ]=
351356DirectFunctionCall1 (namein ,CStringGetDatum (stmt -> fdwname ));
@@ -359,7 +364,8 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
359364 */
360365fdwlib = GetForeignDataWrapperLibrary (stmt -> library );
361366
362- fdwoptions = transformGenericOptions (0 ,stmt -> options ,FdwOpt ,NULL ,
367+ fdwoptions = transformGenericOptions (PointerGetDatum (NULL ),stmt -> options ,
368+ FdwOpt ,NULL ,
363369fdwlib -> validateOptionList );
364370
365371if (PointerIsValid (DatumGetPointer (fdwoptions )))
@@ -447,6 +453,7 @@ AlterForeignDataWrapper(AlterFdwStmt *stmt)
447453tp ,
448454Anum_pg_foreign_data_wrapper_fdwlibrary ,
449455& isnull );
456+ Assert (!isnull );
450457fdwlib = GetForeignDataWrapperLibrary (TextDatumGetCString (datum ));
451458}
452459
@@ -460,13 +467,15 @@ AlterForeignDataWrapper(AlterFdwStmt *stmt)
460467tp ,
461468Anum_pg_foreign_data_wrapper_fdwoptions ,
462469& isnull );
470+ if (isnull )
471+ datum = PointerGetDatum (NULL );
463472
464473/* Transform the options */
465474datum = transformGenericOptions (datum ,stmt -> options ,FdwOpt ,
466475NULL ,fdwlib -> validateOptionList );
467476
468477if (PointerIsValid (DatumGetPointer (datum )))
469- repl_val [Anum_pg_foreign_data_wrapper_fdwoptions - 1 ]= ObjectIdGetDatum ( datum ) ;
478+ repl_val [Anum_pg_foreign_data_wrapper_fdwoptions - 1 ]= datum ;
470479else
471480repl_null [Anum_pg_foreign_data_wrapper_fdwoptions - 1 ]= true;
472481
@@ -603,7 +612,8 @@ CreateForeignServer(CreateForeignServerStmt *stmt)
603612 */
604613rel = heap_open (ForeignServerRelationId ,RowExclusiveLock );
605614
606- MemSet (nulls , false,Natts_pg_foreign_server );
615+ memset (values ,0 ,sizeof (values ));
616+ memset (nulls , false,sizeof (nulls ));
607617
608618values [Anum_pg_foreign_server_srvname - 1 ]=
609619DirectFunctionCall1 (namein ,CStringGetDatum (stmt -> servername ));
@@ -628,7 +638,8 @@ CreateForeignServer(CreateForeignServerStmt *stmt)
628638nulls [Anum_pg_foreign_server_srvacl - 1 ]= true;
629639
630640/* Add server options */
631- srvoptions = transformGenericOptions (0 ,stmt -> options ,ServerOpt ,fdw ,
641+ srvoptions = transformGenericOptions (PointerGetDatum (NULL ),stmt -> options ,
642+ ServerOpt ,fdw ,
632643fdw -> lib -> validateOptionList );
633644
634645if (PointerIsValid (DatumGetPointer (srvoptions )))
@@ -722,6 +733,8 @@ AlterForeignServer(AlterForeignServerStmt *stmt)
722733tp ,
723734Anum_pg_foreign_server_srvoptions ,
724735& isnull );
736+ if (isnull )
737+ datum = PointerGetDatum (NULL );
725738
726739/* Prepare the options array */
727740datum = transformGenericOptions (datum ,stmt -> options ,ServerOpt ,
@@ -868,13 +881,15 @@ CreateUserMapping(CreateUserMappingStmt *stmt)
868881 */
869882rel = heap_open (UserMappingRelationId ,RowExclusiveLock );
870883
871- MemSet (nulls , false,Natts_pg_user_mapping );
884+ memset (values ,0 ,sizeof (values ));
885+ memset (nulls , false,sizeof (nulls ));
872886
873887values [Anum_pg_user_mapping_umuser - 1 ]= ObjectIdGetDatum (useId );
874888values [Anum_pg_user_mapping_umserver - 1 ]= ObjectIdGetDatum (srv -> serverid );
875889
876890/* Add user options */
877- useoptions = transformGenericOptions (0 ,stmt -> options ,UserMappingOpt ,
891+ useoptions = transformGenericOptions (PointerGetDatum (NULL ),stmt -> options ,
892+ UserMappingOpt ,
878893fdw ,fdw -> lib -> validateOptionList );
879894
880895if (PointerIsValid (DatumGetPointer (useoptions )))
@@ -931,12 +946,10 @@ AlterUserMapping(AlterUserMappingStmt *stmt)
931946ObjectIdGetDatum (srv -> serverid ),
9329470 ,0 );
933948if (!OidIsValid (umId ))
934- {
935949ereport (ERROR ,
936950(errcode (ERRCODE_UNDEFINED_OBJECT ),
937951errmsg ("user mapping \"%s\" does not exist for the server" ,
938952MappingUserName (useId ))));
939- }
940953
941954/*
942955 * Must be owner of the server to alter user mapping.
@@ -972,6 +985,8 @@ AlterUserMapping(AlterUserMappingStmt *stmt)
972985tp ,
973986Anum_pg_user_mapping_umoptions ,
974987& isnull );
988+ if (isnull )
989+ datum = PointerGetDatum (NULL );
975990
976991/* Prepare the options array */
977992datum = transformGenericOptions (datum ,stmt -> options ,UserMappingOpt ,