Fix portability problems recently exposed by regression tests on Alphas.
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 27 Dec 2000 23:59:14 +0000 (23:59 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 27 Dec 2000 23:59:14 +0000 (23:59 +0000)
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.

23 files changed:
configure
configure.in
contrib/array/array_iterator.c
src/backend/access/common/heaptuple.c
src/backend/access/common/indextuple.c
src/backend/access/common/printtup.c
src/backend/access/common/tupdesc.c
src/backend/access/heap/heapam.c
src/backend/catalog/catalog.c
src/backend/catalog/heap.c
src/backend/commands/copy.c
src/backend/executor/execTuples.c
src/backend/executor/execUtils.c
src/backend/parser/parse_func.c
src/backend/utils/adt/arrayfuncs.c
src/backend/utils/cache/lsyscache.c
src/include/access/heapam.h
src/include/access/htup.h
src/include/access/itup.h
src/include/access/tupmacs.h
src/include/catalog/catalog.h
src/include/catalog/pg_type.h
src/include/config.h.in

index 1e1dc927c1211af079de12b2b6bb4d847f05bf7e..e15088ee54eb20d5c73a4241a7ad882f78208ddd 100755 (executable)
--- a/configure
+++ b/configure
@@ -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
index 7fea78f864579f18ef997b34d0b2bb4a4c0df584..d721801ceea7afa1812d475cfa479354695e0151 100644 (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)
index 653979ada866b0a5cf3eb506225e4f8ffcd3ad3e..3622cf98195fbda9ed59613daedaa62fab5713b2 100644 (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)
index e76fa5a5652873125de876b9a4cc03da080ed6a3..6405320f85d952432c67ad439fc0587eeda1d786 100644 (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
 #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;
 
+   if (numberOfAttributes > MaxHeapAttributeNumber)
+       elog(ERROR, "heap_formtuple: numberOfAttributes of %d > %d",
+            numberOfAttributes, MaxHeapAttributeNumber);
+
    len = offsetof(HeapTupleHeaderData, t_bits);
 
-   for (i = 0; i < numberOfAttributes && !hasnull; i++)
+   for (i = 0; i < numberOfAttributes; i++)
    {
        if (nulls[i] != ' ')
+       {
            hasnull = true;
+           break;
+       }
    }
 
-   if (numberOfAttributes > MaxHeapAttributeNumber)
-       elog(ERROR, "heap_formtuple: numberOfAttributes of %d > %d",
-            numberOfAttributes, MaxHeapAttributeNumber);
-
    if (hasnull)
    {
        bitmaplen = BITMAPLEN(numberOfAttributes);
index 837b7f632bb39af5ecc841aba617923004d8c156..d473ce6c94d79d5126421f2577c843a0b685dd80 100644 (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);
    }
 }
 
index b05902068ee20b20f579dd87b83677303cdf9475..5b79cb84a4878a65463d244037f35921de24b854 100644 (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;
-
-               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;
-               }
+               Datum       datumBuf;
+
+               /*
+                * 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
index 8b9b7cd537fbaae833039e3107d4b7bcaf7b0741..83977d6a387ac12128044d8d46bef5aa4ac7f37e 100644 (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;
index 48c75f5d17fe1de8ea6205bc8a051f2030e497b1..8832d6ec9b56cc7cf459754433171801e98ca602 100644 (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)
               )
index aed3864e90023c640cd1f83d52c86f00280de0b8..a88a9ea931f96d4df17f4a451a2471934bf2a7f5 100644 (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++;
-   }
-}
index 174b8ca85bb9308778ae22105451b6d453d5df1c..abcc9951b4bf5397db2ea5d5bd37a4448c9c9fec 100644 (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..
     * ----------------
index 6cdba327295b5a251f762ef70c61bbd8e1951ded..f9507342d6d12216f60d23e203c4f0a6c86145db 100644 (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.
index 65eef4141f496cd679f783895a50ae3b06c60f7e..e27e91071f327ead2a85f965915759d4ea95aa43 100644 (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;
index 3b05a78e83add3975a7dbf2a5a70b4dd6873e00c..5d4d7f145b3264fbc62e662fb4c3c25e714d368d 100644 (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
index 9902b0cf92d3f201027e85da49f1e220a055619c..0e1b782fd97d65ec128198392b41e0d4621b29aa 100644 (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);
index 6379f041ad62b429681e9768eeb7b5274d735b66..23dc57ce8a54e9522f844646ea7fceaefdc1e34d 100644 (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;
-           }
+       Datum       itemvalue;
+
+       itemvalue = fetch_att(p, typbyval, typlen);
+       values[i] = DatumGetCString(FunctionCall3(&outputproc,
+                                                 itemvalue,
+                                                 ObjectIdGetDatum(typelem),
+                                                 Int32GetDatum(-1)));
+       if (typlen > 0)
            p += typlen;
-       }
        else
-       {
-           values[i] = DatumGetCString(FunctionCall3(&outputproc,
-                                               PointerGetDatum(p),
-                                               ObjectIdGetDatum(typelem),
-                                               Int32GetDatum(-1)));
-           if (typlen > 0)
-               p += typlen;
-           else
-               p += INTALIGN(*(int32 *) p);
+           p += INTALIGN(*(int32 *) p);
 
-           /*
-            * For the pair of double quotes
-            */
+       /*
+        * 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;
        }
index 24b2cbada95dfaa5ec66538f087b222654c89c11..905c9e1633b6b20fb7afc7726c611137e5c55766 100644 (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);
    }
index db40344dc4668cce1817f25c5c03d3b55a4a9c93..7618cc55ae5e661ebdbe1347b55511926deccca0 100644 (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);
index eebc1570f54efbef0fb505186cff7cc16dd47f07..56631043e3b532de9c5e67fe41ec313218bc8f72 100644 (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:
  *
index 18639eb7f209ff31ddac9562317f67e40797e2c5..f840ead4cb7158e35cc3fb241e2ec4db9dd0db68 100644 (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) ? \
index ab856087a70027e2e5283a77185995a15d96e006..eb977189e14908d23b310f5e925fc9e3c4b06e11 100644 (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 $
  *
  *-------------------------------------------------------------------------
  */
 #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) fetch_att(T, (A)->attbyval, (A)->attlen)
+
+/*
+ * Same, but work from byval/len parameters rather than Form_pg_attribute.
  */
-#define fetchatt(A, T) \
+#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)) \
+       : \
+     ( \
+       (attlen) == (int) sizeof(int32) ? \
+           Int32GetDatum(*((int32 *)(T))) \
+       : \
        ( \
-           (char *) (long) *((int32 *)(T)) \
+           (attlen) == (int) sizeof(int16) ? \
+               Int16GetDatum(*((int16 *)(T))) \
+           : \
+           ( \
+               AssertMacro((attlen) == 1), \
+               CharGetDatum(*((char *)(T))) \
+           ) \
        ) \
+     ) \
+   ) \
+   : \
+   PointerGetDatum((char *) (T)) \
+)
+
+#else /* SIZEOF_DATUM != 8 */
+
+#define fetch_att(T,attbyval,attlen) \
+( \
+   (attbyval) ? \
+   ( \
+       (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
+#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.
        ))) \
 )
 
+/*
+ * 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) ? \
    ) \
 )
 
+/*
+ * 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
index b1d51d520de8bb180377abfe15b90a71ce519364..4ebe9499ad89490a14a7e7ad3c6e2e3ac232b1a5 100644 (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 */
index f9f7372fd7800aabfd09ce1372d0917af244d1f5..d5e0c58dd19339a54d0232fcbb62e9387e4bc46d 100644 (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;
 
index 77a61e641065e5c357d54fbb0633bf6b9c8dce96..8be472c3fec19a7c0c8274dfacc38c480175af24 100644 (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).