@@ -2047,6 +2047,7 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
20472047HeapTuple extTup ;
20482048Datum arrayDatum ;
20492049Datum elementDatum ;
2050+ int arrayLength ;
20502051int arrayIndex ;
20512052bool isnull ;
20522053Datum repl_val [Natts_pg_extension ];
@@ -2066,8 +2067,8 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
20662067
20672068/*
20682069 * Check that the table exists and is a member of the extension being
2069- * created. This ensures that we don't need to registera dependency to
2070- * protect the extconfig entry.
2070+ * created. This ensures that we don't need to registeran additional
2071+ *dependency to protect the extconfig entry.
20712072 */
20722073tablename = get_rel_name (tableoid );
20732074if (tablename == NULL )
@@ -2084,6 +2085,9 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
20842085/*
20852086 * Add the table OID and WHERE condition to the extension's extconfig and
20862087 * extcondition arrays.
2088+ *
2089+ * If the table is already in extconfig, treat this as an update of the
2090+ * WHERE condition.
20872091 */
20882092
20892093/* Find the pg_extension tuple */
@@ -2114,18 +2118,41 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
21142118RelationGetDescr (extRel ),& isnull );
21152119if (isnull )
21162120{
2121+ /* Previously empty extconfig, so build 1-element array */
2122+ arrayLength = 0 ;
2123+ arrayIndex = 1 ;
2124+
21172125a = construct_array (& elementDatum ,1 ,
21182126OIDOID ,
21192127sizeof (Oid ), true,'i' );
21202128}
21212129else
21222130{
2131+ /* Modify or extend existing extconfig array */
2132+ Oid * arrayData ;
2133+ int i ;
2134+
21232135a = DatumGetArrayTypeP (arrayDatum );
2124- Assert (ARR_ELEMTYPE (a )== OIDOID );
2125- Assert (ARR_NDIM (a )== 1 );
2126- Assert (ARR_LBOUND (a )[0 ]== 1 );
21272136
2128- arrayIndex = ARR_DIMS (a )[0 ]+ 1 ;/* add after end */
2137+ arrayLength = ARR_DIMS (a )[0 ];
2138+ if (ARR_NDIM (a )!= 1 ||
2139+ ARR_LBOUND (a )[0 ]!= 1 ||
2140+ arrayLength < 0 ||
2141+ ARR_HASNULL (a )||
2142+ ARR_ELEMTYPE (a )!= OIDOID )
2143+ elog (ERROR ,"extconfig is not a 1-D Oid array" );
2144+ arrayData = (Oid * )ARR_DATA_PTR (a );
2145+
2146+ arrayIndex = arrayLength + 1 ;/* set up to add after end */
2147+
2148+ for (i = 0 ;i < arrayLength ;i ++ )
2149+ {
2150+ if (arrayData [i ]== tableoid )
2151+ {
2152+ arrayIndex = i + 1 ;/* replace this element instead */
2153+ break ;
2154+ }
2155+ }
21292156
21302157a = array_set (a ,1 ,& arrayIndex ,
21312158elementDatum ,
@@ -2145,19 +2172,26 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
21452172RelationGetDescr (extRel ),& isnull );
21462173if (isnull )
21472174{
2175+ if (arrayLength != 0 )
2176+ elog (ERROR ,"extconfig and extcondition arrays do not match" );
2177+
21482178a = construct_array (& elementDatum ,1 ,
21492179TEXTOID ,
21502180-1 , false,'i' );
21512181}
21522182else
21532183{
21542184a = DatumGetArrayTypeP (arrayDatum );
2155- Assert (ARR_ELEMTYPE (a )== TEXTOID );
2156- Assert (ARR_NDIM (a )== 1 );
2157- Assert (ARR_LBOUND (a )[0 ]== 1 );
21582185
2159- arrayIndex = ARR_DIMS (a )[0 ]+ 1 ;/* add after end */
2186+ if (ARR_NDIM (a )!= 1 ||
2187+ ARR_LBOUND (a )[0 ]!= 1 ||
2188+ ARR_HASNULL (a )||
2189+ ARR_ELEMTYPE (a )!= TEXTOID )
2190+ elog (ERROR ,"extcondition is not a 1-D text array" );
2191+ if (ARR_DIMS (a )[0 ]!= arrayLength )
2192+ elog (ERROR ,"extconfig and extcondition arrays do not match" );
21602193
2194+ /* Add or replace at same index as in extconfig */
21612195a = array_set (a ,1 ,& arrayIndex ,
21622196elementDatum ,
21632197 false,
@@ -2182,6 +2216,182 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
21822216PG_RETURN_VOID ();
21832217}
21842218
2219+ /*
2220+ * extension_config_remove
2221+ *
2222+ * Remove the specified table OID from extension's extconfig, if present.
2223+ * This is not currently exposed as a function, but it could be;
2224+ * for now, we just invoke it from ALTER EXTENSION DROP.
2225+ */
2226+ static void
2227+ extension_config_remove (Oid extensionoid ,Oid tableoid )
2228+ {
2229+ Relation extRel ;
2230+ ScanKeyData key [1 ];
2231+ SysScanDesc extScan ;
2232+ HeapTuple extTup ;
2233+ Datum arrayDatum ;
2234+ int arrayLength ;
2235+ int arrayIndex ;
2236+ bool isnull ;
2237+ Datum repl_val [Natts_pg_extension ];
2238+ bool repl_null [Natts_pg_extension ];
2239+ bool repl_repl [Natts_pg_extension ];
2240+ ArrayType * a ;
2241+
2242+ /* Find the pg_extension tuple */
2243+ extRel = heap_open (ExtensionRelationId ,RowExclusiveLock );
2244+
2245+ ScanKeyInit (& key [0 ],
2246+ ObjectIdAttributeNumber ,
2247+ BTEqualStrategyNumber ,F_OIDEQ ,
2248+ ObjectIdGetDatum (extensionoid ));
2249+
2250+ extScan = systable_beginscan (extRel ,ExtensionOidIndexId , true,
2251+ SnapshotNow ,1 ,key );
2252+
2253+ extTup = systable_getnext (extScan );
2254+
2255+ if (!HeapTupleIsValid (extTup ))/* should not happen */
2256+ elog (ERROR ,"extension with oid %u does not exist" ,
2257+ extensionoid );
2258+
2259+ /* Search extconfig for the tableoid */
2260+ arrayDatum = heap_getattr (extTup ,Anum_pg_extension_extconfig ,
2261+ RelationGetDescr (extRel ),& isnull );
2262+ if (isnull )
2263+ {
2264+ /* nothing to do */
2265+ a = NULL ;
2266+ arrayLength = 0 ;
2267+ arrayIndex = -1 ;
2268+ }
2269+ else
2270+ {
2271+ Oid * arrayData ;
2272+ int i ;
2273+
2274+ a = DatumGetArrayTypeP (arrayDatum );
2275+
2276+ arrayLength = ARR_DIMS (a )[0 ];
2277+ if (ARR_NDIM (a )!= 1 ||
2278+ ARR_LBOUND (a )[0 ]!= 1 ||
2279+ arrayLength < 0 ||
2280+ ARR_HASNULL (a )||
2281+ ARR_ELEMTYPE (a )!= OIDOID )
2282+ elog (ERROR ,"extconfig is not a 1-D Oid array" );
2283+ arrayData = (Oid * )ARR_DATA_PTR (a );
2284+
2285+ arrayIndex = -1 ;/* flag for no deletion needed */
2286+
2287+ for (i = 0 ;i < arrayLength ;i ++ )
2288+ {
2289+ if (arrayData [i ]== tableoid )
2290+ {
2291+ arrayIndex = i ;/* index to remove */
2292+ break ;
2293+ }
2294+ }
2295+ }
2296+
2297+ /* If tableoid is not in extconfig, nothing to do */
2298+ if (arrayIndex < 0 )
2299+ {
2300+ systable_endscan (extScan );
2301+ heap_close (extRel ,RowExclusiveLock );
2302+ return ;
2303+ }
2304+
2305+ /* Modify or delete the extconfig value */
2306+ memset (repl_val ,0 ,sizeof (repl_val ));
2307+ memset (repl_null , false,sizeof (repl_null ));
2308+ memset (repl_repl , false,sizeof (repl_repl ));
2309+
2310+ if (arrayLength <=1 )
2311+ {
2312+ /* removing only element, just set array to null */
2313+ repl_null [Anum_pg_extension_extconfig - 1 ]= true;
2314+ }
2315+ else
2316+ {
2317+ /* squeeze out the target element */
2318+ Datum * dvalues ;
2319+ bool * dnulls ;
2320+ int nelems ;
2321+ int i ;
2322+
2323+ deconstruct_array (a ,OIDOID ,sizeof (Oid ), true,'i' ,
2324+ & dvalues ,& dnulls ,& nelems );
2325+
2326+ /* We already checked there are no nulls, so ignore dnulls */
2327+ for (i = arrayIndex ;i < arrayLength - 1 ;i ++ )
2328+ dvalues [i ]= dvalues [i + 1 ];
2329+
2330+ a = construct_array (dvalues ,arrayLength - 1 ,
2331+ OIDOID ,sizeof (Oid ), true,'i' );
2332+
2333+ repl_val [Anum_pg_extension_extconfig - 1 ]= PointerGetDatum (a );
2334+ }
2335+ repl_repl [Anum_pg_extension_extconfig - 1 ]= true;
2336+
2337+ /* Modify or delete the extcondition value */
2338+ arrayDatum = heap_getattr (extTup ,Anum_pg_extension_extcondition ,
2339+ RelationGetDescr (extRel ),& isnull );
2340+ if (isnull )
2341+ {
2342+ elog (ERROR ,"extconfig and extcondition arrays do not match" );
2343+ }
2344+ else
2345+ {
2346+ a = DatumGetArrayTypeP (arrayDatum );
2347+
2348+ if (ARR_NDIM (a )!= 1 ||
2349+ ARR_LBOUND (a )[0 ]!= 1 ||
2350+ ARR_HASNULL (a )||
2351+ ARR_ELEMTYPE (a )!= TEXTOID )
2352+ elog (ERROR ,"extcondition is not a 1-D text array" );
2353+ if (ARR_DIMS (a )[0 ]!= arrayLength )
2354+ elog (ERROR ,"extconfig and extcondition arrays do not match" );
2355+ }
2356+
2357+ if (arrayLength <=1 )
2358+ {
2359+ /* removing only element, just set array to null */
2360+ repl_null [Anum_pg_extension_extcondition - 1 ]= true;
2361+ }
2362+ else
2363+ {
2364+ /* squeeze out the target element */
2365+ Datum * dvalues ;
2366+ bool * dnulls ;
2367+ int nelems ;
2368+ int i ;
2369+
2370+ deconstruct_array (a ,TEXTOID ,-1 , false,'i' ,
2371+ & dvalues ,& dnulls ,& nelems );
2372+
2373+ /* We already checked there are no nulls, so ignore dnulls */
2374+ for (i = arrayIndex ;i < arrayLength - 1 ;i ++ )
2375+ dvalues [i ]= dvalues [i + 1 ];
2376+
2377+ a = construct_array (dvalues ,arrayLength - 1 ,
2378+ TEXTOID ,-1 , false,'i' );
2379+
2380+ repl_val [Anum_pg_extension_extcondition - 1 ]= PointerGetDatum (a );
2381+ }
2382+ repl_repl [Anum_pg_extension_extcondition - 1 ]= true;
2383+
2384+ extTup = heap_modify_tuple (extTup ,RelationGetDescr (extRel ),
2385+ repl_val ,repl_null ,repl_repl );
2386+
2387+ simple_heap_update (extRel ,& extTup -> t_self ,extTup );
2388+ CatalogUpdateIndexes (extRel ,extTup );
2389+
2390+ systable_endscan (extScan );
2391+
2392+ heap_close (extRel ,RowExclusiveLock );
2393+ }
2394+
21852395/*
21862396 * Execute ALTER EXTENSION SET SCHEMA
21872397 */
@@ -2742,6 +2952,13 @@ ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt)
27422952ExtensionRelationId ,
27432953DEPENDENCY_EXTENSION )!= 1 )
27442954elog (ERROR ,"unexpected number of extension dependency records" );
2955+
2956+ /*
2957+ * If it's a relation, it might have an entry in the extension's
2958+ * extconfig array, which we must remove.
2959+ */
2960+ if (object .classId == RelationRelationId )
2961+ extension_config_remove (extension .objectId ,object .objectId );
27452962}
27462963
27472964/*