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

Commit17a7106

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 parent0d0501e commit17a7106

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
@@ -658,6 +658,10 @@ SET LOCAL search_path TO @extschema@;
658658
and reload.
659659
</para>
660660

661+
<indexterm>
662+
<primary>pg_extension_config_dump</primary>
663+
</indexterm>
664+
661665
<para>
662666
To solve this problem, an extension's script file can mark a table
663667
it has created as a configuration table, which will cause
@@ -696,6 +700,14 @@ SELECT pg_catalog.pg_extension_config_dump('my_config', 'WHERE NOT standard_entr
696700
be modified by users, can be handled by creating triggers on the
697701
configuration table to ensure that modified rows are marked correctly.
698702
</para>
703+
704+
<para>
705+
You can alter the filter condition associated with a configuration table
706+
by calling <function>pg_extension_config_dump</> again. (This would
707+
typically be useful in an extension update script.) The only way to mark
708+
a table as no longer a configuration table is to dissociate it from the
709+
extension with <command>ALTER EXTENSION ... DROP TABLE</>.
710+
</para>
699711
</sect2>
700712

701713
<sect2>

‎src/backend/commands/extension.c

Lines changed: 227 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2112,6 +2112,7 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
21122112
HeapTupleextTup;
21132113
DatumarrayDatum;
21142114
DatumelementDatum;
2115+
intarrayLength;
21152116
intarrayIndex;
21162117
boolisnull;
21172118
Datumrepl_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 toprotect the extconfig entry.
21362137
*/
21372138
tablename=get_rel_name(tableoid);
21382139
if (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)
21792183
RelationGetDescr(extRel),&isnull);
21802184
if (isnull)
21812185
{
2186+
/* Previously empty extconfig, so build 1-element array */
2187+
arrayLength=0;
2188+
arrayIndex=1;
2189+
21822190
a=construct_array(&elementDatum,1,
21832191
OIDOID,
21842192
sizeof(Oid), true,'i');
21852193
}
21862194
else
21872195
{
2196+
/* Modify or extend existing extconfig array */
2197+
Oid*arrayData;
2198+
inti;
2199+
21882200
a=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

21952222
a=array_set(a,1,&arrayIndex,
21962223
elementDatum,
@@ -2210,19 +2237,26 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
22102237
RelationGetDescr(extRel),&isnull);
22112238
if (isnull)
22122239
{
2240+
if (arrayLength!=0)
2241+
elog(ERROR,"extconfig and extcondition arrays do not match");
2242+
22132243
a=construct_array(&elementDatum,1,
22142244
TEXTOID,
22152245
-1, false,'i');
22162246
}
22172247
else
22182248
{
22192249
a=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 */
22262260
a=array_set(a,1,&arrayIndex,
22272261
elementDatum,
22282262
false,
@@ -2247,6 +2281,182 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
22472281
PG_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+
staticvoid
2292+
extension_config_remove(Oidextensionoid,Oidtableoid)
2293+
{
2294+
RelationextRel;
2295+
ScanKeyDatakey[1];
2296+
SysScanDescextScan;
2297+
HeapTupleextTup;
2298+
DatumarrayDatum;
2299+
intarrayLength;
2300+
intarrayIndex;
2301+
boolisnull;
2302+
Datumrepl_val[Natts_pg_extension];
2303+
boolrepl_null[Natts_pg_extension];
2304+
boolrepl_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+
inti;
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+
intnelems;
2386+
inti;
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+
intnelems;
2433+
inti;
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)
28073017
ExtensionRelationId,
28083018
DEPENDENCY_EXTENSION)!=1)
28093019
elog(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
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp