vacuum-full_20091207.patch
application/octet-stream
Filename: vacuum-full_20091207.patch
Type: application/octet-stream
Part: 0
Message:
Re: New VACUUM FULL
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: context
| File | + | − |
|---|---|---|
| doc/src/sgml/ref/vacuumdb.sgml | 13 | 1 |
| doc/src/sgml/ref/vacuum.sgml | 22 | 1 |
| src/backend/commands/cluster.c | 128 | 92 |
| src/backend/commands/vacuum.c | 21 | 4 |
| src/backend/parser/gram.y | 3 | 1 |
| src/bin/scripts/vacuumdb.c | 79 | 25 |
| src/include/commands/cluster.h | 2 | 1 |
| src/include/nodes/parsenodes.h | 2 | 1 |
| src/include/parser/kwlist.h | 1 | 0 |
| src/test/regress/expected/select_views_1.out | 14 | 14 |
| src/test/regress/expected/select_views.out | 14 | 14 |
| src/test/regress/expected/vacuum.out | 48 | 0 |
| src/test/regress/sql/select_views.sql | 1 | 1 |
| src/test/regress/sql/vacuum.sql | 44 | 0 |
diff -cprN head/doc/src/sgml/ref/vacuum.sgml work/doc/src/sgml/ref/vacuum.sgml
*** head/doc/src/sgml/ref/vacuum.sgml 2009-11-17 06:32:06.000000000 +0900
--- work/doc/src/sgml/ref/vacuum.sgml 2009-12-07 13:35:34.259453210 +0900
*************** PostgreSQL documentation
*** 21,27 ****
<refsynopsisdiv>
<synopsis>
! VACUUM [ ( { FULL | FREEZE | VERBOSE | ANALYZE } [, ...] ) ] [ <replaceable class="PARAMETER">table</replaceable> [ (<replaceable class="PARAMETER">column</replaceable> [, ...] ) ] ]
VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ <replaceable class="PARAMETER">table</replaceable> ]
VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ <replaceable class="PARAMETER">table</replaceable> [ (<replaceable class="PARAMETER">column</replaceable> [, ...] ) ] ]
</synopsis>
--- 21,27 ----
<refsynopsisdiv>
<synopsis>
! VACUUM [ ( { FULL [ INPLACE ] | FREEZE | VERBOSE | ANALYZE } [, ...] ) ] [ <replaceable class="PARAMETER">table</replaceable> [ (<replaceable class="PARAMETER">column</replaceable> [, ...] ) ] ]
VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ <replaceable class="PARAMETER">table</replaceable> ]
VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ <replaceable class="PARAMETER">table</replaceable> [ (<replaceable class="PARAMETER">column</replaceable> [, ...] ) ] ]
</synopsis>
*************** VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] A
*** 86,91 ****
--- 86,112 ----
Selects <quote>full</quote> vacuum, which can reclaim more
space, but takes much longer and exclusively locks the table.
</para>
+ <para>
+ For user tables, all table data and indexes are rewritten. This
+ method requires extra disk space in which to write the new data,
+ and is generally useful when a significant amount of space needs
+ to be reclaimed from within the table.
+ </para>
+ <para>
+ For system tables, all table data and indexes are modified in
+ place to reclaim space. This method may require less disk space
+ for the table data than <command>VACUUM FULL</command> on a
+ comparable user table, but the indexes will grow which may
+ counteract that benefit. Additionally, the operation is often
+ slower than <command>VACUUM FULL</command> on a comparable user
+ table.
+ </para>
+ <para>
+ If <literal>FULL INPLACE</literal> is specified, the space is
+ reclaimed in the same manner as a system table, even if it is a
+ user table. Specifying <literal>INPLACE</literal> explicitly is
+ rarely useful.
+ </para>
</listitem>
</varlistentry>
diff -cprN head/doc/src/sgml/ref/vacuumdb.sgml work/doc/src/sgml/ref/vacuumdb.sgml
*** head/doc/src/sgml/ref/vacuumdb.sgml 2009-11-28 02:41:26.000000000 +0900
--- work/doc/src/sgml/ref/vacuumdb.sgml 2009-12-07 13:35:34.259453210 +0900
*************** PostgreSQL documentation
*** 24,29 ****
--- 24,30 ----
<command>vacuumdb</command>
<arg rep="repeat"><replaceable>connection-option</replaceable></arg>
<group><arg>--full</arg><arg>-f</arg></group>
+ <group><arg>--inplace</arg><arg>-i</arg></group>
<group><arg>--verbose</arg><arg>-v</arg></group>
<group><arg>--analyze</arg><arg>-z</arg></group>
<group><arg>--freeze</arg><arg>-F</arg></group>
*************** PostgreSQL documentation
*** 36,41 ****
--- 37,43 ----
<arg rep="repeat"><replaceable>connection-options</replaceable></arg>
<group><arg>--all</arg><arg>-a</arg></group>
<group><arg>--full</arg><arg>-f</arg></group>
+ <group><arg>--inplace</arg><arg>-i</arg></group>
<group><arg>--verbose</arg><arg>-v</arg></group>
<group><arg>--analyze</arg><arg>-z</arg></group>
<group><arg>--freeze</arg><arg>-F</arg></group>
*************** PostgreSQL documentation
*** 111,117 ****
<term><option>--full</option></term>
<listitem>
<para>
! Perform <quote>full</quote> vacuuming.
</para>
</listitem>
</varlistentry>
--- 113,129 ----
<term><option>--full</option></term>
<listitem>
<para>
! Perform <quote>full replace</quote> vacuuming.
! </para>
! </listitem>
! </varlistentry>
!
! <varlistentry>
! <term><option>-i</option></term>
! <term><option>--inplace</option></term>
! <listitem>
! <para>
! Perform <quote>full inplace</quote> vacuuming.
</para>
</listitem>
</varlistentry>
diff -cprN head/src/backend/commands/cluster.c work/src/backend/commands/cluster.c
*** head/src/backend/commands/cluster.c 2009-10-06 04:24:36.000000000 +0900
--- work/src/backend/commands/cluster.c 2009-12-07 13:35:34.260468926 +0900
*************** typedef struct
*** 61,69 ****
} RelToCluster;
! static void cluster_rel(RelToCluster *rv, bool recheck, bool verbose);
! static void rebuild_relation(Relation OldHeap, Oid indexOid);
! static TransactionId copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex);
static List *get_tables_to_cluster(MemoryContext cluster_context);
--- 61,70 ----
} RelToCluster;
! static void rebuild_relation(Relation OldHeap, Oid indexOid,
! int freeze_min_age, int freeze_table_age);
! static TransactionId copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap,
! Oid OIDOldIndex, int freeze_min_age, int freeze_table_age);
static List *get_tables_to_cluster(MemoryContext cluster_context);
*************** cluster(ClusterStmt *stmt, bool isTopLev
*** 101,107 ****
Oid tableOid,
indexOid = InvalidOid;
Relation rel;
- RelToCluster rvtc;
/* Find and lock the table */
rel = heap_openrv(stmt->relation, AccessExclusiveLock);
--- 102,107 ----
*************** cluster(ClusterStmt *stmt, bool isTopLev
*** 169,183 ****
stmt->indexname, stmt->relation->relname)));
}
- /* All other checks are done in cluster_rel() */
- rvtc.tableOid = tableOid;
- rvtc.indexOid = indexOid;
-
/* close relation, keep lock till commit */
heap_close(rel, NoLock);
/* Do the job */
! cluster_rel(&rvtc, false, stmt->verbose);
}
else
{
--- 169,179 ----
stmt->indexname, stmt->relation->relname)));
}
/* close relation, keep lock till commit */
heap_close(rel, NoLock);
/* Do the job */
! cluster_rel(tableOid, indexOid, false, stmt->verbose, -1, -1);
}
else
{
*************** cluster(ClusterStmt *stmt, bool isTopLev
*** 226,232 ****
StartTransactionCommand();
/* functions in indexes may want a snapshot set */
PushActiveSnapshot(GetTransactionSnapshot());
! cluster_rel(rvtc, true, stmt->verbose);
PopActiveSnapshot();
CommitTransactionCommand();
}
--- 222,228 ----
StartTransactionCommand();
/* functions in indexes may want a snapshot set */
PushActiveSnapshot(GetTransactionSnapshot());
! cluster_rel(rvtc->tableOid, rvtc->indexOid, true, stmt->verbose, -1, -1);
PopActiveSnapshot();
CommitTransactionCommand();
}
*************** cluster(ClusterStmt *stmt, bool isTopLev
*** 253,260 ****
* the new table, it's better to create the indexes afterwards than to fill
* them incrementally while we load the table.
*/
! static void
! cluster_rel(RelToCluster *rvtc, bool recheck, bool verbose)
{
Relation OldHeap;
--- 249,257 ----
* the new table, it's better to create the indexes afterwards than to fill
* them incrementally while we load the table.
*/
! void
! cluster_rel(Oid tableOid, Oid indexOid, bool recheck, bool verbose,
! int freeze_min_age, int freeze_table_age)
{
Relation OldHeap;
*************** cluster_rel(RelToCluster *rvtc, bool rec
*** 267,273 ****
* case, since cluster() already did it.) The index lock is taken inside
* check_index_is_clusterable.
*/
! OldHeap = try_relation_open(rvtc->tableOid, AccessExclusiveLock);
/* If the table has gone away, we can skip processing it */
if (!OldHeap)
--- 264,270 ----
* case, since cluster() already did it.) The index lock is taken inside
* check_index_is_clusterable.
*/
! OldHeap = try_relation_open(tableOid, AccessExclusiveLock);
/* If the table has gone away, we can skip processing it */
if (!OldHeap)
*************** cluster_rel(RelToCluster *rvtc, bool rec
*** 287,293 ****
Form_pg_index indexForm;
/* Check that the user still owns the relation */
! if (!pg_class_ownercheck(rvtc->tableOid, GetUserId()))
{
relation_close(OldHeap, AccessExclusiveLock);
return;
--- 284,290 ----
Form_pg_index indexForm;
/* Check that the user still owns the relation */
! if (!pg_class_ownercheck(tableOid, GetUserId()))
{
relation_close(OldHeap, AccessExclusiveLock);
return;
*************** cluster_rel(RelToCluster *rvtc, bool rec
*** 308,360 ****
return;
}
! /*
! * Check that the index still exists
! */
! if (!SearchSysCacheExists(RELOID,
! ObjectIdGetDatum(rvtc->indexOid),
! 0, 0, 0))
{
! relation_close(OldHeap, AccessExclusiveLock);
! return;
! }
! /*
! * Check that the index is still the one with indisclustered set.
! */
! tuple = SearchSysCache(INDEXRELID,
! ObjectIdGetDatum(rvtc->indexOid),
! 0, 0, 0);
! if (!HeapTupleIsValid(tuple)) /* probably can't happen */
! {
! relation_close(OldHeap, AccessExclusiveLock);
! return;
! }
! indexForm = (Form_pg_index) GETSTRUCT(tuple);
! if (!indexForm->indisclustered)
! {
ReleaseSysCache(tuple);
- relation_close(OldHeap, AccessExclusiveLock);
- return;
}
- ReleaseSysCache(tuple);
}
! /* Check index is valid to cluster on */
! check_index_is_clusterable(OldHeap, rvtc->indexOid, recheck);
/* rebuild_relation does all the dirty work */
ereport(verbose ? INFO : DEBUG2,
(errmsg("clustering \"%s.%s\"",
get_namespace_name(RelationGetNamespace(OldHeap)),
RelationGetRelationName(OldHeap))));
! rebuild_relation(OldHeap, rvtc->indexOid);
/* NB: rebuild_relation does heap_close() on OldHeap */
}
/*
! * Verify that the specified index is a legitimate index to cluster on
*
* Side effect: obtains exclusive lock on the index. The caller should
* already have exclusive lock on the table, so the index lock is likely
--- 305,360 ----
return;
}
! if (OidIsValid(indexOid))
{
! /*
! * Check that the index still exists
! */
! if (!SearchSysCacheExists(RELOID,
! ObjectIdGetDatum(indexOid),
! 0, 0, 0))
! {
! relation_close(OldHeap, AccessExclusiveLock);
! return;
! }
! /*
! * Check that the index is still the one with indisclustered set.
! */
! tuple = SearchSysCache(INDEXRELID,
! ObjectIdGetDatum(indexOid),
! 0, 0, 0);
! if (!HeapTupleIsValid(tuple)) /* probably can't happen */
! {
! relation_close(OldHeap, AccessExclusiveLock);
! return;
! }
! indexForm = (Form_pg_index) GETSTRUCT(tuple);
! if (!indexForm->indisclustered)
! {
! ReleaseSysCache(tuple);
! relation_close(OldHeap, AccessExclusiveLock);
! return;
! }
ReleaseSysCache(tuple);
}
}
! /* Check heap and index are valid to cluster on */
! check_index_is_clusterable(OldHeap, indexOid, recheck);
/* rebuild_relation does all the dirty work */
ereport(verbose ? INFO : DEBUG2,
(errmsg("clustering \"%s.%s\"",
get_namespace_name(RelationGetNamespace(OldHeap)),
RelationGetRelationName(OldHeap))));
! rebuild_relation(OldHeap, indexOid, freeze_min_age, freeze_table_age);
/* NB: rebuild_relation does heap_close() on OldHeap */
}
/*
! * Verify that the specified heap and index are valid to cluster on
*
* Side effect: obtains exclusive lock on the index. The caller should
* already have exclusive lock on the table, so the index lock is likely
*************** check_index_is_clusterable(Relation OldH
*** 366,371 ****
--- 366,403 ----
{
Relation OldIndex;
+ /*
+ * Disallow clustering system relations. This will definitely NOT work
+ * for shared relations (we have no way to update pg_class rows in other
+ * databases), nor for nailed-in-cache relations (the relfilenode values
+ * for those are hardwired, see relcache.c). It might work for other
+ * system relations, but I ain't gonna risk it.
+ */
+ if (IsSystemRelation(OldHeap))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("\"%s\" is a system catalog",
+ RelationGetRelationName(OldHeap))));
+
+ /*
+ * Don't allow cluster on temp tables of other backends ... their local
+ * buffer manager is not going to cope.
+ */
+ if (RELATION_IS_OTHER_TEMP(OldHeap))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot cluster temporary tables of other sessions")));
+
+ /*
+ * Also check for active uses of the relation in the current transaction,
+ * including open scans and pending AFTER trigger events.
+ */
+ CheckTableNotInUse(OldHeap, "CLUSTER");
+
+ /* Skip checks for index if not specified. */
+ if (!OidIsValid(indexOid))
+ return;
+
OldIndex = index_open(indexOid, AccessExclusiveLock);
/*
*************** check_index_is_clusterable(Relation OldH
*** 448,481 ****
errmsg("cannot cluster on invalid index \"%s\"",
RelationGetRelationName(OldIndex))));
- /*
- * Disallow clustering system relations. This will definitely NOT work
- * for shared relations (we have no way to update pg_class rows in other
- * databases), nor for nailed-in-cache relations (the relfilenode values
- * for those are hardwired, see relcache.c). It might work for other
- * system relations, but I ain't gonna risk it.
- */
- if (IsSystemRelation(OldHeap))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("\"%s\" is a system catalog",
- RelationGetRelationName(OldHeap))));
-
- /*
- * Don't allow cluster on temp tables of other backends ... their local
- * buffer manager is not going to cope.
- */
- if (RELATION_IS_OTHER_TEMP(OldHeap))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("cannot cluster temporary tables of other sessions")));
-
- /*
- * Also check for active uses of the relation in the current transaction,
- * including open scans and pending AFTER trigger events.
- */
- CheckTableNotInUse(OldHeap, "CLUSTER");
-
/* Drop relcache refcnt on OldIndex, but keep lock */
index_close(OldIndex, NoLock);
}
--- 480,485 ----
*************** mark_index_clustered(Relation rel, Oid i
*** 565,571 ****
* NB: this routine closes OldHeap at the right time; caller should not.
*/
static void
! rebuild_relation(Relation OldHeap, Oid indexOid)
{
Oid tableOid = RelationGetRelid(OldHeap);
Oid tableSpace = OldHeap->rd_rel->reltablespace;
--- 569,576 ----
* NB: this routine closes OldHeap at the right time; caller should not.
*/
static void
! rebuild_relation(Relation OldHeap, Oid indexOid,
! int freeze_min_age, int freeze_table_age)
{
Oid tableOid = RelationGetRelid(OldHeap);
Oid tableSpace = OldHeap->rd_rel->reltablespace;
*************** rebuild_relation(Relation OldHeap, Oid i
*** 576,582 ****
Relation newrel;
/* Mark the correct index as clustered */
! mark_index_clustered(OldHeap, indexOid);
/* Close relcache entry, but keep lock until transaction commit */
heap_close(OldHeap, NoLock);
--- 581,588 ----
Relation newrel;
/* Mark the correct index as clustered */
! if (OidIsValid(indexOid))
! mark_index_clustered(OldHeap, indexOid);
/* Close relcache entry, but keep lock until transaction commit */
heap_close(OldHeap, NoLock);
*************** rebuild_relation(Relation OldHeap, Oid i
*** 599,605 ****
/*
* Copy the heap data into the new table in the desired order.
*/
! frozenXid = copy_heap_data(OIDNewHeap, tableOid, indexOid);
/* To make the new heap's data visible (probably not needed?). */
CommandCounterIncrement();
--- 605,612 ----
/*
* Copy the heap data into the new table in the desired order.
*/
! frozenXid = copy_heap_data(OIDNewHeap, tableOid, indexOid,
! freeze_min_age, freeze_table_age);
/* To make the new heap's data visible (probably not needed?). */
CommandCounterIncrement();
*************** make_new_heap(Oid OIDOldHeap, const char
*** 758,764 ****
* freeze cutoff point for the tuples.
*/
static TransactionId
! copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex)
{
Relation NewHeap,
OldHeap,
--- 765,772 ----
* freeze cutoff point for the tuples.
*/
static TransactionId
! copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex,
! int freeze_min_age, int freeze_table_age)
{
Relation NewHeap,
OldHeap,
*************** copy_heap_data(Oid OIDNewHeap, Oid OIDOl
*** 768,775 ****
int natts;
Datum *values;
bool *isnull;
! IndexScanDesc scan;
! HeapTuple tuple;
bool use_wal;
TransactionId OldestXmin;
TransactionId FreezeXid;
--- 776,783 ----
int natts;
Datum *values;
bool *isnull;
! IndexScanDesc indexScan;
! HeapScanDesc heapScan;
bool use_wal;
TransactionId OldestXmin;
TransactionId FreezeXid;
*************** copy_heap_data(Oid OIDNewHeap, Oid OIDOl
*** 780,786 ****
*/
NewHeap = heap_open(OIDNewHeap, AccessExclusiveLock);
OldHeap = heap_open(OIDOldHeap, AccessExclusiveLock);
! OldIndex = index_open(OIDOldIndex, AccessExclusiveLock);
/*
* Their tuple descriptors should be exactly alike, but here we only need
--- 788,797 ----
*/
NewHeap = heap_open(OIDNewHeap, AccessExclusiveLock);
OldHeap = heap_open(OIDOldHeap, AccessExclusiveLock);
! if (OidIsValid(OIDOldIndex))
! OldIndex = index_open(OIDOldIndex, AccessExclusiveLock);
! else
! OldIndex = NULL;
/*
* Their tuple descriptors should be exactly alike, but here we only need
*************** copy_heap_data(Oid OIDNewHeap, Oid OIDOl
*** 809,816 ****
* freeze_min_age to avoid having CLUSTER freeze tuples earlier than a
* plain VACUUM would.
*/
! vacuum_set_xid_limits(-1, -1, OldHeap->rd_rel->relisshared,
! &OldestXmin, &FreezeXid, NULL);
/*
* FreezeXid will become the table's new relfrozenxid, and that mustn't go
--- 820,827 ----
* freeze_min_age to avoid having CLUSTER freeze tuples earlier than a
* plain VACUUM would.
*/
! vacuum_set_xid_limits(freeze_min_age, freeze_table_age,
! OldHeap->rd_rel->relisshared, &OldestXmin, &FreezeXid, NULL);
/*
* FreezeXid will become the table's new relfrozenxid, and that mustn't go
*************** copy_heap_data(Oid OIDNewHeap, Oid OIDOl
*** 828,852 ****
* copied, we scan with SnapshotAny and use HeapTupleSatisfiesVacuum for
* the visibility test.
*/
! scan = index_beginscan(OldHeap, OldIndex,
SnapshotAny, 0, (ScanKey) NULL);
! while ((tuple = index_getnext(scan, ForwardScanDirection)) != NULL)
{
HeapTuple copiedTuple;
bool isdead;
int i;
CHECK_FOR_INTERRUPTS();
! /* Since we used no scan keys, should never need to recheck */
! if (scan->xs_recheck)
! elog(ERROR, "CLUSTER does not support lossy index conditions");
! LockBuffer(scan->xs_cbuf, BUFFER_LOCK_SHARE);
! switch (HeapTupleSatisfiesVacuum(tuple->t_data, OldestXmin,
! scan->xs_cbuf))
{
case HEAPTUPLE_DEAD:
/* Definitely dead */
--- 839,884 ----
* copied, we scan with SnapshotAny and use HeapTupleSatisfiesVacuum for
* the visibility test.
*/
! if (OldIndex != NULL)
! indexScan = index_beginscan(OldHeap, OldIndex,
SnapshotAny, 0, (ScanKey) NULL);
+ else
+ heapScan = heap_beginscan(OldHeap, SnapshotAny, 0, (ScanKey) NULL);
! for (;;)
{
+ HeapTuple tuple;
HeapTuple copiedTuple;
+ Buffer buf;
bool isdead;
int i;
CHECK_FOR_INTERRUPTS();
! if (OldIndex != NULL)
! {
! tuple = index_getnext(indexScan, ForwardScanDirection);
! if (tuple == NULL)
! break;
! /* Since we used no scan keys, should never need to recheck */
! if (indexScan->xs_recheck)
! elog(ERROR, "CLUSTER does not support lossy index conditions");
! buf = indexScan->xs_cbuf;
! }
! else
! {
! tuple = heap_getnext(heapScan, ForwardScanDirection);
! if (tuple == NULL)
! break;
!
! buf = heapScan->rs_cbuf;
! }
!
! LockBuffer(buf, BUFFER_LOCK_SHARE);
!
! switch (HeapTupleSatisfiesVacuum(tuple->t_data, OldestXmin, buf))
{
case HEAPTUPLE_DEAD:
/* Definitely dead */
*************** copy_heap_data(Oid OIDNewHeap, Oid OIDOl
*** 888,894 ****
break;
}
! LockBuffer(scan->xs_cbuf, BUFFER_LOCK_UNLOCK);
if (isdead)
{
--- 920,926 ----
break;
}
! LockBuffer(buf, BUFFER_LOCK_UNLOCK);
if (isdead)
{
*************** copy_heap_data(Oid OIDNewHeap, Oid OIDOl
*** 932,938 ****
heap_freetuple(copiedTuple);
}
! index_endscan(scan);
/* Write out any remaining tuples, and fsync if needed */
end_heap_rewrite(rwstate);
--- 964,973 ----
heap_freetuple(copiedTuple);
}
! if (OldIndex != NULL)
! index_endscan(indexScan);
! else
! heap_endscan(heapScan);
/* Write out any remaining tuples, and fsync if needed */
end_heap_rewrite(rwstate);
*************** copy_heap_data(Oid OIDNewHeap, Oid OIDOl
*** 940,946 ****
pfree(values);
pfree(isnull);
! index_close(OldIndex, NoLock);
heap_close(OldHeap, NoLock);
heap_close(NewHeap, NoLock);
--- 975,982 ----
pfree(values);
pfree(isnull);
! if (OldIndex != NULL)
! index_close(OldIndex, NoLock);
heap_close(OldHeap, NoLock);
heap_close(NewHeap, NoLock);
diff -cprN head/src/backend/commands/vacuum.c work/src/backend/commands/vacuum.c
*** head/src/backend/commands/vacuum.c 2009-11-17 06:32:06.000000000 +0900
--- work/src/backend/commands/vacuum.c 2009-12-07 13:35:34.262449953 +0900
***************
*** 29,38 ****
--- 29,40 ----
#include "access/visibilitymap.h"
#include "access/xact.h"
#include "access/xlog.h"
+ #include "catalog/catalog.h"
#include "catalog/namespace.h"
#include "catalog/pg_database.h"
#include "catalog/pg_namespace.h"
#include "catalog/storage.h"
+ #include "commands/cluster.h"
#include "commands/dbcommands.h"
#include "commands/vacuum.h"
#include "executor/executor.h"
*************** vacuum(VacuumStmt *vacstmt, Oid relid, b
*** 301,306 ****
--- 303,310 ----
Assert((vacstmt->options & VACOPT_VACUUM) ||
!(vacstmt->options & (VACOPT_FULL | VACOPT_FREEZE)));
Assert((vacstmt->options & VACOPT_ANALYZE) || vacstmt->va_cols == NIL);
+ Assert((vacstmt->options & VACOPT_FULL) ||
+ !(vacstmt->options & VACOPT_INPLACE));
stmttype = (vacstmt->options & VACOPT_VACUUM) ? "VACUUM" : "ANALYZE";
*************** vacuum_rel(Oid relid, VacuumStmt *vacstm
*** 1192,1209 ****
SetUserIdAndContext(onerel->rd_rel->relowner, true);
/*
! * Do the actual work --- either FULL or "lazy" vacuum
*/
! if (vacstmt->options & VACOPT_FULL)
heldoff = full_vacuum_rel(onerel, vacstmt);
else
! heldoff = lazy_vacuum_rel(onerel, vacstmt, vac_strategy, scanned_all);
/* Restore userid */
SetUserIdAndContext(save_userid, save_secdefcxt);
/* all done with this class, but hold lock until commit */
! relation_close(onerel, NoLock);
/*
* Complete the transaction and free all temporary memory used.
--- 1196,1226 ----
SetUserIdAndContext(onerel->rd_rel->relowner, true);
/*
! * Do the actual work --- either FULL, FULL INPLACE, or "lazy" vacuum.
! * We can only use FULL INPLACE vacuum for system relations.
*/
! if (!(vacstmt->options & VACOPT_FULL))
! heldoff = lazy_vacuum_rel(onerel, vacstmt, vac_strategy, scanned_all);
! else if ((vacstmt->options & VACOPT_INPLACE) || IsSystemRelation(onerel))
heldoff = full_vacuum_rel(onerel, vacstmt);
else
! {
! /* close relation before clustering, but hold lock until commit */
! relation_close(onerel, NoLock);
! onerel = NULL;
!
! cluster_rel(relid, InvalidOid, false,
! (vacstmt->options & VACOPT_VERBOSE) != 0,
! vacstmt->freeze_min_age, vacstmt->freeze_table_age);
! heldoff = false;
! }
/* Restore userid */
SetUserIdAndContext(save_userid, save_secdefcxt);
/* all done with this class, but hold lock until commit */
! if (onerel)
! relation_close(onerel, NoLock);
/*
* Complete the transaction and free all temporary memory used.
diff -cprN head/src/backend/parser/gram.y work/src/backend/parser/gram.y
*** head/src/backend/parser/gram.y 2009-11-21 05:38:10.000000000 +0900
--- work/src/backend/parser/gram.y 2009-12-07 13:35:34.264455198 +0900
*************** static TypeName *TableFuncTypeName(List
*** 486,492 ****
IDENTITY_P IF_P ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IN_P
INCLUDING INCREMENT INDEX INDEXES INHERIT INHERITS INITIALLY INLINE_P
! INNER_P INOUT INPUT_P INSENSITIVE INSERT INSTEAD INT_P INTEGER
INTERSECT INTERVAL INTO INVOKER IS ISNULL ISOLATION
JOIN
--- 486,492 ----
IDENTITY_P IF_P ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IN_P
INCLUDING INCREMENT INDEX INDEXES INHERIT INHERITS INITIALLY INLINE_P
! INNER_P INOUT INPLACE INPUT_P INSENSITIVE INSERT INSTEAD INT_P INTEGER
INTERSECT INTERVAL INTO INVOKER IS ISNULL ISOLATION
JOIN
*************** vacuum_option_elem:
*** 6708,6713 ****
--- 6708,6714 ----
| VERBOSE { $$ = VACOPT_VERBOSE; }
| FREEZE { $$ = VACOPT_FREEZE; }
| FULL { $$ = VACOPT_FULL; }
+ | FULL INPLACE { $$ = VACOPT_FULL | VACOPT_INPLACE; }
;
AnalyzeStmt:
*************** unreserved_keyword:
*** 10649,10654 ****
--- 10650,10656 ----
| INHERIT
| INHERITS
| INLINE_P
+ | INPLACE
| INPUT_P
| INSENSITIVE
| INSERT
diff -cprN head/src/bin/scripts/vacuumdb.c work/src/bin/scripts/vacuumdb.c
*** head/src/bin/scripts/vacuumdb.c 2009-10-16 19:38:25.000000000 +0900
--- work/src/bin/scripts/vacuumdb.c 2009-12-07 13:35:34.265552562 +0900
***************
*** 14,28 ****
#include "common.h"
! static void vacuum_one_database(const char *dbname, bool full, bool verbose, bool analyze,
! bool freeze, const char *table,
const char *host, const char *port,
const char *username, enum trivalue prompt_password,
const char *progname, bool echo);
! static void vacuum_all_databases(bool full, bool verbose, bool analyze, bool freeze,
! const char *host, const char *port,
! const char *username, enum trivalue prompt_password,
! const char *progname, bool echo, bool quiet);
static void help(const char *progname);
--- 14,29 ----
#include "common.h"
! static void vacuum_one_database(const char *dbname, bool full, bool inplace,
! bool verbose, bool analyze, bool freeze, const char *table,
const char *host, const char *port,
const char *username, enum trivalue prompt_password,
const char *progname, bool echo);
! static void vacuum_all_databases(bool full, bool inplace,
! bool verbose, bool analyze, bool freeze,
! const char *host, const char *port,
! const char *username, enum trivalue prompt_password,
! const char *progname, bool echo, bool quiet);
static void help(const char *progname);
*************** main(int argc, char *argv[])
*** 45,50 ****
--- 46,52 ----
{"table", required_argument, NULL, 't'},
{"full", no_argument, NULL, 'f'},
{"verbose", no_argument, NULL, 'v'},
+ {"inplace", no_argument, NULL, 'i'},
{NULL, 0, NULL, 0}
};
*************** main(int argc, char *argv[])
*** 65,77 ****
char *table = NULL;
bool full = false;
bool verbose = false;
progname = get_progname(argv[0]);
set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
handle_help_version_opts(argc, argv, "vacuumdb", help);
! while ((c = getopt_long(argc, argv, "h:p:U:wWeqd:zaFt:fv", long_options, &optindex)) != -1)
{
switch (c)
{
--- 67,80 ----
char *table = NULL;
bool full = false;
bool verbose = false;
+ bool inplace = false;
progname = get_progname(argv[0]);
set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
handle_help_version_opts(argc, argv, "vacuumdb", help);
! while ((c = getopt_long(argc, argv, "h:p:U:wWeqd:zaFt:fiv", long_options, &optindex)) != -1)
{
switch (c)
{
*************** main(int argc, char *argv[])
*** 117,122 ****
--- 120,128 ----
case 'v':
verbose = true;
break;
+ case 'i':
+ inplace = true;
+ break;
default:
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
exit(1);
*************** main(int argc, char *argv[])
*** 137,142 ****
--- 143,156 ----
exit(1);
}
+ /* INPLACE option requires FULL option. */
+ if (inplace && !full)
+ {
+ fprintf(stderr, _("%s: -i, --inplace option requires -f, --full\n"),
+ progname);
+ exit(1);
+ }
+
setup_cancel_handler();
if (alldb)
*************** main(int argc, char *argv[])
*** 154,160 ****
exit(1);
}
! vacuum_all_databases(full, verbose, analyze, freeze,
host, port, username, prompt_password,
progname, echo, quiet);
}
--- 168,174 ----
exit(1);
}
! vacuum_all_databases(full, inplace, verbose, analyze, freeze,
host, port, username, prompt_password,
progname, echo, quiet);
}
*************** main(int argc, char *argv[])
*** 170,177 ****
dbname = get_user_name(progname);
}
! vacuum_one_database(dbname, full, verbose, analyze, freeze, table,
! host, port, username, prompt_password,
progname, echo);
}
--- 184,191 ----
dbname = get_user_name(progname);
}
! vacuum_one_database(dbname, full, inplace, verbose, analyze, freeze,
! table, host, port, username, prompt_password,
progname, echo);
}
*************** main(int argc, char *argv[])
*** 180,187 ****
static void
! vacuum_one_database(const char *dbname, bool full, bool verbose, bool analyze,
! bool freeze, const char *table,
const char *host, const char *port,
const char *username, enum trivalue prompt_password,
const char *progname, bool echo)
--- 194,201 ----
static void
! vacuum_one_database(const char *dbname, bool full, bool inplace, bool verbose,
! bool analyze, bool freeze, const char *table,
const char *host, const char *port,
const char *username, enum trivalue prompt_password,
const char *progname, bool echo)
*************** vacuum_one_database(const char *dbname,
*** 189,211 ****
PQExpBufferData sql;
PGconn *conn;
initPQExpBuffer(&sql);
appendPQExpBuffer(&sql, "VACUUM");
! if (full)
! appendPQExpBuffer(&sql, " FULL");
! if (freeze)
! appendPQExpBuffer(&sql, " FREEZE");
! if (verbose)
! appendPQExpBuffer(&sql, " VERBOSE");
! if (analyze)
! appendPQExpBuffer(&sql, " ANALYZE");
if (table)
appendPQExpBuffer(&sql, " %s", table);
appendPQExpBuffer(&sql, ";\n");
- conn = connectDatabase(dbname, host, port, username, prompt_password, progname);
if (!executeMaintenanceCommand(conn, sql.data, echo))
{
if (table)
--- 203,264 ----
PQExpBufferData sql;
PGconn *conn;
+ int version;
+ bool first_opt = true;
initPQExpBuffer(&sql);
+ conn = connectDatabase(dbname, host, port, username, prompt_password, progname);
+ version = PQserverVersion(conn);
+
appendPQExpBuffer(&sql, "VACUUM");
!
! if (version >= 80500)
! {
! if (full)
! {
! appendPQExpBuffer(&sql, "%sFULL%s", first_opt ? " (" : ", ",
! inplace ? " INPLACE" : "");
! first_opt = false;
! }
! if (freeze)
! {
! appendPQExpBuffer(&sql, "%sFREEZE", first_opt ? " (" : ", ");
! first_opt = false;
! }
! if (verbose)
! {
! appendPQExpBuffer(&sql, "%sVERBOSE", first_opt ? " (" : ", ");
! first_opt = false;
! }
! if (analyze)
! {
! appendPQExpBuffer(&sql, "%sANALYZE", first_opt ? " (" : ", ");
! first_opt = false;
! }
! if (!first_opt)
! appendPQExpBuffer(&sql, ")");
! }
! else
! {
! /*
! * On older servers, VACUUM FULL is equivalent to VACUUM (FULL
! * INPLACE) on newer servers, so we can ignore 'inplace'.
! */
! if (full)
! appendPQExpBuffer(&sql, " FULL");
! if (freeze)
! appendPQExpBuffer(&sql, " FREEZE");
! if (verbose)
! appendPQExpBuffer(&sql, " VERBOSE");
! if (analyze)
! appendPQExpBuffer(&sql, " ANALYZE");
! }
!
if (table)
appendPQExpBuffer(&sql, " %s", table);
appendPQExpBuffer(&sql, ";\n");
if (!executeMaintenanceCommand(conn, sql.data, echo))
{
if (table)
*************** vacuum_one_database(const char *dbname,
*** 223,230 ****
static void
! vacuum_all_databases(bool full, bool verbose, bool analyze, bool freeze,
! const char *host, const char *port,
const char *username, enum trivalue prompt_password,
const char *progname, bool echo, bool quiet)
{
--- 276,283 ----
static void
! vacuum_all_databases(bool full, bool inplace, bool verbose, bool analyze,
! bool freeze, const char *host, const char *port,
const char *username, enum trivalue prompt_password,
const char *progname, bool echo, bool quiet)
{
*************** vacuum_all_databases(bool full, bool ver
*** 246,253 ****
fflush(stdout);
}
! vacuum_one_database(dbname, full, verbose, analyze, freeze, NULL,
! host, port, username, prompt_password,
progname, echo);
}
--- 299,306 ----
fflush(stdout);
}
! vacuum_one_database(dbname, full, inplace, verbose, analyze, freeze,
! NULL, host, port, username, prompt_password,
progname, echo);
}
*************** help(const char *progname)
*** 267,272 ****
--- 320,326 ----
printf(_(" -e, --echo show the commands being sent to the server\n"));
printf(_(" -f, --full do full vacuuming\n"));
printf(_(" -F, --freeze freeze row transaction information\n"));
+ printf(_(" -i, --inplace do full inplace vacuuming\n"));
printf(_(" -q, --quiet don't write any messages\n"));
printf(_(" -t, --table='TABLE[(COLUMNS)]' vacuum specific table only\n"));
printf(_(" -v, --verbose write a lot of output\n"));
diff -cprN head/src/include/commands/cluster.h work/src/include/commands/cluster.h
*** head/src/include/commands/cluster.h 2009-01-02 02:23:58.000000000 +0900
--- work/src/include/commands/cluster.h 2009-12-07 13:35:34.266552905 +0900
***************
*** 18,24 ****
extern void cluster(ClusterStmt *stmt, bool isTopLevel);
!
extern void check_index_is_clusterable(Relation OldHeap, Oid indexOid,
bool recheck);
extern void mark_index_clustered(Relation rel, Oid indexOid);
--- 18,25 ----
extern void cluster(ClusterStmt *stmt, bool isTopLevel);
! extern void cluster_rel(Oid tableOid, Oid indexOid, bool recheck,
! bool verbose, int freeze_min_age, int freeze_table_age);
extern void check_index_is_clusterable(Relation OldHeap, Oid indexOid,
bool recheck);
extern void mark_index_clustered(Relation rel, Oid indexOid);
diff -cprN head/src/include/nodes/parsenodes.h work/src/include/nodes/parsenodes.h
*** head/src/include/nodes/parsenodes.h 2009-11-21 05:38:11.000000000 +0900
--- work/src/include/nodes/parsenodes.h 2009-12-07 13:35:34.267449827 +0900
*************** typedef enum VacuumOption
*** 2222,2228 ****
VACOPT_ANALYZE = 1 << 1, /* do ANALYZE */
VACOPT_VERBOSE = 1 << 2, /* print progress info */
VACOPT_FREEZE = 1 << 3, /* FREEZE option */
! VACOPT_FULL = 1 << 4 /* FULL (non-concurrent) vacuum */
} VacuumOption;
typedef struct VacuumStmt
--- 2222,2229 ----
VACOPT_ANALYZE = 1 << 1, /* do ANALYZE */
VACOPT_VERBOSE = 1 << 2, /* print progress info */
VACOPT_FREEZE = 1 << 3, /* FREEZE option */
! VACOPT_FULL = 1 << 4, /* FULL (non-concurrent) vacuum */
! VACOPT_INPLACE = 1 << 5 /* traditional FULL INPLACE vacuum */
} VacuumOption;
typedef struct VacuumStmt
diff -cprN head/src/include/parser/kwlist.h work/src/include/parser/kwlist.h
*** head/src/include/parser/kwlist.h 2009-11-06 08:24:27.000000000 +0900
--- work/src/include/parser/kwlist.h 2009-12-07 13:35:34.267449827 +0900
*************** PG_KEYWORD("initially", INITIALLY, RESER
*** 192,197 ****
--- 192,198 ----
PG_KEYWORD("inline", INLINE_P, UNRESERVED_KEYWORD)
PG_KEYWORD("inner", INNER_P, TYPE_FUNC_NAME_KEYWORD)
PG_KEYWORD("inout", INOUT, COL_NAME_KEYWORD)
+ PG_KEYWORD("inplace", INPLACE, UNRESERVED_KEYWORD)
PG_KEYWORD("input", INPUT_P, UNRESERVED_KEYWORD)
PG_KEYWORD("insensitive", INSENSITIVE, UNRESERVED_KEYWORD)
PG_KEYWORD("insert", INSERT, UNRESERVED_KEYWORD)
diff -cprN head/src/test/regress/expected/select_views.out work/src/test/regress/expected/select_views.out
*** head/src/test/regress/expected/select_views.out 2004-04-02 06:59:44.000000000 +0900
--- work/src/test/regress/expected/select_views.out 2009-12-07 13:56:45.296699410 +0900
***************
*** 2,10 ****
-- SELECT_VIEWS
-- test the views defined in CREATE_VIEWS
--
! SELECT * FROM street;
name | thepath | cname
------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------
Access Rd 25 | [(-121.9283,37.894),(-121.9283,37.9)] | Oakland
Ada St | [(-122.2487,37.398),(-122.2496,37.401)] | Lafayette
Agua Fria Creek | [(-121.9254,37.922),(-121.9281,37.889)] | Oakland
--- 2,23 ----
-- SELECT_VIEWS
-- test the views defined in CREATE_VIEWS
--
! SELECT * FROM street ORDER BY name;
name | thepath | cname
------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------
+ 100th Ave | [(-122.1657,37.429),(-122.1647,37.432)] | Oakland
+ 107th Ave | [(-122.1555,37.403),(-122.1531,37.41)] | Oakland
+ 14th St | [(-122.299,37.147),(-122.3,37.148)] | Lafayette
+ 19th Ave | [(-122.2366,37.897),(-122.2359,37.905)] | Berkeley
+ 1st St | [(-121.75508,37.89294),(-121.753581,37.90031)] | Oakland
+ 5th St | [(-122.278,37),(-122.2792,37.005),(-122.2803,37.009)] | Lafayette
+ 5th St | [(-122.296,37.615),(-122.2953,37.598)] | Berkeley
+ 82nd Ave | [(-122.1695,37.596),(-122.1681,37.603)] | Berkeley
+ 85th Ave | [(-122.1877,37.466),(-122.186,37.476)] | Oakland
+ 89th Ave | [(-122.1822,37.459),(-122.1803,37.471)] | Oakland
+ 98th Ave | [(-122.1568,37.498),(-122.1558,37.502)] | Oakland
+ 98th Ave | [(-122.1693,37.438),(-122.1682,37.444)] | Oakland
+ 98th Ave | [(-122.2001,37.258),(-122.1974,37.27)] | Lafayette
Access Rd 25 | [(-121.9283,37.894),(-121.9283,37.9)] | Oakland
Ada St | [(-122.2487,37.398),(-122.2496,37.401)] | Lafayette
Agua Fria Creek | [(-121.9254,37.922),(-121.9281,37.889)] | Oakland
*************** SELECT * FROM street;
*** 325,343 ****
Wisconsin St | [(-122.1994,37.017),(-122.1975,37.998),(-122.1971,37.994)] | Oakland
Wisconsin St | [(-122.1994,37.017),(-122.1975,37.998),(-122.1971,37.994)] | Berkeley
Wp Railroad | [(-122.254,37.902),(-122.2506,37.891)] | Berkeley
- 100th Ave | [(-122.1657,37.429),(-122.1647,37.432)] | Oakland
- 107th Ave | [(-122.1555,37.403),(-122.1531,37.41)] | Oakland
- 14th St | [(-122.299,37.147),(-122.3,37.148)] | Lafayette
- 19th Ave | [(-122.2366,37.897),(-122.2359,37.905)] | Berkeley
- 1st St | [(-121.75508,37.89294),(-121.753581,37.90031)] | Oakland
- 5th St | [(-122.278,37),(-122.2792,37.005),(-122.2803,37.009)] | Lafayette
- 5th St | [(-122.296,37.615),(-122.2953,37.598)] | Berkeley
- 82nd Ave | [(-122.1695,37.596),(-122.1681,37.603)] | Berkeley
- 85th Ave | [(-122.1877,37.466),(-122.186,37.476)] | Oakland
- 89th Ave | [(-122.1822,37.459),(-122.1803,37.471)] | Oakland
- 98th Ave | [(-122.1568,37.498),(-122.1558,37.502)] | Oakland
- 98th Ave | [(-122.1693,37.438),(-122.1682,37.444)] | Oakland
- 98th Ave | [(-122.2001,37.258),(-122.1974,37.27)] | Lafayette
(333 rows)
SELECT name, #thepath FROM iexit ORDER BY 1, 2;
--- 338,343 ----
diff -cprN head/src/test/regress/expected/select_views_1.out work/src/test/regress/expected/select_views_1.out
*** head/src/test/regress/expected/select_views_1.out 2004-04-02 06:59:45.000000000 +0900
--- work/src/test/regress/expected/select_views_1.out 2009-12-07 13:56:56.592452335 +0900
***************
*** 2,10 ****
-- SELECT_VIEWS
-- test the views defined in CREATE_VIEWS
--
! SELECT * FROM street;
name | thepath | cname
------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------
Access Rd 25 | [(-121.9283,37.894),(-121.9283,37.9)] | Oakland
Ada St | [(-122.2487,37.398),(-122.2496,37.401)] | Lafayette
Agua Fria Creek | [(-121.9254,37.922),(-121.9281,37.889)] | Oakland
--- 2,23 ----
-- SELECT_VIEWS
-- test the views defined in CREATE_VIEWS
--
! SELECT * FROM street ORDER BY name;
name | thepath | cname
------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------
+ 100th Ave | [(-122.1657,37.429),(-122.1647,37.432)] | Oakland
+ 107th Ave | [(-122.1555,37.403),(-122.1531,37.41)] | Oakland
+ 14th St | [(-122.299,37.147),(-122.3,37.148)] | Lafayette
+ 19th Ave | [(-122.2366,37.897),(-122.2359,37.905)] | Berkeley
+ 1st St | [(-121.75508,37.89294),(-121.753581,37.90031)] | Oakland
+ 5th St | [(-122.278,37),(-122.2792,37.005),(-122.2803,37.009)] | Lafayette
+ 5th St | [(-122.296,37.615),(-122.2953,37.598)] | Berkeley
+ 82nd Ave | [(-122.1695,37.596),(-122.1681,37.603)] | Berkeley
+ 85th Ave | [(-122.1877,37.466),(-122.186,37.476)] | Oakland
+ 89th Ave | [(-122.1822,37.459),(-122.1803,37.471)] | Oakland
+ 98th Ave | [(-122.1568,37.498),(-122.1558,37.502)] | Oakland
+ 98th Ave | [(-122.1693,37.438),(-122.1682,37.444)] | Oakland
+ 98th Ave | [(-122.2001,37.258),(-122.1974,37.27)] | Lafayette
Access Rd 25 | [(-121.9283,37.894),(-121.9283,37.9)] | Oakland
Ada St | [(-122.2487,37.398),(-122.2496,37.401)] | Lafayette
Agua Fria Creek | [(-121.9254,37.922),(-121.9281,37.889)] | Oakland
*************** SELECT * FROM street;
*** 325,343 ****
Wisconsin St | [(-122.1994,37.017),(-122.1975,37.998),(-122.1971,37.994)] | Oakland
Wisconsin St | [(-122.1994,37.017),(-122.1975,37.998),(-122.1971,37.994)] | Berkeley
Wp Railroad | [(-122.254,37.902),(-122.2506,37.891)] | Berkeley
- 100th Ave | [(-122.1657,37.429),(-122.1647,37.432)] | Oakland
- 107th Ave | [(-122.1555,37.403),(-122.1531,37.41)] | Oakland
- 14th St | [(-122.299,37.147),(-122.3,37.148)] | Lafayette
- 19th Ave | [(-122.2366,37.897),(-122.2359,37.905)] | Berkeley
- 1st St | [(-121.75508,37.89294),(-121.753581,37.90031)] | Oakland
- 5th St | [(-122.278,37),(-122.2792,37.005),(-122.2803,37.009)] | Lafayette
- 5th St | [(-122.296,37.615),(-122.2953,37.598)] | Berkeley
- 82nd Ave | [(-122.1695,37.596),(-122.1681,37.603)] | Berkeley
- 85th Ave | [(-122.1877,37.466),(-122.186,37.476)] | Oakland
- 89th Ave | [(-122.1822,37.459),(-122.1803,37.471)] | Oakland
- 98th Ave | [(-122.1568,37.498),(-122.1558,37.502)] | Oakland
- 98th Ave | [(-122.1693,37.438),(-122.1682,37.444)] | Oakland
- 98th Ave | [(-122.2001,37.258),(-122.1974,37.27)] | Lafayette
(333 rows)
SELECT name, #thepath FROM iexit ORDER BY 1, 2;
--- 338,343 ----
diff -cprN head/src/test/regress/expected/vacuum.out work/src/test/regress/expected/vacuum.out
*** head/src/test/regress/expected/vacuum.out 2009-11-17 06:32:07.000000000 +0900
--- work/src/test/regress/expected/vacuum.out 2009-12-07 14:17:21.882427000 +0900
*************** SELECT * FROM vactst;
*** 57,60 ****
--- 57,108 ----
(0 rows)
VACUUM (FULL, FREEZE) vactst;
+ VACUUM (ANALYZE, FULL INPLACE) vactst;
+ CREATE TABLE vaccluster (i INT PRIMARY KEY);
+ NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "vaccluster_pkey" for table "vaccluster"
+ ALTER TABLE vaccluster CLUSTER ON vaccluster_pkey;
+ INSERT INTO vaccluster SELECT * FROM vactst;
+ CREATE TEMP TABLE vacid (
+ relid regclass,
+ filenode_0 oid,
+ filenode_1 oid,
+ filenode_2 oid,
+ filenode_3 oid
+ );
+ INSERT INTO vacid (relid, filenode_0)
+ SELECT oid, relfilenode FROM pg_class WHERE oid::regclass IN (
+ 'pg_am', -- normal catalog
+ 'pg_class', -- fundamental catalog
+ 'pg_database', -- shared catalog
+ 'vaccluster' , -- clustered table
+ 'vacid', -- temp table
+ 'vactst' -- normal table
+ );
+ CLUSTER; -- only clusterd table should be changed
+ UPDATE vacid SET filenode_1 = relfilenode
+ FROM pg_class WHERE oid = relid;
+ VACUUM (FULL INPLACE); -- all tables should not be changed
+ UPDATE vacid SET filenode_2 = relfilenode
+ FROM pg_class WHERE oid = relid;
+ VACUUM FULL; -- only non-system tables should be changed
+ UPDATE vacid SET filenode_3 = relfilenode
+ FROM pg_class WHERE oid = relid;
+ SELECT relid,
+ filenode_0 <> filenode_1 AS cluster,
+ filenode_1 <> filenode_2 AS full_inplace,
+ filenode_2 <> filenode_3 AS full
+ FROM vacid
+ ORDER BY relid::text;
+ relid | cluster | full_inplace | full
+ -------------+---------+--------------+------
+ pg_am | f | f | f
+ pg_class | f | f | f
+ pg_database | f | f | f
+ vaccluster | t | f | t
+ vacid | f | f | t
+ vactst | f | f | t
+ (6 rows)
+
+ DROP TABLE vaccluster;
+ DROP TABLE vacid;
DROP TABLE vactst;
diff -cprN head/src/test/regress/sql/select_views.sql work/src/test/regress/sql/select_views.sql
*** head/src/test/regress/sql/select_views.sql 2000-01-06 15:41:55.000000000 +0900
--- work/src/test/regress/sql/select_views.sql 2009-12-07 13:54:56.271453771 +0900
***************
*** 3,9 ****
-- test the views defined in CREATE_VIEWS
--
! SELECT * FROM street;
SELECT name, #thepath FROM iexit ORDER BY 1, 2;
--- 3,9 ----
-- test the views defined in CREATE_VIEWS
--
! SELECT * FROM street ORDER BY name;
SELECT name, #thepath FROM iexit ORDER BY 1, 2;
diff -cprN head/src/test/regress/sql/vacuum.sql work/src/test/regress/sql/vacuum.sql
*** head/src/test/regress/sql/vacuum.sql 2009-11-17 06:32:07.000000000 +0900
--- work/src/test/regress/sql/vacuum.sql 2009-12-07 14:17:06.801455203 +0900
*************** DELETE FROM vactst;
*** 40,44 ****
--- 40,88 ----
SELECT * FROM vactst;
VACUUM (FULL, FREEZE) vactst;
+ VACUUM (ANALYZE, FULL INPLACE) vactst;
+ CREATE TABLE vaccluster (i INT PRIMARY KEY);
+ ALTER TABLE vaccluster CLUSTER ON vaccluster_pkey;
+ INSERT INTO vaccluster SELECT * FROM vactst;
+
+ CREATE TEMP TABLE vacid (
+ relid regclass,
+ filenode_0 oid,
+ filenode_1 oid,
+ filenode_2 oid,
+ filenode_3 oid
+ );
+
+ INSERT INTO vacid (relid, filenode_0)
+ SELECT oid, relfilenode FROM pg_class WHERE oid::regclass IN (
+ 'pg_am', -- normal catalog
+ 'pg_class', -- fundamental catalog
+ 'pg_database', -- shared catalog
+ 'vaccluster' , -- clustered table
+ 'vacid', -- temp table
+ 'vactst' -- normal table
+ );
+
+ CLUSTER; -- only clusterd table should be changed
+ UPDATE vacid SET filenode_1 = relfilenode
+ FROM pg_class WHERE oid = relid;
+
+ VACUUM (FULL INPLACE); -- all tables should not be changed
+ UPDATE vacid SET filenode_2 = relfilenode
+ FROM pg_class WHERE oid = relid;
+
+ VACUUM FULL; -- only non-system tables should be changed
+ UPDATE vacid SET filenode_3 = relfilenode
+ FROM pg_class WHERE oid = relid;
+
+ SELECT relid,
+ filenode_0 <> filenode_1 AS cluster,
+ filenode_1 <> filenode_2 AS full_inplace,
+ filenode_2 <> filenode_3 AS full
+ FROM vacid
+ ORDER BY relid::text;
+
+ DROP TABLE vaccluster;
+ DROP TABLE vacid;
DROP TABLE vactst;