@ -118,8 +118,7 @@ static Node *transformCurrentOfExpr(ParseState *pstate, CurrentOfExpr *cexpr);
static Node * transformColumnRef ( ParseState * pstate , ColumnRef * cref ) ;
static Node * transformColumnRef ( ParseState * pstate , ColumnRef * cref ) ;
static Node * transformWholeRowRef ( ParseState * pstate , RangeTblEntry * rte ,
static Node * transformWholeRowRef ( ParseState * pstate , RangeTblEntry * rte ,
int location ) ;
int location ) ;
static Node * transformIndirection ( ParseState * pstate , Node * basenode ,
static Node * transformIndirection ( ParseState * pstate , A_Indirection * ind ) ;
List * indirection ) ;
static Node * transformTypeCast ( ParseState * pstate , TypeCast * tc ) ;
static Node * transformTypeCast ( ParseState * pstate , TypeCast * tc ) ;
static Node * transformCollateClause ( ParseState * pstate , CollateClause * c ) ;
static Node * transformCollateClause ( ParseState * pstate , CollateClause * c ) ;
static Node * make_row_comparison_op ( ParseState * pstate , List * opname ,
static Node * make_row_comparison_op ( ParseState * pstate , List * opname ,
@ -192,14 +191,8 @@ transformExprRecurse(ParseState *pstate, Node *expr)
}
}
case T_A_Indirection :
case T_A_Indirection :
{
result = transformIndirection ( pstate , ( A_Indirection * ) expr ) ;
A_Indirection * ind = ( A_Indirection * ) expr ;
break ;
result = transformExprRecurse ( pstate , ind - > arg ) ;
result = transformIndirection ( pstate , result ,
ind - > indirection ) ;
break ;
}
case T_A_ArrayExpr :
case T_A_ArrayExpr :
result = transformArrayExpr ( pstate , ( A_ArrayExpr * ) expr ,
result = transformArrayExpr ( pstate , ( A_ArrayExpr * ) expr ,
@ -439,11 +432,12 @@ unknown_attribute(ParseState *pstate, Node *relref, char *attname,
}
}
static Node *
static Node *
transformIndirection ( ParseState * pstate , Node * basenode , List * indirection )
transformIndirection ( ParseState * pstate , A_Indirection * ind )
{
{
Node * result = basenode ;
Node * last_srf = pstate - > p_last_srf ;
Node * result = transformExprRecurse ( pstate , ind - > arg ) ;
List * subscripts = NIL ;
List * subscripts = NIL ;
int location = exprLocation ( basenode ) ;
int location = exprLocation ( result ) ;
ListCell * i ;
ListCell * i ;
/*
/*
@ -451,7 +445,7 @@ transformIndirection(ParseState *pstate, Node *basenode, List *indirection)
* subscripting . Adjacent A_Indices nodes have to be treated as a single
* subscripting . Adjacent A_Indices nodes have to be treated as a single
* multidimensional subscript operation .
* multidimensional subscript operation .
*/
*/
foreach ( i , indirection )
foreach ( i , ind - > ind irection)
{
{
Node * n = lfirst ( i ) ;
Node * n = lfirst ( i ) ;
@ -484,6 +478,7 @@ transformIndirection(ParseState *pstate, Node *basenode, List *indirection)
newresult = ParseFuncOrColumn ( pstate ,
newresult = ParseFuncOrColumn ( pstate ,
list_make1 ( n ) ,
list_make1 ( n ) ,
list_make1 ( result ) ,
list_make1 ( result ) ,
last_srf ,
NULL ,
NULL ,
location ) ;
location ) ;
if ( newresult = = NULL )
if ( newresult = = NULL )
@ -632,6 +627,7 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
node = ParseFuncOrColumn ( pstate ,
node = ParseFuncOrColumn ( pstate ,
list_make1 ( makeString ( colname ) ) ,
list_make1 ( makeString ( colname ) ) ,
list_make1 ( node ) ,
list_make1 ( node ) ,
pstate - > p_last_srf ,
NULL ,
NULL ,
cref - > location ) ;
cref - > location ) ;
}
}
@ -678,6 +674,7 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
node = ParseFuncOrColumn ( pstate ,
node = ParseFuncOrColumn ( pstate ,
list_make1 ( makeString ( colname ) ) ,
list_make1 ( makeString ( colname ) ) ,
list_make1 ( node ) ,
list_make1 ( node ) ,
pstate - > p_last_srf ,
NULL ,
NULL ,
cref - > location ) ;
cref - > location ) ;
}
}
@ -737,6 +734,7 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
node = ParseFuncOrColumn ( pstate ,
node = ParseFuncOrColumn ( pstate ,
list_make1 ( makeString ( colname ) ) ,
list_make1 ( makeString ( colname ) ) ,
list_make1 ( node ) ,
list_make1 ( node ) ,
pstate - > p_last_srf ,
NULL ,
NULL ,
cref - > location ) ;
cref - > location ) ;
}
}
@ -927,6 +925,8 @@ transformAExprOp(ParseState *pstate, A_Expr *a)
else
else
{
{
/* Ordinary scalar operator */
/* Ordinary scalar operator */
Node * last_srf = pstate - > p_last_srf ;
lexpr = transformExprRecurse ( pstate , lexpr ) ;
lexpr = transformExprRecurse ( pstate , lexpr ) ;
rexpr = transformExprRecurse ( pstate , rexpr ) ;
rexpr = transformExprRecurse ( pstate , rexpr ) ;
@ -934,6 +934,7 @@ transformAExprOp(ParseState *pstate, A_Expr *a)
a - > name ,
a - > name ,
lexpr ,
lexpr ,
rexpr ,
rexpr ,
last_srf ,
a - > location ) ;
a - > location ) ;
}
}
@ -1053,6 +1054,7 @@ transformAExprNullIf(ParseState *pstate, A_Expr *a)
a - > name ,
a - > name ,
lexpr ,
lexpr ,
rexpr ,
rexpr ,
pstate - > p_last_srf ,
a - > location ) ;
a - > location ) ;
/*
/*
@ -1063,6 +1065,12 @@ transformAExprNullIf(ParseState *pstate, A_Expr *a)
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg ( " NULLIF requires = operator to yield boolean " ) ,
errmsg ( " NULLIF requires = operator to yield boolean " ) ,
parser_errposition ( pstate , a - > location ) ) ) ;
parser_errposition ( pstate , a - > location ) ) ) ;
if ( result - > opretset )
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
/* translator: %s is name of a SQL construct, eg NULLIF */
errmsg ( " %s must not return a set " , " NULLIF " ) ,
parser_errposition ( pstate , a - > location ) ) ) ;
/*
/*
* . . . but the NullIfExpr will yield the first operand ' s type .
* . . . but the NullIfExpr will yield the first operand ' s type .
@ -1266,6 +1274,7 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
a - > name ,
a - > name ,
copyObject ( lexpr ) ,
copyObject ( lexpr ) ,
rexpr ,
rexpr ,
pstate - > p_last_srf ,
a - > location ) ;
a - > location ) ;
}
}
@ -1430,6 +1439,7 @@ transformBoolExpr(ParseState *pstate, BoolExpr *a)
static Node *
static Node *
transformFuncCall ( ParseState * pstate , FuncCall * fn )
transformFuncCall ( ParseState * pstate , FuncCall * fn )
{
{
Node * last_srf = pstate - > p_last_srf ;
List * targs ;
List * targs ;
ListCell * args ;
ListCell * args ;
@ -1465,6 +1475,7 @@ transformFuncCall(ParseState *pstate, FuncCall *fn)
return ParseFuncOrColumn ( pstate ,
return ParseFuncOrColumn ( pstate ,
fn - > funcname ,
fn - > funcname ,
targs ,
targs ,
last_srf ,
fn ,
fn ,
fn - > location ) ;
fn - > location ) ;
}
}
@ -1619,7 +1630,8 @@ transformMultiAssignRef(ParseState *pstate, MultiAssignRef *maref)
static Node *
static Node *
transformCaseExpr ( ParseState * pstate , CaseExpr * c )
transformCaseExpr ( ParseState * pstate , CaseExpr * c )
{
{
CaseExpr * newc ;
CaseExpr * newc = makeNode ( CaseExpr ) ;
Node * last_srf = pstate - > p_last_srf ;
Node * arg ;
Node * arg ;
CaseTestExpr * placeholder ;
CaseTestExpr * placeholder ;
List * newargs ;
List * newargs ;
@ -1628,8 +1640,6 @@ transformCaseExpr(ParseState *pstate, CaseExpr *c)
Node * defresult ;
Node * defresult ;
Oid ptype ;
Oid ptype ;
newc = makeNode ( CaseExpr ) ;
/* transform the test expression, if any */
/* transform the test expression, if any */
arg = transformExprRecurse ( pstate , ( Node * ) c - > arg ) ;
arg = transformExprRecurse ( pstate , ( Node * ) c - > arg ) ;
@ -1741,6 +1751,17 @@ transformCaseExpr(ParseState *pstate, CaseExpr *c)
" CASE/WHEN " ) ;
" CASE/WHEN " ) ;
}
}
/* if any subexpression contained a SRF, complain */
if ( pstate - > p_last_srf ! = last_srf )
ereport ( ERROR ,
( errcode ( ERRCODE_FEATURE_NOT_SUPPORTED ) ,
/* translator: %s is name of a SQL construct, eg GROUP BY */
errmsg ( " set-returning functions are not allowed in %s " ,
" CASE " ) ,
errhint ( " You might be able to move the set-returning function into a LATERAL FROM item. " ) ,
parser_errposition ( pstate ,
exprLocation ( pstate - > p_last_srf ) ) ) ) ;
newc - > location = c - > location ;
newc - > location = c - > location ;
return ( Node * ) newc ;
return ( Node * ) newc ;
@ -2177,6 +2198,7 @@ static Node *
transformCoalesceExpr ( ParseState * pstate , CoalesceExpr * c )
transformCoalesceExpr ( ParseState * pstate , CoalesceExpr * c )
{
{
CoalesceExpr * newc = makeNode ( CoalesceExpr ) ;
CoalesceExpr * newc = makeNode ( CoalesceExpr ) ;
Node * last_srf = pstate - > p_last_srf ;
List * newargs = NIL ;
List * newargs = NIL ;
List * newcoercedargs = NIL ;
List * newcoercedargs = NIL ;
ListCell * args ;
ListCell * args ;
@ -2205,6 +2227,17 @@ transformCoalesceExpr(ParseState *pstate, CoalesceExpr *c)
newcoercedargs = lappend ( newcoercedargs , newe ) ;
newcoercedargs = lappend ( newcoercedargs , newe ) ;
}
}
/* if any subexpression contained a SRF, complain */
if ( pstate - > p_last_srf ! = last_srf )
ereport ( ERROR ,
( errcode ( ERRCODE_FEATURE_NOT_SUPPORTED ) ,
/* translator: %s is name of a SQL construct, eg GROUP BY */
errmsg ( " set-returning functions are not allowed in %s " ,
" COALESCE " ) ,
errhint ( " You might be able to move the set-returning function into a LATERAL FROM item. " ) ,
parser_errposition ( pstate ,
exprLocation ( pstate - > p_last_srf ) ) ) ) ;
newc - > args = newcoercedargs ;
newc - > args = newcoercedargs ;
newc - > location = c - > location ;
newc - > location = c - > location ;
return ( Node * ) newc ;
return ( Node * ) newc ;
@ -2793,7 +2826,8 @@ make_row_comparison_op(ParseState *pstate, List *opname,
Node * rarg = ( Node * ) lfirst ( r ) ;
Node * rarg = ( Node * ) lfirst ( r ) ;
OpExpr * cmp ;
OpExpr * cmp ;
cmp = castNode ( OpExpr , make_op ( pstate , opname , larg , rarg , location ) ) ;
cmp = castNode ( OpExpr , make_op ( pstate , opname , larg , rarg ,
pstate - > p_last_srf , location ) ) ;
/*
/*
* We don ' t use coerce_to_boolean here because we insist on the
* We don ' t use coerce_to_boolean here because we insist on the
@ -3000,12 +3034,19 @@ make_distinct_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree,
{
{
Expr * result ;
Expr * result ;
result = make_op ( pstate , opname , ltree , rtree , location ) ;
result = make_op ( pstate , opname , ltree , rtree ,
pstate - > p_last_srf , location ) ;
if ( ( ( OpExpr * ) result ) - > opresulttype ! = BOOLOID )
if ( ( ( OpExpr * ) result ) - > opresulttype ! = BOOLOID )
ereport ( ERROR ,
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg ( " IS DISTINCT FROM requires = operator to yield boolean " ) ,
errmsg ( " IS DISTINCT FROM requires = operator to yield boolean " ) ,
parser_errposition ( pstate , location ) ) ) ;
parser_errposition ( pstate , location ) ) ) ;
if ( ( ( OpExpr * ) result ) - > opretset )
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
/* translator: %s is name of a SQL construct, eg NULLIF */
errmsg ( " %s must not return a set " , " IS DISTINCT FROM " ) ,
parser_errposition ( pstate , location ) ) ) ;
/*
/*
* We rely on DistinctExpr and OpExpr being same struct
* We rely on DistinctExpr and OpExpr being same struct