Don't use 'return' where you should use 'PG_RETURN_xxx'.
[PostgreSQL.git] / src / backend / utils / adt / datum.c
blob6228271bbcb0acf3056514c0076e47b411f2e0eb
1 /*-------------------------------------------------------------------------
3 * datum.c
4 * POSTGRES Datum (abstract data type) manipulation routines.
6 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * IDENTIFICATION
11 * $PostgreSQL$
13 *-------------------------------------------------------------------------
16 * In the implementation of the next routines we assume the following:
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)"
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.
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.
32 * D) if a type is not "byVal" and has typlen == -2,
33 * then the "Datum" always points to a null-terminated C string.
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.
39 #include "postgres.h"
41 #include "utils/datum.h"
44 /*-------------------------------------------------------------------------
45 * datumGetSize
47 * Find the "real" size of a datum, given the datum value,
48 * whether it is a "by value", and the declared type length.
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 *-------------------------------------------------------------------------
54 Size
55 datumGetSize(Datum value, bool typByVal, int typLen)
57 Size size;
59 if (typByVal)
61 /* Pass-by-value types are always fixed-length */
62 Assert(typLen > 0 && typLen <= sizeof(Datum));
63 size = (Size) typLen;
65 else
67 if (typLen > 0)
69 /* Fixed-length pass-by-ref type */
70 size = (Size) typLen;
72 else if (typLen == -1)
74 /* It is a varlena datatype */
75 struct varlena *s = (struct varlena *) DatumGetPointer(value);
77 if (!PointerIsValid(s))
78 ereport(ERROR,
79 (errcode(ERRCODE_DATA_EXCEPTION),
80 errmsg("invalid Datum pointer")));
82 size = (Size) VARSIZE_ANY(s);
84 else if (typLen == -2)
86 /* It is a cstring datatype */
87 char *s = (char *) DatumGetPointer(value);
89 if (!PointerIsValid(s))
90 ereport(ERROR,
91 (errcode(ERRCODE_DATA_EXCEPTION),
92 errmsg("invalid Datum pointer")));
94 size = (Size) (strlen(s) + 1);
96 else
98 elog(ERROR, "invalid typLen: %d", typLen);
99 size = 0; /* keep compiler quiet */
103 return size;
106 /*-------------------------------------------------------------------------
107 * datumCopy
109 * make a copy of a datum
111 * If the datatype is pass-by-reference, memory is obtained with palloc().
112 *-------------------------------------------------------------------------
114 Datum
115 datumCopy(Datum value, bool typByVal, int typLen)
117 Datum res;
119 if (typByVal)
120 res = value;
121 else
123 Size realSize;
124 char *s;
126 if (DatumGetPointer(value) == NULL)
127 return PointerGetDatum(NULL);
129 realSize = datumGetSize(value, typByVal, typLen);
131 s = (char *) palloc(realSize);
132 memcpy(s, DatumGetPointer(value), realSize);
133 res = PointerGetDatum(s);
135 return res;
138 /*-------------------------------------------------------------------------
139 * datumFree
141 * Free the space occupied by a datum CREATED BY "datumCopy"
143 * NOTE: DO NOT USE THIS ROUTINE with datums returned by heap_getattr() etc.
144 * ONLY datums created by "datumCopy" can be freed!
145 *-------------------------------------------------------------------------
147 #ifdef NOT_USED
148 void
149 datumFree(Datum value, bool typByVal, int typLen)
151 if (!typByVal)
153 Pointer s = DatumGetPointer(value);
155 pfree(s);
158 #endif
160 /*-------------------------------------------------------------------------
161 * datumIsEqual
163 * Return true if two datums are equal, false otherwise
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 *-------------------------------------------------------------------------
174 bool
175 datumIsEqual(Datum value1, Datum value2, bool typByVal, int typLen)
177 bool res;
179 if (typByVal)
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.
187 res = (value1 == value2);
189 else
191 Size size1,
192 size2;
193 char *s1,
194 *s2;
197 * Compare the bytes pointed by the pointers stored in the datums.
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);
207 return res;