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 "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

View File

@ -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)

View File

@ -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)

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;

View File

@ -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)
)

View File

@ -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++;
}
}

View File

@ -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..
* ----------------

View File

@ -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.

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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:
*

View File

@ -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) ? \

View File

@ -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

View File

@ -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 */

View File

@ -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;

View File

@ -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).