@@ -2112,6 +2112,7 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
21122112HeapTuple extTup ;
21132113Datum arrayDatum ;
21142114Datum elementDatum ;
2115+ int arrayLength ;
21152116int arrayIndex ;
21162117bool isnull ;
21172118Datum repl_val [Natts_pg_extension ];
@@ -2131,8 +2132,8 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
21312132
21322133/*
21332134 * Check that the table exists and is a member of the extension being
2134- * created. This ensures that we don't need to registera dependency to
2135- * protect the extconfig entry.
2135+ * created. This ensures that we don't need to registeran additional
2136+ *dependency to protect the extconfig entry.
21362137 */
21372138tablename = get_rel_name (tableoid );
21382139if (tablename == NULL )
@@ -2149,6 +2150,9 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
21492150/*
21502151 * Add the table OID and WHERE condition to the extension's extconfig and
21512152 * extcondition arrays.
2153+ *
2154+ * If the table is already in extconfig, treat this as an update of the
2155+ * WHERE condition.
21522156 */
21532157
21542158/* Find the pg_extension tuple */
@@ -2179,18 +2183,41 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
21792183RelationGetDescr (extRel ),& isnull );
21802184if (isnull )
21812185{
2186+ /* Previously empty extconfig, so build 1-element array */
2187+ arrayLength = 0 ;
2188+ arrayIndex = 1 ;
2189+
21822190a = construct_array (& elementDatum ,1 ,
21832191OIDOID ,
21842192sizeof (Oid ), true,'i' );
21852193}
21862194else
21872195{
2196+ /* Modify or extend existing extconfig array */
2197+ Oid * arrayData ;
2198+ int i ;
2199+
21882200a = DatumGetArrayTypeP (arrayDatum );
2189- Assert (ARR_ELEMTYPE (a )== OIDOID );
2190- Assert (ARR_NDIM (a )== 1 );
2191- Assert (ARR_LBOUND (a )[0 ]== 1 );
21922201
2193- arrayIndex = ARR_DIMS (a )[0 ]+ 1 ;/* add after end */
2202+ arrayLength = ARR_DIMS (a )[0 ];
2203+ if (ARR_NDIM (a )!= 1 ||
2204+ ARR_LBOUND (a )[0 ]!= 1 ||
2205+ arrayLength < 0 ||
2206+ ARR_HASNULL (a )||
2207+ ARR_ELEMTYPE (a )!= OIDOID )
2208+ elog (ERROR ,"extconfig is not a 1-D Oid array" );
2209+ arrayData = (Oid * )ARR_DATA_PTR (a );
2210+
2211+ arrayIndex = arrayLength + 1 ;/* set up to add after end */
2212+
2213+ for (i = 0 ;i < arrayLength ;i ++ )
2214+ {
2215+ if (arrayData [i ]== tableoid )
2216+ {
2217+ arrayIndex = i + 1 ;/* replace this element instead */
2218+ break ;
2219+ }
2220+ }
21942221
21952222a = array_set (a ,1 ,& arrayIndex ,
21962223elementDatum ,
@@ -2210,19 +2237,26 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
22102237RelationGetDescr (extRel ),& isnull );
22112238if (isnull )
22122239{
2240+ if (arrayLength != 0 )
2241+ elog (ERROR ,"extconfig and extcondition arrays do not match" );
2242+
22132243a = construct_array (& elementDatum ,1 ,
22142244TEXTOID ,
22152245-1 , false,'i' );
22162246}
22172247else
22182248{
22192249a = DatumGetArrayTypeP (arrayDatum );
2220- Assert (ARR_ELEMTYPE (a )== TEXTOID );
2221- Assert (ARR_NDIM (a )== 1 );
2222- Assert (ARR_LBOUND (a )[0 ]== 1 );
22232250
2224- arrayIndex = ARR_DIMS (a )[0 ]+ 1 ;/* add after end */
2251+ if (ARR_NDIM (a )!= 1 ||
2252+ ARR_LBOUND (a )[0 ]!= 1 ||
2253+ ARR_HASNULL (a )||
2254+ ARR_ELEMTYPE (a )!= TEXTOID )
2255+ elog (ERROR ,"extcondition is not a 1-D text array" );
2256+ if (ARR_DIMS (a )[0 ]!= arrayLength )
2257+ elog (ERROR ,"extconfig and extcondition arrays do not match" );
22252258
2259+ /* Add or replace at same index as in extconfig */
22262260a = array_set (a ,1 ,& arrayIndex ,
22272261elementDatum ,
22282262 false,
@@ -2247,6 +2281,182 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
22472281PG_RETURN_VOID ();
22482282}
22492283
2284+ /*
2285+ * extension_config_remove
2286+ *
2287+ * Remove the specified table OID from extension's extconfig, if present.
2288+ * This is not currently exposed as a function, but it could be;
2289+ * for now, we just invoke it from ALTER EXTENSION DROP.
2290+ */
2291+ static void
2292+ extension_config_remove (Oid extensionoid ,Oid tableoid )
2293+ {
2294+ Relation extRel ;
2295+ ScanKeyData key [1 ];
2296+ SysScanDesc extScan ;
2297+ HeapTuple extTup ;
2298+ Datum arrayDatum ;
2299+ int arrayLength ;
2300+ int arrayIndex ;
2301+ bool isnull ;
2302+ Datum repl_val [Natts_pg_extension ];
2303+ bool repl_null [Natts_pg_extension ];
2304+ bool repl_repl [Natts_pg_extension ];
2305+ ArrayType * a ;
2306+
2307+ /* Find the pg_extension tuple */
2308+ extRel = heap_open (ExtensionRelationId ,RowExclusiveLock );
2309+
2310+ ScanKeyInit (& key [0 ],
2311+ ObjectIdAttributeNumber ,
2312+ BTEqualStrategyNumber ,F_OIDEQ ,
2313+ ObjectIdGetDatum (extensionoid ));
2314+
2315+ extScan = systable_beginscan (extRel ,ExtensionOidIndexId , true,
2316+ SnapshotNow ,1 ,key );
2317+
2318+ extTup = systable_getnext (extScan );
2319+
2320+ if (!HeapTupleIsValid (extTup ))/* should not happen */
2321+ elog (ERROR ,"extension with oid %u does not exist" ,
2322+ extensionoid );
2323+
2324+ /* Search extconfig for the tableoid */
2325+ arrayDatum = heap_getattr (extTup ,Anum_pg_extension_extconfig ,
2326+ RelationGetDescr (extRel ),& isnull );
2327+ if (isnull )
2328+ {
2329+ /* nothing to do */
2330+ a = NULL ;
2331+ arrayLength = 0 ;
2332+ arrayIndex = -1 ;
2333+ }
2334+ else
2335+ {
2336+ Oid * arrayData ;
2337+ int i ;
2338+
2339+ a = DatumGetArrayTypeP (arrayDatum );
2340+
2341+ arrayLength = ARR_DIMS (a )[0 ];
2342+ if (ARR_NDIM (a )!= 1 ||
2343+ ARR_LBOUND (a )[0 ]!= 1 ||
2344+ arrayLength < 0 ||
2345+ ARR_HASNULL (a )||
2346+ ARR_ELEMTYPE (a )!= OIDOID )
2347+ elog (ERROR ,"extconfig is not a 1-D Oid array" );
2348+ arrayData = (Oid * )ARR_DATA_PTR (a );
2349+
2350+ arrayIndex = -1 ;/* flag for no deletion needed */
2351+
2352+ for (i = 0 ;i < arrayLength ;i ++ )
2353+ {
2354+ if (arrayData [i ]== tableoid )
2355+ {
2356+ arrayIndex = i ;/* index to remove */
2357+ break ;
2358+ }
2359+ }
2360+ }
2361+
2362+ /* If tableoid is not in extconfig, nothing to do */
2363+ if (arrayIndex < 0 )
2364+ {
2365+ systable_endscan (extScan );
2366+ heap_close (extRel ,RowExclusiveLock );
2367+ return ;
2368+ }
2369+
2370+ /* Modify or delete the extconfig value */
2371+ memset (repl_val ,0 ,sizeof (repl_val ));
2372+ memset (repl_null , false,sizeof (repl_null ));
2373+ memset (repl_repl , false,sizeof (repl_repl ));
2374+
2375+ if (arrayLength <=1 )
2376+ {
2377+ /* removing only element, just set array to null */
2378+ repl_null [Anum_pg_extension_extconfig - 1 ]= true;
2379+ }
2380+ else
2381+ {
2382+ /* squeeze out the target element */
2383+ Datum * dvalues ;
2384+ bool * dnulls ;
2385+ int nelems ;
2386+ int i ;
2387+
2388+ deconstruct_array (a ,OIDOID ,sizeof (Oid ), true,'i' ,
2389+ & dvalues ,& dnulls ,& nelems );
2390+
2391+ /* We already checked there are no nulls, so ignore dnulls */
2392+ for (i = arrayIndex ;i < arrayLength - 1 ;i ++ )
2393+ dvalues [i ]= dvalues [i + 1 ];
2394+
2395+ a = construct_array (dvalues ,arrayLength - 1 ,
2396+ OIDOID ,sizeof (Oid ), true,'i' );
2397+
2398+ repl_val [Anum_pg_extension_extconfig - 1 ]= PointerGetDatum (a );
2399+ }
2400+ repl_repl [Anum_pg_extension_extconfig - 1 ]= true;
2401+
2402+ /* Modify or delete the extcondition value */
2403+ arrayDatum = heap_getattr (extTup ,Anum_pg_extension_extcondition ,
2404+ RelationGetDescr (extRel ),& isnull );
2405+ if (isnull )
2406+ {
2407+ elog (ERROR ,"extconfig and extcondition arrays do not match" );
2408+ }
2409+ else
2410+ {
2411+ a = DatumGetArrayTypeP (arrayDatum );
2412+
2413+ if (ARR_NDIM (a )!= 1 ||
2414+ ARR_LBOUND (a )[0 ]!= 1 ||
2415+ ARR_HASNULL (a )||
2416+ ARR_ELEMTYPE (a )!= TEXTOID )
2417+ elog (ERROR ,"extcondition is not a 1-D text array" );
2418+ if (ARR_DIMS (a )[0 ]!= arrayLength )
2419+ elog (ERROR ,"extconfig and extcondition arrays do not match" );
2420+ }
2421+
2422+ if (arrayLength <=1 )
2423+ {
2424+ /* removing only element, just set array to null */
2425+ repl_null [Anum_pg_extension_extcondition - 1 ]= true;
2426+ }
2427+ else
2428+ {
2429+ /* squeeze out the target element */
2430+ Datum * dvalues ;
2431+ bool * dnulls ;
2432+ int nelems ;
2433+ int i ;
2434+
2435+ deconstruct_array (a ,TEXTOID ,-1 , false,'i' ,
2436+ & dvalues ,& dnulls ,& nelems );
2437+
2438+ /* We already checked there are no nulls, so ignore dnulls */
2439+ for (i = arrayIndex ;i < arrayLength - 1 ;i ++ )
2440+ dvalues [i ]= dvalues [i + 1 ];
2441+
2442+ a = construct_array (dvalues ,arrayLength - 1 ,
2443+ TEXTOID ,-1 , false,'i' );
2444+
2445+ repl_val [Anum_pg_extension_extcondition - 1 ]= PointerGetDatum (a );
2446+ }
2447+ repl_repl [Anum_pg_extension_extcondition - 1 ]= true;
2448+
2449+ extTup = heap_modify_tuple (extTup ,RelationGetDescr (extRel ),
2450+ repl_val ,repl_null ,repl_repl );
2451+
2452+ simple_heap_update (extRel ,& extTup -> t_self ,extTup );
2453+ CatalogUpdateIndexes (extRel ,extTup );
2454+
2455+ systable_endscan (extScan );
2456+
2457+ heap_close (extRel ,RowExclusiveLock );
2458+ }
2459+
22502460/*
22512461 * Execute ALTER EXTENSION SET SCHEMA
22522462 */
@@ -2807,6 +3017,13 @@ ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt)
28073017ExtensionRelationId ,
28083018DEPENDENCY_EXTENSION )!= 1 )
28093019elog (ERROR ,"unexpected number of extension dependency records" );
3020+
3021+ /*
3022+ * If it's a relation, it might have an entry in the extension's
3023+ * extconfig array, which we must remove.
3024+ */
3025+ if (object .classId == RelationRelationId )
3026+ extension_config_remove (extension .objectId ,object .objectId );
28103027}
28113028
28123029/*