1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*-------------------------------------------------------------------------
*
* heapvalid.c--
* heap tuple qualification validity checking code
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/common/Attic/heapvalid.c,v 1.13 1997/03/28 07:03:53 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
#include <postgres.h>
#include <fmgr.h>
#include <access/heaptuple.h>
#include <access/valid.h>
#include <access/xact.h>
#include <storage/bufpage.h>
#include <utils/rel.h>
#include <utils/tqual.h>
#include <storage/bufmgr.h>
/* ----------------
* heap_keytest
*
* Test a heap tuple with respect to a scan key.
* ----------------
*/
bool
heap_keytest(HeapTuple t,
TupleDesc tupdesc,
int nkeys,
ScanKey keys)
{
bool isnull;
Datum atp;
int test;
for (; nkeys--; keys++) {
atp = (Datum)heap_getattr(t, InvalidBuffer,
keys->sk_attno,
tupdesc,
&isnull);
if (isnull)
/* XXX eventually should check if SK_ISNULL */
return false;
if (keys->sk_flags & SK_ISNULL) {
return (false);
}
if (keys->sk_flags & SK_COMMUTE)
test = (long) FMGR_PTR2(keys->sk_func, keys->sk_procedure,
keys->sk_argument, atp);
else
test = (long) FMGR_PTR2(keys->sk_func, keys->sk_procedure,
atp, keys->sk_argument);
if (!test == !(keys->sk_flags & SK_NEGATE))
return false;
}
return true;
}
/* ----------------
* heap_tuple_satisfies
*
* Returns a valid HeapTuple if it satisfies the timequal and keytest.
* Returns NULL otherwise. Used to be heap_satisifies (sic) which
* returned a boolean. It now returns a tuple so that we can avoid doing two
* PageGetItem's per tuple.
*
* Complete check of validity including LP_CTUP and keytest.
* This should perhaps be combined with valid somehow in the
* future. (Also, additional rule tests/time range tests.)
*
* on 8/21/92 mao says: i rearranged the tests here to do keytest before
* SatisfiesTimeQual. profiling indicated that even for vacuumed relations,
* time qual checking was more expensive than key testing. time qual is
* least likely to fail, too. we should really add the time qual test to
* the restriction and optimize it in the normal way. this has interactions
* with joey's expensive function work.
* ----------------
*/
HeapTuple
heap_tuple_satisfies(ItemId itemId,
Relation relation,
Buffer buffer,
PageHeader disk_page,
TimeQual qual,
int nKeys,
ScanKey key)
{
HeapTuple tuple, result;
bool res;
TransactionId old_tmin, old_tmax;
if (! ItemIdIsUsed(itemId))
return NULL;
tuple = (HeapTuple) PageGetItem((Page) disk_page, itemId);
if (key != NULL)
res = heap_keytest(tuple, RelationGetTupleDescriptor(relation),
nKeys, key);
else
res = TRUE;
result = (HeapTuple)NULL;
if (res) {
if(relation->rd_rel->relkind == RELKIND_UNCATALOGED) {
result = tuple;
} else {
old_tmin = tuple->t_tmin;
old_tmax = tuple->t_tmax;
res = HeapTupleSatisfiesTimeQual(tuple,qual);
if(tuple->t_tmin != old_tmin ||
tuple->t_tmax != old_tmax) {
SetBufferCommitInfoNeedsSave(buffer);
}
if(res) {
result = tuple;
}
}
}
return result;
}
/*
* TupleUpdatedByCurXactAndCmd() -- Returns true if this tuple has
* already been updated once by the current transaction/command
* pair.
*/
bool
TupleUpdatedByCurXactAndCmd(HeapTuple t)
{
if (TransactionIdEquals(t->t_xmax,
GetCurrentTransactionId()) &&
t->t_cmax == GetCurrentCommandId())
return true;
return false;
}