Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 57b30e8

Browse files
committed
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.
1 parent bd8e071 commit 57b30e8

File tree

13 files changed

+325
-86
lines changed

13 files changed

+325
-86
lines changed

src/backend/executor/execQual.c

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.67 2000/01/26 05:56:21 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.68 2000/02/20 21:32:04 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -1176,7 +1176,7 @@ ExecEvalExpr(Node *expression,
11761176
bool *isNull,
11771177
bool *isDone)
11781178
{
1179-
Datum retDatum = 0;
1179+
Datum retDatum;
11801180

11811181
*isNull = false;
11821182

@@ -1200,36 +1200,33 @@ ExecEvalExpr(Node *expression,
12001200
switch (nodeTag(expression))
12011201
{
12021202
case T_Var:
1203-
retDatum = (Datum) ExecEvalVar((Var *) expression, econtext, isNull);
1203+
retDatum = ExecEvalVar((Var *) expression, econtext, isNull);
12041204
break;
12051205
case T_Const:
12061206
{
12071207
Const *con = (Const *) expression;
12081208

1209-
if (con->constisnull)
1210-
*isNull = true;
12111209
retDatum = con->constvalue;
1210+
*isNull = con->constisnull;
12121211
break;
12131212
}
12141213
case T_Param:
1215-
retDatum = (Datum) ExecEvalParam((Param *) expression, econtext, isNull);
1214+
retDatum = ExecEvalParam((Param *) expression, econtext, isNull);
12161215
break;
12171216
case T_Iter:
1218-
retDatum = (Datum) ExecEvalIter((Iter *) expression,
1219-
econtext,
1220-
isNull,
1221-
isDone);
1217+
retDatum = ExecEvalIter((Iter *) expression,
1218+
econtext,
1219+
isNull,
1220+
isDone);
12221221
break;
12231222
case T_Aggref:
1224-
retDatum = (Datum) ExecEvalAggref((Aggref *) expression,
1225-
econtext,
1226-
isNull);
1223+
retDatum = ExecEvalAggref((Aggref *) expression, econtext, isNull);
12271224
break;
12281225
case T_ArrayRef:
1229-
retDatum = (Datum) ExecEvalArrayRef((ArrayRef *) expression,
1230-
econtext,
1231-
isNull,
1232-
isDone);
1226+
retDatum = ExecEvalArrayRef((ArrayRef *) expression,
1227+
econtext,
1228+
isNull,
1229+
isDone);
12331230
break;
12341231
case T_Expr:
12351232
{
@@ -1238,37 +1235,48 @@ ExecEvalExpr(Node *expression,
12381235
switch (expr->opType)
12391236
{
12401237
case OP_EXPR:
1241-
retDatum = (Datum) ExecEvalOper(expr, econtext, isNull);
1238+
retDatum = ExecEvalOper(expr, econtext, isNull);
12421239
break;
12431240
case FUNC_EXPR:
1244-
retDatum = (Datum) ExecEvalFunc(expr, econtext, isNull, isDone);
1241+
retDatum = ExecEvalFunc(expr, econtext,
1242+
isNull, isDone);
12451243
break;
12461244
case OR_EXPR:
1247-
retDatum = (Datum) ExecEvalOr(expr, econtext, isNull);
1245+
retDatum = ExecEvalOr(expr, econtext, isNull);
12481246
break;
12491247
case AND_EXPR:
1250-
retDatum = (Datum) ExecEvalAnd(expr, econtext, isNull);
1248+
retDatum = ExecEvalAnd(expr, econtext, isNull);
12511249
break;
12521250
case NOT_EXPR:
1253-
retDatum = (Datum) ExecEvalNot(expr, econtext, isNull);
1251+
retDatum = ExecEvalNot(expr, econtext, isNull);
12541252
break;
12551253
case SUBPLAN_EXPR:
1256-
retDatum = (Datum) ExecSubPlan((SubPlan *) expr->oper,
1257-
expr->args, econtext,
1258-
isNull);
1254+
retDatum = ExecSubPlan((SubPlan *) expr->oper,
1255+
expr->args, econtext,
1256+
isNull);
12591257
break;
12601258
default:
1261-
elog(ERROR, "ExecEvalExpr: unknown expression type %d", expr->opType);
1259+
elog(ERROR, "ExecEvalExpr: unknown expression type %d",
1260+
expr->opType);
1261+
retDatum = 0; /* keep compiler quiet */
12621262
break;
12631263
}
12641264
break;
12651265
}
1266+
case T_RelabelType:
1267+
retDatum = ExecEvalExpr(((RelabelType *) expression)->arg,
1268+
econtext,
1269+
isNull,
1270+
isDone);
1271+
break;
12661272
case T_CaseExpr:
1267-
retDatum = (Datum) ExecEvalCase((CaseExpr *) expression, econtext, isNull);
1273+
retDatum = ExecEvalCase((CaseExpr *) expression, econtext, isNull);
12681274
break;
12691275

12701276
default:
1271-
elog(ERROR, "ExecEvalExpr: unknown expression type %d", nodeTag(expression));
1277+
elog(ERROR, "ExecEvalExpr: unknown expression type %d",
1278+
nodeTag(expression));
1279+
retDatum = 0; /* keep compiler quiet */
12721280
break;
12731281
}
12741282

src/backend/nodes/copyfuncs.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.106 2000/02/15 20:49:09 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.107 2000/02/20 21:32:05 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -873,6 +873,26 @@ _copySubLink(SubLink *from)
873873
return newnode;
874874
}
875875

876+
/* ----------------
877+
* _copyRelabelType
878+
* ----------------
879+
*/
880+
static RelabelType *
881+
_copyRelabelType(RelabelType *from)
882+
{
883+
RelabelType *newnode = makeNode(RelabelType);
884+
885+
/* ----------------
886+
* copy remainder of node
887+
* ----------------
888+
*/
889+
Node_Copy(from, newnode, arg);
890+
newnode->resulttype = from->resulttype;
891+
newnode->resulttypmod = from->resulttypmod;
892+
893+
return newnode;
894+
}
895+
876896
/* ----------------
877897
* _copyCaseExpr
878898
* ----------------
@@ -1617,6 +1637,9 @@ copyObject(void *from)
16171637
case T_SubLink:
16181638
retval = _copySubLink(from);
16191639
break;
1640+
case T_RelabelType:
1641+
retval = _copyRelabelType(from);
1642+
break;
16201643
case T_CaseExpr:
16211644
retval = _copyCaseExpr(from);
16221645
break;

src/backend/nodes/equalfuncs.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.61 2000/02/15 20:49:09 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.62 2000/02/20 21:32:05 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -262,6 +262,18 @@ _equalSubLink(SubLink *a, SubLink *b)
262262
return true;
263263
}
264264

265+
static bool
266+
_equalRelabelType(RelabelType *a, RelabelType *b)
267+
{
268+
if (!equal(a->arg, b->arg))
269+
return false;
270+
if (a->resulttype != b->resulttype)
271+
return false;
272+
if (a->resulttypmod != b->resulttypmod)
273+
return false;
274+
return true;
275+
}
276+
265277
static bool
266278
_equalArray(Array *a, Array *b)
267279
{
@@ -806,6 +818,9 @@ equal(void *a, void *b)
806818
case T_SubLink:
807819
retval = _equalSubLink(a, b);
808820
break;
821+
case T_RelabelType:
822+
retval = _equalRelabelType(a, b);
823+
break;
809824
case T_Func:
810825
retval = _equalFunc(a, b);
811826
break;

src/backend/nodes/freefuncs.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/nodes/Attic/freefuncs.c,v 1.36 2000/02/15 20:49:09 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/nodes/Attic/freefuncs.c,v 1.37 2000/02/20 21:32:05 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -650,6 +650,22 @@ _freeSubLink(SubLink *node)
650650
pfree(node);
651651
}
652652

653+
/* ----------------
654+
* _freeRelabelType
655+
* ----------------
656+
*/
657+
static void
658+
_freeRelabelType(RelabelType *node)
659+
{
660+
/* ----------------
661+
* free remainder of node
662+
* ----------------
663+
*/
664+
freeObject(node->arg);
665+
666+
pfree(node);
667+
}
668+
653669
/* ----------------
654670
* _freeCaseExpr
655671
* ----------------
@@ -1241,6 +1257,9 @@ freeObject(void *node)
12411257
case T_SubLink:
12421258
_freeSubLink(node);
12431259
break;
1260+
case T_RelabelType:
1261+
_freeRelabelType(node);
1262+
break;
12441263
case T_CaseExpr:
12451264
_freeCaseExpr(node);
12461265
break;

src/backend/nodes/outfuncs.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.108 2000/02/15 20:49:09 tgl Exp $
9+
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.109 2000/02/20 21:32:05 tgl Exp $
1010
*
1111
* NOTES
1212
* Every (plan) node in POSTGRES has an associated "out" routine which
@@ -770,6 +770,19 @@ _outSubLink(StringInfo str, SubLink *node)
770770
_outNode(str, node->subselect);
771771
}
772772

773+
/*
774+
* RelabelType
775+
*/
776+
static void
777+
_outRelabelType(StringInfo str, RelabelType *node)
778+
{
779+
appendStringInfo(str, " RELABELTYPE :arg ");
780+
_outNode(str, node->arg);
781+
782+
appendStringInfo(str, " :resulttype %u :resulttypmod %d ",
783+
node->resulttype, node->resulttypmod);
784+
}
785+
773786
/*
774787
* Array is a subclass of Expr
775788
*/
@@ -1496,6 +1509,9 @@ _outNode(StringInfo str, void *obj)
14961509
case T_SubLink:
14971510
_outSubLink(str, obj);
14981511
break;
1512+
case T_RelabelType:
1513+
_outRelabelType(str, obj);
1514+
break;
14991515
case T_Array:
15001516
_outArray(str, obj);
15011517
break;

src/backend/nodes/readfuncs.c

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.84 2000/02/15 20:49:12 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.85 2000/02/20 21:32:05 tgl Exp $
1212
*
1313
* NOTES
1414
* Most of the read functions for plan nodes are tested. (In fact, they
@@ -1191,6 +1191,35 @@ _readSubLink()
11911191
return local_node;
11921192
}
11931193

1194+
/* ----------------
1195+
* _readRelabelType
1196+
*
1197+
* RelabelType is a subclass of Node
1198+
* ----------------
1199+
*/
1200+
static RelabelType *
1201+
_readRelabelType()
1202+
{
1203+
RelabelType *local_node;
1204+
char *token;
1205+
int length;
1206+
1207+
local_node = makeNode(RelabelType);
1208+
1209+
token = lsptok(NULL, &length); /* eat :arg */
1210+
local_node->arg = nodeRead(true); /* now read it */
1211+
1212+
token = lsptok(NULL, &length); /* eat :resulttype */
1213+
token = lsptok(NULL, &length); /* get resulttype */
1214+
local_node->resulttype = (Oid) atol(token);
1215+
1216+
token = lsptok(NULL, &length); /* eat :resulttypmod */
1217+
token = lsptok(NULL, &length); /* get resulttypmod */
1218+
local_node->resulttypmod = atoi(token);
1219+
1220+
return local_node;
1221+
}
1222+
11941223
/*
11951224
* Stuff from execnodes.h
11961225
*/
@@ -1820,6 +1849,8 @@ parsePlanString(void)
18201849
return_value = _readAggref();
18211850
else if (length == 7 && strncmp(token, "SUBLINK", length) == 0)
18221851
return_value = _readSubLink();
1852+
else if (length == 11 && strncmp(token, "RELABELTYPE", length) == 0)
1853+
return_value = _readRelabelType();
18231854
else if (length == 3 && strncmp(token, "AGG", length) == 0)
18241855
return_value = _readAgg();
18251856
else if (length == 4 && strncmp(token, "HASH", length) == 0)

0 commit comments

Comments
 (0)