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:
Tom Lane 2000-12-27 23:59:14 +00:00
parent 97799fc475
commit 8609d4abf2
23 changed files with 497 additions and 660 deletions

97
configure vendored
View File

@ -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 $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 if eval "test \"`echo '$''{'pgac_cv_alignof_short'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
@ -7215,7 +7260,7 @@ else
pgac_cv_alignof_short='sizeof(short)' pgac_cv_alignof_short='sizeof(short)'
else else
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 7219 "configure" #line 7264 "configure"
#include "confdefs.h" #include "confdefs.h"
#include <stdio.h> #include <stdio.h>
struct { char filler; short field; } mystruct; struct { char filler; short field; } mystruct;
@ -7227,7 +7272,7 @@ main()
exit(0); exit(0);
} }
EOF 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 then
pgac_cv_alignof_short=`cat conftestval` pgac_cv_alignof_short=`cat conftestval`
else else
@ -7247,7 +7292,7 @@ EOF
echo $ac_n "checking alignment of int""... $ac_c" 1>&6 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 if eval "test \"`echo '$''{'pgac_cv_alignof_int'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
@ -7255,7 +7300,7 @@ else
pgac_cv_alignof_int='sizeof(int)' pgac_cv_alignof_int='sizeof(int)'
else else
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 7259 "configure" #line 7304 "configure"
#include "confdefs.h" #include "confdefs.h"
#include <stdio.h> #include <stdio.h>
struct { char filler; int field; } mystruct; struct { char filler; int field; } mystruct;
@ -7267,7 +7312,7 @@ main()
exit(0); exit(0);
} }
EOF 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 then
pgac_cv_alignof_int=`cat conftestval` pgac_cv_alignof_int=`cat conftestval`
else else
@ -7287,7 +7332,7 @@ EOF
echo $ac_n "checking alignment of long""... $ac_c" 1>&6 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 if eval "test \"`echo '$''{'pgac_cv_alignof_long'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
@ -7295,7 +7340,7 @@ else
pgac_cv_alignof_long='sizeof(long)' pgac_cv_alignof_long='sizeof(long)'
else else
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 7299 "configure" #line 7344 "configure"
#include "confdefs.h" #include "confdefs.h"
#include <stdio.h> #include <stdio.h>
struct { char filler; long field; } mystruct; struct { char filler; long field; } mystruct;
@ -7307,7 +7352,7 @@ main()
exit(0); exit(0);
} }
EOF 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 then
pgac_cv_alignof_long=`cat conftestval` pgac_cv_alignof_long=`cat conftestval`
else else
@ -7328,7 +7373,7 @@ EOF
if [ x"$HAVE_LONG_LONG_INT_64" = xyes ] ; then if [ x"$HAVE_LONG_LONG_INT_64" = xyes ] ; then
echo $ac_n "checking alignment of long long int""... $ac_c" 1>&6 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 if eval "test \"`echo '$''{'pgac_cv_alignof_long_long_int'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
@ -7336,7 +7381,7 @@ else
pgac_cv_alignof_long_long_int='sizeof(long long int)' pgac_cv_alignof_long_long_int='sizeof(long long int)'
else else
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 7340 "configure" #line 7385 "configure"
#include "confdefs.h" #include "confdefs.h"
#include <stdio.h> #include <stdio.h>
struct { char filler; long long int field; } mystruct; struct { char filler; long long int field; } mystruct;
@ -7348,7 +7393,7 @@ main()
exit(0); exit(0);
} }
EOF 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 then
pgac_cv_alignof_long_long_int=`cat conftestval` pgac_cv_alignof_long_long_int=`cat conftestval`
else else
@ -7369,7 +7414,7 @@ EOF
fi fi
echo $ac_n "checking alignment of double""... $ac_c" 1>&6 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 if eval "test \"`echo '$''{'pgac_cv_alignof_double'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
@ -7377,7 +7422,7 @@ else
pgac_cv_alignof_double='sizeof(double)' pgac_cv_alignof_double='sizeof(double)'
else else
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 7381 "configure" #line 7426 "configure"
#include "confdefs.h" #include "confdefs.h"
#include <stdio.h> #include <stdio.h>
struct { char filler; double field; } mystruct; struct { char filler; double field; } mystruct;
@ -7389,7 +7434,7 @@ main()
exit(0); exit(0);
} }
EOF 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 then
pgac_cv_alignof_double=`cat conftestval` pgac_cv_alignof_double=`cat conftestval`
else else
@ -7427,12 +7472,12 @@ EOF
echo $ac_n "checking for POSIX signal interface""... $ac_c" 1>&6 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 if eval "test \"`echo '$''{'pgac_cv_func_posix_signals'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 7436 "configure" #line 7481 "configure"
#include "confdefs.h" #include "confdefs.h"
#include <signal.h> #include <signal.h>
@ -7443,7 +7488,7 @@ act.sa_flags = SA_RESTART;
sigaction(0, &act, &oact); sigaction(0, &act, &oact);
; return 0; } ; return 0; }
EOF 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* rm -rf conftest*
pgac_cv_func_posix_signals=yes pgac_cv_func_posix_signals=yes
else else
@ -7473,7 +7518,7 @@ do
# Extract the first word of "$ac_prog", so it can be a program name with args. # Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2 set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 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 if eval "test \"`echo '$''{'ac_cv_path_TCLSH'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
@ -7509,7 +7554,7 @@ test -n "$TCLSH" && break
done done
echo $ac_n "checking for tclConfig.sh""... $ac_c" 1>&6 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 # Let user override test
if test -z "$TCL_CONFIG_SH"; then if test -z "$TCL_CONFIG_SH"; then
pgac_test_dirs="$with_tclconfig" pgac_test_dirs="$with_tclconfig"
@ -7542,7 +7587,7 @@ fi
# Check for Tk configuration script tkConfig.sh # Check for Tk configuration script tkConfig.sh
if test "$with_tk" = yes; then if test "$with_tk" = yes; then
echo $ac_n "checking for tkConfig.sh""... $ac_c" 1>&6 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 # Let user override test
if test -z "$TK_CONFIG_SH"; then if test -z "$TK_CONFIG_SH"; then
pgac_test_dirs="$with_tkconfig $with_tclconfig" 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. # Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2 set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 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 if eval "test \"`echo '$''{'ac_cv_prog_NSGMLS'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
@ -7617,7 +7662,7 @@ do
# Extract the first word of "$ac_prog", so it can be a program name with args. # Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2 set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 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 if eval "test \"`echo '$''{'ac_cv_prog_JADE'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
@ -7648,7 +7693,7 @@ done
echo $ac_n "checking for DocBook V3.1""... $ac_c" 1>&6 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 if eval "test \"`echo '$''{'pgac_cv_check_docbook'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
@ -7681,7 +7726,7 @@ have_docbook=$pgac_cv_check_docbook
echo $ac_n "checking for DocBook stylesheets""... $ac_c" 1>&6 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 if eval "test \"`echo '$''{'pgac_cv_path_stylesheets'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
@ -7720,7 +7765,7 @@ do
# Extract the first word of "$ac_prog", so it can be a program name with args. # Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2 set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 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 if eval "test \"`echo '$''{'ac_cv_prog_SGMLSPL'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else

View File

@ -1059,6 +1059,11 @@ AC_CHECK_FUNCS([strtoll strtoq], [break])
AC_CHECK_FUNCS([strtoull strtouq], [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. dnl Determine memory alignment requirements for the basic C datatypes.
PGAC_CHECK_ALIGNOF(short) PGAC_CHECK_ALIGNOF(short)

View File

@ -21,6 +21,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <string.h> #include <string.h>
#include "access/tupmacs.h"
#include "access/xact.h" #include "access/xact.h"
#include "fmgr.h" #include "fmgr.h"
#include "miscadmin.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); p = ARR_DATA_PTR(array);
for (i = 0; i < nitems; i++) for (i = 0; i < nitems; i++)
{ {
if (typbyval) Datum itemvalue;
{
switch (typlen) itemvalue = fetch_att(p, typbyval, 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;
}
p += typlen;
}
else
{
result = FunctionCall2(&finfo, PointerGetDatum(p), value);
if (typlen > 0) if (typlen > 0)
p += typlen; p += typlen;
else else
p += INTALIGN(*(int32 *) p); p += INTALIGN(*(int32 *) p);
}
result = FunctionCall2(&finfo, itemvalue, value);
if (DatumGetBool(result)) if (DatumGetBool(result))
{ {
if (!and) if (!and)

View File

@ -2,14 +2,14 @@
* *
* heaptuple.c * heaptuple.c
* This file contains heap tuple accessor and mutator routines, as well * 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) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* *
* IDENTIFICATION * 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 * NOTES
* The old interface functions have been converted to macros * The old interface functions have been converted to macros
@ -23,16 +23,6 @@
#include "access/heapam.h" #include "access/heapam.h"
#include "catalog/pg_type.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 * misc support routines
@ -48,12 +38,12 @@ ComputeDataSize(TupleDesc tupleDesc,
Datum *value, Datum *value,
char *nulls) char *nulls)
{ {
uint32 data_length; uint32 data_length = 0;
int i; int i;
int numberOfAttributes = tupleDesc->natts; int numberOfAttributes = tupleDesc->natts;
Form_pg_attribute *att = tupleDesc->attrs; Form_pg_attribute *att = tupleDesc->attrs;
for (data_length = 0, i = 0; i < numberOfAttributes; i++) for (i = 0; i < numberOfAttributes; i++)
{ {
if (nulls[i] != ' ') if (nulls[i] != ' ')
continue; continue;
@ -114,38 +104,33 @@ DataFill(char *data,
*bitP |= bitmask; *bitP |= bitmask;
} }
/* XXX we are aligning the pointer itself, not the offset */
data = (char *) att_align((long) data, att[i]->attlen, att[i]->attalign); data = (char *) att_align((long) data, att[i]->attlen, att[i]->attalign);
switch (att[i]->attlen)
if (att[i]->attbyval)
{ {
case -1: /* pass-by-value */
store_att_byval(data, value[i], att[i]->attlen);
}
else if (att[i]->attlen == -1)
{
/* varlena */
*infomask |= HEAP_HASVARLENA; *infomask |= HEAP_HASVARLENA;
if (VARATT_IS_EXTERNAL(value[i])) if (VARATT_IS_EXTERNAL(value[i]))
*infomask |= HEAP_HASEXTERNAL; *infomask |= HEAP_HASEXTERNAL;
if (VARATT_IS_COMPRESSED(value[i])) if (VARATT_IS_COMPRESSED(value[i]))
*infomask |= HEAP_HASCOMPRESSED; *infomask |= HEAP_HASCOMPRESSED;
data_length = VARATT_SIZE(DatumGetPointer(value[i])); data_length = VARATT_SIZE(DatumGetPointer(value[i]));
memmove(data, DatumGetPointer(value[i]), data_length); memcpy(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;
} }
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]); data = (char *) att_addlength((long) data, att[i]->attlen, value[i]);
} }
} }
@ -192,89 +177,6 @@ heap_attisnull(HeapTuple tup, int attnum)
return 0; 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 * nocachegetattr
* *
@ -332,8 +234,7 @@ nocachegetattr(HeapTuple tuple,
/* This is handled in the macro */ /* This is handled in the macro */
if (att[attnum]->attcacheoff != -1) if (att[attnum]->attcacheoff != -1)
{ {
return (Datum) return fetchatt(att[attnum],
fetchatt(&(att[attnum]),
(char *) tup + tup->t_hoff + att[attnum]->attcacheoff); (char *) tup + tup->t_hoff + att[attnum]->attcacheoff);
} }
#endif #endif
@ -397,7 +298,7 @@ nocachegetattr(HeapTuple tuple,
{ {
if (att[attnum]->attcacheoff != -1) if (att[attnum]->attcacheoff != -1)
{ {
return (Datum) fetchatt(&(att[attnum]), return fetchatt(att[attnum],
tp + att[attnum]->attcacheoff); tp + att[attnum]->attcacheoff);
} }
else if (!HeapTupleAllFixed(tuple)) else if (!HeapTupleAllFixed(tuple))
@ -460,7 +361,7 @@ nocachegetattr(HeapTuple tuple,
off = att_addlength(off, att[j]->attlen, tp + off); 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 else
{ {
@ -508,10 +409,66 @@ nocachegetattr(HeapTuple tuple,
off = att_align(off, att[attnum]->attlen, att[attnum]->attalign); 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 * heap_copytuple
* *
@ -630,18 +587,21 @@ heap_formtuple(TupleDesc tupleDescriptor,
int i; int i;
int numberOfAttributes = tupleDescriptor->natts; int numberOfAttributes = tupleDescriptor->natts;
len = offsetof(HeapTupleHeaderData, t_bits);
for (i = 0; i < numberOfAttributes && !hasnull; i++)
{
if (nulls[i] != ' ')
hasnull = true;
}
if (numberOfAttributes > MaxHeapAttributeNumber) if (numberOfAttributes > MaxHeapAttributeNumber)
elog(ERROR, "heap_formtuple: numberOfAttributes of %d > %d", elog(ERROR, "heap_formtuple: numberOfAttributes of %d > %d",
numberOfAttributes, MaxHeapAttributeNumber); numberOfAttributes, MaxHeapAttributeNumber);
len = offsetof(HeapTupleHeaderData, t_bits);
for (i = 0; i < numberOfAttributes; i++)
{
if (nulls[i] != ' ')
{
hasnull = true;
break;
}
}
if (hasnull) if (hasnull)
{ {
bitmaplen = BITMAPLEN(numberOfAttributes); bitmaplen = BITMAPLEN(numberOfAttributes);

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * 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,7 +217,7 @@ nocache_index_getattr(IndexTuple tup,
/* This is handled in the macro */ /* This is handled in the macro */
if (att[attnum]->attcacheoff != -1) if (att[attnum]->attcacheoff != -1)
{ {
return (Datum) fetchatt(&(att[attnum]), return fetchatt(att[attnum],
(char *) tup + data_off + (char *) tup + data_off +
att[attnum]->attcacheoff); att[attnum]->attcacheoff);
} }
@ -279,7 +279,7 @@ nocache_index_getattr(IndexTuple tup,
{ {
if (att[attnum]->attcacheoff != -1) if (att[attnum]->attcacheoff != -1)
{ {
return (Datum) fetchatt(&(att[attnum]), return fetchatt(att[attnum],
tp + att[attnum]->attcacheoff); tp + att[attnum]->attcacheoff);
} }
else if (!IndexTupleAllFixed(tup)) else if (!IndexTupleAllFixed(tup))
@ -332,7 +332,7 @@ nocache_index_getattr(IndexTuple tup,
off += att[j]->attlen; off += att[j]->attlen;
} }
return (Datum) fetchatt(&(att[attnum]), tp + att[attnum]->attcacheoff); return fetchatt(att[attnum], tp + att[attnum]->attcacheoff);
} }
else else
{ {
@ -379,7 +379,7 @@ nocache_index_getattr(IndexTuple tup,
off = att_align(off, att[attnum]->attlen, att[attnum]->attalign); off = att_align(off, att[attnum]->attlen, att[attnum]->attalign);
return (Datum) fetchatt(&att[attnum], tp + off); return fetchatt(att[attnum], tp + off);
} }
} }

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * 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)); pq_sendint(&buf, len, sizeof(int32));
if (typeinfo->attrs[i]->attbyval) if (typeinfo->attrs[i]->attbyval)
{ {
int8 i8; Datum datumBuf;
int16 i16;
int32 i32;
switch (len) /*
{ * We need this horsing around because we don't know how
case sizeof(int8): * shorter data values are aligned within a Datum.
i8 = DatumGetChar(attr); */
pq_sendbytes(&buf, (char *) &i8, len); store_att_byval(&datumBuf, attr, len);
break; pq_sendbytes(&buf, (char *) &datumBuf, len);
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;
}
#ifdef IPORTAL_DEBUG #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 #endif
} }
else else

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* some of the executor utility code such as "ExecTypeFromTL" should be * some of the executor utility code such as "ExecTypeFromTL" should be
@ -352,7 +352,6 @@ TupleDescInitEntry(TupleDesc desc,
AssertArg(!PointerIsValid(desc->attrs[attributeNumber - 1])); AssertArg(!PointerIsValid(desc->attrs[attributeNumber - 1]));
/* ---------------- /* ----------------
* allocate storage for this attribute * allocate storage for this attribute
* ---------------- * ----------------
@ -362,7 +361,7 @@ TupleDescInitEntry(TupleDesc desc,
desc->attrs[attributeNumber - 1] = att; desc->attrs[attributeNumber - 1] = att;
/* ---------------- /* ----------------
* initialize some of the attribute fields * initialize the attribute fields
* ---------------- * ----------------
*/ */
att->attrelid = 0; /* dummy value */ att->attrelid = 0; /* dummy value */
@ -372,7 +371,6 @@ TupleDescInitEntry(TupleDesc desc,
else else
MemSet(NameStr(att->attname), 0, NAMEDATALEN); MemSet(NameStr(att->attname), 0, NAMEDATALEN);
att->attdispersion = 0; /* dummy value */ att->attdispersion = 0; /* dummy value */
att->attcacheoff = -1; att->attcacheoff = -1;
att->atttypmod = typmod; att->atttypmod = typmod;
@ -414,8 +412,8 @@ TupleDescInitEntry(TupleDesc desc,
att->atttypid = InvalidOid; att->atttypid = InvalidOid;
att->attlen = (int16) 0; att->attlen = (int16) 0;
att->attbyval = (bool) 0; att->attbyval = (bool) 0;
att->attstorage = 'p';
att->attalign = 'i'; att->attalign = 'i';
att->attstorage = 'p';
return false; return false;
} }
@ -427,42 +425,63 @@ TupleDescInitEntry(TupleDesc desc,
typeForm = (Form_pg_type) GETSTRUCT(tuple); typeForm = (Form_pg_type) GETSTRUCT(tuple);
att->atttypid = tuple->t_data->t_oid; att->atttypid = tuple->t_data->t_oid;
att->attalign = typeForm->typalign;
/*------------------------ /*------------------------
If this attribute is a set, what is really stored in the * There are a couple of cases where we must override the information
attribute is the OID of a tuple in the pg_proc catalog. * stored in pg_type.
The pg_proc tuple contains the query string which defines *
this set - i.e., the query to run to get the set. * First: if this attribute is a set, what is really stored in the
So the atttypid (just assigned above) refers to the type returned * attribute is the OID of a tuple in the pg_proc catalog.
by this query, but the actual length of this attribute is the * The pg_proc tuple contains the query string which defines
length (size) of an OID. * this set - i.e., the query to run to get the set.
* So the atttypid (just assigned above) refers to the type returned
Why not just make the atttypid point to the OID type, instead * by this query, but the actual length of this attribute is the
of the type the query returns? Because the executor uses the atttypid * length (size) of an OID.
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 * (Why not just make the atttypid point to the OID type, instead
an OID. * of the type the query returns? Because the executor uses the atttypid
* to tell the front end what type will be returned (in BeginCommand),
Why not wait until the return type of the set is known (i.e., the * and in the end the type returned will be the result of the query, not
recursive call to the executor to execute the set has returned) * an OID.)
before telling the front end what the return type will be? Because *
the executor is a delicate thing, and making sure that the correct * (Why not wait until the return type of the set is known (i.e., the
order of front-end commands is maintained is messy, especially * recursive call to the executor to execute the set has returned)
considering that target lists may change as inherited attributes * before telling the front end what the return type will be? Because
are considered, etc. Ugh. * 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) if (attisset)
{ {
att->attlen = sizeof(Oid); att->attlen = sizeof(Oid);
att->attbyval = true; 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'; att->attstorage = 'p';
} }
else else
{ {
att->attlen = typeForm->typlen; att->attlen = typeForm->typlen;
att->attbyval = typeForm->typbyval; att->attbyval = typeForm->typbyval;
att->attalign = typeForm->typalign;
att->attstorage = typeForm->typstorage; att->attstorage = typeForm->typstorage;
} }
@ -494,6 +513,7 @@ TupleDescMakeSelfReference(TupleDesc desc,
att->atttypid = TypeShellMake(relname); att->atttypid = TypeShellMake(relname);
att->attlen = sizeof(Oid); att->attlen = sizeof(Oid);
att->attbyval = true; att->attbyval = true;
att->attalign = 'i';
att->attstorage = 'p'; att->attstorage = 'p';
att->attnelems = 0; att->attnelems = 0;
} }
@ -582,15 +602,13 @@ BuildDescForRelation(List *schema, char *relname)
* have a self reference, otherwise it's an error. * have a self reference, otherwise it's an error.
* ---------------- * ----------------
*/ */
if (!strcmp(typename, relname)) if (strcmp(typename, relname) == 0)
TupleDescMakeSelfReference(desc, attnum, relname); TupleDescMakeSelfReference(desc, attnum, relname);
else else
elog(ERROR, "DefineRelation: no such type %s", elog(ERROR, "DefineRelation: no such type %s",
typename); typename);
} }
desc->attrs[attnum - 1]->atttypmod = entry->typename->typmod;
/* This is for constraints */ /* This is for constraints */
if (entry->is_not_null) if (entry->is_not_null)
constr->has_not_null = true; constr->has_not_null = true;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * INTERFACE ROUTINES
@ -537,7 +537,7 @@ fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc,
( (
(tupleDesc)->attrs[(attnum) - 1]->attcacheoff >= 0 ? (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 + (char *) (tup)->t_data + (tup)->t_data->t_hoff +
(tupleDesc)->attrs[(attnum) - 1]->attcacheoff) (tupleDesc)->attrs[(attnum) - 1]->attcacheoff)
) )

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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. * user programs to use them for temporary object identifiers.
*/ */
Oid Oid
newoid() newoid(void)
{ {
Oid lastoid; Oid lastoid;
@ -232,57 +232,3 @@ newoid()
elog(ERROR, "newoid: GetNewObjectId returns invalid oid"); elog(ERROR, "newoid: GetNewObjectId returns invalid oid");
return lastoid; 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++;
}
}

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * INTERFACE ROUTINES
@ -583,12 +583,6 @@ AddNewAttributeTuples(Oid new_rel_oid,
if (hasindex) if (hasindex)
CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs); CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
/* ----------------
* initialize tuple descriptor.
* ----------------
*/
fillatt(tupdesc);
/* ---------------- /* ----------------
* first we add the user attributes.. * first we add the user attributes..
* ---------------- * ----------------

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 void CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null_print);
static Oid GetInputFunction(Oid type); static Oid GetInputFunction(Oid type);
static Oid GetTypeElement(Oid type); static Oid GetTypeElement(Oid type);
static bool IsTypeByVal(Oid type);
static void CopyReadNewline(FILE *fp, int *newline); static void CopyReadNewline(FILE *fp, int *newline);
static char *CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline, char *null_print); static char *CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline, char *null_print);
static void CopyAttributeOut(FILE *fp, char *string, char *delim); 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; Oid in_func_oid;
Datum *values; Datum *values;
char *nulls; char *nulls;
bool *byval;
bool isnull; bool isnull;
int done = 0; int done = 0;
char *string = NULL, char *string = NULL,
@ -653,13 +651,9 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
values = (Datum *) palloc(attr_count * sizeof(Datum)); values = (Datum *) palloc(attr_count * sizeof(Datum));
nulls = (char *) palloc(attr_count * sizeof(char)); nulls = (char *) palloc(attr_count * sizeof(char));
byval = (bool *) palloc(attr_count * sizeof(bool));
for (i = 0; i < attr_count; i++) for (i = 0; i < attr_count; i++)
{
nulls[i] = ' '; nulls[i] = ' ';
byval[i] = IsTypeByVal(attr[i]->atttypid);
}
lineno = 0; lineno = 0;
fe_eof = false; fe_eof = false;
@ -742,39 +736,14 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
for (i = 0; i < attr_count; i++) for (i = 0; i < attr_count; i++)
{ {
if (byval[i] && nulls[i] != 'n') if (nulls[i] == 'n')
{ continue;
ptr = (char *) att_align((long) ptr, attr[i]->attlen, attr[i]->attalign);
switch (attr[i]->attlen) values[i] = fetchatt(attr[i], ptr);
{
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); ptr = att_addlength(ptr, attr[i]->attlen, ptr);
} }
} }
} }
}
if (done) if (done)
continue; continue;
@ -832,7 +801,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
for (i = 0; i < attr_count; i++) for (i = 0; i < attr_count; i++)
{ {
if (!byval[i] && nulls[i] != 'n') if (!attr[i]->attbyval && nulls[i] != 'n')
{ {
if (!binary) if (!binary)
pfree((void *) values[i]); pfree((void *) values[i]);
@ -855,7 +824,6 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
pfree(values); pfree(values);
pfree(nulls); pfree(nulls);
pfree(byval);
if (!binary) if (!binary)
{ {
@ -902,22 +870,6 @@ GetTypeElement(Oid type)
return result; 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. * Reads input from fp until an end of line is seen.

View File

@ -15,7 +15,7 @@
* *
* *
* IDENTIFICATION * 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; return tupType;
} }
/* #ifdef NOT_USED
TupleDesc TupleDesc
ExecCopyTupType(TupleDesc td, int natts) ExecCopyTupType(TupleDesc td, int natts)
{ {
@ -852,30 +852,23 @@ ExecCopyTupType(TupleDesc td, int natts)
} }
return newTd; return newTd;
} }
*/ #endif
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* ExecTypeFromTL * 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 * Currently there are about 4 different places where we create
* TupleDescriptors. They should all be merged, or perhaps * TupleDescriptors. They should all be merged, or perhaps
* be rewritten to call BuildDesc(). * 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 TupleDesc
ExecTypeFromTL(List *targetList) ExecTypeFromTL(List *targetList)
{ {
List *tlcdr; List *tlitem;
TupleDesc typeInfo; TupleDesc typeInfo;
Resdom *resdom; Resdom *resdom;
Oid restype; Oid restype;
@ -897,14 +890,12 @@ ExecTypeFromTL(List *targetList)
typeInfo = CreateTemplateTupleDesc(len); typeInfo = CreateTemplateTupleDesc(len);
/* ---------------- /* ----------------
* notes: get resdom from (resdom expr) * scan list, generate type info for each entry
* get_typbyval comes from src/lib/l-lisp/lsyscache.c
* ---------------- * ----------------
*/ */
tlcdr = targetList; foreach(tlitem, targetList)
while (tlcdr != NIL)
{ {
TargetEntry *tle = lfirst(tlcdr); TargetEntry *tle = lfirst(tlitem);
if (tle->resdom != NULL) if (tle->resdom != NULL)
{ {
@ -920,7 +911,7 @@ ExecTypeFromTL(List *targetList)
0, 0,
false); false);
/* #ifdef NOT_USED
ExecSetTypeInfo(resdom->resno - 1, ExecSetTypeInfo(resdom->resno - 1,
typeInfo, typeInfo,
(Oid) restype, (Oid) restype,
@ -929,13 +920,14 @@ ExecTypeFromTL(List *targetList)
NameStr(*resdom->resname), NameStr(*resdom->resname),
get_typbyval(restype), get_typbyval(restype),
get_typalign(restype)); get_typalign(restype));
*/ #endif
} }
else else
{ {
/* XXX this branch looks fairly broken ... tgl 12/2000 */
Resdom *fjRes; Resdom *fjRes;
List *fjTlistP; List *fjTlistP;
List *fjList = lfirst(tlcdr); List *fjList = lfirst(tlitem);
#ifdef SETS_FIXED #ifdef SETS_FIXED
TargetEntry *tle; TargetEntry *tle;
@ -953,7 +945,7 @@ ExecTypeFromTL(List *targetList)
fjRes->restypmod, fjRes->restypmod,
0, 0,
false); false);
/* #ifdef NOT_USED
ExecSetTypeInfo(fjRes->resno - 1, ExecSetTypeInfo(fjRes->resno - 1,
typeInfo, typeInfo,
(Oid) restype, (Oid) restype,
@ -962,7 +954,7 @@ ExecTypeFromTL(List *targetList)
(char *) fjRes->resname, (char *) fjRes->resname,
get_typbyval(restype), get_typbyval(restype),
get_typalign(restype)); get_typalign(restype));
*/ #endif
foreach(fjTlistP, lnext(fjList)) foreach(fjTlistP, lnext(fjList))
{ {
@ -978,7 +970,7 @@ ExecTypeFromTL(List *targetList)
0, 0,
false); false);
/* #ifdef NOT_USED
ExecSetTypeInfo(fjRes->resno - 1, ExecSetTypeInfo(fjRes->resno - 1,
typeInfo, typeInfo,
(Oid) fjRes->restype, (Oid) fjRes->restype,
@ -987,11 +979,9 @@ ExecTypeFromTL(List *targetList)
(char *) fjRes->resname, (char *) fjRes->resname,
get_typbyval(fjRes->restype), get_typbyval(fjRes->restype),
get_typalign(fjRes->restype)); get_typalign(fjRes->restype));
*/ #endif
} }
} }
tlcdr = lnext(tlcdr);
} }
return typeInfo; return typeInfo;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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; List *targetList;
TupleDesc tupDesc; TupleDesc tupDesc;
int len;
targetList = node->targetlist; targetList = node->targetlist;
tupDesc = ExecTypeFromTL(targetList); tupDesc = ExecTypeFromTL(targetList);
len = ExecTargetListLength(targetList);
if (len > 0)
ExecAssignResultType(commonstate, tupDesc); ExecAssignResultType(commonstate, tupDesc);
else
ExecAssignResultType(commonstate, (TupleDesc) NULL);
} }
/* ---------------- /* ----------------
@ -582,8 +576,8 @@ ExecSetTypeInfo(int index,
} }
/* ---------------- /* ----------------
* ExecFreeTypeInfo frees the array of attrbutes * ExecFreeTypeInfo frees the array of attributes
* created by ExecMakeTypeInfo and returned by ExecTypeFromTL... * created by ExecMakeTypeInfo and returned by ExecTypeFromTL
* ---------------- * ----------------
*/ */
void void

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * 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, * this -- it has varno set to the correct range table entry,
* but has varattno == 0 to signal that the whole tuple is the * 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) if (rte->relname == NULL)
elog(ERROR, elog(ERROR,
@ -453,7 +455,11 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
toid = typenameTypeId(rte->relname); toid = typenameTypeId(rte->relname);
/* replace it in the arg list */ /* 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) else if (!attisset)
toid = exprType(arg); toid = exprType(arg);

View File

@ -8,15 +8,15 @@
* *
* *
* IDENTIFICATION * 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 <ctype.h>
#include "postgres.h" #include "access/tupmacs.h"
#include "catalog/catalog.h" #include "catalog/catalog.h"
#include "catalog/pg_type.h" #include "catalog/pg_type.h"
#include "utils/array.h" #include "utils/array.h"
@ -596,36 +596,11 @@ array_out(PG_FUNCTION_ARGS)
values = (char **) palloc(nitems * sizeof(char *)); values = (char **) palloc(nitems * sizeof(char *));
for (i = 0; i < nitems; i++) for (i = 0; i < nitems; i++)
{ {
if (typbyval) Datum itemvalue;
{
switch (typlen) itemvalue = fetch_att(p, typbyval, typlen);
{
case 1:
values[i] = DatumGetCString(FunctionCall3(&outputproc, values[i] = DatumGetCString(FunctionCall3(&outputproc,
CharGetDatum(*p), itemvalue,
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), ObjectIdGetDatum(typelem),
Int32GetDatum(-1))); Int32GetDatum(-1)));
if (typlen > 0) if (typlen > 0)
@ -636,8 +611,9 @@ array_out(PG_FUNCTION_ARGS)
/* /*
* For the pair of double quotes * For the pair of double quotes
*/ */
if (!typbyval)
overall_length += 2; overall_length += 2;
}
for (tmp = values[i]; *tmp; tmp++) for (tmp = values[i]; *tmp; tmp++)
{ {
overall_length += 1; overall_length += 1;
@ -1358,35 +1334,12 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType)
for (i = 0; i < nitems; i++) for (i = 0; i < nitems; i++)
{ {
/* Get source element */ /* Get source element */
if (inp_typbyval) elt = fetch_att(s, inp_typbyval, inp_typlen);
{
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;
}
s += inp_typlen;
}
else
{
elt = PointerGetDatum(s);
if (inp_typlen > 0) if (inp_typlen > 0)
s += inp_typlen; s += inp_typlen;
else else
s += INTALIGN(*(int32 *) s); s += INTALIGN(*(int32 *) s);
}
/* /*
* Apply the given function to source elt and extra args. * Apply the given function to source elt and extra args.
@ -1516,32 +1469,13 @@ deconstruct_array(ArrayType *array,
p = ARR_DATA_PTR(array); p = ARR_DATA_PTR(array);
for (i = 0; i < nelems; i++) for (i = 0; i < nelems; i++)
{ {
if (elmbyval) elems[i] = fetch_att(p, elmbyval, elmlen);
{
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;
}
p += elmlen;
}
else
{
elems[i] = PointerGetDatum(p);
if (elmlen > 0) if (elmlen > 0)
p += elmlen; p += elmlen;
else else
p += INTALIGN(VARSIZE(p)); p += INTALIGN(VARSIZE(p));
} }
} }
}
/*----------------------------------------------------------------------------- /*-----------------------------------------------------------------------------
@ -1616,22 +1550,7 @@ system_cache_lookup(Oid element_type,
static Datum static Datum
ArrayCast(char *value, bool byval, int len) ArrayCast(char *value, bool byval, int len)
{ {
if (! byval) return fetch_att(value, byval, len);
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 */
} }
/* /*
@ -1651,22 +1570,7 @@ ArrayCastAndSet(Datum src,
{ {
if (typbyval) if (typbyval)
{ {
switch (typlen) store_att_byval(dest, src, 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;
}
/* For by-val types, assume no alignment padding is needed */ /* For by-val types, assume no alignment padding is needed */
inc = typlen; inc = typlen;
} }

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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 * NOTES
* Eventually, the index information should go through here, too. * Eventually, the index information should go through here, too.
@ -15,6 +15,7 @@
*/ */
#include "postgres.h" #include "postgres.h"
#include "access/tupmacs.h"
#include "catalog/pg_operator.h" #include "catalog/pg_operator.h"
#include "catalog/pg_proc.h" #include "catalog/pg_proc.h"
#include "catalog/pg_type.h" #include "catalog/pg_type.h"
@ -807,28 +808,8 @@ get_typdefault(Oid typid)
if (typByVal) if (typByVal)
{ {
int8 i8;
int16 i16;
int32 i32 = 0;
if (dataSize == typLen) if (dataSize == typLen)
{ returnValue = fetch_att(VARDATA(typDefault), typByVal, 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);
}
else else
returnValue = PointerGetDatum(NULL); returnValue = PointerGetDatum(NULL);
} }

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * 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 * fastgetattr
* *
* This gets called many times, so we macro the cacheable and NULL * Fetch a user attribute's value as a Datum (might be either a
* lookups, and call noncachegetattr() for the rest. * 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 ? \ (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 + \ (char *) (tup)->t_data + (tup)->t_data->t_hoff + \
(tupleDesc)->attrs[(attnum)-1]->attcacheoff) \ (tupleDesc)->attrs[(attnum)-1]->attcacheoff) \
) \ ) \
@ -132,8 +138,7 @@ extern Datum nocachegetattr(HeapTuple tup, int attnum,
#else /* defined(DISABLE_COMPLEX_MACRO) */ #else /* defined(DISABLE_COMPLEX_MACRO) */
extern Datum extern Datum fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc,
fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc,
bool *isnull); bool *isnull);
#endif /* defined(DISABLE_COMPLEX_MACRO) */ #endif /* defined(DISABLE_COMPLEX_MACRO) */
@ -142,60 +147,39 @@ fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc,
/* ---------------- /* ----------------
* heap_getattr * heap_getattr
* *
* Find a particular field in a row represented as a heap tuple. * Extract an attribute of a heap tuple and return it as a Datum.
* We return a pointer into that heap tuple, which points to the * This works for either system or user attributes. The given attnum
* first byte of the value of the field in question. * is properly range-checked.
* *
* If the field in question has a NULL value, we return a null * If the field in question has a NULL value, we return a zero Datum
* pointer and return <*isnull> == true. Otherwise, we return * and set *isnull == true. Otherwise, we set *isnull == false.
* <*isnull> == false.
* *
* <tup> is the pointer to the heap tuple. <attnum> is the attribute * <tup> is the pointer to the heap tuple. <attnum> is the attribute
* number of the column (field) caller wants. <tupleDesc> is a * number of the column (field) caller wants. <tupleDesc> is a
* pointer to the structure describing the row and all its fields. * 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) \ #define heap_getattr(tup, attnum, tupleDesc, isnull) \
( \ ( \
AssertMacro((tup) != NULL && \ AssertMacro((tup) != NULL), \
(attnum) > FirstLowInvalidHeapAttributeNumber && \ ( \
(attnum) != 0), \ ((attnum) > 0) ? \
( \
((attnum) > (int) (tup)->t_data->t_natts) ? \ ((attnum) > (int) (tup)->t_data->t_natts) ? \
( \ ( \
((isnull) ? (*(isnull) = true) : (dummyret)NULL), \ ((isnull) ? (*(isnull) = true) : (dummyret)NULL), \
(Datum)NULL \ (Datum)NULL \
) \ ) \
: \ : \
( \
((attnum) > 0) ? \
( \
fastgetattr((tup), (attnum), (tupleDesc), (isnull)) \ fastgetattr((tup), (attnum), (tupleDesc), (isnull)) \
) \ ) \
: \ : \
( \ heap_getsysattr((tup), (attnum), (isnull)) \
((isnull) ? (*(isnull) = false) : (dummyret)NULL), \
((attnum) == SelfItemPointerAttributeNumber) ? \
( \
(Datum)((char *)&((tup)->t_self)) \
) \
: \
(((attnum) == TableOidAttributeNumber) ? \
( \
(Datum)((tup)->t_tableOid) \
) \
: \
( \
(Datum)*(unsigned int *) \
((char *)(tup)->t_data + heap_sysoffset[-(attnum)-1]) \
)) \
) \
) \ ) \
) )
extern Datum heap_getsysattr(HeapTuple tup, int attnum, bool *isnull);
extern HeapAccessStatistics heap_access_stats; /* in stats.c */ 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, Datum *value, char *nulls, uint16 *infomask,
bits8 *bit); bits8 *bit);
extern int heap_attisnull(HeapTuple tup, int attnum); 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, extern Datum nocachegetattr(HeapTuple tup, int attnum,
TupleDesc att, bool *isnull); TupleDesc att, bool *isnull);
extern HeapTuple heap_copytuple(HeapTuple tuple); extern HeapTuple heap_copytuple(HeapTuple tuple);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * 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) #define MaxAttrSize (10 * 1024 * 1024)
/*
* Attribute numbers for the system-defined attributes
*/
#define SelfItemPointerAttributeNumber (-1) #define SelfItemPointerAttributeNumber (-1)
#define ObjectIdAttributeNumber (-2) #define ObjectIdAttributeNumber (-2)
#define MinTransactionIdAttributeNumber (-3) #define MinTransactionIdAttributeNumber (-3)
@ -156,9 +159,6 @@ typedef struct xl_heap_update
#define TableOidAttributeNumber (-7) #define TableOidAttributeNumber (-7)
#define FirstLowInvalidHeapAttributeNumber (-8) #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: * This new HeapTuple for version >= 6.5 and this is why it was changed:
* *

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * 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 ? \ (tupleDesc)->attrs[(attnum)-1]->attcacheoff >= 0 ? \
( \ ( \
(Datum) fetchatt(&((tupleDesc)->attrs[(attnum)-1]), \ fetchatt((tupleDesc)->attrs[(attnum)-1], \
(char *) (tup) + \ (char *) (tup) + \
( \ ( \
IndexTupleHasMinHeader(tup) ? \ IndexTupleHasMinHeader(tup) ? \

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * 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)))) #define att_isnull(ATT, BITS) (!((BITS)[(ATT) >> 3] & (1 << ((ATT) & 0x07))))
/* /*
* given a Form_pg_attribute and a pointer into a tuple's data * Given a Form_pg_attribute and a pointer into a tuple's data area,
* area, return the correct value or pointer. * return the correct value or pointer.
* *
* We return a 4 byte (char *) value in all cases. If the attribute has * We return a Datum value in all cases. If the attribute has "byval" false,
* "byval" false or has variable length, we return the same pointer * we return the same pointer into the tuple data area that we're passed.
* into the tuple data area that we're passed. Otherwise, we return * Otherwise, we return the correct number of bytes fetched from the data
* the 1, 2, or 4 bytes pointed to by it, properly extended to 4 * area and extended to Datum form.
* bytes, depending on the length of the attribute.
* *
* note that T must already be properly LONGALIGN/SHORTALIGN'd for * On machines where Datum is 8 bytes, we support fetching 8-byte byval
* this to work correctly. * attributes; otherwise, only 1, 2, and 4-byte values are supported.
* *
* the double-cast is to stop gcc from (correctly) complaining about * Note that T must already be properly aligned for this to work correctly.
* 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.
*/ */
#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) ? \ (attlen) == (int) sizeof(Datum) ? \
*((Datum *)(T)) \
: \
( \ ( \
(char *) (long) *((int32 *)(T)) \ (attlen) == (int) sizeof(int32) ? \
Int32GetDatum(*((int32 *)(T))) \
: \
( \
(attlen) == (int) sizeof(int16) ? \
Int16GetDatum(*((int16 *)(T))) \
: \
( \
AssertMacro((attlen) == 1), \
CharGetDatum(*((char *)(T))) \
) \
) \
) \
) \ ) \
: \ : \
( \ PointerGetDatum((char *) (T)) \
(*(A))->attlen < (int) sizeof(int16) ? \
(char *) (long) *((char *)(T)) \
: \
(char *) (long) *((int16 *)(T))) \
) \
: \
(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. * and alignment requirement attalign. In practice we don't need the length.
* The attalign cases are tested in what is hopefully something like their * The attalign cases are tested in what is hopefully something like their
* frequency of occurrence. * 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) \ #define att_addlength(cur_offset, attlen, attval) \
( \ ( \
((attlen) != -1) ? \ ((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 #endif

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * 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 IsSystemRelationName(const char *relname);
extern bool IsSharedSystemRelationName(const char *relname); extern bool IsSharedSystemRelationName(const char *relname);
extern Oid newoid(void); extern Oid newoid(void);
extern void fillatt(TupleDesc att);
#endif /* CATALOG_H */ #endif /* CATALOG_H */

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * 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 * NOTES
* the genbki.sh script reads this file and generates .bki * 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 * typbyval determines whether internal Postgres routines pass a value
* of this type by value or by reference. Only char, short, and int- * of this type by value or by reference. typbyval had better be FALSE
* equivalent items can be passed by value, so if the type is not 1, * if the length is not 1, 2, or 4 (or 8 on 8-byte-Datum machines).
* 2, or 4 bytes long, Postgres does not have the option of passing by * Variable-length types are always passed by reference. Note that
* value and so typbyval had better be FALSE. Variable-length types * typbyval can be false even if the length would allow pass-by-value;
* are always passed by reference. Note that typbyval can be false * this is currently true for type float4, for example.
* even if the length would allow pass-by-value; this is currently
* true for type float4, for example.
*/ */
bool typbyval; bool typbyval;

View File

@ -8,7 +8,7 @@
* or in config.h afterwards. Of course, if you edit config.h, then your * or in config.h afterwards. Of course, if you edit config.h, then your
* changes will be overwritten the next time you run configure. * 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 #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 */ /* Define this as the appropriate snprintf format for 64-bit ints, if any */
#undef INT64_FORMAT #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 * 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). * each of the basic C data types (except char, which we assume has align 1).