Commit e44beef7 authored by Tom Lane's avatar Tom Lane

Code review of CLUSTER patch. Clean up problems with relcache getting

confused, toasted data getting lost, etc.
parent 9bccdf17
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.145 2002/08/02 18:15:04 tgl Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.146 2002/08/11 21:17:34 tgl Exp $
--> -->
<appendix id="release"> <appendix id="release">
...@@ -24,6 +24,7 @@ CDATA means the content is "SGML-free", so you can write without ...@@ -24,6 +24,7 @@ CDATA means the content is "SGML-free", so you can write without
worries about funny characters. worries about funny characters.
--> -->
<literallayout><![CDATA[ <literallayout><![CDATA[
CLUSTER is no longer hazardous to your schema
COPY accepts a list of columns to copy COPY accepts a list of columns to copy
ALTER TABLE DROP COLUMN ALTER TABLE DROP COLUMN
CREATE OPERATOR CLASS/DROP OPERATOR CLASS CREATE OPERATOR CLASS/DROP OPERATOR CLASS
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.219 2002/08/06 02:36:33 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.220 2002/08/11 21:17:34 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
...@@ -198,7 +198,8 @@ SystemAttributeByName(const char *attname, bool relhasoids) ...@@ -198,7 +198,8 @@ SystemAttributeByName(const char *attname, bool relhasoids)
* Remove the system relation specific code to elsewhere eventually. * Remove the system relation specific code to elsewhere eventually.
* *
* If storage_create is TRUE then heap_storage_create is called here, * If storage_create is TRUE then heap_storage_create is called here,
* else caller must call heap_storage_create later. * else caller must call heap_storage_create later (or not at all,
* if the relation doesn't need physical storage).
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
Relation Relation
...@@ -291,7 +292,7 @@ heap_create(const char *relname, ...@@ -291,7 +292,7 @@ heap_create(const char *relname,
nailme); nailme);
/* /*
* have the storage manager create the relation. * have the storage manager create the relation's disk file, if wanted.
*/ */
if (storage_create) if (storage_create)
heap_storage_create(rel); heap_storage_create(rel);
...@@ -684,20 +685,21 @@ heap_create_with_catalog(const char *relname, ...@@ -684,20 +685,21 @@ heap_create_with_catalog(const char *relname,
tupdesc->tdhasoid = BoolToHasOid(relhasoids); tupdesc->tdhasoid = BoolToHasOid(relhasoids);
/* /*
* Tell heap_create not to create a physical file; we'll do that below * Create the relcache entry (mostly dummy at this point) and the
* after all our catalog updates are done. (This isn't really * physical disk file. (If we fail further down, it's the smgr's
* necessary anymore, but we may as well avoid the cycles of creating * responsibility to remove the disk file again.)
* and deleting the file in case we fail.) *
* NB: create a physical file only if it's not a view.
*/ */
new_rel_desc = heap_create(relname, new_rel_desc = heap_create(relname,
relnamespace, relnamespace,
tupdesc, tupdesc,
shared_relation, shared_relation,
false, (relkind != RELKIND_VIEW),
allow_system_table_mods); allow_system_table_mods);
/* Fetch the relation OID assigned by heap_create */ /* Fetch the relation OID assigned by heap_create */
new_rel_oid = new_rel_desc->rd_att->attrs[0]->attrelid; new_rel_oid = RelationGetRelid(new_rel_desc);
/* Assign an OID for the relation's tuple type */ /* Assign an OID for the relation's tuple type */
new_type_oid = newoid(); new_type_oid = newoid();
...@@ -761,12 +763,6 @@ heap_create_with_catalog(const char *relname, ...@@ -761,12 +763,6 @@ heap_create_with_catalog(const char *relname,
*/ */
StoreConstraints(new_rel_desc, tupdesc); StoreConstraints(new_rel_desc, tupdesc);
/*
* We create the disk file for this relation here
*/
if (relkind != RELKIND_VIEW)
heap_storage_create(new_rel_desc);
/* /*
* ok, the relation has been cataloged, so close our relations and * ok, the relation has been cataloged, so close our relations and
* return the oid of the newly created relation. * return the oid of the newly created relation.
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.188 2002/08/05 03:29:16 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.189 2002/08/11 21:17:34 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
...@@ -578,14 +578,18 @@ index_create(Oid heapRelationId, ...@@ -578,14 +578,18 @@ index_create(Oid heapRelationId,
indexTupDesc->tdhasoid = WITHOUTOID; indexTupDesc->tdhasoid = WITHOUTOID;
/* /*
* create the index relation (but don't create storage yet) * create the index relation's relcache entry and physical disk file.
* (If we fail further down, it's the smgr's responsibility to remove
* the disk file again.)
*/ */
indexRelation = heap_create(indexRelationName, indexRelation = heap_create(indexRelationName,
namespaceId, namespaceId,
indexTupDesc, indexTupDesc,
shared_relation, shared_relation,
false, true,
allow_system_table_mods); allow_system_table_mods);
/* Fetch the relation OID assigned by heap_create */
indexoid = RelationGetRelid(indexRelation); indexoid = RelationGetRelid(indexRelation);
/* /*
...@@ -611,11 +615,6 @@ index_create(Oid heapRelationId, ...@@ -611,11 +615,6 @@ index_create(Oid heapRelationId,
*/ */
UpdateRelationRelation(indexRelation); UpdateRelationRelation(indexRelation);
/*
* We create the disk file for this relation here
*/
heap_storage_create(indexRelation);
/* /*
* now update the object id's of all the attribute tuple forms in the * now update the object id's of all the attribute tuple forms in the
* index relation's tuple descriptor * index relation's tuple descriptor
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_depend.c,v 1.4 2002/08/05 03:29:16 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_depend.c,v 1.5 2002/08/11 21:17:34 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -121,15 +121,16 @@ recordMultipleDependencies(const ObjectAddress *depender, ...@@ -121,15 +121,16 @@ recordMultipleDependencies(const ObjectAddress *depender,
/* /*
* deleteDependencyRecordsFor -- delete all records with given depender * deleteDependencyRecordsFor -- delete all records with given depender
* classId/objectId. * classId/objectId. Returns the number of records deleted.
* *
* This is used when redefining an existing object. Links leading to the * This is used when redefining an existing object. Links leading to the
* object do not change, and links leading from it will be recreated * object do not change, and links leading from it will be recreated
* (possibly with some differences from before). * (possibly with some differences from before).
*/ */
void long
deleteDependencyRecordsFor(Oid classId, Oid objectId) deleteDependencyRecordsFor(Oid classId, Oid objectId)
{ {
long count = 0;
Relation depRel; Relation depRel;
ScanKeyData key[2]; ScanKeyData key[2];
SysScanDesc scan; SysScanDesc scan;
...@@ -150,11 +151,14 @@ deleteDependencyRecordsFor(Oid classId, Oid objectId) ...@@ -150,11 +151,14 @@ deleteDependencyRecordsFor(Oid classId, Oid objectId)
while (HeapTupleIsValid(tup = systable_getnext(scan))) while (HeapTupleIsValid(tup = systable_getnext(scan)))
{ {
simple_heap_delete(depRel, &tup->t_self); simple_heap_delete(depRel, &tup->t_self);
count++;
} }
systable_endscan(scan); systable_endscan(scan);
heap_close(depRel, RowExclusiveLock); heap_close(depRel, RowExclusiveLock);
return count;
} }
/* /*
......
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.128 2002/08/06 02:36:34 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.129 2002/08/11 21:17:34 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1038,11 +1038,6 @@ BufferReplace(BufferDesc *bufHdr) ...@@ -1038,11 +1038,6 @@ BufferReplace(BufferDesc *bufHdr)
* RelationGetNumberOfBlocks * RelationGetNumberOfBlocks
* Determines the current number of pages in the relation. * Determines the current number of pages in the relation.
* Side effect: relation->rd_nblocks is updated. * Side effect: relation->rd_nblocks is updated.
*
* Note:
* XXX may fail for huge relations.
* XXX should be elsewhere.
* XXX maybe should be hidden
*/ */
BlockNumber BlockNumber
RelationGetNumberOfBlocks(Relation relation) RelationGetNumberOfBlocks(Relation relation)
...@@ -1061,6 +1056,23 @@ RelationGetNumberOfBlocks(Relation relation) ...@@ -1061,6 +1056,23 @@ RelationGetNumberOfBlocks(Relation relation)
return relation->rd_nblocks; return relation->rd_nblocks;
} }
/*
* RelationUpdateNumberOfBlocks
* Forcibly update relation->rd_nblocks.
*
* If the relcache drops an entry for a temp relation, it must call this
* routine after recreating the relcache entry, so that rd_nblocks is
* re-sync'd with reality. See RelationGetNumberOfBlocks.
*/
void
RelationUpdateNumberOfBlocks(Relation relation)
{
if (relation->rd_rel->relkind == RELKIND_VIEW)
relation->rd_nblocks = 0;
else
relation->rd_nblocks = smgrnblocks(DEFAULT_SMGR, relation);
}
/* --------------------------------------------------------------------- /* ---------------------------------------------------------------------
* DropRelationBuffers * DropRelationBuffers
* *
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.171 2002/08/06 02:36:35 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.172 2002/08/11 21:17:35 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -860,11 +860,12 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo, ...@@ -860,11 +860,12 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo,
/* /*
* normal relations are not nailed into the cache; nor can a pre-existing * normal relations are not nailed into the cache; nor can a pre-existing
* relation be new or temp. * relation be new. It could be temp though. (Actually, it could be new
* too, but it's okay to forget that fact if forced to flush the entry.)
*/ */
relation->rd_isnailed = false; relation->rd_isnailed = false;
relation->rd_isnew = false; relation->rd_isnew = false;
relation->rd_istemp = false; relation->rd_istemp = isTempNamespace(relation->rd_rel->relnamespace);
/* /*
* initialize the tuple descriptor (relation->rd_att). * initialize the tuple descriptor (relation->rd_att).
...@@ -909,13 +910,23 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo, ...@@ -909,13 +910,23 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo,
relation->rd_fd = -1; relation->rd_fd = -1;
/* /*
* insert newly created relation into proper relcaches, restore memory * Insert newly created relation into relcache hash tables.
* context and return the new reldesc.
*/ */
oldcxt = MemoryContextSwitchTo(CacheMemoryContext); oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
RelationCacheInsert(relation); RelationCacheInsert(relation);
MemoryContextSwitchTo(oldcxt); MemoryContextSwitchTo(oldcxt);
/*
* If it's a temp rel, RelationGetNumberOfBlocks will assume that
* rd_nblocks is correct. Must forcibly update the block count when
* creating the relcache entry. But if we are doing a rebuild, don't
* do this yet; leave it to RelationClearRelation to do at the end.
* (Otherwise, an elog in RelationUpdateNumberOfBlocks would leave us
* with inconsistent relcache state.)
*/
if (relation->rd_istemp && oldrelation == NULL)
RelationUpdateNumberOfBlocks(relation);
return relation; return relation;
} }
...@@ -1601,8 +1612,7 @@ RelationClose(Relation relation) ...@@ -1601,8 +1612,7 @@ RelationClose(Relation relation)
#ifdef RELCACHE_FORCE_RELEASE #ifdef RELCACHE_FORCE_RELEASE
if (RelationHasReferenceCountZero(relation) && if (RelationHasReferenceCountZero(relation) &&
!relation->rd_isnew && !relation->rd_isnew)
!relation->rd_istemp)
RelationClearRelation(relation, false); RelationClearRelation(relation, false);
#endif #endif
} }
...@@ -1733,19 +1743,15 @@ RelationClearRelation(Relation relation, bool rebuild) ...@@ -1733,19 +1743,15 @@ RelationClearRelation(Relation relation, bool rebuild)
{ {
/* /*
* When rebuilding an open relcache entry, must preserve ref count * When rebuilding an open relcache entry, must preserve ref count
* and new/temp flags. Also attempt to preserve the tupledesc, * and rd_isnew flag. Also attempt to preserve the tupledesc,
* rewrite rules, and trigger substructures in place. Furthermore * rewrite rules, and trigger substructures in place.
* we save/restore rd_nblocks (in case it is a new/temp relation)
* *and* call RelationGetNumberOfBlocks (in case it isn't).
*/ */
int old_refcnt = relation->rd_refcnt; int old_refcnt = relation->rd_refcnt;
bool old_isnew = relation->rd_isnew; bool old_isnew = relation->rd_isnew;
bool old_istemp = relation->rd_istemp;
TupleDesc old_att = relation->rd_att; TupleDesc old_att = relation->rd_att;
RuleLock *old_rules = relation->rd_rules; RuleLock *old_rules = relation->rd_rules;
MemoryContext old_rulescxt = relation->rd_rulescxt; MemoryContext old_rulescxt = relation->rd_rulescxt;
TriggerDesc *old_trigdesc = relation->trigdesc; TriggerDesc *old_trigdesc = relation->trigdesc;
BlockNumber old_nblocks = relation->rd_nblocks;
RelationBuildDescInfo buildinfo; RelationBuildDescInfo buildinfo;
buildinfo.infotype = INFO_RELID; buildinfo.infotype = INFO_RELID;
...@@ -1764,7 +1770,6 @@ RelationClearRelation(Relation relation, bool rebuild) ...@@ -1764,7 +1770,6 @@ RelationClearRelation(Relation relation, bool rebuild)
} }
RelationSetReferenceCount(relation, old_refcnt); RelationSetReferenceCount(relation, old_refcnt);
relation->rd_isnew = old_isnew; relation->rd_isnew = old_isnew;
relation->rd_istemp = old_istemp;
if (equalTupleDescs(old_att, relation->rd_att)) if (equalTupleDescs(old_att, relation->rd_att))
{ {
FreeTupleDesc(relation->rd_att); FreeTupleDesc(relation->rd_att);
...@@ -1791,13 +1796,14 @@ RelationClearRelation(Relation relation, bool rebuild) ...@@ -1791,13 +1796,14 @@ RelationClearRelation(Relation relation, bool rebuild)
} }
else else
FreeTriggerDesc(old_trigdesc); FreeTriggerDesc(old_trigdesc);
relation->rd_nblocks = old_nblocks;
/* /*
* this is kind of expensive, but I think we must do it in case * Update rd_nblocks. This is kind of expensive, but I think we must
* relation has been truncated... * do it in case relation has been truncated... we definitely must
* do it if the rel is new or temp, since RelationGetNumberOfBlocks
* will subsequently assume that the block count is correct.
*/ */
relation->rd_nblocks = RelationGetNumberOfBlocks(relation); RelationUpdateNumberOfBlocks(relation);
} }
} }
...@@ -1811,18 +1817,19 @@ RelationFlushRelation(Relation relation) ...@@ -1811,18 +1817,19 @@ RelationFlushRelation(Relation relation)
{ {
bool rebuild; bool rebuild;
if (relation->rd_isnew || relation->rd_istemp) if (relation->rd_isnew)
{ {
/* /*
* New and temp relcache entries must always be rebuilt, not * New relcache entries are always rebuilt, not flushed; else we'd
* flushed; else we'd forget those two important status bits. * forget the "new" status of the relation, which is a useful
* optimization to have.
*/ */
rebuild = true; rebuild = true;
} }
else else
{ {
/* /*
* Nonlocal rels can be dropped from the relcache if not open. * Pre-existing rels can be dropped from the relcache if not open.
*/ */
rebuild = !RelationHasReferenceCountZero(relation); rebuild = !RelationHasReferenceCountZero(relation);
} }
...@@ -1921,7 +1928,7 @@ RelationCacheInvalidate(void) ...@@ -1921,7 +1928,7 @@ RelationCacheInvalidate(void)
relcacheInvalsReceived++; relcacheInvalsReceived++;
if (RelationHasReferenceCountZero(relation) && !relation->rd_istemp) if (RelationHasReferenceCountZero(relation))
{ {
/* Delete this entry immediately */ /* Delete this entry immediately */
RelationClearRelation(relation, false); RelationClearRelation(relation, false);
...@@ -1965,7 +1972,10 @@ AtEOXact_RelationCache(bool commit) ...@@ -1965,7 +1972,10 @@ AtEOXact_RelationCache(bool commit)
* *
* During commit, reset the flag to false, since we are now out of the * During commit, reset the flag to false, since we are now out of the
* creating transaction. During abort, simply delete the relcache * creating transaction. During abort, simply delete the relcache
* entry --- it isn't interesting any longer. * entry --- it isn't interesting any longer. (NOTE: if we have
* forgotten the isnew state of a new relation due to a forced cache
* flush, the entry will get deleted anyway by shared-cache-inval
* processing of the aborted pg_class insertion.)
*/ */
if (relation->rd_isnew) if (relation->rd_isnew)
{ {
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: dependency.h,v 1.3 2002/07/16 22:12:20 tgl Exp $ * $Id: dependency.h,v 1.4 2002/08/11 21:17:35 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -98,6 +98,6 @@ extern void recordMultipleDependencies(const ObjectAddress *depender, ...@@ -98,6 +98,6 @@ extern void recordMultipleDependencies(const ObjectAddress *depender,
int nreferenced, int nreferenced,
DependencyType behavior); DependencyType behavior);
extern void deleteDependencyRecordsFor(Oid classId, Oid objectId); extern long deleteDependencyRecordsFor(Oid classId, Oid objectId);
#endif /* DEPENDENCY_H */ #endif /* DEPENDENCY_H */
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: bufmgr.h,v 1.62 2002/08/06 02:36:35 tgl Exp $ * $Id: bufmgr.h,v 1.63 2002/08/11 21:17:35 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -161,6 +161,7 @@ extern void AtEOXact_Buffers(bool isCommit); ...@@ -161,6 +161,7 @@ extern void AtEOXact_Buffers(bool isCommit);
extern void FlushBufferPool(void); extern void FlushBufferPool(void);
extern BlockNumber BufferGetBlockNumber(Buffer buffer); extern BlockNumber BufferGetBlockNumber(Buffer buffer);
extern BlockNumber RelationGetNumberOfBlocks(Relation relation); extern BlockNumber RelationGetNumberOfBlocks(Relation relation);
extern void RelationUpdateNumberOfBlocks(Relation relation);
extern int FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock); extern int FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock);
extern void DropRelationBuffers(Relation rel); extern void DropRelationBuffers(Relation rel);
extern void DropRelFileNodeBuffers(RelFileNode rnode, bool istemp); extern void DropRelFileNodeBuffers(RelFileNode rnode, bool istemp);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: rel.h,v 1.61 2002/08/06 02:36:35 tgl Exp $ * $Id: rel.h,v 1.62 2002/08/11 21:17:35 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -113,6 +113,10 @@ typedef struct RelationData ...@@ -113,6 +113,10 @@ typedef struct RelationData
* InvalidBlockNumber */ * InvalidBlockNumber */
int rd_refcnt; /* reference count */ int rd_refcnt; /* reference count */
bool rd_isnew; /* rel was created in current xact */ bool rd_isnew; /* rel was created in current xact */
/*
* NOTE: rd_isnew should be relied on only for optimization purposes;
* it is possible for new-ness to be "forgotten" (eg, after CLUSTER).
*/
bool rd_istemp; /* rel uses the local buffer mgr */ bool rd_istemp; /* rel uses the local buffer mgr */
bool rd_isnailed; /* rel is nailed in cache */ bool rd_isnailed; /* rel is nailed in cache */
bool rd_indexfound; /* true if rd_indexlist is valid */ bool rd_indexfound; /* true if rd_indexlist is valid */
......
This diff is collapsed.
...@@ -8,6 +8,7 @@ CREATE TABLE clstr_tst_s (rf_a SERIAL PRIMARY KEY, ...@@ -8,6 +8,7 @@ CREATE TABLE clstr_tst_s (rf_a SERIAL PRIMARY KEY,
CREATE TABLE clstr_tst (a SERIAL PRIMARY KEY, CREATE TABLE clstr_tst (a SERIAL PRIMARY KEY,
b INT, b INT,
c TEXT, c TEXT,
d TEXT,
CONSTRAINT clstr_tst_con FOREIGN KEY (b) REFERENCES clstr_tst_s); CONSTRAINT clstr_tst_con FOREIGN KEY (b) REFERENCES clstr_tst_s);
CREATE INDEX clstr_tst_b ON clstr_tst (b); CREATE INDEX clstr_tst_b ON clstr_tst (b);
...@@ -55,24 +56,26 @@ INSERT INTO clstr_tst (b, c) VALUES (15, 'quince'); ...@@ -55,24 +56,26 @@ INSERT INTO clstr_tst (b, c) VALUES (15, 'quince');
INSERT INTO clstr_tst (b, c) VALUES (7, 'siete'); INSERT INTO clstr_tst (b, c) VALUES (7, 'siete');
INSERT INTO clstr_tst (b, c) VALUES (16, 'dieciseis'); INSERT INTO clstr_tst (b, c) VALUES (16, 'dieciseis');
INSERT INTO clstr_tst (b, c) VALUES (8, 'ocho'); INSERT INTO clstr_tst (b, c) VALUES (8, 'ocho');
INSERT INTO clstr_tst (b, c) VALUES (6, 'seis'); -- This entry is needed to test that TOASTED values are copied correctly.
INSERT INTO clstr_tst (b, c, d) VALUES (6, 'seis', repeat('xyzzy', 100000));
CLUSTER clstr_tst_c ON clstr_tst; CLUSTER clstr_tst_c ON clstr_tst;
SELECT * from clstr_tst; SELECT a,b,c,substring(d for 30), length(d) from clstr_tst;
SELECT * from clstr_tst ORDER BY a; SELECT a,b,c,substring(d for 30), length(d) from clstr_tst ORDER BY a;
SELECT * from clstr_tst ORDER BY b; SELECT a,b,c,substring(d for 30), length(d) from clstr_tst ORDER BY b;
SELECT * from clstr_tst ORDER BY c; SELECT a,b,c,substring(d for 30), length(d) from clstr_tst ORDER BY c;
-- Verify that inheritance link still works -- Verify that inheritance link still works
INSERT INTO clstr_tst_inh VALUES (0, 100, 'in child table'); INSERT INTO clstr_tst_inh VALUES (0, 100, 'in child table');
SELECT * from clstr_tst; SELECT a,b,c,substring(d for 30), length(d) from clstr_tst;
-- Verify that foreign key link still works -- Verify that foreign key link still works
INSERT INTO clstr_tst (b, c) VALUES (1111, 'this should fail'); INSERT INTO clstr_tst (b, c) VALUES (1111, 'this should fail');
SELECT conname FROM pg_constraint WHERE conrelid=(SELECT oid FROM pg_class SELECT conname FROM pg_constraint WHERE conrelid = 'clstr_tst'::regclass;
WHERE relname='clstr_tst');
SELECT relname FROM pg_class WHERE relname LIKE 'clstr_tst%' ORDER BY relname; SELECT relname, relkind,
EXISTS(SELECT 1 FROM pg_class WHERE oid = c.reltoastrelid) AS hastoast
FROM pg_class c WHERE relname LIKE 'clstr_tst%' ORDER BY relname;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment