Replace typtoout() and gettypelem() with a single routine,
so that fetching an attribute value needs only one SearchSysCacheTuple call instead of two redundant searches. This speeds up a large SELECT by about ten percent, and probably will help GROUP BY and SELECT DISTINCT too.
This commit is contained in:
parent
77f5428244
commit
d03e98737c
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.37 1998/12/12 22:04:09 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.38 1999/01/24 05:40:47 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -33,11 +33,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* typtoout - used by printtup and debugtup
|
* getTypeOutAndElem -- get both typoutput and typelem for a type
|
||||||
|
*
|
||||||
|
* We used to fetch these with two separate function calls,
|
||||||
|
* typtoout() and gettypelem(), which each called SearchSysCacheTuple.
|
||||||
|
* This way takes half the time.
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
Oid
|
int
|
||||||
typtoout(Oid type)
|
getTypeOutAndElem(Oid type, Oid* typOutput, Oid* typElem)
|
||||||
{
|
{
|
||||||
HeapTuple typeTuple;
|
HeapTuple typeTuple;
|
||||||
|
|
||||||
@ -46,26 +50,18 @@ typtoout(Oid type)
|
|||||||
0, 0, 0);
|
0, 0, 0);
|
||||||
|
|
||||||
if (HeapTupleIsValid(typeTuple))
|
if (HeapTupleIsValid(typeTuple))
|
||||||
return (Oid) ((Form_pg_type) GETSTRUCT(typeTuple))->typoutput;
|
{
|
||||||
|
Form_pg_type pt = (Form_pg_type) GETSTRUCT(typeTuple);
|
||||||
|
*typOutput = (Oid) pt->typoutput;
|
||||||
|
*typElem = (Oid) pt->typelem;
|
||||||
|
return OidIsValid(*typOutput);
|
||||||
|
}
|
||||||
|
|
||||||
elog(ERROR, "typtoout: Cache lookup of type %d failed", type);
|
elog(ERROR, "getTypeOutAndElem: Cache lookup of type %d failed", type);
|
||||||
return InvalidOid;
|
|
||||||
}
|
|
||||||
|
|
||||||
Oid
|
*typOutput = InvalidOid;
|
||||||
gettypelem(Oid type)
|
*typElem = InvalidOid;
|
||||||
{
|
return 0;
|
||||||
HeapTuple typeTuple;
|
|
||||||
|
|
||||||
typeTuple = SearchSysCacheTuple(TYPOID,
|
|
||||||
ObjectIdGetDatum(type),
|
|
||||||
0, 0, 0);
|
|
||||||
|
|
||||||
if (HeapTupleIsValid(typeTuple))
|
|
||||||
return (Oid) ((Form_pg_type) GETSTRUCT(typeTuple))->typelem;
|
|
||||||
|
|
||||||
elog(ERROR, "typtoout: Cache lookup of type %d failed", type);
|
|
||||||
return InvalidOid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
@ -77,19 +73,19 @@ printtup(HeapTuple tuple, TupleDesc typeinfo)
|
|||||||
{
|
{
|
||||||
int i,
|
int i,
|
||||||
j,
|
j,
|
||||||
k;
|
k,
|
||||||
|
outputlen;
|
||||||
char *outputstr;
|
char *outputstr;
|
||||||
Datum attr;
|
Datum attr;
|
||||||
bool isnull;
|
bool isnull;
|
||||||
Oid typoutput;
|
Oid typoutput,
|
||||||
|
typelem;
|
||||||
#ifdef MULTIBYTE
|
#ifdef MULTIBYTE
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* tell the frontend to expect new tuple data
|
* tell the frontend to expect new tuple data (in ASCII style)
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
pq_putnchar("D", 1);
|
pq_putnchar("D", 1);
|
||||||
@ -127,28 +123,29 @@ printtup(HeapTuple tuple, TupleDesc typeinfo)
|
|||||||
attr = heap_getattr(tuple, i + 1, typeinfo, &isnull);
|
attr = heap_getattr(tuple, i + 1, typeinfo, &isnull);
|
||||||
if (isnull)
|
if (isnull)
|
||||||
continue;
|
continue;
|
||||||
|
if (getTypeOutAndElem((Oid) typeinfo->attrs[i]->atttypid,
|
||||||
typoutput = typtoout((Oid) typeinfo->attrs[i]->atttypid);
|
&typoutput, &typelem))
|
||||||
if (OidIsValid(typoutput))
|
|
||||||
{
|
{
|
||||||
outputstr = fmgr(typoutput, attr,
|
outputstr = fmgr(typoutput, attr, typelem,
|
||||||
gettypelem(typeinfo->attrs[i]->atttypid),
|
|
||||||
typeinfo->attrs[i]->atttypmod);
|
typeinfo->attrs[i]->atttypmod);
|
||||||
#ifdef MULTIBYTE
|
#ifdef MULTIBYTE
|
||||||
p = pg_server_to_client(outputstr, strlen(outputstr));
|
p = pg_server_to_client(outputstr, strlen(outputstr));
|
||||||
pq_putint(strlen(p) + VARHDRSZ, VARHDRSZ);
|
outputlen = strlen(p);
|
||||||
pq_putnchar(p, strlen(p));
|
pq_putint(outputlen + VARHDRSZ, VARHDRSZ);
|
||||||
|
pq_putnchar(p, outputlen);
|
||||||
#else
|
#else
|
||||||
pq_putint(strlen(outputstr) + VARHDRSZ, VARHDRSZ);
|
outputlen = strlen(outputstr);
|
||||||
pq_putnchar(outputstr, strlen(outputstr));
|
pq_putint(outputlen + VARHDRSZ, VARHDRSZ);
|
||||||
|
pq_putnchar(outputstr, outputlen);
|
||||||
#endif
|
#endif
|
||||||
pfree(outputstr);
|
pfree(outputstr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
outputstr = "<unprintable>";
|
outputstr = "<unprintable>";
|
||||||
pq_putint(strlen(outputstr) + VARHDRSZ, VARHDRSZ);
|
outputlen = strlen(outputstr);
|
||||||
pq_putnchar(outputstr, strlen(outputstr));
|
pq_putint(outputlen + VARHDRSZ, VARHDRSZ);
|
||||||
|
pq_putnchar(outputstr, outputlen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -202,17 +199,18 @@ debugtup(HeapTuple tuple, TupleDesc typeinfo)
|
|||||||
Datum attr;
|
Datum attr;
|
||||||
char *value;
|
char *value;
|
||||||
bool isnull;
|
bool isnull;
|
||||||
Oid typoutput;
|
Oid typoutput,
|
||||||
|
typelem;
|
||||||
|
|
||||||
for (i = 0; i < tuple->t_data->t_natts; ++i)
|
for (i = 0; i < tuple->t_data->t_natts; ++i)
|
||||||
{
|
{
|
||||||
attr = heap_getattr(tuple, i + 1, typeinfo, &isnull);
|
attr = heap_getattr(tuple, i + 1, typeinfo, &isnull);
|
||||||
typoutput = typtoout((Oid) typeinfo->attrs[i]->atttypid);
|
if (isnull)
|
||||||
|
continue;
|
||||||
if (!isnull && OidIsValid(typoutput))
|
if (getTypeOutAndElem((Oid) typeinfo->attrs[i]->atttypid,
|
||||||
|
&typoutput, &typelem))
|
||||||
{
|
{
|
||||||
value = fmgr(typoutput, attr,
|
value = fmgr(typoutput, attr, typelem,
|
||||||
gettypelem(typeinfo->attrs[i]->atttypid),
|
|
||||||
typeinfo->attrs[i]->atttypmod);
|
typeinfo->attrs[i]->atttypmod);
|
||||||
printatt((unsigned) i + 1, typeinfo->attrs[i], value);
|
printatt((unsigned) i + 1, typeinfo->attrs[i], value);
|
||||||
pfree(value);
|
pfree(value);
|
||||||
@ -223,7 +221,6 @@ debugtup(HeapTuple tuple, TupleDesc typeinfo)
|
|||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* printtup_internal
|
* printtup_internal
|
||||||
* Protocol expects either T, D, C, E, or N.
|
|
||||||
* We use a different data prefix, e.g. 'B' instead of 'D' to
|
* We use a different data prefix, e.g. 'B' instead of 'D' to
|
||||||
* indicate a tuple in internal (binary) form.
|
* indicate a tuple in internal (binary) form.
|
||||||
*
|
*
|
||||||
@ -240,7 +237,7 @@ printtup_internal(HeapTuple tuple, TupleDesc typeinfo)
|
|||||||
bool isnull;
|
bool isnull;
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* tell the frontend to expect new tuple data
|
* tell the frontend to expect new tuple data (in binary style)
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
pq_putnchar("B", 1);
|
pq_putnchar("B", 1);
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
* columns. (ie. tuples from the same group are consecutive)
|
* columns. (ie. tuples from the same group are consecutive)
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.23 1998/11/27 19:52:01 vadim Exp $
|
* $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.24 1999/01/24 05:40:47 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -364,12 +364,14 @@ sameGroup(HeapTuple oldtuple,
|
|||||||
*val2;
|
*val2;
|
||||||
int i;
|
int i;
|
||||||
AttrNumber att;
|
AttrNumber att;
|
||||||
Oid typoutput;
|
Oid typoutput,
|
||||||
|
typelem;
|
||||||
|
|
||||||
for (i = 0; i < numCols; i++)
|
for (i = 0; i < numCols; i++)
|
||||||
{
|
{
|
||||||
att = grpColIdx[i];
|
att = grpColIdx[i];
|
||||||
typoutput = typtoout((Oid) tupdesc->attrs[att - 1]->atttypid);
|
getTypeOutAndElem((Oid) tupdesc->attrs[att - 1]->atttypid,
|
||||||
|
&typoutput, &typelem);
|
||||||
|
|
||||||
attr1 = heap_getattr(oldtuple,
|
attr1 = heap_getattr(oldtuple,
|
||||||
att,
|
att,
|
||||||
@ -386,11 +388,9 @@ sameGroup(HeapTuple oldtuple,
|
|||||||
if (isNull1) /* both are null, they are equal */
|
if (isNull1) /* both are null, they are equal */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
val1 = fmgr(typoutput, attr1,
|
val1 = fmgr(typoutput, attr1, typelem,
|
||||||
gettypelem(tupdesc->attrs[att - 1]->atttypid),
|
|
||||||
tupdesc->attrs[att - 1]->atttypmod);
|
tupdesc->attrs[att - 1]->atttypmod);
|
||||||
val2 = fmgr(typoutput, attr2,
|
val2 = fmgr(typoutput, attr2, typelem,
|
||||||
gettypelem(tupdesc->attrs[att - 1]->atttypid),
|
|
||||||
tupdesc->attrs[att - 1]->atttypmod);
|
tupdesc->attrs[att - 1]->atttypmod);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeUnique.c,v 1.18 1998/11/27 19:52:03 vadim Exp $
|
* $Header: /cvsroot/pgsql/src/backend/executor/nodeUnique.c,v 1.19 1999/01/24 05:40:48 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -31,7 +31,7 @@
|
|||||||
#include "executor/nodeUnique.h"
|
#include "executor/nodeUnique.h"
|
||||||
#include "optimizer/clauses.h"
|
#include "optimizer/clauses.h"
|
||||||
#include "access/heapam.h"
|
#include "access/heapam.h"
|
||||||
#include "access/printtup.h" /* for typtoout() */
|
#include "access/printtup.h" /* for getTypeOutAndElem() */
|
||||||
#include "utils/builtins.h" /* for namecpy() */
|
#include "utils/builtins.h" /* for namecpy() */
|
||||||
|
|
||||||
/* ----------------------------------------------------------------
|
/* ----------------------------------------------------------------
|
||||||
@ -117,7 +117,8 @@ ExecUnique(Unique *node)
|
|||||||
char *uniqueAttr;
|
char *uniqueAttr;
|
||||||
AttrNumber uniqueAttrNum;
|
AttrNumber uniqueAttrNum;
|
||||||
TupleDesc tupDesc;
|
TupleDesc tupDesc;
|
||||||
Oid typoutput;
|
Oid typoutput,
|
||||||
|
typelem;
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* get information from the node
|
* get information from the node
|
||||||
@ -132,12 +133,14 @@ ExecUnique(Unique *node)
|
|||||||
if (uniqueAttr)
|
if (uniqueAttr)
|
||||||
{
|
{
|
||||||
tupDesc = ExecGetResultType(uniquestate);
|
tupDesc = ExecGetResultType(uniquestate);
|
||||||
typoutput = typtoout((Oid) tupDesc->attrs[uniqueAttrNum - 1]->atttypid);
|
getTypeOutAndElem((Oid) tupDesc->attrs[uniqueAttrNum - 1]->atttypid,
|
||||||
|
&typoutput, &typelem);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* keep compiler quiet */
|
{ /* keep compiler quiet */
|
||||||
tupDesc = NULL;
|
tupDesc = NULL;
|
||||||
typoutput = 0;
|
typoutput = InvalidOid;
|
||||||
|
typelem = InvalidOid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
@ -196,11 +199,9 @@ ExecUnique(Unique *node)
|
|||||||
{
|
{
|
||||||
if (isNull1) /* both are null, they are equal */
|
if (isNull1) /* both are null, they are equal */
|
||||||
continue;
|
continue;
|
||||||
val1 = fmgr(typoutput, attr1,
|
val1 = fmgr(typoutput, attr1, typelem,
|
||||||
gettypelem(tupDesc->attrs[uniqueAttrNum - 1]->atttypid),
|
|
||||||
tupDesc->attrs[uniqueAttrNum - 1]->atttypmod);
|
tupDesc->attrs[uniqueAttrNum - 1]->atttypmod);
|
||||||
val2 = fmgr(typoutput, attr2,
|
val2 = fmgr(typoutput, attr2, typelem,
|
||||||
gettypelem(tupDesc->attrs[uniqueAttrNum - 1]->atttypid),
|
|
||||||
tupDesc->attrs[uniqueAttrNum - 1]->atttypmod);
|
tupDesc->attrs[uniqueAttrNum - 1]->atttypmod);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
* spi.c--
|
* spi.c--
|
||||||
* Server Programming Interface
|
* Server Programming Interface
|
||||||
*
|
*
|
||||||
* $Id: spi.c,v 1.29 1998/12/14 05:18:51 scrappy Exp $
|
* $Id: spi.c,v 1.30 1999/01/24 05:40:48 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -409,7 +409,8 @@ SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber)
|
|||||||
{
|
{
|
||||||
Datum val;
|
Datum val;
|
||||||
bool isnull;
|
bool isnull;
|
||||||
Oid foutoid;
|
Oid foutoid,
|
||||||
|
typelem;
|
||||||
|
|
||||||
SPI_result = 0;
|
SPI_result = 0;
|
||||||
if (tuple->t_data->t_natts < fnumber || fnumber <= 0)
|
if (tuple->t_data->t_natts < fnumber || fnumber <= 0)
|
||||||
@ -421,15 +422,14 @@ SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber)
|
|||||||
val = heap_getattr(tuple, fnumber, tupdesc, &isnull);
|
val = heap_getattr(tuple, fnumber, tupdesc, &isnull);
|
||||||
if (isnull)
|
if (isnull)
|
||||||
return NULL;
|
return NULL;
|
||||||
foutoid = typtoout((Oid) tupdesc->attrs[fnumber - 1]->atttypid);
|
if (! getTypeOutAndElem((Oid) tupdesc->attrs[fnumber - 1]->atttypid,
|
||||||
if (!OidIsValid(foutoid))
|
&foutoid, &typelem))
|
||||||
{
|
{
|
||||||
SPI_result = SPI_ERROR_NOOUTFUNC;
|
SPI_result = SPI_ERROR_NOOUTFUNC;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (fmgr(foutoid, val,
|
return (fmgr(foutoid, val, typelem,
|
||||||
gettypelem(tupdesc->attrs[fnumber - 1]->atttypid),
|
|
||||||
tupdesc->attrs[fnumber - 1]->atttypmod));
|
tupdesc->attrs[fnumber - 1]->atttypmod));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: be-dumpdata.c,v 1.19 1998/12/14 06:50:23 scrappy Exp $
|
* $Id: be-dumpdata.c,v 1.20 1999/01/24 05:40:49 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -213,7 +213,8 @@ be_printtup(HeapTuple tuple, TupleDesc typeinfo)
|
|||||||
int i;
|
int i;
|
||||||
Datum attr;
|
Datum attr;
|
||||||
bool isnull;
|
bool isnull;
|
||||||
Oid typoutput;
|
Oid typoutput,
|
||||||
|
typelem;
|
||||||
|
|
||||||
PortalEntry *entry = NULL;
|
PortalEntry *entry = NULL;
|
||||||
PortalBuffer *portal = NULL;
|
PortalBuffer *portal = NULL;
|
||||||
@ -298,7 +299,8 @@ be_printtup(HeapTuple tuple, TupleDesc typeinfo)
|
|||||||
for (i = 0; i < tuple->t_data->t_natts; i++)
|
for (i = 0; i < tuple->t_data->t_natts; i++)
|
||||||
{
|
{
|
||||||
attr = heap_getattr(tuple, i + 1, typeinfo, &isnull);
|
attr = heap_getattr(tuple, i + 1, typeinfo, &isnull);
|
||||||
typoutput = typtoout((Oid) typeinfo->attrs[i]->atttypid);
|
getTypeOutAndElem((Oid) typeinfo->attrs[i]->atttypid,
|
||||||
|
&typoutput, &typelem);
|
||||||
|
|
||||||
lengths[i] = typeinfo->attrs[i]->attlen;
|
lengths[i] = typeinfo->attrs[i]->attlen;
|
||||||
|
|
||||||
@ -311,11 +313,8 @@ be_printtup(HeapTuple tuple, TupleDesc typeinfo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isnull && OidIsValid(typoutput))
|
if (!isnull && OidIsValid(typoutput))
|
||||||
{
|
values[i] = fmgr(typoutput, attr, typelem,
|
||||||
values[i] = fmgr(typoutput, attr,
|
|
||||||
gettypelem(typeinfo->attrs[i]->atttypid),
|
|
||||||
typeinfo->attrs[i]->atttypmod);
|
typeinfo->attrs[i]->atttypmod);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
values[i] = NULL;
|
values[i] = NULL;
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: printtup.h,v 1.5 1998/09/01 04:34:22 momjian Exp $
|
* $Id: printtup.h,v 1.6 1999/01/24 05:40:46 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -16,11 +16,10 @@
|
|||||||
#include <access/htup.h>
|
#include <access/htup.h>
|
||||||
#include <access/tupdesc.h>
|
#include <access/tupdesc.h>
|
||||||
|
|
||||||
extern Oid typtoout(Oid type);
|
extern int getTypeOutAndElem(Oid type, Oid* typOutput, Oid* typElem);
|
||||||
extern void printtup(HeapTuple tuple, TupleDesc typeinfo);
|
extern void printtup(HeapTuple tuple, TupleDesc typeinfo);
|
||||||
extern void showatts(char *name, TupleDesc attinfo);
|
extern void showatts(char *name, TupleDesc attinfo);
|
||||||
extern void debugtup(HeapTuple tuple, TupleDesc typeinfo);
|
extern void debugtup(HeapTuple tuple, TupleDesc typeinfo);
|
||||||
extern void printtup_internal(HeapTuple tuple, TupleDesc typeinfo);
|
extern void printtup_internal(HeapTuple tuple, TupleDesc typeinfo);
|
||||||
extern Oid gettypelem(Oid type);
|
|
||||||
|
|
||||||
#endif /* PRINTTUP_H */
|
#endif /* PRINTTUP_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user