Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
2300ac0d
Commit
2300ac0d
authored
Feb 07, 1997
by
Bruce Momjian
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add attribute optimization statistics.
parent
4c0faba0
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
580 additions
and
224 deletions
+580
-224
src/backend/commands/vacuum.c
src/backend/commands/vacuum.c
+524
-197
src/backend/parser/analyze.c
src/backend/parser/analyze.c
+3
-3
src/backend/parser/catalog_utils.c
src/backend/parser/catalog_utils.c
+10
-8
src/backend/parser/parse_query.c
src/backend/parser/parse_query.c
+3
-3
src/backend/utils/adt/selfuncs.c
src/backend/utils/adt/selfuncs.c
+5
-4
src/include/commands/vacuum.h
src/include/commands/vacuum.h
+33
-7
src/include/parser/catalog_utils.h
src/include/parser/catalog_utils.h
+2
-2
No files found.
src/backend/commands/vacuum.c
View file @
2300ac0d
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.1
8 1997/01/29 02:59:03 vadim
Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.1
9 1997/02/07 16:22:34 momjian
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -20,6 +20,7 @@
...
@@ -20,6 +20,7 @@
#include <postgres.h>
#include <postgres.h>
#include <fmgr.h>
#include <utils/portal.h>
#include <utils/portal.h>
#include <access/genam.h>
#include <access/genam.h>
#include <access/heapam.h>
#include <access/heapam.h>
...
@@ -32,12 +33,17 @@
...
@@ -32,12 +33,17 @@
#include <catalog/catalog.h>
#include <catalog/catalog.h>
#include <catalog/pg_class.h>
#include <catalog/pg_class.h>
#include <catalog/pg_proc.h>
#include <catalog/pg_proc.h>
#include <catalog/pg_statistic.h>
#include <catalog/pg_type.h>
#include <catalog/pg_operator.h>
#include <storage/smgr.h>
#include <storage/smgr.h>
#include <storage/lmgr.h>
#include <storage/lmgr.h>
#include <utils/inval.h>
#include <utils/inval.h>
#include <utils/mcxt.h>
#include <utils/mcxt.h>
#include <utils/inval.h>
#include <utils/syscache.h>
#include <utils/syscache.h>
#include <commands/vacuum.h>
#include <commands/vacuum.h>
#include <parser/catalog_utils.h>
#include <storage/bufpage.h>
#include <storage/bufpage.h>
#include "storage/shmem.h"
#include "storage/shmem.h"
#ifndef HAVE_GETRUSAGE
#ifndef HAVE_GETRUSAGE
...
@@ -48,44 +54,48 @@
...
@@ -48,44 +54,48 @@
#endif
#endif
bool
VacuumRunning
=
false
;
bool
VacuumRunning
=
false
;
static
int
MESS
LEV
;
/* message level */
static
int
MESS
AGE_LEVEL
;
/* message level */
typedef
struct
{
#define swapLong(a,b) {long tmp; tmp=a; a=b; b=tmp;}
FuncIndexInfo
finfo
;
#define swapInt(a,b) {int tmp; tmp=a; a=b; b=tmp;}
FuncIndexInfo
*
finfoP
;
#define swapDatum(a,b) {Datum tmp; tmp=a; a=b; b=tmp;}
IndexTupleForm
tform
;
#define VacAttrStatsEqValid(stats) ( RegProcedureIsValid(stats->cmpeq))
int
natts
;
#define VacAttrStatsLtGtValid(stats) ( RegProcedureIsValid(stats->cmplt) && \
}
IndDesc
;
RegProcedureIsValid(stats->cmpgt) && \
RegProcedureIsValid(stats->outfunc) )
/* non-export function prototypes */
/* non-export function prototypes */
static
void
_vc_init
(
void
);
static
void
vc_init
(
void
);
static
void
_vc_shutdown
(
void
);
static
void
vc_shutdown
(
void
);
static
void
_vc_vacuum
(
NameData
*
VacRelP
);
static
void
vc_vacuum
(
NameData
*
VacRelP
);
static
VRelList
_vc_getrels
(
Portal
p
,
NameData
*
VacRelP
);
static
VRelList
vc_getrels
(
Portal
p
,
NameData
*
VacRelP
);
static
void
_vc_vacone
(
VRelList
curvrl
);
static
void
vc_vacone
(
Oid
relid
);
static
void
_vc_scanheap
(
VRelList
curvrl
,
Relation
onerel
,
VPageList
Vvpl
,
VPageList
Fvpl
);
static
void
vc_scanheap
(
VRelStats
*
vacrelstats
,
Relation
onerel
,
VPageList
Vvpl
,
VPageList
Fvpl
);
static
void
_vc_rpfheap
(
VRelList
curvrl
,
Relation
onerel
,
VPageList
Vvpl
,
VPageList
Fvpl
,
int
nindices
,
Relation
*
Irel
);
static
void
vc_rpfheap
(
VRelStats
*
vacrelstats
,
Relation
onerel
,
VPageList
Vvpl
,
VPageList
Fvpl
,
int
nindices
,
Relation
*
Irel
);
static
void
_vc_vacheap
(
VRelList
curvrl
,
Relation
onerel
,
VPageList
vpl
);
static
void
vc_vacheap
(
VRelStats
*
vacrelstats
,
Relation
onerel
,
VPageList
vpl
);
static
void
_vc_vacpage
(
Page
page
,
VPageDescr
vpd
,
Relation
archrel
);
static
void
vc_vacpage
(
Page
page
,
VPageDescr
vpd
,
Relation
archrel
);
static
void
_vc_vaconeind
(
VPageList
vpl
,
Relation
indrel
,
int
nhtups
);
static
void
vc_vaconeind
(
VPageList
vpl
,
Relation
indrel
,
int
nhtups
);
static
void
_vc_scanoneind
(
Relation
indrel
,
int
nhtups
);
static
void
vc_scanoneind
(
Relation
indrel
,
int
nhtups
);
static
void
_vc_updstats
(
Oid
relid
,
int
npages
,
int
ntuples
,
bool
hasindex
);
static
void
vc_attrstats
(
Relation
onerel
,
VacAttrStats
*
vacattrstats
,
HeapTuple
htup
);
static
void
_vc_setpagelock
(
Relation
rel
,
BlockNumber
blkno
);
static
void
vc_bucketcpy
(
AttributeTupleForm
attr
,
Datum
value
,
Datum
*
bucket
,
int16
*
bucket_len
);
static
VPageDescr
_vc_tidreapped
(
ItemPointer
itemptr
,
VPageList
curvrl
);
static
void
vc_updstats
(
Oid
relid
,
int
npages
,
int
ntups
,
bool
hasindex
,
VacAttrStats
*
vacattrstats
);
static
void
_vc_reappage
(
VPageList
vpl
,
VPageDescr
vpc
);
static
void
vc_delhilowstats
(
Oid
relid
);
static
void
_vc_vpinsert
(
VPageList
vpl
,
VPageDescr
vpnew
);
static
void
vc_setpagelock
(
Relation
rel
,
BlockNumber
blkno
);
static
void
_vc_free
(
Portal
p
,
VRelList
vrl
);
static
VPageDescr
vc_tidreapped
(
ItemPointer
itemptr
,
VPageList
vpl
);
static
void
_vc_getindices
(
Oid
relid
,
int
*
nindices
,
Relation
**
Irel
);
static
void
vc_reappage
(
VPageList
vpl
,
VPageDescr
vpc
);
static
void
_vc_clsindices
(
int
nindices
,
Relation
*
Irel
);
static
void
vc_vpinsert
(
VPageList
vpl
,
VPageDescr
vpnew
);
static
Relation
_vc_getarchrel
(
Relation
heaprel
);
static
void
vc_free
(
Portal
p
,
VRelList
vrl
);
static
void
_vc_archive
(
Relation
archrel
,
HeapTuple
htup
);
static
void
vc_getindices
(
Oid
relid
,
int
*
nindices
,
Relation
**
Irel
);
static
bool
_vc_isarchrel
(
char
*
rname
);
static
void
vc_clsindices
(
int
nindices
,
Relation
*
Irel
);
static
void
_vc_mkindesc
(
Relation
onerel
,
int
nindices
,
Relation
*
Irel
,
IndDesc
**
Idesc
);
static
Relation
vc_getarchrel
(
Relation
heaprel
);
static
char
*
_vc_find_eq
(
char
*
bot
,
int
nelem
,
int
size
,
char
*
elm
,
int
(
*
compar
)(
char
*
,
char
*
));
static
void
vc_archive
(
Relation
archrel
,
HeapTuple
htup
);
static
int
_vc_cmp_blk
(
char
*
left
,
char
*
right
);
static
bool
vc_isarchrel
(
char
*
rname
);
static
int
_vc_cmp_offno
(
char
*
left
,
char
*
right
);
static
void
vc_mkindesc
(
Relation
onerel
,
int
nindices
,
Relation
*
Irel
,
IndDesc
**
Idesc
);
static
bool
_vc_enough_space
(
VPageDescr
vpd
,
Size
len
);
static
char
*
vc_find_eq
(
char
*
bot
,
int
nelem
,
int
size
,
char
*
elm
,
int
(
*
compar
)(
char
*
,
char
*
));
static
int
vc_cmp_blk
(
char
*
left
,
char
*
right
);
static
int
vc_cmp_offno
(
char
*
left
,
char
*
right
);
static
bool
vc_enough_space
(
VPageDescr
vpd
,
Size
len
);
void
void
vacuum
(
char
*
vacrel
,
bool
verbose
)
vacuum
(
char
*
vacrel
,
bool
verbose
)
...
@@ -93,30 +103,30 @@ vacuum(char *vacrel, bool verbose)
...
@@ -93,30 +103,30 @@ vacuum(char *vacrel, bool verbose)
NameData
VacRel
;
NameData
VacRel
;
if
(
verbose
)
if
(
verbose
)
MESS
LEV
=
NOTICE
;
MESS
AGE_LEVEL
=
NOTICE
;
else
else
MESS
LEV
=
DEBUG
;
MESS
AGE_LEVEL
=
DEBUG
;
/* vacrel gets de-allocated on transaction commit */
/* vacrel gets de-allocated on transaction commit */
/* initialize vacuum cleaner */
/* initialize vacuum cleaner */
_
vc_init
();
vc_init
();
/* vacuum the database */
/* vacuum the database */
if
(
vacrel
)
if
(
vacrel
)
{
{
strcpy
(
VacRel
.
data
,
vacrel
);
strcpy
(
VacRel
.
data
,
vacrel
);
_
vc_vacuum
(
&
VacRel
);
vc_vacuum
(
&
VacRel
);
}
}
else
else
_
vc_vacuum
(
NULL
);
vc_vacuum
(
NULL
);
/* clean up */
/* clean up */
_
vc_shutdown
();
vc_shutdown
();
}
}
/*
/*
*
_vc_init(), _
vc_shutdown() -- start up and shut down the vacuum cleaner.
*
vc_init(),
vc_shutdown() -- start up and shut down the vacuum cleaner.
*
*
* We run exactly one vacuum cleaner at a time. We use the file system
* We run exactly one vacuum cleaner at a time. We use the file system
* to guarantee an exclusive lock on vacuuming, since a single vacuum
* to guarantee an exclusive lock on vacuuming, since a single vacuum
...
@@ -128,12 +138,12 @@ vacuum(char *vacrel, bool verbose)
...
@@ -128,12 +138,12 @@ vacuum(char *vacrel, bool verbose)
* is invoked via a sql command, and so is already executing inside
* is invoked via a sql command, and so is already executing inside
* a transaction. We need to leave ourselves in a predictable state
* a transaction. We need to leave ourselves in a predictable state
* on entry and exit to the vacuum cleaner. We commit the transaction
* on entry and exit to the vacuum cleaner. We commit the transaction
* started in PostgresMain() inside
_
vc_init(), and start one in
* started in PostgresMain() inside vc_init(), and start one in
*
_
vc_shutdown() to match the commit waiting for us back in
* vc_shutdown() to match the commit waiting for us back in
* PostgresMain().
* PostgresMain().
*/
*/
static
void
static
void
_
vc_init
()
vc_init
()
{
{
int
fd
;
int
fd
;
...
@@ -156,7 +166,7 @@ _vc_init()
...
@@ -156,7 +166,7 @@ _vc_init()
}
}
static
void
static
void
_
vc_shutdown
()
vc_shutdown
()
{
{
/* on entry, not in a transaction */
/* on entry, not in a transaction */
if
(
unlink
(
"pg_vlock"
)
<
0
)
if
(
unlink
(
"pg_vlock"
)
<
0
)
...
@@ -167,6 +177,7 @@ _vc_shutdown()
...
@@ -167,6 +177,7 @@ _vc_shutdown()
/* matches the CommitTransaction in PostgresMain() */
/* matches the CommitTransaction in PostgresMain() */
StartTransactionCommand
();
StartTransactionCommand
();
}
}
void
void
...
@@ -179,7 +190,7 @@ vc_abort()
...
@@ -179,7 +190,7 @@ vc_abort()
}
}
/*
/*
*
_
vc_vacuum() -- vacuum the database.
* vc_vacuum() -- vacuum the database.
*
*
* This routine builds a list of relations to vacuum, and then calls
* This routine builds a list of relations to vacuum, and then calls
* code that vacuums them one at a time. We are careful to vacuum each
* code that vacuums them one at a time. We are careful to vacuum each
...
@@ -187,7 +198,7 @@ vc_abort()
...
@@ -187,7 +198,7 @@ vc_abort()
* locks at one time.
* locks at one time.
*/
*/
static
void
static
void
_
vc_vacuum
(
NameData
*
VacRelP
)
vc_vacuum
(
NameData
*
VacRelP
)
{
{
VRelList
vrl
,
cur
;
VRelList
vrl
,
cur
;
char
*
pname
;
char
*
pname
;
...
@@ -206,19 +217,24 @@ _vc_vacuum(NameData *VacRelP)
...
@@ -206,19 +217,24 @@ _vc_vacuum(NameData *VacRelP)
pfree
(
pname
);
pfree
(
pname
);
/* get list of relations */
/* get list of relations */
vrl
=
_
vc_getrels
(
p
,
VacRelP
);
vrl
=
vc_getrels
(
p
,
VacRelP
);
if
(
VacRelP
!=
NULL
)
vc_delhilowstats
(
vrl
->
vrl_relid
);
else
vc_delhilowstats
(
InvalidOid
);
/* vacuum each heap relation */
/* vacuum each heap relation */
for
(
cur
=
vrl
;
cur
!=
(
VRelList
)
NULL
;
cur
=
cur
->
vrl_next
)
for
(
cur
=
vrl
;
cur
!=
(
VRelList
)
NULL
;
cur
=
cur
->
vrl_next
)
_vc_vacone
(
cur
);
vc_vacone
(
cur
->
vrl_relid
);
_
vc_free
(
p
,
vrl
);
vc_free
(
p
,
vrl
);
PortalDestroy
(
&
p
);
PortalDestroy
(
&
p
);
}
}
static
VRelList
static
VRelList
_
vc_getrels
(
Portal
p
,
NameData
*
VacRelP
)
vc_getrels
(
Portal
p
,
NameData
*
VacRelP
)
{
{
Relation
pgclass
;
Relation
pgclass
;
TupleDesc
pgcdesc
;
TupleDesc
pgcdesc
;
...
@@ -246,7 +262,7 @@ _vc_getrels(Portal p, NameData *VacRelP)
...
@@ -246,7 +262,7 @@ _vc_getrels(Portal p, NameData *VacRelP)
ScanKeyEntryInitialize
(
&
pgckey
,
0x0
,
Anum_pg_class_relkind
,
ScanKeyEntryInitialize
(
&
pgckey
,
0x0
,
Anum_pg_class_relkind
,
CharacterEqualRegProcedure
,
CharGetDatum
(
'r'
));
CharacterEqualRegProcedure
,
CharGetDatum
(
'r'
));
}
}
portalmem
=
PortalGetVariableMemory
(
p
);
portalmem
=
PortalGetVariableMemory
(
p
);
vrl
=
cur
=
(
VRelList
)
NULL
;
vrl
=
cur
=
(
VRelList
)
NULL
;
...
@@ -271,7 +287,7 @@ _vc_getrels(Portal p, NameData *VacRelP)
...
@@ -271,7 +287,7 @@ _vc_getrels(Portal p, NameData *VacRelP)
rname
=
(
char
*
)
d
;
rname
=
(
char
*
)
d
;
/* skip archive relations */
/* skip archive relations */
if
(
_
vc_isarchrel
(
rname
))
{
if
(
vc_isarchrel
(
rname
))
{
ReleaseBuffer
(
buf
);
ReleaseBuffer
(
buf
);
continue
;
continue
;
}
}
...
@@ -320,9 +336,6 @@ _vc_getrels(Portal p, NameData *VacRelP)
...
@@ -320,9 +336,6 @@ _vc_getrels(Portal p, NameData *VacRelP)
(
void
)
MemoryContextSwitchTo
(
old
);
(
void
)
MemoryContextSwitchTo
(
old
);
cur
->
vrl_relid
=
pgctup
->
t_oid
;
cur
->
vrl_relid
=
pgctup
->
t_oid
;
cur
->
vrl_attlist
=
(
VAttList
)
NULL
;
cur
->
vrl_npages
=
cur
->
vrl_ntups
=
0
;
cur
->
vrl_hasindex
=
false
;
cur
->
vrl_next
=
(
VRelList
)
NULL
;
cur
->
vrl_next
=
(
VRelList
)
NULL
;
/* wei hates it if you forget to do this */
/* wei hates it if you forget to do this */
...
@@ -332,8 +345,8 @@ _vc_getrels(Portal p, NameData *VacRelP)
...
@@ -332,8 +345,8 @@ _vc_getrels(Portal p, NameData *VacRelP)
elog
(
NOTICE
,
"Vacuum: table not found"
);
elog
(
NOTICE
,
"Vacuum: table not found"
);
heap_close
(
pgclass
);
heap_endscan
(
pgcscan
);
heap_endscan
(
pgcscan
);
heap_close
(
pgclass
);
CommitTransactionCommand
();
CommitTransactionCommand
();
...
@@ -341,10 +354,10 @@ _vc_getrels(Portal p, NameData *VacRelP)
...
@@ -341,10 +354,10 @@ _vc_getrels(Portal p, NameData *VacRelP)
}
}
/*
/*
*
_
vc_vacone() -- vacuum one heap relation
* vc_vacone() -- vacuum one heap relation
*
*
* This routine vacuums a single heap, cleans out its indices, and
* This routine vacuums a single heap, cleans out its indices, and
* updates its statistics npages and ntup
le
s statistics.
* updates its statistics npages and ntups statistics.
*
*
* Doing one heap at a time incurs extra overhead, since we need to
* Doing one heap at a time incurs extra overhead, since we need to
* check that the heap exists again just before we vacuum it. The
* check that the heap exists again just before we vacuum it. The
...
@@ -353,11 +366,11 @@ _vc_getrels(Portal p, NameData *VacRelP)
...
@@ -353,11 +366,11 @@ _vc_getrels(Portal p, NameData *VacRelP)
* us to lock the entire database during one pass of the vacuum cleaner.
* us to lock the entire database during one pass of the vacuum cleaner.
*/
*/
static
void
static
void
_vc_vacone
(
VRelList
curvrl
)
vc_vacone
(
Oid
relid
)
{
{
Relation
pgclass
;
Relation
pgclass
;
TupleDesc
pgcdesc
;
TupleDesc
pgcdesc
;
HeapTuple
pgctup
;
HeapTuple
pgctup
,
pgttup
;
Buffer
pgcbuf
;
Buffer
pgcbuf
;
HeapScanDesc
pgcscan
;
HeapScanDesc
pgcscan
;
Relation
onerel
;
Relation
onerel
;
...
@@ -366,14 +379,15 @@ _vc_vacone (VRelList curvrl)
...
@@ -366,14 +379,15 @@ _vc_vacone (VRelList curvrl)
VPageListData
Fvpl
;
/* List of pages with space enough for re-using */
VPageListData
Fvpl
;
/* List of pages with space enough for re-using */
VPageDescr
*
vpp
;
VPageDescr
*
vpp
;
Relation
*
Irel
;
Relation
*
Irel
;
int
nindices
;
int32
nindices
,
i
,
attr_cnt
;
int
i
;
AttributeTupleForm
*
attr
;
VRelStats
*
vacrelstats
;
StartTransactionCommand
();
StartTransactionCommand
();
ScanKeyEntryInitialize
(
&
pgckey
,
0x0
,
ObjectIdAttributeNumber
,
ScanKeyEntryInitialize
(
&
pgckey
,
0x0
,
ObjectIdAttributeNumber
,
ObjectIdEqualRegProcedure
,
ObjectIdEqualRegProcedure
,
ObjectIdGetDatum
(
curvrl
->
vrl_
relid
));
ObjectIdGetDatum
(
relid
));
pgclass
=
heap_openr
(
RelationRelationName
);
pgclass
=
heap_openr
(
RelationRelationName
);
pgcdesc
=
RelationGetTupleDescriptor
(
pgclass
);
pgcdesc
=
RelationGetTupleDescriptor
(
pgclass
);
...
@@ -392,23 +406,80 @@ _vc_vacone (VRelList curvrl)
...
@@ -392,23 +406,80 @@ _vc_vacone (VRelList curvrl)
}
}
/* now open the class and vacuum it */
/* now open the class and vacuum it */
onerel
=
heap_open
(
curvrl
->
vrl_relid
);
onerel
=
heap_open
(
relid
);
attr_cnt
=
onerel
->
rd_att
->
natts
;
attr
=
onerel
->
rd_att
->
attrs
;
vacrelstats
=
(
VRelStats
*
)
palloc
(
sizeof
(
VRelStats
));
vacrelstats
->
relid
=
relid
;
vacrelstats
->
npages
=
vacrelstats
->
ntups
=
0
;
vacrelstats
->
hasindex
=
false
;
vacrelstats
->
vacattrstats
=
(
VacAttrStats
*
)
palloc
(
attr_cnt
*
sizeof
(
VacAttrStats
));
for
(
i
=
0
;
i
<
attr_cnt
;
i
++
)
{
Operator
func_operator
;
OperatorTupleForm
pgopform
;
VacAttrStats
*
stats
=
&
vacrelstats
->
vacattrstats
[
i
];
stats
->
attr
=
palloc
(
ATTRIBUTE_TUPLE_SIZE
);
memmove
(
stats
->
attr
,
attr
[
i
],
ATTRIBUTE_TUPLE_SIZE
);
stats
->
best
=
stats
->
guess1
=
stats
->
guess2
=
0
;
stats
->
max
=
stats
->
min
=
0
;
stats
->
best_len
=
stats
->
guess1_len
=
stats
->
guess2_len
=
0
;
stats
->
max_len
=
stats
->
min_len
=
0
;
stats
->
initialized
=
false
;
stats
->
best_cnt
=
stats
->
guess1_cnt
=
stats
->
guess1_hits
=
stats
->
guess2_hits
=
0
;
stats
->
max_cnt
=
stats
->
min_cnt
=
stats
->
null_cnt
=
stats
->
nonnull_cnt
=
0
;
func_operator
=
oper
(
"="
,
stats
->
attr
->
atttypid
,
stats
->
attr
->
atttypid
,
true
);
if
(
func_operator
!=
NULL
)
{
pgopform
=
(
OperatorTupleForm
)
GETSTRUCT
(
func_operator
);
stats
->
cmpeq
=
pgopform
->
oprcode
;
}
else
stats
->
cmpeq
=
InvalidOid
;
func_operator
=
oper
(
"<"
,
stats
->
attr
->
atttypid
,
stats
->
attr
->
atttypid
,
true
);
if
(
func_operator
!=
NULL
)
{
pgopform
=
(
OperatorTupleForm
)
GETSTRUCT
(
func_operator
);
stats
->
cmplt
=
pgopform
->
oprcode
;
}
else
stats
->
cmplt
=
InvalidOid
;
func_operator
=
oper
(
">"
,
stats
->
attr
->
atttypid
,
stats
->
attr
->
atttypid
,
true
);
if
(
func_operator
!=
NULL
)
{
pgopform
=
(
OperatorTupleForm
)
GETSTRUCT
(
func_operator
);
stats
->
cmpgt
=
pgopform
->
oprcode
;
}
else
stats
->
cmpgt
=
InvalidOid
;
func_operator
=
oper
(
">"
,
stats
->
attr
->
atttypid
,
stats
->
attr
->
atttypid
,
true
);
if
(
func_operator
!=
NULL
)
{
pgopform
=
(
OperatorTupleForm
)
GETSTRUCT
(
func_operator
);
stats
->
cmpgt
=
pgopform
->
oprcode
;
}
else
stats
->
cmpgt
=
InvalidOid
;
pgttup
=
SearchSysCacheTuple
(
TYPOID
,
ObjectIdGetDatum
(
stats
->
attr
->
atttypid
),
0
,
0
,
0
);
if
(
HeapTupleIsValid
(
pgttup
))
stats
->
outfunc
=
((
TypeTupleForm
)
GETSTRUCT
(
pgttup
))
->
typoutput
;
else
stats
->
outfunc
=
InvalidOid
;
}
/* we require the relation to be locked until the indices are cleaned */
/* we require the relation to be locked until the indices are cleaned */
RelationSetLockForWrite
(
onerel
);
RelationSetLockForWrite
(
onerel
);
/* scan it */
/* scan it */
Vvpl
.
vpl_npages
=
Fvpl
.
vpl_npages
=
0
;
Vvpl
.
vpl_npages
=
Fvpl
.
vpl_npages
=
0
;
_vc_scanheap
(
curvrl
,
onerel
,
&
Vvpl
,
&
Fvpl
);
vc_scanheap
(
vacrelstats
,
onerel
,
&
Vvpl
,
&
Fvpl
);
/* Now open indices */
/* Now open indices */
Irel
=
(
Relation
*
)
NULL
;
Irel
=
(
Relation
*
)
NULL
;
_vc_getindices
(
curvrl
->
vrl_
relid
,
&
nindices
,
&
Irel
);
vc_getindices
(
vacrelstats
->
relid
,
&
nindices
,
&
Irel
);
if
(
nindices
>
0
)
if
(
nindices
>
0
)
curvrl
->
vrl_
hasindex
=
true
;
vacrelstats
->
hasindex
=
true
;
else
else
curvrl
->
vrl_
hasindex
=
false
;
vacrelstats
->
hasindex
=
false
;
/* Clean/scan index relation(s) */
/* Clean/scan index relation(s) */
if
(
Irel
!=
(
Relation
*
)
NULL
)
if
(
Irel
!=
(
Relation
*
)
NULL
)
...
@@ -416,23 +487,23 @@ _vc_vacone (VRelList curvrl)
...
@@ -416,23 +487,23 @@ _vc_vacone (VRelList curvrl)
if
(
Vvpl
.
vpl_npages
>
0
)
if
(
Vvpl
.
vpl_npages
>
0
)
{
{
for
(
i
=
0
;
i
<
nindices
;
i
++
)
for
(
i
=
0
;
i
<
nindices
;
i
++
)
_vc_vaconeind
(
&
Vvpl
,
Irel
[
i
],
curvrl
->
vrl_
ntups
);
vc_vaconeind
(
&
Vvpl
,
Irel
[
i
],
vacrelstats
->
ntups
);
}
}
else
/* just scan indices to update statistic */
else
/* just scan indices to update statistic */
{
{
for
(
i
=
0
;
i
<
nindices
;
i
++
)
for
(
i
=
0
;
i
<
nindices
;
i
++
)
_vc_scanoneind
(
Irel
[
i
],
curvrl
->
vrl_
ntups
);
vc_scanoneind
(
Irel
[
i
],
vacrelstats
->
ntups
);
}
}
}
}
if
(
Fvpl
.
vpl_npages
>
0
)
/* Try to shrink heap */
if
(
Fvpl
.
vpl_npages
>
0
)
/* Try to shrink heap */
_vc_rpfheap
(
curvrl
,
onerel
,
&
Vvpl
,
&
Fvpl
,
nindices
,
Irel
);
vc_rpfheap
(
vacrelstats
,
onerel
,
&
Vvpl
,
&
Fvpl
,
nindices
,
Irel
);
else
else
{
{
if
(
Irel
!=
(
Relation
*
)
NULL
)
if
(
Irel
!=
(
Relation
*
)
NULL
)
_
vc_clsindices
(
nindices
,
Irel
);
vc_clsindices
(
nindices
,
Irel
);
if
(
Vvpl
.
vpl_npages
>
0
)
/* Clean pages from Vvpl list */
if
(
Vvpl
.
vpl_npages
>
0
)
/* Clean pages from Vvpl list */
_vc_vacheap
(
curvrl
,
onerel
,
&
Vvpl
);
vc_vacheap
(
vacrelstats
,
onerel
,
&
Vvpl
);
}
}
/* ok - free Vvpl list of reapped pages */
/* ok - free Vvpl list of reapped pages */
...
@@ -452,14 +523,18 @@ _vc_vacone (VRelList curvrl)
...
@@ -452,14 +523,18 @@ _vc_vacone (VRelList curvrl)
heap_close
(
pgclass
);
heap_close
(
pgclass
);
/* update statistics in pg_class */
/* update statistics in pg_class */
_vc_updstats
(
curvrl
->
vrl_relid
,
curvrl
->
vrl_npages
,
curvrl
->
vrl_ntups
,
vc_updstats
(
vacrelstats
->
relid
,
vacrelstats
->
npages
,
vacrelstats
->
ntups
,
curvrl
->
vrl_hasindex
);
vacrelstats
->
hasindex
,
vacrelstats
->
vacattrstats
);
/* next command frees everything anyway */
if
(
vacrelstats
->
vacattrstats
!=
NULL
)
pfree
(
vacrelstats
);
CommitTransactionCommand
();
CommitTransactionCommand
();
}
}
/*
/*
*
_
vc_scanheap() -- scan an open heap relation
* vc_scanheap() -- scan an open heap relation
*
*
* This routine sets commit times, constructs Vvpl list of
* This routine sets commit times, constructs Vvpl list of
* empty/uninitialized pages and pages with dead tuples and
* empty/uninitialized pages and pages with dead tuples and
...
@@ -468,7 +543,7 @@ _vc_vacone (VRelList curvrl)
...
@@ -468,7 +543,7 @@ _vc_vacone (VRelList curvrl)
* on the number of live tuples in a heap.
* on the number of live tuples in a heap.
*/
*/
static
void
static
void
_vc_scanheap
(
VRelList
curvrl
,
Relation
onerel
,
vc_scanheap
(
VRelStats
*
vacrelstats
,
Relation
onerel
,
VPageList
Vvpl
,
VPageList
Fvpl
)
VPageList
Vvpl
,
VPageList
Fvpl
)
{
{
int
nblocks
,
blkno
;
int
nblocks
,
blkno
;
...
@@ -487,14 +562,14 @@ _vc_scanheap (VRelList curvrl, Relation onerel,
...
@@ -487,14 +562,14 @@ _vc_scanheap (VRelList curvrl, Relation onerel,
Size
frsize
,
frsusf
;
Size
frsize
,
frsusf
;
Size
min_tlen
=
MAXTUPLEN
;
Size
min_tlen
=
MAXTUPLEN
;
Size
max_tlen
=
0
;
Size
max_tlen
=
0
;
int
i
;
int
32
i
/*, attr_cnt*/
;
struct
rusage
ru0
,
ru1
;
struct
rusage
ru0
,
ru1
;
getrusage
(
RUSAGE_SELF
,
&
ru0
);
getrusage
(
RUSAGE_SELF
,
&
ru0
);
nvac
=
ntups
=
nunused
=
ncrash
=
nempg
=
nnepg
=
nchpg
=
nemend
=
0
;
nvac
=
ntups
=
nunused
=
ncrash
=
nempg
=
nnepg
=
nchpg
=
nemend
=
0
;
frsize
=
frsusf
=
0
;
frsize
=
frsusf
=
0
;
relname
=
(
RelationGetRelationName
(
onerel
))
->
data
;
relname
=
(
RelationGetRelationName
(
onerel
))
->
data
;
nblocks
=
RelationGetNumberOfBlocks
(
onerel
);
nblocks
=
RelationGetNumberOfBlocks
(
onerel
);
...
@@ -532,7 +607,7 @@ _vc_scanheap (VRelList curvrl, Relation onerel,
...
@@ -532,7 +607,7 @@ _vc_scanheap (VRelList curvrl, Relation onerel,
frsize
+=
(
vpc
->
vpd_free
-
sizeof
(
ItemIdData
));
frsize
+=
(
vpc
->
vpd_free
-
sizeof
(
ItemIdData
));
nnepg
++
;
nnepg
++
;
nemend
++
;
nemend
++
;
_
vc_reappage
(
Vvpl
,
vpc
);
vc_reappage
(
Vvpl
,
vpc
);
WriteBuffer
(
buf
);
WriteBuffer
(
buf
);
continue
;
continue
;
}
}
...
@@ -542,7 +617,7 @@ _vc_scanheap (VRelList curvrl, Relation onerel,
...
@@ -542,7 +617,7 @@ _vc_scanheap (VRelList curvrl, Relation onerel,
frsize
+=
(
vpc
->
vpd_free
-
sizeof
(
ItemIdData
));
frsize
+=
(
vpc
->
vpd_free
-
sizeof
(
ItemIdData
));
nempg
++
;
nempg
++
;
nemend
++
;
nemend
++
;
_
vc_reappage
(
Vvpl
,
vpc
);
vc_reappage
(
Vvpl
,
vpc
);
ReleaseBuffer
(
buf
);
ReleaseBuffer
(
buf
);
continue
;
continue
;
}
}
...
@@ -585,7 +660,7 @@ _vc_scanheap (VRelList curvrl, Relation onerel,
...
@@ -585,7 +660,7 @@ _vc_scanheap (VRelList curvrl, Relation onerel,
tupgone
=
true
;
tupgone
=
true
;
}
}
else
{
else
{
elog
(
MESS
LEV
,
"Rel %.*s: InsertTransactionInProgress %u for TID %u/%u"
,
elog
(
MESS
AGE_LEVEL
,
"Rel %.*s: InsertTransactionInProgress %u for TID %u/%u"
,
NAMEDATALEN
,
relname
,
htup
->
t_xmin
,
blkno
,
offnum
);
NAMEDATALEN
,
relname
,
htup
->
t_xmin
,
blkno
,
offnum
);
}
}
}
}
...
@@ -677,6 +752,7 @@ DELETE_TRANSACTION_ID_VALID %d, TUPGONE %d.",
...
@@ -677,6 +752,7 @@ DELETE_TRANSACTION_ID_VALID %d, TUPGONE %d.",
min_tlen
=
htup
->
t_len
;
min_tlen
=
htup
->
t_len
;
if
(
htup
->
t_len
>
max_tlen
)
if
(
htup
->
t_len
>
max_tlen
)
max_tlen
=
htup
->
t_len
;
max_tlen
=
htup
->
t_len
;
vc_attrstats
(
onerel
,
vacrelstats
->
vacattrstats
,
htup
);
}
}
}
}
...
@@ -692,7 +768,7 @@ DELETE_TRANSACTION_ID_VALID %d, TUPGONE %d.",
...
@@ -692,7 +768,7 @@ DELETE_TRANSACTION_ID_VALID %d, TUPGONE %d.",
PageRepairFragmentation
(
tempPage
);
PageRepairFragmentation
(
tempPage
);
vpc
->
vpd_free
=
((
PageHeader
)
tempPage
)
->
pd_upper
-
((
PageHeader
)
tempPage
)
->
pd_lower
;
vpc
->
vpd_free
=
((
PageHeader
)
tempPage
)
->
pd_upper
-
((
PageHeader
)
tempPage
)
->
pd_lower
;
frsize
+=
vpc
->
vpd_free
;
frsize
+=
vpc
->
vpd_free
;
_
vc_reappage
(
Vvpl
,
vpc
);
vc_reappage
(
Vvpl
,
vpc
);
pfree
(
tempPage
);
pfree
(
tempPage
);
tempPage
=
(
Page
)
NULL
;
tempPage
=
(
Page
)
NULL
;
}
}
...
@@ -700,7 +776,7 @@ DELETE_TRANSACTION_ID_VALID %d, TUPGONE %d.",
...
@@ -700,7 +776,7 @@ DELETE_TRANSACTION_ID_VALID %d, TUPGONE %d.",
{
/* there are only ~LP_USED line pointers */
{
/* there are only ~LP_USED line pointers */
vpc
->
vpd_free
=
((
PageHeader
)
page
)
->
pd_upper
-
((
PageHeader
)
page
)
->
pd_lower
;
vpc
->
vpd_free
=
((
PageHeader
)
page
)
->
pd_upper
-
((
PageHeader
)
page
)
->
pd_lower
;
frsize
+=
vpc
->
vpd_free
;
frsize
+=
vpc
->
vpd_free
;
_
vc_reappage
(
Vvpl
,
vpc
);
vc_reappage
(
Vvpl
,
vpc
);
}
}
if
(
dobufrel
)
if
(
dobufrel
)
ReleaseBuffer
(
buf
);
ReleaseBuffer
(
buf
);
...
@@ -713,12 +789,13 @@ DELETE_TRANSACTION_ID_VALID %d, TUPGONE %d.",
...
@@ -713,12 +789,13 @@ DELETE_TRANSACTION_ID_VALID %d, TUPGONE %d.",
pfree
(
vpc
);
pfree
(
vpc
);
/* save stats in the rel list for use later */
/* save stats in the rel list for use later */
curvrl
->
vrl_ntups
=
ntups
;
vacrelstats
->
ntups
=
ntups
;
curvrl
->
vrl_npages
=
nblocks
;
vacrelstats
->
npages
=
nblocks
;
/* vacrelstats->natts = attr_cnt;*/
if
(
ntups
==
0
)
if
(
ntups
==
0
)
min_tlen
=
max_tlen
=
0
;
min_tlen
=
max_tlen
=
0
;
curvrl
->
vrl_
min_tlen
=
min_tlen
;
vacrelstats
->
min_tlen
=
min_tlen
;
curvrl
->
vrl_
max_tlen
=
max_tlen
;
vacrelstats
->
max_tlen
=
max_tlen
;
Vvpl
->
vpl_nemend
=
nemend
;
Vvpl
->
vpl_nemend
=
nemend
;
Fvpl
->
vpl_nemend
=
nemend
;
Fvpl
->
vpl_nemend
=
nemend
;
...
@@ -738,9 +815,9 @@ DELETE_TRANSACTION_ID_VALID %d, TUPGONE %d.",
...
@@ -738,9 +815,9 @@ DELETE_TRANSACTION_ID_VALID %d, TUPGONE %d.",
for
(
i
=
0
;
i
<
nusf
;
i
++
)
for
(
i
=
0
;
i
<
nusf
;
i
++
)
{
{
vp
=
Vvpl
->
vpl_pgdesc
[
i
];
vp
=
Vvpl
->
vpl_pgdesc
[
i
];
if
(
_
vc_enough_space
(
vp
,
min_tlen
)
)
if
(
vc_enough_space
(
vp
,
min_tlen
)
)
{
{
_
vc_vpinsert
(
Fvpl
,
vp
);
vc_vpinsert
(
Fvpl
,
vp
);
frsusf
+=
vp
->
vpd_free
;
frsusf
+=
vp
->
vpd_free
;
}
}
}
}
...
@@ -748,7 +825,7 @@ DELETE_TRANSACTION_ID_VALID %d, TUPGONE %d.",
...
@@ -748,7 +825,7 @@ DELETE_TRANSACTION_ID_VALID %d, TUPGONE %d.",
getrusage
(
RUSAGE_SELF
,
&
ru1
);
getrusage
(
RUSAGE_SELF
,
&
ru1
);
elog
(
MESS
LEV
,
"Rel %.*s: Pages %u: Changed %u, Reapped %u, Empty %u, New %u; \
elog
(
MESS
AGE_LEVEL
,
"Rel %.*s: Pages %u: Changed %u, Reapped %u, Empty %u, New %u; \
Tup %u: Vac %u, Crash %u, UnUsed %u, MinLen %u, MaxLen %u; Re-using: Free/Avail. Space %u/%u; EndEmpty/Avail. Pages %u/%u. Elapsed %u/%u sec."
,
Tup %u: Vac %u, Crash %u, UnUsed %u, MinLen %u, MaxLen %u; Re-using: Free/Avail. Space %u/%u; EndEmpty/Avail. Pages %u/%u. Elapsed %u/%u sec."
,
NAMEDATALEN
,
relname
,
NAMEDATALEN
,
relname
,
nblocks
,
nchpg
,
Vvpl
->
vpl_npages
,
nempg
,
nnepg
,
nblocks
,
nchpg
,
Vvpl
->
vpl_npages
,
nempg
,
nnepg
,
...
@@ -757,11 +834,11 @@ Tup %u: Vac %u, Crash %u, UnUsed %u, MinLen %u, MaxLen %u; Re-using: Free/Avail.
...
@@ -757,11 +834,11 @@ Tup %u: Vac %u, Crash %u, UnUsed %u, MinLen %u, MaxLen %u; Re-using: Free/Avail.
ru1
.
ru_stime
.
tv_sec
-
ru0
.
ru_stime
.
tv_sec
,
ru1
.
ru_stime
.
tv_sec
-
ru0
.
ru_stime
.
tv_sec
,
ru1
.
ru_utime
.
tv_sec
-
ru0
.
ru_utime
.
tv_sec
);
ru1
.
ru_utime
.
tv_sec
-
ru0
.
ru_utime
.
tv_sec
);
}
/*
_
vc_scanheap */
}
/* vc_scanheap */
/*
/*
*
_
vc_rpfheap() -- try to repaire relation' fragmentation
* vc_rpfheap() -- try to repaire relation' fragmentation
*
*
* This routine marks dead tuples as unused and tries re-use dead space
* This routine marks dead tuples as unused and tries re-use dead space
* by moving tuples (and inserting indices if needed). It constructs
* by moving tuples (and inserting indices if needed). It constructs
...
@@ -771,7 +848,7 @@ Tup %u: Vac %u, Crash %u, UnUsed %u, MinLen %u, MaxLen %u; Re-using: Free/Avail.
...
@@ -771,7 +848,7 @@ Tup %u: Vac %u, Crash %u, UnUsed %u, MinLen %u, MaxLen %u; Re-using: Free/Avail.
* if some end-blocks are gone away.
* if some end-blocks are gone away.
*/
*/
static
void
static
void
_vc_rpfheap
(
VRelList
curvrl
,
Relation
onerel
,
vc_rpfheap
(
VRelStats
*
vacrelstats
,
Relation
onerel
,
VPageList
Vvpl
,
VPageList
Fvpl
,
int
nindices
,
Relation
*
Irel
)
VPageList
Vvpl
,
VPageList
Fvpl
,
int
nindices
,
Relation
*
Irel
)
{
{
TransactionId
myXID
;
TransactionId
myXID
;
...
@@ -806,7 +883,7 @@ _vc_rpfheap (VRelList curvrl, Relation onerel,
...
@@ -806,7 +883,7 @@ _vc_rpfheap (VRelList curvrl, Relation onerel,
if
(
Irel
!=
(
Relation
*
)
NULL
)
/* preparation for index' inserts */
if
(
Irel
!=
(
Relation
*
)
NULL
)
/* preparation for index' inserts */
{
{
_
vc_mkindesc
(
onerel
,
nindices
,
Irel
,
&
Idesc
);
vc_mkindesc
(
onerel
,
nindices
,
Irel
,
&
Idesc
);
tupdesc
=
RelationGetTupleDescriptor
(
onerel
);
tupdesc
=
RelationGetTupleDescriptor
(
onerel
);
idatum
=
(
Datum
*
)
palloc
(
INDEX_MAX_KEYS
*
sizeof
(
*
idatum
));
idatum
=
(
Datum
*
)
palloc
(
INDEX_MAX_KEYS
*
sizeof
(
*
idatum
));
inulls
=
(
char
*
)
palloc
(
INDEX_MAX_KEYS
*
sizeof
(
*
inulls
));
inulls
=
(
char
*
)
palloc
(
INDEX_MAX_KEYS
*
sizeof
(
*
inulls
));
...
@@ -815,7 +892,7 @@ _vc_rpfheap (VRelList curvrl, Relation onerel,
...
@@ -815,7 +892,7 @@ _vc_rpfheap (VRelList curvrl, Relation onerel,
/* if the relation has an archive, open it */
/* if the relation has an archive, open it */
if
(
onerel
->
rd_rel
->
relarch
!=
'n'
)
if
(
onerel
->
rd_rel
->
relarch
!=
'n'
)
{
{
archrel
=
_
vc_getarchrel
(
onerel
);
archrel
=
vc_getarchrel
(
onerel
);
/* Archive tuples from "empty" end-pages */
/* Archive tuples from "empty" end-pages */
for
(
vpp
=
Vvpl
->
vpl_pgdesc
+
Vvpl
->
vpl_npages
-
1
,
for
(
vpp
=
Vvpl
->
vpl_pgdesc
+
Vvpl
->
vpl_npages
-
1
,
i
=
Vvpl
->
vpl_nemend
;
i
>
0
;
i
--
,
vpp
--
)
i
=
Vvpl
->
vpl_nemend
;
i
>
0
;
i
--
,
vpp
--
)
...
@@ -825,7 +902,7 @@ _vc_rpfheap (VRelList curvrl, Relation onerel,
...
@@ -825,7 +902,7 @@ _vc_rpfheap (VRelList curvrl, Relation onerel,
buf
=
ReadBuffer
(
onerel
,
(
*
vpp
)
->
vpd_blkno
);
buf
=
ReadBuffer
(
onerel
,
(
*
vpp
)
->
vpd_blkno
);
page
=
BufferGetPage
(
buf
);
page
=
BufferGetPage
(
buf
);
Assert
(
!
PageIsEmpty
(
page
)
);
Assert
(
!
PageIsEmpty
(
page
)
);
_
vc_vacpage
(
page
,
*
vpp
,
archrel
);
vc_vacpage
(
page
,
*
vpp
,
archrel
);
WriteBuffer
(
buf
);
WriteBuffer
(
buf
);
}
}
}
}
...
@@ -848,7 +925,7 @@ _vc_rpfheap (VRelList curvrl, Relation onerel,
...
@@ -848,7 +925,7 @@ _vc_rpfheap (VRelList curvrl, Relation onerel,
vpc
=
(
VPageDescr
)
palloc
(
sizeof
(
VPageDescrData
)
+
MaxOffsetNumber
*
sizeof
(
OffsetNumber
));
vpc
=
(
VPageDescr
)
palloc
(
sizeof
(
VPageDescrData
)
+
MaxOffsetNumber
*
sizeof
(
OffsetNumber
));
vpc
->
vpd_nusd
=
vpc
->
vpd_noff
=
0
;
vpc
->
vpd_nusd
=
vpc
->
vpd_noff
=
0
;
nblocks
=
curvrl
->
vrl_
npages
;
nblocks
=
vacrelstats
->
npages
;
for
(
blkno
=
nblocks
-
Vvpl
->
vpl_nemend
-
1
;
;
blkno
--
)
for
(
blkno
=
nblocks
-
Vvpl
->
vpl_nemend
-
1
;
;
blkno
--
)
{
{
/* if it's reapped page and it was used by me - quit */
/* if it's reapped page and it was used by me - quit */
...
@@ -868,7 +945,7 @@ _vc_rpfheap (VRelList curvrl, Relation onerel,
...
@@ -868,7 +945,7 @@ _vc_rpfheap (VRelList curvrl, Relation onerel,
if
(
Vvplast
->
vpd_noff
>
0
)
/* there are dead tuples */
if
(
Vvplast
->
vpd_noff
>
0
)
/* there are dead tuples */
{
/* on this page - clean */
{
/* on this page - clean */
Assert
(
!
isempty
);
Assert
(
!
isempty
);
_
vc_vacpage
(
page
,
Vvplast
,
archrel
);
vc_vacpage
(
page
,
Vvplast
,
archrel
);
dowrite
=
true
;
dowrite
=
true
;
}
}
else
else
...
@@ -913,7 +990,7 @@ _vc_rpfheap (VRelList curvrl, Relation onerel,
...
@@ -913,7 +990,7 @@ _vc_rpfheap (VRelList curvrl, Relation onerel,
/* try to find new page for this tuple */
/* try to find new page for this tuple */
if
(
ToBuf
==
InvalidBuffer
||
if
(
ToBuf
==
InvalidBuffer
||
!
_
vc_enough_space
(
ToVpd
,
tlen
)
)
!
vc_enough_space
(
ToVpd
,
tlen
)
)
{
{
if
(
ToBuf
!=
InvalidBuffer
)
if
(
ToBuf
!=
InvalidBuffer
)
{
{
...
@@ -923,7 +1000,7 @@ _vc_rpfheap (VRelList curvrl, Relation onerel,
...
@@ -923,7 +1000,7 @@ _vc_rpfheap (VRelList curvrl, Relation onerel,
* If no one tuple can't be added to this page -
* If no one tuple can't be added to this page -
* remove page from Fvpl. - vadim 11/27/96
* remove page from Fvpl. - vadim 11/27/96
*/
*/
if
(
!
_vc_enough_space
(
ToVpd
,
curvrl
->
vrl_
min_tlen
)
)
if
(
!
vc_enough_space
(
ToVpd
,
vacrelstats
->
min_tlen
)
)
{
{
if
(
ToVpd
!=
Fvplast
)
if
(
ToVpd
!=
Fvplast
)
{
{
...
@@ -943,7 +1020,7 @@ _vc_rpfheap (VRelList curvrl, Relation onerel,
...
@@ -943,7 +1020,7 @@ _vc_rpfheap (VRelList curvrl, Relation onerel,
}
}
for
(
i
=
0
;
i
<
Fnpages
;
i
++
)
for
(
i
=
0
;
i
<
Fnpages
;
i
++
)
{
{
if
(
_
vc_enough_space
(
Fvpl
->
vpl_pgdesc
[
i
],
tlen
)
)
if
(
vc_enough_space
(
Fvpl
->
vpl_pgdesc
[
i
],
tlen
)
)
break
;
break
;
}
}
if
(
i
==
Fnpages
)
if
(
i
==
Fnpages
)
...
@@ -954,7 +1031,7 @@ _vc_rpfheap (VRelList curvrl, Relation onerel,
...
@@ -954,7 +1031,7 @@ _vc_rpfheap (VRelList curvrl, Relation onerel,
ToPage
=
BufferGetPage
(
ToBuf
);
ToPage
=
BufferGetPage
(
ToBuf
);
/* if this page was not used before - clean it */
/* if this page was not used before - clean it */
if
(
!
PageIsEmpty
(
ToPage
)
&&
ToVpd
->
vpd_nusd
==
0
)
if
(
!
PageIsEmpty
(
ToPage
)
&&
ToVpd
->
vpd_nusd
==
0
)
_
vc_vacpage
(
ToPage
,
ToVpd
,
archrel
);
vc_vacpage
(
ToPage
,
ToVpd
,
archrel
);
}
}
/* copy tuple */
/* copy tuple */
...
@@ -1022,7 +1099,7 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
...
@@ -1022,7 +1099,7 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
if
(
vpc
->
vpd_noff
>
0
)
/* some tuples were moved */
if
(
vpc
->
vpd_noff
>
0
)
/* some tuples were moved */
{
{
_
vc_reappage
(
&
Nvpl
,
vpc
);
vc_reappage
(
&
Nvpl
,
vpc
);
WriteBuffer
(
buf
);
WriteBuffer
(
buf
);
}
}
else
if
(
dowrite
)
else
if
(
dowrite
)
...
@@ -1071,7 +1148,7 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
...
@@ -1071,7 +1148,7 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
{
{
/* noff == 0 in empty pages only - such pages should be re-used */
/* noff == 0 in empty pages only - such pages should be re-used */
Assert
(
(
*
vpp
)
->
vpd_noff
>
0
);
Assert
(
(
*
vpp
)
->
vpd_noff
>
0
);
_
vc_vacpage
(
page
,
*
vpp
,
archrel
);
vc_vacpage
(
page
,
*
vpp
,
archrel
);
}
}
else
/* this page was used */
else
/* this page was used */
{
{
...
@@ -1100,7 +1177,7 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
...
@@ -1100,7 +1177,7 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
getrusage
(
RUSAGE_SELF
,
&
ru1
);
getrusage
(
RUSAGE_SELF
,
&
ru1
);
elog
(
MESS
LEV
,
"Rel %.*s: Pages: %u --> %u; Tuple(s) moved: %u. \
elog
(
MESS
AGE_LEVEL
,
"Rel %.*s: Pages: %u --> %u; Tuple(s) moved: %u. \
Elapsed %u/%u sec."
,
Elapsed %u/%u sec."
,
NAMEDATALEN
,
(
RelationGetRelationName
(
onerel
))
->
data
,
NAMEDATALEN
,
(
RelationGetRelationName
(
onerel
))
->
data
,
nblocks
,
blkno
,
nmoved
,
nblocks
,
blkno
,
nmoved
,
...
@@ -1122,7 +1199,7 @@ Elapsed %u/%u sec.",
...
@@ -1122,7 +1199,7 @@ Elapsed %u/%u sec.",
vpsave
=
*
vpleft
;
*
vpleft
=
*
vpright
;
*
vpright
=
vpsave
;
vpsave
=
*
vpleft
;
*
vpleft
=
*
vpright
;
*
vpright
=
vpsave
;
}
}
for
(
i
=
0
;
i
<
nindices
;
i
++
)
for
(
i
=
0
;
i
<
nindices
;
i
++
)
_vc_vaconeind
(
&
Nvpl
,
Irel
[
i
],
curvrl
->
vrl_
ntups
);
vc_vaconeind
(
&
Nvpl
,
Irel
[
i
],
vacrelstats
->
ntups
);
}
}
/*
/*
...
@@ -1165,7 +1242,7 @@ Elapsed %u/%u sec.",
...
@@ -1165,7 +1242,7 @@ Elapsed %u/%u sec.",
{
{
blkno
=
smgrtruncate
(
onerel
->
rd_rel
->
relsmgr
,
onerel
,
blkno
);
blkno
=
smgrtruncate
(
onerel
->
rd_rel
->
relsmgr
,
onerel
,
blkno
);
Assert
(
blkno
>=
0
);
Assert
(
blkno
>=
0
);
curvrl
->
vrl_
npages
=
blkno
;
/* set new number of blocks */
vacrelstats
->
npages
=
blkno
;
/* set new number of blocks */
}
}
if
(
archrel
!=
(
Relation
)
NULL
)
if
(
archrel
!=
(
Relation
)
NULL
)
...
@@ -1176,21 +1253,21 @@ Elapsed %u/%u sec.",
...
@@ -1176,21 +1253,21 @@ Elapsed %u/%u sec.",
pfree
(
Idesc
);
pfree
(
Idesc
);
pfree
(
idatum
);
pfree
(
idatum
);
pfree
(
inulls
);
pfree
(
inulls
);
_
vc_clsindices
(
nindices
,
Irel
);
vc_clsindices
(
nindices
,
Irel
);
}
}
pfree
(
vpc
);
pfree
(
vpc
);
}
/*
_
vc_rpfheap */
}
/* vc_rpfheap */
/*
/*
*
_
vc_vacheap() -- free dead tuples
* vc_vacheap() -- free dead tuples
*
*
* This routine marks dead tuples as unused and truncates relation
* This routine marks dead tuples as unused and truncates relation
* if there are "empty" end-blocks.
* if there are "empty" end-blocks.
*/
*/
static
void
static
void
_vc_vacheap
(
VRelList
curvrl
,
Relation
onerel
,
VPageList
Vvpl
)
vc_vacheap
(
VRelStats
*
vacrelstats
,
Relation
onerel
,
VPageList
Vvpl
)
{
{
Buffer
buf
;
Buffer
buf
;
Page
page
;
Page
page
;
...
@@ -1202,7 +1279,7 @@ _vc_vacheap (VRelList curvrl, Relation onerel, VPageList Vvpl)
...
@@ -1202,7 +1279,7 @@ _vc_vacheap (VRelList curvrl, Relation onerel, VPageList Vvpl)
nblocks
=
Vvpl
->
vpl_npages
;
nblocks
=
Vvpl
->
vpl_npages
;
/* if the relation has an archive, open it */
/* if the relation has an archive, open it */
if
(
onerel
->
rd_rel
->
relarch
!=
'n'
)
if
(
onerel
->
rd_rel
->
relarch
!=
'n'
)
archrel
=
_
vc_getarchrel
(
onerel
);
archrel
=
vc_getarchrel
(
onerel
);
else
else
{
{
archrel
=
(
Relation
)
NULL
;
archrel
=
(
Relation
)
NULL
;
...
@@ -1215,7 +1292,7 @@ _vc_vacheap (VRelList curvrl, Relation onerel, VPageList Vvpl)
...
@@ -1215,7 +1292,7 @@ _vc_vacheap (VRelList curvrl, Relation onerel, VPageList Vvpl)
{
{
buf
=
ReadBuffer
(
onerel
,
(
*
vpp
)
->
vpd_blkno
);
buf
=
ReadBuffer
(
onerel
,
(
*
vpp
)
->
vpd_blkno
);
page
=
BufferGetPage
(
buf
);
page
=
BufferGetPage
(
buf
);
_
vc_vacpage
(
page
,
*
vpp
,
archrel
);
vc_vacpage
(
page
,
*
vpp
,
archrel
);
WriteBuffer
(
buf
);
WriteBuffer
(
buf
);
}
}
}
}
...
@@ -1223,11 +1300,11 @@ _vc_vacheap (VRelList curvrl, Relation onerel, VPageList Vvpl)
...
@@ -1223,11 +1300,11 @@ _vc_vacheap (VRelList curvrl, Relation onerel, VPageList Vvpl)
/* truncate relation if there are some empty end-pages */
/* truncate relation if there are some empty end-pages */
if
(
Vvpl
->
vpl_nemend
>
0
)
if
(
Vvpl
->
vpl_nemend
>
0
)
{
{
Assert
(
curvrl
->
vrl_
npages
>=
Vvpl
->
vpl_nemend
);
Assert
(
vacrelstats
->
npages
>=
Vvpl
->
vpl_nemend
);
nblocks
=
curvrl
->
vrl_
npages
-
Vvpl
->
vpl_nemend
;
nblocks
=
vacrelstats
->
npages
-
Vvpl
->
vpl_nemend
;
elog
(
MESS
LEV
,
"Rel %.*s: Pages: %u --> %u."
,
elog
(
MESS
AGE_LEVEL
,
"Rel %.*s: Pages: %u --> %u."
,
NAMEDATALEN
,
(
RelationGetRelationName
(
onerel
))
->
data
,
NAMEDATALEN
,
(
RelationGetRelationName
(
onerel
))
->
data
,
curvrl
->
vrl_
npages
,
nblocks
);
vacrelstats
->
npages
,
nblocks
);
/*
/*
* we have to flush "empty" end-pages (if changed, but who knows it)
* we have to flush "empty" end-pages (if changed, but who knows it)
...
@@ -1237,20 +1314,20 @@ _vc_vacheap (VRelList curvrl, Relation onerel, VPageList Vvpl)
...
@@ -1237,20 +1314,20 @@ _vc_vacheap (VRelList curvrl, Relation onerel, VPageList Vvpl)
nblocks
=
smgrtruncate
(
onerel
->
rd_rel
->
relsmgr
,
onerel
,
nblocks
);
nblocks
=
smgrtruncate
(
onerel
->
rd_rel
->
relsmgr
,
onerel
,
nblocks
);
Assert
(
nblocks
>=
0
);
Assert
(
nblocks
>=
0
);
curvrl
->
vrl_
npages
=
nblocks
;
/* set new number of blocks */
vacrelstats
->
npages
=
nblocks
;
/* set new number of blocks */
}
}
if
(
archrel
!=
(
Relation
)
NULL
)
if
(
archrel
!=
(
Relation
)
NULL
)
heap_close
(
archrel
);
heap_close
(
archrel
);
}
/*
_
vc_vacheap */
}
/* vc_vacheap */
/*
/*
*
_
vc_vacpage() -- free (and archive if needed) dead tuples on a page
* vc_vacpage() -- free (and archive if needed) dead tuples on a page
* and repaire its fragmentation.
* and repaire its fragmentation.
*/
*/
static
void
static
void
_
vc_vacpage
(
Page
page
,
VPageDescr
vpd
,
Relation
archrel
)
vc_vacpage
(
Page
page
,
VPageDescr
vpd
,
Relation
archrel
)
{
{
ItemId
itemid
;
ItemId
itemid
;
HeapTuple
htup
;
HeapTuple
htup
;
...
@@ -1263,20 +1340,20 @@ _vc_vacpage (Page page, VPageDescr vpd, Relation archrel)
...
@@ -1263,20 +1340,20 @@ _vc_vacpage (Page page, VPageDescr vpd, Relation archrel)
if
(
archrel
!=
(
Relation
)
NULL
&&
ItemIdIsUsed
(
itemid
)
)
if
(
archrel
!=
(
Relation
)
NULL
&&
ItemIdIsUsed
(
itemid
)
)
{
{
htup
=
(
HeapTuple
)
PageGetItem
(
page
,
itemid
);
htup
=
(
HeapTuple
)
PageGetItem
(
page
,
itemid
);
_
vc_archive
(
archrel
,
htup
);
vc_archive
(
archrel
,
htup
);
}
}
itemid
->
lp_flags
&=
~
LP_USED
;
itemid
->
lp_flags
&=
~
LP_USED
;
}
}
PageRepairFragmentation
(
page
);
PageRepairFragmentation
(
page
);
}
/*
_
vc_vacpage */
}
/* vc_vacpage */
/*
/*
* _vc_scanoneind() -- scan one index relation to update statistic.
* _vc_scanoneind() -- scan one index relation to update statistic.
*
*
*/
*/
static
void
static
void
_
vc_scanoneind
(
Relation
indrel
,
int
nhtups
)
vc_scanoneind
(
Relation
indrel
,
int
nhtups
)
{
{
RetrieveIndexResult
res
;
RetrieveIndexResult
res
;
IndexScanDesc
iscan
;
IndexScanDesc
iscan
;
...
@@ -1301,11 +1378,11 @@ _vc_scanoneind (Relation indrel, int nhtups)
...
@@ -1301,11 +1378,11 @@ _vc_scanoneind (Relation indrel, int nhtups)
/* now update statistics in pg_class */
/* now update statistics in pg_class */
nipages
=
RelationGetNumberOfBlocks
(
indrel
);
nipages
=
RelationGetNumberOfBlocks
(
indrel
);
_vc_updstats
(
indrel
->
rd_id
,
nipages
,
nitups
,
false
);
vc_updstats
(
indrel
->
rd_id
,
nipages
,
nitups
,
false
,
NULL
);
getrusage
(
RUSAGE_SELF
,
&
ru1
);
getrusage
(
RUSAGE_SELF
,
&
ru1
);
elog
(
MESS
LEV
,
"Ind %.*s: Pages %u; Tuples %u. Elapsed %u/%u sec."
,
elog
(
MESS
AGE_LEVEL
,
"Ind %.*s: Pages %u; Tuples %u. Elapsed %u/%u sec."
,
NAMEDATALEN
,
indrel
->
rd_rel
->
relname
.
data
,
nipages
,
nitups
,
NAMEDATALEN
,
indrel
->
rd_rel
->
relname
.
data
,
nipages
,
nitups
,
ru1
.
ru_stime
.
tv_sec
-
ru0
.
ru_stime
.
tv_sec
,
ru1
.
ru_stime
.
tv_sec
-
ru0
.
ru_stime
.
tv_sec
,
ru1
.
ru_utime
.
tv_sec
-
ru0
.
ru_utime
.
tv_sec
);
ru1
.
ru_utime
.
tv_sec
-
ru0
.
ru_utime
.
tv_sec
);
...
@@ -1314,10 +1391,10 @@ _vc_scanoneind (Relation indrel, int nhtups)
...
@@ -1314,10 +1391,10 @@ _vc_scanoneind (Relation indrel, int nhtups)
elog
(
NOTICE
,
"NUMBER OF INDEX' TUPLES (%u) IS NOT THE SAME AS HEAP' (%u)"
,
elog
(
NOTICE
,
"NUMBER OF INDEX' TUPLES (%u) IS NOT THE SAME AS HEAP' (%u)"
,
nitups
,
nhtups
);
nitups
,
nhtups
);
}
/*
_
vc_scanoneind */
}
/* vc_scanoneind */
/*
/*
*
_
vc_vaconeind() -- vacuum one index relation.
* vc_vaconeind() -- vacuum one index relation.
*
*
* Vpl is the VPageList of the heap we're currently vacuuming.
* Vpl is the VPageList of the heap we're currently vacuuming.
* It's locked. Indrel is an index relation on the vacuumed heap.
* It's locked. Indrel is an index relation on the vacuumed heap.
...
@@ -1329,7 +1406,7 @@ _vc_scanoneind (Relation indrel, int nhtups)
...
@@ -1329,7 +1406,7 @@ _vc_scanoneind (Relation indrel, int nhtups)
* pg_class.
* pg_class.
*/
*/
static
void
static
void
_
vc_vaconeind
(
VPageList
vpl
,
Relation
indrel
,
int
nhtups
)
vc_vaconeind
(
VPageList
vpl
,
Relation
indrel
,
int
nhtups
)
{
{
RetrieveIndexResult
res
;
RetrieveIndexResult
res
;
IndexScanDesc
iscan
;
IndexScanDesc
iscan
;
...
@@ -1351,7 +1428,7 @@ _vc_vaconeind(VPageList vpl, Relation indrel, int nhtups)
...
@@ -1351,7 +1428,7 @@ _vc_vaconeind(VPageList vpl, Relation indrel, int nhtups)
!=
(
RetrieveIndexResult
)
NULL
)
{
!=
(
RetrieveIndexResult
)
NULL
)
{
heapptr
=
&
res
->
heap_iptr
;
heapptr
=
&
res
->
heap_iptr
;
if
(
(
vp
=
_
vc_tidreapped
(
heapptr
,
vpl
))
!=
(
VPageDescr
)
NULL
)
if
(
(
vp
=
vc_tidreapped
(
heapptr
,
vpl
))
!=
(
VPageDescr
)
NULL
)
{
{
#if 0
#if 0
elog(DEBUG, "<%x,%x> -> <%x,%x>",
elog(DEBUG, "<%x,%x> -> <%x,%x>",
...
@@ -1380,11 +1457,11 @@ _vc_vaconeind(VPageList vpl, Relation indrel, int nhtups)
...
@@ -1380,11 +1457,11 @@ _vc_vaconeind(VPageList vpl, Relation indrel, int nhtups)
/* now update statistics in pg_class */
/* now update statistics in pg_class */
nipages
=
RelationGetNumberOfBlocks
(
indrel
);
nipages
=
RelationGetNumberOfBlocks
(
indrel
);
_vc_updstats
(
indrel
->
rd_id
,
nipages
,
nitups
,
false
);
vc_updstats
(
indrel
->
rd_id
,
nipages
,
nitups
,
false
,
NULL
);
getrusage
(
RUSAGE_SELF
,
&
ru1
);
getrusage
(
RUSAGE_SELF
,
&
ru1
);
elog
(
MESS
LEV
,
"Ind %.*s: Pages %u; Tuples %u: Deleted %u. Elapsed %u/%u sec."
,
elog
(
MESS
AGE_LEVEL
,
"Ind %.*s: Pages %u; Tuples %u: Deleted %u. Elapsed %u/%u sec."
,
NAMEDATALEN
,
indrel
->
rd_rel
->
relname
.
data
,
nipages
,
nitups
,
nvac
,
NAMEDATALEN
,
indrel
->
rd_rel
->
relname
.
data
,
nipages
,
nitups
,
nvac
,
ru1
.
ru_stime
.
tv_sec
-
ru0
.
ru_stime
.
tv_sec
,
ru1
.
ru_stime
.
tv_sec
-
ru0
.
ru_stime
.
tv_sec
,
ru1
.
ru_utime
.
tv_sec
-
ru0
.
ru_utime
.
tv_sec
);
ru1
.
ru_utime
.
tv_sec
-
ru0
.
ru_utime
.
tv_sec
);
...
@@ -1393,15 +1470,15 @@ _vc_vaconeind(VPageList vpl, Relation indrel, int nhtups)
...
@@ -1393,15 +1470,15 @@ _vc_vaconeind(VPageList vpl, Relation indrel, int nhtups)
elog
(
NOTICE
,
"NUMBER OF INDEX' TUPLES (%u) IS NOT THE SAME AS HEAP' (%u)"
,
elog
(
NOTICE
,
"NUMBER OF INDEX' TUPLES (%u) IS NOT THE SAME AS HEAP' (%u)"
,
nitups
,
nhtups
);
nitups
,
nhtups
);
}
/*
_
vc_vaconeind */
}
/* vc_vaconeind */
/*
/*
*
_
vc_tidreapped() -- is a particular tid reapped?
* vc_tidreapped() -- is a particular tid reapped?
*
*
* vpl->VPageDescr_array is sorted in right order.
* vpl->VPageDescr_array is sorted in right order.
*/
*/
static
VPageDescr
static
VPageDescr
_
vc_tidreapped
(
ItemPointer
itemptr
,
VPageList
vpl
)
vc_tidreapped
(
ItemPointer
itemptr
,
VPageList
vpl
)
{
{
OffsetNumber
ioffno
;
OffsetNumber
ioffno
;
OffsetNumber
*
voff
;
OffsetNumber
*
voff
;
...
@@ -1412,9 +1489,9 @@ _vc_tidreapped(ItemPointer itemptr, VPageList vpl)
...
@@ -1412,9 +1489,9 @@ _vc_tidreapped(ItemPointer itemptr, VPageList vpl)
ioffno
=
ItemPointerGetOffsetNumber
(
itemptr
);
ioffno
=
ItemPointerGetOffsetNumber
(
itemptr
);
vp
=
&
vpd
;
vp
=
&
vpd
;
vpp
=
(
VPageDescr
*
)
_
vc_find_eq
((
char
*
)(
vpl
->
vpl_pgdesc
),
vpp
=
(
VPageDescr
*
)
vc_find_eq
((
char
*
)(
vpl
->
vpl_pgdesc
),
vpl
->
vpl_npages
,
sizeof
(
VPageDescr
),
(
char
*
)
&
vp
,
vpl
->
vpl_npages
,
sizeof
(
VPageDescr
),
(
char
*
)
&
vp
,
_
vc_cmp_blk
);
vc_cmp_blk
);
if
(
vpp
==
(
VPageDescr
*
)
NULL
)
if
(
vpp
==
(
VPageDescr
*
)
NULL
)
return
((
VPageDescr
)
NULL
);
return
((
VPageDescr
)
NULL
);
...
@@ -1426,74 +1503,333 @@ _vc_tidreapped(ItemPointer itemptr, VPageList vpl)
...
@@ -1426,74 +1503,333 @@ _vc_tidreapped(ItemPointer itemptr, VPageList vpl)
return
(
vp
);
return
(
vp
);
}
}
voff
=
(
OffsetNumber
*
)
_
vc_find_eq
((
char
*
)(
vp
->
vpd_voff
),
voff
=
(
OffsetNumber
*
)
vc_find_eq
((
char
*
)(
vp
->
vpd_voff
),
vp
->
vpd_noff
,
sizeof
(
OffsetNumber
),
(
char
*
)
&
ioffno
,
vp
->
vpd_noff
,
sizeof
(
OffsetNumber
),
(
char
*
)
&
ioffno
,
_
vc_cmp_offno
);
vc_cmp_offno
);
if
(
voff
==
(
OffsetNumber
*
)
NULL
)
if
(
voff
==
(
OffsetNumber
*
)
NULL
)
return
((
VPageDescr
)
NULL
);
return
((
VPageDescr
)
NULL
);
return
(
vp
);
return
(
vp
);
}
/* _vc_tidreapped */
}
/* vc_tidreapped */
/*
* vc_attrstats() -- compute column statistics used by the optimzer
*
* We compute the column min, max, null and non-null counts.
* Plus we attempt to find the count of the value that occurs most
* frequently in each column
* These figures are used to compute the selectivity of the column
*
* We use a three-bucked cache to get the most frequent item
* The 'guess' buckets count hits. A cache miss causes guess1
* to get the most hit 'guess' item in the most recent cycle, and
* the new item goes into guess2. Whenever the total count of hits
* of a 'guess' entry is larger than 'best', 'guess' becomes 'best'.
*
* This method works perfectly for columns with unique values, and columns
* with only two unique values, plus nulls.
*
* It becomes less perfect as the number of unique values increases and
* their distribution in the table becomes more random.
*
*/
static
void
vc_attrstats
(
Relation
onerel
,
VacAttrStats
*
vacattrstats
,
HeapTuple
htup
)
{
int
i
,
attr_cnt
;
AttributeTupleForm
*
attr
;
TupleDesc
tupDesc
;
Datum
value
;
bool
isnull
;
attr_cnt
=
onerel
->
rd_att
->
natts
;
attr
=
onerel
->
rd_att
->
attrs
;
tupDesc
=
onerel
->
rd_att
;
for
(
i
=
0
;
i
<
attr_cnt
;
i
++
)
{
VacAttrStats
*
stats
=
&
vacattrstats
[
i
];
bool
value_hit
=
true
;
value
=
(
Datum
)
heap_getattr
(
htup
,
InvalidBuffer
,
i
+
1
,
tupDesc
,
&
isnull
);
if
(
!
VacAttrStatsEqValid
(
stats
))
continue
;
if
(
isnull
)
stats
->
null_cnt
++
;
else
{
stats
->
nonnull_cnt
++
;
if
(
stats
->
initialized
==
false
)
{
vc_bucketcpy
(
stats
->
attr
,
value
,
&
stats
->
best
,
&
stats
->
best_len
);
/* best_cnt gets incremented later */
vc_bucketcpy
(
stats
->
attr
,
value
,
&
stats
->
guess1
,
&
stats
->
guess1_len
);
stats
->
guess1_cnt
=
stats
->
guess1_hits
=
1
;
vc_bucketcpy
(
stats
->
attr
,
value
,
&
stats
->
guess2
,
&
stats
->
guess2_len
);
stats
->
guess2_hits
=
1
;
if
(
VacAttrStatsLtGtValid
(
stats
))
{
vc_bucketcpy
(
stats
->
attr
,
value
,
&
stats
->
max
,
&
stats
->
max_len
);
vc_bucketcpy
(
stats
->
attr
,
value
,
&
stats
->
min
,
&
stats
->
min_len
);
}
stats
->
initialized
=
true
;
}
if
(
VacAttrStatsLtGtValid
(
stats
)
&&
fmgr
(
stats
->
cmplt
,
value
,
stats
->
min
))
{
vc_bucketcpy
(
stats
->
attr
,
value
,
&
stats
->
min
,
&
stats
->
min_len
);
stats
->
min_cnt
=
0
;
}
if
(
VacAttrStatsLtGtValid
(
stats
)
&&
fmgr
(
stats
->
cmpgt
,
value
,
stats
->
max
))
{
vc_bucketcpy
(
stats
->
attr
,
value
,
&
stats
->
max
,
&
stats
->
max_len
);
stats
->
max_cnt
=
0
;
}
if
(
VacAttrStatsLtGtValid
(
stats
)
&&
fmgr
(
stats
->
cmpeq
,
value
,
stats
->
min
))
stats
->
min_cnt
++
;
else
if
(
VacAttrStatsLtGtValid
(
stats
)
&&
fmgr
(
stats
->
cmpeq
,
value
,
stats
->
max
))
stats
->
max_cnt
++
;
if
(
fmgr
(
stats
->
cmpeq
,
value
,
stats
->
best
))
stats
->
best_cnt
++
;
else
if
(
fmgr
(
stats
->
cmpeq
,
value
,
stats
->
guess1
))
{
stats
->
guess1_cnt
++
;
stats
->
guess1_hits
++
;
}
else
if
(
fmgr
(
stats
->
cmpeq
,
value
,
stats
->
guess2
))
stats
->
guess2_hits
++
;
else
value_hit
=
false
;
if
(
stats
->
guess2_hits
>
stats
->
guess1_hits
)
{
swapDatum
(
stats
->
guess1
,
stats
->
guess2
);
swapInt
(
stats
->
guess1_len
,
stats
->
guess2_len
);
stats
->
guess1_cnt
=
stats
->
guess2_hits
;
swapLong
(
stats
->
guess1_hits
,
stats
->
guess2_hits
);
}
if
(
stats
->
guess1_cnt
>
stats
->
best_cnt
)
{
swapDatum
(
stats
->
best
,
stats
->
guess1
);
swapLong
(
stats
->
best_cnt
,
stats
->
guess1_cnt
);
stats
->
guess1_hits
=
1
;
stats
->
guess2_hits
=
1
;
}
if
(
!
value_hit
)
{
vc_bucketcpy
(
stats
->
attr
,
value
,
&
stats
->
guess2
,
&
stats
->
guess2_len
);
stats
->
guess1_hits
=
1
;
stats
->
guess2_hits
=
1
;
}
}
}
return
;
}
/*
* vc_bucketcpy() -- update pg_class statistics for one relation
*
*/
static
void
vc_bucketcpy
(
AttributeTupleForm
attr
,
Datum
value
,
Datum
*
bucket
,
int16
*
bucket_len
)
{
if
(
attr
->
attbyval
&&
attr
->
attlen
!=
-
1
)
*
bucket
=
value
;
else
{
int
len
=
(
attr
->
attlen
!=
-
1
?
attr
->
attlen
:
VARSIZE
(
value
));
if
(
len
>
*
bucket_len
)
{
if
(
*
bucket_len
!=
0
)
pfree
(
DatumGetPointer
(
*
bucket
));
*
bucket
=
PointerGetDatum
(
palloc
(
len
));
*
bucket_len
=
len
;
}
memmove
(
DatumGetPointer
(
*
bucket
),
DatumGetPointer
(
value
),
len
);
}
}
/*
/*
*
_
vc_updstats() -- update pg_class statistics for one relation
* vc_updstats() -- update pg_class statistics for one relation
*
*
* This routine works for both index and heap relation entries in
* This routine works for both index and heap relation entries in
* pg_class. We violate no-overwrite semantics here by storing new
* pg_class. We violate no-overwrite semantics here by storing new
* values for ntup
le
s, npages, and hasindex directly in the pg_class
* values for ntups, npages, and hasindex directly in the pg_class
* tuple that's already on the page. The reason for this is that if
* tuple that's already on the page. The reason for this is that if
* we updated these tuples in the usual way, then every tuple in pg_class
* we updated these tuples in the usual way, then every tuple in pg_class
* would be replaced every day. This would make planning and executing
* would be replaced every day. This would make planning and executing
* historical queries very expensive.
* historical queries very expensive.
*/
*/
static
void
static
void
_vc_updstats
(
Oid
relid
,
int
npages
,
int
ntuples
,
bool
hasindex
)
vc_updstats
(
Oid
relid
,
int
npages
,
int
ntups
,
bool
hasindex
,
VacAttrStats
*
vacattrstats
)
{
{
Relation
rd
;
Relation
rd
,
ad
,
sd
;
HeapScanDesc
sdesc
;
HeapScanDesc
rsdesc
,
asdesc
;
HeapTuple
tup
;
TupleDesc
sdesc
;
Buffer
buf
;
HeapTuple
rtup
,
atup
,
stup
;
Buffer
rbuf
,
abuf
;
Form_pg_class
pgcform
;
Form_pg_class
pgcform
;
ScanKeyData
skey
;
ScanKeyData
rskey
,
askey
;
AttributeTupleForm
attp
;
/*
/*
* update number of tuples and number of pages in pg_class
* update number of tuples and number of pages in pg_class
*/
*/
ScanKeyEntryInitialize
(
&
skey
,
0x0
,
ObjectIdAttributeNumber
,
ScanKeyEntryInitialize
(
&
r
skey
,
0x0
,
ObjectIdAttributeNumber
,
ObjectIdEqualRegProcedure
,
ObjectIdEqualRegProcedure
,
ObjectIdGetDatum
(
relid
));
ObjectIdGetDatum
(
relid
));
rd
=
heap_openr
(
RelationRelationName
);
rd
=
heap_openr
(
RelationRelationName
);
sdesc
=
heap_beginscan
(
rd
,
false
,
NowTimeQual
,
1
,
&
skey
);
rsdesc
=
heap_beginscan
(
rd
,
false
,
NowTimeQual
,
1
,
&
r
skey
);
if
(
!
HeapTupleIsValid
(
tup
=
heap_getnext
(
sdesc
,
0
,
&
buf
)))
if
(
!
HeapTupleIsValid
(
rtup
=
heap_getnext
(
rsdesc
,
0
,
&
r
buf
)))
elog
(
WARN
,
"pg_class entry for relid %d vanished during vacuuming"
,
elog
(
WARN
,
"pg_class entry for relid %d vanished during vacuuming"
,
relid
);
relid
);
/* overwrite the existing statistics in the tuple */
/* overwrite the existing statistics in the tuple */
_vc_setpagelock
(
rd
,
BufferGetBlockNumber
(
buf
));
vc_setpagelock
(
rd
,
BufferGetBlockNumber
(
r
buf
));
pgcform
=
(
Form_pg_class
)
GETSTRUCT
(
tup
);
pgcform
=
(
Form_pg_class
)
GETSTRUCT
(
r
tup
);
pgcform
->
reltuples
=
ntup
le
s
;
pgcform
->
reltuples
=
ntups
;
pgcform
->
relpages
=
npages
;
pgcform
->
relpages
=
npages
;
pgcform
->
relhasindex
=
hasindex
;
pgcform
->
relhasindex
=
hasindex
;
if
(
vacattrstats
!=
NULL
)
{
ad
=
heap_openr
(
AttributeRelationName
);
sd
=
heap_openr
(
StatisticRelationName
);
ScanKeyEntryInitialize
(
&
askey
,
0
,
Anum_pg_attribute_attrelid
,
F_INT4EQ
,
relid
);
asdesc
=
heap_beginscan
(
ad
,
false
,
NowTimeQual
,
1
,
&
askey
);
while
(
HeapTupleIsValid
(
atup
=
heap_getnext
(
asdesc
,
0
,
&
abuf
)))
{
int
slot
,
i
;
double
selratio
;
/* average ratio of rows selected for a random constant */
VacAttrStats
*
stats
;
Datum
values
[
Natts_pg_statistic
];
char
nulls
[
Natts_pg_statistic
];
attp
=
(
AttributeTupleForm
)
GETSTRUCT
(
atup
);
slot
=
attp
->
attnum
-
1
;
if
(
slot
<
0
)
/* skip system attributes for now,
they are unique anyway */
continue
;
stats
=
&
vacattrstats
[
slot
];
/* overwrite the existing statistics in the tuple */
if
(
VacAttrStatsEqValid
(
stats
))
{
vc_setpagelock
(
ad
,
BufferGetBlockNumber
(
abuf
));
if
(
stats
->
nonnull_cnt
+
stats
->
null_cnt
==
0
||
(
stats
->
null_cnt
<=
1
&&
stats
->
best_cnt
==
1
))
selratio
=
0
;
else
if
(
VacAttrStatsLtGtValid
(
stats
)
&&
stats
->
min_cnt
+
stats
->
max_cnt
==
stats
->
nonnull_cnt
)
{
double
min_cnt_d
=
stats
->
min_cnt
,
max_cnt_d
=
stats
->
max_cnt
,
null_cnt_d
=
stats
->
null_cnt
,
nonnullcnt_d
=
stats
->
nonnull_cnt
;
/* prevent overflow */
selratio
=
(
min_cnt_d
*
min_cnt_d
+
max_cnt_d
*
max_cnt_d
+
null_cnt_d
*
null_cnt_d
)
/
(
nonnullcnt_d
+
null_cnt_d
)
/
(
nonnullcnt_d
+
null_cnt_d
);
}
else
{
double
most
=
(
double
)(
stats
->
best_cnt
>
stats
->
null_cnt
?
stats
->
best_cnt
:
stats
->
null_cnt
);
double
total
=
((
double
)
stats
->
nonnull_cnt
)
+
((
double
)
stats
->
null_cnt
);
/* we assume count of other values are 20%
of best count in table */
selratio
=
(
most
*
most
+
0
.
20
*
most
*
(
total
-
most
))
/
total
/
total
;
}
if
(
selratio
>
1
.
0
)
selratio
=
1
.
0
;
attp
->
attnvals
=
(
selratio
?
(
selratio
*
ATTNVALS_SCALE
)
:
0
);
WriteNoReleaseBuffer
(
abuf
);
/* DO PG_STATISTIC INSERTS */
/* doing system relations, especially pg_statistic is a problem */
if
(
VacAttrStatsLtGtValid
(
stats
)
&&
stats
->
initialized
/* &&
!IsSystemRelationName(pgcform->relname.data)*/
)
{
func_ptr
out_function
;
char
*
out_string
;
int
dummy
;
for
(
i
=
0
;
i
<
Natts_pg_statistic
;
++
i
)
nulls
[
i
]
=
' '
;
/* ----------------
* initialize values[]
* ----------------
*/
i
=
0
;
values
[
i
++
]
=
(
Datum
)
relid
;
/* 1 */
values
[
i
++
]
=
(
Datum
)
attp
->
attnum
;
/* 2 */
values
[
i
++
]
=
(
Datum
)
InvalidOid
;
/* 3 */
fmgr_info
(
stats
->
outfunc
,
&
out_function
,
&
dummy
);
out_string
=
(
*
out_function
)(
stats
->
min
,
stats
->
attr
->
atttypid
);
values
[
i
++
]
=
(
Datum
)
fmgr
(
TextInRegProcedure
,
out_string
);
pfree
(
out_string
);
out_string
=
(
char
*
)(
*
out_function
)(
stats
->
max
,
stats
->
attr
->
atttypid
);
values
[
i
++
]
=
(
Datum
)
fmgr
(
TextInRegProcedure
,
out_string
);
pfree
(
out_string
);
sdesc
=
sd
->
rd_att
;
stup
=
heap_formtuple
(
sdesc
,
values
,
nulls
);
/* ----------------
* insert the tuple in the relation and get the tuple's oid.
* ----------------
*/
heap_insert
(
sd
,
stup
);
pfree
(
DatumGetPointer
(
values
[
3
]));
pfree
(
DatumGetPointer
(
values
[
4
]));
pfree
(
stup
);
}
}
}
heap_endscan
(
asdesc
);
heap_close
(
ad
);
heap_close
(
sd
);
}
/* XXX -- after write, should invalidate relcache in other backends */
/* XXX -- after write, should invalidate relcache in other backends */
WriteNoReleaseBuffer
(
buf
);
/* heap_endscan release scan' buffers ? */
WriteNoReleaseBuffer
(
r
buf
);
/* heap_endscan release scan' buffers ? */
/* invalidating system relations confuses the function cache
/* invalidating system relations confuses the function cache
of pg_operator and pg_opclass */
of pg_operator and pg_opclass */
if
(
!
IsSystemRelationName
(
pgcform
->
relname
.
data
))
if
(
!
IsSystemRelationName
(
pgcform
->
relname
.
data
))
RelationInvalidateHeapTuple
(
rd
,
tup
);
RelationInvalidateHeapTuple
(
rd
,
r
tup
);
/* that's all, folks */
/* that's all, folks */
heap_endscan
(
sdesc
);
heap_endscan
(
r
sdesc
);
heap_close
(
rd
);
heap_close
(
rd
);
}
}
static
void
_vc_setpagelock
(
Relation
rel
,
BlockNumber
blkno
)
/*
* vc_delhilowstats() -- delete pg_statistics rows
*
*/
static
void
vc_delhilowstats
(
Oid
relid
)
{
Relation
pgstatistic
;
HeapScanDesc
pgsscan
;
HeapTuple
pgstup
;
ScanKeyData
pgskey
;
pgstatistic
=
heap_openr
(
StatisticRelationName
);
if
(
relid
!=
InvalidOid
)
{
ScanKeyEntryInitialize
(
&
pgskey
,
0x0
,
Anum_pg_statistic_starelid
,
ObjectIdEqualRegProcedure
,
ObjectIdGetDatum
(
relid
));
pgsscan
=
heap_beginscan
(
pgstatistic
,
false
,
NowTimeQual
,
1
,
&
pgskey
);
}
else
pgsscan
=
heap_beginscan
(
pgstatistic
,
false
,
NowTimeQual
,
0
,
NULL
);
while
(
HeapTupleIsValid
(
pgstup
=
heap_getnext
(
pgsscan
,
0
,
NULL
)))
{
heap_delete
(
pgstatistic
,
&
pgstup
->
t_ctid
);
}
heap_endscan
(
pgsscan
);
heap_close
(
pgstatistic
);
}
static
void
vc_setpagelock
(
Relation
rel
,
BlockNumber
blkno
)
{
{
ItemPointerData
itm
;
ItemPointerData
itm
;
...
@@ -1504,14 +1840,14 @@ static void _vc_setpagelock(Relation rel, BlockNumber blkno)
...
@@ -1504,14 +1840,14 @@ static void _vc_setpagelock(Relation rel, BlockNumber blkno)
/*
/*
*
_
vc_reappage() -- save a page on the array of reapped pages.
* vc_reappage() -- save a page on the array of reapped pages.
*
*
* As a side effect of the way that the vacuuming loop for a given
* As a side effect of the way that the vacuuming loop for a given
* relation works, higher pages come after lower pages in the array
* relation works, higher pages come after lower pages in the array
* (and highest tid on a page is last).
* (and highest tid on a page is last).
*/
*/
static
void
static
void
_
vc_reappage
(
VPageList
vpl
,
VPageDescr
vpc
)
vc_reappage
(
VPageList
vpl
,
VPageDescr
vpc
)
{
{
VPageDescr
newvpd
;
VPageDescr
newvpd
;
...
@@ -1527,12 +1863,12 @@ _vc_reappage(VPageList vpl, VPageDescr vpc)
...
@@ -1527,12 +1863,12 @@ _vc_reappage(VPageList vpl, VPageDescr vpc)
newvpd
->
vpd_noff
=
vpc
->
vpd_noff
;
newvpd
->
vpd_noff
=
vpc
->
vpd_noff
;
/* insert this page into vpl list */
/* insert this page into vpl list */
_
vc_vpinsert
(
vpl
,
newvpd
);
vc_vpinsert
(
vpl
,
newvpd
);
}
/*
_
vc_reappage */
}
/* vc_reappage */
static
void
static
void
_
vc_vpinsert
(
VPageList
vpl
,
VPageDescr
vpnew
)
vc_vpinsert
(
VPageList
vpl
,
VPageDescr
vpnew
)
{
{
/* allocate a VPageDescr entry if needed */
/* allocate a VPageDescr entry if needed */
...
@@ -1546,10 +1882,9 @@ _vc_vpinsert (VPageList vpl, VPageDescr vpnew)
...
@@ -1546,10 +1882,9 @@ _vc_vpinsert (VPageList vpl, VPageDescr vpnew)
}
}
static
void
static
void
_
vc_free
(
Portal
p
,
VRelList
vrl
)
vc_free
(
Portal
p
,
VRelList
vrl
)
{
{
VRelList
p_vrl
;
VRelList
p_vrl
;
VAttList
p_val
,
val
;
MemoryContext
old
;
MemoryContext
old
;
PortalVariableMemory
pmem
;
PortalVariableMemory
pmem
;
...
@@ -1558,14 +1893,6 @@ _vc_free(Portal p, VRelList vrl)
...
@@ -1558,14 +1893,6 @@ _vc_free(Portal p, VRelList vrl)
while
(
vrl
!=
(
VRelList
)
NULL
)
{
while
(
vrl
!=
(
VRelList
)
NULL
)
{
/* free attribute list */
val
=
vrl
->
vrl_attlist
;
while
(
val
!=
(
VAttList
)
NULL
)
{
p_val
=
val
;
val
=
val
->
val_next
;
pfree
(
p_val
);
}
/* free rel list entry */
/* free rel list entry */
p_vrl
=
vrl
;
p_vrl
=
vrl
;
vrl
=
vrl
->
vrl_next
;
vrl
=
vrl
->
vrl_next
;
...
@@ -1576,7 +1903,7 @@ _vc_free(Portal p, VRelList vrl)
...
@@ -1576,7 +1903,7 @@ _vc_free(Portal p, VRelList vrl)
}
}
/*
/*
*
_
vc_getarchrel() -- open the archive relation for a heap relation
* vc_getarchrel() -- open the archive relation for a heap relation
*
*
* The archive relation is named 'a,XXXXX' for the heap relation
* The archive relation is named 'a,XXXXX' for the heap relation
* whose relid is XXXXX.
* whose relid is XXXXX.
...
@@ -1585,7 +1912,7 @@ _vc_free(Portal p, VRelList vrl)
...
@@ -1585,7 +1912,7 @@ _vc_free(Portal p, VRelList vrl)
#define ARCHIVE_PREFIX "a,"
#define ARCHIVE_PREFIX "a,"
static
Relation
static
Relation
_
vc_getarchrel
(
Relation
heaprel
)
vc_getarchrel
(
Relation
heaprel
)
{
{
Relation
archrel
;
Relation
archrel
;
char
*
archrelname
;
char
*
archrelname
;
...
@@ -1600,19 +1927,19 @@ _vc_getarchrel(Relation heaprel)
...
@@ -1600,19 +1927,19 @@ _vc_getarchrel(Relation heaprel)
}
}
/*
/*
*
_
vc_archive() -- write a tuple to an archive relation
* vc_archive() -- write a tuple to an archive relation
*
*
* In the future, this will invoke the archived accessd method. For
* In the future, this will invoke the archived accessd method. For
* now, archive relations are on mag disk.
* now, archive relations are on mag disk.
*/
*/
static
void
static
void
_
vc_archive
(
Relation
archrel
,
HeapTuple
htup
)
vc_archive
(
Relation
archrel
,
HeapTuple
htup
)
{
{
doinsert
(
archrel
,
htup
);
doinsert
(
archrel
,
htup
);
}
}
static
bool
static
bool
_
vc_isarchrel
(
char
*
rname
)
vc_isarchrel
(
char
*
rname
)
{
{
if
(
strncmp
(
ARCHIVE_PREFIX
,
rname
,
strlen
(
ARCHIVE_PREFIX
))
==
0
)
if
(
strncmp
(
ARCHIVE_PREFIX
,
rname
,
strlen
(
ARCHIVE_PREFIX
))
==
0
)
return
(
true
);
return
(
true
);
...
@@ -1621,7 +1948,7 @@ _vc_isarchrel(char *rname)
...
@@ -1621,7 +1948,7 @@ _vc_isarchrel(char *rname)
}
}
static
char
*
static
char
*
_
vc_find_eq
(
char
*
bot
,
int
nelem
,
int
size
,
char
*
elm
,
int
(
*
compar
)(
char
*
,
char
*
))
vc_find_eq
(
char
*
bot
,
int
nelem
,
int
size
,
char
*
elm
,
int
(
*
compar
)(
char
*
,
char
*
))
{
{
int
res
;
int
res
;
int
last
=
nelem
-
1
;
int
last
=
nelem
-
1
;
...
@@ -1671,10 +1998,10 @@ _vc_find_eq (char *bot, int nelem, int size, char *elm, int (*compar)(char *, ch
...
@@ -1671,10 +1998,10 @@ _vc_find_eq (char *bot, int nelem, int size, char *elm, int (*compar)(char *, ch
first_move
=
true
;
first_move
=
true
;
}
}
}
/*
_
vc_find_eq */
}
/* vc_find_eq */
static
int
static
int
_
vc_cmp_blk
(
char
*
left
,
char
*
right
)
vc_cmp_blk
(
char
*
left
,
char
*
right
)
{
{
BlockNumber
lblk
,
rblk
;
BlockNumber
lblk
,
rblk
;
...
@@ -1687,10 +2014,10 @@ _vc_cmp_blk (char *left, char *right)
...
@@ -1687,10 +2014,10 @@ _vc_cmp_blk (char *left, char *right)
return
(
0
);
return
(
0
);
return
(
1
);
return
(
1
);
}
/*
_
vc_cmp_blk */
}
/* vc_cmp_blk */
static
int
static
int
_
vc_cmp_offno
(
char
*
left
,
char
*
right
)
vc_cmp_offno
(
char
*
left
,
char
*
right
)
{
{
if
(
*
(
OffsetNumber
*
)
left
<
*
(
OffsetNumber
*
)
right
)
if
(
*
(
OffsetNumber
*
)
left
<
*
(
OffsetNumber
*
)
right
)
...
@@ -1699,11 +2026,11 @@ _vc_cmp_offno (char *left, char *right)
...
@@ -1699,11 +2026,11 @@ _vc_cmp_offno (char *left, char *right)
return
(
0
);
return
(
0
);
return
(
1
);
return
(
1
);
}
/*
_
vc_cmp_offno */
}
/* vc_cmp_offno */
static
void
static
void
_
vc_getindices
(
Oid
relid
,
int
*
nindices
,
Relation
**
Irel
)
vc_getindices
(
Oid
relid
,
int
*
nindices
,
Relation
**
Irel
)
{
{
Relation
pgindex
;
Relation
pgindex
;
Relation
irel
;
Relation
irel
;
...
@@ -1773,11 +2100,11 @@ _vc_getindices (Oid relid, int *nindices, Relation **Irel)
...
@@ -1773,11 +2100,11 @@ _vc_getindices (Oid relid, int *nindices, Relation **Irel)
*
Irel
=
(
Relation
*
)
NULL
;
*
Irel
=
(
Relation
*
)
NULL
;
}
}
}
/*
_
vc_getindices */
}
/* vc_getindices */
static
void
static
void
_
vc_clsindices
(
int
nindices
,
Relation
*
Irel
)
vc_clsindices
(
int
nindices
,
Relation
*
Irel
)
{
{
if
(
Irel
==
(
Relation
*
)
NULL
)
if
(
Irel
==
(
Relation
*
)
NULL
)
...
@@ -1788,11 +2115,11 @@ _vc_clsindices (int nindices, Relation *Irel)
...
@@ -1788,11 +2115,11 @@ _vc_clsindices (int nindices, Relation *Irel)
}
}
pfree
(
Irel
);
pfree
(
Irel
);
}
/*
_
vc_clsindices */
}
/* vc_clsindices */
static
void
static
void
_
vc_mkindesc
(
Relation
onerel
,
int
nindices
,
Relation
*
Irel
,
IndDesc
**
Idesc
)
vc_mkindesc
(
Relation
onerel
,
int
nindices
,
Relation
*
Irel
,
IndDesc
**
Idesc
)
{
{
IndDesc
*
idcur
;
IndDesc
*
idcur
;
HeapTuple
pgIndexTup
;
HeapTuple
pgIndexTup
;
...
@@ -1824,11 +2151,11 @@ _vc_mkindesc (Relation onerel, int nindices, Relation *Irel, IndDesc **Idesc)
...
@@ -1824,11 +2151,11 @@ _vc_mkindesc (Relation onerel, int nindices, Relation *Irel, IndDesc **Idesc)
idcur
->
natts
=
natts
;
idcur
->
natts
=
natts
;
}
}
}
/*
_
vc_mkindesc */
}
/* vc_mkindesc */
static
bool
static
bool
_
vc_enough_space
(
VPageDescr
vpd
,
Size
len
)
vc_enough_space
(
VPageDescr
vpd
,
Size
len
)
{
{
len
=
DOUBLEALIGN
(
len
);
len
=
DOUBLEALIGN
(
len
);
...
@@ -1845,4 +2172,4 @@ _vc_enough_space (VPageDescr vpd, Size len)
...
@@ -1845,4 +2172,4 @@ _vc_enough_space (VPageDescr vpd, Size len)
return
(
false
);
return
(
false
);
}
/*
_
vc_enough_space */
}
/* vc_enough_space */
src/backend/parser/analyze.c
View file @
2300ac0d
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.2
0 1997/01/22 01:42:54
momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.2
1 1997/02/07 16:22:50
momjian Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -1486,7 +1486,7 @@ any_ordering_op(int restype)
...
@@ -1486,7 +1486,7 @@ any_ordering_op(int restype)
Operator
order_op
;
Operator
order_op
;
Oid
order_opid
;
Oid
order_opid
;
order_op
=
oper
(
"<"
,
restype
,
restype
);
order_op
=
oper
(
"<"
,
restype
,
restype
,
false
);
order_opid
=
oprid
(
order_op
);
order_opid
=
oprid
(
order_op
);
return
order_opid
;
return
order_opid
;
...
@@ -1554,7 +1554,7 @@ transformSortClause(ParseState *pstate,
...
@@ -1554,7 +1554,7 @@ transformSortClause(ParseState *pstate,
sortcl
->
resdom
=
resdom
=
restarget
->
resdom
;
sortcl
->
resdom
=
resdom
=
restarget
->
resdom
;
sortcl
->
opoid
=
oprid
(
oper
(
sortby
->
useOp
,
sortcl
->
opoid
=
oprid
(
oper
(
sortby
->
useOp
,
resdom
->
restype
,
resdom
->
restype
,
resdom
->
restype
));
resdom
->
restype
,
false
));
if
(
sortlist
==
NIL
)
{
if
(
sortlist
==
NIL
)
{
s
=
sortlist
=
lcons
(
sortcl
,
NIL
);
s
=
sortlist
=
lcons
(
sortcl
,
NIL
);
}
else
{
}
else
{
...
...
src/backend/parser/catalog_utils.c
View file @
2300ac0d
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/Attic/catalog_utils.c,v 1.1
5 1997/01/22 01:4
3:08 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/Attic/catalog_utils.c,v 1.1
6 1997/02/07 16:2
3:08 momjian Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -473,7 +473,7 @@ binary_oper_select_candidate(Oid arg1,
...
@@ -473,7 +473,7 @@ binary_oper_select_candidate(Oid arg1,
/* Given operator, types of arg1, and arg2, return oper struct */
/* Given operator, types of arg1, and arg2, return oper struct */
/* arg1, arg2 --typeids */
/* arg1, arg2 --typeids */
Operator
Operator
oper
(
char
*
op
,
Oid
arg1
,
Oid
arg2
)
oper
(
char
*
op
,
Oid
arg1
,
Oid
arg2
,
bool
noWarnings
)
{
{
HeapTuple
tup
;
HeapTuple
tup
;
CandidateList
candidates
;
CandidateList
candidates
;
...
@@ -492,7 +492,8 @@ oper(char *op, Oid arg1, Oid arg2)
...
@@ -492,7 +492,8 @@ oper(char *op, Oid arg1, Oid arg2)
/*
/*
* no operators of the desired types found
* no operators of the desired types found
*/
*/
op_error
(
op
,
arg1
,
arg2
);
if
(
!
noWarnings
)
op_error
(
op
,
arg1
,
arg2
);
return
(
NULL
);
return
(
NULL
);
}
else
if
(
ncandidates
==
1
)
{
}
else
if
(
ncandidates
==
1
)
{
/*
/*
...
@@ -523,11 +524,12 @@ oper(char *op, Oid arg1, Oid arg2)
...
@@ -523,11 +524,12 @@ oper(char *op, Oid arg1, Oid arg2)
/* we chose none of them */
/* we chose none of them */
tp1
=
get_id_type
(
arg1
);
tp1
=
get_id_type
(
arg1
);
tp2
=
get_id_type
(
arg2
);
tp2
=
get_id_type
(
arg2
);
elog
(
NOTICE
,
"there is more than one operator %s for types"
,
op
);
if
(
!
noWarnings
)
{
elog
(
NOTICE
,
"%s and %s. You will have to retype this query"
,
elog
(
NOTICE
,
"there is more than one operator %s for types"
,
op
);
tname
(
tp1
),
tname
(
tp2
));
elog
(
NOTICE
,
"%s and %s. You will have to retype this query"
,
elog
(
WARN
,
"using an explicit cast"
);
tname
(
tp1
),
tname
(
tp2
));
elog
(
WARN
,
"using an explicit cast"
);
}
return
(
NULL
);
return
(
NULL
);
}
}
}
}
...
...
src/backend/parser/parse_query.c
View file @
2300ac0d
...
@@ -8,7 +8,7 @@
...
@@ -8,7 +8,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/Attic/parse_query.c,v 1.1
2 1997/01/22 01:43:19
momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/Attic/parse_query.c,v 1.1
3 1997/02/07 16:23:21
momjian Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -352,7 +352,7 @@ make_op(char *opname, Node *ltree, Node *rtree)
...
@@ -352,7 +352,7 @@ make_op(char *opname, Node *ltree, Node *rtree)
/* right operator */
/* right operator */
ltypeId
=
(
ltree
==
NULL
)
?
UNKNOWNOID
:
exprType
(
ltree
);
ltypeId
=
(
ltree
==
NULL
)
?
UNKNOWNOID
:
exprType
(
ltree
);
temp
=
right_oper
(
opname
,
ltypeId
);
temp
=
oper
(
opname
,
ltypeId
,
rtypeId
,
false
);
opform
=
(
OperatorTupleForm
)
GETSTRUCT
(
temp
);
opform
=
(
OperatorTupleForm
)
GETSTRUCT
(
temp
);
left
=
make_operand
(
opname
,
ltree
,
ltypeId
,
opform
->
oprleft
);
left
=
make_operand
(
opname
,
ltree
,
ltypeId
,
opform
->
oprleft
);
right
=
NULL
;
right
=
NULL
;
...
@@ -411,7 +411,7 @@ make_op(char *opname, Node *ltree, Node *rtree)
...
@@ -411,7 +411,7 @@ make_op(char *opname, Node *ltree, Node *rtree)
((
Const
*
)
ltree
)
->
constbyval
=
tbyval
(
newtype
);
((
Const
*
)
ltree
)
->
constbyval
=
tbyval
(
newtype
);
}
}
temp
=
oper
(
opname
,
ltypeId
,
rtypeId
);
temp
=
oper
(
opname
,
ltypeId
,
rtypeId
,
false
);
opform
=
(
OperatorTupleForm
)
GETSTRUCT
(
temp
);
opform
=
(
OperatorTupleForm
)
GETSTRUCT
(
temp
);
left
=
make_operand
(
opname
,
ltree
,
ltypeId
,
opform
->
oprleft
);
left
=
make_operand
(
opname
,
ltree
,
ltypeId
,
opform
->
oprleft
);
right
=
make_operand
(
opname
,
rtree
,
rtypeId
,
opform
->
oprright
);
right
=
make_operand
(
opname
,
rtree
,
rtypeId
,
opform
->
oprright
);
...
...
src/backend/utils/adt/selfuncs.c
View file @
2300ac0d
...
@@ -12,7 +12,7 @@
...
@@ -12,7 +12,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.
4 1996/11/03 06:53:08 scrappy
Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.
5 1997/02/07 16:23:39 momjian
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -33,6 +33,7 @@
...
@@ -33,6 +33,7 @@
#include "utils/lsyscache.h"
/* for get_oprrest() */
#include "utils/lsyscache.h"
/* for get_oprrest() */
#include "catalog/pg_statistic.h"
#include "catalog/pg_statistic.h"
#include "commands/vacuum.h"
/* for ATTNVALS_SCALE */
/* N is not a valid var/constant or relation id */
/* N is not a valid var/constant or relation id */
#define NONVALUE(N) ((N) == -1)
#define NONVALUE(N) ((N) == -1)
...
@@ -68,7 +69,7 @@ eqsel(Oid opid,
...
@@ -68,7 +69,7 @@ eqsel(Oid opid,
if
(
nvals
==
0
)
if
(
nvals
==
0
)
*
result
=
0
.
0
;
*
result
=
0
.
0
;
else
else
*
result
=
1
.
0
/
nvals
;
*
result
=
((
float64data
)
nvals
)
/
((
float64data
)
ATTNVALS_SCALE
)
;
}
}
return
(
result
);
return
(
result
);
}
}
...
@@ -125,7 +126,7 @@ intltsel(Oid opid,
...
@@ -125,7 +126,7 @@ intltsel(Oid opid,
if
(
nvals
==
0
)
if
(
nvals
==
0
)
*
result
=
1
.
0
/
3
.
0
;
*
result
=
1
.
0
/
3
.
0
;
else
else
*
result
=
3
.
0
/
nvals
;
*
result
=
3
.
0
*
((
float64data
)
nvals
)
/
((
float64data
)
ATTNVALS_SCALE
)
;
}
else
{
}
else
{
bottom
=
high
-
low
;
bottom
=
high
-
low
;
if
(
bottom
==
0
)
if
(
bottom
==
0
)
...
@@ -192,7 +193,7 @@ eqjoinsel(Oid opid,
...
@@ -192,7 +193,7 @@ eqjoinsel(Oid opid,
if
(
max
==
0
)
if
(
max
==
0
)
*
result
=
1
.
0
;
*
result
=
1
.
0
;
else
else
*
result
=
1
.
0
/
max
;
*
result
=
((
float64data
)
max
)
/
((
float64data
)
ATTNVALS_SCALE
)
;
}
}
return
(
result
);
return
(
result
);
}
}
...
...
src/include/commands/vacuum.h
View file @
2300ac0d
...
@@ -6,13 +6,16 @@
...
@@ -6,13 +6,16 @@
*
*
* Copyright (c) 1994, Regents of the University of California
* Copyright (c) 1994, Regents of the University of California
*
*
* $Id: vacuum.h,v 1.
5 1997/01/13 03:44:54
momjian Exp $
* $Id: vacuum.h,v 1.
6 1997/02/07 16:23:57
momjian Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
#ifndef VACUUM_H
#ifndef VACUUM_H
#define VACUUM_H
#define VACUUM_H
#include <access/funcindex.h>
#include <catalog/pg_index.h>
typedef
struct
VAttListData
{
typedef
struct
VAttListData
{
int
val_dummy
;
int
val_dummy
;
struct
VAttListData
*
val_next
;
struct
VAttListData
*
val_next
;
...
@@ -38,23 +41,46 @@ typedef struct VPageListData {
...
@@ -38,23 +41,46 @@ typedef struct VPageListData {
typedef
VPageListData
*
VPageList
;
typedef
VPageListData
*
VPageList
;
typedef
struct
{
FuncIndexInfo
finfo
;
FuncIndexInfo
*
finfoP
;
IndexTupleForm
tform
;
int
natts
;
}
IndDesc
;
typedef
struct
{
AttributeTupleForm
attr
;
Datum
best
,
guess1
,
guess2
,
max
,
min
;
int16
best_len
,
guess1_len
,
guess2_len
,
max_len
,
min_len
;
int32
best_cnt
,
guess1_cnt
,
guess1_hits
,
guess2_hits
,
null_cnt
,
nonnull_cnt
;
int32
max_cnt
,
min_cnt
;
regproc
cmpeq
,
cmplt
,
cmpgt
,
outfunc
;
bool
initialized
;
}
VacAttrStats
;
typedef
struct
VRelListData
{
typedef
struct
VRelListData
{
Oid
vrl_relid
;
Oid
vrl_relid
;
VAttList
vrl_attlist
;
int
vrl_ntups
;
int
vrl_npages
;
Size
vrl_min_tlen
;
Size
vrl_max_tlen
;
bool
vrl_hasindex
;
struct
VRelListData
*
vrl_next
;
struct
VRelListData
*
vrl_next
;
}
VRelListData
;
}
VRelListData
;
typedef
VRelListData
*
VRelList
;
typedef
VRelListData
*
VRelList
;
typedef
struct
VRelStats
{
Oid
relid
;
int
ntups
;
int
npages
;
Size
min_tlen
;
Size
max_tlen
;
bool
hasindex
;
int
natts
;
VacAttrStats
*
vacattrstats
;
}
VRelStats
;
extern
bool
VacuumRunning
;
extern
bool
VacuumRunning
;
extern
void
vc_abort
(
void
);
extern
void
vc_abort
(
void
);
extern
void
vacuum
(
char
*
vacrel
,
bool
verbose
);
extern
void
vacuum
(
char
*
vacrel
,
bool
verbose
);
#define ATTNVALS_SCALE 1000000000
/* XXX so it can act as a float4 */
#endif
/* VACUUM_H */
#endif
/* VACUUM_H */
src/include/parser/catalog_utils.h
View file @
2300ac0d
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
*
*
* Copyright (c) 1994, Regents of the University of California
* Copyright (c) 1994, Regents of the University of California
*
*
* $Id: catalog_utils.h,v 1.
7 1997/01/22 01:44:0
2 momjian Exp $
* $Id: catalog_utils.h,v 1.
8 1997/02/07 16:24:1
2 momjian Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -31,7 +31,7 @@ extern bool tbyval(Type t);
...
@@ -31,7 +31,7 @@ extern bool tbyval(Type t);
extern
char
*
tname
(
Type
t
);
extern
char
*
tname
(
Type
t
);
extern
int
tbyvalue
(
Type
t
);
extern
int
tbyvalue
(
Type
t
);
extern
Oid
oprid
(
Operator
op
);
extern
Oid
oprid
(
Operator
op
);
extern
Operator
oper
(
char
*
op
,
Oid
arg1
,
Oid
arg2
);
extern
Operator
oper
(
char
*
op
,
Oid
arg1
,
Oid
arg2
,
bool
noWarnings
);
extern
Operator
right_oper
(
char
*
op
,
Oid
arg
);
extern
Operator
right_oper
(
char
*
op
,
Oid
arg
);
extern
Operator
left_oper
(
char
*
op
,
Oid
arg
);
extern
Operator
left_oper
(
char
*
op
,
Oid
arg
);
extern
int
varattno
(
Relation
rd
,
char
*
a
);
extern
int
varattno
(
Relation
rd
,
char
*
a
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment