Skip to content

Commit e522cbe

Browse files
committed
preliminary work on replacing LoadPlan with SQL AST approach - basic working support
1 parent 704ba4f commit e522cbe

File tree

91 files changed

+1783
-431
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

91 files changed

+1783
-431
lines changed

hibernate-core/hibernate-core.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,9 @@ cleanEclipse {
179179
project.delete '.externalToolBuilders'
180180
project.delete 'hibernate-core-RunnableIdeTest.launch'
181181
}
182+
182183
tasks.eclipse.dependsOn(cleanEclipse)
184+
183185
eclipse {
184186
project {
185187
file {

hibernate-core/src/main/java/org/hibernate/internal/util/NullnessHelper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public static <T> T coalesceSuppliedValues(Supplier<T>... valueSuppliers) {
7777
return value;
7878
}
7979
}
80-
else {
80+
else if ( value != null ) {
8181
return value;
8282
}
8383
}
Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
5+
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
6+
*/
7+
package org.hibernate.loader.internal;
8+
9+
import java.util.ArrayList;
10+
import java.util.HashSet;
11+
import java.util.Iterator;
12+
import java.util.List;
13+
import java.util.Set;
14+
15+
import org.hibernate.LockMode;
16+
import org.hibernate.LockOptions;
17+
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
18+
import org.hibernate.engine.jdbc.spi.JdbcServices;
19+
import org.hibernate.engine.spi.SessionFactoryImplementor;
20+
import org.hibernate.engine.spi.SharedSessionContractImplementor;
21+
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
22+
import org.hibernate.metamodel.mapping.EntityMappingType;
23+
import org.hibernate.metamodel.mapping.JdbcMapping;
24+
import org.hibernate.query.ComparisonOperator;
25+
import org.hibernate.query.NavigablePath;
26+
import org.hibernate.query.spi.QueryOptions;
27+
import org.hibernate.query.spi.QueryParameterBindings;
28+
import org.hibernate.sql.ast.Clause;
29+
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
30+
import org.hibernate.sql.ast.spi.SqlAliasBaseManager;
31+
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
32+
import org.hibernate.sql.ast.spi.SqlSelection;
33+
import org.hibernate.sql.ast.tree.expression.ColumnReference;
34+
import org.hibernate.sql.ast.tree.from.TableGroup;
35+
import org.hibernate.sql.ast.tree.from.TableReference;
36+
import org.hibernate.sql.ast.tree.predicate.ComparisonPredicate;
37+
import org.hibernate.sql.ast.tree.select.QuerySpec;
38+
import org.hibernate.sql.ast.tree.select.SelectStatement;
39+
import org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl;
40+
import org.hibernate.sql.exec.internal.JdbcParameterImpl;
41+
import org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl;
42+
import org.hibernate.sql.exec.spi.Callback;
43+
import org.hibernate.sql.exec.spi.ExecutionContext;
44+
import org.hibernate.sql.exec.spi.JdbcParameter;
45+
import org.hibernate.sql.exec.spi.JdbcParameterBinding;
46+
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
47+
import org.hibernate.sql.exec.spi.JdbcSelect;
48+
import org.hibernate.sql.results.internal.RowTransformerPassThruImpl;
49+
import org.hibernate.sql.results.internal.domain.basic.BasicResult;
50+
import org.hibernate.sql.results.spi.DomainResult;
51+
52+
import org.jboss.logging.Logger;
53+
54+
/**
55+
* @author Steve Ebersole
56+
*/
57+
class DatabaseSnapshotExecutor {
58+
private static final Logger log = Logger.getLogger( DatabaseSnapshotExecutor.class );
59+
60+
private final EntityMappingType entityDescriptor;
61+
private final SessionFactoryImplementor sessionFactory;
62+
63+
private final JdbcSelect jdbcSelect;
64+
private final List<JdbcParameter> jdbcParameters;
65+
66+
DatabaseSnapshotExecutor(
67+
EntityMappingType entityDescriptor,
68+
SessionFactoryImplementor sessionFactory) {
69+
this.entityDescriptor = entityDescriptor;
70+
this.sessionFactory = sessionFactory;
71+
72+
final QuerySpec rootQuerySpec = new QuerySpec( true );
73+
74+
final SqlAliasBaseManager sqlAliasBaseManager = new SqlAliasBaseManager();
75+
76+
final LoaderSqlAstCreationState state = new LoaderSqlAstCreationState(
77+
rootQuerySpec,
78+
sqlAliasBaseManager,
79+
LockOptions.READ,
80+
sessionFactory
81+
);
82+
83+
final NavigablePath rootPath = new NavigablePath( entityDescriptor.getEntityName() );
84+
85+
final TableGroup rootTableGroup = entityDescriptor.createRootTableGroup(
86+
rootPath,
87+
null,
88+
null,
89+
LockMode.NONE,
90+
sqlAliasBaseManager,
91+
state.getSqlExpressionResolver(),
92+
() -> rootQuerySpec::applyPredicate,
93+
sessionFactory
94+
);
95+
96+
rootQuerySpec.getFromClause().addRoot( rootTableGroup );
97+
98+
jdbcParameters = new ArrayList<>(
99+
entityDescriptor.getIdentifierMapping().getJdbcTypeCount( sessionFactory.getTypeConfiguration() )
100+
);
101+
final List<DomainResult> domainResults = new ArrayList<>();
102+
103+
final NavigablePath idPath = rootPath.append( EntityIdentifierMapping.ROLE_LOCAL_NAME );
104+
entityDescriptor.getIdentifierMapping().visitColumns(
105+
idPath,
106+
rootTableGroup,
107+
state,
108+
(col, tab, jdbcMapping) -> {
109+
final TableReference tableReference = rootTableGroup.resolveTableReference( tab );
110+
111+
final JdbcParameter jdbcParameter = new JdbcParameterImpl( jdbcMapping );
112+
jdbcParameters.add( jdbcParameter );
113+
114+
final ColumnReference columnReference = (ColumnReference) state.getSqlExpressionResolver()
115+
.resolveSqlExpression(
116+
SqlExpressionResolver.createColumnReferenceKey( tableReference, col ),
117+
s -> new ColumnReference(
118+
tableReference,
119+
col,
120+
jdbcMapping,
121+
sessionFactory
122+
)
123+
);
124+
125+
rootQuerySpec.applyPredicate(
126+
new ComparisonPredicate(
127+
columnReference,
128+
ComparisonOperator.EQUAL,
129+
jdbcParameter
130+
)
131+
);
132+
133+
final SqlSelection sqlSelection = state.getSqlExpressionResolver().resolveSqlSelection(
134+
columnReference,
135+
jdbcMapping.getJavaTypeDescriptor(),
136+
sessionFactory.getTypeConfiguration()
137+
);
138+
139+
rootQuerySpec.getSelectClause().addSqlSelection( sqlSelection );
140+
141+
//noinspection unchecked
142+
domainResults.add(
143+
new BasicResult(
144+
sqlSelection.getValuesArrayPosition(),
145+
null,
146+
jdbcMapping.getJavaTypeDescriptor()
147+
)
148+
);
149+
}
150+
);
151+
152+
entityDescriptor.visitStateArrayContributors(
153+
contributorMapping -> {
154+
final NavigablePath attrPath = rootPath.append( contributorMapping.getAttributeName() );
155+
contributorMapping.visitColumns(
156+
attrPath,
157+
rootTableGroup,
158+
state,
159+
(columnExpression, containingTableExpression, jdbcMapping) -> {
160+
final TableReference tableReference = rootTableGroup.resolveTableReference(
161+
containingTableExpression );
162+
163+
final JdbcParameter jdbcParameter = new JdbcParameterImpl( jdbcMapping );
164+
jdbcParameters.add( jdbcParameter );
165+
166+
final ColumnReference columnReference = (ColumnReference) state.getSqlExpressionResolver()
167+
.resolveSqlExpression(
168+
SqlExpressionResolver.createColumnReferenceKey(
169+
tableReference,
170+
columnExpression
171+
),
172+
s -> new ColumnReference(
173+
tableReference,
174+
columnExpression,
175+
jdbcMapping,
176+
sessionFactory
177+
)
178+
);
179+
180+
final SqlSelection sqlSelection = state.getSqlExpressionResolver()
181+
.resolveSqlSelection(
182+
columnReference,
183+
jdbcMapping.getJavaTypeDescriptor(),
184+
sessionFactory.getTypeConfiguration()
185+
);
186+
187+
rootQuerySpec.getSelectClause().addSqlSelection( sqlSelection );
188+
189+
//noinspection unchecked
190+
domainResults.add(
191+
new BasicResult(
192+
sqlSelection.getValuesArrayPosition(),
193+
null,
194+
jdbcMapping.getJavaTypeDescriptor()
195+
)
196+
);
197+
}
198+
);
199+
}
200+
);
201+
202+
final Set<String> tableNames = new HashSet<>();
203+
rootTableGroup.applyAffectedTableNames( tableNames::add );
204+
205+
final SelectStatement selectStatement = new SelectStatement( rootQuerySpec, domainResults, tableNames );
206+
207+
208+
final JdbcServices jdbcServices = sessionFactory.getJdbcServices();
209+
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
210+
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
211+
212+
jdbcSelect = sqlAstTranslatorFactory.buildSelectConverter( sessionFactory ).interpret( selectStatement );
213+
}
214+
215+
Object[] loadDatabaseSnapshot(Object id, SharedSessionContractImplementor session) {
216+
log.tracef( "Getting current persistent state for `%s#%s`", entityDescriptor.getEntityName(), id );
217+
218+
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl(
219+
entityDescriptor.getIdentifierMapping().getJdbcTypeCount( sessionFactory.getTypeConfiguration() )
220+
);
221+
222+
final Iterator<JdbcParameter> paramItr = jdbcParameters.iterator();
223+
224+
entityDescriptor.getIdentifierMapping().visitJdbcValues(
225+
id,
226+
Clause.WHERE,
227+
(value, type) -> {
228+
assert paramItr.hasNext();
229+
final JdbcParameter parameter = paramItr.next();
230+
jdbcParameterBindings.addBinding(
231+
parameter,
232+
new JdbcParameterBinding() {
233+
@Override
234+
public JdbcMapping getBindType() {
235+
return type;
236+
}
237+
238+
@Override
239+
public Object getBindValue() {
240+
return value;
241+
}
242+
}
243+
);
244+
},
245+
session
246+
);
247+
assert !paramItr.hasNext();
248+
249+
final List list = JdbcSelectExecutorStandardImpl.INSTANCE.list(
250+
jdbcSelect,
251+
jdbcParameterBindings,
252+
new ExecutionContext() {
253+
@Override
254+
public SharedSessionContractImplementor getSession() {
255+
return session;
256+
}
257+
258+
@Override
259+
public QueryOptions getQueryOptions() {
260+
return QueryOptions.NONE;
261+
}
262+
263+
@Override
264+
public QueryParameterBindings getQueryParameterBindings() {
265+
return QueryParameterBindings.NO_PARAM_BINDINGS;
266+
}
267+
268+
@Override
269+
public Callback getCallback() {
270+
return null;
271+
}
272+
},
273+
RowTransformerPassThruImpl.instance()
274+
);
275+
276+
if ( list.isEmpty() ) {
277+
return null;
278+
}
279+
280+
final int size = list.size();
281+
final Object[] values = new Object[size];
282+
for ( int i = 0; i < size; i++ ) {
283+
values[i] = list.get( i );
284+
}
285+
286+
return values;
287+
}
288+
289+
}

0 commit comments

Comments
 (0)