1 /*-------------------------------------------------------------------------
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
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
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.
41 #include "utils/datum.h"
44 /*-------------------------------------------------------------------------
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 *-------------------------------------------------------------------------
55 datumGetSize(Datum value
, bool typByVal
, int typLen
)
61 /* Pass-by-value types are always fixed-length */
62 Assert(typLen
> 0 && typLen
<= sizeof(Datum
));
69 /* Fixed-length pass-by-ref type */
72 else if (typLen
== -1)
74 /* It is a varlena datatype */
75 struct varlena
*s
= (struct varlena
*) DatumGetPointer(value
);
77 if (!PointerIsValid(s
))
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
))
91 (errcode(ERRCODE_DATA_EXCEPTION
),
92 errmsg("invalid Datum pointer")));
94 size
= (Size
) (strlen(s
) + 1);
98 elog(ERROR
, "invalid typLen: %d", typLen
);
99 size
= 0; /* keep compiler quiet */
106 /*-------------------------------------------------------------------------
109 * make a copy of a datum
111 * If the datatype is pass-by-reference, memory is obtained with palloc().
112 *-------------------------------------------------------------------------
115 datumCopy(Datum value
, bool typByVal
, int typLen
)
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
);
138 /*-------------------------------------------------------------------------
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 *-------------------------------------------------------------------------
149 datumFree(Datum value
, bool typByVal
, int typLen
)
153 Pointer s
= DatumGetPointer(value
);
160 /*-------------------------------------------------------------------------
163 * Return true if two datums are equal, false otherwise
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 *-------------------------------------------------------------------------
175 datumIsEqual(Datum value1
, Datum value2
, bool typByVal
, int typLen
)
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
);
197 * Compare the bytes pointed by the pointers stored in the datums.
199 size1
= datumGetSize(value1
, typByVal
, typLen
);
200 size2
= datumGetSize(value2
, typByVal
, typLen
);
203 s1
= (char *) DatumGetPointer(value1
);
204 s2
= (char *) DatumGetPointer(value2
);
205 res
= (memcmp(s1
, s2
, size1
) == 0);