1515 */
1616package org .springframework .data .jpa .repository .query ;
1717
18- import static org .springframework .data .jpa .repository .query .QueryTokens .*;
19-
20- import java .util .ArrayList ;
21- import java .util .Collections ;
22- import java .util .List ;
23-
24- import org .jspecify .annotations .Nullable ;
25-
2618import org .springframework .data .jpa .repository .query .HqlParser .VariableContext ;
2719
2820/**
2921 * {@link ParsedQueryIntrospector} for HQL queries.
3022 *
3123 * @author Mark Paluch
3224 * @author Oscar Fanchin
33- * @author kssumin
25+ * @author Soomin Kim
3426 */
35- @ SuppressWarnings ({ "UnreachableCode" , "ConstantValue" })
27+ @ SuppressWarnings ({ "UnreachableCode" })
3628class HqlQueryIntrospector extends HqlBaseVisitor <Void > implements ParsedQueryIntrospector <HibernateQueryInformation > {
3729
3830private final HqlQueryRenderer renderer = new HqlQueryRenderer ();
31+ private final QueryInformationHolder introspection = new QueryInformationHolder ();
3932
40- private @ Nullable String primaryFromAlias = null ;
41- private @ Nullable List <QueryToken > projection ;
42- private boolean projectionProcessed ;
43- private boolean hasConstructorExpression = false ;
4433private boolean hasCte = false ;
4534private boolean hasFromFunction = false ;
46- private QueryInformation .StatementType statementType = QueryInformation .StatementType .SELECT ;
4735
4836@ Override
4937public HibernateQueryInformation getParsedQueryInformation () {
50- return new HibernateQueryInformation (primaryFromAlias , projection == null ? Collections .emptyList () : projection ,
51- hasConstructorExpression , statementType , hasCte , hasFromFunction );
38+ return new HibernateQueryInformation (introspection , hasCte , hasFromFunction );
5239}
5340
5441@ Override
5542public Void visitSelectStatement (HqlParser .SelectStatementContext ctx ) {
56- statementType = QueryInformation .StatementType .SELECT ;
43+
44+ introspection .setStatementType (QueryInformation .StatementType .SELECT );
5745return super .visitSelectStatement (ctx );
5846}
5947
48+ @ Override
49+ public Void visitFromQuery (HqlParser .FromQueryContext ctx ) {
50+
51+ introspection .setStatementType (QueryInformation .StatementType .SELECT );
52+ return super .visitFromQuery (ctx );
53+ }
54+
6055@ Override
6156public Void visitInsertStatement (HqlParser .InsertStatementContext ctx ) {
62- statementType = QueryInformation .StatementType .INSERT ;
57+
58+ introspection .setStatementType (QueryInformation .StatementType .INSERT );
6359return super .visitInsertStatement (ctx );
6460}
6561
6662@ Override
6763public Void visitUpdateStatement (HqlParser .UpdateStatementContext ctx ) {
68- statementType = QueryInformation .StatementType .UPDATE ;
64+
65+ introspection .setStatementType (QueryInformation .StatementType .UPDATE );
6966return super .visitUpdateStatement (ctx );
7067}
7168
7269@ Override
7370public Void visitDeleteStatement (HqlParser .DeleteStatementContext ctx ) {
74- statementType = QueryInformation .StatementType .DELETE ;
71+
72+ introspection .setStatementType (QueryInformation .StatementType .DELETE );
7573return super .visitDeleteStatement (ctx );
7674}
7775
7876@ Override
7977public Void visitSelectClause (HqlParser .SelectClauseContext ctx ) {
8078
81- if (!this .projectionProcessed ) {
82- this .projection = captureSelectItems (ctx .selectionList ().selection (), renderer );
83- this .projectionProcessed = true ;
84- }
79+ introspection .captureProjection (ctx .selectionList ().selection (), renderer ::visitSelection );
8580
8681return super .visitSelectClause (ctx );
8782}
@@ -95,9 +90,9 @@ public Void visitCte(HqlParser.CteContext ctx) {
9590@ Override
9691public Void visitRootEntity (HqlParser .RootEntityContext ctx ) {
9792
98- if (this . primaryFromAlias == null && ctx .variable () != null && !HqlQueryRenderer .isSubquery (ctx )
93+ if (ctx .variable () != null && !HqlQueryRenderer .isSubquery (ctx )
9994&& !HqlQueryRenderer .isSetQuery (ctx )) {
100- this . primaryFromAlias = capturePrimaryAlias (ctx .variable ());
95+ capturePrimaryAlias (ctx .variable ());
10196}
10297
10398return super .visitRootEntity (ctx );
@@ -106,9 +101,9 @@ public Void visitRootEntity(HqlParser.RootEntityContext ctx) {
106101@ Override
107102public Void visitRootSubquery (HqlParser .RootSubqueryContext ctx ) {
108103
109- if (this . primaryFromAlias == null && ctx .variable () != null && !HqlQueryRenderer .isSubquery (ctx )
104+ if (ctx .variable () != null && !HqlQueryRenderer .isSubquery (ctx )
110105&& !HqlQueryRenderer .isSetQuery (ctx )) {
111- this . primaryFromAlias = capturePrimaryAlias (ctx .variable ());
106+ capturePrimaryAlias (ctx .variable ());
112107}
113108
114109return super .visitRootSubquery (ctx );
@@ -117,9 +112,9 @@ public Void visitRootSubquery(HqlParser.RootSubqueryContext ctx) {
117112@ Override
118113public Void visitRootFunction (HqlParser .RootFunctionContext ctx ) {
119114
120- if (this . primaryFromAlias == null && ctx .variable () != null && !HqlQueryRenderer .isSubquery (ctx )
115+ if (ctx .variable () != null && !HqlQueryRenderer .isSubquery (ctx )
121116&& !HqlQueryRenderer .isSetQuery (ctx )) {
122- this . primaryFromAlias = capturePrimaryAlias (ctx .variable ());
117+ capturePrimaryAlias (ctx .variable ());
123118this .hasFromFunction = true ;
124119}
125120
@@ -129,27 +124,13 @@ public Void visitRootFunction(HqlParser.RootFunctionContext ctx) {
129124@ Override
130125public Void visitInstantiation (HqlParser .InstantiationContext ctx ) {
131126
132- hasConstructorExpression = true ;
133-
127+ introspection .constructorExpressionPresent ();
134128return super .visitInstantiation (ctx );
135129}
136130
137- private static String capturePrimaryAlias (VariableContext ctx ) {
138- return ((ctx ).nakedIdentifier () != null ? ctx .nakedIdentifier () : ctx .identifier ()).getText ();
131+ private void capturePrimaryAlias (VariableContext ctx ) {
132+ introspection
133+ .capturePrimaryAlias ((ctx .nakedIdentifier () != null ? ctx .nakedIdentifier () : ctx .identifier ()).getText ());
139134}
140135
141- private static List <QueryToken > captureSelectItems (List <HqlParser .SelectionContext > selections ,
142- HqlQueryRenderer itemRenderer ) {
143-
144- List <QueryToken > selectItemTokens = new ArrayList <>(selections .size () * 2 );
145- for (HqlParser .SelectionContext selection : selections ) {
146-
147- if (!selectItemTokens .isEmpty ()) {
148- selectItemTokens .add (TOKEN_COMMA );
149- }
150-
151- selectItemTokens .add (QueryTokens .token (QueryRenderer .from (itemRenderer .visitSelection (selection )).render ()));
152- }
153- return selectItemTokens ;
154- }
155136}
0 commit comments