aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/common/heapvalid.c
blob: b80c5dd9eb0abcfc608d50a26e5bb54872035e4a (plain)
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
/*-------------------------------------------------------------------------
 *
 * 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.1.1.1 1996/07/09 06:21:09 scrappy Exp $
 *
 *-------------------------------------------------------------------------
 */
#include "c.h"

#include "access/htup.h"
#include "access/skey.h"
#include "access/heapam.h"
#include "utils/tqual.h"
#include "access/valid.h"	/* where the declarations go */
#include "access/xact.h"

#include "storage/buf.h"
#include "storage/bufmgr.h"
#include "storage/bufpage.h"
#include "storage/itemid.h"
#include "fmgr.h"
#include "utils/elog.h"
#include "utils/rel.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_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,
		     PageHeader disk_page,
		     TimeQual	qual,
		     int nKeys,
		     ScanKey key)
{
    HeapTuple	tuple;
    bool res;
    
    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;
    
    if (res && (relation->rd_rel->relkind == RELKIND_UNCATALOGED
		|| HeapTupleSatisfiesTimeQual(tuple,qual)))
	return tuple;
    
    return (HeapTuple) NULL;
}

/*
 *  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;
}