HqlQueryRenderer.java
/*
* Copyright 2022-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.jpa.repository.query;
import static org.springframework.data.jpa.repository.query.QueryTokens.*;
import java.util.ArrayList;
import java.util.List;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.RuleContext;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.RuleNode;
import org.antlr.v4.runtime.tree.TerminalNode;
import org.springframework.data.jpa.repository.query.QueryRenderer.QueryRendererBuilder;
import org.springframework.util.CollectionUtils;
/**
* An ANTLR {@link org.antlr.v4.runtime.tree.ParseTreeVisitor} that renders an HQL query without making any changes.
*
* @author Greg Turnquist
* @author Christoph Strobl
* @author Oscar Fanchin
* @author Mark Paluch
* @author TaeHyun Kang
* @since 3.1
*/
@SuppressWarnings({ "ConstantConditions", "DuplicatedCode", "UnreachableCode" })
class HqlQueryRenderer extends HqlBaseVisitor<QueryTokenStream> {
/**
* Is this AST tree a {@literal subquery}?
*
* @return {@literal true} is the query is a subquery; {@literal false} otherwise.
*/
static boolean isSubquery(ParserRuleContext ctx) {
while (ctx != null) {
if (ctx instanceof HqlParser.SubqueryContext || ctx instanceof HqlParser.CteContext) {
return true;
}
if (ctx instanceof HqlParser.SelectStatementContext ||
ctx instanceof HqlParser.InsertStatementContext ||
ctx instanceof HqlParser.DeleteStatementContext ||
ctx instanceof HqlParser.UpdateStatementContext) {
return false;
}
ctx = ctx.getParent();
}
return false;
}
/**
* Is this AST tree a {@literal set} query that has been added through {@literal UNION|INTERSECT|EXCEPT}?
*
* @return {@literal true} is the query is a set query; {@literal false} otherwise.
*/
static boolean isSetQuery(ParserRuleContext ctx) {
while (ctx != null) {
if (ctx instanceof HqlParser.OrderedQueryContext
&& ctx.getParent() instanceof HqlParser.QueryExpressionContext qec) {
if (qec.orderedQuery().indexOf(ctx) != 0) {
return true;
}
}
ctx = ctx.getParent();
}
return false;
}
@Override
public QueryTokenStream visitStart(HqlParser.StartContext ctx) {
return visit(ctx.ql_statement());
}
@Override
public QueryTokenStream visitWithClause(HqlParser.WithClauseContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(QueryTokens.expression(ctx.WITH()));
builder.append(QueryTokenStream.concatExpressions(ctx.cte(), this::visit, TOKEN_COMMA));
return builder;
}
@Override
public QueryTokenStream visitCte(HqlParser.CteContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.appendExpression(visit(ctx.identifier()));
builder.append(TOKEN_AS);
if (ctx.NOT() != null) {
builder.append(QueryTokens.expression(ctx.NOT()));
}
if (ctx.MATERIALIZED() != null) {
builder.append(TOKEN_MATERIALIZED);
}
builder.append(TOKEN_OPEN_PAREN);
builder.appendInline(visit(ctx.queryExpression()));
builder.append(TOKEN_CLOSE_PAREN);
if (ctx.searchClause() != null) {
builder.appendExpression(visit(ctx.searchClause()));
}
if (ctx.cycleClause() != null) {
builder.appendExpression(visit(ctx.cycleClause()));
}
return builder;
}
@Override
public QueryTokenStream visitCteAttributes(HqlParser.CteAttributesContext ctx) {
return QueryTokenStream.concat(ctx.identifier(), this::visit, TOKEN_COMMA);
}
@Override
public QueryTokenStream visitSearchSpecifications(HqlParser.SearchSpecificationsContext ctx) {
return QueryTokenStream.concat(ctx.searchSpecification(), this::visit, TOKEN_COMMA);
}
@Override
public QueryTokenStream visitOrderedQuery(HqlParser.OrderedQueryContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
if (ctx.query() != null) {
builder.append(visit(ctx.query()));
} else if (ctx.queryExpression() != null) {
builder.append(TOKEN_OPEN_PAREN);
builder.append(visit(ctx.queryExpression()));
builder.append(TOKEN_CLOSE_PAREN);
}
if (ctx.queryOrder() != null) {
builder.append(visit(ctx.queryOrder()));
}
if (ctx.limitClause() != null) {
builder.appendExpression(visit(ctx.limitClause()));
}
if (ctx.offsetClause() != null) {
builder.appendExpression(visit(ctx.offsetClause()));
}
if (ctx.fetchClause() != null) {
builder.appendExpression(visit(ctx.fetchClause()));
}
return builder;
}
@Override
public QueryTokenStream visitFromClause(HqlParser.FromClauseContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(QueryTokens.expression(ctx.FROM()));
builder.appendExpression(QueryTokenStream.concat(ctx.entityWithJoins(), this::visit, TOKEN_COMMA));
return builder;
}
@Override
public QueryTokenStream visitEntityWithJoins(HqlParser.EntityWithJoinsContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.appendInline(visit(ctx.fromRoot()));
builder.appendInline(QueryTokenStream.concat(ctx.joinSpecifier(), this::visit, EMPTY_TOKEN));
return builder;
}
@Override
public QueryTokenStream visitRootSubquery(HqlParser.RootSubqueryContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
if (ctx.LATERAL() != null) {
builder.append(QueryTokens.expression(ctx.LATERAL()));
}
builder.appendExpression(QueryTokenStream.group(visit(ctx.subquery())));
if (ctx.variable() != null) {
builder.appendExpression(visit(ctx.variable()));
}
return builder;
}
@Override
public QueryTokenStream visitSimpleSetReturningFunction(HqlParser.SimpleSetReturningFunctionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(visit(ctx.identifier()));
builder.append(TOKEN_OPEN_PAREN);
if (ctx.genericFunctionArguments() != null) {
builder.append(visit(ctx.genericFunctionArguments()));
}
builder.append(TOKEN_CLOSE_PAREN);
return builder;
}
@Override
public QueryTokenStream visitJoin(HqlParser.JoinContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(TOKEN_SPACE);
builder.append(visit(ctx.joinType()));
builder.append(QueryTokens.expression(ctx.JOIN()));
if (ctx.FETCH() != null) {
builder.append(QueryTokens.expression(ctx.FETCH()));
}
builder.append(visit(ctx.joinTarget()));
if (ctx.joinRestriction() != null) {
builder.appendExpression(visit(ctx.joinRestriction()));
}
return builder;
}
@Override
public QueryTokenStream visitJoinSubquery(HqlParser.JoinSubqueryContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
if (ctx.LATERAL() != null) {
builder.append(QueryTokens.expression(ctx.LATERAL()));
}
builder.append(QueryTokenStream.group(visit(ctx.subquery())));
if (ctx.variable() != null) {
builder.appendExpression(visit(ctx.variable()));
}
return builder;
}
@Override
public QueryTokenStream visitSetClause(HqlParser.SetClauseContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(QueryTokens.expression(ctx.SET()));
return builder.append(QueryTokenStream.concat(ctx.assignment(), this::visit, TOKEN_COMMA));
}
@Override
public QueryTokenStream visitAssignment(HqlParser.AssignmentContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(visit(ctx.simplePath()));
builder.append(TOKEN_EQUALS);
builder.append(visit(ctx.expressionOrPredicate()));
return builder;
}
@Override
public QueryTokenStream visitTargetFields(HqlParser.TargetFieldsContext ctx) {
return QueryTokenStream.group(QueryTokenStream.concat(ctx.simplePath(), this::visit, TOKEN_COMMA));
}
@Override
public QueryTokenStream visitValuesList(HqlParser.ValuesListContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(QueryTokens.expression(ctx.VALUES()));
builder.append(QueryTokenStream.concat(ctx.values(), this::visit, TOKEN_COMMA));
return builder;
}
@Override
public QueryTokenStream visitValues(HqlParser.ValuesContext ctx) {
return QueryTokenStream.group(QueryTokenStream.concat(ctx.expression(), this::visit, TOKEN_COMMA));
}
@Override
public QueryTokenStream visitConflictTarget(HqlParser.ConflictTargetContext ctx) {
if (ctx.identifier() != null) {
return QueryTokenStream.concatExpressions(ctx.children, this::visit);
}
return QueryTokenStream.group(QueryTokenStream.concat(ctx.simplePath(), this::visit, TOKEN_COMMA));
}
@Override
public QueryTokenStream visitInstantiation(HqlParser.InstantiationContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(QueryTokens.expression(ctx.NEW()));
builder.append(visit(ctx.instantiationTarget()));
builder.append(QueryTokenStream.group(visit(ctx.instantiationArguments())));
return builder;
}
public QueryTokenStream visitSelectionList(HqlParser.SelectionListContext ctx) {
return QueryTokenStream.concat(ctx.selection(), this::visit, TOKEN_COMMA);
}
@Override
public QueryTokenStream visitMapEntrySelection(HqlParser.MapEntrySelectionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(QueryTokens.expression(ctx.ENTRY()));
builder.append(QueryTokenStream.group(visit(ctx.path())));
return builder;
}
@Override
public QueryTokenStream visitJpaSelectObjectSyntax(HqlParser.JpaSelectObjectSyntaxContext ctx) {
return QueryTokenStream.ofFunction(ctx.OBJECT(), visit(ctx.identifier()));
}
@Override
public QueryTokenStream visitWhereClause(HqlParser.WhereClauseContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(QueryTokens.expression(ctx.WHERE()));
builder.append(QueryTokenStream.concatExpressions(ctx.predicate(), this::visit, TOKEN_COMMA));
return builder;
}
@Override
public QueryTokenStream visitJpaCollectionJoin(HqlParser.JpaCollectionJoinContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(TOKEN_COMMA);
builder.append(QueryTokens.token(ctx.IN()));
builder.append(QueryTokenStream.group(visit(ctx.path())));
if (ctx.variable() != null) {
builder.appendExpression(visit(ctx.variable()));
}
return builder;
}
@Override
public QueryTokenStream visitGroupByClause(HqlParser.GroupByClauseContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(QueryTokens.expression(ctx.GROUP()));
builder.append(QueryTokens.expression(ctx.BY()));
builder.append(QueryTokenStream.concat(ctx.groupedItem(), this::visit, TOKEN_COMMA));
return builder;
}
@Override
public QueryTokenStream visitOrderByClause(HqlParser.OrderByClauseContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(QueryTokens.expression(ctx.ORDER()));
builder.append(QueryTokens.expression(ctx.BY()));
builder.appendExpression(QueryTokenStream.concat(ctx.sortedItem(), this::visit, TOKEN_COMMA));
return builder;
}
@Override
public QueryTokenStream visitHavingClause(HqlParser.HavingClauseContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(QueryTokens.expression(ctx.HAVING()));
builder.appendExpression(QueryTokenStream.concat(ctx.predicate(), this::visit, TOKEN_COMMA));
return builder;
}
@Override
public QueryTokenStream visitLocalDateTimeLiteral(HqlParser.LocalDateTimeLiteralContext ctx) {
if (ctx.DATETIME() == null) {
return QueryTokenStream.group(visit(ctx.localDateTime()));
}
return QueryTokenStream.concatExpressions(ctx.children, this::visit);
}
@Override
public QueryTokenStream visitZonedDateTimeLiteral(HqlParser.ZonedDateTimeLiteralContext ctx) {
if (ctx.DATETIME() == null) {
return QueryTokenStream.group(visit(ctx.zonedDateTime()));
}
return QueryTokenStream.concatExpressions(ctx.children, this::visit);
}
@Override
public QueryTokenStream visitOffsetDateTimeLiteral(HqlParser.OffsetDateTimeLiteralContext ctx) {
if (ctx.DATETIME() == null) {
return QueryTokenStream.group(visit(ctx.offsetDateTime()));
}
return QueryTokenStream.concatExpressions(ctx.children, this::visit);
}
@Override
public QueryTokenStream visitDateLiteral(HqlParser.DateLiteralContext ctx) {
if (ctx.DATE() == null) {
return QueryTokenStream.group(visit(ctx.date()));
}
return QueryTokenStream.concatExpressions(ctx.children, this::visit);
}
@Override
public QueryTokenStream visitTimeLiteral(HqlParser.TimeLiteralContext ctx) {
if (ctx.TIME() == null) {
return QueryTokenStream.group(visit(ctx.time()));
}
return QueryTokenStream.concatExpressions(ctx.children, this::visit);
}
@Override
public QueryTokenStream visitOffsetDateTime(HqlParser.OffsetDateTimeContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.appendExpression(visit(ctx.date()));
builder.appendInline(visit(ctx.time()));
builder.appendInline(visit(ctx.offset()));
return builder;
}
@Override
public QueryTokenStream visitOffsetDateTimeWithMinutes(HqlParser.OffsetDateTimeWithMinutesContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.appendExpression(visit(ctx.date()));
builder.appendInline(visit(ctx.time()));
builder.appendInline(visit(ctx.offsetWithMinutes()));
return builder;
}
@Override
public QueryTokenStream visitJdbcTimestampLiteral(HqlParser.JdbcTimestampLiteralContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(TOKEN_OPEN_BRACE);
builder.append(QueryTokens.token("ts"));
builder.appendInline(visit(ctx.dateTime() != null ? ctx.dateTime() : ctx.genericTemporalLiteralText()));
builder.append(QueryTokens.TOKEN_CLOSE_BRACE);
return builder;
}
@Override
public QueryTokenStream visitJdbcDateLiteral(HqlParser.JdbcDateLiteralContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(TOKEN_OPEN_BRACE);
builder.append(QueryTokens.token("d"));
builder.append(visit(ctx.date() != null ? ctx.date() : ctx.genericTemporalLiteralText()));
builder.append(QueryTokens.TOKEN_CLOSE_BRACE);
return builder;
}
@Override
public QueryTokenStream visitJdbcTimeLiteral(HqlParser.JdbcTimeLiteralContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(TOKEN_OPEN_BRACE);
builder.append(QueryTokens.token("t"));
builder.append(visit(ctx.time() != null ? ctx.time() : ctx.genericTemporalLiteralText()));
builder.append(QueryTokens.TOKEN_CLOSE_BRACE);
return builder;
}
@Override
public QueryTokenStream visitArrayLiteral(HqlParser.ArrayLiteralContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(TOKEN_OPEN_SQUARE_BRACKET);
builder.append(QueryTokenStream.concat(ctx.expression(), this::visit, TOKEN_COMMA));
builder.append(TOKEN_CLOSE_SQUARE_BRACKET);
return builder;
}
@Override
public QueryTokenStream visitGeneralizedLiteral(HqlParser.GeneralizedLiteralContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(TOKEN_OPEN_PAREN);
builder.append(visit(ctx.generalizedLiteralType()));
builder.append(TOKEN_COLON);
builder.append(visit(ctx.generalizedLiteralText()));
builder.append(TOKEN_CLOSE_PAREN);
return builder;
}
@Override
public QueryTokenStream visitDate(HqlParser.DateContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(visit(ctx.year()));
builder.append(TOKEN_DASH);
builder.append(visit(ctx.month()));
builder.append(TOKEN_DASH);
builder.append(visit(ctx.day()));
return builder;
}
@Override
public QueryTokenStream visitTime(HqlParser.TimeContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(visit(ctx.hour()));
builder.append(TOKEN_COLON);
builder.append(visit(ctx.minute()));
if (ctx.second() != null) {
builder.append(TOKEN_COLON);
builder.append(visit(ctx.second()));
}
return builder;
}
@Override
public QueryTokenStream visitOffset(HqlParser.OffsetContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
if (ctx.MINUS() != null) {
builder.append(QueryTokens.token(ctx.MINUS()));
} else if (ctx.PLUS() != null) {
builder.append(QueryTokens.token(ctx.PLUS()));
}
builder.append(visit(ctx.hour()));
if (ctx.minute() != null) {
builder.append(TOKEN_COLON);
builder.append(visit(ctx.minute()));
}
return builder;
}
@Override
public QueryTokenStream visitOffsetWithMinutes(HqlParser.OffsetWithMinutesContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
if (ctx.MINUS() != null) {
builder.append(QueryTokens.token(ctx.MINUS()));
} else if (ctx.PLUS() != null) {
builder.append(QueryTokens.token(ctx.PLUS()));
}
builder.append(visit(ctx.hour()));
builder.append(TOKEN_COLON);
builder.append(visit(ctx.minute()));
return builder;
}
@Override
public QueryTokenStream visitBinaryLiteral(HqlParser.BinaryLiteralContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
if (ctx.BINARY_LITERAL() != null) {
builder.append(QueryTokens.expression(ctx.BINARY_LITERAL()));
} else if (ctx.HEX_LITERAL() != null) {
builder.append(TOKEN_OPEN_BRACE);
builder.append(QueryTokenStream.concat(ctx.HEX_LITERAL(), QueryTokens::token, TOKEN_COMMA));
builder.append(TOKEN_CLOSE_BRACE);
}
return builder;
}
@Override
public QueryTokenStream visitTupleExpression(HqlParser.TupleExpressionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(TOKEN_OPEN_PAREN);
builder.append(QueryTokenStream.concat(ctx.expressionOrPredicate(), this::visit, TOKEN_COMMA));
builder.append(TOKEN_CLOSE_PAREN);
return builder;
}
@Override
public QueryTokenStream visitHqlConcatenationExpression(HqlParser.HqlConcatenationExpressionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.appendInline(visit(ctx.expression(0)));
builder.append(TOKEN_DOUBLE_PIPE);
builder.append(visit(ctx.expression(1)));
return builder;
}
@Override
public QueryTokenStream visitGroupedExpression(HqlParser.GroupedExpressionContext ctx) {
return QueryTokenStream.group(visit(ctx.expression()));
}
@Override
public QueryTokenStream visitSignedNumericLiteral(HqlParser.SignedNumericLiteralContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(QueryTokens.token(ctx.op));
builder.append(visit(ctx.numericLiteral()));
return builder;
}
@Override
public QueryTokenStream visitSubqueryExpression(HqlParser.SubqueryExpressionContext ctx) {
return QueryTokenStream.group(visit(ctx.subquery()));
}
@Override
public QueryTokenStream visitSignedExpression(HqlParser.SignedExpressionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(QueryTokens.token(ctx.op));
builder.appendInline(visit(ctx.expression()));
return builder;
}
@Override
public QueryTokenStream visitSyntacticPathExpression(HqlParser.SyntacticPathExpressionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.appendInline(visit(ctx.syntacticDomainPath()));
if (ctx.pathContinuation() != null) {
builder.appendInline(visit(ctx.pathContinuation()));
}
return builder;
}
@Override
public QueryTokenStream visitPathContinuation(HqlParser.PathContinuationContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(TOKEN_DOT);
builder.append(visit(ctx.simplePath()));
return builder;
}
@Override
public QueryTokenStream visitEntityTypeReference(HqlParser.EntityTypeReferenceContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
if (ctx.path() != null) {
builder.appendInline(visit(ctx.path()));
}
if (ctx.parameter() != null) {
builder.appendInline(visit(ctx.parameter()));
}
return QueryTokenStream.ofFunction(ctx.TYPE(), builder);
}
@Override
public QueryTokenStream visitEntityIdReference(HqlParser.EntityIdReferenceContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(QueryTokens.token(ctx.ID()));
builder.append(TOKEN_OPEN_PAREN);
builder.appendInline(visit(ctx.path()));
builder.append(TOKEN_CLOSE_PAREN);
if (ctx.pathContinuation() != null) {
builder.appendInline(visit(ctx.pathContinuation()));
}
return builder;
}
@Override
public QueryTokenStream visitEntityVersionReference(HqlParser.EntityVersionReferenceContext ctx) {
return QueryTokenStream.ofFunction(ctx.VERSION(), visit(ctx.path()));
}
@Override
public QueryTokenStream visitEntityNaturalIdReference(HqlParser.EntityNaturalIdReferenceContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(QueryTokens.token(ctx.NATURALID()));
builder.append(TOKEN_OPEN_PAREN);
builder.appendInline(visit(ctx.path()));
builder.append(TOKEN_CLOSE_PAREN);
if (ctx.pathContinuation() != null) {
builder.appendInline(visit(ctx.pathContinuation()));
}
return builder;
}
@Override
public QueryTokenStream visitSyntacticDomainPath(HqlParser.SyntacticDomainPathContext ctx) {
if (ctx.treatedNavigablePath() != null) {
return visit(ctx.treatedNavigablePath());
}
if (ctx.collectionValueNavigablePath() != null) {
return visit(ctx.collectionValueNavigablePath());
}
if (ctx.mapKeyNavigablePath() != null) {
return visit(ctx.mapKeyNavigablePath());
}
if (ctx.toOneFkReference() != null) {
return visit(ctx.toOneFkReference());
}
if (ctx.function() != null) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(visit(ctx.function()));
if (ctx.indexedPathAccessFragment() != null) {
builder.append(visit(ctx.indexedPathAccessFragment()));
}
if (ctx.slicedPathAccessFragment() != null) {
builder.append(visit(ctx.slicedPathAccessFragment()));
}
if (ctx.pathContinuation() != null) {
builder.append(visit(ctx.pathContinuation()));
}
return builder;
}
if (ctx.indexedPathAccessFragment() != null) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(visit(ctx.simplePath()));
builder.append(visit(ctx.indexedPathAccessFragment()));
return builder;
}
if (ctx.slicedPathAccessFragment() != null) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(visit(ctx.simplePath()));
builder.append(visit(ctx.slicedPathAccessFragment()));
return builder;
}
return QueryRenderer.empty();
}
@Override
public QueryTokenStream visitSlicedPathAccessFragment(HqlParser.SlicedPathAccessFragmentContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(TOKEN_OPEN_SQUARE_BRACKET);
builder.appendInline(visit(ctx.expression(0)));
builder.append(TOKEN_COLON);
builder.appendInline(visit(ctx.expression(1)));
builder.append(TOKEN_CLOSE_SQUARE_BRACKET);
return builder;
}
@Override
public QueryTokenStream visitSubstringFunction(HqlParser.SubstringFunctionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
if (ctx.FROM() == null) {
builder.appendInline(visit(ctx.expression()));
builder.append(TOKEN_COMMA);
} else {
builder.appendExpression(visit(ctx.expression()));
builder.append(QueryTokens.expression(ctx.FROM()));
}
if (ctx.substringFunctionLengthArgument() != null) {
if (ctx.FOR() == null) {
builder.appendInline(visit(ctx.substringFunctionStartArgument()));
builder.append(TOKEN_COMMA);
} else {
builder.appendExpression(visit(ctx.substringFunctionStartArgument()));
builder.append(QueryTokens.expression(ctx.FOR()));
}
builder.append(visit(ctx.substringFunctionLengthArgument()));
} else {
builder.appendExpression(visit(ctx.substringFunctionStartArgument()));
}
return QueryTokenStream.ofFunction(ctx.SUBSTRING(), builder);
}
@Override
public QueryTokenStream visitPadFunction(HqlParser.PadFunctionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.appendExpression(visit(ctx.expression()));
builder.append(QueryTokens.expression(ctx.WITH()));
builder.appendExpression(visit(ctx.padLength()));
if (ctx.padCharacter() != null) {
builder.appendExpression(visit(ctx.padSpecification()));
builder.appendExpression(visit(ctx.padCharacter()));
} else {
builder.appendExpression(visit(ctx.padSpecification()));
}
return QueryTokenStream.ofFunction(ctx.PAD(), builder);
}
@Override
public QueryTokenStream visitPositionFunction(HqlParser.PositionFunctionContext ctx) {
QueryRendererBuilder nested = QueryRenderer.builder();
nested.appendExpression(visit(ctx.positionFunctionPatternArgument()));
nested.append(QueryTokens.expression(ctx.IN()));
nested.append(visit(ctx.positionFunctionStringArgument()));
return QueryTokenStream.ofFunction(ctx.POSITION(), nested);
}
@Override
public QueryTokenStream visitOverlayFunction(HqlParser.OverlayFunctionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(QueryTokens.token(ctx.OVERLAY()));
builder.append(TOKEN_OPEN_PAREN);
builder.appendExpression(visit(ctx.overlayFunctionStringArgument()));
builder.append(QueryTokens.expression(ctx.PLACING()));
builder.append(visit(ctx.overlayFunctionReplacementArgument()));
builder.append(QueryTokens.expression(ctx.FROM()));
builder.append(visit(ctx.overlayFunctionStartArgument()));
if (ctx.overlayFunctionLengthArgument() != null) {
builder.append(QueryTokens.expression(ctx.FOR()));
builder.append(visit(ctx.overlayFunctionLengthArgument()));
}
builder.append(TOKEN_CLOSE_PAREN);
return builder;
}
@Override
public QueryTokenStream visitCurrentDateFunction(HqlParser.CurrentDateFunctionContext ctx) {
if (ctx.CURRENT_DATE() != null) {
return QueryTokenStream.ofFunction(ctx.CURRENT_DATE(), QueryTokenStream.empty());
}
return QueryTokenStream.concatExpressions(ctx.children, this::visit);
}
@Override
public QueryTokenStream visitCurrentTimeFunction(HqlParser.CurrentTimeFunctionContext ctx) {
if (ctx.CURRENT_TIME() != null) {
return QueryTokenStream.ofFunction(ctx.CURRENT_TIME(), QueryTokenStream.empty());
}
return QueryTokenStream.concatExpressions(ctx.children, this::visit);
}
@Override
public QueryTokenStream visitCurrentTimestampFunction(HqlParser.CurrentTimestampFunctionContext ctx) {
if (ctx.CURRENT_TIMESTAMP() != null) {
return QueryTokenStream.ofFunction(ctx.CURRENT_TIMESTAMP(), QueryTokenStream.empty());
}
return QueryTokenStream.concatExpressions(ctx.children, this::visit);
}
@Override
public QueryTokenStream visitInstantFunction(HqlParser.InstantFunctionContext ctx) {
if (ctx.CURRENT_INSTANT() != null) {
return QueryTokenStream.ofFunction(ctx.CURRENT_INSTANT(), QueryTokenStream.empty());
}
return QueryTokenStream.concatExpressions(ctx.children, this::visit);
}
@Override
public QueryTokenStream visitLocalDateTimeFunction(HqlParser.LocalDateTimeFunctionContext ctx) {
if (ctx.LOCAL_DATETIME() != null) {
return QueryTokenStream.ofFunction(ctx.LOCAL_DATETIME(), QueryTokenStream.empty());
}
return QueryTokenStream.concatExpressions(ctx.children, this::visit);
}
@Override
public QueryTokenStream visitOffsetDateTimeFunction(HqlParser.OffsetDateTimeFunctionContext ctx) {
if (ctx.OFFSET_DATETIME() != null) {
return QueryTokenStream.ofFunction(ctx.OFFSET_DATETIME(), QueryTokenStream.empty());
}
return QueryTokenStream.concatExpressions(ctx.children, this::visit);
}
@Override
public QueryTokenStream visitLocalDateFunction(HqlParser.LocalDateFunctionContext ctx) {
if (ctx.LOCAL_DATE() != null) {
return QueryTokenStream.ofFunction(ctx.LOCAL_DATE(), QueryTokenStream.empty());
}
return QueryTokenStream.concatExpressions(ctx.children, this::visit);
}
@Override
public QueryTokenStream visitLocalTimeFunction(HqlParser.LocalTimeFunctionContext ctx) {
if (ctx.LOCAL_TIME() != null) {
return QueryTokenStream.ofFunction(ctx.LOCAL_TIME(), QueryTokenStream.empty());
}
return QueryTokenStream.concatExpressions(ctx.children, this::visit);
}
@Override
public QueryTokenStream visitFormatFunction(HqlParser.FormatFunctionContext ctx) {
QueryRendererBuilder args = QueryRenderer.builder();
args.appendExpression(visit(ctx.expression()));
args.append(QueryTokens.expression(ctx.AS()));
args.appendExpression(visit(ctx.format()));
return QueryTokenStream.ofFunction(ctx.FORMAT(), args);
}
@Override
public QueryTokenStream visitCollateFunction(HqlParser.CollateFunctionContext ctx) {
QueryRendererBuilder args = QueryRenderer.builder();
args.appendExpression(visit(ctx.expression()));
args.append(QueryTokens.expression(ctx.AS()));
args.appendExpression(visit(ctx.collation()));
return QueryTokenStream.ofFunction(ctx.COLLATE(), args);
}
@Override
public QueryTokenStream visitCube(HqlParser.CubeContext ctx) {
return QueryTokenStream.ofFunction(ctx.CUBE(),
QueryTokenStream.concat(ctx.expressionOrPredicate(), this::visit, TOKEN_COMMA));
}
@Override
public QueryTokenStream visitRollup(HqlParser.RollupContext ctx) {
return QueryTokenStream.ofFunction(ctx.ROLLUP(),
QueryTokenStream.concat(ctx.expressionOrPredicate(), this::visit, TOKEN_COMMA));
}
@Override
public QueryTokenStream visitTruncFunction(HqlParser.TruncFunctionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
if (ctx.TRUNC() != null) {
builder.append(QueryTokens.token(ctx.TRUNC()));
} else {
builder.append(QueryTokens.token(ctx.TRUNCATE()));
}
builder.append(TOKEN_OPEN_PAREN);
if (ctx.datetimeField() != null) {
builder.append(visit(ctx.expression(0)));
builder.append(TOKEN_COMMA);
builder.append(visit(ctx.datetimeField()));
} else {
builder.append(QueryTokenStream.concat(ctx.expression(), this::visit, TOKEN_COMMA));
}
builder.append(TOKEN_CLOSE_PAREN);
return builder;
}
@Override
public QueryTokenStream visitJpaNonstandardFunction(HqlParser.JpaNonstandardFunctionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(QueryTokens.token(ctx.FUNCTION()));
builder.append(TOKEN_OPEN_PAREN);
QueryRendererBuilder nested = QueryRenderer.builder();
nested.appendInline(visit(ctx.jpaNonstandardFunctionName()));
if (ctx.castTarget() != null) {
nested.append(QueryTokens.expression(ctx.AS()));
nested.append(visit(ctx.castTarget()));
}
if (ctx.genericFunctionArguments() != null) {
nested.append(TOKEN_COMMA);
nested.appendInline(visit(ctx.genericFunctionArguments()));
}
builder.appendInline(nested);
builder.append(TOKEN_CLOSE_PAREN);
return builder;
}
@Override
public QueryTokenStream visitColumnFunction(HqlParser.ColumnFunctionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(QueryTokens.token(ctx.COLUMN()));
builder.append(TOKEN_OPEN_PAREN);
QueryRendererBuilder nested = QueryRenderer.builder();
nested.appendInline(visit(ctx.path()));
nested.append(TOKEN_DOT);
nested.appendExpression(visit(ctx.jpaNonstandardFunctionName()));
if (ctx.castTarget() != null) {
nested.append(QueryTokens.expression(ctx.AS()));
nested.appendExpression(visit(ctx.jpaNonstandardFunctionName()));
}
builder.appendInline(nested);
builder.append(TOKEN_CLOSE_PAREN);
return builder;
}
@Override
public QueryTokenStream visitGenericFunctionArguments(HqlParser.GenericFunctionArgumentsContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
if (ctx.DISTINCT() != null) {
builder.append(QueryTokens.expression(ctx.DISTINCT()));
}
if (ctx.datetimeField() != null) {
builder.append(visit(ctx.datetimeField()));
builder.append(TOKEN_COMMA);
}
builder.append(QueryTokenStream.concat(ctx.expressionOrPredicate(), this::visit, TOKEN_COMMA));
return builder;
}
@Override
public QueryTokenStream visitCollectionSizeFunction(HqlParser.CollectionSizeFunctionContext ctx) {
return QueryTokenStream.ofFunction(ctx.SIZE(), visit(ctx.path()));
}
@Override
public QueryTokenStream visitElementAggregateFunction(HqlParser.ElementAggregateFunctionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
if (ctx.MAXELEMENT() != null || ctx.MINELEMENT() != null) {
builder.append(QueryTokens.token(ctx.MAXELEMENT() != null ? ctx.MAXELEMENT() : ctx.MINELEMENT()));
builder.append(TOKEN_OPEN_PAREN);
builder.append(visit(ctx.path()));
builder.append(TOKEN_CLOSE_PAREN);
} else {
if (ctx.MAX() != null) {
builder.append(QueryTokens.token(ctx.MAX()));
}
if (ctx.MIN() != null) {
builder.append(QueryTokens.token(ctx.MIN()));
}
if (ctx.SUM() != null) {
builder.append(QueryTokens.token(ctx.SUM()));
}
if (ctx.AVG() != null) {
builder.append(QueryTokens.token(ctx.AVG()));
}
builder.append(TOKEN_OPEN_PAREN);
builder.append(visit(ctx.elementsValuesQuantifier()));
builder.append(TOKEN_OPEN_PAREN);
if (ctx.path() != null) {
builder.append(visit(ctx.path()));
}
builder.append(TOKEN_CLOSE_PAREN);
builder.append(TOKEN_CLOSE_PAREN);
}
return builder;
}
@Override
public QueryTokenStream visitIndexAggregateFunction(HqlParser.IndexAggregateFunctionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
if (ctx.MAXINDEX() != null || ctx.MININDEX() != null) {
builder.append(QueryTokens.token(ctx.MAXINDEX() != null ? ctx.MAXINDEX() : ctx.MININDEX()));
builder.append(TOKEN_OPEN_PAREN);
builder.append(visit(ctx.path()));
builder.append(TOKEN_CLOSE_PAREN);
} else {
if (ctx.MAX() != null) {
builder.append(QueryTokens.token(ctx.MAX()));
}
if (ctx.MIN() != null) {
builder.append(QueryTokens.token(ctx.MIN()));
}
if (ctx.SUM() != null) {
builder.append(QueryTokens.token(ctx.SUM()));
}
if (ctx.AVG() != null) {
builder.append(QueryTokens.token(ctx.AVG()));
}
builder.append(TOKEN_OPEN_PAREN);
builder.append(visit(ctx.indicesKeysQuantifier()));
builder.append(TOKEN_OPEN_PAREN);
if (ctx.path() != null) {
builder.append(visit(ctx.path()));
}
builder.append(TOKEN_CLOSE_PAREN);
builder.append(TOKEN_CLOSE_PAREN);
}
return builder;
}
@Override
public QueryTokenStream visitCollectionFunctionMisuse(HqlParser.CollectionFunctionMisuseContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(
visit(ctx.elementsValuesQuantifier() != null ? ctx.elementsValuesQuantifier() : ctx.indicesKeysQuantifier()));
builder.append(TOKEN_OPEN_PAREN);
builder.append(visit(ctx.path()));
builder.append(TOKEN_CLOSE_PAREN);
return builder;
}
@Override
public QueryTokenStream visitListaggFunction(HqlParser.ListaggFunctionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(QueryTokens.token(ctx.LISTAGG()));
builder.append(TOKEN_OPEN_PAREN);
QueryRendererBuilder nested = QueryRenderer.builder();
if (ctx.DISTINCT() != null) {
builder.append(QueryTokens.expression(ctx.DISTINCT()));
}
builder.appendInline(visit(ctx.expressionOrPredicate(0)));
builder.append(TOKEN_COMMA);
builder.appendInline(visit(ctx.expressionOrPredicate(1)));
if (ctx.onOverflowClause() != null) {
builder.appendExpression(visit(ctx.onOverflowClause()));
}
builder.appendInline(nested);
builder.append(TOKEN_CLOSE_PAREN);
if (ctx.withinGroupClause() != null) {
builder.appendExpression(visit(ctx.withinGroupClause()));
}
if (ctx.filterClause() != null) {
builder.appendExpression(visit(ctx.filterClause()));
}
if (ctx.overClause() != null) {
builder.appendExpression(visit(ctx.overClause()));
}
return builder;
}
@Override
public QueryTokenStream visitWithinGroupClause(HqlParser.WithinGroupClauseContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(QueryTokens.expression(ctx.WITHIN()));
builder.append(QueryTokens.expression(ctx.GROUP()));
builder.append(TOKEN_OPEN_PAREN);
builder.appendInline(visit(ctx.orderByClause()));
builder.append(TOKEN_CLOSE_PAREN);
return builder;
}
@Override
public QueryTokenStream visitJsonArrayFunction(HqlParser.JsonArrayFunctionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.appendExpression(QueryTokenStream.concat(ctx.expressionOrPredicate(), this::visit, TOKEN_COMMA));
if (ctx.jsonNullClause() != null) {
builder.appendExpression(visit(ctx.jsonNullClause()));
}
return QueryTokenStream.ofFunction(ctx.JSON_ARRAY(), builder);
}
@Override
public QueryTokenStream visitJsonExistsFunction(HqlParser.JsonExistsFunctionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.appendExpression(QueryTokenStream.concat(ctx.expression(), this::visit, TOKEN_COMMA));
if (ctx.jsonPassingClause() != null) {
builder.appendExpression(visit(ctx.jsonPassingClause()));
}
if (ctx.jsonExistsOnErrorClause() != null) {
builder.appendExpression(visit(ctx.jsonExistsOnErrorClause()));
}
return QueryTokenStream.ofFunction(ctx.JSON_EXISTS(), builder);
}
@Override
public QueryTokenStream visitJsonObjectFunction(HqlParser.JsonObjectFunctionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.appendExpression(QueryTokenStream.concat(ctx.jsonObjectFunctionEntry(), this::visit, TOKEN_COMMA));
if (ctx.jsonNullClause() != null) {
builder.appendExpression(visit(ctx.jsonNullClause()));
}
return QueryTokenStream.ofFunction(ctx.JSON_OBJECT(), builder);
}
@Override
public QueryTokenStream visitJsonQueryFunction(HqlParser.JsonQueryFunctionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.appendExpression(QueryTokenStream.concat(ctx.expression(), this::visit, TOKEN_COMMA));
if (ctx.jsonPassingClause() != null) {
builder.appendExpression(visit(ctx.jsonPassingClause()));
}
if (ctx.jsonQueryWrapperClause() != null) {
builder.appendExpression(visit(ctx.jsonQueryWrapperClause()));
}
builder.append(QueryTokenStream.concat(ctx.jsonQueryOnErrorOrEmptyClause(), this::visit, TOKEN_SPACE));
return QueryTokenStream.ofFunction(ctx.JSON_QUERY(), builder);
}
@Override
public QueryTokenStream visitJsonValueFunction(HqlParser.JsonValueFunctionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(QueryTokenStream.concat(ctx.expression(), this::visit, TOKEN_COMMA));
if (ctx.jsonPassingClause() != null) {
builder.appendExpression(visit(ctx.jsonPassingClause()));
}
if (ctx.jsonValueReturningClause() != null) {
builder.appendExpression(visit(ctx.jsonValueReturningClause()));
}
builder.append(QueryTokenStream.concat(ctx.jsonValueOnErrorOrEmptyClause(), this::visit, TOKEN_SPACE));
return QueryTokenStream.ofFunction(ctx.JSON_VALUE(), builder);
}
@Override
public QueryTokenStream visitJsonArrayAggFunction(HqlParser.JsonArrayAggFunctionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.appendExpression(visit(ctx.expressionOrPredicate()));
if (ctx.jsonNullClause() != null) {
builder.appendExpression(visit(ctx.jsonNullClause()));
}
if (ctx.orderByClause() != null) {
builder.appendExpression(visit(ctx.orderByClause()));
}
QueryTokenStream function = QueryTokenStream.ofFunction(ctx.JSON_ARRAYAGG(), builder);
if (ctx.filterClause() == null) {
return function;
}
QueryRendererBuilder functionWithFilter = QueryRenderer.builder();
functionWithFilter.appendExpression(function);
functionWithFilter.appendExpression(visit(ctx.filterClause()));
return functionWithFilter.build();
}
@Override
public QueryTokenStream visitJsonObjectAggFunction(HqlParser.JsonObjectAggFunctionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
if (ctx.KEY() != null) {
builder.append(QueryTokens.expression(ctx.KEY()));
}
builder.appendExpression(visit(ctx.expressionOrPredicate(0)));
if (ctx.VALUE() != null) {
builder.append(QueryTokens.expression(ctx.VALUE()));
} else {
builder.append(TOKEN_COLON);
}
builder.appendExpression(visit(ctx.expressionOrPredicate(1)));
if (ctx.jsonNullClause() != null) {
builder.appendExpression(visit(ctx.jsonNullClause()));
}
if (ctx.jsonUniqueKeysClause() != null) {
builder.appendExpression(visit(ctx.jsonUniqueKeysClause()));
}
QueryTokenStream function = QueryTokenStream.ofFunction(ctx.JSON_OBJECTAGG(), builder);
if (ctx.filterClause() == null) {
return function;
}
QueryRendererBuilder functionWithFilter = QueryRenderer.builder();
functionWithFilter.appendExpression(function);
functionWithFilter.appendExpression(visit(ctx.filterClause()));
return functionWithFilter.build();
}
@Override
public QueryTokenStream visitJsonPassingClause(HqlParser.JsonPassingClauseContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(QueryTokens.expression(ctx.PASSING()));
builder.append(QueryTokenStream.concat(ctx.aliasedExpressionOrPredicate(), this::visit, TOKEN_COMMA));
return builder;
}
@Override
public QueryTokenStream visitJsonTableFunction(HqlParser.JsonTableFunctionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.appendExpression(QueryTokenStream.concat(ctx.expression(), this::visit, TOKEN_COMMA));
if (ctx.jsonPassingClause() != null) {
builder.appendExpression(visit(ctx.jsonPassingClause()));
}
builder.appendExpression(visit(ctx.jsonTableColumnsClause()));
if (ctx.jsonTableErrorClause() != null) {
builder.appendExpression(visit(ctx.jsonTableErrorClause()));
}
return QueryTokenStream.ofFunction(ctx.JSON_TABLE(), builder);
}
@Override
public QueryTokenStream visitJsonTableColumnsClause(HqlParser.JsonTableColumnsClauseContext ctx) {
return QueryTokenStream.ofFunction(ctx.COLUMNS(), visit(ctx.jsonTableColumns()));
}
@Override
public QueryTokenStream visitJsonTableColumns(HqlParser.JsonTableColumnsContext ctx) {
return QueryTokenStream.concat(ctx.jsonTableColumn(), this::visit, TOKEN_COMMA);
}
@Override
public QueryTokenStream visitXmlElementFunction(HqlParser.XmlElementFunctionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(QueryTokens.expression(ctx.NAME()));
builder.append(visit(ctx.identifier()));
if (ctx.xmlAttributesFunction() != null) {
builder.append(TOKEN_COMMA);
builder.append(visit(ctx.xmlAttributesFunction()));
}
if (!CollectionUtils.isEmpty(ctx.expressionOrPredicate())) {
builder.append(TOKEN_COMMA);
builder.append(QueryTokenStream.concat(ctx.expressionOrPredicate(), this::visit, TOKEN_COMMA));
}
return QueryTokenStream.ofFunction(ctx.XMLELEMENT(), builder);
}
@Override
public QueryTokenStream visitXmlAttributesFunction(HqlParser.XmlAttributesFunctionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.appendExpression(QueryTokenStream.concat(ctx.aliasedExpressionOrPredicate(), this::visit, TOKEN_COMMA));
return QueryTokenStream.ofFunction(ctx.XMLATTRIBUTES(), builder);
}
@Override
public QueryTokenStream visitXmlForestFunction(HqlParser.XmlForestFunctionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.appendExpression(
QueryTokenStream.concat(ctx.potentiallyAliasedExpressionOrPredicate(), this::visit, TOKEN_COMMA));
return QueryTokenStream.ofFunction(ctx.XMLFOREST(), builder);
}
@Override
public QueryTokenStream visitXmlPiFunction(HqlParser.XmlPiFunctionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(QueryTokens.expression(ctx.NAME()));
builder.append(visit(ctx.identifier()));
if (ctx.expression() != null) {
builder.append(TOKEN_COMMA);
builder.append(visit(ctx.expression()));
}
return QueryTokenStream.ofFunction(ctx.XMLPI(), builder);
}
@Override
public QueryTokenStream visitXmlQueryFunction(HqlParser.XmlQueryFunctionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.appendExpression(visit(ctx.expression(0)));
builder.append(QueryTokens.expression(ctx.PASSING()));
builder.appendExpression(visit(ctx.expression(1)));
return QueryTokenStream.ofFunction(ctx.XMLQUERY(), builder);
}
@Override
public QueryTokenStream visitXmlExistsFunction(HqlParser.XmlExistsFunctionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.appendExpression(visit(ctx.expression(0)));
builder.append(QueryTokens.expression(ctx.PASSING()));
builder.appendExpression(visit(ctx.expression(1)));
return QueryTokenStream.ofFunction(ctx.XMLEXISTS(), builder);
}
@Override
public QueryTokenStream visitXmlAggFunction(HqlParser.XmlAggFunctionContext ctx) {
QueryRendererBuilder args = QueryRenderer.builder();
args.appendExpression(visit(ctx.expression()));
if (ctx.orderByClause() != null) {
args.appendExpression(visit(ctx.orderByClause()));
}
QueryTokenStream function = QueryTokenStream.ofFunction(ctx.XMLAGG(), args);
if (ctx.filterClause() == null && ctx.overClause() == null) {
return function;
}
QueryRendererBuilder builder = QueryRenderer.builder();
builder.appendExpression(function);
if (ctx.filterClause() != null) {
builder.appendExpression(visit(ctx.filterClause()));
}
if (ctx.overClause() != null) {
builder.appendExpression(visit(ctx.overClause()));
}
return builder;
}
@Override
public QueryTokenStream visitXmlTableFunction(HqlParser.XmlTableFunctionContext ctx) {
QueryRendererBuilder args = QueryRenderer.builder();
args.appendExpression(visit(ctx.expression(0)));
args.append(QueryTokens.expression(ctx.PASSING()));
args.appendExpression(visit(ctx.expression(1)));
args.appendExpression(visit(ctx.xmlTableColumnsClause()));
return QueryTokenStream.ofFunction(ctx.XMLTABLE(), args);
}
@Override
public QueryTokenStream visitXmlTableColumnsClause(HqlParser.XmlTableColumnsClauseContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(QueryTokens.expression(ctx.COLUMNS()));
builder.append(QueryTokenStream.concat(ctx.xmlTableColumn(), this::visit, TOKEN_COMMA));
return builder;
}
@Override
public QueryTokenStream visitPath(HqlParser.PathContext ctx) {
return QueryTokenStream.concat(ctx.children, this::visit, EMPTY_TOKEN);
}
@Override
public QueryTokenStream visitGeneralPathFragment(HqlParser.GeneralPathFragmentContext ctx) {
return QueryTokenStream.concat(ctx.children, this::visit, EMPTY_TOKEN);
}
@Override
public QueryTokenStream visitIndexedPathAccessFragment(HqlParser.IndexedPathAccessFragmentContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(TOKEN_OPEN_SQUARE_BRACKET);
builder.appendInline(visit(ctx.expression()));
builder.append(TOKEN_CLOSE_SQUARE_BRACKET);
if (ctx.generalPathFragment() != null) {
builder.append(TOKEN_DOT);
builder.append(visit(ctx.generalPathFragment()));
}
return builder;
}
@Override
public QueryTokenStream visitSimplePath(HqlParser.SimplePathContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(visit(ctx.identifier()));
if (!ctx.simplePathElement().isEmpty()) {
builder.append(TOKEN_DOT);
}
builder.append(QueryTokenStream.concat(ctx.simplePathElement(), this::visit, TOKEN_DOT));
return builder;
}
@Override
public QueryTokenStream visitSimplePathElement(HqlParser.SimplePathElementContext ctx) {
return visit(ctx.identifier());
}
@Override
public QueryTokenStream visitGenericFunction(HqlParser.GenericFunctionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
QueryRendererBuilder nested = QueryRenderer.builder();
nested.append(visit(ctx.genericFunctionName()));
nested.append(TOKEN_OPEN_PAREN);
if (ctx.genericFunctionArguments() != null) {
nested.appendInline(visit(ctx.genericFunctionArguments()));
} else if (ctx.ASTERISK() != null) {
nested.append(QueryTokens.token(ctx.ASTERISK()));
}
nested.append(TOKEN_CLOSE_PAREN);
builder.append(nested);
if (ctx.pathContinuation() != null) {
builder.append(visit(ctx.pathContinuation()));
}
if (ctx.nthSideClause() != null) {
builder.appendExpression(visit(ctx.nthSideClause()));
}
if (ctx.nullsClause() != null) {
builder.appendExpression(visit(ctx.nullsClause()));
}
if (ctx.withinGroupClause() != null) {
builder.appendExpression(visit(ctx.withinGroupClause()));
}
if (ctx.filterClause() != null) {
builder.appendExpression(visit(ctx.filterClause()));
}
if (ctx.overClause() != null) {
builder.appendExpression(visit(ctx.overClause()));
}
return builder;
}
@Override
public QueryTokenStream visitFilterClause(HqlParser.FilterClauseContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(QueryTokens.expression(ctx.FILTER()));
builder.append(TOKEN_OPEN_PAREN);
builder.appendInline(visit(ctx.whereClause()));
builder.append(TOKEN_CLOSE_PAREN);
return builder;
}
@Override
public QueryTokenStream visitOverClause(HqlParser.OverClauseContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(QueryTokens.expression(ctx.OVER()));
QueryRendererBuilder nested = QueryRenderer.builder();
List<ParseTree> trees = new ArrayList<>();
if (ctx.partitionClause() != null) {
trees.add(ctx.partitionClause());
}
if (ctx.orderByClause() != null) {
trees.add(ctx.orderByClause());
}
if (ctx.frameClause() != null) {
trees.add(ctx.frameClause());
}
nested.appendInline(QueryTokenStream.concat(trees, this::visit, TOKEN_SPACE));
builder.appendInline(QueryTokenStream.group(nested));
return builder;
}
@Override
public QueryTokenStream visitPartitionClause(HqlParser.PartitionClauseContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(QueryTokens.expression(ctx.PARTITION()));
builder.append(QueryTokens.expression(ctx.BY()));
builder.append(QueryTokenStream.concat(ctx.expression(), this::visit, TOKEN_COMMA));
return builder;
}
@Override
public QueryTokenStream visitCastFunction(HqlParser.CastFunctionContext ctx) {
QueryRendererBuilder nested = QueryRenderer.builder();
nested.appendExpression(visit(ctx.expression()));
nested.append(QueryTokens.expression(ctx.AS()));
nested.appendExpression(visit(ctx.castTarget()));
return QueryTokenStream.ofFunction(ctx.CAST(), nested);
}
@Override
public QueryTokenStream visitCastTarget(HqlParser.CastTargetContext ctx) {
List<TerminalNode> literals = ctx.INTEGER_LITERAL();
if (!CollectionUtils.isEmpty(literals)) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(visit(ctx.castTargetType()));
builder.append(TOKEN_OPEN_PAREN);
QueryRendererBuilder args = QueryRenderer.builder();
for (int i = 0; i < literals.size(); i++) {
if (i > 0) {
args.append(TOKEN_COMMA);
}
args.append(QueryTokens.token(literals.get(i)));
}
builder.appendInline(args.build());
builder.append(TOKEN_CLOSE_PAREN);
return builder.build();
}
return visit(ctx.castTargetType());
}
@Override
public QueryTokenStream visitCastTargetType(HqlParser.CastTargetTypeContext ctx) {
return QueryTokens.token(ctx.fullTargetName);
}
@Override
public QueryTokenStream visitExtractFunction(HqlParser.ExtractFunctionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
if (ctx.EXTRACT() != null) {
builder.append(QueryTokens.token(ctx.EXTRACT()));
builder.append(TOKEN_OPEN_PAREN);
QueryRendererBuilder nested = QueryRenderer.builder();
nested.appendExpression(visit(ctx.extractField()));
nested.append(QueryTokens.expression(ctx.FROM()));
nested.appendExpression(visit(ctx.expression()));
builder.appendInline(nested);
builder.append(TOKEN_CLOSE_PAREN);
} else if (ctx.datetimeField() != null) {
builder.append(visit(ctx.datetimeField()));
builder.append(TOKEN_OPEN_PAREN);
builder.appendInline(visit(ctx.expression()));
builder.append(TOKEN_CLOSE_PAREN);
}
return builder;
}
@Override
public QueryTokenStream visitTrimFunction(HqlParser.TrimFunctionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
if (ctx.trimSpecification() != null) {
builder.appendExpression(visit(ctx.trimSpecification()));
}
if (ctx.trimCharacter() != null) {
builder.appendExpression(visit(ctx.trimCharacter()));
}
if (ctx.FROM() != null) {
builder.append(QueryTokens.expression(ctx.FROM()));
}
if (ctx.expression() != null) {
builder.append(visit(ctx.expression()));
}
return QueryTokenStream.ofFunction(ctx.TRIM(), builder);
}
@Override
public QueryTokenStream visitEveryFunction(HqlParser.EveryFunctionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.appendExpression(visit(ctx.everyAllQuantifier()));
if (ctx.predicate() != null) {
builder.append(TOKEN_OPEN_PAREN);
builder.appendInline(visit(ctx.predicate()));
builder.append(TOKEN_CLOSE_PAREN);
if (ctx.filterClause() != null) {
builder.appendExpression(visit(ctx.filterClause()));
}
if (ctx.overClause() != null) {
builder.appendExpression(visit(ctx.overClause()));
}
} else if (ctx.subquery() != null) {
builder.append(TOKEN_OPEN_PAREN);
builder.appendInline(visit(ctx.subquery()));
builder.append(TOKEN_CLOSE_PAREN);
} else {
builder.append(visit(ctx.collectionQuantifier()));
builder.append(TOKEN_OPEN_PAREN);
builder.appendInline(visit(ctx.simplePath()));
builder.append(TOKEN_CLOSE_PAREN);
}
return builder;
}
@Override
public QueryTokenStream visitAnyFunction(HqlParser.AnyFunctionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.appendExpression(visit(ctx.anySomeQuantifier()));
if (ctx.predicate() != null) {
builder.append(TOKEN_OPEN_PAREN);
builder.appendInline(visit(ctx.predicate()));
builder.append(TOKEN_CLOSE_PAREN);
if (ctx.filterClause() != null) {
builder.appendExpression(visit(ctx.filterClause()));
}
if (ctx.overClause() != null) {
builder.appendExpression(visit(ctx.overClause()));
}
} else if (ctx.subquery() != null) {
builder.append(TOKEN_OPEN_PAREN);
builder.appendInline(visit(ctx.subquery()));
builder.append(TOKEN_CLOSE_PAREN);
} else {
builder.append(visit(ctx.collectionQuantifier()));
builder.append(TOKEN_OPEN_PAREN);
builder.appendInline(visit(ctx.simplePath()));
builder.append(TOKEN_CLOSE_PAREN);
}
return builder;
}
@Override
public QueryTokenStream visitTreatedNavigablePath(HqlParser.TreatedNavigablePathContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
QueryRendererBuilder nested = QueryRenderer.builder();
nested.appendExpression(visit(ctx.path()));
nested.append(QueryTokens.expression(ctx.AS()));
nested.append(visit(ctx.simplePath()));
builder.append(QueryTokenStream.ofFunction(ctx.TREAT(), nested));
if (ctx.pathContinuation() != null) {
builder.append(visit(ctx.pathContinuation()));
}
return builder;
}
@Override
public QueryTokenStream visitCollectionValueNavigablePath(HqlParser.CollectionValueNavigablePathContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(visit(ctx.elementValueQuantifier()));
builder.append(TOKEN_OPEN_PAREN);
builder.append(visit(ctx.path()));
builder.append(TOKEN_CLOSE_PAREN);
if (ctx.pathContinuation() != null) {
builder.append(visit(ctx.pathContinuation()));
}
return builder;
}
@Override
public QueryTokenStream visitMapKeyNavigablePath(HqlParser.MapKeyNavigablePathContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
builder.append(visit(ctx.indexKeyQuantifier()));
builder.append(TOKEN_OPEN_PAREN);
builder.append(visit(ctx.path()));
builder.append(TOKEN_CLOSE_PAREN);
if (ctx.pathContinuation() != null) {
builder.append(visit(ctx.pathContinuation()));
}
return builder;
}
@Override
public QueryTokenStream visitToOneFkReference(HqlParser.ToOneFkReferenceContext ctx) {
return QueryTokenStream.ofFunction(ctx.FK(), visit(ctx.path()));
}
@Override
public QueryTokenStream visitGroupedPredicate(HqlParser.GroupedPredicateContext ctx) {
return QueryTokenStream.group(visit(ctx.predicate()));
}
@Override
public QueryTokenStream visitInList(HqlParser.InListContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
if (ctx.simplePath() != null) {
if (ctx.ELEMENTS() != null) {
builder.append(QueryTokens.token(ctx.ELEMENTS()));
} else if (ctx.INDICES() != null) {
builder.append(QueryTokens.token(ctx.INDICES()));
}
builder.append(TOKEN_OPEN_PAREN);
builder.appendInline(visit(ctx.simplePath()));
builder.append(TOKEN_CLOSE_PAREN);
} else if (ctx.subquery() != null) {
builder.append(TOKEN_OPEN_PAREN);
builder.appendInline(visit(ctx.subquery()));
builder.append(TOKEN_CLOSE_PAREN);
} else if (ctx.parameter() != null) {
builder.append(visit(ctx.parameter()));
} else if (ctx.expressionOrPredicate() != null) {
builder.append(TOKEN_OPEN_PAREN);
builder.appendInline(QueryTokenStream.concat(ctx.expressionOrPredicate(), this::visit, TOKEN_COMMA));
builder.append(TOKEN_CLOSE_PAREN);
}
return builder;
}
@Override
public QueryTokenStream visitExistsExpression(HqlParser.ExistsExpressionContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
if (ctx.simplePath() != null) {
builder.append(QueryTokens.expression(ctx.EXISTS()));
if (ctx.ELEMENTS() != null) {
builder.append(QueryTokens.token(ctx.ELEMENTS()));
} else if (ctx.INDICES() != null) {
builder.append(QueryTokens.token(ctx.INDICES()));
}
builder.append(TOKEN_OPEN_PAREN);
builder.append(visit(ctx.simplePath()));
builder.append(TOKEN_CLOSE_PAREN);
} else if (ctx.expression() != null) {
builder.append(QueryTokens.expression(ctx.EXISTS()));
builder.appendExpression(visit(ctx.expression()));
}
return builder;
}
@Override
public QueryTokenStream visitInstantiationArguments(HqlParser.InstantiationArgumentsContext ctx) {
return QueryTokenStream.concat(ctx.instantiationArgument(), this::visit, TOKEN_COMMA);
}
@Override
public QueryTokenStream visitParameter(HqlParser.ParameterContext ctx) {
QueryRendererBuilder builder = QueryRenderer.builder();
if (ctx.prefix.getText().equals(":")) {
builder.append(TOKEN_COLON);
builder.append(visit(ctx.identifier()));
} else if (ctx.prefix.getText().equals("?")) {
builder.append(TOKEN_QUESTION_MARK);
if (ctx.INTEGER_LITERAL() != null) {
builder.append(QueryTokens.token(ctx.INTEGER_LITERAL()));
}
}
return builder;
}
@Override
public QueryTokenStream visitEntityName(HqlParser.EntityNameContext ctx) {
return QueryTokenStream.concat(ctx.identifier(), this::visit, TOKEN_DOT);
}
@Override
public QueryTokenStream visitChildren(RuleNode node) {
int childCount = node.getChildCount();
if (childCount == 1 && node.getChild(0) instanceof RuleContext t) {
return visit(t);
}
if (childCount == 1 && node.getChild(0) instanceof TerminalNode t) {
return QueryTokens.token(t);
}
return QueryTokenStream.concatExpressions(node, this::visit);
}
}