1+ /**
2+ * Copyright (c) 2025 Contributors to the Eclipse Foundation
3+ *
4+ * This program and the accompanying materials are made
5+ * available under the terms of the Eclipse Public License 2.0
6+ * which is available at https://www.eclipse.org/legal/epl-2.0/
7+ *
8+ * SPDX-License-Identifier: EPL-2.0
9+ */
10+ package org .eclipse .hawkbit .repository .jpa ;
11+
12+ import java .lang .reflect .InvocationTargetException ;
13+ import java .lang .reflect .Method ;
14+ import java .util .List ;
15+ import java .util .Map ;
16+
17+ import jakarta .persistence .TypedQuery ;
18+
19+ import lombok .NoArgsConstructor ;
20+ import lombok .extern .slf4j .Slf4j ;
21+ import org .hibernate .engine .spi .SessionFactoryImplementor ;
22+ import org .hibernate .engine .spi .SharedSessionContractImplementor ;
23+ import org .hibernate .metamodel .mapping .MappingModelExpressible ;
24+ import org .hibernate .query .spi .QueryEngine ;
25+ import org .hibernate .query .spi .QueryParameterImplementor ;
26+ import org .hibernate .query .sqm .internal .QuerySqmImpl ;
27+ import org .hibernate .query .sqm .internal .SqmUtil ;
28+ import org .hibernate .query .sqm .spi .SqmParameterMappingModelResolutionAccess ;
29+ import org .hibernate .query .sqm .sql .SqmTranslation ;
30+ import org .hibernate .query .sqm .sql .SqmTranslator ;
31+ import org .hibernate .query .sqm .sql .SqmTranslatorFactory ;
32+ import org .hibernate .query .sqm .tree .SqmDmlStatement ;
33+ import org .hibernate .query .sqm .tree .expression .SqmParameter ;
34+ import org .hibernate .query .sqm .tree .select .SqmSelectStatement ;
35+ import org .hibernate .sql .ast .SqlAstTranslatorFactory ;
36+ import org .hibernate .sql .ast .tree .MutationStatement ;
37+ import org .hibernate .sql .ast .tree .Statement ;
38+ import org .hibernate .sql .ast .tree .select .SelectStatement ;
39+ import org .hibernate .sql .exec .spi .JdbcParameterBindings ;
40+ import org .hibernate .sql .exec .spi .JdbcParametersList ;
41+
42+ @ NoArgsConstructor (access = lombok .AccessLevel .PRIVATE )
43+ @ Slf4j
44+ public class Utils {
45+
46+ private static final Method getSqmTranslatorFactory ;
47+
48+ static {
49+ Method method = null ;
50+ try {
51+ method = QueryEngine .class .getMethod ("getSqmTranslatorFactory" );
52+ } catch (final NoSuchMethodException e ) {
53+ log .warn ("Can't resolve getSqmTranslatorFactory method (Utils.toString won't work)" , e );
54+ }
55+ getSqmTranslatorFactory = method ;
56+ }
57+
58+ public static String toSql (final TypedQuery <?> typedQuery ) {
59+ if (getSqmTranslatorFactory == null ) {
60+ throw new UnsupportedOperationException ("SqmTranslatorFactory resolver is not available" );
61+ }
62+
63+ final QuerySqmImpl <?> hqlQuery = typedQuery .unwrap (QuerySqmImpl .class );
64+ final SessionFactoryImplementor factory = hqlQuery .getSessionFactory ();
65+ final SharedSessionContractImplementor session = hqlQuery .getSession ();
66+ final SessionFactoryImplementor sessionFactory = session .getFactory ();
67+
68+ final SqmTranslatorFactory sqmTranslatorFactory ;
69+ try {
70+ sqmTranslatorFactory = (SqmTranslatorFactory ) getSqmTranslatorFactory .invoke (factory .getQueryEngine ());
71+ } catch (final IllegalAccessException | InvocationTargetException e ) {
72+ throw new UnsupportedOperationException ("Can't create SqmTranslatorFactory" , e );
73+ }
74+
75+ final SqmTranslator <? extends Statement > sqmSelectTranslator =
76+ hqlQuery .getSqmStatement () instanceof SqmSelectStatement <?> selectStatement
77+ ? sqmTranslatorFactory .createSelectTranslator (selectStatement ,
78+ hqlQuery .getQueryOptions (), hqlQuery .getDomainParameterXref (), hqlQuery .getQueryParameterBindings (),
79+ hqlQuery .getLoadQueryInfluencers (), sessionFactory , false )
80+ : sqmTranslatorFactory .createMutationTranslator ((SqmDmlStatement <?>) hqlQuery .getSqmStatement (),
81+ hqlQuery .getQueryOptions (), hqlQuery .getDomainParameterXref (), hqlQuery .getQueryParameterBindings (),
82+ hqlQuery .getLoadQueryInfluencers (), sessionFactory );
83+
84+ final SqmTranslation <? extends Statement > sqmTranslation = sqmSelectTranslator .translate ();
85+ final SqlAstTranslatorFactory sqlAstTranslatorFactory = factory .getJdbcServices ().getJdbcEnvironment ().getSqlAstTranslatorFactory ();
86+ final Map <QueryParameterImplementor <?>, Map <SqmParameter <?>, List <JdbcParametersList >>> jdbcParamsXref = SqmUtil .generateJdbcParamsXref (
87+ hqlQuery .getDomainParameterXref (), sqmTranslation ::getJdbcParamsBySqmParam );
88+
89+ final JdbcParameterBindings jdbcParameterBindings = SqmUtil .createJdbcParameterBindings (hqlQuery .getQueryParameterBindings (),
90+ hqlQuery .getDomainParameterXref (), jdbcParamsXref , factory .getRuntimeMetamodels ().getMappingMetamodel (),
91+ sqmSelectTranslator .getFromClauseAccess ()::findTableGroup , new SqmParameterMappingModelResolutionAccess () {
92+
93+ @ Override
94+ @ SuppressWarnings ("unchecked" )
95+ public <T > MappingModelExpressible <T > getResolvedMappingModelType (final SqmParameter <T > parameter ) {
96+ return (MappingModelExpressible <T >) sqmTranslation .getSqmParameterMappingModelTypeResolutions ().get (parameter );
97+ }
98+ }, hqlQuery .getSession ());
99+ return (sqmTranslation .getSqlAst () instanceof SelectStatement selectStatement
100+ ? sqlAstTranslatorFactory .buildSelectTranslator (factory , selectStatement )
101+ .translate (jdbcParameterBindings , hqlQuery .getQueryOptions ())
102+ : sqlAstTranslatorFactory .buildMutationTranslator (factory , (MutationStatement ) sqmTranslation .getSqlAst ())
103+ .translate (jdbcParameterBindings , hqlQuery .getQueryOptions ()))
104+ .getSqlString ();
105+ }
106+ }
0 commit comments