1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-10 17:42:29 +03:00

Fix portability problems recently exposed by regression tests on Alphas.

1. Distinguish cases where a Datum representing a tuple datatype is an OID
from cases where it is a pointer to TupleTableSlot, and make sure we use
the right typlen in each case.
2. Make fetchatt() and related code support 8-byte by-value datatypes on
machines where Datum is 8 bytes.  Centralize knowledge of the available
by-value datatype sizes in two macros in tupmacs.h, so that this will be
easier if we ever have to do it again.
This commit is contained in:
Tom Lane
2000-12-27 23:59:14 +00:00
parent 97799fc475
commit 8609d4abf2
23 changed files with 497 additions and 660 deletions

View File

@@ -2,14 +2,14 @@
*
* heaptuple.c
* This file contains heap tuple accessor and mutator routines, as well
* as a few various tuple utilities.
* as various tuple utilities.
*
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.67 2000/11/30 18:38:45 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.68 2000/12/27 23:59:10 tgl Exp $
*
* NOTES
* The old interface functions have been converted to macros
@@ -23,16 +23,6 @@
#include "access/heapam.h"
#include "catalog/pg_type.h"
/* Used by heap_getattr() macro, for speed */
long heap_sysoffset[] = {
/* Only the first one is pass-by-ref, and is handled specially in the macro */
offsetof(HeapTupleHeaderData, t_ctid),
offsetof(HeapTupleHeaderData, t_oid),
offsetof(HeapTupleHeaderData, t_xmin),
offsetof(HeapTupleHeaderData, t_cmin),
offsetof(HeapTupleHeaderData, t_xmax),
offsetof(HeapTupleHeaderData, t_cmax)
};
/* ----------------------------------------------------------------
* misc support routines
@@ -48,12 +38,12 @@ ComputeDataSize(TupleDesc tupleDesc,
Datum *value,
char *nulls)
{
uint32 data_length;
uint32 data_length = 0;
int i;
int numberOfAttributes = tupleDesc->natts;
Form_pg_attribute *att = tupleDesc->attrs;
for (data_length = 0, i = 0; i < numberOfAttributes; i++)
for (i = 0; i < numberOfAttributes; i++)
{
if (nulls[i] != ' ')
continue;
@@ -114,38 +104,33 @@ DataFill(char *data,
*bitP |= bitmask;
}
/* XXX we are aligning the pointer itself, not the offset */
data = (char *) att_align((long) data, att[i]->attlen, att[i]->attalign);
switch (att[i]->attlen)
if (att[i]->attbyval)
{
case -1:
*infomask |= HEAP_HASVARLENA;
if (VARATT_IS_EXTERNAL(value[i]))
*infomask |= HEAP_HASEXTERNAL;
if (VARATT_IS_COMPRESSED(value[i]))
*infomask |= HEAP_HASCOMPRESSED;
data_length = VARATT_SIZE(DatumGetPointer(value[i]));
memmove(data, DatumGetPointer(value[i]), data_length);
break;
case sizeof(char):
*data = att[i]->attbyval ?
DatumGetChar(value[i]) : *((char *) value[i]);
break;
case sizeof(int16):
*(short *) data = (att[i]->attbyval ?
DatumGetInt16(value[i]) :
*((short *) value[i]));
break;
case sizeof(int32):
*(int32 *) data = (att[i]->attbyval ?
DatumGetInt32(value[i]) :
*((int32 *) value[i]));
break;
default:
Assert(att[i]->attlen >= 0);
memmove(data, DatumGetPointer(value[i]),
(size_t) (att[i]->attlen));
break;
/* pass-by-value */
store_att_byval(data, value[i], att[i]->attlen);
}
else if (att[i]->attlen == -1)
{
/* varlena */
*infomask |= HEAP_HASVARLENA;
if (VARATT_IS_EXTERNAL(value[i]))
*infomask |= HEAP_HASEXTERNAL;
if (VARATT_IS_COMPRESSED(value[i]))
*infomask |= HEAP_HASCOMPRESSED;
data_length = VARATT_SIZE(DatumGetPointer(value[i]));
memcpy(data, DatumGetPointer(value[i]), data_length);
}
else
{
/* fixed-length pass-by-reference */
Assert(att[i]->attlen >= 0);
memcpy(data, DatumGetPointer(value[i]),
(size_t) (att[i]->attlen));
}
data = (char *) att_addlength((long) data, att[i]->attlen, value[i]);
}
}
@@ -192,89 +177,6 @@ heap_attisnull(HeapTuple tup, int attnum)
return 0;
}
/* ----------------------------------------------------------------
* system attribute heap tuple support
* ----------------------------------------------------------------
*/
/* ----------------
* heap_sysattrlen
*
* This routine returns the length of a system attribute.
* ----------------
*/
int
heap_sysattrlen(AttrNumber attno)
{
HeapTupleHeader f = NULL;
switch (attno)
{
case TableOidAttributeNumber:
return sizeof f->t_oid;
case SelfItemPointerAttributeNumber:
return sizeof f->t_ctid;
case ObjectIdAttributeNumber:
return sizeof f->t_oid;
case MinTransactionIdAttributeNumber:
return sizeof f->t_xmin;
case MinCommandIdAttributeNumber:
return sizeof f->t_cmin;
case MaxTransactionIdAttributeNumber:
return sizeof f->t_xmax;
case MaxCommandIdAttributeNumber:
return sizeof f->t_cmax;
default:
elog(ERROR, "sysattrlen: System attribute number %d unknown.", attno);
return 0;
}
}
/* ----------------
* heap_sysattrbyval
*
* This routine returns the "by-value" property of a system attribute.
* ----------------
*/
bool
heap_sysattrbyval(AttrNumber attno)
{
bool byval;
switch (attno)
{
case TableOidAttributeNumber:
byval = true;
break;
case SelfItemPointerAttributeNumber:
byval = false;
break;
case ObjectIdAttributeNumber:
byval = true;
break;
case MinTransactionIdAttributeNumber:
byval = true;
break;
case MinCommandIdAttributeNumber:
byval = true;
break;
case MaxTransactionIdAttributeNumber:
byval = true;
break;
case MaxCommandIdAttributeNumber:
byval = true;
break;
default:
byval = true;
elog(ERROR, "sysattrbyval: System attribute number %d unknown.",
attno);
break;
}
return byval;
}
/* ----------------
* nocachegetattr
*
@@ -332,8 +234,7 @@ nocachegetattr(HeapTuple tuple,
/* This is handled in the macro */
if (att[attnum]->attcacheoff != -1)
{
return (Datum)
fetchatt(&(att[attnum]),
return fetchatt(att[attnum],
(char *) tup + tup->t_hoff + att[attnum]->attcacheoff);
}
#endif
@@ -397,8 +298,8 @@ nocachegetattr(HeapTuple tuple,
{
if (att[attnum]->attcacheoff != -1)
{
return (Datum) fetchatt(&(att[attnum]),
tp + att[attnum]->attcacheoff);
return fetchatt(att[attnum],
tp + att[attnum]->attcacheoff);
}
else if (!HeapTupleAllFixed(tuple))
{
@@ -460,7 +361,7 @@ nocachegetattr(HeapTuple tuple,
off = att_addlength(off, att[j]->attlen, tp + off);
}
return (Datum) fetchatt(&(att[attnum]), tp + att[attnum]->attcacheoff);
return fetchatt(att[attnum], tp + att[attnum]->attcacheoff);
}
else
{
@@ -508,10 +409,66 @@ nocachegetattr(HeapTuple tuple,
off = att_align(off, att[attnum]->attlen, att[attnum]->attalign);
return (Datum) fetchatt(&(att[attnum]), tp + off);
return fetchatt(att[attnum], tp + off);
}
}
/* ----------------
* heap_getsysattr
*
* Fetch the value of a system attribute for a tuple.
*
* This is a support routine for the heap_getattr macro. The macro
* has already determined that the attnum refers to a system attribute.
* ----------------
*/
Datum
heap_getsysattr(HeapTuple tup, int attnum, bool *isnull)
{
Datum result;
Assert(tup);
/* Currently, no sys attribute ever reads as NULL. */
if (isnull)
*isnull = false;
switch (attnum)
{
case SelfItemPointerAttributeNumber:
/* pass-by-reference datatype */
result = PointerGetDatum(&(tup->t_self));
break;
case ObjectIdAttributeNumber:
result = ObjectIdGetDatum(tup->t_data->t_oid);
break;
case MinTransactionIdAttributeNumber:
/* XXX should have a TransactionIdGetDatum macro */
result = (Datum) (tup->t_data->t_xmin);
break;
case MinCommandIdAttributeNumber:
/* XXX should have a CommandIdGetDatum macro */
result = (Datum) (tup->t_data->t_cmin);
break;
case MaxTransactionIdAttributeNumber:
/* XXX should have a TransactionIdGetDatum macro */
result = (Datum) (tup->t_data->t_xmax);
break;
case MaxCommandIdAttributeNumber:
/* XXX should have a CommandIdGetDatum macro */
result = (Datum) (tup->t_data->t_cmax);
break;
case TableOidAttributeNumber:
result = ObjectIdGetDatum(tup->t_tableOid);
break;
default:
elog(ERROR, "heap_getsysattr: invalid attnum %d", attnum);
result = 0; /* keep compiler quiet */
break;
}
return result;
}
/* ----------------
* heap_copytuple
*
@@ -630,18 +587,21 @@ heap_formtuple(TupleDesc tupleDescriptor,
int i;
int numberOfAttributes = tupleDescriptor->natts;
len = offsetof(HeapTupleHeaderData, t_bits);
for (i = 0; i < numberOfAttributes && !hasnull; i++)
{
if (nulls[i] != ' ')
hasnull = true;
}
if (numberOfAttributes > MaxHeapAttributeNumber)
elog(ERROR, "heap_formtuple: numberOfAttributes of %d > %d",
numberOfAttributes, MaxHeapAttributeNumber);
len = offsetof(HeapTupleHeaderData, t_bits);
for (i = 0; i < numberOfAttributes; i++)
{
if (nulls[i] != ' ')
{
hasnull = true;
break;
}
}
if (hasnull)
{
bitmaplen = BITMAPLEN(numberOfAttributes);

View File

@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/common/indextuple.c,v 1.48 2000/12/07 02:00:47 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/access/common/indextuple.c,v 1.49 2000/12/27 23:59:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -217,9 +217,9 @@ nocache_index_getattr(IndexTuple tup,
/* This is handled in the macro */
if (att[attnum]->attcacheoff != -1)
{
return (Datum) fetchatt(&(att[attnum]),
(char *) tup + data_off +
att[attnum]->attcacheoff);
return fetchatt(att[attnum],
(char *) tup + data_off +
att[attnum]->attcacheoff);
}
#endif
}
@@ -279,8 +279,8 @@ nocache_index_getattr(IndexTuple tup,
{
if (att[attnum]->attcacheoff != -1)
{
return (Datum) fetchatt(&(att[attnum]),
tp + att[attnum]->attcacheoff);
return fetchatt(att[attnum],
tp + att[attnum]->attcacheoff);
}
else if (!IndexTupleAllFixed(tup))
{
@@ -332,7 +332,7 @@ nocache_index_getattr(IndexTuple tup,
off += att[j]->attlen;
}
return (Datum) fetchatt(&(att[attnum]), tp + att[attnum]->attcacheoff);
return fetchatt(att[attnum], tp + att[attnum]->attcacheoff);
}
else
{
@@ -379,7 +379,7 @@ nocache_index_getattr(IndexTuple tup,
off = att_align(off, att[attnum]->attlen, att[attnum]->attalign);
return (Datum) fetchatt(&att[attnum], tp + off);
return fetchatt(att[attnum], tp + off);
}
}

View File

@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.55 2000/12/01 22:10:31 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.56 2000/12/27 23:59:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -436,30 +436,17 @@ printtup_internal(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
pq_sendint(&buf, len, sizeof(int32));
if (typeinfo->attrs[i]->attbyval)
{
int8 i8;
int16 i16;
int32 i32;
Datum datumBuf;
switch (len)
{
case sizeof(int8):
i8 = DatumGetChar(attr);
pq_sendbytes(&buf, (char *) &i8, len);
break;
case sizeof(int16):
i16 = DatumGetInt16(attr);
pq_sendbytes(&buf, (char *) &i16, len);
break;
case sizeof(int32):
i32 = DatumGetInt32(attr);
pq_sendbytes(&buf, (char *) &i32, len);
break;
default:
elog(ERROR, "printtup_internal: unexpected typlen");
break;
}
/*
* We need this horsing around because we don't know how
* shorter data values are aligned within a Datum.
*/
store_att_byval(&datumBuf, attr, len);
pq_sendbytes(&buf, (char *) &datumBuf, len);
#ifdef IPORTAL_DEBUG
fprintf(stderr, "byval length %d data %d\n", len, attr);
fprintf(stderr, "byval length %d data %ld\n", len,
(long) attr);
#endif
}
else

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.69 2000/11/16 22:30:15 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.70 2000/12/27 23:59:10 tgl Exp $
*
* NOTES
* some of the executor utility code such as "ExecTypeFromTL" should be
@@ -352,7 +352,6 @@ TupleDescInitEntry(TupleDesc desc,
AssertArg(!PointerIsValid(desc->attrs[attributeNumber - 1]));
/* ----------------
* allocate storage for this attribute
* ----------------
@@ -362,7 +361,7 @@ TupleDescInitEntry(TupleDesc desc,
desc->attrs[attributeNumber - 1] = att;
/* ----------------
* initialize some of the attribute fields
* initialize the attribute fields
* ----------------
*/
att->attrelid = 0; /* dummy value */
@@ -372,7 +371,6 @@ TupleDescInitEntry(TupleDesc desc,
else
MemSet(NameStr(att->attname), 0, NAMEDATALEN);
att->attdispersion = 0; /* dummy value */
att->attcacheoff = -1;
att->atttypmod = typmod;
@@ -414,8 +412,8 @@ TupleDescInitEntry(TupleDesc desc,
att->atttypid = InvalidOid;
att->attlen = (int16) 0;
att->attbyval = (bool) 0;
att->attstorage = 'p';
att->attalign = 'i';
att->attstorage = 'p';
return false;
}
@@ -427,42 +425,63 @@ TupleDescInitEntry(TupleDesc desc,
typeForm = (Form_pg_type) GETSTRUCT(tuple);
att->atttypid = tuple->t_data->t_oid;
att->attalign = typeForm->typalign;
/* ------------------------
If this attribute is a set, what is really stored in the
attribute is the OID of a tuple in the pg_proc catalog.
The pg_proc tuple contains the query string which defines
this set - i.e., the query to run to get the set.
So the atttypid (just assigned above) refers to the type returned
by this query, but the actual length of this attribute is the
length (size) of an OID.
Why not just make the atttypid point to the OID type, instead
of the type the query returns? Because the executor uses the atttypid
to tell the front end what type will be returned (in BeginCommand),
and in the end the type returned will be the result of the query, not
an OID.
Why not wait until the return type of the set is known (i.e., the
recursive call to the executor to execute the set has returned)
before telling the front end what the return type will be? Because
the executor is a delicate thing, and making sure that the correct
order of front-end commands is maintained is messy, especially
considering that target lists may change as inherited attributes
are considered, etc. Ugh.
-----------------------------------------
*/
/*------------------------
* There are a couple of cases where we must override the information
* stored in pg_type.
*
* First: if this attribute is a set, what is really stored in the
* attribute is the OID of a tuple in the pg_proc catalog.
* The pg_proc tuple contains the query string which defines
* this set - i.e., the query to run to get the set.
* So the atttypid (just assigned above) refers to the type returned
* by this query, but the actual length of this attribute is the
* length (size) of an OID.
*
* (Why not just make the atttypid point to the OID type, instead
* of the type the query returns? Because the executor uses the atttypid
* to tell the front end what type will be returned (in BeginCommand),
* and in the end the type returned will be the result of the query, not
* an OID.)
*
* (Why not wait until the return type of the set is known (i.e., the
* recursive call to the executor to execute the set has returned)
* before telling the front end what the return type will be? Because
* the executor is a delicate thing, and making sure that the correct
* order of front-end commands is maintained is messy, especially
* considering that target lists may change as inherited attributes
* are considered, etc. Ugh.)
*
* Second: if we are dealing with a complex type (a tuple type), then
* pg_type will say that the representation is the same as Oid. But
* if typmod is sizeof(Pointer) then the internal representation is
* actually a pointer to a TupleTableSlot, and we have to substitute
* that information.
*
* A set of complex type is first and foremost a set, so its
* representation is Oid not pointer. So, test that case first.
*-----------------------------------------
*/
if (attisset)
{
att->attlen = sizeof(Oid);
att->attbyval = true;
att->attalign = 'i';
att->attstorage = 'p';
}
else if (typeForm->typtype == 'c' && typmod == sizeof(Pointer))
{
att->attlen = sizeof(Pointer);
att->attbyval = true;
att->attalign = 'd'; /* kluge to work with 8-byte pointers */
/* XXX ought to have a separate attalign value for pointers ... */
att->attstorage = 'p';
}
else
{
att->attlen = typeForm->typlen;
att->attbyval = typeForm->typbyval;
att->attalign = typeForm->typalign;
att->attstorage = typeForm->typstorage;
}
@@ -494,6 +513,7 @@ TupleDescMakeSelfReference(TupleDesc desc,
att->atttypid = TypeShellMake(relname);
att->attlen = sizeof(Oid);
att->attbyval = true;
att->attalign = 'i';
att->attstorage = 'p';
att->attnelems = 0;
}
@@ -582,15 +602,13 @@ BuildDescForRelation(List *schema, char *relname)
* have a self reference, otherwise it's an error.
* ----------------
*/
if (!strcmp(typename, relname))
if (strcmp(typename, relname) == 0)
TupleDescMakeSelfReference(desc, attnum, relname);
else
elog(ERROR, "DefineRelation: no such type %s",
typename);
}
desc->attrs[attnum - 1]->atttypmod = entry->typename->typmod;
/* This is for constraints */
if (entry->is_not_null)
constr->has_not_null = true;

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.101 2000/12/11 09:14:03 inoue Exp $
* $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.102 2000/12/27 23:59:10 tgl Exp $
*
*
* INTERFACE ROUTINES
@@ -537,7 +537,7 @@ fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc,
(
(tupleDesc)->attrs[(attnum) - 1]->attcacheoff >= 0 ?
(
(Datum) fetchatt(&((tupleDesc)->attrs[(attnum) - 1]),
fetchatt((tupleDesc)->attrs[(attnum) - 1],
(char *) (tup)->t_data + (tup)->t_data->t_hoff +
(tupleDesc)->attrs[(attnum) - 1]->attcacheoff)
)

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/catalog.c,v 1.37 2000/11/16 22:30:17 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/catalog.c,v 1.38 2000/12/27 23:59:11 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -223,7 +223,7 @@ IsSharedSystemRelationName(const char *relname)
* user programs to use them for temporary object identifiers.
*/
Oid
newoid()
newoid(void)
{
Oid lastoid;
@@ -232,57 +232,3 @@ newoid()
elog(ERROR, "newoid: GetNewObjectId returns invalid oid");
return lastoid;
}
/*
* fillatt - fills the ATTRIBUTE relation fields from the TYP
*
* Expects that the atttypid domain is set for each att[].
* Returns with the attnum, and attlen domains set.
* attnum, attproc, atttyparg, ... should be set by the user.
*
* In the future, attnum may not be set?!? or may be passed as an arg?!?
*
* Current implementation is very inefficient--should cashe the
* information if this is at all possible.
*
* Check to see if this is really needed, and especially in the case
* of index tuples.
*/
void
fillatt(TupleDesc tupleDesc)
{
int natts = tupleDesc->natts;
Form_pg_attribute *att = tupleDesc->attrs;
Form_pg_attribute *attributeP;
int i;
if (natts < 0 || natts > MaxHeapAttributeNumber)
elog(ERROR, "fillatt: %d attributes is too large", natts);
if (natts == 0)
{
elog(DEBUG, "fillatt: called with natts == 0");
return;
}
attributeP = &att[0];
for (i = 1; i <= natts; i++)
{
(*attributeP)->attnum = (int16) i;
/*
* Check if the attr is a set before messing with the length
* and byval, since those were already set in
* TupleDescInitEntry. In fact, this seems redundant here,
* but who knows what I'll break if I take it out...
*/
if (!(*attributeP)->attisset)
{
get_typlenbyval((*attributeP)->atttypid,
& (*attributeP)->attlen,
& (*attributeP)->attbyval);
}
attributeP++;
}
}

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.154 2000/12/22 23:12:03 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.155 2000/12/27 23:59:11 tgl Exp $
*
*
* INTERFACE ROUTINES
@@ -583,12 +583,6 @@ AddNewAttributeTuples(Oid new_rel_oid,
if (hasindex)
CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
/* ----------------
* initialize tuple descriptor.
* ----------------
*/
fillatt(tupdesc);
/* ----------------
* first we add the user attributes..
* ----------------

View File

@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.125 2000/12/02 20:49:24 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.126 2000/12/27 23:59:14 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -49,7 +49,6 @@ static void CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim,
static void CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null_print);
static Oid GetInputFunction(Oid type);
static Oid GetTypeElement(Oid type);
static bool IsTypeByVal(Oid type);
static void CopyReadNewline(FILE *fp, int *newline);
static char *CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline, char *null_print);
static void CopyAttributeOut(FILE *fp, char *string, char *delim);
@@ -586,7 +585,6 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
Oid in_func_oid;
Datum *values;
char *nulls;
bool *byval;
bool isnull;
int done = 0;
char *string = NULL,
@@ -653,13 +651,9 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
values = (Datum *) palloc(attr_count * sizeof(Datum));
nulls = (char *) palloc(attr_count * sizeof(char));
byval = (bool *) palloc(attr_count * sizeof(bool));
for (i = 0; i < attr_count; i++)
{
nulls[i] = ' ';
byval[i] = IsTypeByVal(attr[i]->atttypid);
}
lineno = 0;
fe_eof = false;
@@ -742,36 +736,11 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
for (i = 0; i < attr_count; i++)
{
if (byval[i] && nulls[i] != 'n')
{
switch (attr[i]->attlen)
{
case sizeof(char):
values[i] = (Datum) *(unsigned char *) ptr;
ptr += sizeof(char);
break;
case sizeof(short):
ptr = (char *) SHORTALIGN(ptr);
values[i] = (Datum) *(unsigned short *) ptr;
ptr += sizeof(short);
break;
case sizeof(int32):
ptr = (char *) INTALIGN(ptr);
values[i] = (Datum) *(uint32 *) ptr;
ptr += sizeof(int32);
break;
default:
elog(ERROR, "COPY BINARY: impossible size");
break;
}
}
else if (nulls[i] != 'n')
{
ptr = (char *) att_align(ptr, attr[i]->attlen, attr[i]->attalign);
values[i] = (Datum) ptr;
ptr = att_addlength(ptr, attr[i]->attlen, ptr);
}
if (nulls[i] == 'n')
continue;
ptr = (char *) att_align((long) ptr, attr[i]->attlen, attr[i]->attalign);
values[i] = fetchatt(attr[i], ptr);
ptr = att_addlength(ptr, attr[i]->attlen, ptr);
}
}
}
@@ -832,7 +801,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
for (i = 0; i < attr_count; i++)
{
if (!byval[i] && nulls[i] != 'n')
if (!attr[i]->attbyval && nulls[i] != 'n')
{
if (!binary)
pfree((void *) values[i]);
@@ -855,7 +824,6 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
pfree(values);
pfree(nulls);
pfree(byval);
if (!binary)
{
@@ -902,22 +870,6 @@ GetTypeElement(Oid type)
return result;
}
static bool
IsTypeByVal(Oid type)
{
HeapTuple typeTuple;
bool result;
typeTuple = SearchSysCache(TYPEOID,
ObjectIdGetDatum(type),
0, 0, 0);
if (!HeapTupleIsValid(typeTuple))
elog(ERROR, "IsTypeByVal: Cache lookup of type %u failed", type);
result = ((Form_pg_type) GETSTRUCT(typeTuple))->typbyval;
ReleaseSysCache(typeTuple);
return result;
}
/*
* Reads input from fp until an end of line is seen.

View File

@@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.43 2000/11/12 00:36:57 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.44 2000/12/27 23:59:11 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -835,7 +835,7 @@ ExecGetTupType(Plan *node)
return tupType;
}
/*
#ifdef NOT_USED
TupleDesc
ExecCopyTupType(TupleDesc td, int natts)
{
@@ -852,30 +852,23 @@ ExecCopyTupType(TupleDesc td, int natts)
}
return newTd;
}
*/
#endif
/* ----------------------------------------------------------------
* ExecTypeFromTL
*
* Generate a tuple descriptor for the result tuple of a targetlist.
* Note that resjunk columns, if any, are included in the result.
*
* Currently there are about 4 different places where we create
* TupleDescriptors. They should all be merged, or perhaps
* be rewritten to call BuildDesc().
*
* old comments
* Forms attribute type info from the target list in the node.
* It assumes all domains are individually specified in the target list.
* It fails if the target list contains something like Emp.all
* which represents all the attributes from EMP relation.
*
* Conditions:
* The inner and outer subtrees should be initialized because it
* might be necessary to know the type infos of the subtrees.
* ----------------------------------------------------------------
*/
TupleDesc
ExecTypeFromTL(List *targetList)
{
List *tlcdr;
List *tlitem;
TupleDesc typeInfo;
Resdom *resdom;
Oid restype;
@@ -897,14 +890,12 @@ ExecTypeFromTL(List *targetList)
typeInfo = CreateTemplateTupleDesc(len);
/* ----------------
* notes: get resdom from (resdom expr)
* get_typbyval comes from src/lib/l-lisp/lsyscache.c
* scan list, generate type info for each entry
* ----------------
*/
tlcdr = targetList;
while (tlcdr != NIL)
foreach(tlitem, targetList)
{
TargetEntry *tle = lfirst(tlcdr);
TargetEntry *tle = lfirst(tlitem);
if (tle->resdom != NULL)
{
@@ -920,7 +911,7 @@ ExecTypeFromTL(List *targetList)
0,
false);
/*
#ifdef NOT_USED
ExecSetTypeInfo(resdom->resno - 1,
typeInfo,
(Oid) restype,
@@ -929,13 +920,14 @@ ExecTypeFromTL(List *targetList)
NameStr(*resdom->resname),
get_typbyval(restype),
get_typalign(restype));
*/
#endif
}
else
{
/* XXX this branch looks fairly broken ... tgl 12/2000 */
Resdom *fjRes;
List *fjTlistP;
List *fjList = lfirst(tlcdr);
List *fjList = lfirst(tlitem);
#ifdef SETS_FIXED
TargetEntry *tle;
@@ -953,7 +945,7 @@ ExecTypeFromTL(List *targetList)
fjRes->restypmod,
0,
false);
/*
#ifdef NOT_USED
ExecSetTypeInfo(fjRes->resno - 1,
typeInfo,
(Oid) restype,
@@ -962,7 +954,7 @@ ExecTypeFromTL(List *targetList)
(char *) fjRes->resname,
get_typbyval(restype),
get_typalign(restype));
*/
#endif
foreach(fjTlistP, lnext(fjList))
{
@@ -978,7 +970,7 @@ ExecTypeFromTL(List *targetList)
0,
false);
/*
#ifdef NOT_USED
ExecSetTypeInfo(fjRes->resno - 1,
typeInfo,
(Oid) fjRes->restype,
@@ -987,11 +979,9 @@ ExecTypeFromTL(List *targetList)
(char *) fjRes->resname,
get_typbyval(fjRes->restype),
get_typalign(fjRes->restype));
*/
#endif
}
}
tlcdr = lnext(tlcdr);
}
return typeInfo;

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.69 2000/11/16 22:30:20 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.70 2000/12/27 23:59:11 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -274,16 +274,10 @@ ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate)
{
List *targetList;
TupleDesc tupDesc;
int len;
targetList = node->targetlist;
tupDesc = ExecTypeFromTL(targetList);
len = ExecTargetListLength(targetList);
if (len > 0)
ExecAssignResultType(commonstate, tupDesc);
else
ExecAssignResultType(commonstate, (TupleDesc) NULL);
ExecAssignResultType(commonstate, tupDesc);
}
/* ----------------
@@ -582,8 +576,8 @@ ExecSetTypeInfo(int index,
}
/* ----------------
* ExecFreeTypeInfo frees the array of attrbutes
* created by ExecMakeTypeInfo and returned by ExecTypeFromTL...
* ExecFreeTypeInfo frees the array of attributes
* created by ExecMakeTypeInfo and returned by ExecTypeFromTL
* ----------------
*/
void

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.95 2000/12/15 19:22:03 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.96 2000/12/27 23:59:11 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -442,10 +442,12 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
/*
* for func(relname), the param to the function is the tuple
* under consideration. we build a special VarNode to reflect
* under consideration. We build a special VarNode to reflect
* this -- it has varno set to the correct range table entry,
* but has varattno == 0 to signal that the whole tuple is the
* argument.
* argument. Also, it has typmod set to sizeof(Pointer) to
* signal that the runtime representation will be a pointer
* not an Oid.
*/
if (rte->relname == NULL)
elog(ERROR,
@@ -453,7 +455,11 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
toid = typenameTypeId(rte->relname);
/* replace it in the arg list */
lfirst(i) = makeVar(vnum, 0, toid, -1, sublevels_up);
lfirst(i) = makeVar(vnum,
InvalidAttrNumber,
toid,
sizeof(Pointer),
sublevels_up);
}
else if (!attisset)
toid = exprType(arg);

View File

@@ -8,15 +8,15 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.67 2000/12/03 20:45:35 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.68 2000/12/27 23:59:12 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include <ctype.h>
#include "postgres.h"
#include "access/tupmacs.h"
#include "catalog/catalog.h"
#include "catalog/pg_type.h"
#include "utils/array.h"
@@ -596,48 +596,24 @@ array_out(PG_FUNCTION_ARGS)
values = (char **) palloc(nitems * sizeof(char *));
for (i = 0; i < nitems; i++)
{
if (typbyval)
{
switch (typlen)
{
case 1:
values[i] = DatumGetCString(FunctionCall3(&outputproc,
CharGetDatum(*p),
ObjectIdGetDatum(typelem),
Int32GetDatum(-1)));
break;
case 2:
values[i] = DatumGetCString(FunctionCall3(&outputproc,
Int16GetDatum(*(int16 *) p),
ObjectIdGetDatum(typelem),
Int32GetDatum(-1)));
break;
case 3:
case 4:
values[i] = DatumGetCString(FunctionCall3(&outputproc,
Int32GetDatum(*(int32 *) p),
ObjectIdGetDatum(typelem),
Int32GetDatum(-1)));
break;
}
p += typlen;
}
else
{
values[i] = DatumGetCString(FunctionCall3(&outputproc,
PointerGetDatum(p),
ObjectIdGetDatum(typelem),
Int32GetDatum(-1)));
if (typlen > 0)
p += typlen;
else
p += INTALIGN(*(int32 *) p);
Datum itemvalue;
/*
* For the pair of double quotes
*/
itemvalue = fetch_att(p, typbyval, typlen);
values[i] = DatumGetCString(FunctionCall3(&outputproc,
itemvalue,
ObjectIdGetDatum(typelem),
Int32GetDatum(-1)));
if (typlen > 0)
p += typlen;
else
p += INTALIGN(*(int32 *) p);
/*
* For the pair of double quotes
*/
if (!typbyval)
overall_length += 2;
}
for (tmp = values[i]; *tmp; tmp++)
{
overall_length += 1;
@@ -1358,35 +1334,12 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType)
for (i = 0; i < nitems; i++)
{
/* Get source element */
if (inp_typbyval)
{
switch (inp_typlen)
{
case 1:
elt = CharGetDatum(*s);
break;
case 2:
elt = Int16GetDatum(*(int16 *) s);
break;
case 4:
elt = Int32GetDatum(*(int32 *) s);
break;
default:
elog(ERROR, "array_map: unsupported byval length %d",
inp_typlen);
elt = 0; /* keep compiler quiet */
break;
}
elt = fetch_att(s, inp_typbyval, inp_typlen);
if (inp_typlen > 0)
s += inp_typlen;
}
else
{
elt = PointerGetDatum(s);
if (inp_typlen > 0)
s += inp_typlen;
else
s += INTALIGN(*(int32 *) s);
}
s += INTALIGN(*(int32 *) s);
/*
* Apply the given function to source elt and extra args.
@@ -1516,30 +1469,11 @@ deconstruct_array(ArrayType *array,
p = ARR_DATA_PTR(array);
for (i = 0; i < nelems; i++)
{
if (elmbyval)
{
switch (elmlen)
{
case 1:
elems[i] = CharGetDatum(*p);
break;
case 2:
elems[i] = Int16GetDatum(*(int16 *) p);
break;
case 4:
elems[i] = Int32GetDatum(*(int32 *) p);
break;
}
elems[i] = fetch_att(p, elmbyval, elmlen);
if (elmlen > 0)
p += elmlen;
}
else
{
elems[i] = PointerGetDatum(p);
if (elmlen > 0)
p += elmlen;
else
p += INTALIGN(VARSIZE(p));
}
p += INTALIGN(VARSIZE(p));
}
}
@@ -1616,22 +1550,7 @@ system_cache_lookup(Oid element_type,
static Datum
ArrayCast(char *value, bool byval, int len)
{
if (! byval)
return PointerGetDatum(value);
switch (len)
{
case 1:
return CharGetDatum(*value);
case 2:
return Int16GetDatum(*(int16 *) value);
case 4:
return Int32GetDatum(*(int32 *) value);
default:
elog(ERROR, "ArrayCast: unsupported byval length %d", len);
break;
}
return 0; /* keep compiler quiet */
return fetch_att(value, byval, len);
}
/*
@@ -1651,22 +1570,7 @@ ArrayCastAndSet(Datum src,
{
if (typbyval)
{
switch (typlen)
{
case 1:
*dest = DatumGetChar(src);
break;
case 2:
*(int16 *) dest = DatumGetInt16(src);
break;
case 4:
*(int32 *) dest = DatumGetInt32(src);
break;
default:
elog(ERROR, "ArrayCastAndSet: unsupported byval length %d",
typlen);
break;
}
store_att_byval(dest, src, typlen);
/* For by-val types, assume no alignment padding is needed */
inc = typlen;
}

View File

@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.48 2000/11/20 20:36:49 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.49 2000/12/27 23:59:12 tgl Exp $
*
* NOTES
* Eventually, the index information should go through here, too.
@@ -15,6 +15,7 @@
*/
#include "postgres.h"
#include "access/tupmacs.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
@@ -807,28 +808,8 @@ get_typdefault(Oid typid)
if (typByVal)
{
int8 i8;
int16 i16;
int32 i32 = 0;
if (dataSize == typLen)
{
switch (typLen)
{
case sizeof(int8):
memcpy((char *) &i8, VARDATA(typDefault), sizeof(int8));
i32 = i8;
break;
case sizeof(int16):
memcpy((char *) &i16, VARDATA(typDefault), sizeof(int16));
i32 = i16;
break;
case sizeof(int32):
memcpy((char *) &i32, VARDATA(typDefault), sizeof(int32));
break;
}
returnValue = Int32GetDatum(i32);
}
returnValue = fetch_att(VARDATA(typDefault), typByVal, typLen);
else
returnValue = PointerGetDatum(NULL);
}