Fix portability problems recently exposed by regression tests on Alphas.
1. Distinguish cases where a Datum representing a tuple datatype is an OID from cases where it is a pointer to TupleTableSlot, and make sure we use the right typlen in each case. 2. Make fetchatt() and related code support 8-byte by-value datatypes on machines where Datum is 8 bytes. Centralize knowledge of the available by-value datatype sizes in two macros in tupmacs.h, so that this will be easier if we ever have to do it again.
This commit is contained in:
parent
97799fc475
commit
8609d4abf2
97
configure
vendored
97
configure
vendored
@ -7206,8 +7206,53 @@ done
|
||||
|
||||
|
||||
|
||||
echo $ac_n "checking size of unsigned long""... $ac_c" 1>&6
|
||||
echo "configure:7211: checking size of unsigned long" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_sizeof_unsigned_long'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
if test "$cross_compiling" = yes; then
|
||||
ac_cv_sizeof_unsigned_long=4
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 7219 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <stdio.h>
|
||||
main()
|
||||
{
|
||||
FILE *f=fopen("conftestval", "w");
|
||||
if (!f) exit(1);
|
||||
fprintf(f, "%d\n", sizeof(unsigned long));
|
||||
exit(0);
|
||||
}
|
||||
EOF
|
||||
if { (eval echo configure:7230: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
|
||||
then
|
||||
ac_cv_sizeof_unsigned_long=`cat conftestval`
|
||||
else
|
||||
echo "configure: failed program was:" >&5
|
||||
cat conftest.$ac_ext >&5
|
||||
rm -fr conftest*
|
||||
ac_cv_sizeof_unsigned_long=0
|
||||
fi
|
||||
rm -fr conftest*
|
||||
fi
|
||||
|
||||
fi
|
||||
echo "$ac_t""$ac_cv_sizeof_unsigned_long" 1>&6
|
||||
cat >> confdefs.h <<EOF
|
||||
#define SIZEOF_UNSIGNED_LONG $ac_cv_sizeof_unsigned_long
|
||||
EOF
|
||||
|
||||
|
||||
cat >> confdefs.h <<EOF
|
||||
#define SIZEOF_DATUM $ac_cv_sizeof_unsigned_long
|
||||
EOF
|
||||
|
||||
|
||||
|
||||
echo $ac_n "checking alignment of short""... $ac_c" 1>&6
|
||||
echo "configure:7211: checking alignment of short" >&5
|
||||
echo "configure:7256: checking alignment of short" >&5
|
||||
if eval "test \"`echo '$''{'pgac_cv_alignof_short'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@ -7215,7 +7260,7 @@ else
|
||||
pgac_cv_alignof_short='sizeof(short)'
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 7219 "configure"
|
||||
#line 7264 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <stdio.h>
|
||||
struct { char filler; short field; } mystruct;
|
||||
@ -7227,7 +7272,7 @@ main()
|
||||
exit(0);
|
||||
}
|
||||
EOF
|
||||
if { (eval echo configure:7231: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
|
||||
if { (eval echo configure:7276: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
|
||||
then
|
||||
pgac_cv_alignof_short=`cat conftestval`
|
||||
else
|
||||
@ -7247,7 +7292,7 @@ EOF
|
||||
|
||||
|
||||
echo $ac_n "checking alignment of int""... $ac_c" 1>&6
|
||||
echo "configure:7251: checking alignment of int" >&5
|
||||
echo "configure:7296: checking alignment of int" >&5
|
||||
if eval "test \"`echo '$''{'pgac_cv_alignof_int'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@ -7255,7 +7300,7 @@ else
|
||||
pgac_cv_alignof_int='sizeof(int)'
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 7259 "configure"
|
||||
#line 7304 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <stdio.h>
|
||||
struct { char filler; int field; } mystruct;
|
||||
@ -7267,7 +7312,7 @@ main()
|
||||
exit(0);
|
||||
}
|
||||
EOF
|
||||
if { (eval echo configure:7271: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
|
||||
if { (eval echo configure:7316: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
|
||||
then
|
||||
pgac_cv_alignof_int=`cat conftestval`
|
||||
else
|
||||
@ -7287,7 +7332,7 @@ EOF
|
||||
|
||||
|
||||
echo $ac_n "checking alignment of long""... $ac_c" 1>&6
|
||||
echo "configure:7291: checking alignment of long" >&5
|
||||
echo "configure:7336: checking alignment of long" >&5
|
||||
if eval "test \"`echo '$''{'pgac_cv_alignof_long'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@ -7295,7 +7340,7 @@ else
|
||||
pgac_cv_alignof_long='sizeof(long)'
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 7299 "configure"
|
||||
#line 7344 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <stdio.h>
|
||||
struct { char filler; long field; } mystruct;
|
||||
@ -7307,7 +7352,7 @@ main()
|
||||
exit(0);
|
||||
}
|
||||
EOF
|
||||
if { (eval echo configure:7311: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
|
||||
if { (eval echo configure:7356: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
|
||||
then
|
||||
pgac_cv_alignof_long=`cat conftestval`
|
||||
else
|
||||
@ -7328,7 +7373,7 @@ EOF
|
||||
|
||||
if [ x"$HAVE_LONG_LONG_INT_64" = xyes ] ; then
|
||||
echo $ac_n "checking alignment of long long int""... $ac_c" 1>&6
|
||||
echo "configure:7332: checking alignment of long long int" >&5
|
||||
echo "configure:7377: checking alignment of long long int" >&5
|
||||
if eval "test \"`echo '$''{'pgac_cv_alignof_long_long_int'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@ -7336,7 +7381,7 @@ else
|
||||
pgac_cv_alignof_long_long_int='sizeof(long long int)'
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 7340 "configure"
|
||||
#line 7385 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <stdio.h>
|
||||
struct { char filler; long long int field; } mystruct;
|
||||
@ -7348,7 +7393,7 @@ main()
|
||||
exit(0);
|
||||
}
|
||||
EOF
|
||||
if { (eval echo configure:7352: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
|
||||
if { (eval echo configure:7397: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
|
||||
then
|
||||
pgac_cv_alignof_long_long_int=`cat conftestval`
|
||||
else
|
||||
@ -7369,7 +7414,7 @@ EOF
|
||||
|
||||
fi
|
||||
echo $ac_n "checking alignment of double""... $ac_c" 1>&6
|
||||
echo "configure:7373: checking alignment of double" >&5
|
||||
echo "configure:7418: checking alignment of double" >&5
|
||||
if eval "test \"`echo '$''{'pgac_cv_alignof_double'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@ -7377,7 +7422,7 @@ else
|
||||
pgac_cv_alignof_double='sizeof(double)'
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 7381 "configure"
|
||||
#line 7426 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <stdio.h>
|
||||
struct { char filler; double field; } mystruct;
|
||||
@ -7389,7 +7434,7 @@ main()
|
||||
exit(0);
|
||||
}
|
||||
EOF
|
||||
if { (eval echo configure:7393: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
|
||||
if { (eval echo configure:7438: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
|
||||
then
|
||||
pgac_cv_alignof_double=`cat conftestval`
|
||||
else
|
||||
@ -7427,12 +7472,12 @@ EOF
|
||||
|
||||
|
||||
echo $ac_n "checking for POSIX signal interface""... $ac_c" 1>&6
|
||||
echo "configure:7431: checking for POSIX signal interface" >&5
|
||||
echo "configure:7476: checking for POSIX signal interface" >&5
|
||||
if eval "test \"`echo '$''{'pgac_cv_func_posix_signals'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 7436 "configure"
|
||||
#line 7481 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <signal.h>
|
||||
|
||||
@ -7443,7 +7488,7 @@ act.sa_flags = SA_RESTART;
|
||||
sigaction(0, &act, &oact);
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:7447: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
if { (eval echo configure:7492: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
rm -rf conftest*
|
||||
pgac_cv_func_posix_signals=yes
|
||||
else
|
||||
@ -7473,7 +7518,7 @@ do
|
||||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:7477: checking for $ac_word" >&5
|
||||
echo "configure:7522: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_path_TCLSH'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@ -7509,7 +7554,7 @@ test -n "$TCLSH" && break
|
||||
done
|
||||
|
||||
echo $ac_n "checking for tclConfig.sh""... $ac_c" 1>&6
|
||||
echo "configure:7513: checking for tclConfig.sh" >&5
|
||||
echo "configure:7558: checking for tclConfig.sh" >&5
|
||||
# Let user override test
|
||||
if test -z "$TCL_CONFIG_SH"; then
|
||||
pgac_test_dirs="$with_tclconfig"
|
||||
@ -7542,7 +7587,7 @@ fi
|
||||
# Check for Tk configuration script tkConfig.sh
|
||||
if test "$with_tk" = yes; then
|
||||
echo $ac_n "checking for tkConfig.sh""... $ac_c" 1>&6
|
||||
echo "configure:7546: checking for tkConfig.sh" >&5
|
||||
echo "configure:7591: checking for tkConfig.sh" >&5
|
||||
# Let user override test
|
||||
if test -z "$TK_CONFIG_SH"; then
|
||||
pgac_test_dirs="$with_tkconfig $with_tclconfig"
|
||||
@ -7581,7 +7626,7 @@ do
|
||||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:7585: checking for $ac_word" >&5
|
||||
echo "configure:7630: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_NSGMLS'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@ -7617,7 +7662,7 @@ do
|
||||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:7621: checking for $ac_word" >&5
|
||||
echo "configure:7666: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_JADE'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@ -7648,7 +7693,7 @@ done
|
||||
|
||||
|
||||
echo $ac_n "checking for DocBook V3.1""... $ac_c" 1>&6
|
||||
echo "configure:7652: checking for DocBook V3.1" >&5
|
||||
echo "configure:7697: checking for DocBook V3.1" >&5
|
||||
if eval "test \"`echo '$''{'pgac_cv_check_docbook'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@ -7681,7 +7726,7 @@ have_docbook=$pgac_cv_check_docbook
|
||||
|
||||
|
||||
echo $ac_n "checking for DocBook stylesheets""... $ac_c" 1>&6
|
||||
echo "configure:7685: checking for DocBook stylesheets" >&5
|
||||
echo "configure:7730: checking for DocBook stylesheets" >&5
|
||||
if eval "test \"`echo '$''{'pgac_cv_path_stylesheets'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@ -7720,7 +7765,7 @@ do
|
||||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:7724: checking for $ac_word" >&5
|
||||
echo "configure:7769: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_SGMLSPL'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -1059,6 +1059,11 @@ AC_CHECK_FUNCS([strtoll strtoq], [break])
|
||||
AC_CHECK_FUNCS([strtoull strtouq], [break])
|
||||
|
||||
|
||||
dnl Need a #define for the size of Datum (unsigned long)
|
||||
|
||||
AC_CHECK_SIZEOF(unsigned long, 4)
|
||||
AC_DEFINE_UNQUOTED(SIZEOF_DATUM, $ac_cv_sizeof_unsigned_long)
|
||||
|
||||
dnl Determine memory alignment requirements for the basic C datatypes.
|
||||
|
||||
PGAC_CHECK_ALIGNOF(short)
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "access/tupmacs.h"
|
||||
#include "access/xact.h"
|
||||
#include "fmgr.h"
|
||||
#include "miscadmin.h"
|
||||
@ -80,37 +81,17 @@ array_iterator(Oid elemtype, Oid proc, int and, ArrayType *array, Datum value)
|
||||
p = ARR_DATA_PTR(array);
|
||||
for (i = 0; i < nitems; i++)
|
||||
{
|
||||
if (typbyval)
|
||||
{
|
||||
switch (typlen)
|
||||
{
|
||||
case 1:
|
||||
result = FunctionCall2(&finfo,
|
||||
CharGetDatum(*p),
|
||||
value);
|
||||
break;
|
||||
case 2:
|
||||
result = FunctionCall2(&finfo,
|
||||
Int16GetDatum(*(int16 *) p),
|
||||
value);
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
result = FunctionCall2(&finfo,
|
||||
Int32GetDatum(*(int32 *) p),
|
||||
value);
|
||||
break;
|
||||
}
|
||||
Datum itemvalue;
|
||||
|
||||
itemvalue = fetch_att(p, typbyval, typlen);
|
||||
|
||||
if (typlen > 0)
|
||||
p += typlen;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = FunctionCall2(&finfo, PointerGetDatum(p), value);
|
||||
if (typlen > 0)
|
||||
p += typlen;
|
||||
else
|
||||
p += INTALIGN(*(int32 *) p);
|
||||
}
|
||||
p += INTALIGN(*(int32 *) p);
|
||||
|
||||
result = FunctionCall2(&finfo, itemvalue, value);
|
||||
|
||||
if (DatumGetBool(result))
|
||||
{
|
||||
if (!and)
|
||||
|
@ -2,14 +2,14 @@
|
||||
*
|
||||
* heaptuple.c
|
||||
* This file contains heap tuple accessor and mutator routines, as well
|
||||
* as a few various tuple utilities.
|
||||
* as various tuple utilities.
|
||||
*
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.67 2000/11/30 18:38:45 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.68 2000/12/27 23:59:10 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* The old interface functions have been converted to macros
|
||||
@ -23,16 +23,6 @@
|
||||
#include "access/heapam.h"
|
||||
#include "catalog/pg_type.h"
|
||||
|
||||
/* Used by heap_getattr() macro, for speed */
|
||||
long heap_sysoffset[] = {
|
||||
/* Only the first one is pass-by-ref, and is handled specially in the macro */
|
||||
offsetof(HeapTupleHeaderData, t_ctid),
|
||||
offsetof(HeapTupleHeaderData, t_oid),
|
||||
offsetof(HeapTupleHeaderData, t_xmin),
|
||||
offsetof(HeapTupleHeaderData, t_cmin),
|
||||
offsetof(HeapTupleHeaderData, t_xmax),
|
||||
offsetof(HeapTupleHeaderData, t_cmax)
|
||||
};
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* misc support routines
|
||||
@ -48,12 +38,12 @@ ComputeDataSize(TupleDesc tupleDesc,
|
||||
Datum *value,
|
||||
char *nulls)
|
||||
{
|
||||
uint32 data_length;
|
||||
uint32 data_length = 0;
|
||||
int i;
|
||||
int numberOfAttributes = tupleDesc->natts;
|
||||
Form_pg_attribute *att = tupleDesc->attrs;
|
||||
|
||||
for (data_length = 0, i = 0; i < numberOfAttributes; i++)
|
||||
for (i = 0; i < numberOfAttributes; i++)
|
||||
{
|
||||
if (nulls[i] != ' ')
|
||||
continue;
|
||||
@ -114,38 +104,33 @@ DataFill(char *data,
|
||||
*bitP |= bitmask;
|
||||
}
|
||||
|
||||
/* XXX we are aligning the pointer itself, not the offset */
|
||||
data = (char *) att_align((long) data, att[i]->attlen, att[i]->attalign);
|
||||
switch (att[i]->attlen)
|
||||
|
||||
if (att[i]->attbyval)
|
||||
{
|
||||
case -1:
|
||||
*infomask |= HEAP_HASVARLENA;
|
||||
if (VARATT_IS_EXTERNAL(value[i]))
|
||||
*infomask |= HEAP_HASEXTERNAL;
|
||||
if (VARATT_IS_COMPRESSED(value[i]))
|
||||
*infomask |= HEAP_HASCOMPRESSED;
|
||||
data_length = VARATT_SIZE(DatumGetPointer(value[i]));
|
||||
memmove(data, DatumGetPointer(value[i]), data_length);
|
||||
break;
|
||||
case sizeof(char):
|
||||
*data = att[i]->attbyval ?
|
||||
DatumGetChar(value[i]) : *((char *) value[i]);
|
||||
break;
|
||||
case sizeof(int16):
|
||||
*(short *) data = (att[i]->attbyval ?
|
||||
DatumGetInt16(value[i]) :
|
||||
*((short *) value[i]));
|
||||
break;
|
||||
case sizeof(int32):
|
||||
*(int32 *) data = (att[i]->attbyval ?
|
||||
DatumGetInt32(value[i]) :
|
||||
*((int32 *) value[i]));
|
||||
break;
|
||||
default:
|
||||
Assert(att[i]->attlen >= 0);
|
||||
memmove(data, DatumGetPointer(value[i]),
|
||||
(size_t) (att[i]->attlen));
|
||||
break;
|
||||
/* pass-by-value */
|
||||
store_att_byval(data, value[i], att[i]->attlen);
|
||||
}
|
||||
else if (att[i]->attlen == -1)
|
||||
{
|
||||
/* varlena */
|
||||
*infomask |= HEAP_HASVARLENA;
|
||||
if (VARATT_IS_EXTERNAL(value[i]))
|
||||
*infomask |= HEAP_HASEXTERNAL;
|
||||
if (VARATT_IS_COMPRESSED(value[i]))
|
||||
*infomask |= HEAP_HASCOMPRESSED;
|
||||
data_length = VARATT_SIZE(DatumGetPointer(value[i]));
|
||||
memcpy(data, DatumGetPointer(value[i]), data_length);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* fixed-length pass-by-reference */
|
||||
Assert(att[i]->attlen >= 0);
|
||||
memcpy(data, DatumGetPointer(value[i]),
|
||||
(size_t) (att[i]->attlen));
|
||||
}
|
||||
|
||||
data = (char *) att_addlength((long) data, att[i]->attlen, value[i]);
|
||||
}
|
||||
}
|
||||
@ -192,89 +177,6 @@ heap_attisnull(HeapTuple tup, int attnum)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* system attribute heap tuple support
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ----------------
|
||||
* heap_sysattrlen
|
||||
*
|
||||
* This routine returns the length of a system attribute.
|
||||
* ----------------
|
||||
*/
|
||||
int
|
||||
heap_sysattrlen(AttrNumber attno)
|
||||
{
|
||||
HeapTupleHeader f = NULL;
|
||||
|
||||
switch (attno)
|
||||
{
|
||||
case TableOidAttributeNumber:
|
||||
return sizeof f->t_oid;
|
||||
case SelfItemPointerAttributeNumber:
|
||||
return sizeof f->t_ctid;
|
||||
case ObjectIdAttributeNumber:
|
||||
return sizeof f->t_oid;
|
||||
case MinTransactionIdAttributeNumber:
|
||||
return sizeof f->t_xmin;
|
||||
case MinCommandIdAttributeNumber:
|
||||
return sizeof f->t_cmin;
|
||||
case MaxTransactionIdAttributeNumber:
|
||||
return sizeof f->t_xmax;
|
||||
case MaxCommandIdAttributeNumber:
|
||||
return sizeof f->t_cmax;
|
||||
|
||||
default:
|
||||
elog(ERROR, "sysattrlen: System attribute number %d unknown.", attno);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* heap_sysattrbyval
|
||||
*
|
||||
* This routine returns the "by-value" property of a system attribute.
|
||||
* ----------------
|
||||
*/
|
||||
bool
|
||||
heap_sysattrbyval(AttrNumber attno)
|
||||
{
|
||||
bool byval;
|
||||
|
||||
switch (attno)
|
||||
{
|
||||
case TableOidAttributeNumber:
|
||||
byval = true;
|
||||
break;
|
||||
case SelfItemPointerAttributeNumber:
|
||||
byval = false;
|
||||
break;
|
||||
case ObjectIdAttributeNumber:
|
||||
byval = true;
|
||||
break;
|
||||
case MinTransactionIdAttributeNumber:
|
||||
byval = true;
|
||||
break;
|
||||
case MinCommandIdAttributeNumber:
|
||||
byval = true;
|
||||
break;
|
||||
case MaxTransactionIdAttributeNumber:
|
||||
byval = true;
|
||||
break;
|
||||
case MaxCommandIdAttributeNumber:
|
||||
byval = true;
|
||||
break;
|
||||
default:
|
||||
byval = true;
|
||||
elog(ERROR, "sysattrbyval: System attribute number %d unknown.",
|
||||
attno);
|
||||
break;
|
||||
}
|
||||
|
||||
return byval;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* nocachegetattr
|
||||
*
|
||||
@ -332,8 +234,7 @@ nocachegetattr(HeapTuple tuple,
|
||||
/* This is handled in the macro */
|
||||
if (att[attnum]->attcacheoff != -1)
|
||||
{
|
||||
return (Datum)
|
||||
fetchatt(&(att[attnum]),
|
||||
return fetchatt(att[attnum],
|
||||
(char *) tup + tup->t_hoff + att[attnum]->attcacheoff);
|
||||
}
|
||||
#endif
|
||||
@ -397,8 +298,8 @@ nocachegetattr(HeapTuple tuple,
|
||||
{
|
||||
if (att[attnum]->attcacheoff != -1)
|
||||
{
|
||||
return (Datum) fetchatt(&(att[attnum]),
|
||||
tp + att[attnum]->attcacheoff);
|
||||
return fetchatt(att[attnum],
|
||||
tp + att[attnum]->attcacheoff);
|
||||
}
|
||||
else if (!HeapTupleAllFixed(tuple))
|
||||
{
|
||||
@ -460,7 +361,7 @@ nocachegetattr(HeapTuple tuple,
|
||||
off = att_addlength(off, att[j]->attlen, tp + off);
|
||||
}
|
||||
|
||||
return (Datum) fetchatt(&(att[attnum]), tp + att[attnum]->attcacheoff);
|
||||
return fetchatt(att[attnum], tp + att[attnum]->attcacheoff);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -508,10 +409,66 @@ nocachegetattr(HeapTuple tuple,
|
||||
|
||||
off = att_align(off, att[attnum]->attlen, att[attnum]->attalign);
|
||||
|
||||
return (Datum) fetchatt(&(att[attnum]), tp + off);
|
||||
return fetchatt(att[attnum], tp + off);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* heap_getsysattr
|
||||
*
|
||||
* Fetch the value of a system attribute for a tuple.
|
||||
*
|
||||
* This is a support routine for the heap_getattr macro. The macro
|
||||
* has already determined that the attnum refers to a system attribute.
|
||||
* ----------------
|
||||
*/
|
||||
Datum
|
||||
heap_getsysattr(HeapTuple tup, int attnum, bool *isnull)
|
||||
{
|
||||
Datum result;
|
||||
|
||||
Assert(tup);
|
||||
|
||||
/* Currently, no sys attribute ever reads as NULL. */
|
||||
if (isnull)
|
||||
*isnull = false;
|
||||
|
||||
switch (attnum)
|
||||
{
|
||||
case SelfItemPointerAttributeNumber:
|
||||
/* pass-by-reference datatype */
|
||||
result = PointerGetDatum(&(tup->t_self));
|
||||
break;
|
||||
case ObjectIdAttributeNumber:
|
||||
result = ObjectIdGetDatum(tup->t_data->t_oid);
|
||||
break;
|
||||
case MinTransactionIdAttributeNumber:
|
||||
/* XXX should have a TransactionIdGetDatum macro */
|
||||
result = (Datum) (tup->t_data->t_xmin);
|
||||
break;
|
||||
case MinCommandIdAttributeNumber:
|
||||
/* XXX should have a CommandIdGetDatum macro */
|
||||
result = (Datum) (tup->t_data->t_cmin);
|
||||
break;
|
||||
case MaxTransactionIdAttributeNumber:
|
||||
/* XXX should have a TransactionIdGetDatum macro */
|
||||
result = (Datum) (tup->t_data->t_xmax);
|
||||
break;
|
||||
case MaxCommandIdAttributeNumber:
|
||||
/* XXX should have a CommandIdGetDatum macro */
|
||||
result = (Datum) (tup->t_data->t_cmax);
|
||||
break;
|
||||
case TableOidAttributeNumber:
|
||||
result = ObjectIdGetDatum(tup->t_tableOid);
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "heap_getsysattr: invalid attnum %d", attnum);
|
||||
result = 0; /* keep compiler quiet */
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* heap_copytuple
|
||||
*
|
||||
@ -630,18 +587,21 @@ heap_formtuple(TupleDesc tupleDescriptor,
|
||||
int i;
|
||||
int numberOfAttributes = tupleDescriptor->natts;
|
||||
|
||||
len = offsetof(HeapTupleHeaderData, t_bits);
|
||||
|
||||
for (i = 0; i < numberOfAttributes && !hasnull; i++)
|
||||
{
|
||||
if (nulls[i] != ' ')
|
||||
hasnull = true;
|
||||
}
|
||||
|
||||
if (numberOfAttributes > MaxHeapAttributeNumber)
|
||||
elog(ERROR, "heap_formtuple: numberOfAttributes of %d > %d",
|
||||
numberOfAttributes, MaxHeapAttributeNumber);
|
||||
|
||||
len = offsetof(HeapTupleHeaderData, t_bits);
|
||||
|
||||
for (i = 0; i < numberOfAttributes; i++)
|
||||
{
|
||||
if (nulls[i] != ' ')
|
||||
{
|
||||
hasnull = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasnull)
|
||||
{
|
||||
bitmaplen = BITMAPLEN(numberOfAttributes);
|
||||
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/common/indextuple.c,v 1.48 2000/12/07 02:00:47 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/common/indextuple.c,v 1.49 2000/12/27 23:59:10 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -217,9 +217,9 @@ nocache_index_getattr(IndexTuple tup,
|
||||
/* This is handled in the macro */
|
||||
if (att[attnum]->attcacheoff != -1)
|
||||
{
|
||||
return (Datum) fetchatt(&(att[attnum]),
|
||||
(char *) tup + data_off +
|
||||
att[attnum]->attcacheoff);
|
||||
return fetchatt(att[attnum],
|
||||
(char *) tup + data_off +
|
||||
att[attnum]->attcacheoff);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -279,8 +279,8 @@ nocache_index_getattr(IndexTuple tup,
|
||||
{
|
||||
if (att[attnum]->attcacheoff != -1)
|
||||
{
|
||||
return (Datum) fetchatt(&(att[attnum]),
|
||||
tp + att[attnum]->attcacheoff);
|
||||
return fetchatt(att[attnum],
|
||||
tp + att[attnum]->attcacheoff);
|
||||
}
|
||||
else if (!IndexTupleAllFixed(tup))
|
||||
{
|
||||
@ -332,7 +332,7 @@ nocache_index_getattr(IndexTuple tup,
|
||||
off += att[j]->attlen;
|
||||
}
|
||||
|
||||
return (Datum) fetchatt(&(att[attnum]), tp + att[attnum]->attcacheoff);
|
||||
return fetchatt(att[attnum], tp + att[attnum]->attcacheoff);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -379,7 +379,7 @@ nocache_index_getattr(IndexTuple tup,
|
||||
|
||||
off = att_align(off, att[attnum]->attlen, att[attnum]->attalign);
|
||||
|
||||
return (Datum) fetchatt(&att[attnum], tp + off);
|
||||
return fetchatt(att[attnum], tp + off);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.55 2000/12/01 22:10:31 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.56 2000/12/27 23:59:10 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -436,30 +436,17 @@ printtup_internal(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
|
||||
pq_sendint(&buf, len, sizeof(int32));
|
||||
if (typeinfo->attrs[i]->attbyval)
|
||||
{
|
||||
int8 i8;
|
||||
int16 i16;
|
||||
int32 i32;
|
||||
Datum datumBuf;
|
||||
|
||||
switch (len)
|
||||
{
|
||||
case sizeof(int8):
|
||||
i8 = DatumGetChar(attr);
|
||||
pq_sendbytes(&buf, (char *) &i8, len);
|
||||
break;
|
||||
case sizeof(int16):
|
||||
i16 = DatumGetInt16(attr);
|
||||
pq_sendbytes(&buf, (char *) &i16, len);
|
||||
break;
|
||||
case sizeof(int32):
|
||||
i32 = DatumGetInt32(attr);
|
||||
pq_sendbytes(&buf, (char *) &i32, len);
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "printtup_internal: unexpected typlen");
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* We need this horsing around because we don't know how
|
||||
* shorter data values are aligned within a Datum.
|
||||
*/
|
||||
store_att_byval(&datumBuf, attr, len);
|
||||
pq_sendbytes(&buf, (char *) &datumBuf, len);
|
||||
#ifdef IPORTAL_DEBUG
|
||||
fprintf(stderr, "byval length %d data %d\n", len, attr);
|
||||
fprintf(stderr, "byval length %d data %ld\n", len,
|
||||
(long) attr);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.69 2000/11/16 22:30:15 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.70 2000/12/27 23:59:10 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* some of the executor utility code such as "ExecTypeFromTL" should be
|
||||
@ -352,7 +352,6 @@ TupleDescInitEntry(TupleDesc desc,
|
||||
|
||||
AssertArg(!PointerIsValid(desc->attrs[attributeNumber - 1]));
|
||||
|
||||
|
||||
/* ----------------
|
||||
* allocate storage for this attribute
|
||||
* ----------------
|
||||
@ -362,7 +361,7 @@ TupleDescInitEntry(TupleDesc desc,
|
||||
desc->attrs[attributeNumber - 1] = att;
|
||||
|
||||
/* ----------------
|
||||
* initialize some of the attribute fields
|
||||
* initialize the attribute fields
|
||||
* ----------------
|
||||
*/
|
||||
att->attrelid = 0; /* dummy value */
|
||||
@ -372,7 +371,6 @@ TupleDescInitEntry(TupleDesc desc,
|
||||
else
|
||||
MemSet(NameStr(att->attname), 0, NAMEDATALEN);
|
||||
|
||||
|
||||
att->attdispersion = 0; /* dummy value */
|
||||
att->attcacheoff = -1;
|
||||
att->atttypmod = typmod;
|
||||
@ -414,8 +412,8 @@ TupleDescInitEntry(TupleDesc desc,
|
||||
att->atttypid = InvalidOid;
|
||||
att->attlen = (int16) 0;
|
||||
att->attbyval = (bool) 0;
|
||||
att->attstorage = 'p';
|
||||
att->attalign = 'i';
|
||||
att->attstorage = 'p';
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -427,42 +425,63 @@ TupleDescInitEntry(TupleDesc desc,
|
||||
typeForm = (Form_pg_type) GETSTRUCT(tuple);
|
||||
|
||||
att->atttypid = tuple->t_data->t_oid;
|
||||
att->attalign = typeForm->typalign;
|
||||
|
||||
/* ------------------------
|
||||
If this attribute is a set, what is really stored in the
|
||||
attribute is the OID of a tuple in the pg_proc catalog.
|
||||
The pg_proc tuple contains the query string which defines
|
||||
this set - i.e., the query to run to get the set.
|
||||
So the atttypid (just assigned above) refers to the type returned
|
||||
by this query, but the actual length of this attribute is the
|
||||
length (size) of an OID.
|
||||
|
||||
Why not just make the atttypid point to the OID type, instead
|
||||
of the type the query returns? Because the executor uses the atttypid
|
||||
to tell the front end what type will be returned (in BeginCommand),
|
||||
and in the end the type returned will be the result of the query, not
|
||||
an OID.
|
||||
|
||||
Why not wait until the return type of the set is known (i.e., the
|
||||
recursive call to the executor to execute the set has returned)
|
||||
before telling the front end what the return type will be? Because
|
||||
the executor is a delicate thing, and making sure that the correct
|
||||
order of front-end commands is maintained is messy, especially
|
||||
considering that target lists may change as inherited attributes
|
||||
are considered, etc. Ugh.
|
||||
-----------------------------------------
|
||||
*/
|
||||
/*------------------------
|
||||
* There are a couple of cases where we must override the information
|
||||
* stored in pg_type.
|
||||
*
|
||||
* First: if this attribute is a set, what is really stored in the
|
||||
* attribute is the OID of a tuple in the pg_proc catalog.
|
||||
* The pg_proc tuple contains the query string which defines
|
||||
* this set - i.e., the query to run to get the set.
|
||||
* So the atttypid (just assigned above) refers to the type returned
|
||||
* by this query, but the actual length of this attribute is the
|
||||
* length (size) of an OID.
|
||||
*
|
||||
* (Why not just make the atttypid point to the OID type, instead
|
||||
* of the type the query returns? Because the executor uses the atttypid
|
||||
* to tell the front end what type will be returned (in BeginCommand),
|
||||
* and in the end the type returned will be the result of the query, not
|
||||
* an OID.)
|
||||
*
|
||||
* (Why not wait until the return type of the set is known (i.e., the
|
||||
* recursive call to the executor to execute the set has returned)
|
||||
* before telling the front end what the return type will be? Because
|
||||
* the executor is a delicate thing, and making sure that the correct
|
||||
* order of front-end commands is maintained is messy, especially
|
||||
* considering that target lists may change as inherited attributes
|
||||
* are considered, etc. Ugh.)
|
||||
*
|
||||
* Second: if we are dealing with a complex type (a tuple type), then
|
||||
* pg_type will say that the representation is the same as Oid. But
|
||||
* if typmod is sizeof(Pointer) then the internal representation is
|
||||
* actually a pointer to a TupleTableSlot, and we have to substitute
|
||||
* that information.
|
||||
*
|
||||
* A set of complex type is first and foremost a set, so its
|
||||
* representation is Oid not pointer. So, test that case first.
|
||||
*-----------------------------------------
|
||||
*/
|
||||
if (attisset)
|
||||
{
|
||||
att->attlen = sizeof(Oid);
|
||||
att->attbyval = true;
|
||||
att->attalign = 'i';
|
||||
att->attstorage = 'p';
|
||||
}
|
||||
else if (typeForm->typtype == 'c' && typmod == sizeof(Pointer))
|
||||
{
|
||||
att->attlen = sizeof(Pointer);
|
||||
att->attbyval = true;
|
||||
att->attalign = 'd'; /* kluge to work with 8-byte pointers */
|
||||
/* XXX ought to have a separate attalign value for pointers ... */
|
||||
att->attstorage = 'p';
|
||||
}
|
||||
else
|
||||
{
|
||||
att->attlen = typeForm->typlen;
|
||||
att->attbyval = typeForm->typbyval;
|
||||
att->attalign = typeForm->typalign;
|
||||
att->attstorage = typeForm->typstorage;
|
||||
}
|
||||
|
||||
@ -494,6 +513,7 @@ TupleDescMakeSelfReference(TupleDesc desc,
|
||||
att->atttypid = TypeShellMake(relname);
|
||||
att->attlen = sizeof(Oid);
|
||||
att->attbyval = true;
|
||||
att->attalign = 'i';
|
||||
att->attstorage = 'p';
|
||||
att->attnelems = 0;
|
||||
}
|
||||
@ -582,15 +602,13 @@ BuildDescForRelation(List *schema, char *relname)
|
||||
* have a self reference, otherwise it's an error.
|
||||
* ----------------
|
||||
*/
|
||||
if (!strcmp(typename, relname))
|
||||
if (strcmp(typename, relname) == 0)
|
||||
TupleDescMakeSelfReference(desc, attnum, relname);
|
||||
else
|
||||
elog(ERROR, "DefineRelation: no such type %s",
|
||||
typename);
|
||||
}
|
||||
|
||||
desc->attrs[attnum - 1]->atttypmod = entry->typename->typmod;
|
||||
|
||||
/* This is for constraints */
|
||||
if (entry->is_not_null)
|
||||
constr->has_not_null = true;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.101 2000/12/11 09:14:03 inoue Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.102 2000/12/27 23:59:10 tgl Exp $
|
||||
*
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
@ -537,7 +537,7 @@ fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc,
|
||||
(
|
||||
(tupleDesc)->attrs[(attnum) - 1]->attcacheoff >= 0 ?
|
||||
(
|
||||
(Datum) fetchatt(&((tupleDesc)->attrs[(attnum) - 1]),
|
||||
fetchatt((tupleDesc)->attrs[(attnum) - 1],
|
||||
(char *) (tup)->t_data + (tup)->t_data->t_hoff +
|
||||
(tupleDesc)->attrs[(attnum) - 1]->attcacheoff)
|
||||
)
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/catalog.c,v 1.37 2000/11/16 22:30:17 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/catalog.c,v 1.38 2000/12/27 23:59:11 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -223,7 +223,7 @@ IsSharedSystemRelationName(const char *relname)
|
||||
* user programs to use them for temporary object identifiers.
|
||||
*/
|
||||
Oid
|
||||
newoid()
|
||||
newoid(void)
|
||||
{
|
||||
Oid lastoid;
|
||||
|
||||
@ -232,57 +232,3 @@ newoid()
|
||||
elog(ERROR, "newoid: GetNewObjectId returns invalid oid");
|
||||
return lastoid;
|
||||
}
|
||||
|
||||
/*
|
||||
* fillatt - fills the ATTRIBUTE relation fields from the TYP
|
||||
*
|
||||
* Expects that the atttypid domain is set for each att[].
|
||||
* Returns with the attnum, and attlen domains set.
|
||||
* attnum, attproc, atttyparg, ... should be set by the user.
|
||||
*
|
||||
* In the future, attnum may not be set?!? or may be passed as an arg?!?
|
||||
*
|
||||
* Current implementation is very inefficient--should cashe the
|
||||
* information if this is at all possible.
|
||||
*
|
||||
* Check to see if this is really needed, and especially in the case
|
||||
* of index tuples.
|
||||
*/
|
||||
void
|
||||
fillatt(TupleDesc tupleDesc)
|
||||
{
|
||||
int natts = tupleDesc->natts;
|
||||
Form_pg_attribute *att = tupleDesc->attrs;
|
||||
Form_pg_attribute *attributeP;
|
||||
int i;
|
||||
|
||||
if (natts < 0 || natts > MaxHeapAttributeNumber)
|
||||
elog(ERROR, "fillatt: %d attributes is too large", natts);
|
||||
if (natts == 0)
|
||||
{
|
||||
elog(DEBUG, "fillatt: called with natts == 0");
|
||||
return;
|
||||
}
|
||||
|
||||
attributeP = &att[0];
|
||||
|
||||
for (i = 1; i <= natts; i++)
|
||||
{
|
||||
(*attributeP)->attnum = (int16) i;
|
||||
|
||||
/*
|
||||
* Check if the attr is a set before messing with the length
|
||||
* and byval, since those were already set in
|
||||
* TupleDescInitEntry. In fact, this seems redundant here,
|
||||
* but who knows what I'll break if I take it out...
|
||||
*/
|
||||
if (!(*attributeP)->attisset)
|
||||
{
|
||||
get_typlenbyval((*attributeP)->atttypid,
|
||||
& (*attributeP)->attlen,
|
||||
& (*attributeP)->attbyval);
|
||||
}
|
||||
|
||||
attributeP++;
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.154 2000/12/22 23:12:03 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.155 2000/12/27 23:59:11 tgl Exp $
|
||||
*
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
@ -583,12 +583,6 @@ AddNewAttributeTuples(Oid new_rel_oid,
|
||||
if (hasindex)
|
||||
CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
|
||||
|
||||
/* ----------------
|
||||
* initialize tuple descriptor.
|
||||
* ----------------
|
||||
*/
|
||||
fillatt(tupdesc);
|
||||
|
||||
/* ----------------
|
||||
* first we add the user attributes..
|
||||
* ----------------
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.125 2000/12/02 20:49:24 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.126 2000/12/27 23:59:14 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -49,7 +49,6 @@ static void CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim,
|
||||
static void CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null_print);
|
||||
static Oid GetInputFunction(Oid type);
|
||||
static Oid GetTypeElement(Oid type);
|
||||
static bool IsTypeByVal(Oid type);
|
||||
static void CopyReadNewline(FILE *fp, int *newline);
|
||||
static char *CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline, char *null_print);
|
||||
static void CopyAttributeOut(FILE *fp, char *string, char *delim);
|
||||
@ -586,7 +585,6 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
|
||||
Oid in_func_oid;
|
||||
Datum *values;
|
||||
char *nulls;
|
||||
bool *byval;
|
||||
bool isnull;
|
||||
int done = 0;
|
||||
char *string = NULL,
|
||||
@ -653,13 +651,9 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
|
||||
|
||||
values = (Datum *) palloc(attr_count * sizeof(Datum));
|
||||
nulls = (char *) palloc(attr_count * sizeof(char));
|
||||
byval = (bool *) palloc(attr_count * sizeof(bool));
|
||||
|
||||
for (i = 0; i < attr_count; i++)
|
||||
{
|
||||
nulls[i] = ' ';
|
||||
byval[i] = IsTypeByVal(attr[i]->atttypid);
|
||||
}
|
||||
|
||||
lineno = 0;
|
||||
fe_eof = false;
|
||||
@ -742,36 +736,11 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
|
||||
|
||||
for (i = 0; i < attr_count; i++)
|
||||
{
|
||||
if (byval[i] && nulls[i] != 'n')
|
||||
{
|
||||
|
||||
switch (attr[i]->attlen)
|
||||
{
|
||||
case sizeof(char):
|
||||
values[i] = (Datum) *(unsigned char *) ptr;
|
||||
ptr += sizeof(char);
|
||||
break;
|
||||
case sizeof(short):
|
||||
ptr = (char *) SHORTALIGN(ptr);
|
||||
values[i] = (Datum) *(unsigned short *) ptr;
|
||||
ptr += sizeof(short);
|
||||
break;
|
||||
case sizeof(int32):
|
||||
ptr = (char *) INTALIGN(ptr);
|
||||
values[i] = (Datum) *(uint32 *) ptr;
|
||||
ptr += sizeof(int32);
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "COPY BINARY: impossible size");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (nulls[i] != 'n')
|
||||
{
|
||||
ptr = (char *) att_align(ptr, attr[i]->attlen, attr[i]->attalign);
|
||||
values[i] = (Datum) ptr;
|
||||
ptr = att_addlength(ptr, attr[i]->attlen, ptr);
|
||||
}
|
||||
if (nulls[i] == 'n')
|
||||
continue;
|
||||
ptr = (char *) att_align((long) ptr, attr[i]->attlen, attr[i]->attalign);
|
||||
values[i] = fetchatt(attr[i], ptr);
|
||||
ptr = att_addlength(ptr, attr[i]->attlen, ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -832,7 +801,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
|
||||
|
||||
for (i = 0; i < attr_count; i++)
|
||||
{
|
||||
if (!byval[i] && nulls[i] != 'n')
|
||||
if (!attr[i]->attbyval && nulls[i] != 'n')
|
||||
{
|
||||
if (!binary)
|
||||
pfree((void *) values[i]);
|
||||
@ -855,7 +824,6 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
|
||||
|
||||
pfree(values);
|
||||
pfree(nulls);
|
||||
pfree(byval);
|
||||
|
||||
if (!binary)
|
||||
{
|
||||
@ -902,22 +870,6 @@ GetTypeElement(Oid type)
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsTypeByVal(Oid type)
|
||||
{
|
||||
HeapTuple typeTuple;
|
||||
bool result;
|
||||
|
||||
typeTuple = SearchSysCache(TYPEOID,
|
||||
ObjectIdGetDatum(type),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(typeTuple))
|
||||
elog(ERROR, "IsTypeByVal: Cache lookup of type %u failed", type);
|
||||
result = ((Form_pg_type) GETSTRUCT(typeTuple))->typbyval;
|
||||
ReleaseSysCache(typeTuple);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reads input from fp until an end of line is seen.
|
||||
|
@ -15,7 +15,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.43 2000/11/12 00:36:57 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.44 2000/12/27 23:59:11 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -835,7 +835,7 @@ ExecGetTupType(Plan *node)
|
||||
return tupType;
|
||||
}
|
||||
|
||||
/*
|
||||
#ifdef NOT_USED
|
||||
TupleDesc
|
||||
ExecCopyTupType(TupleDesc td, int natts)
|
||||
{
|
||||
@ -852,30 +852,23 @@ ExecCopyTupType(TupleDesc td, int natts)
|
||||
}
|
||||
return newTd;
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecTypeFromTL
|
||||
*
|
||||
* Generate a tuple descriptor for the result tuple of a targetlist.
|
||||
* Note that resjunk columns, if any, are included in the result.
|
||||
*
|
||||
* Currently there are about 4 different places where we create
|
||||
* TupleDescriptors. They should all be merged, or perhaps
|
||||
* be rewritten to call BuildDesc().
|
||||
*
|
||||
* old comments
|
||||
* Forms attribute type info from the target list in the node.
|
||||
* It assumes all domains are individually specified in the target list.
|
||||
* It fails if the target list contains something like Emp.all
|
||||
* which represents all the attributes from EMP relation.
|
||||
*
|
||||
* Conditions:
|
||||
* The inner and outer subtrees should be initialized because it
|
||||
* might be necessary to know the type infos of the subtrees.
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
TupleDesc
|
||||
ExecTypeFromTL(List *targetList)
|
||||
{
|
||||
List *tlcdr;
|
||||
List *tlitem;
|
||||
TupleDesc typeInfo;
|
||||
Resdom *resdom;
|
||||
Oid restype;
|
||||
@ -897,14 +890,12 @@ ExecTypeFromTL(List *targetList)
|
||||
typeInfo = CreateTemplateTupleDesc(len);
|
||||
|
||||
/* ----------------
|
||||
* notes: get resdom from (resdom expr)
|
||||
* get_typbyval comes from src/lib/l-lisp/lsyscache.c
|
||||
* scan list, generate type info for each entry
|
||||
* ----------------
|
||||
*/
|
||||
tlcdr = targetList;
|
||||
while (tlcdr != NIL)
|
||||
foreach(tlitem, targetList)
|
||||
{
|
||||
TargetEntry *tle = lfirst(tlcdr);
|
||||
TargetEntry *tle = lfirst(tlitem);
|
||||
|
||||
if (tle->resdom != NULL)
|
||||
{
|
||||
@ -920,7 +911,7 @@ ExecTypeFromTL(List *targetList)
|
||||
0,
|
||||
false);
|
||||
|
||||
/*
|
||||
#ifdef NOT_USED
|
||||
ExecSetTypeInfo(resdom->resno - 1,
|
||||
typeInfo,
|
||||
(Oid) restype,
|
||||
@ -929,13 +920,14 @@ ExecTypeFromTL(List *targetList)
|
||||
NameStr(*resdom->resname),
|
||||
get_typbyval(restype),
|
||||
get_typalign(restype));
|
||||
*/
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
/* XXX this branch looks fairly broken ... tgl 12/2000 */
|
||||
Resdom *fjRes;
|
||||
List *fjTlistP;
|
||||
List *fjList = lfirst(tlcdr);
|
||||
List *fjList = lfirst(tlitem);
|
||||
|
||||
#ifdef SETS_FIXED
|
||||
TargetEntry *tle;
|
||||
@ -953,7 +945,7 @@ ExecTypeFromTL(List *targetList)
|
||||
fjRes->restypmod,
|
||||
0,
|
||||
false);
|
||||
/*
|
||||
#ifdef NOT_USED
|
||||
ExecSetTypeInfo(fjRes->resno - 1,
|
||||
typeInfo,
|
||||
(Oid) restype,
|
||||
@ -962,7 +954,7 @@ ExecTypeFromTL(List *targetList)
|
||||
(char *) fjRes->resname,
|
||||
get_typbyval(restype),
|
||||
get_typalign(restype));
|
||||
*/
|
||||
#endif
|
||||
|
||||
foreach(fjTlistP, lnext(fjList))
|
||||
{
|
||||
@ -978,7 +970,7 @@ ExecTypeFromTL(List *targetList)
|
||||
0,
|
||||
false);
|
||||
|
||||
/*
|
||||
#ifdef NOT_USED
|
||||
ExecSetTypeInfo(fjRes->resno - 1,
|
||||
typeInfo,
|
||||
(Oid) fjRes->restype,
|
||||
@ -987,11 +979,9 @@ ExecTypeFromTL(List *targetList)
|
||||
(char *) fjRes->resname,
|
||||
get_typbyval(fjRes->restype),
|
||||
get_typalign(fjRes->restype));
|
||||
*/
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
tlcdr = lnext(tlcdr);
|
||||
}
|
||||
|
||||
return typeInfo;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.69 2000/11/16 22:30:20 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.70 2000/12/27 23:59:11 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -274,16 +274,10 @@ ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate)
|
||||
{
|
||||
List *targetList;
|
||||
TupleDesc tupDesc;
|
||||
int len;
|
||||
|
||||
targetList = node->targetlist;
|
||||
tupDesc = ExecTypeFromTL(targetList);
|
||||
len = ExecTargetListLength(targetList);
|
||||
|
||||
if (len > 0)
|
||||
ExecAssignResultType(commonstate, tupDesc);
|
||||
else
|
||||
ExecAssignResultType(commonstate, (TupleDesc) NULL);
|
||||
ExecAssignResultType(commonstate, tupDesc);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
@ -582,8 +576,8 @@ ExecSetTypeInfo(int index,
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* ExecFreeTypeInfo frees the array of attrbutes
|
||||
* created by ExecMakeTypeInfo and returned by ExecTypeFromTL...
|
||||
* ExecFreeTypeInfo frees the array of attributes
|
||||
* created by ExecMakeTypeInfo and returned by ExecTypeFromTL
|
||||
* ----------------
|
||||
*/
|
||||
void
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.95 2000/12/15 19:22:03 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.96 2000/12/27 23:59:11 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -442,10 +442,12 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
|
||||
/*
|
||||
* for func(relname), the param to the function is the tuple
|
||||
* under consideration. we build a special VarNode to reflect
|
||||
* under consideration. We build a special VarNode to reflect
|
||||
* this -- it has varno set to the correct range table entry,
|
||||
* but has varattno == 0 to signal that the whole tuple is the
|
||||
* argument.
|
||||
* argument. Also, it has typmod set to sizeof(Pointer) to
|
||||
* signal that the runtime representation will be a pointer
|
||||
* not an Oid.
|
||||
*/
|
||||
if (rte->relname == NULL)
|
||||
elog(ERROR,
|
||||
@ -453,7 +455,11 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
toid = typenameTypeId(rte->relname);
|
||||
|
||||
/* replace it in the arg list */
|
||||
lfirst(i) = makeVar(vnum, 0, toid, -1, sublevels_up);
|
||||
lfirst(i) = makeVar(vnum,
|
||||
InvalidAttrNumber,
|
||||
toid,
|
||||
sizeof(Pointer),
|
||||
sublevels_up);
|
||||
}
|
||||
else if (!attisset)
|
||||
toid = exprType(arg);
|
||||
|
@ -8,15 +8,15 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.67 2000/12/03 20:45:35 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.68 2000/12/27 23:59:12 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/tupmacs.h"
|
||||
#include "catalog/catalog.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "utils/array.h"
|
||||
@ -596,48 +596,24 @@ array_out(PG_FUNCTION_ARGS)
|
||||
values = (char **) palloc(nitems * sizeof(char *));
|
||||
for (i = 0; i < nitems; i++)
|
||||
{
|
||||
if (typbyval)
|
||||
{
|
||||
switch (typlen)
|
||||
{
|
||||
case 1:
|
||||
values[i] = DatumGetCString(FunctionCall3(&outputproc,
|
||||
CharGetDatum(*p),
|
||||
ObjectIdGetDatum(typelem),
|
||||
Int32GetDatum(-1)));
|
||||
break;
|
||||
case 2:
|
||||
values[i] = DatumGetCString(FunctionCall3(&outputproc,
|
||||
Int16GetDatum(*(int16 *) p),
|
||||
ObjectIdGetDatum(typelem),
|
||||
Int32GetDatum(-1)));
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
values[i] = DatumGetCString(FunctionCall3(&outputproc,
|
||||
Int32GetDatum(*(int32 *) p),
|
||||
ObjectIdGetDatum(typelem),
|
||||
Int32GetDatum(-1)));
|
||||
break;
|
||||
}
|
||||
p += typlen;
|
||||
}
|
||||
else
|
||||
{
|
||||
values[i] = DatumGetCString(FunctionCall3(&outputproc,
|
||||
PointerGetDatum(p),
|
||||
ObjectIdGetDatum(typelem),
|
||||
Int32GetDatum(-1)));
|
||||
if (typlen > 0)
|
||||
p += typlen;
|
||||
else
|
||||
p += INTALIGN(*(int32 *) p);
|
||||
Datum itemvalue;
|
||||
|
||||
/*
|
||||
* For the pair of double quotes
|
||||
*/
|
||||
itemvalue = fetch_att(p, typbyval, typlen);
|
||||
values[i] = DatumGetCString(FunctionCall3(&outputproc,
|
||||
itemvalue,
|
||||
ObjectIdGetDatum(typelem),
|
||||
Int32GetDatum(-1)));
|
||||
if (typlen > 0)
|
||||
p += typlen;
|
||||
else
|
||||
p += INTALIGN(*(int32 *) p);
|
||||
|
||||
/*
|
||||
* For the pair of double quotes
|
||||
*/
|
||||
if (!typbyval)
|
||||
overall_length += 2;
|
||||
}
|
||||
|
||||
for (tmp = values[i]; *tmp; tmp++)
|
||||
{
|
||||
overall_length += 1;
|
||||
@ -1358,35 +1334,12 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType)
|
||||
for (i = 0; i < nitems; i++)
|
||||
{
|
||||
/* Get source element */
|
||||
if (inp_typbyval)
|
||||
{
|
||||
switch (inp_typlen)
|
||||
{
|
||||
case 1:
|
||||
elt = CharGetDatum(*s);
|
||||
break;
|
||||
case 2:
|
||||
elt = Int16GetDatum(*(int16 *) s);
|
||||
break;
|
||||
case 4:
|
||||
elt = Int32GetDatum(*(int32 *) s);
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "array_map: unsupported byval length %d",
|
||||
inp_typlen);
|
||||
elt = 0; /* keep compiler quiet */
|
||||
break;
|
||||
}
|
||||
elt = fetch_att(s, inp_typbyval, inp_typlen);
|
||||
|
||||
if (inp_typlen > 0)
|
||||
s += inp_typlen;
|
||||
}
|
||||
else
|
||||
{
|
||||
elt = PointerGetDatum(s);
|
||||
if (inp_typlen > 0)
|
||||
s += inp_typlen;
|
||||
else
|
||||
s += INTALIGN(*(int32 *) s);
|
||||
}
|
||||
s += INTALIGN(*(int32 *) s);
|
||||
|
||||
/*
|
||||
* Apply the given function to source elt and extra args.
|
||||
@ -1516,30 +1469,11 @@ deconstruct_array(ArrayType *array,
|
||||
p = ARR_DATA_PTR(array);
|
||||
for (i = 0; i < nelems; i++)
|
||||
{
|
||||
if (elmbyval)
|
||||
{
|
||||
switch (elmlen)
|
||||
{
|
||||
case 1:
|
||||
elems[i] = CharGetDatum(*p);
|
||||
break;
|
||||
case 2:
|
||||
elems[i] = Int16GetDatum(*(int16 *) p);
|
||||
break;
|
||||
case 4:
|
||||
elems[i] = Int32GetDatum(*(int32 *) p);
|
||||
break;
|
||||
}
|
||||
elems[i] = fetch_att(p, elmbyval, elmlen);
|
||||
if (elmlen > 0)
|
||||
p += elmlen;
|
||||
}
|
||||
else
|
||||
{
|
||||
elems[i] = PointerGetDatum(p);
|
||||
if (elmlen > 0)
|
||||
p += elmlen;
|
||||
else
|
||||
p += INTALIGN(VARSIZE(p));
|
||||
}
|
||||
p += INTALIGN(VARSIZE(p));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1616,22 +1550,7 @@ system_cache_lookup(Oid element_type,
|
||||
static Datum
|
||||
ArrayCast(char *value, bool byval, int len)
|
||||
{
|
||||
if (! byval)
|
||||
return PointerGetDatum(value);
|
||||
|
||||
switch (len)
|
||||
{
|
||||
case 1:
|
||||
return CharGetDatum(*value);
|
||||
case 2:
|
||||
return Int16GetDatum(*(int16 *) value);
|
||||
case 4:
|
||||
return Int32GetDatum(*(int32 *) value);
|
||||
default:
|
||||
elog(ERROR, "ArrayCast: unsupported byval length %d", len);
|
||||
break;
|
||||
}
|
||||
return 0; /* keep compiler quiet */
|
||||
return fetch_att(value, byval, len);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1651,22 +1570,7 @@ ArrayCastAndSet(Datum src,
|
||||
{
|
||||
if (typbyval)
|
||||
{
|
||||
switch (typlen)
|
||||
{
|
||||
case 1:
|
||||
*dest = DatumGetChar(src);
|
||||
break;
|
||||
case 2:
|
||||
*(int16 *) dest = DatumGetInt16(src);
|
||||
break;
|
||||
case 4:
|
||||
*(int32 *) dest = DatumGetInt32(src);
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "ArrayCastAndSet: unsupported byval length %d",
|
||||
typlen);
|
||||
break;
|
||||
}
|
||||
store_att_byval(dest, src, typlen);
|
||||
/* For by-val types, assume no alignment padding is needed */
|
||||
inc = typlen;
|
||||
}
|
||||
|
25
src/backend/utils/cache/lsyscache.c
vendored
25
src/backend/utils/cache/lsyscache.c
vendored
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.48 2000/11/20 20:36:49 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.49 2000/12/27 23:59:12 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Eventually, the index information should go through here, too.
|
||||
@ -15,6 +15,7 @@
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/tupmacs.h"
|
||||
#include "catalog/pg_operator.h"
|
||||
#include "catalog/pg_proc.h"
|
||||
#include "catalog/pg_type.h"
|
||||
@ -807,28 +808,8 @@ get_typdefault(Oid typid)
|
||||
|
||||
if (typByVal)
|
||||
{
|
||||
int8 i8;
|
||||
int16 i16;
|
||||
int32 i32 = 0;
|
||||
|
||||
if (dataSize == typLen)
|
||||
{
|
||||
switch (typLen)
|
||||
{
|
||||
case sizeof(int8):
|
||||
memcpy((char *) &i8, VARDATA(typDefault), sizeof(int8));
|
||||
i32 = i8;
|
||||
break;
|
||||
case sizeof(int16):
|
||||
memcpy((char *) &i16, VARDATA(typDefault), sizeof(int16));
|
||||
i32 = i16;
|
||||
break;
|
||||
case sizeof(int32):
|
||||
memcpy((char *) &i32, VARDATA(typDefault), sizeof(int32));
|
||||
break;
|
||||
}
|
||||
returnValue = Int32GetDatum(i32);
|
||||
}
|
||||
returnValue = fetch_att(VARDATA(typDefault), typByVal, typLen);
|
||||
else
|
||||
returnValue = PointerGetDatum(NULL);
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: heapam.h,v 1.59 2000/11/30 18:38:46 tgl Exp $
|
||||
* $Id: heapam.h,v 1.60 2000/12/27 23:59:13 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -90,9 +90,15 @@ typedef HeapAccessStatisticsData *HeapAccessStatistics;
|
||||
/* ----------------
|
||||
* fastgetattr
|
||||
*
|
||||
* This gets called many times, so we macro the cacheable and NULL
|
||||
* lookups, and call noncachegetattr() for the rest.
|
||||
* Fetch a user attribute's value as a Datum (might be either a
|
||||
* value, or a pointer into the data area of the tuple).
|
||||
*
|
||||
* This must not be used when a system attribute might be requested.
|
||||
* Furthermore, the passed attnum MUST be valid. Use heap_getattr()
|
||||
* instead, if in doubt.
|
||||
*
|
||||
* This gets called many times, so we macro the cacheable and NULL
|
||||
* lookups, and call nocachegetattr() for the rest.
|
||||
* ----------------
|
||||
*/
|
||||
|
||||
@ -109,7 +115,7 @@ extern Datum nocachegetattr(HeapTuple tup, int attnum,
|
||||
( \
|
||||
(tupleDesc)->attrs[(attnum)-1]->attcacheoff >= 0 ? \
|
||||
( \
|
||||
(Datum) fetchatt(&((tupleDesc)->attrs[(attnum)-1]), \
|
||||
fetchatt((tupleDesc)->attrs[(attnum)-1], \
|
||||
(char *) (tup)->t_data + (tup)->t_data->t_hoff + \
|
||||
(tupleDesc)->attrs[(attnum)-1]->attcacheoff) \
|
||||
) \
|
||||
@ -132,9 +138,8 @@ extern Datum nocachegetattr(HeapTuple tup, int attnum,
|
||||
|
||||
#else /* defined(DISABLE_COMPLEX_MACRO) */
|
||||
|
||||
extern Datum
|
||||
fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc,
|
||||
bool *isnull);
|
||||
extern Datum fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc,
|
||||
bool *isnull);
|
||||
|
||||
#endif /* defined(DISABLE_COMPLEX_MACRO) */
|
||||
|
||||
@ -142,60 +147,39 @@ fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc,
|
||||
/* ----------------
|
||||
* heap_getattr
|
||||
*
|
||||
* Find a particular field in a row represented as a heap tuple.
|
||||
* We return a pointer into that heap tuple, which points to the
|
||||
* first byte of the value of the field in question.
|
||||
* Extract an attribute of a heap tuple and return it as a Datum.
|
||||
* This works for either system or user attributes. The given attnum
|
||||
* is properly range-checked.
|
||||
*
|
||||
* If the field in question has a NULL value, we return a null
|
||||
* pointer and return <*isnull> == true. Otherwise, we return
|
||||
* <*isnull> == false.
|
||||
* If the field in question has a NULL value, we return a zero Datum
|
||||
* and set *isnull == true. Otherwise, we set *isnull == false.
|
||||
*
|
||||
* <tup> is the pointer to the heap tuple. <attnum> is the attribute
|
||||
* number of the column (field) caller wants. <tupleDesc> is a
|
||||
* pointer to the structure describing the row and all its fields.
|
||||
*
|
||||
* Because this macro is often called with constants, it generates
|
||||
* compiler warnings about 'left-hand comma expression has no effect.
|
||||
*
|
||||
* ----------------
|
||||
*/
|
||||
#define heap_getattr(tup, attnum, tupleDesc, isnull) \
|
||||
( \
|
||||
AssertMacro((tup) != NULL && \
|
||||
(attnum) > FirstLowInvalidHeapAttributeNumber && \
|
||||
(attnum) != 0), \
|
||||
((attnum) > (int) (tup)->t_data->t_natts) ? \
|
||||
( \
|
||||
((isnull) ? (*(isnull) = true) : (dummyret)NULL), \
|
||||
(Datum)NULL \
|
||||
) \
|
||||
: \
|
||||
AssertMacro((tup) != NULL), \
|
||||
( \
|
||||
((attnum) > 0) ? \
|
||||
( \
|
||||
fastgetattr((tup), (attnum), (tupleDesc), (isnull)) \
|
||||
) \
|
||||
: \
|
||||
( \
|
||||
((isnull) ? (*(isnull) = false) : (dummyret)NULL), \
|
||||
((attnum) == SelfItemPointerAttributeNumber) ? \
|
||||
((attnum) > (int) (tup)->t_data->t_natts) ? \
|
||||
( \
|
||||
(Datum)((char *)&((tup)->t_self)) \
|
||||
((isnull) ? (*(isnull) = true) : (dummyret)NULL), \
|
||||
(Datum)NULL \
|
||||
) \
|
||||
: \
|
||||
(((attnum) == TableOidAttributeNumber) ? \
|
||||
( \
|
||||
(Datum)((tup)->t_tableOid) \
|
||||
) \
|
||||
: \
|
||||
( \
|
||||
(Datum)*(unsigned int *) \
|
||||
((char *)(tup)->t_data + heap_sysoffset[-(attnum)-1]) \
|
||||
)) \
|
||||
fastgetattr((tup), (attnum), (tupleDesc), (isnull)) \
|
||||
) \
|
||||
: \
|
||||
heap_getsysattr((tup), (attnum), (isnull)) \
|
||||
) \
|
||||
)
|
||||
|
||||
extern Datum heap_getsysattr(HeapTuple tup, int attnum, bool *isnull);
|
||||
|
||||
extern HeapAccessStatistics heap_access_stats; /* in stats.c */
|
||||
|
||||
/* ----------------
|
||||
@ -238,8 +222,6 @@ extern void DataFill(char *data, TupleDesc tupleDesc,
|
||||
Datum *value, char *nulls, uint16 *infomask,
|
||||
bits8 *bit);
|
||||
extern int heap_attisnull(HeapTuple tup, int attnum);
|
||||
extern int heap_sysattrlen(AttrNumber attno);
|
||||
extern bool heap_sysattrbyval(AttrNumber attno);
|
||||
extern Datum nocachegetattr(HeapTuple tup, int attnum,
|
||||
TupleDesc att, bool *isnull);
|
||||
extern HeapTuple heap_copytuple(HeapTuple tuple);
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: htup.h,v 1.41 2000/11/30 08:46:25 vadim Exp $
|
||||
* $Id: htup.h,v 1.42 2000/12/27 23:59:13 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -147,6 +147,9 @@ typedef struct xl_heap_update
|
||||
#define MaxAttrSize (10 * 1024 * 1024)
|
||||
|
||||
|
||||
/*
|
||||
* Attribute numbers for the system-defined attributes
|
||||
*/
|
||||
#define SelfItemPointerAttributeNumber (-1)
|
||||
#define ObjectIdAttributeNumber (-2)
|
||||
#define MinTransactionIdAttributeNumber (-3)
|
||||
@ -156,9 +159,6 @@ typedef struct xl_heap_update
|
||||
#define TableOidAttributeNumber (-7)
|
||||
#define FirstLowInvalidHeapAttributeNumber (-8)
|
||||
|
||||
/* If you make any changes above, the order of offsets in this must change */
|
||||
extern long heap_sysoffset[];
|
||||
|
||||
/*
|
||||
* This new HeapTuple for version >= 6.5 and this is why it was changed:
|
||||
*
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: itup.h,v 1.26 2000/11/30 18:38:46 tgl Exp $
|
||||
* $Id: itup.h,v 1.27 2000/12/27 23:59:13 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -111,7 +111,7 @@ typedef RetrieveIndexResultData *RetrieveIndexResult;
|
||||
( \
|
||||
(tupleDesc)->attrs[(attnum)-1]->attcacheoff >= 0 ? \
|
||||
( \
|
||||
(Datum) fetchatt(&((tupleDesc)->attrs[(attnum)-1]), \
|
||||
fetchatt((tupleDesc)->attrs[(attnum)-1], \
|
||||
(char *) (tup) + \
|
||||
( \
|
||||
IndexTupleHasMinHeader(tup) ? \
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: tupmacs.h,v 1.14 2000/03/17 02:36:37 tgl Exp $
|
||||
* $Id: tupmacs.h,v 1.15 2000/12/27 23:59:13 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -22,50 +22,79 @@
|
||||
#define att_isnull(ATT, BITS) (!((BITS)[(ATT) >> 3] & (1 << ((ATT) & 0x07))))
|
||||
|
||||
/*
|
||||
* given a Form_pg_attribute and a pointer into a tuple's data
|
||||
* area, return the correct value or pointer.
|
||||
* Given a Form_pg_attribute and a pointer into a tuple's data area,
|
||||
* return the correct value or pointer.
|
||||
*
|
||||
* We return a 4 byte (char *) value in all cases. If the attribute has
|
||||
* "byval" false or has variable length, we return the same pointer
|
||||
* into the tuple data area that we're passed. Otherwise, we return
|
||||
* the 1, 2, or 4 bytes pointed to by it, properly extended to 4
|
||||
* bytes, depending on the length of the attribute.
|
||||
* We return a Datum value in all cases. If the attribute has "byval" false,
|
||||
* we return the same pointer into the tuple data area that we're passed.
|
||||
* Otherwise, we return the correct number of bytes fetched from the data
|
||||
* area and extended to Datum form.
|
||||
*
|
||||
* note that T must already be properly LONGALIGN/SHORTALIGN'd for
|
||||
* this to work correctly.
|
||||
* On machines where Datum is 8 bytes, we support fetching 8-byte byval
|
||||
* attributes; otherwise, only 1, 2, and 4-byte values are supported.
|
||||
*
|
||||
* the double-cast is to stop gcc from (correctly) complaining about
|
||||
* casting integer types with size < sizeof(char *) to (char *).
|
||||
* sign-extension may get weird if you use an integer type that
|
||||
* isn't the same size as (char *) for the first cast. (on the other
|
||||
* hand, it's safe to use another type for the (foo *)(T).)
|
||||
*
|
||||
* attbyval seems to be fairly redundant. We have to return a pointer if
|
||||
* the value is longer than 4 bytes or has variable length; returning the
|
||||
* value would be useless. In fact, for at least the variable length case,
|
||||
* the caller assumes we return a pointer regardless of attbyval.
|
||||
* I would eliminate attbyval altogether, but I don't know how. -BRYANH.
|
||||
* Note that T must already be properly aligned for this to work correctly.
|
||||
*/
|
||||
#define fetchatt(A, T) \
|
||||
#define fetchatt(A,T) fetch_att(T, (A)->attbyval, (A)->attlen)
|
||||
|
||||
/*
|
||||
* Same, but work from byval/len parameters rather than Form_pg_attribute.
|
||||
*/
|
||||
#if SIZEOF_DATUM == 8
|
||||
|
||||
#define fetch_att(T,attbyval,attlen) \
|
||||
( \
|
||||
(*(A))->attbyval && (*(A))->attlen != -1 ? \
|
||||
(attbyval) ? \
|
||||
( \
|
||||
(*(A))->attlen > (int) sizeof(int16) ? \
|
||||
( \
|
||||
(char *) (long) *((int32 *)(T)) \
|
||||
) \
|
||||
(attlen) == (int) sizeof(Datum) ? \
|
||||
*((Datum *)(T)) \
|
||||
: \
|
||||
( \
|
||||
(attlen) == (int) sizeof(int32) ? \
|
||||
Int32GetDatum(*((int32 *)(T))) \
|
||||
: \
|
||||
( \
|
||||
(*(A))->attlen < (int) sizeof(int16) ? \
|
||||
(char *) (long) *((char *)(T)) \
|
||||
(attlen) == (int) sizeof(int16) ? \
|
||||
Int16GetDatum(*((int16 *)(T))) \
|
||||
: \
|
||||
(char *) (long) *((int16 *)(T))) \
|
||||
( \
|
||||
AssertMacro((attlen) == 1), \
|
||||
CharGetDatum(*((char *)(T))) \
|
||||
) \
|
||||
) \
|
||||
) \
|
||||
) \
|
||||
: \
|
||||
(char *) (T) \
|
||||
PointerGetDatum((char *) (T)) \
|
||||
)
|
||||
|
||||
/* att_align aligns the given offset as needed for a datum of length attlen
|
||||
#else /* SIZEOF_DATUM != 8 */
|
||||
|
||||
#define fetch_att(T,attbyval,attlen) \
|
||||
( \
|
||||
(attbyval) ? \
|
||||
( \
|
||||
(attlen) == (int) sizeof(int32) ? \
|
||||
Int32GetDatum(*((int32 *)(T))) \
|
||||
: \
|
||||
( \
|
||||
(attlen) == (int) sizeof(int16) ? \
|
||||
Int16GetDatum(*((int16 *)(T))) \
|
||||
: \
|
||||
( \
|
||||
AssertMacro((attlen) == 1), \
|
||||
CharGetDatum(*((char *)(T))) \
|
||||
) \
|
||||
) \
|
||||
) \
|
||||
: \
|
||||
PointerGetDatum((char *) (T)) \
|
||||
)
|
||||
|
||||
#endif /* SIZEOF_DATUM == 8 */
|
||||
|
||||
/*
|
||||
* att_align aligns the given offset as needed for a datum of length attlen
|
||||
* and alignment requirement attalign. In practice we don't need the length.
|
||||
* The attalign cases are tested in what is hopefully something like their
|
||||
* frequency of occurrence.
|
||||
@ -81,6 +110,10 @@
|
||||
))) \
|
||||
)
|
||||
|
||||
/*
|
||||
* att_addlength increments the given offset by the length of the attribute.
|
||||
* attval is only accessed if we are dealing with a varlena attribute.
|
||||
*/
|
||||
#define att_addlength(cur_offset, attlen, attval) \
|
||||
( \
|
||||
((attlen) != -1) ? \
|
||||
@ -93,4 +126,60 @@
|
||||
) \
|
||||
)
|
||||
|
||||
/*
|
||||
* store_att_byval is a partial inverse of fetch_att: store a given Datum
|
||||
* value into a tuple data area at the specified address. However, it only
|
||||
* handles the byval case, because in typical usage the caller needs to
|
||||
* distinguish by-val and by-ref cases anyway, and so a do-it-all macro
|
||||
* wouldn't be convenient.
|
||||
*/
|
||||
#if SIZEOF_DATUM == 8
|
||||
|
||||
#define store_att_byval(T,newdatum,attlen) \
|
||||
do { \
|
||||
switch (attlen) \
|
||||
{ \
|
||||
case sizeof(char): \
|
||||
*(char *) (T) = DatumGetChar(newdatum); \
|
||||
break; \
|
||||
case sizeof(int16): \
|
||||
*(int16 *) (T) = DatumGetInt16(newdatum); \
|
||||
break; \
|
||||
case sizeof(int32): \
|
||||
*(int32 *) (T) = DatumGetInt32(newdatum); \
|
||||
break; \
|
||||
case sizeof(Datum): \
|
||||
*(Datum *) (T) = (newdatum); \
|
||||
break; \
|
||||
default: \
|
||||
elog(ERROR, "store_att_byval: unsupported byval length %d", \
|
||||
(int) (attlen)); \
|
||||
break; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#else /* SIZEOF_DATUM != 8 */
|
||||
|
||||
#define store_att_byval(T,newdatum,attlen) \
|
||||
do { \
|
||||
switch (attlen) \
|
||||
{ \
|
||||
case sizeof(char): \
|
||||
*(char *) (T) = DatumGetChar(newdatum); \
|
||||
break; \
|
||||
case sizeof(int16): \
|
||||
*(int16 *) (T) = DatumGetInt16(newdatum); \
|
||||
break; \
|
||||
case sizeof(int32): \
|
||||
*(int32 *) (T) = DatumGetInt32(newdatum); \
|
||||
break; \
|
||||
default: \
|
||||
elog(ERROR, "store_att_byval: unsupported byval length %d", \
|
||||
(int) (attlen)); \
|
||||
break; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif /* SIZEOF_DATUM == 8 */
|
||||
|
||||
#endif
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: catalog.h,v 1.13 2000/10/16 14:52:26 vadim Exp $
|
||||
* $Id: catalog.h,v 1.14 2000/12/27 23:59:13 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -30,7 +30,7 @@ extern char *GetDatabasePath(Oid tblNode);
|
||||
|
||||
extern bool IsSystemRelationName(const char *relname);
|
||||
extern bool IsSharedSystemRelationName(const char *relname);
|
||||
|
||||
extern Oid newoid(void);
|
||||
extern void fillatt(TupleDesc att);
|
||||
|
||||
#endif /* CATALOG_H */
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: pg_type.h,v 1.98 2000/11/30 18:38:47 tgl Exp $
|
||||
* $Id: pg_type.h,v 1.99 2000/12/27 23:59:13 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* the genbki.sh script reads this file and generates .bki
|
||||
@ -51,13 +51,11 @@ CATALOG(pg_type) BOOTSTRAP
|
||||
|
||||
/*
|
||||
* typbyval determines whether internal Postgres routines pass a value
|
||||
* of this type by value or by reference. Only char, short, and int-
|
||||
* equivalent items can be passed by value, so if the type is not 1,
|
||||
* 2, or 4 bytes long, Postgres does not have the option of passing by
|
||||
* value and so typbyval had better be FALSE. Variable-length types
|
||||
* are always passed by reference. Note that typbyval can be false
|
||||
* even if the length would allow pass-by-value; this is currently
|
||||
* true for type float4, for example.
|
||||
* of this type by value or by reference. typbyval had better be FALSE
|
||||
* if the length is not 1, 2, or 4 (or 8 on 8-byte-Datum machines).
|
||||
* Variable-length types are always passed by reference. Note that
|
||||
* typbyval can be false even if the length would allow pass-by-value;
|
||||
* this is currently true for type float4, for example.
|
||||
*/
|
||||
bool typbyval;
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* or in config.h afterwards. Of course, if you edit config.h, then your
|
||||
* changes will be overwritten the next time you run configure.
|
||||
*
|
||||
* $Id: config.h.in,v 1.153 2000/12/02 18:16:40 tgl Exp $
|
||||
* $Id: config.h.in,v 1.154 2000/12/27 23:59:14 tgl Exp $
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_H
|
||||
@ -581,6 +581,11 @@ extern void srandom(unsigned int seed);
|
||||
/* Define this as the appropriate snprintf format for 64-bit ints, if any */
|
||||
#undef INT64_FORMAT
|
||||
|
||||
/*
|
||||
* We need a #define symbol for sizeof(Datum) for use in some #if tests.
|
||||
*/
|
||||
#undef SIZEOF_DATUM
|
||||
|
||||
/*
|
||||
* These must be defined as the alignment requirement (NOT the size) of
|
||||
* each of the basic C data types (except char, which we assume has align 1).
|
||||
|
Loading…
Reference in New Issue
Block a user