+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
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;
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
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
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;
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
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
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;
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
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
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;
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
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
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;
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
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>
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
# 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
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"
# 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"
# 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
# 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
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
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
# 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
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)
#include <sys/types.h>
#include <string.h>
+#include "access/tupmacs.h"
#include "access/xact.h"
#include "fmgr.h"
#include "miscadmin.h"
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)
*
* 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
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;
*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]);
}
}
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
*
/* 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
{
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))
{
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
{
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
*
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);
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
/* 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
}
{
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))
{
off += att[j]->attlen;
}
- return (Datum) fetchatt(&(att[attnum]), tp + att[attnum]->attcacheoff);
+ return fetchatt(att[attnum], tp + att[attnum]->attcacheoff);
}
else
{
off = att_align(off, att[attnum]->attlen, att[attnum]->attalign);
- return (Datum) fetchatt(&att[attnum], tp + off);
+ return fetchatt(att[attnum], tp + off);
}
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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
*
*
* 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
AssertArg(!PointerIsValid(desc->attrs[attributeNumber - 1]));
-
/* ----------------
* allocate storage for this attribute
* ----------------
desc->attrs[attributeNumber - 1] = att;
/* ----------------
- * initialize some of the attribute fields
+ * initialize the attribute fields
* ----------------
*/
att->attrelid = 0; /* dummy value */
else
MemSet(NameStr(att->attname), 0, NAMEDATALEN);
-
att->attdispersion = 0; /* dummy value */
att->attcacheoff = -1;
att->atttypmod = typmod;
att->atttypid = InvalidOid;
att->attlen = (int16) 0;
att->attbyval = (bool) 0;
- att->attstorage = 'p';
att->attalign = 'i';
+ att->attstorage = 'p';
return false;
}
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;
}
att->atttypid = TypeShellMake(relname);
att->attlen = sizeof(Oid);
att->attbyval = true;
+ att->attalign = 'i';
att->attstorage = 'p';
att->attnelems = 0;
}
* 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;
*
*
* 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
(
(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)
)
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* user programs to use them for temporary object identifiers.
*/
Oid
-newoid()
+newoid(void)
{
Oid lastoid;
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++;
- }
-}
*
*
* 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
if (hasindex)
CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
- /* ----------------
- * initialize tuple descriptor.
- * ----------------
- */
- fillatt(tupdesc);
-
/* ----------------
* first we add the user attributes..
* ----------------
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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);
Oid in_func_oid;
Datum *values;
char *nulls;
- bool *byval;
bool isnull;
int done = 0;
char *string = NULL,
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;
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);
}
}
}
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]);
pfree(values);
pfree(nulls);
- pfree(byval);
if (!binary)
{
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.
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
return tupType;
}
-/*
+#ifdef NOT_USED
TupleDesc
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;
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)
{
0,
false);
-/*
+#ifdef NOT_USED
ExecSetTypeInfo(resdom->resno - 1,
typeInfo,
(Oid) restype,
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;
fjRes->restypmod,
0,
false);
-/*
+#ifdef NOT_USED
ExecSetTypeInfo(fjRes->resno - 1,
typeInfo,
(Oid) restype,
(char *) fjRes->resname,
get_typbyval(restype),
get_typalign(restype));
-*/
+#endif
foreach(fjTlistP, lnext(fjList))
{
0,
false);
-/*
+#ifdef NOT_USED
ExecSetTypeInfo(fjRes->resno - 1,
typeInfo,
(Oid) fjRes->restype,
(char *) fjRes->resname,
get_typbyval(fjRes->restype),
get_typalign(fjRes->restype));
-*/
+#endif
}
}
-
- tlcdr = lnext(tlcdr);
}
return typeInfo;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
{
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);
}
/* ----------------
}
/* ----------------
- * 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
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
/*
* 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,
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);
*
*
* 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"
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;
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.
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));
}
}
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);
}
/*
{
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;
}
* 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.
*/
#include "postgres.h"
+#include "access/tupmacs.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
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);
}
* 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 $
*
*-------------------------------------------------------------------------
*/
/* ----------------
* 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.
* ----------------
*/
( \
(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) \
) \
#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) */
/* ----------------
* 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 */
/* ----------------
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);
* 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 $
*
*-------------------------------------------------------------------------
*/
#define MaxAttrSize (10 * 1024 * 1024)
+/*
+ * Attribute numbers for the system-defined attributes
+ */
#define SelfItemPointerAttributeNumber (-1)
#define ObjectIdAttributeNumber (-2)
#define MinTransactionIdAttributeNumber (-3)
#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:
*
* 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 $
*
*-------------------------------------------------------------------------
*/
( \
(tupleDesc)->attrs[(attnum)-1]->attcacheoff >= 0 ? \
( \
- (Datum) fetchatt(&((tupleDesc)->attrs[(attnum)-1]), \
+ fetchatt((tupleDesc)->attrs[(attnum)-1], \
(char *) (tup) + \
( \
IndexTupleHasMinHeader(tup) ? \
* 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
* 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 $
*
*-------------------------------------------------------------------------
*/
extern bool IsSystemRelationName(const char *relname);
extern bool IsSharedSystemRelationName(const char *relname);
+
extern Oid newoid(void);
-extern void fillatt(TupleDesc att);
#endif /* CATALOG_H */
* 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
/*
* 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;
* 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
/* 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).