@@ -81,28 +81,8 @@ static Expr *make_distinct_op(ParseState *pstate, List *opname,
8181/*
8282 * transformExpr -
8383 * Analyze and transform expressions. Type checking and type casting is
84- * done here. The optimizer and the executor cannot handle the original
85- * (raw) expressions collected by the parse tree. Hence the transformation
86- * here.
87- *
88- * NOTE: there are various cases in which this routine will get applied to
89- * an already-transformed expression. Some examples:
90- * 1. At least one construct (BETWEEN/AND) puts the same nodes
91- * into two branches of the parse tree; hence, some nodes
92- * are transformed twice.
93- * 2. Another way it can happen is that coercion of an operator or
94- * function argument to the required type (via coerce_type())
95- * can apply transformExpr to an already-transformed subexpression.
96- * An example here is "SELECT count(*) + 1.0 FROM table".
97- * 3. CREATE TABLE t1 (LIKE t2 INCLUDING INDEXES) can pass in
98- * already-transformed index expressions.
99- * While it might be possible to eliminate these cases, the path of
100- * least resistance so far has been to ensure that transformExpr() does
101- * no damage if applied to an already-transformed tree. This is pretty
102- * easy for cases where the transformation replaces one node type with
103- * another, such as A_Const => Const; we just do nothing when handed
104- * a Const. More care is needed for node types that are used as both
105- * input and output of transformExpr; see SubLink for example.
84+ * done here. This processing converts the raw grammar output into
85+ * expression trees with fully determined semantics.
10686 */
10787Node *
10888transformExpr (ParseState * pstate , Node * expr , ParseExprKind exprKind )
@@ -168,48 +148,8 @@ transformExprRecurse(ParseState *pstate, Node *expr)
168148 break ;
169149
170150 case T_TypeCast :
171- {
172- TypeCast * tc = (TypeCast * ) expr ;
173-
174- /*
175- * If the subject of the typecast is an ARRAY[] construct and
176- * the target type is an array type, we invoke
177- * transformArrayExpr() directly so that we can pass down the
178- * type information. This avoids some cases where
179- * transformArrayExpr() might not infer the correct type.
180- */
181- if (IsA (tc -> arg , A_ArrayExpr ))
182- {
183- Oid targetType ;
184- Oid elementType ;
185- int32 targetTypmod ;
186-
187- typenameTypeIdAndMod (pstate , tc -> typeName ,
188- & targetType , & targetTypmod );
189-
190- /*
191- * If target is a domain over array, work with the base
192- * array type here. transformTypeCast below will cast the
193- * array type to the domain. In the usual case that the
194- * target is not a domain, transformTypeCast is a no-op.
195- */
196- targetType = getBaseTypeAndTypmod (targetType ,
197- & targetTypmod );
198- elementType = get_element_type (targetType );
199- if (OidIsValid (elementType ))
200- {
201- tc = copyObject (tc );
202- tc -> arg = transformArrayExpr (pstate ,
203- (A_ArrayExpr * ) tc -> arg ,
204- targetType ,
205- elementType ,
206- targetTypmod );
207- }
208- }
209-
210- result = transformTypeCast (pstate , tc );
211- break ;
212- }
151+ result = transformTypeCast (pstate , (TypeCast * ) expr );
152+ break ;
213153
214154 case T_CollateClause :
215155 result = transformCollateClause (pstate , (CollateClause * ) expr );
@@ -324,37 +264,19 @@ transformExprRecurse(ParseState *pstate, Node *expr)
324264 result = transformCurrentOfExpr (pstate , (CurrentOfExpr * ) expr );
325265 break ;
326266
327- /*********************************************
328- * Quietly accept node types that may be presented when we are
329- * called on an already-transformed tree .
267+ /*
268+ * CaseTestExpr and SetToDefault don't require any processing;
269+ * they are only injected into parse trees in fully-formed state .
330270 *
331- * Do any other node types need to be accepted? For now we are
332- * taking a conservative approach, and only accepting node
333- * types that are demonstrably necessary to accept.
334- *********************************************/
335- case T_Var :
336- case T_Const :
337- case T_Param :
338- case T_Aggref :
339- case T_WindowFunc :
340- case T_ArrayRef :
341- case T_FuncExpr :
342- case T_OpExpr :
343- case T_DistinctExpr :
344- case T_NullIfExpr :
345- case T_ScalarArrayOpExpr :
346- case T_FieldSelect :
347- case T_FieldStore :
348- case T_RelabelType :
349- case T_CoerceViaIO :
350- case T_ArrayCoerceExpr :
351- case T_ConvertRowtypeExpr :
352- case T_CollateExpr :
271+ * Ordinarily we should not see a Var here, but it is convenient
272+ * for transformJoinUsingClause() to create untransformed operator
273+ * trees containing already-transformed Vars. The best
274+ * alternative would be to deconstruct and reconstruct column
275+ * references, which seems expensively pointless. So allow it.
276+ */
353277 case T_CaseTestExpr :
354- case T_ArrayExpr :
355- case T_CoerceToDomain :
356- case T_CoerceToDomainValue :
357278 case T_SetToDefault :
279+ case T_Var :
358280 {
359281 result = (Node * ) expr ;
360282 break ;
@@ -1461,10 +1383,6 @@ transformCaseExpr(ParseState *pstate, CaseExpr *c)
14611383 Node * defresult ;
14621384 Oid ptype ;
14631385
1464- /* If we already transformed this node, do nothing */
1465- if (OidIsValid (c -> casetype ))
1466- return (Node * ) c ;
1467-
14681386 newc = makeNode (CaseExpr );
14691387
14701388 /* transform the test expression, if any */
@@ -1592,10 +1510,6 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
15921510 Query * qtree ;
15931511 const char * err ;
15941512
1595- /* If we already transformed this node, do nothing */
1596- if (IsA (sublink -> subselect , Query ))
1597- return result ;
1598-
15991513 /*
16001514 * Check to see if the sublink is in an invalid place within the query. We
16011515 * allow sublinks everywhere in SELECT/INSERT/UPDATE/DELETE, but generally
@@ -1964,10 +1878,6 @@ transformRowExpr(ParseState *pstate, RowExpr *r)
19641878 int fnum ;
19651879 ListCell * lc ;
19661880
1967- /* If we already transformed this node, do nothing */
1968- if (OidIsValid (r -> row_typeid ))
1969- return (Node * ) r ;
1970-
19711881 newr = makeNode (RowExpr );
19721882
19731883 /* Transform the field expressions */
@@ -2074,10 +1984,6 @@ transformXmlExpr(ParseState *pstate, XmlExpr *x)
20741984 ListCell * lc ;
20751985 int i ;
20761986
2077- /* If we already transformed this node, do nothing */
2078- if (OidIsValid (x -> type ))
2079- return (Node * ) x ;
2080-
20811987 newx = makeNode (XmlExpr );
20821988 newx -> op = x -> op ;
20831989 if (x -> name )
@@ -2381,14 +2287,51 @@ static Node *
23812287transformTypeCast (ParseState * pstate , TypeCast * tc )
23822288{
23832289 Node * result ;
2384- Node * expr = transformExprRecurse ( pstate , tc -> arg ) ;
2385- Oid inputType = exprType ( expr ) ;
2290+ Node * expr ;
2291+ Oid inputType ;
23862292 Oid targetType ;
23872293 int32 targetTypmod ;
23882294 int location ;
23892295
23902296 typenameTypeIdAndMod (pstate , tc -> typeName , & targetType , & targetTypmod );
23912297
2298+ /*
2299+ * If the subject of the typecast is an ARRAY[] construct and the target
2300+ * type is an array type, we invoke transformArrayExpr() directly so that
2301+ * we can pass down the type information. This avoids some cases where
2302+ * transformArrayExpr() might not infer the correct type. Otherwise, just
2303+ * transform the argument normally.
2304+ */
2305+ if (IsA (tc -> arg , A_ArrayExpr ))
2306+ {
2307+ Oid targetBaseType ;
2308+ int32 targetBaseTypmod ;
2309+ Oid elementType ;
2310+
2311+ /*
2312+ * If target is a domain over array, work with the base array type
2313+ * here. Below, we'll cast the array type to the domain. In the
2314+ * usual case that the target is not a domain, the remaining steps
2315+ * will be a no-op.
2316+ */
2317+ targetBaseTypmod = targetTypmod ;
2318+ targetBaseType = getBaseTypeAndTypmod (targetType , & targetBaseTypmod );
2319+ elementType = get_element_type (targetBaseType );
2320+ if (OidIsValid (elementType ))
2321+ {
2322+ expr = transformArrayExpr (pstate ,
2323+ (A_ArrayExpr * ) tc -> arg ,
2324+ targetBaseType ,
2325+ elementType ,
2326+ targetBaseTypmod );
2327+ }
2328+ else
2329+ expr = transformExprRecurse (pstate , tc -> arg );
2330+ }
2331+ else
2332+ expr = transformExprRecurse (pstate , tc -> arg );
2333+
2334+ inputType = exprType (expr );
23922335 if (inputType == InvalidOid )
23932336 return expr ; /* do nothing if NULL input */
23942337
0 commit comments