head	1.12;
access;
symbols
	release_4_2:1.12
	aix_ok:1.10
	Version_2_1:1.5;
locks; strict;
comment	@ * @;


1.12
date	94.02.07.11.29.23;	author aoki;	state Exp;
branches;
next	1.11;

1.11
date	94.02.02.00.22.27;	author marc;	state Exp;
branches;
next	1.10;

1.10
date	93.07.19.03.48.22;	author aoki;	state Exp;
branches;
next	1.9;

1.9
date	93.02.05.02.04.49;	author aoki;	state Exp;
branches;
next	1.8;

1.8
date	93.01.16.03.14.59;	author aoki;	state Exp;
branches;
next	1.7;

1.7
date	92.03.06.22.17.36;	author clarsen;	state Exp;
branches;
next	1.6;

1.6
date	91.03.27.23.21.01;	author kemnitz;	state Exp;
branches;
next	1.5;

1.5
date	91.02.20.00.52.08;	author cimarron;	state Exp;
branches;
next	1.4;

1.4
date	91.02.11.17.21.01;	author cimarron;	state Exp;
branches;
next	1.3;

1.3
date	91.02.10.18.23.19;	author cimarron;	state Exp;
branches;
next	1.2;

1.2
date	91.02.06.18.03.00;	author cimarron;	state Exp;
branches;
next	1.1;

1.1
date	91.01.29.15.19.22;	author cimarron;	state Exp;
branches;
next	;


desc
@reorganization of access method code 1/28/91 -cim
@


1.12
log
@proto fixes
@
text
@/*----------------------------------------------------------------------------
 *   FILE
 *	printtup.c
 *
 *   DESCRIPTION
 *	Routines to print out tuples to the destination (binary or non-binary
 *	portals, frontend/interactive backend, etc.).
 *
 *   INTERFACE ROUTINES
 *	typtoout
 *	printtup
 *	showatts
 *	debugtup
 *	printtup_internal
 *
 *   NOTES
 *
 *   IDENTIFICATION
 *	$Header: /import/faerie/faerie/aoki/postgres/src/backend/access/common/RCS/printtup.c,v 1.11 1994/02/02 00:22:27 marc Exp aoki $
 *----------------------------------------------------------------------------
 */

#include <sys/file.h>
#include <stdio.h>
#include <strings.h>

#include "tmp/postgres.h"

RcsId("$Header: /import/faerie/faerie/aoki/postgres/src/backend/access/common/RCS/printtup.c,v 1.11 1994/02/02 00:22:27 marc Exp aoki $");

#include "access/heapam.h"
#include "access/htup.h"
#include "access/skey.h"
#include "storage/buf.h"
#include "utils/memutils.h"
#include "utils/palloc.h"
#include "fmgr.h"
#include "utils/log.h"

#include "catalog/syscache.h"
#include "catalog/pg_type.h"

#include "tmp/libpq.h"

/* ----------------------------------------------------------------
 *	printtup / debugtup support
 * ----------------------------------------------------------------
 */
/* ----------------
 *	typtoout - used by printtup and debugtup
 * ----------------
 */
ObjectId
typtoout(type)
    ObjectId	type;
{
    HeapTuple	typeTuple;

    typeTuple = SearchSysCacheTuple(TYPOID,
				    (char *) (long) type,
				    (char *) NULL,
				    (char *) NULL,
				    (char *) NULL);

    if (HeapTupleIsValid(typeTuple))
	return((ObjectId)
	       ((TypeTupleForm) GETSTRUCT(typeTuple))->typoutput);

    elog(WARN, "typtoout: Cache lookup of type %d failed", type);
    return(InvalidObjectId);
}

static
ObjectId
gettypelem(type)
    ObjectId	type;

{
    HeapTuple	typeTuple;

    typeTuple = SearchSysCacheTuple(TYPOID,
				    (char *) (long) type,
				    (char *) NULL,
				    (char *) NULL,
				    (char *) NULL);

    if (HeapTupleIsValid(typeTuple))
	return((ObjectId)
	       ((TypeTupleForm) GETSTRUCT(typeTuple))->typelem);

    elog(WARN, "typtoout: Cache lookup of type %d failed", type);
    return(InvalidObjectId);
}

/* ----------------
 *	printtup
 * ----------------
 */
void
printtup(tuple, typeinfo)
    HeapTuple		tuple;
    struct attribute 	*typeinfo[];
{
    int		i, j, k;
    char	*outputstr, *attr;
    Boolean	isnull;
    ObjectId	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((ObjectId) typeinfo[i]->atttypid);
	
	if (!isnull && ObjectIdIsValid(typoutput)) {
	    outputstr = fmgr(typoutput, attr, gettypelem(typeinfo[i]->atttypid));
	    pq_putint(strlen(outputstr)+4, 4);
	    pq_putnchar(outputstr, strlen(outputstr));
	    pfree(outputstr);
	}
    }
}

/* ----------------
 *	printatt
 * ----------------
 */
static
void
printatt(attributeId, attributeP, value)
    unsigned		attributeId;
    struct attribute	*attributeP;
    char			*value;
{
    printf("\t%2d: %.*s%s%s%s\t(typeid = %lu, len = %d, byval = %c)\n",
	   attributeId,
	   NAMEDATALEN,		/* attname is a char16 */
	   attributeP->attname,
	   value != NULL ? " = \"" : "",
	   value != NULL ? value : "",
	   value != NULL ? "\"" : "",
	   attributeP->atttypid,
	   attributeP->attlen,
	   attributeP->attbyval ? 't' : 'f');
}

/* ----------------
 *	showatts
 * ----------------
 */
showatts(name, natts, attinfo)
    char			*name;
    int			natts;
    struct attribute	*attinfo[];
{
    register int	i;
    
    puts(name);
    for (i = 0; i < natts; ++i)
	printatt((unsigned) i+1, attinfo[i], (char *) NULL);
    printf("\t----\n");
}

/* ----------------
 *	debugtup
 * ----------------
 */
void
debugtup(tuple, typeinfo)
    HeapTuple		tuple;
    struct attribute 	*typeinfo[];
{
    register int	i;
    char		*attr, *value;
    Boolean		isnull;
    ObjectId		typoutput;
    
    for (i = 0; i < tuple->t_natts; ++i) {
	attr = heap_getattr(tuple, InvalidBuffer, i+1, typeinfo, &isnull);
	typoutput = typtoout((ObjectId) typeinfo[i]->atttypid);
	
	if (!isnull && ObjectIdIsValid(typoutput)) {
	    value = fmgr(typoutput, attr, gettypelem(typeinfo[i]->atttypid));
	    printatt((unsigned) i+1, typeinfo[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(tuple, typeinfo)
    HeapTuple		tuple;
    struct attribute 	*typeinfo[];
{
    int		i, j, k;
    char	*outputstr, *attr;
    Boolean	isnull;
    ObjectId	typoutput;
    
    /* ----------------
     *	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[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[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
		}
	    }
	}
    }
}
@


1.11
log
@Fixes to make sure we don't expect NameData variables to be NULL terminated
and that we don't write mroe than NAMEDATALEN chars into them
@
text
@d19 1
a19 1
 *	$Header: /usr/local/devel/postgres.test/src/backend/access/common/RCS/printtup.c,v 1.10 1993/07/19 03:48:22 aoki Exp marc $
d29 1
a29 1
RcsId("$Header: /usr/local/devel/postgres.test/src/backend/access/common/RCS/printtup.c,v 1.10 1993/07/19 03:48:22 aoki Exp marc $");
d36 1
d43 2
d60 1
a60 1
				    (char *) type,
d82 1
a82 1
				    (char *) type,
@


1.10
log
@removed dead code
iportal code was sending too much stuff for varlenas
@
text
@d19 1
a19 1
 *	$Header$
d29 1
a29 1
RcsId("$Header: /faerie/hpux/postgres/src/backend/access/common/RCS/printtup.c,v 1.9 1993/02/05 02:04:49 aoki Exp aoki $");
d160 1
a160 1
    printf("\t%2d: %s%s%s%s\t(typeid = %lu, len = %d, byval = %c)\n",
d162 1
@


1.9
log
@printtup_internal assumed little-endian.  (did no one test binary
portals on a sun??)
@
text
@d1 20
a20 3
/*
 * printtup.c --
 *	Routines to print out tuples to the standard output.
d29 1
a29 1
RcsId("$Header: /home2/aoki/postgres/src/backend/access/common/RCS/printtup.c,v 1.8 1993/01/16 03:14:59 aoki Exp aoki $");
a41 26
/* ----------------
 *	convtypeinfo
 *
 *	Converts an old-style typeinfo (struct attribute array) into
 *	the new-style typeinfo (struct attribute (*) array).
 *
 *	XXX temporary, but still called by the executor.
 * ----------------
 */
struct attribute **
convtypeinfo(natts, att)
    int 		natts;
    struct attribute	*att;
{
    struct	attribute *ap, **rpp, **retatt;
    
    rpp = retatt = (struct attribute **) 
	palloc(natts * sizeof(*rpp) + natts * sizeof(**rpp));
    MemoryCopy(rpp + natts, att, natts * sizeof(**rpp));
    
    ap = (struct attribute *)(rpp + natts);
    while (--natts >= 0)
	*rpp++ = ap++;
    return(retatt);
}

d70 1
d153 1
d266 3
d277 1
a277 1
		len = VARSIZE(attr);
d298 1
a298 1
		    case 1:
d302 1
a302 1
		    case 2:
d306 1
a306 1
		    case 4:
@


1.8
log
@removed references to utils/fmgr.h and parser/parse.h
@
text
@d12 1
a12 1
RcsId("$Header: /home2/aoki/postgres/src/backend/access/common/RCS/printtup.c,v 1.7 1992/03/06 22:17:36 clarsen Exp aoki $");
d222 1
a241 3
#if 0
    FILE *f = fopen("/dev/ttyp0","w");
#endif
d274 1
a274 1
	int len;
a276 1
	len = typeinfo[i]->attlen;
d279 13
a291 11
	    switch (len) {
	      case -1: {
		  /* variable length, assume a varlena structure */
		  int l = VARSIZE(PointerGetDatum(attr));
		  pq_putint(l,4);
		  pq_putnchar(VARDATA(PointerGetDatum(attr)),l);
#if 0
		  {
		  char *d = VARDATA(PointerGetDatum(attr));
		  fprintf(f,"length %d data %x%x%x%x\n",l,*d,*(d+1),*(d+2),*(d+3));
		  }
d293 24
a316 9
	      }   
		break;

	      default:		/* fixed size */
	       if (typeinfo[i]->attbyval) {
		  pq_putint(len,4);
		  pq_putnchar(&attr,len);
#if 0
	          fprintf(f,"byval length %d data %d\n",len,attr);
d318 5
a322 5
	       } else {
		  pq_putint(len,4);
		  pq_putnchar(attr,len);
#if 0
		  fprintf(f,"byref length %d data %x\n",len,attr);
d324 1
a324 2
	       }
	        break;
a327 3
#if 0
    fclose(f);
#endif
@


1.7
log
@*** empty log message ***
@
text
@d12 1
a12 1
RcsId("$Header: RCS/printtup.c,v 1.6 91/03/27 23:21:01 kemnitz Exp Locker: clarsen $");
d19 1
a19 1
#include "utils/fmgr.h"
@


1.6
log
@changed fmgr to use 2 arguments so array_out is happy.
@
text
@d12 1
a12 1
RcsId("$Header: RCS/printtup.c,v 1.5 91/02/20 00:52:08 cimarron Exp Locker: kemnitz $");
d222 97
@


1.5
log
@changed typtoout
@
text
@d12 1
a12 1
RcsId("$Header: RCS/printtup.c,v 1.4 91/02/11 17:21:01 cimarron Exp Locker: cimarron $");
d79 21
d149 1
a149 1
	    outputstr = fmgr(typoutput, attr);
d214 1
a214 1
	    value = fmgr(typoutput, attr);
@


1.4
log
@declared printtup.c and debugtup.c as returning void.
@
text
@d12 1
a12 1
RcsId("$Header: RCS/printtup.c,v 1.3 91/02/10 18:23:19 cimarron Exp Locker: cimarron $");
a24 3

static ObjectId	typtoout();

a44 8
    /* ----------------
     *	REMOVED:
     *
     * pfree(att);	
     *
     *	executor now does the freeing.. -cim 8/8/89
     * ----------------
     */
d59 1
a59 1
static ObjectId
d89 2
a90 2
    char		*outputstr, *attr;
    Boolean		isnull;
@


1.3
log
@reorganization of libpq routines to provide
 PQexec and PQfn functionality from both the front
 end applications and the postgres backend.
@
text
@d12 1
a12 1
RcsId("$Header: RCS/printtup.c,v 1.2 91/02/06 18:03:00 cimarron Exp Locker: cimarron $");
d94 1
d189 1
@


1.2
log
@changed code to use heap_ access method calls explicitly
@
text
@d12 1
a12 1
RcsId("$Header: RCS/printtup.c,v 1.1 91/01/29 15:19:22 cimarron Exp Locker: cimarron $");
a62 27
 *	
 * ----------------------------------------------------------------
 */
/* ----------------
 *	initport
 * ----------------
 */
initport(name, natts, attinfo)
    char		*name;
    int			natts;
    struct attribute	*attinfo[];
{
    register int	i;
    
    putnchar("P", 1);
    putint(0, 4);
    putstr(name);
    putnchar("T", 1);
    putint(natts, 2);
    for (i = 0; i < natts; ++i) {
	putstr(attinfo[i]->attname);	/* if 16 char name oops.. */
	putint((int) attinfo[i]->atttypid, 4);
	putint(attinfo[i]->attlen, 2);
    }
}

/* ----------------------------------------------------------------
d103 10
a112 1
    putnchar("D", 1);
d121 1
a121 1
	    putint(j, 1);
d127 1
a127 1
	putint(j, 1);
d129 3
a131 7
    /*	XXX no longer needed???
     *	{
     *     char 	*s = tuple->t_bits;
     *    
     *     for (i = USEDBITMAPLEN(tuple); --i >= 0; )
     *        putc(reversebitmapchar(*s++), Pfout);
     *  }
d139 2
a140 2
	    putint(strlen(outputstr)+4, 4);
	    putnchar(outputstr, strlen(outputstr));
a208 52

/* ----------------------------------------------------------------
 *			bogus routines
 * ----------------------------------------------------------------
 */
#ifdef BOGUSROUTINES	/* XXX no longer seem to be called */
int
reversebitmapchar(c)
	int	c;
{
	int	i, rev, bit;
	
	rev = 0;
	bit = 01;
	for (i = 8; --i >= 0; ) {
		rev <<= 1;
		if (c & bit)
			rev |= 01;
		bit <<= 1;
	}
	return(rev);
}

dumptup(tuple, typeinfo)
	HeapTuple		tuple;
	struct attribute 	*typeinfo[];
{
	int		i;
	char		*attr, *s;
	Boolean		isnull;

	putnchar("D", 1);
	s = tuple->t_bits;
	for (i = USEDBITMAPLEN(tuple); --i >= 0; )
		putint(*s++, 1);
	for (i = 1; i <= tuple->t_natts; ++i) {
		attr = heap_getattr(tuple, InvalidBuffer, i, typeinfo, &isnull);
		if (!isnull) {
			/*
			 * The following if statement should be replaced
			 * to use the 'send' procedure of a type if such an
			 * item exists.
			 */
			if (typeinfo[i-1]->attlen < 0) {
				putint((int) VARSIZE(attr), 4);
				putnchar(VARDATA(attr), (int) VARSIZE(attr));
			} else
				putnchar(attr, typeinfo[i-1]->attlen);
		}
	}
}
#endif	/* BOGUSROUTINES */
@


1.1
log
@Initial revision
@
text
@d12 1
a12 1
RcsId("$Header: RCS/printtup.c,v 1.7 90/11/20 15:50:37 sp Exp Locker: cimarron $");
d28 1
a28 1
/*
d35 1
d39 2
a40 2
	int 			natts;
	struct attribute	*att;
d42 19
a60 1
	struct	attribute *ap, **rpp, **retatt;
d62 26
a87 3
	rpp = retatt = (struct attribute **) 
	    palloc(natts * sizeof(*rpp) + natts * sizeof(**rpp));
	MemoryCopy(rpp + natts, att, natts * sizeof(**rpp));
d89 26
a114 12
	/* ----------------
	 *	REMOVED:
	 *
	 * pfree(att);	
	 *
	 *	executor now does the freeing.. -cim 8/8/89
	 * ----------------
	 */
	ap = (struct attribute *)(rpp + natts);
	while (--natts >= 0)
		*rpp++ = ap++;
	return(retatt);
d117 4
d122 2
a123 2
	HeapTuple		tuple;
	struct attribute 	*typeinfo[];
d125 17
a141 18
	int		i, j, k;
	char		*outputstr, *attr;
	Boolean		isnull;
	ObjectId	typoutput;

	putnchar("D", 1);
	j = 0;
	k = 1 << 7;
	for (i = 0; i < tuple->t_natts; ) {
		attr = amgetattr(tuple, InvalidBuffer, ++i, typeinfo, &isnull);
		if (!isnull)
			j |= k;
		k >>= 1;
		if (!(i & 7)) {
			putint(j, 1);
			j = 0;
			k = 1 << 7;
		}
d143 15
a157 2
	if (i & 7)
		putint(j, 1);
d159 8
a166 3
/*			XXX no longer needed???
	{
		char 	*s = tuple->t_bits;
d168 59
a226 2
		for (i = USEDBITMAPLEN(tuple); --i >= 0; )
			putc(reversebitmapchar(*s++), Pfout);
d228 2
a229 11
*/
	for (i = 0; i < tuple->t_natts; ++i) {
		attr = amgetattr(tuple, InvalidBuffer, i+1, typeinfo, &isnull);
		typoutput = typtoout((ObjectId) typeinfo[i]->atttypid);
		if (!isnull && ObjectIdIsValid(typoutput)) {
			outputstr = fmgr(typoutput, attr);
			putint(strlen(outputstr)+4, 4);
			putnchar(outputstr, strlen(outputstr));
			pfree(outputstr);
		}
	}
d232 4
d267 1
a267 1
		attr = amgetattr(tuple, InvalidBuffer, i, typeinfo, &isnull);
a283 87
initport(name, natts, attinfo)
	char			*name;
	int			natts;
	struct attribute	*attinfo[];
{
	register int	i;

	putnchar("P", 1);
	putint(0, 4);
	putstr(name);
	putnchar("T", 1);
	putint(natts, 2);
	for (i = 0; i < natts; ++i) {
		putstr(attinfo[i]->attname);	/* if 16 char name oops.. */
		putint((int) attinfo[i]->atttypid, 4);
		putint(attinfo[i]->attlen, 2);
	}
}

void
printatt(attributeId, attributeP, value)
	unsigned		attributeId;
	struct attribute	*attributeP;
	char			*value;
{
	printf("\t%2d: %s%s%s%s\t(typeid = %lu, len = %d, byval = %c)\n",
	       attributeId,
	       attributeP->attname,
	       value != NULL ? " = \"" : "",
	       value != NULL ? value : "",
	       value != NULL ? "\"" : "",
	       attributeP->atttypid,
	       attributeP->attlen,
	       attributeP->attbyval ? 't' : 'f');
}

showatts(name, natts, attinfo)
	char			*name;
	int			natts;
	struct attribute	*attinfo[];
{
	register int	i;
	
	puts(name);
	for (i = 0; i < natts; ++i)
		printatt((unsigned) i+1, attinfo[i], (char *) NULL);
	printf("\t----\n");
}

debugtup(tuple, typeinfo)
	HeapTuple		tuple;
	struct attribute 	*typeinfo[];
{
	register int	i;
	char		*attr, *value;
	Boolean		isnull;
	ObjectId	typoutput;

	for (i = 0; i < tuple->t_natts; ++i) {
		attr = amgetattr(tuple, InvalidBuffer, i+1, typeinfo, &isnull);
		typoutput = typtoout((ObjectId) typeinfo[i]->atttypid);
		if (!isnull && ObjectIdIsValid(typoutput)) {
			value = fmgr(typoutput, attr);
			printatt((unsigned) i+1, typeinfo[i], value);
			pfree(value);
		}
	}
	printf("\t----\n");
}

static ObjectId
typtoout(type)
	ObjectId	type;
{
	HeapTuple	typeTuple;

	typeTuple = SearchSysCacheTuple(TYPOID,
					(char *) type,
					(char *) NULL,
					(char *) NULL,
					(char *) NULL);
	if (HeapTupleIsValid(typeTuple))
		return((ObjectId)
       ((TypeTupleForm) GETSTRUCT(typeTuple))->typoutput);
	elog(WARN, "typtoout: Cache lookup of type %d failed", type);
	return(InvalidObjectId);
}
@
