Skip to content

Commit 6534444

Browse files
Jan WieckJan Wieck
Jan Wieck
authored and
Jan Wieck
committed
Changed TOAST relations to have relkind RELKIND_TOASTVALUE.
Special handling of TOAST relations during VACUUM. TOAST relations are vacuumed while the lock on the master table is still active. The ANALYZE flag doesn't propagate to their vacuuming because the toaster access routines allways use index access ignoring stats, so why compute them at all. Protection of TOAST relations against normal INSERT/UPDATE/DELETE while offering SELECT for debugging purposes. Jan
1 parent 01e1d8f commit 6534444

File tree

4 files changed

+75
-17
lines changed

4 files changed

+75
-17
lines changed

src/backend/catalog/index.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.122 2000/07/04 06:11:23 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.123 2000/07/05 16:17:37 wieck Exp $
1212
*
1313
*
1414
* INTERFACE ROUTINES
@@ -1335,7 +1335,8 @@ IndexesAreActive(Oid relid, bool confirmCommitted)
13351335

13361336
if (!LockClassinfoForUpdate(relid, &tuple, &buffer, confirmCommitted))
13371337
elog(ERROR, "IndexesAreActive couldn't lock %u", relid);
1338-
if (((Form_pg_class) GETSTRUCT(&tuple))->relkind != RELKIND_RELATION)
1338+
if (((Form_pg_class) GETSTRUCT(&tuple))->relkind != RELKIND_RELATION &&
1339+
((Form_pg_class) GETSTRUCT(&tuple))->relkind != RELKIND_TOASTVALUE)
13391340
elog(ERROR, "relation %u isn't an relation", relid);
13401341
isactive = ((Form_pg_class) GETSTRUCT(&tuple))->relhasindex;
13411342
ReleaseBuffer(buffer);

src/backend/commands/command.c

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.86 2000/07/05 13:50:59 wieck Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.87 2000/07/05 16:17:38 wieck Exp $
1212
*
1313
* NOTES
1414
* The PerformAddAttribute() code, like most of the relation
@@ -1319,14 +1319,14 @@ AlterTableCreateToastTable(const char *relationName, bool silent)
13191319
-1, 0, false);
13201320
TupleDescInitEntry(tupdesc, (AttrNumber) 3,
13211321
"chunk_data",
1322-
TEXTOID, /* XXX wouldn't BYTEAOID be better? */
1322+
BYTEAOID,
13231323
-1, 0, false);
13241324

1325-
/* XXX use RELKIND_TOASTVALUE here? */
13261325
/* XXX what if owning relation is temp? need we mark toasttable too? */
1327-
/* !!! No need to worry about temp. It'll go away when it's master */
1328-
/* table is deleted. Jan */
1329-
heap_create_with_catalog(toast_relname, tupdesc, RELKIND_RELATION,
1326+
/* XXX How do we know? No naming collisions possible because names */
1327+
/* are OID based. And toast table disappears when master table */
1328+
/* is destroyed. So what is it good for anyway? Jan */
1329+
heap_create_with_catalog(toast_relname, tupdesc, RELKIND_TOASTVALUE,
13301330
false, true);
13311331

13321332
/* make the toast relation visible, else index creation will fail */
@@ -1368,6 +1368,39 @@ AlterTableCreateToastTable(const char *relationName, bool silent)
13681368

13691369
heap_freetuple(reltup);
13701370

1371+
/*
1372+
* Finally update the toast relations pg_class tuple to say
1373+
* it has an index.
1374+
*/
1375+
reltup = SearchSysCacheTuple(RELNAME, PointerGetDatum(toast_relname),
1376+
0, 0, 0);
1377+
if (!HeapTupleIsValid(reltup))
1378+
elog(ERROR, "ALTER TABLE: just created toast relation \"%s\" not found",
1379+
toast_relname);
1380+
classtuple.t_self = reltup->t_self;
1381+
switch (heap_mark4update(class_rel, &classtuple, &buffer))
1382+
{
1383+
case HeapTupleSelfUpdated:
1384+
case HeapTupleMayBeUpdated:
1385+
break;
1386+
default:
1387+
elog(ERROR, "couldn't lock pg_class tuple");
1388+
}
1389+
reltup = heap_copytuple(&classtuple);
1390+
ReleaseBuffer(buffer);
1391+
1392+
((Form_pg_class) GETSTRUCT(reltup))->relhasindex = true;
1393+
heap_update(class_rel, &reltup->t_self, reltup, NULL);
1394+
1395+
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs);
1396+
CatalogIndexInsert(ridescs, Num_pg_class_indices, class_rel, reltup);
1397+
CatalogCloseIndices(Num_pg_class_indices, ridescs);
1398+
1399+
heap_freetuple(reltup);
1400+
1401+
/*
1402+
* Close relatons and make changes visible
1403+
*/
13711404
heap_close(class_rel, NoLock);
13721405
heap_close(rel, NoLock);
13731406

src/backend/commands/vacuum.c

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.161 2000/06/28 03:31:28 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.162 2000/07/05 16:17:38 wieck Exp $
1212
*
1313
1414
*-------------------------------------------------------------------------
@@ -58,7 +58,7 @@ static void vacuum_init(void);
5858
static void vacuum_shutdown(void);
5959
static void vac_vacuum(NameData *VacRelP, bool analyze, List *anal_cols2);
6060
static VRelList getrels(NameData *VacRelP);
61-
static void vacuum_rel(Oid relid, bool analyze);
61+
static void vacuum_rel(Oid relid, bool analyze, bool is_toastrel);
6262
static void scan_heap(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages, VacPageList fraged_pages);
6363
static void repair_frag(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages, VacPageList fraged_pages, int nindices, Relation *Irel);
6464
static void vacuum_heap(VRelStats *vacrelstats, Relation onerel, VacPageList vacpagelist);
@@ -235,7 +235,7 @@ vac_vacuum(NameData *VacRelP, bool analyze, List *anal_cols2)
235235
/* vacuum each heap relation */
236236
for (cur = vrl; cur != (VRelList) NULL; cur = cur->vrl_next)
237237
{
238-
vacuum_rel(cur->vrl_relid, analyze);
238+
vacuum_rel(cur->vrl_relid, analyze, false);
239239
/* analyze separately so locking is minimized */
240240
if (analyze)
241241
analyze_rel(cur->vrl_relid, anal_cols2, MESSAGE_LEVEL);
@@ -347,7 +347,7 @@ getrels(NameData *VacRelP)
347347
* us to lock the entire database during one pass of the vacuum cleaner.
348348
*/
349349
static void
350-
vacuum_rel(Oid relid, bool analyze)
350+
vacuum_rel(Oid relid, bool analyze, bool is_toastrel)
351351
{
352352
HeapTuple tuple;
353353
Relation onerel;
@@ -361,8 +361,10 @@ vacuum_rel(Oid relid, bool analyze)
361361
i;
362362
VRelStats *vacrelstats;
363363
bool reindex = false;
364+
Oid toast_relid;
364365

365-
StartTransactionCommand();
366+
if (!is_toastrel)
367+
StartTransactionCommand();
366368

367369
/*
368370
* Check for user-requested abort. Note we want this to be inside a
@@ -380,7 +382,8 @@ vacuum_rel(Oid relid, bool analyze)
380382
0, 0, 0);
381383
if (!HeapTupleIsValid(tuple))
382384
{
383-
CommitTransactionCommand();
385+
if (!is_toastrel)
386+
CommitTransactionCommand();
384387
return;
385388
}
386389

@@ -392,14 +395,21 @@ vacuum_rel(Oid relid, bool analyze)
392395
*/
393396
onerel = heap_open(relid, AccessExclusiveLock);
394397

398+
/*
399+
* Remember the relations TOAST relation for later
400+
*
401+
*/
402+
toast_relid = onerel->rd_rel->reltoastrelid;
403+
395404
#ifndef NO_SECURITY
396405
if (!pg_ownercheck(GetPgUserName(), RelationGetRelationName(onerel),
397406
RELNAME))
398407
{
399408
elog(NOTICE, "Skipping \"%s\" --- only table owner can VACUUM it",
400409
RelationGetRelationName(onerel));
401410
heap_close(onerel, AccessExclusiveLock);
402-
CommitTransactionCommand();
411+
if (!is_toastrel)
412+
CommitTransactionCommand();
403413
return;
404414
}
405415
#endif
@@ -488,8 +498,18 @@ vacuum_rel(Oid relid, bool analyze)
488498
update_relstats(vacrelstats->relid, vacrelstats->num_pages,
489499
vacrelstats->num_tuples, vacrelstats->hasindex, vacrelstats);
490500

501+
/* If the relation has a secondary toast one, vacuum that too
502+
* while we still hold the lock on the master table. We don't
503+
* need to propagate "analyze" to it, because the toaster
504+
* allways uses hardcoded index access and statistics are
505+
* totally unimportant for toast relations
506+
*/
507+
if (toast_relid != InvalidOid)
508+
vacuum_rel(toast_relid, false, true);
509+
491510
/* next command frees attribute stats */
492-
CommitTransactionCommand();
511+
if (!is_toastrel)
512+
CommitTransactionCommand();
493513
}
494514

495515
/*

src/backend/executor/execMain.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
*
2828
*
2929
* IDENTIFICATION
30-
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.120 2000/07/05 13:22:25 wieck Exp $
30+
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.121 2000/07/05 16:17:43 wieck Exp $
3131
*
3232
*-------------------------------------------------------------------------
3333
*/
@@ -720,6 +720,10 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
720720
elog(ERROR, "You can't change sequence relation %s",
721721
RelationGetRelationName(resultRelationDesc));
722722

723+
if (resultRelationDesc->rd_rel->relkind == RELKIND_TOASTVALUE)
724+
elog(ERROR, "You can't change toast relation %s",
725+
RelationGetRelationName(resultRelationDesc));
726+
723727
resultRelationInfo = makeNode(RelationInfo);
724728
resultRelationInfo->ri_RangeTableIndex = resultRelationIndex;
725729
resultRelationInfo->ri_RelationDesc = resultRelationDesc;

0 commit comments

Comments
 (0)