1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* datum.c
|
2000-07-12 04:37:39 +02:00
|
|
|
* POSTGRES Datum (abstract data type) manipulation routines.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2002-06-20 22:29:54 +02:00
|
|
|
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2002-06-20 22:29:54 +02:00
|
|
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/datum.c,v 1.23 2002/06/20 20:29:37 momjian Exp $
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
* In the implementation of the next routines we assume the following:
|
|
|
|
*
|
|
|
|
* A) if a type is "byVal" then all the information is stored in the
|
|
|
|
* Datum itself (i.e. no pointers involved!). In this case the
|
2000-07-12 04:37:39 +02:00
|
|
|
* length of the type is always greater than zero and not more than
|
1996-07-09 08:22:35 +02:00
|
|
|
* "sizeof(Datum)"
|
|
|
|
* B) if a type is not "byVal" and it has a fixed length, then
|
|
|
|
* the "Datum" always contain a pointer to a stream of bytes.
|
|
|
|
* The number of significant bytes are always equal to the length of the
|
|
|
|
* type.
|
|
|
|
* C) if a type is not "byVal" and is of variable length (i.e. it has
|
|
|
|
* length == -1) then "Datum" always points to a "struct varlena".
|
|
|
|
* This varlena structure has information about the actual length of this
|
|
|
|
* particular instance of the type and about its value.
|
|
|
|
*
|
2000-07-12 04:37:39 +02:00
|
|
|
* Note that we do not treat "toasted" datums specially; therefore what
|
|
|
|
* will be copied or compared is the compressed data or toast reference.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2000-07-12 04:37:39 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
#include "postgres.h"
|
2000-07-12 04:37:39 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
#include "utils/datum.h"
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
* datumGetSize
|
|
|
|
*
|
|
|
|
* Find the "real" size of a datum, given the datum value,
|
2000-07-12 04:37:39 +02:00
|
|
|
* whether it is a "by value", and its length.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
* To cut a long story short, usually the real size is equal to the
|
|
|
|
* type length, with the exception of variable length types which have
|
|
|
|
* a length equal to -1. In this case, we have to look at the value of
|
|
|
|
* the datum itself (which is a pointer to a 'varlena' struct) to find
|
|
|
|
* its size.
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
Size
|
2000-07-12 04:37:39 +02:00
|
|
|
datumGetSize(Datum value, bool typByVal, int typLen)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-07-12 04:37:39 +02:00
|
|
|
Size size;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-07-12 04:37:39 +02:00
|
|
|
if (typByVal)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-07-12 04:37:39 +02:00
|
|
|
/* Pass-by-value types are always fixed-length */
|
|
|
|
Assert(typLen > 0 && typLen <= sizeof(Datum));
|
|
|
|
size = (Size) typLen;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
else
|
2000-07-12 04:37:39 +02:00
|
|
|
{
|
|
|
|
if (typLen == -1)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-07-12 04:37:39 +02:00
|
|
|
/* Assume it is a varlena datatype */
|
|
|
|
struct varlena *s = (struct varlena *) DatumGetPointer(value);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
if (!PointerIsValid(s))
|
2000-07-12 04:37:39 +02:00
|
|
|
elog(ERROR, "datumGetSize: Invalid Datum Pointer");
|
1997-09-07 07:04:48 +02:00
|
|
|
size = (Size) VARSIZE(s);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2000-07-12 04:37:39 +02:00
|
|
|
/* Fixed-length pass-by-ref type */
|
|
|
|
size = (Size) typLen;
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1998-09-01 05:29:17 +02:00
|
|
|
return size;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
* datumCopy
|
|
|
|
*
|
|
|
|
* make a copy of a datum
|
|
|
|
*
|
2000-07-12 04:37:39 +02:00
|
|
|
* If the datatype is pass-by-reference, memory is obtained with palloc().
|
1996-07-09 08:22:35 +02:00
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
Datum
|
2000-07-12 04:37:39 +02:00
|
|
|
datumCopy(Datum value, bool typByVal, int typLen)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
Datum res;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-07-12 04:37:39 +02:00
|
|
|
if (typByVal)
|
1997-09-07 07:04:48 +02:00
|
|
|
res = value;
|
|
|
|
else
|
|
|
|
{
|
2000-07-12 04:37:39 +02:00
|
|
|
Size realSize;
|
|
|
|
char *s;
|
|
|
|
|
|
|
|
if (DatumGetPointer(value) == NULL)
|
|
|
|
return PointerGetDatum(NULL);
|
|
|
|
|
|
|
|
realSize = datumGetSize(value, typByVal, typLen);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
s = (char *) palloc(realSize);
|
2000-07-12 04:37:39 +02:00
|
|
|
memcpy(s, DatumGetPointer(value), realSize);
|
|
|
|
res = PointerGetDatum(s);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1998-09-01 05:29:17 +02:00
|
|
|
return res;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
* datumFree
|
|
|
|
*
|
|
|
|
* Free the space occupied by a datum CREATED BY "datumCopy"
|
|
|
|
*
|
Restructure index AM interface for index building and index tuple deletion,
per previous discussion on pghackers. Most of the duplicate code in
different AMs' ambuild routines has been moved out to a common routine
in index.c; this means that all index types now do the right things about
inserting recently-dead tuples, etc. (I also removed support for EXTEND
INDEX in the ambuild routines, since that's about to go away anyway, and
it cluttered the code a lot.) The retail indextuple deletion routines have
been replaced by a "bulk delete" routine in which the indexscan is inside
the access method. I haven't pushed this change as far as it should go yet,
but it should allow considerable simplification of the internal bookkeeping
for deletions. Also, add flag columns to pg_am to eliminate various
hardcoded tests on AM OIDs, and remove unused pg_am columns.
Fix rtree and gist index types to not attempt to store NULLs; before this,
gist usually crashed, while rtree managed not to crash but computed wacko
bounding boxes for NULL entries (which might have had something to do with
the performance problems we've heard about occasionally).
Add AtEOXact routines to hash, rtree, and gist, all of which have static
state that needs to be reset after an error. We discovered this need long
ago for btree, but missed the other guys.
Oh, one more thing: concurrent VACUUM is now the default.
2001-07-16 00:48:19 +02:00
|
|
|
* NOTE: DO NOT USE THIS ROUTINE with datums returned by heap_getattr() etc.
|
1996-07-09 08:22:35 +02:00
|
|
|
* ONLY datums created by "datumCopy" can be freed!
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
1997-08-19 23:40:56 +02:00
|
|
|
#ifdef NOT_USED
|
1996-07-09 08:22:35 +02:00
|
|
|
void
|
2000-07-12 04:37:39 +02:00
|
|
|
datumFree(Datum value, bool typByVal, int typLen)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-07-12 04:37:39 +02:00
|
|
|
if (!typByVal)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-07-12 04:37:39 +02:00
|
|
|
Pointer s = DatumGetPointer(value);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
pfree(s);
|
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1997-08-19 23:40:56 +02:00
|
|
|
#endif
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
* datumIsEqual
|
|
|
|
*
|
|
|
|
* Return true if two datums are equal, false otherwise
|
|
|
|
*
|
|
|
|
* NOTE: XXX!
|
|
|
|
* We just compare the bytes of the two values, one by one.
|
|
|
|
* This routine will return false if there are 2 different
|
|
|
|
* representations of the same value (something along the lines
|
|
|
|
* of say the representation of zero in one's complement arithmetic).
|
2000-07-12 04:37:39 +02:00
|
|
|
* Also, it will probably not give the answer you want if either
|
|
|
|
* datum has been "toasted".
|
1996-07-09 08:22:35 +02:00
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
bool
|
2000-07-12 04:37:39 +02:00
|
|
|
datumIsEqual(Datum value1, Datum value2, bool typByVal, int typLen)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
bool res;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-07-12 04:37:39 +02:00
|
|
|
if (typByVal)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* just compare the two datums. NOTE: just comparing "len" bytes
|
|
|
|
* will not do the work, because we do not know how these bytes
|
|
|
|
* are aligned inside the "Datum".
|
|
|
|
*/
|
2000-07-12 04:37:39 +02:00
|
|
|
res = (value1 == value2);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
else
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-07-12 04:37:39 +02:00
|
|
|
Size size1,
|
|
|
|
size2;
|
|
|
|
char *s1,
|
|
|
|
*s2;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
/*
|
2000-07-12 04:37:39 +02:00
|
|
|
* Compare the bytes pointed by the pointers stored in the datums.
|
1997-09-07 07:04:48 +02:00
|
|
|
*/
|
2000-07-12 04:37:39 +02:00
|
|
|
size1 = datumGetSize(value1, typByVal, typLen);
|
|
|
|
size2 = datumGetSize(value2, typByVal, typLen);
|
1997-09-07 07:04:48 +02:00
|
|
|
if (size1 != size2)
|
1998-09-01 05:29:17 +02:00
|
|
|
return false;
|
1997-09-07 07:04:48 +02:00
|
|
|
s1 = (char *) DatumGetPointer(value1);
|
|
|
|
s2 = (char *) DatumGetPointer(value2);
|
2000-07-12 04:37:39 +02:00
|
|
|
res = (memcmp(s1, s2, size1) == 0);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
2000-07-12 04:37:39 +02:00
|
|
|
return res;
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|