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

Commitb15a6da

Browse files
committed
Get rid of any toast table when converting a table to a view.
Also make sure other fields of the view's pg_class entry are appropriatefor a view; it shouldn't have relfrozenxid set for instance.This ancient omission isn't believed to have any serious consequences inversions 8.4-9.2, so no backpatch. But let's fix it before it does biteus in some serious way. It's just luck that the case doesn't causeproblems for autovacuum. (It did cause problems in 8.3, but that's outof support.)Andres Freund
1 parent2b78d10 commitb15a6da

File tree

5 files changed

+101
-21
lines changed

5 files changed

+101
-21
lines changed

‎src/backend/rewrite/rewriteDefine.c

Lines changed: 87 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616

1717
#include"access/heapam.h"
1818
#include"access/htup_details.h"
19+
#include"access/multixact.h"
20+
#include"access/transam.h"
21+
#include"access/xact.h"
1922
#include"catalog/catalog.h"
2023
#include"catalog/dependency.h"
2124
#include"catalog/heap.h"
@@ -409,7 +412,7 @@ DefineQueryRewrite(char *rulename,
409412
* strict, because they will reject relations that once had such but
410413
* don't anymore. But we don't really care, because this whole
411414
* business of converting relations to views is just a kluge to allow
412-
*loading ancient pg_dump files.)
415+
*dump/reload of views that participate in circular dependencies.)
413416
*/
414417
if (event_relation->rd_rel->relkind!=RELKIND_VIEW)
415418
{
@@ -500,30 +503,103 @@ DefineQueryRewrite(char *rulename,
500503
replace);
501504

502505
/*
503-
* Set pg_class 'relhasrules' field TRUE for event relation. If
504-
* appropriate, also modify the 'relkind' field to show that the
505-
* relation is now a view.
506+
* Set pg_class 'relhasrules' field TRUE for event relation.
506507
*
507508
* Important side effect: an SI notice is broadcast to force all
508509
* backends (including me!) to update relcache entries with the new
509510
* rule.
510511
*/
511-
SetRelationRuleStatus(event_relid, true,RelisBecomingView);
512+
SetRelationRuleStatus(event_relid, true);
512513
}
513514

514-
/*
515-
* If the relation is becoming a view, delete the storage files associated
516-
* with it. Also, get rid of any system attribute entries in pg_attribute,
517-
* because a view shouldn't have any of those.
515+
/* ---------------------------------------------------------------------
516+
* If the relation is becoming a view:
517+
* - delete the associated storage files
518+
* - get rid of any system attributes in pg_attribute; a view shouldn't
519+
* have any of those
520+
* - remove the toast table; there is no need for it anymore, and its
521+
* presence would make vacuum slightly more complicated
522+
* - set relkind to RELKIND_VIEW, and adjust other pg_class fields
523+
* to be appropriate for a view
518524
*
519525
* NB: we had better have AccessExclusiveLock to do this ...
520-
*
521-
* XXX what about getting rid of its TOAST table? For now, we don't.
526+
* ---------------------------------------------------------------------
522527
*/
523528
if (RelisBecomingView)
524529
{
530+
RelationrelationRelation;
531+
Oidtoastrelid;
532+
HeapTupleclassTup;
533+
Form_pg_classclassForm;
534+
535+
relationRelation=heap_open(RelationRelationId,RowExclusiveLock);
536+
toastrelid=event_relation->rd_rel->reltoastrelid;
537+
538+
/* drop storage while table still looks like a table */
525539
RelationDropStorage(event_relation);
526540
DeleteSystemAttributeTuples(event_relid);
541+
542+
/*
543+
* Drop the toast table if any. (This won't take care of updating
544+
* the toast fields in the relation's own pg_class entry; we handle
545+
* that below.)
546+
*/
547+
if (OidIsValid(toastrelid))
548+
{
549+
ObjectAddresstoastobject;
550+
551+
/*
552+
* Delete the dependency of the toast relation on the main
553+
* relation so we can drop the former without dropping the latter.
554+
*/
555+
deleteDependencyRecordsFor(RelationRelationId,toastrelid,
556+
false);
557+
558+
/* Make deletion of dependency record visible */
559+
CommandCounterIncrement();
560+
561+
/* Now drop toast table, including its index */
562+
toastobject.classId=RelationRelationId;
563+
toastobject.objectId=toastrelid;
564+
toastobject.objectSubId=0;
565+
performDeletion(&toastobject,DROP_RESTRICT,
566+
PERFORM_DELETION_INTERNAL);
567+
}
568+
569+
/*
570+
* SetRelationRuleStatus may have updated the pg_class row, so we must
571+
* advance the command counter before trying to update it again.
572+
*/
573+
CommandCounterIncrement();
574+
575+
/*
576+
* Fix pg_class entry to look like a normal view's, including setting
577+
* the correct relkind and removal of reltoastrelid/reltoastidxid of
578+
* the toast table we potentially removed above.
579+
*/
580+
classTup=SearchSysCacheCopy1(RELOID,ObjectIdGetDatum(event_relid));
581+
if (!HeapTupleIsValid(classTup))
582+
elog(ERROR,"cache lookup failed for relation %u",event_relid);
583+
classForm= (Form_pg_class)GETSTRUCT(classTup);
584+
585+
classForm->reltablespace=InvalidOid;
586+
classForm->relpages=0;
587+
classForm->reltuples=0;
588+
classForm->relallvisible=0;
589+
classForm->reltoastrelid=InvalidOid;
590+
classForm->reltoastidxid=InvalidOid;
591+
classForm->relhasindex= false;
592+
classForm->relkind=RELKIND_VIEW;
593+
classForm->relhasoids= false;
594+
classForm->relhaspkey= false;
595+
classForm->relfrozenxid=InvalidTransactionId;
596+
classForm->relminmxid=InvalidMultiXactId;
597+
598+
simple_heap_update(relationRelation,&classTup->t_self,classTup);
599+
CatalogUpdateIndexes(relationRelation,classTup);
600+
601+
heap_freetuple(classTup);
602+
heap_close(relationRelation,RowExclusiveLock);
527603
}
528604

529605
/* Close rel, but keep lock till commit... */

‎src/backend/rewrite/rewriteSupport.c

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ IsDefinedRewriteRule(Oid owningRel, const char *ruleName)
4141

4242
/*
4343
* SetRelationRuleStatus
44-
*Set the value of the relation's relhasrules field in pg_class;
45-
*if the relation is becoming a view, also adjust its relkind.
44+
*Set the value of the relation's relhasrules field in pg_class.
4645
*
4746
* NOTE: caller must be holding an appropriate lock on the relation.
4847
*
@@ -53,8 +52,7 @@ IsDefinedRewriteRule(Oid owningRel, const char *ruleName)
5352
* row.
5453
*/
5554
void
56-
SetRelationRuleStatus(OidrelationId,boolrelHasRules,
57-
boolrelIsBecomingView)
55+
SetRelationRuleStatus(OidrelationId,boolrelHasRules)
5856
{
5957
RelationrelationRelation;
6058
HeapTupletuple;
@@ -69,13 +67,10 @@ SetRelationRuleStatus(Oid relationId, bool relHasRules,
6967
elog(ERROR,"cache lookup failed for relation %u",relationId);
7068
classForm= (Form_pg_class)GETSTRUCT(tuple);
7169

72-
if (classForm->relhasrules!=relHasRules||
73-
(relIsBecomingView&&classForm->relkind!=RELKIND_VIEW))
70+
if (classForm->relhasrules!=relHasRules)
7471
{
7572
/* Do the update */
7673
classForm->relhasrules=relHasRules;
77-
if (relIsBecomingView)
78-
classForm->relkind=RELKIND_VIEW;
7974

8075
simple_heap_update(relationRelation,&tuple->t_self,tuple);
8176

‎src/include/rewrite/rewriteSupport.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@
1919

2020
externboolIsDefinedRewriteRule(OidowningRel,constchar*ruleName);
2121

22-
externvoidSetRelationRuleStatus(OidrelationId,boolrelHasRules,
23-
boolrelIsBecomingView);
22+
externvoidSetRelationRuleStatus(OidrelationId,boolrelHasRules);
2423

2524
externOidget_rewrite_oid(Oidrelid,constchar*rulename,boolmissing_ok);
2625
externOidget_rewrite_oid_without_relid(constchar*rulename,

‎src/test/regress/expected/rules.out

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2327,6 +2327,13 @@ select xmin, * from fooview; -- fail, views don't have such a column
23272327
ERROR: column "xmin" does not exist
23282328
LINE 1: select xmin, * from fooview;
23292329
^
2330+
select reltoastrelid, reltoastidxid, relkind, relfrozenxid
2331+
from pg_class where oid = 'fooview'::regclass;
2332+
reltoastrelid | reltoastidxid | relkind | relfrozenxid
2333+
---------------+---------------+---------+--------------
2334+
0 | 0 | v | 0
2335+
(1 row)
2336+
23302337
drop view fooview;
23312338
--
23322339
-- check for planner problems with complex inherited UPDATES

‎src/test/regress/sql/rules.sql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,9 @@ create rule "_RETURN" as on select to fooview do instead
872872
select*from fooview;
873873
select xmin,*from fooview;-- fail, views don't have such a column
874874

875+
select reltoastrelid, reltoastidxid, relkind, relfrozenxid
876+
from pg_classwhereoid='fooview'::regclass;
877+
875878
dropview fooview;
876879

877880
--

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp