@@ -234,10 +234,10 @@ public RelNode visitParse(Parse node, CalcitePlanContext context) {
234
234
RexNode sourceField = rexVisitor .analyze (node .getSourceField (), context );
235
235
ParseMethod parseMethod = node .getParseMethod ();
236
236
java .util .Map <String , Literal > arguments = node .getArguments ();
237
- assert arguments .isEmpty ();
238
237
String pattern = (String ) node .getPattern ().getValue ();
239
238
List <String > groupCandidates =
240
239
ParseUtils .getNamedGroupCandidates (parseMethod , pattern , arguments );
240
+ List <RexNode > overrideFields = new ArrayList <>();
241
241
List <RexNode > newFields =
242
242
groupCandidates .stream ()
243
243
.map (
@@ -247,84 +247,69 @@ public RelNode visitParse(Parse node, CalcitePlanContext context) {
247
247
SqlLibraryOperators .REGEXP_EXTRACT ,
248
248
sourceField ,
249
249
context .rexBuilder .makeLiteral (pattern ));
250
+ if (originalFieldNames .contains (group )) {
251
+ overrideFields .add (context .relBuilder .field (group ));
252
+ }
250
253
return context .relBuilder .alias (regexp , group );
251
254
})
252
255
.toList ();
253
256
context .relBuilder .projectPlus (newFields );
254
-
255
- List <String > overriding = new ArrayList <>(groupCandidates );
256
- overriding .retainAll (originalFieldNames );
257
- renameForOverriding (overriding , context );
258
-
257
+ context .relBuilder .projectExcept (overrideFields );
258
+ renameForOverriding (groupCandidates , context );
259
259
return context .relBuilder .peek ();
260
260
}
261
261
262
- private static void renameForOverriding (List <String > overriding , CalcitePlanContext context ) {
263
- if (!overriding .isEmpty ()) {
264
- List <RexNode > toDrop = context .relBuilder .fields (overriding );
265
- context .relBuilder .projectExcept (toDrop );
266
- // the overriding field in Calcite will add a numeric suffix, for example:
267
- // `| eval SAL = SAL + 1` creates a field SAL0 to replace SAL, so we rename it back to SAL,
268
- // or query `| eval SAL=SAL + 1 | where exists [ source=DEPT | where emp.SAL=HISAL ]` fails.
269
- List <String > newNames =
270
- context .relBuilder .peek ().getRowType ().getFieldNames ().stream ()
271
- .map (
272
- cur -> {
273
- String noNumericSuffix = cur .replaceAll ("\\ d" , "" );
274
- if (overriding .contains (noNumericSuffix )) {
275
- return noNumericSuffix ;
276
- } else {
277
- return cur ;
278
- }
279
- })
280
- .toList ();
281
- context .relBuilder .rename (newNames );
282
- }
283
- }
284
-
285
262
@ Override
286
263
public RelNode visitEval (Eval node , CalcitePlanContext context ) {
287
264
visitChildren (node , context );
288
265
List <String > originalFieldNames = context .relBuilder .peek ().getRowType ().getFieldNames ();
289
- List <RexNode > evalList =
290
- node .getExpressionList ().stream ()
291
- .map (
292
- expr -> {
293
- boolean containsSubqueryExpression = containsSubqueryExpression (expr );
294
- final Holder <@ Nullable RexCorrelVariable > v = Holder .empty ();
295
- if (containsSubqueryExpression ) {
296
- context .relBuilder .variable (v ::set );
297
- context .pushCorrelVar (v .get ());
298
- }
299
- RexNode eval = rexVisitor .analyze (expr , context );
300
- if (containsSubqueryExpression ) {
301
- // RelBuilder.projectPlus doesn't have a parameter with variablesSet:
302
- // projectPlus(Iterable<CorrelationId> variablesSet, RexNode... nodes)
303
- context .relBuilder .project (
304
- Iterables .concat (context .relBuilder .fields (), ImmutableList .of (eval )),
305
- ImmutableList .of (),
306
- false ,
307
- ImmutableList .of (v .get ().id ));
308
- context .popCorrelVar ();
309
- } else {
310
- context .relBuilder .projectPlus (eval );
311
- }
312
- return eval ;
313
- })
314
- .toList ();
315
- // Overriding the existing field if the alias has the same name with original field name.
316
- List <String > overriding =
317
- evalList .stream ()
318
- .filter (expr -> expr .getKind () == AS )
319
- .map (
320
- expr ->
321
- ((RexLiteral ) ((RexCall ) expr ).getOperands ().get (1 )).getValueAs (String .class ))
322
- .collect (Collectors .toList ());
323
- overriding .retainAll (originalFieldNames );
324
- renameForOverriding (overriding , context );
266
+ node .getExpressionList ()
267
+ .forEach (
268
+ expr -> {
269
+ boolean containsSubqueryExpression = containsSubqueryExpression (expr );
270
+ final Holder <@ Nullable RexCorrelVariable > v = Holder .empty ();
271
+ if (containsSubqueryExpression ) {
272
+ context .relBuilder .variable (v ::set );
273
+ context .pushCorrelVar (v .get ());
274
+ }
275
+ RexNode eval = rexVisitor .analyze (expr , context );
276
+ if (containsSubqueryExpression ) {
277
+ // RelBuilder.projectPlus doesn't have a parameter with variablesSet:
278
+ // projectPlus(Iterable<CorrelationId> variablesSet, RexNode... nodes)
279
+ context .relBuilder .project (
280
+ Iterables .concat (context .relBuilder .fields (), ImmutableList .of (eval )),
281
+ ImmutableList .of (),
282
+ false ,
283
+ ImmutableList .of (v .get ().id ));
284
+ context .popCorrelVar ();
285
+ } else {
286
+ // Overriding the existing field if the alias has the same name with original field
287
+ // name.
288
+ RexNode overrideField = null ;
289
+ String alias =
290
+ ((RexLiteral ) ((RexCall ) eval ).getOperands ().get (1 )).getValueAs (String .class );
291
+ if (originalFieldNames .contains (alias )) {
292
+ overrideField = context .relBuilder .field (alias );
293
+ context .relBuilder .projectPlus (eval );
294
+ context .relBuilder .projectExcept (overrideField );
295
+ renameForOverriding (List .of (alias ), context );
296
+ } else {
297
+ context .relBuilder .projectPlus (eval );
298
+ }
299
+ }
300
+ });
325
301
return context .relBuilder .peek ();
326
302
}
327
303
304
+ private static void renameForOverriding (List <String > newNames , CalcitePlanContext context ) {
305
+ List <String > originalFieldNames = context .relBuilder .peek ().getRowType ().getFieldNames ();
306
+ int length = originalFieldNames .size ();
307
+ List <String > expectedRenameFields =
308
+ new ArrayList <>(originalFieldNames .subList (0 , length - newNames .size ()));
309
+ expectedRenameFields .addAll (newNames );
310
+ context .relBuilder .rename (expectedRenameFields );
311
+ }
312
+
328
313
@ Override
329
314
public RelNode visitAggregation (Aggregation node , CalcitePlanContext context ) {
330
315
visitChildren (node , context );
0 commit comments