vacuum-full_20091027.patch
application/octet-stream
Filename: vacuum-full_20091027.patch
Type: application/octet-stream
Part: 0
Message:
New VACUUM FULL
Patch
Format: context
| File | + | − |
|---|---|---|
| src/backend/commands/analyze.c | 5 | 5 |
| src/backend/commands/cluster.c | 128 | 92 |
| src/backend/commands/vacuum.c | 69 | 25 |
| src/backend/commands/vacuumlazy.c | 3 | 2 |
| src/backend/nodes/copyfuncs.c | 1 | 4 |
| src/backend/nodes/equalfuncs.c | 1 | 4 |
| src/backend/parser/gram.y | 54 | 20 |
| src/backend/postmaster/autovacuum.c | 4 | 4 |
| src/backend/tcop/utility.c | 1 | 1 |
| src/include/commands/cluster.h | 2 | 1 |
| src/include/nodes/parsenodes.h | 14 | 4 |
| src/include/parser/kwlist.h | 1 | 0 |
diff -cpr head/src/backend/commands/analyze.c work/src/backend/commands/analyze.c
*** head/src/backend/commands/analyze.c 2009-08-13 03:23:49.000000000 +0900
--- work/src/backend/commands/analyze.c 2009-10-27 10:15:06.817275251 +0900
*************** analyze_rel(Oid relid, VacuumStmt *vacst
*** 135,141 ****
Oid save_userid;
bool save_secdefcxt;
! if (vacstmt->verbose)
elevel = INFO;
else
elevel = DEBUG2;
--- 135,141 ----
Oid save_userid;
bool save_secdefcxt;
! if (vacstmt->options & VACOPT_VERBOSE)
elevel = INFO;
else
elevel = DEBUG2;
*************** analyze_rel(Oid relid, VacuumStmt *vacst
*** 173,179 ****
(pg_database_ownercheck(MyDatabaseId, GetUserId()) && !onerel->rd_rel->relisshared)))
{
/* No need for a WARNING if we already complained during VACUUM */
! if (!vacstmt->vacuum)
{
if (onerel->rd_rel->relisshared)
ereport(WARNING,
--- 173,179 ----
(pg_database_ownercheck(MyDatabaseId, GetUserId()) && !onerel->rd_rel->relisshared)))
{
/* No need for a WARNING if we already complained during VACUUM */
! if (!(vacstmt->options & VACOPT_VACUUM))
{
if (onerel->rd_rel->relisshared)
ereport(WARNING,
*************** analyze_rel(Oid relid, VacuumStmt *vacst
*** 199,205 ****
if (onerel->rd_rel->relkind != RELKIND_RELATION)
{
/* No need for a WARNING if we already complained during VACUUM */
! if (!vacstmt->vacuum)
ereport(WARNING,
(errmsg("skipping \"%s\" --- cannot analyze indexes, views, or special system tables",
RelationGetRelationName(onerel))));
--- 199,205 ----
if (onerel->rd_rel->relkind != RELKIND_RELATION)
{
/* No need for a WARNING if we already complained during VACUUM */
! if (!(vacstmt->options & VACOPT_VACUUM))
ereport(WARNING,
(errmsg("skipping \"%s\" --- cannot analyze indexes, views, or special system tables",
RelationGetRelationName(onerel))));
*************** analyze_rel(Oid relid, VacuumStmt *vacst
*** 475,481 ****
* VACUUM ANALYZE, don't overwrite the accurate count already inserted by
* VACUUM.
*/
! if (!vacstmt->vacuum)
{
for (ind = 0; ind < nindexes; ind++)
{
--- 475,481 ----
* VACUUM ANALYZE, don't overwrite the accurate count already inserted by
* VACUUM.
*/
! if (!(vacstmt->options & VACOPT_VACUUM))
{
for (ind = 0; ind < nindexes; ind++)
{
*************** analyze_rel(Oid relid, VacuumStmt *vacst
*** 493,499 ****
cleanup:
/* If this isn't part of VACUUM ANALYZE, let index AMs do cleanup */
! if (!vacstmt->vacuum)
{
for (ind = 0; ind < nindexes; ind++)
{
--- 493,499 ----
cleanup:
/* If this isn't part of VACUUM ANALYZE, let index AMs do cleanup */
! if (!(vacstmt->options & VACOPT_VACUUM))
{
for (ind = 0; ind < nindexes; ind++)
{
diff -cpr 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-10-27 12:58:36.218261609 +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 -cpr head/src/backend/commands/vacuum.c work/src/backend/commands/vacuum.c
*** head/src/backend/commands/vacuum.c 2009-10-26 11:26:29.000000000 +0900
--- work/src/backend/commands/vacuum.c 2009-10-27 13:24:51.283271344 +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"
*************** void
*** 289,302 ****
vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast,
BufferAccessStrategy bstrategy, bool for_wraparound, bool isTopLevel)
{
! const char *stmttype = vacstmt->vacuum ? "VACUUM" : "ANALYZE";
volatile MemoryContext anl_context = NULL;
volatile bool all_rels,
in_outer_xact,
use_own_xacts;
List *relations;
! if (vacstmt->verbose)
elevel = INFO;
else
elevel = DEBUG2;
--- 291,319 ----
vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast,
BufferAccessStrategy bstrategy, bool for_wraparound, bool isTopLevel)
{
! const char *stmttype;
volatile MemoryContext anl_context = NULL;
volatile bool all_rels,
in_outer_xact,
use_own_xacts;
List *relations;
! /* Adjust options. */
! if (vacstmt->options & (VACOPT_INPLACE | VACOPT_REPLACE | VACOPT_FREEZE))
! vacstmt->options |= VACOPT_VACUUM;
! if (vacstmt->va_cols)
! vacstmt->options |= VACOPT_ANALYZE;
!
! Assert(vacstmt->options & (VACOPT_VACUUM | VACOPT_ANALYZE));
! stmttype = (vacstmt->options & VACOPT_VACUUM) ? "VACUUM" : "ANALYZE";
!
! if (vacstmt->options & VACOPT_FREEZE)
! {
! vacstmt->freeze_min_age = 0;
! vacstmt->freeze_table_age = 0;
! }
!
! if (vacstmt->options & VACOPT_VERBOSE)
elevel = INFO;
else
elevel = DEBUG2;
*************** vacuum(VacuumStmt *vacstmt, Oid relid, b
*** 315,336 ****
*
* ANALYZE (without VACUUM) can run either way.
*/
! if (vacstmt->vacuum)
{
PreventTransactionChain(isTopLevel, stmttype);
in_outer_xact = false;
}
else
in_outer_xact = IsInTransactionChain(isTopLevel);
/*
- * Send info about dead objects to the statistics collector, unless we are
- * in autovacuum --- autovacuum.c does this for itself.
- */
- if (vacstmt->vacuum && !IsAutoVacuumWorkerProcess())
- pgstat_vacuum_stat();
-
- /*
* Create special memory context for cross-transaction storage.
*
* Since it is a child of PortalContext, it will go away eventually even
--- 332,353 ----
*
* ANALYZE (without VACUUM) can run either way.
*/
! if (vacstmt->options & VACOPT_VACUUM)
{
PreventTransactionChain(isTopLevel, stmttype);
in_outer_xact = false;
+
+ /*
+ * Send info about dead objects to the statistics collector, unless we are
+ * in autovacuum --- autovacuum.c does this for itself.
+ */
+ if (!IsAutoVacuumWorkerProcess())
+ pgstat_vacuum_stat();
}
else
in_outer_xact = IsInTransactionChain(isTopLevel);
/*
* Create special memory context for cross-transaction storage.
*
* Since it is a child of PortalContext, it will go away eventually even
*************** vacuum(VacuumStmt *vacstmt, Oid relid, b
*** 378,388 ****
* transaction block, and also in an autovacuum worker, use own
* transactions so we can release locks sooner.
*/
! if (vacstmt->vacuum)
use_own_xacts = true;
else
{
! Assert(vacstmt->analyze);
if (IsAutoVacuumWorkerProcess())
use_own_xacts = true;
else if (in_outer_xact)
--- 395,405 ----
* transaction block, and also in an autovacuum worker, use own
* transactions so we can release locks sooner.
*/
! if (vacstmt->options & VACOPT_VACUUM)
use_own_xacts = true;
else
{
! Assert(vacstmt->options & VACOPT_ANALYZE);
if (IsAutoVacuumWorkerProcess())
use_own_xacts = true;
else if (in_outer_xact)
*************** vacuum(VacuumStmt *vacstmt, Oid relid, b
*** 438,448 ****
Oid relid = lfirst_oid(cur);
bool scanned_all = false;
! if (vacstmt->vacuum)
! vacuum_rel(relid, vacstmt, do_toast, for_wraparound,
! &scanned_all);
! if (vacstmt->analyze)
{
MemoryContext old_context = NULL;
--- 455,465 ----
Oid relid = lfirst_oid(cur);
bool scanned_all = false;
! if (vacstmt->options & VACOPT_VACUUM)
! vacuum_rel(relid, vacstmt, do_toast, for_wraparound,
! &scanned_all);
! if (vacstmt->options & VACOPT_ANALYZE)
{
MemoryContext old_context = NULL;
*************** vacuum(VacuumStmt *vacstmt, Oid relid, b
*** 502,508 ****
StartTransactionCommand();
}
! if (vacstmt->vacuum && !IsAutoVacuumWorkerProcess())
{
/*
* Update pg_database.datfrozenxid, and truncate pg_clog if possible.
--- 519,525 ----
StartTransactionCommand();
}
! if ((vacstmt->options & VACOPT_VACUUM) && !IsAutoVacuumWorkerProcess())
{
/*
* Update pg_database.datfrozenxid, and truncate pg_clog if possible.
*************** vacuum_rel(Oid relid, VacuumStmt *vacstm
*** 1033,1039 ****
*/
PushActiveSnapshot(GetTransactionSnapshot());
! if (!vacstmt->full)
{
/*
* In lazy vacuum, we can set the PROC_IN_VACUUM flag, which lets
--- 1050,1056 ----
*/
PushActiveSnapshot(GetTransactionSnapshot());
! if (!(vacstmt->options & (VACOPT_INPLACE | VACOPT_REPLACE)))
{
/*
* In lazy vacuum, we can set the PROC_IN_VACUUM flag, which lets
*************** vacuum_rel(Oid relid, VacuumStmt *vacstm
*** 1073,1079 ****
* vacuum, but just ShareUpdateExclusiveLock for concurrent vacuum. Either
* way, we can be sure that no other backend is vacuuming the same table.
*/
! lmode = vacstmt->full ? AccessExclusiveLock : ShareUpdateExclusiveLock;
/*
* Open the relation and get the appropriate lock on it.
--- 1090,1098 ----
* vacuum, but just ShareUpdateExclusiveLock for concurrent vacuum. Either
* way, we can be sure that no other backend is vacuuming the same table.
*/
! lmode = (vacstmt->options & VACOPT_INPLACE)
! ? AccessExclusiveLock
! : ShareUpdateExclusiveLock;
/*
* Open the relation and get the appropriate lock on it.
*************** vacuum_rel(Oid relid, VacuumStmt *vacstm
*** 1183,1200 ****
SetUserIdAndContext(onerel->rd_rel->relowner, true);
/*
! * Do the actual work --- either FULL or "lazy" vacuum
*/
! if (vacstmt->full)
! full_vacuum_rel(onerel, vacstmt);
else
! 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.
--- 1202,1244 ----
SetUserIdAndContext(onerel->rd_rel->relowner, true);
/*
! * Do the actual work --- either FULL REPLACE, INPLACE, or "lazy" vacuum
*/
! if (vacstmt->options & VACOPT_REPLACE)
! {
! if (IsSystemRelation(onerel))
! {
! /*
! * Since we cannot FULL REPLACE vacuum for system relations,
! * do FULL INPLACE vacuum instead.
! */
! 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);
! }
! }
else
! {
! if (vacstmt->options & VACOPT_INPLACE)
! full_vacuum_rel(onerel, vacstmt);
! else
! 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 */
! if (onerel)
! relation_close(onerel, NoLock);
/*
* Complete the transaction and free all temporary memory used.
*************** full_vacuum_rel(Relation onerel, VacuumS
*** 1323,1329 ****
/* report results to the stats collector, too */
pgstat_report_vacuum(RelationGetRelid(onerel), onerel->rd_rel->relisshared,
! true, vacstmt->analyze, vacrelstats->rel_tuples);
}
--- 1367,1373 ----
/* report results to the stats collector, too */
pgstat_report_vacuum(RelationGetRelid(onerel), onerel->rd_rel->relisshared,
! true, (vacstmt->options & VACOPT_ANALYZE) != 0, vacrelstats->rel_tuples);
}
diff -cpr head/src/backend/commands/vacuumlazy.c work/src/backend/commands/vacuumlazy.c
*** head/src/backend/commands/vacuumlazy.c 2009-08-24 11:18:32.000000000 +0900
--- work/src/backend/commands/vacuumlazy.c 2009-10-27 10:15:06.820375310 +0900
*************** lazy_vacuum_rel(Relation onerel, VacuumS
*** 160,166 ****
if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration > 0)
starttime = GetCurrentTimestamp();
! if (vacstmt->verbose)
elevel = INFO;
else
elevel = DEBUG2;
--- 160,166 ----
if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration > 0)
starttime = GetCurrentTimestamp();
! if (vacstmt->options & VACOPT_VERBOSE)
elevel = INFO;
else
elevel = DEBUG2;
*************** lazy_vacuum_rel(Relation onerel, VacuumS
*** 222,228 ****
pgstat_report_vacuum(RelationGetRelid(onerel),
onerel->rd_rel->relisshared,
vacrelstats->scanned_all,
! vacstmt->analyze, vacrelstats->rel_tuples);
/* and log the action if appropriate */
if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration >= 0)
--- 222,229 ----
pgstat_report_vacuum(RelationGetRelid(onerel),
onerel->rd_rel->relisshared,
vacrelstats->scanned_all,
! (vacstmt->options & VACOPT_ANALYZE) != 0,
! vacrelstats->rel_tuples);
/* and log the action if appropriate */
if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration >= 0)
diff -cpr head/src/backend/nodes/copyfuncs.c work/src/backend/nodes/copyfuncs.c
*** head/src/backend/nodes/copyfuncs.c 2009-10-26 11:26:31.000000000 +0900
--- work/src/backend/nodes/copyfuncs.c 2009-10-27 10:15:06.821324102 +0900
*************** _copyVacuumStmt(VacuumStmt *from)
*** 2955,2964 ****
{
VacuumStmt *newnode = makeNode(VacuumStmt);
! COPY_SCALAR_FIELD(vacuum);
! COPY_SCALAR_FIELD(full);
! COPY_SCALAR_FIELD(analyze);
! COPY_SCALAR_FIELD(verbose);
COPY_SCALAR_FIELD(freeze_min_age);
COPY_SCALAR_FIELD(freeze_table_age);
COPY_NODE_FIELD(relation);
--- 2955,2961 ----
{
VacuumStmt *newnode = makeNode(VacuumStmt);
! COPY_SCALAR_FIELD(options);
COPY_SCALAR_FIELD(freeze_min_age);
COPY_SCALAR_FIELD(freeze_table_age);
COPY_NODE_FIELD(relation);
diff -cpr head/src/backend/nodes/equalfuncs.c work/src/backend/nodes/equalfuncs.c
*** head/src/backend/nodes/equalfuncs.c 2009-10-26 11:26:31.000000000 +0900
--- work/src/backend/nodes/equalfuncs.c 2009-10-27 10:15:06.822375336 +0900
*************** _equalDropdbStmt(DropdbStmt *a, DropdbSt
*** 1482,1491 ****
static bool
_equalVacuumStmt(VacuumStmt *a, VacuumStmt *b)
{
! COMPARE_SCALAR_FIELD(vacuum);
! COMPARE_SCALAR_FIELD(full);
! COMPARE_SCALAR_FIELD(analyze);
! COMPARE_SCALAR_FIELD(verbose);
COMPARE_SCALAR_FIELD(freeze_min_age);
COMPARE_SCALAR_FIELD(freeze_table_age);
COMPARE_NODE_FIELD(relation);
--- 1482,1488 ----
static bool
_equalVacuumStmt(VacuumStmt *a, VacuumStmt *b)
{
! COMPARE_SCALAR_FIELD(options);
COMPARE_SCALAR_FIELD(freeze_min_age);
COMPARE_SCALAR_FIELD(freeze_table_age);
COMPARE_NODE_FIELD(relation);
diff -cpr head/src/backend/parser/gram.y work/src/backend/parser/gram.y
*** head/src/backend/parser/gram.y 2009-10-15 07:14:22.000000000 +0900
--- work/src/backend/parser/gram.y 2009-10-27 13:23:10.577271273 +0900
*************** static TypeName *TableFuncTypeName(List
*** 234,239 ****
--- 234,240 ----
transaction_mode_item
%type <ival> opt_lock lock_type cast_context
+ %type <ival> vacuum_option_list vacuum_option_elem
%type <boolean> opt_force opt_or_replace
opt_grant_grant_option opt_grant_admin_option
opt_nowait opt_if_exists opt_with_data
*************** static TypeName *TableFuncTypeName(List
*** 489,495 ****
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
--- 490,496 ----
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
*************** cluster_index_specification:
*** 6625,6636 ****
VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
{
VacuumStmt *n = makeNode(VacuumStmt);
! n->vacuum = true;
! n->analyze = false;
! n->full = $2;
n->freeze_min_age = $3 ? 0 : -1;
n->freeze_table_age = $3 ? 0 : -1;
- n->verbose = $4;
n->relation = NULL;
n->va_cols = NIL;
$$ = (Node *)n;
--- 6626,6638 ----
VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
{
VacuumStmt *n = makeNode(VacuumStmt);
! n->options = VACOPT_VACUUM;
! if ($2)
! n->options |= VACOPT_FULL;
! if ($4)
! n->options |= VACOPT_VERBOSE;
n->freeze_min_age = $3 ? 0 : -1;
n->freeze_table_age = $3 ? 0 : -1;
n->relation = NULL;
n->va_cols = NIL;
$$ = (Node *)n;
*************** VacuumStmt: VACUUM opt_full opt_freeze o
*** 6638,6649 ****
| VACUUM opt_full opt_freeze opt_verbose qualified_name
{
VacuumStmt *n = makeNode(VacuumStmt);
! n->vacuum = true;
! n->analyze = false;
! n->full = $2;
n->freeze_min_age = $3 ? 0 : -1;
n->freeze_table_age = $3 ? 0 : -1;
- n->verbose = $4;
n->relation = $5;
n->va_cols = NIL;
$$ = (Node *)n;
--- 6640,6652 ----
| VACUUM opt_full opt_freeze opt_verbose qualified_name
{
VacuumStmt *n = makeNode(VacuumStmt);
! n->options = VACOPT_VACUUM;
! if ($2)
! n->options |= VACOPT_FULL;
! if ($4)
! n->options |= VACOPT_VERBOSE;
n->freeze_min_age = $3 ? 0 : -1;
n->freeze_table_age = $3 ? 0 : -1;
n->relation = $5;
n->va_cols = NIL;
$$ = (Node *)n;
*************** VacuumStmt: VACUUM opt_full opt_freeze o
*** 6651,6675 ****
| VACUUM opt_full opt_freeze opt_verbose AnalyzeStmt
{
VacuumStmt *n = (VacuumStmt *) $5;
! n->vacuum = true;
! n->full = $2;
n->freeze_min_age = $3 ? 0 : -1;
n->freeze_table_age = $3 ? 0 : -1;
- n->verbose |= $4;
$$ = (Node *)n;
}
;
AnalyzeStmt:
analyze_keyword opt_verbose
{
VacuumStmt *n = makeNode(VacuumStmt);
! n->vacuum = false;
! n->analyze = true;
! n->full = false;
n->freeze_min_age = -1;
n->freeze_table_age = -1;
- n->verbose = $2;
n->relation = NULL;
n->va_cols = NIL;
$$ = (Node *)n;
--- 6654,6709 ----
| VACUUM opt_full opt_freeze opt_verbose AnalyzeStmt
{
VacuumStmt *n = (VacuumStmt *) $5;
! n->options |= VACOPT_VACUUM;
! if ($2)
! n->options |= VACOPT_FULL;
! if ($4)
! n->options |= VACOPT_VERBOSE;
n->freeze_min_age = $3 ? 0 : -1;
n->freeze_table_age = $3 ? 0 : -1;
$$ = (Node *)n;
}
+ | VACUUM '(' vacuum_option_list ')'
+ {
+ VacuumStmt *n = makeNode(VacuumStmt);
+ n->options = VACOPT_VACUUM | $3;
+ n->relation = NULL;
+ n->va_cols = NIL;
+ $$ = (Node *) n;
+ }
+ | VACUUM '(' vacuum_option_list ')' qualified_name opt_name_list
+ {
+ VacuumStmt *n = makeNode(VacuumStmt);
+ n->options = VACOPT_VACUUM | $3;
+ n->relation = $5;
+ n->va_cols = $6;
+ $$ = (Node *) n;
+ }
+ ;
+
+ vacuum_option_list:
+ vacuum_option_elem { $$ = $1; }
+ | vacuum_option_list ',' vacuum_option_elem { $$ = $1 | $3; }
+ ;
+
+ vacuum_option_elem:
+ analyze_keyword { $$ = VACOPT_ANALYZE; }
+ | VERBOSE { $$ = VACOPT_VERBOSE; }
+ | FREEZE { $$ = VACOPT_FREEZE; }
+ | FULL { $$ = VACOPT_FULL; }
+ | FULL INPLACE { $$ = VACOPT_INPLACE; }
+ | FULL REPLACE { $$ = VACOPT_REPLACE; }
;
AnalyzeStmt:
analyze_keyword opt_verbose
{
VacuumStmt *n = makeNode(VacuumStmt);
! n->options = VACOPT_ANALYZE;
! if ($2)
! n->options |= VACOPT_VERBOSE;
n->freeze_min_age = -1;
n->freeze_table_age = -1;
n->relation = NULL;
n->va_cols = NIL;
$$ = (Node *)n;
*************** AnalyzeStmt:
*** 6677,6688 ****
| analyze_keyword opt_verbose qualified_name opt_name_list
{
VacuumStmt *n = makeNode(VacuumStmt);
! n->vacuum = false;
! n->analyze = true;
! n->full = false;
n->freeze_min_age = -1;
n->freeze_table_age = -1;
- n->verbose = $2;
n->relation = $3;
n->va_cols = $4;
$$ = (Node *)n;
--- 6711,6721 ----
| analyze_keyword opt_verbose qualified_name opt_name_list
{
VacuumStmt *n = makeNode(VacuumStmt);
! n->options = VACOPT_ANALYZE;
! if ($2)
! n->options |= VACOPT_VERBOSE;
n->freeze_min_age = -1;
n->freeze_table_age = -1;
n->relation = $3;
n->va_cols = $4;
$$ = (Node *)n;
*************** unreserved_keyword:
*** 10616,10621 ****
--- 10649,10655 ----
| INHERIT
| INHERITS
| INLINE_P
+ | INPLACE
| INPUT_P
| INSENSITIVE
| INSERT
diff -cpr head/src/backend/postmaster/autovacuum.c work/src/backend/postmaster/autovacuum.c
*** head/src/backend/postmaster/autovacuum.c 2009-09-01 04:40:59.000000000 +0900
--- work/src/backend/postmaster/autovacuum.c 2009-10-27 10:15:06.826375552 +0900
*************** autovacuum_do_vac_analyze(autovac_table
*** 2640,2651 ****
MemSet(&vacstmt, 0, sizeof(vacstmt));
vacstmt.type = T_VacuumStmt;
! vacstmt.vacuum = tab->at_dovacuum;
! vacstmt.full = false;
! vacstmt.analyze = tab->at_doanalyze;
vacstmt.freeze_min_age = tab->at_freeze_min_age;
vacstmt.freeze_table_age = tab->at_freeze_table_age;
- vacstmt.verbose = false;
vacstmt.relation = NULL; /* not used since we pass a relid */
vacstmt.va_cols = NIL;
--- 2640,2651 ----
MemSet(&vacstmt, 0, sizeof(vacstmt));
vacstmt.type = T_VacuumStmt;
! if (tab->at_dovacuum)
! vacstmt.options |= VACOPT_VACUUM;
! if (tab->at_doanalyze)
! vacstmt.options |= VACOPT_ANALYZE;
vacstmt.freeze_min_age = tab->at_freeze_min_age;
vacstmt.freeze_table_age = tab->at_freeze_table_age;
vacstmt.relation = NULL; /* not used since we pass a relid */
vacstmt.va_cols = NIL;
diff -cpr head/src/backend/tcop/utility.c work/src/backend/tcop/utility.c
*** head/src/backend/tcop/utility.c 2009-10-26 11:26:40.000000000 +0900
--- work/src/backend/tcop/utility.c 2009-10-27 10:51:53.562278044 +0900
*************** CreateCommandTag(Node *parsetree)
*** 1815,1821 ****
break;
case T_VacuumStmt:
! if (((VacuumStmt *) parsetree)->vacuum)
tag = "VACUUM";
else
tag = "ANALYZE";
--- 1815,1821 ----
break;
case T_VacuumStmt:
! if (((VacuumStmt *) parsetree)->options & VACOPT_VACUUM)
tag = "VACUUM";
else
tag = "ANALYZE";
diff -cpr 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-10-27 11:26:14.373277502 +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 -cpr head/src/include/nodes/parsenodes.h work/src/include/nodes/parsenodes.h
*** head/src/include/nodes/parsenodes.h 2009-10-26 11:26:41.000000000 +0900
--- work/src/include/nodes/parsenodes.h 2009-10-27 13:23:10.700283894 +0900
*************** typedef struct ClusterStmt
*** 2204,2216 ****
* just one node type for both.
* ----------------------
*/
typedef struct VacuumStmt
{
NodeTag type;
! bool vacuum; /* do VACUUM step */
! bool full; /* do FULL (non-concurrent) vacuum */
! bool analyze; /* do ANALYZE step */
! bool verbose; /* print progress info */
int freeze_min_age; /* min freeze age, or -1 to use default */
int freeze_table_age; /* age at which to scan whole table */
RangeVar *relation; /* single table to process, or NULL */
--- 2204,2226 ----
* just one node type for both.
* ----------------------
*/
+
+ typedef enum VacuumOption
+ {
+ VACOPT_VACUUM = 1 << 0, /* do VACUUM */
+ VACOPT_ANALYZE = 1 << 1, /* do ANALYZE */
+ VACOPT_VERBOSE = 1 << 2, /* VERBOSE option */
+ VACOPT_FREEZE = 1 << 3, /* FREEZE option */
+ VACOPT_INPLACE = 1 << 4, /* traditional VACUUM FULL */
+ VACOPT_REPLACE = 1 << 5, /* rewrite-version of VACUUM FULL */
+
+ VACOPT_FULL = VACOPT_REPLACE /* default is REPLACE */
+ } VacuumOption;
+
typedef struct VacuumStmt
{
NodeTag type;
! bits32 options; /* OR of VacuumOption flags */
int freeze_min_age; /* min freeze age, or -1 to use default */
int freeze_table_age; /* age at which to scan whole table */
RangeVar *relation; /* single table to process, or NULL */
diff -cpr head/src/include/parser/kwlist.h work/src/include/parser/kwlist.h
*** head/src/include/parser/kwlist.h 2009-10-13 05:39:42.000000000 +0900
--- work/src/include/parser/kwlist.h 2009-10-27 13:16:20.770282670 +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)