mirror of
https://github.com/postgres/postgres.git
synced 2025-07-26 01:22:12 +03:00
Create a new expression node type RelabelType, which exists solely to
represent the result of a binary-compatible type coercion. At runtime it just evaluates its argument --- but during type resolution, exprType will pick up the output type of the RelabelType node instead of the type of the argument. This solves some longstanding problems with dropped type coercions, an example being 'select now()::abstime::int4' which used to produce date-formatted output, not an integer, because the coercion to int4 was dropped on the floor.
This commit is contained in:
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.106 2000/02/15 20:49:09 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.107 2000/02/20 21:32:05 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -873,6 +873,26 @@ _copySubLink(SubLink *from)
|
||||
return newnode;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* _copyRelabelType
|
||||
* ----------------
|
||||
*/
|
||||
static RelabelType *
|
||||
_copyRelabelType(RelabelType *from)
|
||||
{
|
||||
RelabelType *newnode = makeNode(RelabelType);
|
||||
|
||||
/* ----------------
|
||||
* copy remainder of node
|
||||
* ----------------
|
||||
*/
|
||||
Node_Copy(from, newnode, arg);
|
||||
newnode->resulttype = from->resulttype;
|
||||
newnode->resulttypmod = from->resulttypmod;
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* _copyCaseExpr
|
||||
* ----------------
|
||||
@ -1617,6 +1637,9 @@ copyObject(void *from)
|
||||
case T_SubLink:
|
||||
retval = _copySubLink(from);
|
||||
break;
|
||||
case T_RelabelType:
|
||||
retval = _copyRelabelType(from);
|
||||
break;
|
||||
case T_CaseExpr:
|
||||
retval = _copyCaseExpr(from);
|
||||
break;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.61 2000/02/15 20:49:09 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.62 2000/02/20 21:32:05 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -262,6 +262,18 @@ _equalSubLink(SubLink *a, SubLink *b)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalRelabelType(RelabelType *a, RelabelType *b)
|
||||
{
|
||||
if (!equal(a->arg, b->arg))
|
||||
return false;
|
||||
if (a->resulttype != b->resulttype)
|
||||
return false;
|
||||
if (a->resulttypmod != b->resulttypmod)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalArray(Array *a, Array *b)
|
||||
{
|
||||
@ -806,6 +818,9 @@ equal(void *a, void *b)
|
||||
case T_SubLink:
|
||||
retval = _equalSubLink(a, b);
|
||||
break;
|
||||
case T_RelabelType:
|
||||
retval = _equalRelabelType(a, b);
|
||||
break;
|
||||
case T_Func:
|
||||
retval = _equalFunc(a, b);
|
||||
break;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/Attic/freefuncs.c,v 1.36 2000/02/15 20:49:09 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/Attic/freefuncs.c,v 1.37 2000/02/20 21:32:05 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -650,6 +650,22 @@ _freeSubLink(SubLink *node)
|
||||
pfree(node);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* _freeRelabelType
|
||||
* ----------------
|
||||
*/
|
||||
static void
|
||||
_freeRelabelType(RelabelType *node)
|
||||
{
|
||||
/* ----------------
|
||||
* free remainder of node
|
||||
* ----------------
|
||||
*/
|
||||
freeObject(node->arg);
|
||||
|
||||
pfree(node);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* _freeCaseExpr
|
||||
* ----------------
|
||||
@ -1241,6 +1257,9 @@ freeObject(void *node)
|
||||
case T_SubLink:
|
||||
_freeSubLink(node);
|
||||
break;
|
||||
case T_RelabelType:
|
||||
_freeRelabelType(node);
|
||||
break;
|
||||
case T_CaseExpr:
|
||||
_freeCaseExpr(node);
|
||||
break;
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.108 2000/02/15 20:49:09 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.109 2000/02/20 21:32:05 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Every (plan) node in POSTGRES has an associated "out" routine which
|
||||
@ -770,6 +770,19 @@ _outSubLink(StringInfo str, SubLink *node)
|
||||
_outNode(str, node->subselect);
|
||||
}
|
||||
|
||||
/*
|
||||
* RelabelType
|
||||
*/
|
||||
static void
|
||||
_outRelabelType(StringInfo str, RelabelType *node)
|
||||
{
|
||||
appendStringInfo(str, " RELABELTYPE :arg ");
|
||||
_outNode(str, node->arg);
|
||||
|
||||
appendStringInfo(str, " :resulttype %u :resulttypmod %d ",
|
||||
node->resulttype, node->resulttypmod);
|
||||
}
|
||||
|
||||
/*
|
||||
* Array is a subclass of Expr
|
||||
*/
|
||||
@ -1496,6 +1509,9 @@ _outNode(StringInfo str, void *obj)
|
||||
case T_SubLink:
|
||||
_outSubLink(str, obj);
|
||||
break;
|
||||
case T_RelabelType:
|
||||
_outRelabelType(str, obj);
|
||||
break;
|
||||
case T_Array:
|
||||
_outArray(str, obj);
|
||||
break;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.84 2000/02/15 20:49:12 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.85 2000/02/20 21:32:05 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Most of the read functions for plan nodes are tested. (In fact, they
|
||||
@ -1191,6 +1191,35 @@ _readSubLink()
|
||||
return local_node;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* _readRelabelType
|
||||
*
|
||||
* RelabelType is a subclass of Node
|
||||
* ----------------
|
||||
*/
|
||||
static RelabelType *
|
||||
_readRelabelType()
|
||||
{
|
||||
RelabelType *local_node;
|
||||
char *token;
|
||||
int length;
|
||||
|
||||
local_node = makeNode(RelabelType);
|
||||
|
||||
token = lsptok(NULL, &length); /* eat :arg */
|
||||
local_node->arg = nodeRead(true); /* now read it */
|
||||
|
||||
token = lsptok(NULL, &length); /* eat :resulttype */
|
||||
token = lsptok(NULL, &length); /* get resulttype */
|
||||
local_node->resulttype = (Oid) atol(token);
|
||||
|
||||
token = lsptok(NULL, &length); /* eat :resulttypmod */
|
||||
token = lsptok(NULL, &length); /* get resulttypmod */
|
||||
local_node->resulttypmod = atoi(token);
|
||||
|
||||
return local_node;
|
||||
}
|
||||
|
||||
/*
|
||||
* Stuff from execnodes.h
|
||||
*/
|
||||
@ -1820,6 +1849,8 @@ parsePlanString(void)
|
||||
return_value = _readAggref();
|
||||
else if (length == 7 && strncmp(token, "SUBLINK", length) == 0)
|
||||
return_value = _readSubLink();
|
||||
else if (length == 11 && strncmp(token, "RELABELTYPE", length) == 0)
|
||||
return_value = _readRelabelType();
|
||||
else if (length == 3 && strncmp(token, "AGG", length) == 0)
|
||||
return_value = _readAgg();
|
||||
else if (length == 4 && strncmp(token, "HASH", length) == 0)
|
||||
|
Reference in New Issue
Block a user