~ubuntu-branches/ubuntu/oneiric/postgresql-9.1/oneiric-security

« back to all changes in this revision

Viewing changes to src/backend/utils/adt/datum.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2011-05-11 10:41:53 UTC
  • Revision ID: james.westby@ubuntu.com-20110511104153-psbh2o58553fv1m0
Tags: upstream-9.1~beta1
ImportĀ upstreamĀ versionĀ 9.1~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 *
 
3
 * datum.c
 
4
 *        POSTGRES Datum (abstract data type) manipulation routines.
 
5
 *
 
6
 * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
 
7
 * Portions Copyright (c) 1994, Regents of the University of California
 
8
 *
 
9
 *
 
10
 * IDENTIFICATION
 
11
 *        src/backend/utils/adt/datum.c
 
12
 *
 
13
 *-------------------------------------------------------------------------
 
14
 */
 
15
/*
 
16
 * In the implementation of the next routines we assume the following:
 
17
 *
 
18
 * A) if a type is "byVal" then all the information is stored in the
 
19
 * Datum itself (i.e. no pointers involved!). In this case the
 
20
 * length of the type is always greater than zero and not more than
 
21
 * "sizeof(Datum)"
 
22
 *
 
23
 * B) if a type is not "byVal" and it has a fixed length (typlen > 0),
 
24
 * then the "Datum" always contains a pointer to a stream of bytes.
 
25
 * The number of significant bytes are always equal to the typlen.
 
26
 *
 
27
 * C) if a type is not "byVal" and has typlen == -1,
 
28
 * then the "Datum" always points to a "struct varlena".
 
29
 * This varlena structure has information about the actual length of this
 
30
 * particular instance of the type and about its value.
 
31
 *
 
32
 * D) if a type is not "byVal" and has typlen == -2,
 
33
 * then the "Datum" always points to a null-terminated C string.
 
34
 *
 
35
 * Note that we do not treat "toasted" datums specially; therefore what
 
36
 * will be copied or compared is the compressed data or toast reference.
 
37
 */
 
38
 
 
39
#include "postgres.h"
 
40
 
 
41
#include "utils/datum.h"
 
42
 
 
43
 
 
44
/*-------------------------------------------------------------------------
 
45
 * datumGetSize
 
46
 *
 
47
 * Find the "real" size of a datum, given the datum value,
 
48
 * whether it is a "by value", and the declared type length.
 
49
 *
 
50
 * This is essentially an out-of-line version of the att_addlength_datum()
 
51
 * macro in access/tupmacs.h.  We do a tad more error checking though.
 
52
 *-------------------------------------------------------------------------
 
53
 */
 
54
Size
 
55
datumGetSize(Datum value, bool typByVal, int typLen)
 
56
{
 
57
        Size            size;
 
58
 
 
59
        if (typByVal)
 
60
        {
 
61
                /* Pass-by-value types are always fixed-length */
 
62
                Assert(typLen > 0 && typLen <= sizeof(Datum));
 
63
                size = (Size) typLen;
 
64
        }
 
65
        else
 
66
        {
 
67
                if (typLen > 0)
 
68
                {
 
69
                        /* Fixed-length pass-by-ref type */
 
70
                        size = (Size) typLen;
 
71
                }
 
72
                else if (typLen == -1)
 
73
                {
 
74
                        /* It is a varlena datatype */
 
75
                        struct varlena *s = (struct varlena *) DatumGetPointer(value);
 
76
 
 
77
                        if (!PointerIsValid(s))
 
78
                                ereport(ERROR,
 
79
                                                (errcode(ERRCODE_DATA_EXCEPTION),
 
80
                                                 errmsg("invalid Datum pointer")));
 
81
 
 
82
                        size = (Size) VARSIZE_ANY(s);
 
83
                }
 
84
                else if (typLen == -2)
 
85
                {
 
86
                        /* It is a cstring datatype */
 
87
                        char       *s = (char *) DatumGetPointer(value);
 
88
 
 
89
                        if (!PointerIsValid(s))
 
90
                                ereport(ERROR,
 
91
                                                (errcode(ERRCODE_DATA_EXCEPTION),
 
92
                                                 errmsg("invalid Datum pointer")));
 
93
 
 
94
                        size = (Size) (strlen(s) + 1);
 
95
                }
 
96
                else
 
97
                {
 
98
                        elog(ERROR, "invalid typLen: %d", typLen);
 
99
                        size = 0;                       /* keep compiler quiet */
 
100
                }
 
101
        }
 
102
 
 
103
        return size;
 
104
}
 
105
 
 
106
/*-------------------------------------------------------------------------
 
107
 * datumCopy
 
108
 *
 
109
 * make a copy of a datum
 
110
 *
 
111
 * If the datatype is pass-by-reference, memory is obtained with palloc().
 
112
 *-------------------------------------------------------------------------
 
113
 */
 
114
Datum
 
115
datumCopy(Datum value, bool typByVal, int typLen)
 
116
{
 
117
        Datum           res;
 
118
 
 
119
        if (typByVal)
 
120
                res = value;
 
121
        else
 
122
        {
 
123
                Size            realSize;
 
124
                char       *s;
 
125
 
 
126
                if (DatumGetPointer(value) == NULL)
 
127
                        return PointerGetDatum(NULL);
 
128
 
 
129
                realSize = datumGetSize(value, typByVal, typLen);
 
130
 
 
131
                s = (char *) palloc(realSize);
 
132
                memcpy(s, DatumGetPointer(value), realSize);
 
133
                res = PointerGetDatum(s);
 
134
        }
 
135
        return res;
 
136
}
 
137
 
 
138
/*-------------------------------------------------------------------------
 
139
 * datumFree
 
140
 *
 
141
 * Free the space occupied by a datum CREATED BY "datumCopy"
 
142
 *
 
143
 * NOTE: DO NOT USE THIS ROUTINE with datums returned by heap_getattr() etc.
 
144
 * ONLY datums created by "datumCopy" can be freed!
 
145
 *-------------------------------------------------------------------------
 
146
 */
 
147
#ifdef NOT_USED
 
148
void
 
149
datumFree(Datum value, bool typByVal, int typLen)
 
150
{
 
151
        if (!typByVal)
 
152
        {
 
153
                Pointer         s = DatumGetPointer(value);
 
154
 
 
155
                pfree(s);
 
156
        }
 
157
}
 
158
#endif
 
159
 
 
160
/*-------------------------------------------------------------------------
 
161
 * datumIsEqual
 
162
 *
 
163
 * Return true if two datums are equal, false otherwise
 
164
 *
 
165
 * NOTE: XXX!
 
166
 * We just compare the bytes of the two values, one by one.
 
167
 * This routine will return false if there are 2 different
 
168
 * representations of the same value (something along the lines
 
169
 * of say the representation of zero in one's complement arithmetic).
 
170
 * Also, it will probably not give the answer you want if either
 
171
 * datum has been "toasted".
 
172
 *-------------------------------------------------------------------------
 
173
 */
 
174
bool
 
175
datumIsEqual(Datum value1, Datum value2, bool typByVal, int typLen)
 
176
{
 
177
        bool            res;
 
178
 
 
179
        if (typByVal)
 
180
        {
 
181
                /*
 
182
                 * just compare the two datums. NOTE: just comparing "len" bytes will
 
183
                 * not do the work, because we do not know how these bytes are aligned
 
184
                 * inside the "Datum".  We assume instead that any given datatype is
 
185
                 * consistent about how it fills extraneous bits in the Datum.
 
186
                 */
 
187
                res = (value1 == value2);
 
188
        }
 
189
        else
 
190
        {
 
191
                Size            size1,
 
192
                                        size2;
 
193
                char       *s1,
 
194
                                   *s2;
 
195
 
 
196
                /*
 
197
                 * Compare the bytes pointed by the pointers stored in the datums.
 
198
                 */
 
199
                size1 = datumGetSize(value1, typByVal, typLen);
 
200
                size2 = datumGetSize(value2, typByVal, typLen);
 
201
                if (size1 != size2)
 
202
                        return false;
 
203
                s1 = (char *) DatumGetPointer(value1);
 
204
                s2 = (char *) DatumGetPointer(value2);
 
205
                res = (memcmp(s1, s2, size1) == 0);
 
206
        }
 
207
        return res;
 
208
}