@@ -81,28 +81,8 @@ static Expr *make_distinct_op(ParseState *pstate, List *opname,
81
81
/*
82
82
* transformExpr -
83
83
* 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.
106
86
*/
107
87
Node *
108
88
transformExpr (ParseState * pstate , Node * expr , ParseExprKind exprKind )
@@ -168,48 +148,8 @@ transformExprRecurse(ParseState *pstate, Node *expr)
168
148
break ;
169
149
170
150
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 ;
213
153
214
154
case T_CollateClause :
215
155
result = transformCollateClause (pstate , (CollateClause * ) expr );
@@ -324,37 +264,19 @@ transformExprRecurse(ParseState *pstate, Node *expr)
324
264
result = transformCurrentOfExpr (pstate , (CurrentOfExpr * ) expr );
325
265
break ;
326
266
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 .
330
270
*
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
+ */
353
277
case T_CaseTestExpr :
354
- case T_ArrayExpr :
355
- case T_CoerceToDomain :
356
- case T_CoerceToDomainValue :
357
278
case T_SetToDefault :
279
+ case T_Var :
358
280
{
359
281
result = (Node * ) expr ;
360
282
break ;
@@ -1461,10 +1383,6 @@ transformCaseExpr(ParseState *pstate, CaseExpr *c)
1461
1383
Node * defresult ;
1462
1384
Oid ptype ;
1463
1385
1464
- /* If we already transformed this node, do nothing */
1465
- if (OidIsValid (c -> casetype ))
1466
- return (Node * ) c ;
1467
-
1468
1386
newc = makeNode (CaseExpr );
1469
1387
1470
1388
/* transform the test expression, if any */
@@ -1592,10 +1510,6 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
1592
1510
Query * qtree ;
1593
1511
const char * err ;
1594
1512
1595
- /* If we already transformed this node, do nothing */
1596
- if (IsA (sublink -> subselect , Query ))
1597
- return result ;
1598
-
1599
1513
/*
1600
1514
* Check to see if the sublink is in an invalid place within the query. We
1601
1515
* allow sublinks everywhere in SELECT/INSERT/UPDATE/DELETE, but generally
@@ -1964,10 +1878,6 @@ transformRowExpr(ParseState *pstate, RowExpr *r)
1964
1878
int fnum ;
1965
1879
ListCell * lc ;
1966
1880
1967
- /* If we already transformed this node, do nothing */
1968
- if (OidIsValid (r -> row_typeid ))
1969
- return (Node * ) r ;
1970
-
1971
1881
newr = makeNode (RowExpr );
1972
1882
1973
1883
/* Transform the field expressions */
@@ -2074,10 +1984,6 @@ transformXmlExpr(ParseState *pstate, XmlExpr *x)
2074
1984
ListCell * lc ;
2075
1985
int i ;
2076
1986
2077
- /* If we already transformed this node, do nothing */
2078
- if (OidIsValid (x -> type ))
2079
- return (Node * ) x ;
2080
-
2081
1987
newx = makeNode (XmlExpr );
2082
1988
newx -> op = x -> op ;
2083
1989
if (x -> name )
@@ -2381,14 +2287,51 @@ static Node *
2381
2287
transformTypeCast (ParseState * pstate , TypeCast * tc )
2382
2288
{
2383
2289
Node * result ;
2384
- Node * expr = transformExprRecurse ( pstate , tc -> arg ) ;
2385
- Oid inputType = exprType ( expr ) ;
2290
+ Node * expr ;
2291
+ Oid inputType ;
2386
2292
Oid targetType ;
2387
2293
int32 targetTypmod ;
2388
2294
int location ;
2389
2295
2390
2296
typenameTypeIdAndMod (pstate , tc -> typeName , & targetType , & targetTypmod );
2391
2297
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 );
2392
2335
if (inputType == InvalidOid )
2393
2336
return expr ; /* do nothing if NULL input */
2394
2337
0 commit comments