Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitbfe738d

Browse files
committed
Fix pg_extension_config_dump() to handle update cases more sanely.
If pg_extension_config_dump() is executed again for a table already listedin the extension's extconfig, the code was blindly making a new array entry.This does not seem useful. Fix it to replace the existing array entryinstead, so that it's possible for extension update scripts to alter thefilter conditions for configuration tables.In addition, teach ALTER EXTENSION DROP TABLE to check for an extconfigentry for the target table, and remove it if present. This is not a 100%solution because it's allowed for an extension update script to justsummarily DROP a member table, and that code path doesn't go throughExecAlterExtensionContentsStmt. We could probably make that case cleanthings up if we had to, but it would involve sticking a very ugly wartsomewhere in the guts of dependency.c. Since on the whole it seems quiteunlikely that extension updates would want to remove pre-existingconfiguration tables, making the case possible with an explicit commandseems sufficient.Per bug #7756 from Regina Obe. Back-patch to 9.1 where extensions wereintroduced.
1 parent3881aed commitbfe738d

File tree

2 files changed

+239
-10
lines changed

2 files changed

+239
-10
lines changed

‎doc/src/sgml/extend.sgml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,10 @@ SET LOCAL search_path TO @extschema@;
665665
and reload.
666666
</para>
667667

668+
<indexterm>
669+
<primary>pg_extension_config_dump</primary>
670+
</indexterm>
671+
668672
<para>
669673
To solve this problem, an extension's script file can mark a table
670674
it has created as a configuration table, which will cause
@@ -703,6 +707,14 @@ SELECT pg_catalog.pg_extension_config_dump('my_config', 'WHERE NOT standard_entr
703707
be modified by users, can be handled by creating triggers on the
704708
configuration table to ensure that modified rows are marked correctly.
705709
</para>
710+
711+
<para>
712+
You can alter the filter condition associated with a configuration table
713+
by calling <function>pg_extension_config_dump</> again. (This would
714+
typically be useful in an extension update script.) The only way to mark
715+
a table as no longer a configuration table is to dissociate it from the
716+
extension with <command>ALTER EXTENSION ... DROP TABLE</>.
717+
</para>
706718
</sect2>
707719

708720
<sect2>

‎src/backend/commands/extension.c

Lines changed: 227 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2047,6 +2047,7 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
20472047
HeapTupleextTup;
20482048
DatumarrayDatum;
20492049
DatumelementDatum;
2050+
intarrayLength;
20502051
intarrayIndex;
20512052
boolisnull;
20522053
Datumrepl_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 toprotect the extconfig entry.
20712072
*/
20722073
tablename=get_rel_name(tableoid);
20732074
if (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)
21142118
RelationGetDescr(extRel),&isnull);
21152119
if (isnull)
21162120
{
2121+
/* Previously empty extconfig, so build 1-element array */
2122+
arrayLength=0;
2123+
arrayIndex=1;
2124+
21172125
a=construct_array(&elementDatum,1,
21182126
OIDOID,
21192127
sizeof(Oid), true,'i');
21202128
}
21212129
else
21222130
{
2131+
/* Modify or extend existing extconfig array */
2132+
Oid*arrayData;
2133+
inti;
2134+
21232135
a=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

21302157
a=array_set(a,1,&arrayIndex,
21312158
elementDatum,
@@ -2145,19 +2172,26 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
21452172
RelationGetDescr(extRel),&isnull);
21462173
if (isnull)
21472174
{
2175+
if (arrayLength!=0)
2176+
elog(ERROR,"extconfig and extcondition arrays do not match");
2177+
21482178
a=construct_array(&elementDatum,1,
21492179
TEXTOID,
21502180
-1, false,'i');
21512181
}
21522182
else
21532183
{
21542184
a=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 */
21612195
a=array_set(a,1,&arrayIndex,
21622196
elementDatum,
21632197
false,
@@ -2182,6 +2216,182 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
21822216
PG_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+
staticvoid
2227+
extension_config_remove(Oidextensionoid,Oidtableoid)
2228+
{
2229+
RelationextRel;
2230+
ScanKeyDatakey[1];
2231+
SysScanDescextScan;
2232+
HeapTupleextTup;
2233+
DatumarrayDatum;
2234+
intarrayLength;
2235+
intarrayIndex;
2236+
boolisnull;
2237+
Datumrepl_val[Natts_pg_extension];
2238+
boolrepl_null[Natts_pg_extension];
2239+
boolrepl_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+
inti;
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+
intnelems;
2321+
inti;
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+
intnelems;
2368+
inti;
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)
27422952
ExtensionRelationId,
27432953
DEPENDENCY_EXTENSION)!=1)
27442954
elog(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
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp