@ -37,6 +37,7 @@
bool Transform_null_equals = false ;
bool Transform_null_equals = false ;
static Node * transformExprRecurse ( ParseState * pstate , Node * expr ) ;
static Node * transformParamRef ( ParseState * pstate , ParamRef * pref ) ;
static Node * transformParamRef ( ParseState * pstate , ParamRef * pref ) ;
static Node * transformAExprOp ( ParseState * pstate , A_Expr * a ) ;
static Node * transformAExprOp ( ParseState * pstate , A_Expr * a ) ;
static Node * transformAExprAnd ( ParseState * pstate , A_Expr * a ) ;
static Node * transformAExprAnd ( ParseState * pstate , A_Expr * a ) ;
@ -100,9 +101,27 @@ static Expr *make_distinct_op(ParseState *pstate, List *opname,
* input and output of transformExpr ; see SubLink for example .
* input and output of transformExpr ; see SubLink for example .
*/
*/
Node *
Node *
transformExpr ( ParseState * pstate , Node * expr )
transformExpr ( ParseState * pstate , Node * expr , ParseExprKind exprKind )
{
{
Node * result = NULL ;
Node * result ;
ParseExprKind sv_expr_kind ;
/* Save and restore identity of expression type we're parsing */
Assert ( exprKind ! = EXPR_KIND_NONE ) ;
sv_expr_kind = pstate - > p_expr_kind ;
pstate - > p_expr_kind = exprKind ;
result = transformExprRecurse ( pstate , expr ) ;
pstate - > p_expr_kind = sv_expr_kind ;
return result ;
}
static Node *
transformExprRecurse ( ParseState * pstate , Node * expr )
{
Node * result ;
if ( expr = = NULL )
if ( expr = = NULL )
return NULL ;
return NULL ;
@ -133,7 +152,7 @@ transformExpr(ParseState *pstate, Node *expr)
{
{
A_Indirection * ind = ( A_Indirection * ) expr ;
A_Indirection * ind = ( A_Indirection * ) expr ;
result = transformExpr ( pstate , ind - > arg ) ;
result = transformExprRecurse ( pstate , ind - > arg ) ;
result = transformIndirection ( pstate , result ,
result = transformIndirection ( pstate , result ,
ind - > indirection ) ;
ind - > indirection ) ;
break ;
break ;
@ -230,6 +249,8 @@ transformExpr(ParseState *pstate, Node *expr)
break ;
break ;
default :
default :
elog ( ERROR , " unrecognized A_Expr kind: %d " , a - > kind ) ;
elog ( ERROR , " unrecognized A_Expr kind: %d " , a - > kind ) ;
result = NULL ; /* keep compiler quiet */
break ;
}
}
break ;
break ;
}
}
@ -242,7 +263,7 @@ transformExpr(ParseState *pstate, Node *expr)
{
{
NamedArgExpr * na = ( NamedArgExpr * ) expr ;
NamedArgExpr * na = ( NamedArgExpr * ) expr ;
na - > arg = ( Expr * ) transformExpr ( pstate , ( Node * ) na - > arg ) ;
na - > arg = ( Expr * ) transformExprRecurse ( pstate , ( Node * ) na - > arg ) ;
result = expr ;
result = expr ;
break ;
break ;
}
}
@ -279,7 +300,7 @@ transformExpr(ParseState *pstate, Node *expr)
{
{
NullTest * n = ( NullTest * ) expr ;
NullTest * n = ( NullTest * ) expr ;
n - > arg = ( Expr * ) transformExpr ( pstate , ( Node * ) n - > arg ) ;
n - > arg = ( Expr * ) transformExprRecurse ( pstate , ( Node * ) n - > arg ) ;
/* the argument can be any type, so don't coerce it */
/* the argument can be any type, so don't coerce it */
n - > argisrow = type_is_rowtype ( exprType ( ( Node * ) n - > arg ) ) ;
n - > argisrow = type_is_rowtype ( exprType ( ( Node * ) n - > arg ) ) ;
result = expr ;
result = expr ;
@ -334,6 +355,7 @@ transformExpr(ParseState *pstate, Node *expr)
default :
default :
/* should not reach here */
/* should not reach here */
elog ( ERROR , " unrecognized node type: %d " , ( int ) nodeTag ( expr ) ) ;
elog ( ERROR , " unrecognized node type: %d " , ( int ) nodeTag ( expr ) ) ;
result = NULL ; /* keep compiler quiet */
break ;
break ;
}
}
@ -843,7 +865,7 @@ transformAExprOp(ParseState *pstate, A_Expr *a)
else
else
n - > arg = ( Expr * ) lexpr ;
n - > arg = ( Expr * ) lexpr ;
result = transformExpr ( pstate , ( Node * ) n ) ;
result = transformExprRecurse ( pstate , ( Node * ) n ) ;
}
}
else if ( lexpr & & IsA ( lexpr , RowExpr ) & &
else if ( lexpr & & IsA ( lexpr , RowExpr ) & &
rexpr & & IsA ( rexpr , SubLink ) & &
rexpr & & IsA ( rexpr , SubLink ) & &
@ -860,14 +882,14 @@ transformAExprOp(ParseState *pstate, A_Expr *a)
s - > testexpr = lexpr ;
s - > testexpr = lexpr ;
s - > operName = a - > name ;
s - > operName = a - > name ;
s - > location = a - > location ;
s - > location = a - > location ;
result = transformExpr ( pstate , ( Node * ) s ) ;
result = transformExprRecurse ( pstate , ( Node * ) s ) ;
}
}
else if ( lexpr & & IsA ( lexpr , RowExpr ) & &
else if ( lexpr & & IsA ( lexpr , RowExpr ) & &
rexpr & & IsA ( rexpr , RowExpr ) )
rexpr & & IsA ( rexpr , RowExpr ) )
{
{
/* "row op row" */
/* "row op row" */
lexpr = transformExpr ( pstate , lexpr ) ;
lexpr = transformExprRecurse ( pstate , lexpr ) ;
rexpr = transformExpr ( pstate , rexpr ) ;
rexpr = transformExprRecurse ( pstate , rexpr ) ;
Assert ( IsA ( lexpr , RowExpr ) ) ;
Assert ( IsA ( lexpr , RowExpr ) ) ;
Assert ( IsA ( rexpr , RowExpr ) ) ;
Assert ( IsA ( rexpr , RowExpr ) ) ;
@ -880,8 +902,8 @@ transformAExprOp(ParseState *pstate, A_Expr *a)
else
else
{
{
/* Ordinary scalar operator */
/* Ordinary scalar operator */
lexpr = transformExpr ( pstate , lexpr ) ;
lexpr = transformExprRecurse ( pstate , lexpr ) ;
rexpr = transformExpr ( pstate , rexpr ) ;
rexpr = transformExprRecurse ( pstate , rexpr ) ;
result = ( Node * ) make_op ( pstate ,
result = ( Node * ) make_op ( pstate ,
a - > name ,
a - > name ,
@ -896,8 +918,8 @@ transformAExprOp(ParseState *pstate, A_Expr *a)
static Node *
static Node *
transformAExprAnd ( ParseState * pstate , A_Expr * a )
transformAExprAnd ( ParseState * pstate , A_Expr * a )
{
{
Node * lexpr = transformExpr ( pstate , a - > lexpr ) ;
Node * lexpr = transformExprRecurse ( pstate , a - > lexpr ) ;
Node * rexpr = transformExpr ( pstate , a - > rexpr ) ;
Node * rexpr = transformExprRecurse ( pstate , a - > rexpr ) ;
lexpr = coerce_to_boolean ( pstate , lexpr , " AND " ) ;
lexpr = coerce_to_boolean ( pstate , lexpr , " AND " ) ;
rexpr = coerce_to_boolean ( pstate , rexpr , " AND " ) ;
rexpr = coerce_to_boolean ( pstate , rexpr , " AND " ) ;
@ -910,8 +932,8 @@ transformAExprAnd(ParseState *pstate, A_Expr *a)
static Node *
static Node *
transformAExprOr ( ParseState * pstate , A_Expr * a )
transformAExprOr ( ParseState * pstate , A_Expr * a )
{
{
Node * lexpr = transformExpr ( pstate , a - > lexpr ) ;
Node * lexpr = transformExprRecurse ( pstate , a - > lexpr ) ;
Node * rexpr = transformExpr ( pstate , a - > rexpr ) ;
Node * rexpr = transformExprRecurse ( pstate , a - > rexpr ) ;
lexpr = coerce_to_boolean ( pstate , lexpr , " OR " ) ;
lexpr = coerce_to_boolean ( pstate , lexpr , " OR " ) ;
rexpr = coerce_to_boolean ( pstate , rexpr , " OR " ) ;
rexpr = coerce_to_boolean ( pstate , rexpr , " OR " ) ;
@ -924,7 +946,7 @@ transformAExprOr(ParseState *pstate, A_Expr *a)
static Node *
static Node *
transformAExprNot ( ParseState * pstate , A_Expr * a )
transformAExprNot ( ParseState * pstate , A_Expr * a )
{
{
Node * rexpr = transformExpr ( pstate , a - > rexpr ) ;
Node * rexpr = transformExprRecurse ( pstate , a - > rexpr ) ;
rexpr = coerce_to_boolean ( pstate , rexpr , " NOT " ) ;
rexpr = coerce_to_boolean ( pstate , rexpr , " NOT " ) ;
@ -936,8 +958,8 @@ transformAExprNot(ParseState *pstate, A_Expr *a)
static Node *
static Node *
transformAExprOpAny ( ParseState * pstate , A_Expr * a )
transformAExprOpAny ( ParseState * pstate , A_Expr * a )
{
{
Node * lexpr = transformExpr ( pstate , a - > lexpr ) ;
Node * lexpr = transformExprRecurse ( pstate , a - > lexpr ) ;
Node * rexpr = transformExpr ( pstate , a - > rexpr ) ;
Node * rexpr = transformExprRecurse ( pstate , a - > rexpr ) ;
return ( Node * ) make_scalar_array_op ( pstate ,
return ( Node * ) make_scalar_array_op ( pstate ,
a - > name ,
a - > name ,
@ -950,8 +972,8 @@ transformAExprOpAny(ParseState *pstate, A_Expr *a)
static Node *
static Node *
transformAExprOpAll ( ParseState * pstate , A_Expr * a )
transformAExprOpAll ( ParseState * pstate , A_Expr * a )
{
{
Node * lexpr = transformExpr ( pstate , a - > lexpr ) ;
Node * lexpr = transformExprRecurse ( pstate , a - > lexpr ) ;
Node * rexpr = transformExpr ( pstate , a - > rexpr ) ;
Node * rexpr = transformExprRecurse ( pstate , a - > rexpr ) ;
return ( Node * ) make_scalar_array_op ( pstate ,
return ( Node * ) make_scalar_array_op ( pstate ,
a - > name ,
a - > name ,
@ -964,8 +986,8 @@ transformAExprOpAll(ParseState *pstate, A_Expr *a)
static Node *
static Node *
transformAExprDistinct ( ParseState * pstate , A_Expr * a )
transformAExprDistinct ( ParseState * pstate , A_Expr * a )
{
{
Node * lexpr = transformExpr ( pstate , a - > lexpr ) ;
Node * lexpr = transformExprRecurse ( pstate , a - > lexpr ) ;
Node * rexpr = transformExpr ( pstate , a - > rexpr ) ;
Node * rexpr = transformExprRecurse ( pstate , a - > rexpr ) ;
if ( lexpr & & IsA ( lexpr , RowExpr ) & &
if ( lexpr & & IsA ( lexpr , RowExpr ) & &
rexpr & & IsA ( rexpr , RowExpr ) )
rexpr & & IsA ( rexpr , RowExpr ) )
@ -990,8 +1012,8 @@ transformAExprDistinct(ParseState *pstate, A_Expr *a)
static Node *
static Node *
transformAExprNullIf ( ParseState * pstate , A_Expr * a )
transformAExprNullIf ( ParseState * pstate , A_Expr * a )
{
{
Node * lexpr = transformExpr ( pstate , a - > lexpr ) ;
Node * lexpr = transformExprRecurse ( pstate , a - > lexpr ) ;
Node * rexpr = transformExpr ( pstate , a - > rexpr ) ;
Node * rexpr = transformExprRecurse ( pstate , a - > rexpr ) ;
OpExpr * result ;
OpExpr * result ;
result = ( OpExpr * ) make_op ( pstate ,
result = ( OpExpr * ) make_op ( pstate ,
@ -1029,7 +1051,7 @@ transformAExprOf(ParseState *pstate, A_Expr *a)
* Checking an expression for match to a list of type names . Will result
* Checking an expression for match to a list of type names . Will result
* in a boolean constant node .
* in a boolean constant node .
*/
*/
Node * lexpr = transformExpr ( pstate , a - > lexpr ) ;
Node * lexpr = transformExprRecurse ( pstate , a - > lexpr ) ;
Const * result ;
Const * result ;
ListCell * telem ;
ListCell * telem ;
Oid ltype ,
Oid ltype ,
@ -1092,12 +1114,12 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
* First step : transform all the inputs , and detect whether any are
* First step : transform all the inputs , and detect whether any are
* RowExprs or contain Vars .
* RowExprs or contain Vars .
*/
*/
lexpr = transformExpr ( pstate , a - > lexpr ) ;
lexpr = transformExprRecurse ( pstate , a - > lexpr ) ;
haveRowExpr = ( lexpr & & IsA ( lexpr , RowExpr ) ) ;
haveRowExpr = ( lexpr & & IsA ( lexpr , RowExpr ) ) ;
rexprs = rvars = rnonvars = NIL ;
rexprs = rvars = rnonvars = NIL ;
foreach ( l , ( List * ) a - > rexpr )
foreach ( l , ( List * ) a - > rexpr )
{
{
Node * rexpr = transformExpr ( pstate , lfirst ( l ) ) ;
Node * rexpr = transformExprRecurse ( pstate , lfirst ( l ) ) ;
haveRowExpr | = ( rexpr & & IsA ( rexpr , RowExpr ) ) ;
haveRowExpr | = ( rexpr & & IsA ( rexpr , RowExpr ) ) ;
rexprs = lappend ( rexprs , rexpr ) ;
rexprs = lappend ( rexprs , rexpr ) ;
@ -1222,7 +1244,7 @@ transformFuncCall(ParseState *pstate, FuncCall *fn)
targs = NIL ;
targs = NIL ;
foreach ( args , fn - > args )
foreach ( args , fn - > args )
{
{
targs = lappend ( targs , transformExpr ( pstate ,
targs = lappend ( targs , transformExprRecurse ( pstate ,
( Node * ) lfirst ( args ) ) ) ;
( Node * ) lfirst ( args ) ) ) ;
}
}
@ -1258,7 +1280,7 @@ transformCaseExpr(ParseState *pstate, CaseExpr *c)
newc = makeNode ( CaseExpr ) ;
newc = makeNode ( CaseExpr ) ;
/* transform the test expression, if any */
/* transform the test expression, if any */
arg = transformExpr ( pstate , ( Node * ) c - > arg ) ;
arg = transformExprRecurse ( pstate , ( Node * ) c - > arg ) ;
/* generate placeholder for test expression */
/* generate placeholder for test expression */
if ( arg )
if ( arg )
@ -1311,14 +1333,14 @@ transformCaseExpr(ParseState *pstate, CaseExpr *c)
warg ,
warg ,
w - > location ) ;
w - > location ) ;
}
}
neww - > expr = ( Expr * ) transformExpr ( pstate , warg ) ;
neww - > expr = ( Expr * ) transformExprRecurse ( pstate , warg ) ;
neww - > expr = ( Expr * ) coerce_to_boolean ( pstate ,
neww - > expr = ( Expr * ) coerce_to_boolean ( pstate ,
( Node * ) neww - > expr ,
( Node * ) neww - > expr ,
" CASE/WHEN " ) ;
" CASE/WHEN " ) ;
warg = ( Node * ) w - > result ;
warg = ( Node * ) w - > result ;
neww - > result = ( Expr * ) transformExpr ( pstate , warg ) ;
neww - > result = ( Expr * ) transformExprRecurse ( pstate , warg ) ;
neww - > location = w - > location ;
neww - > location = w - > location ;
newargs = lappend ( newargs , neww ) ;
newargs = lappend ( newargs , neww ) ;
@ -1337,7 +1359,7 @@ transformCaseExpr(ParseState *pstate, CaseExpr *c)
n - > location = - 1 ;
n - > location = - 1 ;
defresult = ( Node * ) n ;
defresult = ( Node * ) n ;
}
}
newc - > defresult = ( Expr * ) transformExpr ( pstate , defresult ) ;
newc - > defresult = ( Expr * ) transformExprRecurse ( pstate , defresult ) ;
/*
/*
* Note : default result is considered the most significant type in
* Note : default result is considered the most significant type in
@ -1380,12 +1402,92 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
{
{
Node * result = ( Node * ) sublink ;
Node * result = ( Node * ) sublink ;
Query * qtree ;
Query * qtree ;
const char * err ;
/* If we already transformed this node, do nothing */
/* If we already transformed this node, do nothing */
if ( IsA ( sublink - > subselect , Query ) )
if ( IsA ( sublink - > subselect , Query ) )
return result ;
return result ;
/*
* Check to see if the sublink is in an invalid place within the query .
* We allow sublinks everywhere in SELECT / INSERT / UPDATE / DELETE , but
* generally not in utility statements .
*/
err = NULL ;
switch ( pstate - > p_expr_kind )
{
case EXPR_KIND_NONE :
Assert ( false ) ; /* can't happen */
break ;
case EXPR_KIND_OTHER :
/* Accept sublink here; caller must throw error if wanted */
break ;
case EXPR_KIND_JOIN_ON :
case EXPR_KIND_JOIN_USING :
case EXPR_KIND_FROM_SUBSELECT :
case EXPR_KIND_FROM_FUNCTION :
case EXPR_KIND_WHERE :
case EXPR_KIND_HAVING :
case EXPR_KIND_WINDOW_PARTITION :
case EXPR_KIND_WINDOW_ORDER :
case EXPR_KIND_WINDOW_FRAME_RANGE :
case EXPR_KIND_WINDOW_FRAME_ROWS :
case EXPR_KIND_SELECT_TARGET :
case EXPR_KIND_INSERT_TARGET :
case EXPR_KIND_UPDATE_SOURCE :
case EXPR_KIND_UPDATE_TARGET :
case EXPR_KIND_GROUP_BY :
case EXPR_KIND_ORDER_BY :
case EXPR_KIND_DISTINCT_ON :
case EXPR_KIND_LIMIT :
case EXPR_KIND_OFFSET :
case EXPR_KIND_RETURNING :
case EXPR_KIND_VALUES :
/* okay */
break ;
case EXPR_KIND_CHECK_CONSTRAINT :
case EXPR_KIND_DOMAIN_CHECK :
err = _ ( " cannot use subquery in CHECK constraint " ) ;
break ;
case EXPR_KIND_COLUMN_DEFAULT :
case EXPR_KIND_FUNCTION_DEFAULT :
err = _ ( " cannot use subquery in DEFAULT expression " ) ;
break ;
case EXPR_KIND_INDEX_EXPRESSION :
err = _ ( " cannot use subquery in index expression " ) ;
break ;
case EXPR_KIND_INDEX_PREDICATE :
err = _ ( " cannot use subquery in index predicate " ) ;
break ;
case EXPR_KIND_ALTER_COL_TRANSFORM :
err = _ ( " cannot use subquery in transform expression " ) ;
break ;
case EXPR_KIND_EXECUTE_PARAMETER :
err = _ ( " cannot use subquery in EXECUTE parameter " ) ;
break ;
case EXPR_KIND_TRIGGER_WHEN :
err = _ ( " cannot use subquery in trigger WHEN condition " ) ;
break ;
/*
* There is intentionally no default : case here , so that the
* compiler will warn if we add a new ParseExprKind without
* extending this switch . If we do see an unrecognized value at
* runtime , the behavior will be the same as for EXPR_KIND_OTHER ,
* which is sane anyway .
*/
}
if ( err )
ereport ( ERROR ,
( errcode ( ERRCODE_FEATURE_NOT_SUPPORTED ) ,
errmsg_internal ( " %s " , err ) ,
parser_errposition ( pstate , sublink - > location ) ) ) ;
pstate - > p_hasSubLinks = true ;
pstate - > p_hasSubLinks = true ;
/*
* OK , let ' s transform the sub - SELECT .
*/
qtree = parse_sub_analyze ( sublink - > subselect , pstate , NULL , false ) ;
qtree = parse_sub_analyze ( sublink - > subselect , pstate , NULL , false ) ;
/*
/*
@ -1450,7 +1552,7 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
/*
/*
* Transform lefthand expression , and convert to a list
* Transform lefthand expression , and convert to a list
*/
*/
lefthand = transformExpr ( pstate , sublink - > testexpr ) ;
lefthand = transformExprRecurse ( pstate , sublink - > testexpr ) ;
if ( lefthand & & IsA ( lefthand , RowExpr ) )
if ( lefthand & & IsA ( lefthand , RowExpr ) )
left_list = ( ( RowExpr * ) lefthand ) - > args ;
left_list = ( ( RowExpr * ) lefthand ) - > args ;
else
else
@ -1557,7 +1659,7 @@ transformArrayExpr(ParseState *pstate, A_ArrayExpr *a,
}
}
else
else
{
{
newe = transformExpr ( pstate , e ) ;
newe = transformExprRecurse ( pstate , e ) ;
/*
/*
* Check for sub - array expressions , if we haven ' t already found
* Check for sub - array expressions , if we haven ' t already found
@ -1679,7 +1781,7 @@ transformRowExpr(ParseState *pstate, RowExpr *r)
ListCell * lc ;
ListCell * lc ;
/* Transform the field expressions */
/* Transform the field expressions */
newr - > args = transformExpressionList ( pstate , r - > args ) ;
newr - > args = transformExpressionList ( pstate , r - > args , pstate - > p_expr_kind ) ;
/* Barring later casting, we consider the type RECORD */
/* Barring later casting, we consider the type RECORD */
newr - > row_typeid = RECORDOID ;
newr - > row_typeid = RECORDOID ;
@ -1712,7 +1814,7 @@ transformCoalesceExpr(ParseState *pstate, CoalesceExpr *c)
Node * e = ( Node * ) lfirst ( args ) ;
Node * e = ( Node * ) lfirst ( args ) ;
Node * newe ;
Node * newe ;
newe = transformExpr ( pstate , e ) ;
newe = transformExprRecurse ( pstate , e ) ;
newargs = lappend ( newargs , newe ) ;
newargs = lappend ( newargs , newe ) ;
}
}
@ -1751,7 +1853,7 @@ transformMinMaxExpr(ParseState *pstate, MinMaxExpr *m)
Node * e = ( Node * ) lfirst ( args ) ;
Node * e = ( Node * ) lfirst ( args ) ;
Node * newe ;
Node * newe ;
newe = transformExpr ( pstate , e ) ;
newe = transformExprRecurse ( pstate , e ) ;
newargs = lappend ( newargs , newe ) ;
newargs = lappend ( newargs , newe ) ;
}
}
@ -1805,7 +1907,7 @@ transformXmlExpr(ParseState *pstate, XmlExpr *x)
Assert ( IsA ( r , ResTarget ) ) ;
Assert ( IsA ( r , ResTarget ) ) ;
expr = transformExpr ( pstate , r - > val ) ;
expr = transformExprRecurse ( pstate , r - > val ) ;
if ( r - > name )
if ( r - > name )
argname = map_sql_identifier_to_xml_name ( r - > name , false , false ) ;
argname = map_sql_identifier_to_xml_name ( r - > name , false , false ) ;
@ -1851,7 +1953,7 @@ transformXmlExpr(ParseState *pstate, XmlExpr *x)
Node * e = ( Node * ) lfirst ( lc ) ;
Node * e = ( Node * ) lfirst ( lc ) ;
Node * newe ;
Node * newe ;
newe = transformExpr ( pstate , e ) ;
newe = transformExprRecurse ( pstate , e ) ;
switch ( x - > op )
switch ( x - > op )
{
{
case IS_XMLCONCAT :
case IS_XMLCONCAT :
@ -1914,7 +2016,7 @@ transformXmlSerialize(ParseState *pstate, XmlSerialize *xs)
xexpr = makeNode ( XmlExpr ) ;
xexpr = makeNode ( XmlExpr ) ;
xexpr - > op = IS_XMLSERIALIZE ;
xexpr - > op = IS_XMLSERIALIZE ;
xexpr - > args = list_make1 ( coerce_to_specific_type ( pstate ,
xexpr - > args = list_make1 ( coerce_to_specific_type ( pstate ,
transformExpr ( pstate , xs - > expr ) ,
transformExprRecurse ( pstate , xs - > expr ) ,
XMLOID ,
XMLOID ,
" XMLSERIALIZE " ) ) ;
" XMLSERIALIZE " ) ) ;
@ -1977,7 +2079,7 @@ transformBooleanTest(ParseState *pstate, BooleanTest *b)
clausename = NULL ; /* keep compiler quiet */
clausename = NULL ; /* keep compiler quiet */
}
}
b - > arg = ( Expr * ) transformExpr ( pstate , ( Node * ) b - > arg ) ;
b - > arg = ( Expr * ) transformExprRecurse ( pstate , ( Node * ) b - > arg ) ;
b - > arg = ( Expr * ) coerce_to_boolean ( pstate ,
b - > arg = ( Expr * ) coerce_to_boolean ( pstate ,
( Node * ) b - > arg ,
( Node * ) b - > arg ,
@ -2082,7 +2184,7 @@ static Node *
transformTypeCast ( ParseState * pstate , TypeCast * tc )
transformTypeCast ( ParseState * pstate , TypeCast * tc )
{
{
Node * result ;
Node * result ;
Node * expr = transformExpr ( pstate , tc - > arg ) ;
Node * expr = transformExprRecurse ( pstate , tc - > arg ) ;
Oid inputType = exprType ( expr ) ;
Oid inputType = exprType ( expr ) ;
Oid targetType ;
Oid targetType ;
int32 targetTypmod ;
int32 targetTypmod ;
@ -2130,7 +2232,7 @@ transformCollateClause(ParseState *pstate, CollateClause *c)
Oid argtype ;
Oid argtype ;
newc = makeNode ( CollateExpr ) ;
newc = makeNode ( CollateExpr ) ;
newc - > arg = ( Expr * ) transformExpr ( pstate , c - > arg ) ;
newc - > arg = ( Expr * ) transformExprRecurse ( pstate , c - > arg ) ;
argtype = exprType ( ( Node * ) newc - > arg ) ;
argtype = exprType ( ( Node * ) newc - > arg ) ;
@ -2433,3 +2535,87 @@ make_distinct_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree,
return result ;
return result ;
}
}
/*
* Produce a string identifying an expression by kind .
*
* Note : when practical , use a simple SQL keyword for the result . If that
* doesn ' t work well , check call sites to see whether custom error message
* strings are required .
*/
const char *
ParseExprKindName ( ParseExprKind exprKind )
{
switch ( exprKind )
{
case EXPR_KIND_NONE :
return " invalid expression context " ;
case EXPR_KIND_OTHER :
return " extension expression " ;
case EXPR_KIND_JOIN_ON :
return " JOIN/ON " ;
case EXPR_KIND_JOIN_USING :
return " JOIN/USING " ;
case EXPR_KIND_FROM_SUBSELECT :
return " sub-SELECT in FROM " ;
case EXPR_KIND_FROM_FUNCTION :
return " function in FROM " ;
case EXPR_KIND_WHERE :
return " WHERE " ;
case EXPR_KIND_HAVING :
return " HAVING " ;
case EXPR_KIND_WINDOW_PARTITION :
return " window PARTITION BY " ;
case EXPR_KIND_WINDOW_ORDER :
return " window ORDER BY " ;
case EXPR_KIND_WINDOW_FRAME_RANGE :
return " window RANGE " ;
case EXPR_KIND_WINDOW_FRAME_ROWS :
return " window ROWS " ;
case EXPR_KIND_SELECT_TARGET :
return " SELECT " ;
case EXPR_KIND_INSERT_TARGET :
return " INSERT " ;
case EXPR_KIND_UPDATE_SOURCE :
case EXPR_KIND_UPDATE_TARGET :
return " UPDATE " ;
case EXPR_KIND_GROUP_BY :
return " GROUP BY " ;
case EXPR_KIND_ORDER_BY :
return " ORDER BY " ;
case EXPR_KIND_DISTINCT_ON :
return " DISTINCT ON " ;
case EXPR_KIND_LIMIT :
return " LIMIT " ;
case EXPR_KIND_OFFSET :
return " OFFSET " ;
case EXPR_KIND_RETURNING :
return " RETURNING " ;
case EXPR_KIND_VALUES :
return " VALUES " ;
case EXPR_KIND_CHECK_CONSTRAINT :
case EXPR_KIND_DOMAIN_CHECK :
return " CHECK " ;
case EXPR_KIND_COLUMN_DEFAULT :
case EXPR_KIND_FUNCTION_DEFAULT :
return " DEFAULT " ;
case EXPR_KIND_INDEX_EXPRESSION :
return " index expression " ;
case EXPR_KIND_INDEX_PREDICATE :
return " index predicate " ;
case EXPR_KIND_ALTER_COL_TRANSFORM :
return " USING " ;
case EXPR_KIND_EXECUTE_PARAMETER :
return " EXECUTE " ;
case EXPR_KIND_TRIGGER_WHEN :
return " WHEN " ;
/*
* There is intentionally no default : case here , so that the
* compiler will warn if we add a new ParseExprKind without
* extending this switch . If we do see an unrecognized value at
* runtime , we ' ll fall through to the " unrecognized " return .
*/
}
return " unrecognized expression kind " ;
}