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

Postgres95 1.01 Distribution - Virgin Sources

This commit is contained in:
Marc G. Fournier
1996-07-09 06:22:35 +00:00
commit d31084e9d1
868 changed files with 242656 additions and 0 deletions

View File

@@ -0,0 +1,16 @@
#-------------------------------------------------------------------------
#
# Makefile.inc--
# Makefile for access/common
#
# Copyright (c) 1994, Regents of the University of California
#
#
# IDENTIFICATION
# $Header: /cvsroot/pgsql/src/backend/access/common/Attic/Makefile.inc,v 1.1.1.1 1996/07/09 06:21:09 scrappy Exp $
#
#-------------------------------------------------------------------------
SUBSRCS+= heaptuple.c heapvalid.c indextuple.c indexvalid.c printtup.c \
scankey.c tupdesc.c

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,134 @@
/*-------------------------------------------------------------------------
*
* heapvalid.c--
* heap tuple qualification validity checking code
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/common/Attic/heapvalid.c,v 1.1.1.1 1996/07/09 06:21:09 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
#include "c.h"
#include "access/htup.h"
#include "access/skey.h"
#include "access/heapam.h"
#include "utils/tqual.h"
#include "access/valid.h" /* where the declarations go */
#include "access/xact.h"
#include "storage/buf.h"
#include "storage/bufmgr.h"
#include "storage/bufpage.h"
#include "storage/itemid.h"
#include "fmgr.h"
#include "utils/elog.h"
#include "utils/rel.h"
/* ----------------
* heap_keytest
*
* Test a heap tuple with respect to a scan key.
* ----------------
*/
bool
heap_keytest(HeapTuple t,
TupleDesc tupdesc,
int nkeys,
ScanKey keys)
{
bool isnull;
Datum atp;
int test;
for (; nkeys--; keys++) {
atp = (Datum)heap_getattr(t, InvalidBuffer,
keys->sk_attno,
tupdesc,
&isnull);
if (isnull)
/* XXX eventually should check if SK_ISNULL */
return false;
if (keys->sk_flags & SK_COMMUTE)
test = (long) FMGR_PTR2(keys->sk_func, keys->sk_procedure,
keys->sk_argument, atp);
else
test = (long) FMGR_PTR2(keys->sk_func, keys->sk_procedure,
atp, keys->sk_argument);
if (!test == !(keys->sk_flags & SK_NEGATE))
return false;
}
return true;
}
/* ----------------
* heap_tuple_satisfies
*
* Returns a valid HeapTuple if it satisfies the timequal and keytest.
* Returns NULL otherwise. Used to be heap_satisifies (sic) which
* returned a boolean. It now returns a tuple so that we can avoid doing two
* PageGetItem's per tuple.
*
* Complete check of validity including LP_CTUP and keytest.
* This should perhaps be combined with valid somehow in the
* future. (Also, additional rule tests/time range tests.)
*
* on 8/21/92 mao says: i rearranged the tests here to do keytest before
* SatisfiesTimeQual. profiling indicated that even for vacuumed relations,
* time qual checking was more expensive than key testing. time qual is
* least likely to fail, too. we should really add the time qual test to
* the restriction and optimize it in the normal way. this has interactions
* with joey's expensive function work.
* ----------------
*/
HeapTuple
heap_tuple_satisfies(ItemId itemId,
Relation relation,
PageHeader disk_page,
TimeQual qual,
int nKeys,
ScanKey key)
{
HeapTuple tuple;
bool res;
if (! ItemIdIsUsed(itemId))
return NULL;
tuple = (HeapTuple) PageGetItem((Page) disk_page, itemId);
if (key != NULL)
res = heap_keytest(tuple, RelationGetTupleDescriptor(relation),
nKeys, key);
else
res = TRUE;
if (res && (relation->rd_rel->relkind == RELKIND_UNCATALOGED
|| HeapTupleSatisfiesTimeQual(tuple,qual)))
return tuple;
return (HeapTuple) NULL;
}
/*
* TupleUpdatedByCurXactAndCmd() -- Returns true if this tuple has
* already been updated once by the current transaction/command
* pair.
*/
bool
TupleUpdatedByCurXactAndCmd(HeapTuple t)
{
if (TransactionIdEquals(t->t_xmax,
GetCurrentTransactionId()) &&
t->t_cmax == GetCurrentCommandId())
return true;
return false;
}

View File

@@ -0,0 +1,427 @@
/*-------------------------------------------------------------------------
*
* indextuple.c--
* This file contains index tuple accessor and mutator routines,
* as well as a few various tuple utilities.
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/common/indextuple.c,v 1.1.1.1 1996/07/09 06:21:09 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
#include <string.h>
#include "c.h"
#include "access/ibit.h"
#include "access/itup.h" /* where the declarations go */
#include "access/heapam.h"
#include "access/genam.h"
#include "access/tupdesc.h"
#include "access/tupmacs.h"
#include "storage/itemptr.h"
#include "utils/elog.h"
#include "utils/palloc.h"
static Size IndexInfoFindDataOffset(unsigned short t_info);
/* ----------------------------------------------------------------
* index_ tuple interface routines
* ----------------------------------------------------------------
*/
/* ----------------
* index_formtuple
* ----------------
*/
IndexTuple
index_formtuple(TupleDesc tupleDescriptor,
Datum value[],
char null[])
{
register char *tp; /* tuple pointer */
IndexTuple tuple; /* return tuple */
Size size, hoff;
int i;
unsigned short infomask = 0;
bool hasnull = false;
char tupmask = 0;
int numberOfAttributes = tupleDescriptor->natts;
if (numberOfAttributes > MaxIndexAttributeNumber)
elog(WARN, "index_formtuple: numberOfAttributes of %d > %d",
numberOfAttributes, MaxIndexAttributeNumber);
for (i = 0; i < numberOfAttributes && !hasnull; i++) {
if (null[i] != ' ') hasnull = true;
}
if (hasnull) infomask |= INDEX_NULL_MASK;
hoff = IndexInfoFindDataOffset(infomask);
size = hoff
+ ComputeDataSize(tupleDescriptor,
value, null);
size = DOUBLEALIGN(size); /* be conservative */
tp = (char *) palloc(size);
tuple = (IndexTuple) tp;
memset(tp,0,(int)size);
DataFill((char *)tp + hoff,
tupleDescriptor,
value,
null,
&tupmask,
(hasnull ? (bits8*)tp + sizeof(*tuple) : NULL));
/*
* We do this because DataFill wants to initialize a "tupmask" which
* is used for HeapTuples, but we want an indextuple infomask. The only
* "relevent" info is the "has variable attributes" field, which is in
* mask position 0x02. We have already set the null mask above.
*/
if (tupmask & 0x02) infomask |= INDEX_VAR_MASK;
/*
* Here we make sure that we can actually hold the size. We also want
* to make sure that size is not aligned oddly. This actually is a
* rather odd way to make sure the size is not too large overall.
*/
if (size & 0xE000)
elog(WARN, "index_formtuple: data takes %d bytes: too big", size);
infomask |= size;
/* ----------------
* initialize metadata
* ----------------
*/
tuple->t_info = infomask;
return (tuple);
}
/* ----------------
* fastgetiattr
*
* This is a newer version of fastgetiattr which attempts to be
* faster by caching attribute offsets in the attribute descriptor.
*
* an alternate way to speed things up would be to cache offsets
* with the tuple, but that seems more difficult unless you take
* the storage hit of actually putting those offsets into the
* tuple you send to disk. Yuck.
*
* This scheme will be slightly slower than that, but should
* preform well for queries which hit large #'s of tuples. After
* you cache the offsets once, examining all the other tuples using
* the same attribute descriptor will go much quicker. -cim 5/4/91
* ----------------
*/
char *
fastgetiattr(IndexTuple tup,
int attnum,
TupleDesc tupleDesc,
bool *isnull)
{
register char *tp; /* ptr to att in tuple */
register char *bp; /* ptr to att in tuple */
int slow; /* do we have to walk nulls? */
register int data_off; /* tuple data offset */
/* ----------------
* sanity checks
* ----------------
*/
Assert(PointerIsValid(isnull));
Assert(attnum > 0);
/* ----------------
* Three cases:
*
* 1: No nulls and no variable length attributes.
* 2: Has a null or a varlena AFTER att.
* 3: Has nulls or varlenas BEFORE att.
* ----------------
*/
*isnull = false;
data_off = IndexTupleHasMinHeader(tup) ? sizeof *tup :
IndexInfoFindDataOffset(tup->t_info);
if (IndexTupleNoNulls(tup)) {
/* first attribute is always at position zero */
if (attnum == 1) {
return(fetchatt(&(tupleDesc->attrs[0]), (char *) tup + data_off));
}
attnum--;
if (tupleDesc->attrs[attnum]->attcacheoff > 0) {
return(fetchatt(&(tupleDesc->attrs[attnum]),
(char *) tup + data_off +
tupleDesc->attrs[attnum]->attcacheoff));
}
tp = (char *) tup + data_off;
slow = 0;
}else { /* there's a null somewhere in the tuple */
bp = (char *) tup + sizeof(*tup); /* "knows" t_bits are here! */
slow = 0;
/* ----------------
* check to see if desired att is null
* ----------------
*/
attnum--;
{
if (att_isnull(attnum, bp)) {
*isnull = true;
return NULL;
}
}
/* ----------------
* Now check to see if any preceeding bits are null...
* ----------------
*/
{
register int i = 0; /* current offset in bp */
register int mask; /* bit in byte we're looking at */
register char n; /* current byte in bp */
register int byte, finalbit;
byte = attnum >> 3;
finalbit = attnum & 0x07;
for (; i <= byte; i++) {
n = bp[i];
if (i < byte) {
/* check for nulls in any "earlier" bytes */
if ((~n) != 0) {
slow++;
break;
}
} else {
/* check for nulls "before" final bit of last byte*/
mask = (finalbit << 1) - 1;
if ((~n) & mask)
slow++;
}
}
}
tp = (char *) tup + data_off;
}
/* now check for any non-fixed length attrs before our attribute */
if (!slow) {
if (tupleDesc->attrs[attnum]->attcacheoff > 0) {
return(fetchatt(&(tupleDesc->attrs[attnum]),
tp + tupleDesc->attrs[attnum]->attcacheoff));
}else if (!IndexTupleAllFixed(tup)) {
register int j = 0;
for (j = 0; j < attnum && !slow; j++)
if (tupleDesc->attrs[j]->attlen < 1) slow = 1;
}
}
/*
* if slow is zero, and we got here, we know that we have a tuple with
* no nulls. We also know that we have to initialize the remainder of
* the attribute cached offset values.
*/
if (!slow) {
register int j = 1;
register long off;
/*
* need to set cache for some atts
*/
tupleDesc->attrs[0]->attcacheoff = 0;
while (tupleDesc->attrs[j]->attcacheoff > 0) j++;
off = tupleDesc->attrs[j-1]->attcacheoff +
tupleDesc->attrs[j-1]->attlen;
for (; j < attnum + 1; j++) {
/*
* Fix me when going to a machine with more than a four-byte
* word!
*/
switch(tupleDesc->attrs[j]->attlen)
{
case -1:
off = (tupleDesc->attrs[j]->attalign=='d')?
DOUBLEALIGN(off):INTALIGN(off);
break;
case sizeof(char):
break;
case sizeof(short):
off = SHORTALIGN(off);
break;
case sizeof(int32):
off = INTALIGN(off);
break;
default:
if (tupleDesc->attrs[j]->attlen > sizeof(int32))
off = (tupleDesc->attrs[j]->attalign=='d')?
DOUBLEALIGN(off) : LONGALIGN(off);
else
elog(WARN, "fastgetiattr: attribute %d has len %d",
j, tupleDesc->attrs[j]->attlen);
break;
}
tupleDesc->attrs[j]->attcacheoff = off;
off += tupleDesc->attrs[j]->attlen;
}
return(fetchatt( &(tupleDesc->attrs[attnum]),
tp + tupleDesc->attrs[attnum]->attcacheoff));
}else {
register bool usecache = true;
register int off = 0;
register int i;
/*
* Now we know that we have to walk the tuple CAREFULLY.
*/
for (i = 0; i < attnum; i++) {
if (!IndexTupleNoNulls(tup)) {
if (att_isnull(i, bp)) {
usecache = false;
continue;
}
}
if (usecache && tupleDesc->attrs[i]->attcacheoff > 0) {
off = tupleDesc->attrs[i]->attcacheoff;
if (tupleDesc->attrs[i]->attlen == -1)
usecache = false;
else
continue;
}
if (usecache) tupleDesc->attrs[i]->attcacheoff = off;
switch(tupleDesc->attrs[i]->attlen)
{
case sizeof(char):
off++;
break;
case sizeof(short):
off = SHORTALIGN(off) + sizeof(short);
break;
case -1:
usecache = false;
off = (tupleDesc->attrs[i]->attalign=='d')?
DOUBLEALIGN(off):INTALIGN(off);
off += VARSIZE(tp + off);
break;
default:
if (tupleDesc->attrs[i]->attlen > sizeof(int32))
off = (tupleDesc->attrs[i]->attalign=='d') ?
DOUBLEALIGN(off) + tupleDesc->attrs[i]->attlen :
LONGALIGN(off) + tupleDesc->attrs[i]->attlen;
else
elog(WARN, "fastgetiattr2: attribute %d has len %d",
i, tupleDesc->attrs[i]->attlen);
break;
}
}
return(fetchatt(&tupleDesc->attrs[attnum], tp + off));
}
}
/* ----------------
* index_getattr
* ----------------
*/
Datum
index_getattr(IndexTuple tuple,
AttrNumber attNum,
TupleDesc tupDesc,
bool *isNullOutP)
{
Assert (attNum > 0);
return (Datum)
fastgetiattr(tuple, attNum, tupDesc, isNullOutP);
}
RetrieveIndexResult
FormRetrieveIndexResult(ItemPointer indexItemPointer,
ItemPointer heapItemPointer)
{
RetrieveIndexResult result;
Assert(ItemPointerIsValid(indexItemPointer));
Assert(ItemPointerIsValid(heapItemPointer));
result = (RetrieveIndexResult) palloc(sizeof *result);
result->index_iptr = *indexItemPointer;
result->heap_iptr = *heapItemPointer;
return (result);
}
/*
* Takes an infomask as argument (primarily because this needs to be usable
* at index_formtuple time so enough space is allocated).
*
* Change me if adding an attribute to IndexTuples!!!!!!!!!!!
*/
static Size
IndexInfoFindDataOffset(unsigned short t_info)
{
if (!(t_info & INDEX_NULL_MASK))
return((Size) sizeof(IndexTupleData));
else {
Size size = sizeof(IndexTupleData);
if (t_info & INDEX_NULL_MASK) {
size += sizeof(IndexAttributeBitMapData);
}
return DOUBLEALIGN(size); /* be conservative */
}
}
/*
* Copies source into target. If *target == NULL, we palloc space; otherwise
* we assume we have space that is already palloc'ed.
*/
void
CopyIndexTuple(IndexTuple source, IndexTuple *target)
{
Size size;
IndexTuple ret;
size = IndexTupleSize(source);
if (*target == NULL) {
*target = (IndexTuple) palloc(size);
}
ret = *target;
memmove((char*)ret, (char*)source, size);
}

View File

@@ -0,0 +1,84 @@
/*-------------------------------------------------------------------------
*
* indexvalid.c--
* index tuple qualification validity checking code
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/common/Attic/indexvalid.c,v 1.1.1.1 1996/07/09 06:21:09 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "executor/execdebug.h"
#include "access/genam.h"
#include "access/iqual.h" /* where the declarations go */
#include "access/itup.h"
#include "access/skey.h"
#include "storage/buf.h"
#include "storage/bufpage.h"
#include "storage/itemid.h"
#include "utils/rel.h"
/* ----------------------------------------------------------------
* index scan key qualification code
* ----------------------------------------------------------------
*/
int NIndexTupleProcessed;
/* ----------------
* index_keytest
*
* old comments
* May eventually combine with other tests (like timeranges)?
* Should have Buffer buffer; as an argument and pass it to amgetattr.
* ----------------
*/
bool
index_keytest(IndexTuple tuple,
TupleDesc tupdesc,
int scanKeySize,
ScanKey key)
{
bool isNull;
Datum datum;
int test;
IncrIndexProcessed();
while (scanKeySize > 0) {
datum = index_getattr(tuple,
1,
tupdesc,
&isNull);
if (isNull) {
/* XXX eventually should check if SK_ISNULL */
return (false);
}
if (key[0].sk_flags & SK_COMMUTE) {
test = (int) (*(key[0].sk_func))
(DatumGetPointer(key[0].sk_argument),
datum);
} else {
test = (int) (*(key[0].sk_func))
(datum,
DatumGetPointer(key[0].sk_argument));
}
if (!test == !(key[0].sk_flags & SK_NEGATE)) {
return (false);
}
scanKeySize -= 1;
key++;
}
return (true);
}

View File

@@ -0,0 +1,306 @@
/*-------------------------------------------------------------------------
*
* printtup.c--
* Routines to print out tuples to the destination (binary or non-binary
* portals, frontend/interactive backend, etc.).
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.1.1.1 1996/07/09 06:21:10 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
#include <sys/file.h>
#include <stdio.h>
#include <string.h>
#include "postgres.h"
#include "access/heapam.h"
#include "access/htup.h"
#include "access/skey.h"
#include "access/printtup.h"
#include "access/tupdesc.h"
#include "storage/buf.h"
#include "utils/memutils.h"
#include "utils/palloc.h"
#include "fmgr.h"
#include "utils/elog.h"
#include "utils/syscache.h"
#include "catalog/pg_type.h"
#include "libpq/libpq.h"
/* ----------------------------------------------------------------
* printtup / debugtup support
* ----------------------------------------------------------------
*/
/* ----------------
* typtoout - used by printtup and debugtup
* ----------------
*/
Oid
typtoout(Oid type)
{
HeapTuple typeTuple;
typeTuple = SearchSysCacheTuple(TYPOID,
ObjectIdGetDatum(type),
0, 0, 0);
if (HeapTupleIsValid(typeTuple))
return((Oid)
((TypeTupleForm) GETSTRUCT(typeTuple))->typoutput);
elog(WARN, "typtoout: Cache lookup of type %d failed", type);
return(InvalidOid);
}
Oid
gettypelem(Oid type)
{
HeapTuple typeTuple;
typeTuple = SearchSysCacheTuple(TYPOID,
ObjectIdGetDatum(type),
0,0,0);
if (HeapTupleIsValid(typeTuple))
return((Oid)
((TypeTupleForm) GETSTRUCT(typeTuple))->typelem);
elog(WARN, "typtoout: Cache lookup of type %d failed", type);
return(InvalidOid);
}
/* ----------------
* printtup
* ----------------
*/
void
printtup(HeapTuple tuple, TupleDesc typeinfo)
{
int i, j, k;
char *outputstr, *attr;
bool isnull;
Oid typoutput;
/* ----------------
* tell the frontend to expect new tuple data
* ----------------
*/
pq_putnchar("D", 1);
/* ----------------
* send a bitmap of which attributes are null
* ----------------
*/
j = 0;
k = 1 << 7;
for (i = 0; i < tuple->t_natts; ) {
attr = heap_getattr(tuple, InvalidBuffer, ++i, typeinfo, &isnull);
if (!isnull)
j |= k;
k >>= 1;
if (!(i & 7)) {
pq_putint(j, 1);
j = 0;
k = 1 << 7;
}
}
if (i & 7)
pq_putint(j, 1);
/* ----------------
* send the attributes of this tuple
* ----------------
*/
for (i = 0; i < tuple->t_natts; ++i) {
attr = heap_getattr(tuple, InvalidBuffer, i+1, typeinfo, &isnull);
typoutput = typtoout((Oid) typeinfo->attrs[i]->atttypid);
if (!isnull && OidIsValid(typoutput)) {
outputstr = fmgr(typoutput, attr,
gettypelem(typeinfo->attrs[i]->atttypid));
pq_putint(strlen(outputstr)+4, 4);
pq_putnchar(outputstr, strlen(outputstr));
pfree(outputstr);
}
}
}
/* ----------------
* printatt
* ----------------
*/
static void
printatt(unsigned attributeId,
AttributeTupleForm attributeP,
char *value)
{
printf("\t%2d: %.*s%s%s%s\t(typeid = %u, len = %d, byval = %c)\n",
attributeId,
NAMEDATALEN, /* attname is a char16 */
attributeP->attname.data,
value != NULL ? " = \"" : "",
value != NULL ? value : "",
value != NULL ? "\"" : "",
(unsigned int) (attributeP->atttypid),
attributeP->attlen,
attributeP->attbyval ? 't' : 'f');
}
/* ----------------
* showatts
* ----------------
*/
void
showatts(char *name, TupleDesc tupleDesc)
{
int i;
int natts = tupleDesc->natts;
AttributeTupleForm *attinfo = tupleDesc->attrs;
puts(name);
for (i = 0; i < natts; ++i)
printatt((unsigned) i+1, attinfo[i], (char *) NULL);
printf("\t----\n");
}
/* ----------------
* debugtup
* ----------------
*/
void
debugtup(HeapTuple tuple, TupleDesc typeinfo)
{
register int i;
char *attr, *value;
bool isnull;
Oid typoutput;
for (i = 0; i < tuple->t_natts; ++i) {
attr = heap_getattr(tuple, InvalidBuffer, i+1, typeinfo, &isnull);
typoutput = typtoout((Oid) typeinfo->attrs[i]->atttypid);
if (!isnull && OidIsValid(typoutput)) {
value = fmgr(typoutput, attr,
gettypelem(typeinfo->attrs[i]->atttypid));
printatt((unsigned) i+1, typeinfo->attrs[i], value);
pfree(value);
}
}
printf("\t----\n");
}
/*#define IPORTAL_DEBUG*/
/* ----------------
* printtup_internal
* Protocol expects either T, D, C, E, or N.
* We use a different data prefix, e.g. 'B' instead of 'D' to
* indicate a tuple in internal (binary) form.
*
* This is same as printtup, except we don't use the typout func.
* ----------------
*/
void
printtup_internal(HeapTuple tuple, TupleDesc typeinfo)
{
int i, j, k;
char *attr;
bool isnull;
/* ----------------
* tell the frontend to expect new tuple data
* ----------------
*/
pq_putnchar("B", 1);
/* ----------------
* send a bitmap of which attributes are null
* ----------------
*/
j = 0;
k = 1 << 7;
for (i = 0; i < tuple->t_natts; ) {
attr = heap_getattr(tuple, InvalidBuffer, ++i, typeinfo, &isnull);
if (!isnull)
j |= k;
k >>= 1;
if (!(i & 7)) {
pq_putint(j, 1);
j = 0;
k = 1 << 7;
}
}
if (i & 7)
pq_putint(j, 1);
/* ----------------
* send the attributes of this tuple
* ----------------
*/
#ifdef IPORTAL_DEBUG
fprintf(stderr, "sending tuple with %d atts\n", tuple->t_natts);
#endif
for (i = 0; i < tuple->t_natts; ++i) {
int32 len = typeinfo->attrs[i]->attlen;
attr = heap_getattr(tuple, InvalidBuffer, i+1, typeinfo, &isnull);
if (!isnull) {
/* # of bytes, and opaque data */
if (len == -1) {
/* variable length, assume a varlena structure */
len = VARSIZE(attr) - VARHDRSZ;
pq_putint(len, sizeof(int32));
pq_putnchar(VARDATA(attr), len);
#ifdef IPORTAL_DEBUG
{
char *d = VARDATA(attr);
fprintf(stderr, "length %d data %x%x%x%x\n",
len, *d, *(d+1), *(d+2), *(d+3));
}
#endif
} else {
/* fixed size */
if (typeinfo->attrs[i]->attbyval) {
int8 i8;
int16 i16;
int32 i32;
pq_putint(len, sizeof(int32));
switch (len) {
case sizeof(int8):
i8 = DatumGetChar(attr);
pq_putnchar((char *) &i8, len);
break;
case sizeof(int16):
i16 = DatumGetInt16(attr);
pq_putnchar((char *) &i16, len);
break;
case sizeof(int32):
i32 = DatumGetInt32(attr);
pq_putnchar((char *) &i32, len);
break;
}
#ifdef IPORTAL_DEBUG
fprintf(stderr, "byval length %d data %d\n", len, attr);
#endif
} else {
pq_putint(len, sizeof(int32));
pq_putnchar(attr, len);
#ifdef IPORTAL_DEBUG
fprintf(stderr, "byref length %d data %x\n", len, attr);
#endif
}
}
}
}
}

View File

@@ -0,0 +1,68 @@
/*-------------------------------------------------------------------------
*
* scan.c--
* scan direction and key code
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/common/scankey.c,v 1.1.1.1 1996/07/09 06:21:10 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
#include "c.h"
#include "access/sdir.h"
#include "access/attnum.h"
#include "access/skey.h"
#include "fmgr.h"
/*
* ScanKeyEntryIsLegal --
* True iff the scan key entry is legal.
*/
#define ScanKeyEntryIsLegal(entry) \
((bool) (AssertMacro(PointerIsValid(entry)) && \
AttributeNumberIsValid(entry->sk_attno)))
/*
* ScanKeyEntrySetIllegal --
* Marks a scan key entry as illegal.
*/
void
ScanKeyEntrySetIllegal(ScanKey entry)
{
Assert(PointerIsValid(entry));
entry->sk_flags = 0; /* just in case... */
entry->sk_attno = InvalidAttrNumber;
entry->sk_procedure = 0; /* should be InvalidRegProcedure */
}
/*
* ScanKeyEntryInitialize --
* Initializes an scan key entry.
*
* Note:
* Assumes the scan key entry is valid.
* Assumes the intialized scan key entry will be legal.
*/
void
ScanKeyEntryInitialize(ScanKey entry,
bits16 flags,
AttrNumber attributeNumber,
RegProcedure procedure,
Datum argument)
{
Assert(PointerIsValid(entry));
entry->sk_flags = flags;
entry->sk_attno = attributeNumber;
entry->sk_procedure = procedure;
entry->sk_argument = argument;
fmgr_info(procedure, &entry->sk_func, &entry->sk_nargs);
Assert(ScanKeyEntryIsLegal(entry));
}

View File

@@ -0,0 +1,398 @@
/*-------------------------------------------------------------------------
*
* tupdesc.c--
* POSTGRES tuple descriptor support code
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.1.1.1 1996/07/09 06:21:10 scrappy Exp $
*
* NOTES
* some of the executor utility code such as "ExecTypeFromTL" should be
* moved here.
*
*-------------------------------------------------------------------------
*/
#include <stdio.h> /* for sprintf() */
#include <ctype.h>
#include <string.h>
#include "postgres.h"
#include "nodes/pg_list.h"
#include "nodes/parsenodes.h"
#include "access/attnum.h"
#include "access/htup.h"
#include "access/tupdesc.h"
#include "utils/builtins.h"
#include "utils/elog.h" /* XXX generate exceptions instead */
#include "utils/palloc.h"
#include "utils/syscache.h"
#include "catalog/pg_type.h"
#include "nodes/primnodes.h"
#include "parser/catalog_utils.h"
/* ----------------------------------------------------------------
* CreateTemplateTupleDesc
*
* This function allocates and zeros a tuple descriptor structure.
* ----------------------------------------------------------------
*/
TupleDesc
CreateTemplateTupleDesc(int natts)
{
uint32 size;
TupleDesc desc;
/* ----------------
* sanity checks
* ----------------
*/
AssertArg(natts >= 1);
/* ----------------
* allocate enough memory for the tuple descriptor and
* zero it as TupleDescInitEntry assumes that the descriptor
* is filled with NULL pointers.
* ----------------
*/
size = natts * sizeof (AttributeTupleForm);
desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
desc->attrs = (AttributeTupleForm*) palloc(size);
memset(desc->attrs, 0, size);
desc->natts = natts;
return (desc);
}
/* ----------------------------------------------------------------
* CreateTupleDesc
*
* This function allocates a new TupleDesc from AttributeTupleForm array
* ----------------------------------------------------------------
*/
TupleDesc
CreateTupleDesc(int natts, AttributeTupleForm* attrs)
{
TupleDesc desc;
/* ----------------
* sanity checks
* ----------------
*/
AssertArg(natts >= 1);
desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
desc->attrs = attrs;
desc->natts = natts;
return (desc);
}
/* ----------------------------------------------------------------
* CreateTupleDescCopy
*
* This function creates a new TupleDesc by copying from an existing
* TupleDesc
*
* ----------------------------------------------------------------
*/
TupleDesc
CreateTupleDescCopy(TupleDesc tupdesc)
{
TupleDesc desc;
int i, size;
desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
desc->natts = tupdesc->natts;
size = desc->natts * sizeof (AttributeTupleForm);
desc->attrs = (AttributeTupleForm*) palloc(size);
for (i=0;i<desc->natts;i++) {
desc->attrs[i] =
(AttributeTupleForm)palloc(ATTRIBUTE_TUPLE_SIZE);
memmove(desc->attrs[i],
tupdesc->attrs[i],
ATTRIBUTE_TUPLE_SIZE);
}
return desc;
}
/* ----------------------------------------------------------------
* TupleDescInitEntry
*
* This function initializes a single attribute structure in
* a preallocated tuple descriptor.
* ----------------------------------------------------------------
*/
bool
TupleDescInitEntry(TupleDesc desc,
AttrNumber attributeNumber,
char *attributeName,
char *typeName,
int attdim,
bool attisset)
{
HeapTuple tuple;
TypeTupleForm typeForm;
AttributeTupleForm att;
/* ----------------
* sanity checks
* ----------------
*/
AssertArg(PointerIsValid(desc));
AssertArg(attributeNumber >= 1);
/* attributeName's are sometimes NULL,
from resdom's. I don't know why that is, though -- Jolly */
/* AssertArg(NameIsValid(attributeName));*/
/* AssertArg(NameIsValid(typeName));*/
AssertArg(!PointerIsValid(desc->attrs[attributeNumber - 1]));
/* ----------------
* allocate storage for this attribute
* ----------------
*/
att = (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE);
desc->attrs[attributeNumber - 1] = att;
/* ----------------
* initialize some of the attribute fields
* ----------------
*/
att->attrelid = 0; /* dummy value */
if (attributeName != NULL)
namestrcpy(&(att->attname), attributeName);
else
memset(att->attname.data,0,NAMEDATALEN);
att->attdefrel = 0; /* dummy value */
att->attnvals = 0; /* dummy value */
att->atttyparg = 0; /* dummy value */
att->attbound = 0; /* dummy value */
att->attcanindex = 0; /* dummy value */
att->attproc = 0; /* dummy value */
att->attcacheoff = -1;
att->attnum = attributeNumber;
att->attnelems = attdim;
att->attisset = attisset;
/* ----------------
* search the system cache for the type tuple of the attribute
* we are creating so that we can get the typeid and some other
* stuff.
*
* Note: in the special case of
*
* create EMP (name = char16, manager = EMP)
*
* RelationNameCreateHeapRelation() calls BuildDesc() which
* calls this routine and since EMP does not exist yet, the
* system cache lookup below fails. That's fine, but rather
* then doing a elog(WARN) we just leave that information
* uninitialized, return false, then fix things up later.
* -cim 6/14/90
* ----------------
*/
tuple = SearchSysCacheTuple(TYPNAME, PointerGetDatum(typeName),
0,0,0);
if (! HeapTupleIsValid(tuple)) {
/* ----------------
* here type info does not exist yet so we just fill
* the attribute with dummy information and return false.
* ----------------
*/
att->atttypid = InvalidOid;
att->attlen = (int16) 0;
att->attbyval = (bool) 0;
att->attalign = 'i';
return false;
}
/* ----------------
* type info exists so we initialize our attribute
* information from the type tuple we found..
* ----------------
*/
typeForm = (TypeTupleForm) GETSTRUCT(tuple);
att->atttypid = tuple->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.
-----------------------------------------
*/
if (attisset) {
Type t = type("oid");
att->attlen = tlen(t);
att->attbyval = tbyval(t);
} else {
att->attlen = typeForm->typlen;
att->attbyval = typeForm->typbyval;
}
return true;
}
/* ----------------------------------------------------------------
* TupleDescMakeSelfReference
*
* This function initializes a "self-referential" attribute like
* manager in "create EMP (name=text, manager = EMP)".
* It calls TypeShellMake() which inserts a "shell" type
* tuple into pg_type. A self-reference is one kind of set, so
* its size and byval are the same as for a set. See the comments
* above in TupleDescInitEntry.
* ----------------------------------------------------------------
*/
static void
TupleDescMakeSelfReference(TupleDesc desc,
AttrNumber attnum,
char *relname)
{
AttributeTupleForm att;
Type t = type("oid");
att = desc->attrs[attnum-1];
att->atttypid = TypeShellMake(relname);
att->attlen = tlen(t);
att->attbyval = tbyval(t);
att->attnelems = 0;
}
/* ----------------------------------------------------------------
* BuildDescForRelation
*
* This is a general purpose function identical to BuildDesc
* but is used by the DefineRelation() code to catch the
* special case where you
*
* create FOO ( ..., x = FOO )
*
* here, the initial type lookup for "x = FOO" will fail
* because FOO isn't in the catalogs yet. But since we
* are creating FOO, instead of doing an elog() we add
* a shell type tuple to pg_type and fix things later
* in amcreate().
* ----------------------------------------------------------------
*/
TupleDesc
BuildDescForRelation(List *schema, char *relname)
{
int natts;
AttrNumber attnum;
List *p;
TupleDesc desc;
char *attname;
char *typename;
int attdim;
bool attisset;
/* ----------------
* allocate a new tuple descriptor
* ----------------
*/
natts = length(schema);
desc = CreateTemplateTupleDesc(natts);
attnum = 0;
typename = palloc(NAMEDATALEN+1);
foreach(p, schema) {
ColumnDef *entry;
List *arry;
/* ----------------
* for each entry in the list, get the name and type
* information from the list and have TupleDescInitEntry
* fill in the attribute information we need.
* ----------------
*/
attnum++;
entry = lfirst(p);
attname = entry->colname;
arry = entry->typename->arrayBounds;
attisset = entry->typename->setof;
if (arry != NIL) {
char buf[20];
attdim = length(arry);
/* array of XXX is _XXX (inherited from release 3) */
sprintf(buf, "_%.*s", NAMEDATALEN, entry->typename->name);
strcpy(typename, buf);
} else {
strcpy(typename, entry->typename->name);
attdim = 0;
}
if (! TupleDescInitEntry(desc, attnum, attname,
typename, attdim, attisset)) {
/* ----------------
* if TupleDescInitEntry() fails, it means there is
* no type in the system catalogs. So now we check if
* the type name equals the relation name. If so we
* have a self reference, otherwise it's an error.
* ----------------
*/
if (!strcmp(typename, relname)) {
TupleDescMakeSelfReference(desc, attnum, relname);
} else
elog(WARN, "DefineRelation: no such type %.*s",
NAMEDATALEN, typename);
}
/*
* this is for char() and varchar(). When an entry is of type
* char() or varchar(), typlen is set to the appropriate length,
* which we'll use here instead. (The catalog lookup only returns
* the length of bpchar and varchar which is not what we want!)
* - ay 6/95
*/
if (entry->typename->typlen > 0) {
desc->attrs[attnum - 1]->attlen = entry->typename->typlen;
}
}
return desc;
}