]> granicus.if.org Git - postgresql/commitdiff
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).