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

Commit1d6c72a

Browse files
committed
Move materialized views' is-populated status into their pg_class entries.
Previously this state was represented by whether the view's disk file hadzero or nonzero size, which is problematic for numerous reasons, since it'sbreaking a fundamental assumption about heap storage. This was done toallow unlogged matviews to revert to unpopulated status after a crashdespite our lack of any ability to update catalog entries post-crash.However, this poses enough risk of future problems that it seems better tonot support unlogged matviews until we can find another way. Accordingly,revert that choice as well as a number of existing kluges forced by itin favor of creating a pg_class.relispopulated flag column.
1 parent5da5798 commit1d6c72a

File tree

22 files changed

+141
-179
lines changed

22 files changed

+141
-179
lines changed

‎doc/src/sgml/catalogs.sgml

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1863,6 +1863,14 @@
18631863
<entry>True if table has (or once had) any inheritance children</entry>
18641864
</row>
18651865

1866+
<row>
1867+
<entry><structfield>relispopulated</structfield></entry>
1868+
<entry><type>bool</type></entry>
1869+
<entry></entry>
1870+
<entry>True if relation is populated (this is true for all
1871+
relations other than some materialized views)</entry>
1872+
</row>
1873+
18661874
<row>
18671875
<entry><structfield>relfrozenxid</structfield></entry>
18681876
<entry><type>xid</type></entry>
@@ -7776,14 +7784,14 @@
77767784
<row>
77777785
<entry><structfield>hasindexes</structfield></entry>
77787786
<entry><type>boolean</type></entry>
7779-
<entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.relhasindex</literal></entry>
7787+
<entry></entry>
77807788
<entry>True if materialized view has (or recently had) any indexes</entry>
77817789
</row>
77827790
<row>
7783-
<entry><structfield>isscannable</structfield></entry>
7791+
<entry><structfield>ispopulated</structfield></entry>
77847792
<entry><type>boolean</type></entry>
77857793
<entry></entry>
7786-
<entry>True if materialized viewcan currentlybe scanned</entry>
7794+
<entry>True if materialized viewis currentlypopulated</entry>
77877795
</row>
77887796
<row>
77897797
<entry><structfield>definition</structfield></entry>

‎doc/src/sgml/func.sgml

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14238,10 +14238,6 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
1423814238
<primary>pg_tablespace_location</primary>
1423914239
</indexterm>
1424014240

14241-
<indexterm>
14242-
<primary>pg_relation_is_scannable</primary>
14243-
</indexterm>
14244-
1424514241
<indexterm>
1424614242
<primary>pg_typeof</primary>
1424714243
</indexterm>
@@ -14410,11 +14406,6 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
1441014406
<entry><type>text</type></entry>
1441114407
<entry>get the path in the file system that this tablespace is located in</entry>
1441214408
</row>
14413-
<row>
14414-
<entry><literal><function>pg_relation_is_scannable(<parameter>relation_oid</parameter>)</function></literal></entry>
14415-
<entry><type>boolean</type></entry>
14416-
<entry>is the relation scannable; a materialized view which has not been loaded will not be scannable</entry>
14417-
</row>
1441814409
<row>
1441914410
<entry><literal><function>pg_typeof(<parameter>any</parameter>)</function></literal></entry>
1442014411
<entry><type>regtype</type></entry>

‎src/backend/catalog/heap.c

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,7 @@ InsertPgClassTuple(Relation pg_class_desc,
780780
values[Anum_pg_class_relhasrules-1]=BoolGetDatum(rd_rel->relhasrules);
781781
values[Anum_pg_class_relhastriggers-1]=BoolGetDatum(rd_rel->relhastriggers);
782782
values[Anum_pg_class_relhassubclass-1]=BoolGetDatum(rd_rel->relhassubclass);
783+
values[Anum_pg_class_relispopulated-1]=BoolGetDatum(rd_rel->relispopulated);
783784
values[Anum_pg_class_relfrozenxid-1]=TransactionIdGetDatum(rd_rel->relfrozenxid);
784785
values[Anum_pg_class_relminmxid-1]=MultiXactIdGetDatum(rd_rel->relminmxid);
785786
if (relacl!= (Datum)0)
@@ -1345,26 +1346,6 @@ heap_create_init_fork(Relation rel)
13451346
smgrimmedsync(rel->rd_smgr,INIT_FORKNUM);
13461347
}
13471348

1348-
/*
1349-
* Check whether a materialized view is in an initial, unloaded state.
1350-
*
1351-
* The check here must match what is set up in heap_create_init_fork().
1352-
* Currently the init fork is an empty file. A missing heap is also
1353-
* considered to be unloaded.
1354-
*/
1355-
bool
1356-
heap_is_matview_init_state(Relationrel)
1357-
{
1358-
Assert(rel->rd_rel->relkind==RELKIND_MATVIEW);
1359-
1360-
RelationOpenSmgr(rel);
1361-
1362-
if (!smgrexists(rel->rd_smgr,MAIN_FORKNUM))
1363-
return true;
1364-
1365-
return (smgrnblocks(rel->rd_smgr,MAIN_FORKNUM)<1);
1366-
}
1367-
13681349
/*
13691350
*RelationRemoveInheritance
13701351
*

‎src/backend/catalog/system_views.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ CREATE VIEW pg_matviews AS
101101
pg_get_userbyid(C.relowner)AS matviewowner,
102102
T.spcnameAS tablespace,
103103
C.relhasindexAS hasindexes,
104-
pg_relation_is_scannable(C.oid)ASisscannable,
104+
C.relispopulatedASispopulated,
105105
pg_get_viewdef(C.oid)AS definition
106106
FROM pg_class CLEFT JOIN pg_namespace NON (N.oid=C.relnamespace)
107107
LEFT JOIN pg_tablespace TON (T.oid=C.reltablespace)

‎src/backend/commands/cluster.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
#include"catalog/objectaccess.h"
3131
#include"catalog/toasting.h"
3232
#include"commands/cluster.h"
33-
#include"commands/matview.h"
3433
#include"commands/tablecmds.h"
3534
#include"commands/vacuum.h"
3635
#include"miscadmin.h"
@@ -388,7 +387,7 @@ cluster_rel(Oid tableOid, Oid indexOid, bool recheck, bool verbose,
388387
* database.
389388
*/
390389
if (OldHeap->rd_rel->relkind==RELKIND_MATVIEW&&
391-
!OldHeap->rd_ispopulated)
390+
!RelationIsPopulated(OldHeap))
392391
{
393392
relation_close(OldHeap,AccessExclusiveLock);
394393
return;
@@ -922,10 +921,6 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex,
922921
get_namespace_name(RelationGetNamespace(OldHeap)),
923922
RelationGetRelationName(OldHeap))));
924923

925-
if (OldHeap->rd_rel->relkind==RELKIND_MATVIEW)
926-
/* Make sure the heap looks good even if no rows are written. */
927-
SetMatViewToPopulated(NewHeap);
928-
929924
/*
930925
* Scan through the OldHeap, either in OldIndex order or sequentially;
931926
* copy each tuple into the NewHeap, or transiently to the tuplesort

‎src/backend/commands/createas.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -359,10 +359,6 @@ intorel_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
359359
*/
360360
intoRelationDesc=heap_open(intoRelationId,AccessExclusiveLock);
361361

362-
if (is_matview&& !into->skipData)
363-
/* Make sure the heap looks good even if no rows are written. */
364-
SetMatViewToPopulated(intoRelationDesc);
365-
366362
/*
367363
* Check INSERT permission on the constructed table.
368364
*
@@ -381,6 +377,13 @@ intorel_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
381377

382378
ExecCheckRTPerms(list_make1(rte), true);
383379

380+
/*
381+
* Tentatively mark the target as populated, if it's a matview and we're
382+
* going to fill it; otherwise, no change needed.
383+
*/
384+
if (is_matview&& !into->skipData)
385+
SetMatViewPopulatedState(intoRelationDesc, true);
386+
384387
/*
385388
* Fill private fields of myState for use by later routines
386389
*/

‎src/backend/commands/matview.c

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,23 @@
1414
*/
1515
#include"postgres.h"
1616

17-
#include"access/heapam_xlog.h"
17+
#include"access/htup_details.h"
1818
#include"access/multixact.h"
19-
#include"access/relscan.h"
2019
#include"access/xact.h"
2120
#include"catalog/catalog.h"
22-
#include"catalog/heap.h"
21+
#include"catalog/indexing.h"
2322
#include"catalog/namespace.h"
2423
#include"commands/cluster.h"
2524
#include"commands/matview.h"
2625
#include"commands/tablecmds.h"
2726
#include"executor/executor.h"
2827
#include"miscadmin.h"
2928
#include"rewrite/rewriteHandler.h"
30-
#include"storage/lmgr.h"
3129
#include"storage/smgr.h"
3230
#include"tcop/tcopprot.h"
31+
#include"utils/rel.h"
3332
#include"utils/snapmgr.h"
33+
#include"utils/syscache.h"
3434

3535

3636
typedefstruct
@@ -52,38 +52,45 @@ static void refresh_matview_datafill(DestReceiver *dest, Query *query,
5252
constchar*queryString);
5353

5454
/*
55-
* SetMatViewToPopulated
56-
*Indicate that the materialized view has been populated by its query.
57-
*
58-
* NOTE: The heap starts out in a state that doesn't look scannable, and can
59-
* only transition from there to scannable at the time a new heap is created.
55+
* SetMatViewPopulatedState
56+
*Mark a materialized view as populated, or not.
6057
*
6158
* NOTE: caller must be holding an appropriate lock on the relation.
6259
*/
6360
void
64-
SetMatViewToPopulated(Relationrelation)
61+
SetMatViewPopulatedState(Relationrelation,boolnewstate)
6562
{
66-
Pagepage;
63+
Relationpgrel;
64+
HeapTupletuple;
6765

6866
Assert(relation->rd_rel->relkind==RELKIND_MATVIEW);
69-
Assert(relation->rd_ispopulated== false);
70-
71-
page= (Page)palloc(BLCKSZ);
72-
PageInit(page,BLCKSZ,0);
7367

74-
if (RelationNeedsWAL(relation))
75-
log_newpage(&(relation->rd_node),MAIN_FORKNUM,0,page);
68+
/*
69+
* Update relation's pg_class entry. Crucial side-effect: other backends
70+
* (and this one too!) are sent SI message to make them rebuild relcache
71+
* entries.
72+
*/
73+
pgrel=heap_open(RelationRelationId,RowExclusiveLock);
74+
tuple=SearchSysCacheCopy1(RELOID,
75+
ObjectIdGetDatum(RelationGetRelid(relation)));
76+
if (!HeapTupleIsValid(tuple))
77+
elog(ERROR,"cache lookup failed for relation %u",
78+
RelationGetRelid(relation));
7679

77-
RelationOpenSmgr(relation);
80+
((Form_pg_class)GETSTRUCT(tuple))->relispopulated=newstate;
7881

79-
PageSetChecksumInplace(page,0);
80-
smgrextend(relation->rd_smgr,MAIN_FORKNUM,0, (char*)page, true);
82+
simple_heap_update(pgrel,&tuple->t_self,tuple);
8183

82-
pfree(page);
84+
CatalogUpdateIndexes(pgrel,tuple);
8385

84-
smgrimmedsync(relation->rd_smgr,MAIN_FORKNUM);
86+
heap_freetuple(tuple);
87+
heap_close(pgrel,RowExclusiveLock);
8588

86-
RelationCacheInvalidateEntry(relation->rd_id);
89+
/*
90+
* Advance command counter to make the updated pg_class row locally
91+
* visible.
92+
*/
93+
CommandCounterIncrement();
8794
}
8895

8996
/*
@@ -97,14 +104,14 @@ SetMatViewToPopulated(Relation relation)
97104
* If WITH NO DATA was specified, this is effectively like a TRUNCATE;
98105
* otherwise it is like a TRUNCATE followed by an INSERT using the SELECT
99106
* statement associated with the materialized view. The statement node's
100-
* skipData fieldis used to indicate that the clause was used.
107+
* skipData fieldshows whether the clause was used.
101108
*
102109
* Indexes are rebuilt too, via REINDEX. Since we are effectively bulk-loading
103110
* the new heap, it's better to create the indexes afterwards than to fill them
104111
* incrementally while we load.
105112
*
106-
* Thescannablestate is changed based on whether the contents reflect the
107-
* result set of the materialized view's query.
113+
* Thematview's "populated"state is changed based on whether the contents
114+
*reflect theresult set of the materialized view's query.
108115
*/
109116
void
110117
ExecRefreshMatView(RefreshMatViewStmt*stmt,constchar*queryString,
@@ -184,6 +191,12 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
184191
*/
185192
CheckTableNotInUse(matviewRel,"REFRESH MATERIALIZED VIEW");
186193

194+
/*
195+
* Tentatively mark the matview as populated or not (this will roll back
196+
* if we fail later).
197+
*/
198+
SetMatViewPopulatedState(matviewRel, !stmt->skipData);
199+
187200
tableSpace=matviewRel->rd_rel->reltablespace;
188201

189202
heap_close(matviewRel,NoLock);
@@ -192,6 +205,7 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
192205
OIDNewHeap=make_new_heap(matviewOid,tableSpace);
193206
dest=CreateTransientRelDestReceiver(OIDNewHeap);
194207

208+
/* Generate the data, if wanted. */
195209
if (!stmt->skipData)
196210
refresh_matview_datafill(dest,dataQuery,queryString);
197211

@@ -300,8 +314,6 @@ transientrel_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
300314
myState->hi_options |=HEAP_INSERT_SKIP_WAL;
301315
myState->bistate=GetBulkInsertState();
302316

303-
SetMatViewToPopulated(transientrel);
304-
305317
/* Not using WAL requires smgr_targblock be initially invalid */
306318
Assert(RelationGetTargetBlock(transientrel)==InvalidBlockNumber);
307319
}

‎src/backend/commands/vacuumlazy.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -230,13 +230,7 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt,
230230
*
231231
* Don't even think about it unless we have a shot at releasing a goodly
232232
* number of pages. Otherwise, the time taken isn't worth it.
233-
*
234-
* Leave a populated materialized view with at least one page.
235233
*/
236-
if (onerel->rd_rel->relkind==RELKIND_MATVIEW&&
237-
vacrelstats->nonempty_pages==0)
238-
vacrelstats->nonempty_pages=1;
239-
240234
possibly_freeable=vacrelstats->rel_pages-vacrelstats->nonempty_pages;
241235
if (possibly_freeable>0&&
242236
(possibly_freeable >=REL_TRUNCATE_MINIMUM||

‎src/backend/utils/adt/dbsize.c

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -834,30 +834,3 @@ pg_relation_filepath(PG_FUNCTION_ARGS)
834834

835835
PG_RETURN_TEXT_P(cstring_to_text(path));
836836
}
837-
838-
839-
/*
840-
* Indicate whether a relation is scannable.
841-
*
842-
* Currently, this is always true except for a materialized view which has not
843-
* been populated. It is expected that other conditions for allowing a
844-
* materialized view to be scanned will be added in later releases.
845-
*/
846-
Datum
847-
pg_relation_is_scannable(PG_FUNCTION_ARGS)
848-
{
849-
Oidrelid;
850-
Relationrelation;
851-
boolresult;
852-
853-
relid=PG_GETARG_OID(0);
854-
relation=try_relation_open(relid,AccessShareLock);
855-
856-
if (relation==NULL)
857-
PG_RETURN_BOOL(false);
858-
859-
result=RelationIsScannable(relation);
860-
861-
relation_close(relation,AccessShareLock);
862-
PG_RETURN_BOOL(result);
863-
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp