Skip to content

Commit eaf5f70

Browse files
committed
Merge branch 'PGPROEE_transfer_tables' into PGPROEE9_6-15-64-xid
2 parents 5df22d7 + 1c4c0fc commit eaf5f70

File tree

31 files changed

+1358
-61
lines changed

31 files changed

+1358
-61
lines changed

contrib/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ SUBDIRS = \
3535
pg_query_state \
3636
pg_standby \
3737
pg_stat_statements \
38+
pg_transfer \
3839
pg_trgm \
3940
pgcrypto \
4041
pgrowlocks \

src/backend/catalog/catalog.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,7 @@ GetNewRelFileNode(Oid reltablespace, Relation pg_class, char relpersistence)
393393
backend = BackendIdForTempRelations();
394394
break;
395395
case RELPERSISTENCE_UNLOGGED:
396+
case RELPERSISTENCE_CONSTANT:
396397
case RELPERSISTENCE_PERMANENT:
397398
backend = InvalidBackendId;
398399
break;

src/backend/catalog/index.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3509,6 +3509,9 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence,
35093509
* REINDEX_REL_FORCE_INDEXES_PERMANENT: if true, set the persistence of the
35103510
* rebuilt indexes to permanent.
35113511
*
3512+
* REINDEX_REL_FORCE_INDEXES_CONSTANT: if true, set the persistence of the
3513+
* rebuilt indexes to constant.
3514+
*
35123515
* Returns true if any indexes were rebuilt (including toast table's index
35133516
* when relevant). Note that a CommandCounterIncrement will occur after each
35143517
* index rebuild.
@@ -3592,6 +3595,8 @@ reindex_relation(Oid relid, int flags, int options)
35923595
persistence = RELPERSISTENCE_UNLOGGED;
35933596
else if (flags & REINDEX_REL_FORCE_INDEXES_PERMANENT)
35943597
persistence = RELPERSISTENCE_PERMANENT;
3598+
else if (flags & REINDEX_REL_FORCE_INDEXES_CONSTANT)
3599+
persistence = RELPERSISTENCE_CONSTANT;
35953600
else
35963601
persistence = rel->rd_rel->relpersistence;
35973602

src/backend/catalog/storage.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ RelationCreateStorage(RelFileNode rnode, char relpersistence)
9393
needs_wal = false;
9494
break;
9595
case RELPERSISTENCE_PERMANENT:
96+
case RELPERSISTENCE_CONSTANT:
9697
backend = InvalidBackendId;
9798
needs_wal = true;
9899
break;

src/backend/commands/cluster.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1543,6 +1543,15 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
15431543
reindex_flags |= REINDEX_REL_FORCE_INDEXES_UNLOGGED;
15441544
else if (newrelpersistence == RELPERSISTENCE_PERMANENT)
15451545
reindex_flags |= REINDEX_REL_FORCE_INDEXES_PERMANENT;
1546+
else if (newrelpersistence == RELPERSISTENCE_CONSTANT)
1547+
{
1548+
/*
1549+
* Actually, there is no need in rebuilding CONSTANT indexes,
1550+
* but if someone forced CLUSTER or VACUUM FULL on CONSTANT
1551+
* relation, we must do it.
1552+
*/
1553+
reindex_flags |= REINDEX_REL_FORCE_INDEXES_CONSTANT;
1554+
}
15461555

15471556
reindex_relation(OIDOldHeap, reindex_flags, 0);
15481557

src/backend/commands/sequence.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,11 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
125125
ereport(ERROR,
126126
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
127127
errmsg("unlogged sequences are not supported")));
128+
/* CONSTANT sequences are not implemented -- not clear if useful. */
129+
if (seq->sequence->relpersistence == RELPERSISTENCE_CONSTANT)
130+
ereport(ERROR,
131+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
132+
errmsg("CONSTANT sequences are not supported")));
128133

129134
/*
130135
* If if_not_exists was given and a relation with the same name already

src/backend/commands/tablecmds.c

Lines changed: 126 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ typedef struct AlteredTableInfo
160160
bool new_notnull; /* T if we added new NOT NULL constraints */
161161
int rewrite; /* Reason for forced rewrite, if any */
162162
Oid newTableSpace; /* new tablespace; 0 means no change */
163-
bool chgPersistence; /* T if SET LOGGED/UNLOGGED is used */
163+
bool chgPersistence; /* T if SET LOGGED/UNLOGGED/CONSTANT is used */
164164
char newrelpersistence; /* if above is true */
165165
/* Objects to rebuild after completing ALTER TYPE operations */
166166
List *changedConstraintOids; /* OIDs of constraints to rebuild */
@@ -402,7 +402,8 @@ static void change_owner_recurse_to_sequences(Oid relationOid,
402402
static ObjectAddress ATExecClusterOn(Relation rel, const char *indexName,
403403
LOCKMODE lockmode);
404404
static void ATExecDropCluster(Relation rel, LOCKMODE lockmode);
405-
static bool ATPrepChangePersistence(Relation rel, bool toLogged);
405+
static void ATExecSetConstant(Relation rel, LOCKMODE lockmode);
406+
static bool ATPrepChangePersistence(Relation rel, char newrelpersistence);
406407
static void ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel,
407408
char *tablespacename, LOCKMODE lockmode);
408409
static void ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode);
@@ -3036,6 +3037,7 @@ AlterTableGetLockLevel(List *cmds)
30363037

30373038
case AT_SetLogged:
30383039
case AT_SetUnLogged:
3040+
case AT_SetConstant:
30393041
cmd_lockmode = AccessExclusiveLock;
30403042
break;
30413043

@@ -3258,7 +3260,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
32583260
break;
32593261
case AT_SetLogged: /* SET LOGGED */
32603262
ATSimplePermissions(rel, ATT_TABLE);
3261-
tab->chgPersistence = ATPrepChangePersistence(rel, true);
3263+
tab->chgPersistence = ATPrepChangePersistence(rel, RELPERSISTENCE_PERMANENT);
32623264
/* force rewrite if necessary; see comment in ATRewriteTables */
32633265
if (tab->chgPersistence)
32643266
{
@@ -3269,7 +3271,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
32693271
break;
32703272
case AT_SetUnLogged: /* SET UNLOGGED */
32713273
ATSimplePermissions(rel, ATT_TABLE);
3272-
tab->chgPersistence = ATPrepChangePersistence(rel, false);
3274+
tab->chgPersistence = ATPrepChangePersistence(rel, RELPERSISTENCE_UNLOGGED);
32733275
/* force rewrite if necessary; see comment in ATRewriteTables */
32743276
if (tab->chgPersistence)
32753277
{
@@ -3278,6 +3280,14 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
32783280
}
32793281
pass = AT_PASS_MISC;
32803282
break;
3283+
case AT_SetConstant: /* SET CONSTANT */
3284+
ATSimplePermissions(rel, ATT_TABLE);
3285+
tab->chgPersistence = ATPrepChangePersistence(rel, RELPERSISTENCE_CONSTANT);
3286+
/* We do not rewrite relation, just freeze it in ATExecSetConstant. */
3287+
if (tab->chgPersistence)
3288+
tab->newrelpersistence = RELPERSISTENCE_CONSTANT;
3289+
pass = AT_PASS_MISC;
3290+
break;
32813291
case AT_AddOids: /* SET WITH OIDS */
32823292
ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
32833293
if (!rel->rd_rel->relhasoids || recursing)
@@ -3579,6 +3589,9 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
35793589
case AT_SetLogged: /* SET LOGGED */
35803590
case AT_SetUnLogged: /* SET UNLOGGED */
35813591
break;
3592+
case AT_SetConstant: /* SET CONSTANT */
3593+
ATExecSetConstant(rel, lockmode);
3594+
break;
35823595
case AT_AddOids: /* SET WITH OIDS */
35833596
/* Use the ADD COLUMN code, unless prep decided to do nothing */
35843597
if (cmd->def != NULL)
@@ -6312,6 +6325,12 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
63126325
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
63136326
errmsg("constraints on temporary tables must involve temporary tables of this session")));
63146327
break;
6328+
case RELPERSISTENCE_CONSTANT:
6329+
ereport(ERROR,
6330+
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
6331+
errmsg("constraints on CONSTANT tables are not supported")));
6332+
break;
6333+
63156334
}
63166335

63176336
/*
@@ -9350,6 +9369,74 @@ ATExecDropCluster(Relation rel, LOCKMODE lockmode)
93509369
mark_index_clustered(rel, InvalidOid, false);
93519370
}
93529371

9372+
9373+
static void
9374+
setRelpersistenceConstant(Relation rel)
9375+
{
9376+
Relation pg_class;
9377+
Oid relid;
9378+
HeapTuple tuple;
9379+
9380+
relid = RelationGetRelid(rel);
9381+
9382+
pg_class = heap_open(RelationRelationId, RowExclusiveLock);
9383+
9384+
tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid));
9385+
9386+
if (!HeapTupleIsValid(tuple))
9387+
elog(ERROR, "cache lookup failed for relation %u", relid);
9388+
9389+
((Form_pg_class) GETSTRUCT(tuple))->relpersistence = RELPERSISTENCE_CONSTANT;
9390+
simple_heap_update(pg_class, &tuple->t_self, tuple);
9391+
9392+
/* keep catalog indexes current */
9393+
CatalogUpdateIndexes(pg_class, tuple);
9394+
/* Invalidate cached info about relation. */
9395+
CacheInvalidateRelcache(rel);
9396+
9397+
heap_close(pg_class, RowExclusiveLock);
9398+
heap_freetuple(tuple);
9399+
}
9400+
9401+
/*
9402+
* Change relation relpersistence to RELPERSISTENCE_CONSTANT.
9403+
*/
9404+
static void
9405+
ATExecSetConstant(Relation rel, LOCKMODE lockmode)
9406+
{
9407+
List *index_oid_list;
9408+
ListCell *i;
9409+
9410+
if (rel->rd_rel->relkind != RELKIND_RELATION
9411+
&& rel->rd_rel->relkind != RELKIND_TOASTVALUE)
9412+
elog(ERROR, "cannot apply SET CONSTANT to relation %s, because it's not a table.",
9413+
NameStr(rel->rd_rel->relname));
9414+
setRelpersistenceConstant(rel);
9415+
9416+
/* Find all the indexes belonging to this relation */
9417+
index_oid_list = RelationGetIndexList(rel);
9418+
9419+
/* For each index, change its relpersistence */
9420+
foreach(i, index_oid_list)
9421+
{
9422+
Relation indexRelation = index_open(lfirst_oid(i), lockmode);
9423+
setRelpersistenceConstant(indexRelation);
9424+
index_close(indexRelation, NoLock);
9425+
}
9426+
9427+
list_free(index_oid_list);
9428+
9429+
/* If it has a toast table, change its relpersistence.
9430+
* And also recursevily for toast_index
9431+
*/
9432+
if (rel->rd_rel->reltoastrelid != InvalidOid)
9433+
{
9434+
Relation toastRelation = heap_open(rel->rd_rel->reltoastrelid, lockmode);
9435+
ATExecSetConstant(toastRelation, lockmode);
9436+
heap_close(toastRelation, NoLock);
9437+
}
9438+
}
9439+
93539440
/*
93549441
* ALTER TABLE SET TABLESPACE
93559442
*/
@@ -11290,46 +11377,55 @@ ATExecGenericOptions(Relation rel, List *options)
1129011377
}
1129111378

1129211379
/*
11293-
* Preparation phase for SET LOGGED/UNLOGGED
11380+
* Preparation phase for SET LOGGED/UNLOGGED/CONSTANT
1129411381
*
1129511382
* This verifies that we're not trying to change a temp table. Also,
1129611383
* existing foreign key constraints are checked to avoid ending up with
1129711384
* permanent tables referencing unlogged tables.
11385+
* Foreign key constraints on CONSTANT tables are not allowed.
1129811386
*
1129911387
* Return value is false if the operation is a no-op (in which case the
1130011388
* checks are skipped), otherwise true.
1130111389
*/
1130211390
static bool
11303-
ATPrepChangePersistence(Relation rel, bool toLogged)
11391+
ATPrepChangePersistence(Relation rel, char newrelpersistence)
1130411392
{
1130511393
Relation pg_constraint;
1130611394
HeapTuple tuple;
1130711395
SysScanDesc scan;
1130811396
ScanKeyData skey[1];
11397+
bool toLogged = false;
11398+
11399+
/*
11400+
* When we track constraints, constant tables behaves just like
11401+
* permanent ones.
11402+
*/
11403+
if (newrelpersistence == RELPERSISTENCE_PERMANENT
11404+
|| newrelpersistence == RELPERSISTENCE_CONSTANT)
11405+
toLogged = true;
11406+
11407+
/* Nothing to do */
11408+
if (rel->rd_rel->relpersistence == newrelpersistence)
11409+
return false;
1130911410

1131011411
/*
11311-
* Disallow changing status for a temp table. Also verify whether we can
11312-
* get away with doing nothing; in such cases we don't need to run the
11313-
* checks below, either.
11412+
* Disallow changing status for a temp and constant tables.
1131411413
*/
1131511414
switch (rel->rd_rel->relpersistence)
1131611415
{
1131711416
case RELPERSISTENCE_TEMP:
1131811417
ereport(ERROR,
1131911418
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
11320-
errmsg("cannot change logged status of table \"%s\" because it is temporary",
11419+
errmsg("cannot change persistence of table \"%s\" because it is temporary",
1132111420
RelationGetRelationName(rel)),
1132211421
errtable(rel)));
1132311422
break;
11324-
case RELPERSISTENCE_PERMANENT:
11325-
if (toLogged)
11326-
/* nothing to do */
11327-
return false;
11328-
break;
11329-
case RELPERSISTENCE_UNLOGGED:
11330-
if (!toLogged)
11331-
/* nothing to do */
11332-
return false;
11423+
case RELPERSISTENCE_CONSTANT:
11424+
ereport(ERROR,
11425+
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
11426+
errmsg("cannot change persistence of table \"%s\" because it is constant",
11427+
RelationGetRelationName(rel)),
11428+
errtable(rel)));
1133311429
break;
1133411430
}
1133511431

@@ -11363,15 +11459,23 @@ ATPrepChangePersistence(Relation rel, bool toLogged)
1136311459
Relation foreignrel;
1136411460

1136511461
/* the opposite end of what we used as scankey */
11366-
foreignrelid = toLogged ? con->confrelid : con->conrelid;
11462+
foreignrelid = toLogged? con->confrelid : con->conrelid;
1136711463

1136811464
/* ignore if self-referencing */
1136911465
if (RelationGetRelid(rel) == foreignrelid)
1137011466
continue;
1137111467

1137211468
foreignrel = relation_open(foreignrelid, AccessShareLock);
1137311469

11374-
if (toLogged)
11470+
if (newrelpersistence == RELPERSISTENCE_CONSTANT)
11471+
ereport(ERROR,
11472+
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
11473+
errmsg("could not change table \"%s\" to constant because it references table \"%s\"",
11474+
RelationGetRelationName(rel),
11475+
RelationGetRelationName(foreignrel)),
11476+
errtableconstraint(rel, NameStr(con->conname))));
11477+
11478+
if (newrelpersistence == RELPERSISTENCE_PERMANENT)
1137511479
{
1137611480
if (foreignrel->rd_rel->relpersistence != RELPERSISTENCE_PERMANENT)
1137711481
ereport(ERROR,
@@ -11381,7 +11485,7 @@ ATPrepChangePersistence(Relation rel, bool toLogged)
1138111485
RelationGetRelationName(foreignrel)),
1138211486
errtableconstraint(rel, NameStr(con->conname))));
1138311487
}
11384-
else
11488+
if (newrelpersistence == RELPERSISTENCE_UNLOGGED)
1138511489
{
1138611490
if (foreignrel->rd_rel->relpersistence == RELPERSISTENCE_PERMANENT)
1138711491
ereport(ERROR,

src/backend/commands/view.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,11 @@ DefineView(ViewStmt *stmt, const char *queryString)
505505
ereport(ERROR,
506506
(errcode(ERRCODE_SYNTAX_ERROR),
507507
errmsg("views cannot be unlogged because they do not have storage")));
508+
/* CONSTANT views are not sensible. */
509+
if (stmt->view->relpersistence == RELPERSISTENCE_CONSTANT)
510+
ereport(ERROR,
511+
(errcode(ERRCODE_SYNTAX_ERROR),
512+
errmsg("views cannot be CONSTANT because they do not have storage")));
508513

509514
/*
510515
* If the user didn't explicitly ask for a temporary view, check whether

src/backend/optimizer/util/pathnode.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2977,6 +2977,16 @@ create_modifytable_path(PlannerInfo *root, RelOptInfo *rel,
29772977
Assert(returningLists == NIL ||
29782978
list_length(resultRelations) == list_length(returningLists));
29792979

2980+
foreach(lc, resultRelations)
2981+
{
2982+
Index rti = lfirst_int(lc);
2983+
RangeTblEntry *rte = planner_rt_fetch(rti, root);
2984+
2985+
/* RELPERSISTENCE_CONSTANT */
2986+
if (rte->relpersistence == 'c')
2987+
elog(ERROR, "This operation is not allowed on CONSTANT relations");
2988+
}
2989+
29802990
pathnode->path.pathtype = T_ModifyTable;
29812991
pathnode->path.parent = rel;
29822992
/* pathtarget is not interesting, just make it minimally valid */

src/backend/optimizer/util/plancat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
107107
relation = heap_open(relationObjectId, NoLock);
108108

109109
/* Temporary and unlogged relations are inaccessible during recovery. */
110-
if (!RelationNeedsWAL(relation) && RecoveryInProgress())
110+
if (!RelationNeedsWAL(relation) && RecoveryInProgress())
111111
ereport(ERROR,
112112
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
113113
errmsg("cannot access temporary or unlogged relations during recovery")));

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy