@@ -2050,6 +2050,7 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
20502050HeapTuple extTup ;
20512051Datum arrayDatum ;
20522052Datum elementDatum ;
2053+ int arrayLength ;
20532054int arrayIndex ;
20542055bool isnull ;
20552056Datum repl_val [Natts_pg_extension ];
@@ -2069,8 +2070,8 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
20692070
20702071/*
20712072 * Check that the table exists and is a member of the extension being
2072- * created. This ensures that we don't need to registera dependency to
2073- * protect the extconfig entry.
2073+ * created. This ensures that we don't need to registeran additional
2074+ *dependency to protect the extconfig entry.
20742075 */
20752076tablename = get_rel_name (tableoid );
20762077if (tablename == NULL )
@@ -2087,6 +2088,9 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
20872088/*
20882089 * Add the table OID and WHERE condition to the extension's extconfig and
20892090 * extcondition arrays.
2091+ *
2092+ * If the table is already in extconfig, treat this as an update of the
2093+ * WHERE condition.
20902094 */
20912095
20922096/* Find the pg_extension tuple */
@@ -2117,18 +2121,41 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
21172121RelationGetDescr (extRel ),& isnull );
21182122if (isnull )
21192123{
2124+ /* Previously empty extconfig, so build 1-element array */
2125+ arrayLength = 0 ;
2126+ arrayIndex = 1 ;
2127+
21202128a = construct_array (& elementDatum ,1 ,
21212129OIDOID ,
21222130sizeof (Oid ), true,'i' );
21232131}
21242132else
21252133{
2134+ /* Modify or extend existing extconfig array */
2135+ Oid * arrayData ;
2136+ int i ;
2137+
21262138a = DatumGetArrayTypeP (arrayDatum );
2127- Assert (ARR_ELEMTYPE (a )== OIDOID );
2128- Assert (ARR_NDIM (a )== 1 );
2129- Assert (ARR_LBOUND (a )[0 ]== 1 );
21302139
2131- arrayIndex = ARR_DIMS (a )[0 ]+ 1 ;/* add after end */
2140+ arrayLength = ARR_DIMS (a )[0 ];
2141+ if (ARR_NDIM (a )!= 1 ||
2142+ ARR_LBOUND (a )[0 ]!= 1 ||
2143+ arrayLength < 0 ||
2144+ ARR_HASNULL (a )||
2145+ ARR_ELEMTYPE (a )!= OIDOID )
2146+ elog (ERROR ,"extconfig is not a 1-D Oid array" );
2147+ arrayData = (Oid * )ARR_DATA_PTR (a );
2148+
2149+ arrayIndex = arrayLength + 1 ;/* set up to add after end */
2150+
2151+ for (i = 0 ;i < arrayLength ;i ++ )
2152+ {
2153+ if (arrayData [i ]== tableoid )
2154+ {
2155+ arrayIndex = i + 1 ;/* replace this element instead */
2156+ break ;
2157+ }
2158+ }
21322159
21332160a = array_set (a ,1 ,& arrayIndex ,
21342161elementDatum ,
@@ -2148,19 +2175,26 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
21482175RelationGetDescr (extRel ),& isnull );
21492176if (isnull )
21502177{
2178+ if (arrayLength != 0 )
2179+ elog (ERROR ,"extconfig and extcondition arrays do not match" );
2180+
21512181a = construct_array (& elementDatum ,1 ,
21522182TEXTOID ,
21532183-1 , false,'i' );
21542184}
21552185else
21562186{
21572187a = DatumGetArrayTypeP (arrayDatum );
2158- Assert (ARR_ELEMTYPE (a )== TEXTOID );
2159- Assert (ARR_NDIM (a )== 1 );
2160- Assert (ARR_LBOUND (a )[0 ]== 1 );
21612188
2162- arrayIndex = ARR_DIMS (a )[0 ]+ 1 ;/* add after end */
2189+ if (ARR_NDIM (a )!= 1 ||
2190+ ARR_LBOUND (a )[0 ]!= 1 ||
2191+ ARR_HASNULL (a )||
2192+ ARR_ELEMTYPE (a )!= TEXTOID )
2193+ elog (ERROR ,"extcondition is not a 1-D text array" );
2194+ if (ARR_DIMS (a )[0 ]!= arrayLength )
2195+ elog (ERROR ,"extconfig and extcondition arrays do not match" );
21632196
2197+ /* Add or replace at same index as in extconfig */
21642198a = array_set (a ,1 ,& arrayIndex ,
21652199elementDatum ,
21662200 false,
@@ -2185,6 +2219,182 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
21852219PG_RETURN_VOID ();
21862220}
21872221
2222+ /*
2223+ * extension_config_remove
2224+ *
2225+ * Remove the specified table OID from extension's extconfig, if present.
2226+ * This is not currently exposed as a function, but it could be;
2227+ * for now, we just invoke it from ALTER EXTENSION DROP.
2228+ */
2229+ static void
2230+ extension_config_remove (Oid extensionoid ,Oid tableoid )
2231+ {
2232+ Relation extRel ;
2233+ ScanKeyData key [1 ];
2234+ SysScanDesc extScan ;
2235+ HeapTuple extTup ;
2236+ Datum arrayDatum ;
2237+ int arrayLength ;
2238+ int arrayIndex ;
2239+ bool isnull ;
2240+ Datum repl_val [Natts_pg_extension ];
2241+ bool repl_null [Natts_pg_extension ];
2242+ bool repl_repl [Natts_pg_extension ];
2243+ ArrayType * a ;
2244+
2245+ /* Find the pg_extension tuple */
2246+ extRel = heap_open (ExtensionRelationId ,RowExclusiveLock );
2247+
2248+ ScanKeyInit (& key [0 ],
2249+ ObjectIdAttributeNumber ,
2250+ BTEqualStrategyNumber ,F_OIDEQ ,
2251+ ObjectIdGetDatum (extensionoid ));
2252+
2253+ extScan = systable_beginscan (extRel ,ExtensionOidIndexId , true,
2254+ SnapshotNow ,1 ,key );
2255+
2256+ extTup = systable_getnext (extScan );
2257+
2258+ if (!HeapTupleIsValid (extTup ))/* should not happen */
2259+ elog (ERROR ,"extension with oid %u does not exist" ,
2260+ extensionoid );
2261+
2262+ /* Search extconfig for the tableoid */
2263+ arrayDatum = heap_getattr (extTup ,Anum_pg_extension_extconfig ,
2264+ RelationGetDescr (extRel ),& isnull );
2265+ if (isnull )
2266+ {
2267+ /* nothing to do */
2268+ a = NULL ;
2269+ arrayLength = 0 ;
2270+ arrayIndex = -1 ;
2271+ }
2272+ else
2273+ {
2274+ Oid * arrayData ;
2275+ int i ;
2276+
2277+ a = DatumGetArrayTypeP (arrayDatum );
2278+
2279+ arrayLength = ARR_DIMS (a )[0 ];
2280+ if (ARR_NDIM (a )!= 1 ||
2281+ ARR_LBOUND (a )[0 ]!= 1 ||
2282+ arrayLength < 0 ||
2283+ ARR_HASNULL (a )||
2284+ ARR_ELEMTYPE (a )!= OIDOID )
2285+ elog (ERROR ,"extconfig is not a 1-D Oid array" );
2286+ arrayData = (Oid * )ARR_DATA_PTR (a );
2287+
2288+ arrayIndex = -1 ;/* flag for no deletion needed */
2289+
2290+ for (i = 0 ;i < arrayLength ;i ++ )
2291+ {
2292+ if (arrayData [i ]== tableoid )
2293+ {
2294+ arrayIndex = i ;/* index to remove */
2295+ break ;
2296+ }
2297+ }
2298+ }
2299+
2300+ /* If tableoid is not in extconfig, nothing to do */
2301+ if (arrayIndex < 0 )
2302+ {
2303+ systable_endscan (extScan );
2304+ heap_close (extRel ,RowExclusiveLock );
2305+ return ;
2306+ }
2307+
2308+ /* Modify or delete the extconfig value */
2309+ memset (repl_val ,0 ,sizeof (repl_val ));
2310+ memset (repl_null , false,sizeof (repl_null ));
2311+ memset (repl_repl , false,sizeof (repl_repl ));
2312+
2313+ if (arrayLength <=1 )
2314+ {
2315+ /* removing only element, just set array to null */
2316+ repl_null [Anum_pg_extension_extconfig - 1 ]= true;
2317+ }
2318+ else
2319+ {
2320+ /* squeeze out the target element */
2321+ Datum * dvalues ;
2322+ bool * dnulls ;
2323+ int nelems ;
2324+ int i ;
2325+
2326+ deconstruct_array (a ,OIDOID ,sizeof (Oid ), true,'i' ,
2327+ & dvalues ,& dnulls ,& nelems );
2328+
2329+ /* We already checked there are no nulls, so ignore dnulls */
2330+ for (i = arrayIndex ;i < arrayLength - 1 ;i ++ )
2331+ dvalues [i ]= dvalues [i + 1 ];
2332+
2333+ a = construct_array (dvalues ,arrayLength - 1 ,
2334+ OIDOID ,sizeof (Oid ), true,'i' );
2335+
2336+ repl_val [Anum_pg_extension_extconfig - 1 ]= PointerGetDatum (a );
2337+ }
2338+ repl_repl [Anum_pg_extension_extconfig - 1 ]= true;
2339+
2340+ /* Modify or delete the extcondition value */
2341+ arrayDatum = heap_getattr (extTup ,Anum_pg_extension_extcondition ,
2342+ RelationGetDescr (extRel ),& isnull );
2343+ if (isnull )
2344+ {
2345+ elog (ERROR ,"extconfig and extcondition arrays do not match" );
2346+ }
2347+ else
2348+ {
2349+ a = DatumGetArrayTypeP (arrayDatum );
2350+
2351+ if (ARR_NDIM (a )!= 1 ||
2352+ ARR_LBOUND (a )[0 ]!= 1 ||
2353+ ARR_HASNULL (a )||
2354+ ARR_ELEMTYPE (a )!= TEXTOID )
2355+ elog (ERROR ,"extcondition is not a 1-D text array" );
2356+ if (ARR_DIMS (a )[0 ]!= arrayLength )
2357+ elog (ERROR ,"extconfig and extcondition arrays do not match" );
2358+ }
2359+
2360+ if (arrayLength <=1 )
2361+ {
2362+ /* removing only element, just set array to null */
2363+ repl_null [Anum_pg_extension_extcondition - 1 ]= true;
2364+ }
2365+ else
2366+ {
2367+ /* squeeze out the target element */
2368+ Datum * dvalues ;
2369+ bool * dnulls ;
2370+ int nelems ;
2371+ int i ;
2372+
2373+ deconstruct_array (a ,TEXTOID ,-1 , false,'i' ,
2374+ & dvalues ,& dnulls ,& nelems );
2375+
2376+ /* We already checked there are no nulls, so ignore dnulls */
2377+ for (i = arrayIndex ;i < arrayLength - 1 ;i ++ )
2378+ dvalues [i ]= dvalues [i + 1 ];
2379+
2380+ a = construct_array (dvalues ,arrayLength - 1 ,
2381+ TEXTOID ,-1 , false,'i' );
2382+
2383+ repl_val [Anum_pg_extension_extcondition - 1 ]= PointerGetDatum (a );
2384+ }
2385+ repl_repl [Anum_pg_extension_extcondition - 1 ]= true;
2386+
2387+ extTup = heap_modify_tuple (extTup ,RelationGetDescr (extRel ),
2388+ repl_val ,repl_null ,repl_repl );
2389+
2390+ simple_heap_update (extRel ,& extTup -> t_self ,extTup );
2391+ CatalogUpdateIndexes (extRel ,extTup );
2392+
2393+ systable_endscan (extScan );
2394+
2395+ heap_close (extRel ,RowExclusiveLock );
2396+ }
2397+
21882398/*
21892399 * Execute ALTER EXTENSION SET SCHEMA
21902400 */
@@ -2745,6 +2955,13 @@ ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt)
27452955ExtensionRelationId ,
27462956DEPENDENCY_EXTENSION )!= 1 )
27472957elog (ERROR ,"unexpected number of extension dependency records" );
2958+
2959+ /*
2960+ * If it's a relation, it might have an entry in the extension's
2961+ * extconfig array, which we must remove.
2962+ */
2963+ if (object .classId == RelationRelationId )
2964+ extension_config_remove (extension .objectId ,object .objectId );
27482965}
27492966
27502967/*