HHH-16742 fix implementation of TupleMetadata
fix issue when "same" selection item is assigned two different aliases
This commit is contained in:
parent
acf9495af3
commit
c5ecf5d41c
|
@ -11,7 +11,6 @@ import java.time.Instant;
|
|||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
@ -128,36 +127,62 @@ public abstract class AbstractSelectionQuery<R>
|
|||
|
||||
private TupleMetadata getTupleMetadata(List<SqmSelection<?>> selections) {
|
||||
if ( getQueryOptions().getTupleTransformer() == null ) {
|
||||
return new TupleMetadata( buildTupleElementMap( selections ) );
|
||||
return new TupleMetadata( buildTupleElementArray( selections ), buildTupleAliasArray( selections ) );
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException(
|
||||
"Illegal combination of Tuple resultType and (non-JpaTupleBuilder) TupleTransformer : " +
|
||||
getQueryOptions().getTupleTransformer()
|
||||
"Illegal combination of Tuple resultType and (non-JpaTupleBuilder) TupleTransformer: "
|
||||
+ getQueryOptions().getTupleTransformer()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<TupleElement<?>, Integer> buildTupleElementMap(List<SqmSelection<?>> selections) {
|
||||
final Map<TupleElement<?>, Integer> tupleElementMap;
|
||||
if ( selections.size() == 1
|
||||
&& selections.get( 0 ).getSelectableNode() instanceof CompoundSelection<?> ) {
|
||||
final List<? extends JpaSelection<?>> selectionItems =
|
||||
selections.get( 0 ).getSelectableNode()
|
||||
.getSelectionItems();
|
||||
tupleElementMap = new IdentityHashMap<>( selectionItems.size() );
|
||||
private static TupleElement<?>[] buildTupleElementArray(List<SqmSelection<?>> selections) {
|
||||
final TupleElement<?>[] elements;
|
||||
if ( selections.size() == 1 ) {
|
||||
final SqmSelectableNode<?> selectableNode = selections.get(0).getSelectableNode();
|
||||
if ( selectableNode instanceof CompoundSelection<?> ) {
|
||||
final List<? extends JpaSelection<?>> selectionItems = selectableNode.getSelectionItems();
|
||||
elements = new TupleElement<?>[ selectionItems.size() ];
|
||||
for ( int i = 0; i < selectionItems.size(); i++ ) {
|
||||
tupleElementMap.put( selectionItems.get( i ), i );
|
||||
elements[i] = selectionItems.get( i );
|
||||
}
|
||||
}
|
||||
else {
|
||||
tupleElementMap = new IdentityHashMap<>( selections.size() );
|
||||
for (int i = 0; i < selections.size(); i++ ) {
|
||||
final SqmSelection<?> selection = selections.get( i );
|
||||
tupleElementMap.put( selection.getSelectableNode(), i );
|
||||
elements = new TupleElement<?>[] { selectableNode };
|
||||
}
|
||||
}
|
||||
return tupleElementMap;
|
||||
else {
|
||||
elements = new TupleElement<?>[ selections.size() ];
|
||||
for ( int i = 0; i < selections.size(); i++ ) {
|
||||
elements[i] = selections.get(i).getSelectableNode();
|
||||
}
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
private static String[] buildTupleAliasArray(List<SqmSelection<?>> selections) {
|
||||
final String[] elements;
|
||||
if ( selections.size() == 1 ) {
|
||||
final SqmSelectableNode<?> selectableNode = selections.get(0).getSelectableNode();
|
||||
if ( selectableNode instanceof CompoundSelection<?> ) {
|
||||
final List<? extends JpaSelection<?>> selectionItems = selectableNode.getSelectionItems();
|
||||
elements = new String[ selectionItems.size() ];
|
||||
for ( int i = 0; i < selectionItems.size(); i++ ) {
|
||||
elements[i] = selectionItems.get( i ).getAlias();
|
||||
}
|
||||
}
|
||||
else {
|
||||
elements = new String[] { selectableNode.getAlias() };
|
||||
}
|
||||
}
|
||||
else {
|
||||
elements = new String[ selections.size() ];
|
||||
for ( int i = 0; i < selections.size(); i++ ) {
|
||||
elements[i] = selections.get(i).getAlias();
|
||||
}
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
protected void applyOptions(NamedSqmQueryMemento memento) {
|
||||
|
@ -173,8 +198,10 @@ public abstract class AbstractSelectionQuery<R>
|
|||
|
||||
if ( memento.getParameterTypes() != null ) {
|
||||
for ( Map.Entry<String, String> entry : memento.getParameterTypes().entrySet() ) {
|
||||
final QueryParameterImplementor<?> parameter = getParameterMetadata().getQueryParameter( entry.getKey() );
|
||||
final BasicType<?> type = getSessionFactory().getTypeConfiguration()
|
||||
final QueryParameterImplementor<?> parameter =
|
||||
getParameterMetadata().getQueryParameter( entry.getKey() );
|
||||
final BasicType<?> type =
|
||||
getSessionFactory().getTypeConfiguration()
|
||||
.getBasicTypeRegistry()
|
||||
.getRegisteredType( entry.getValue() );
|
||||
parameter.applyAnticipatedType( type );
|
||||
|
|
|
@ -7,51 +7,58 @@
|
|||
|
||||
package org.hibernate.sql.results.internal;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import jakarta.persistence.TupleElement;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import jakarta.persistence.TupleElement;
|
||||
|
||||
import static java.util.Collections.unmodifiableMap;
|
||||
|
||||
/**
|
||||
* Metadata about the tuple structure.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
* @author Gavin King
|
||||
*/
|
||||
public final class TupleMetadata {
|
||||
private final Map<TupleElement<?>, Integer> index;
|
||||
private final TupleElement<?>[] elements;
|
||||
private final String[] aliases;
|
||||
private Map<String, Integer> nameIndex;
|
||||
private Map<TupleElement<?>, Integer> elementIndex;
|
||||
private List<TupleElement<?>> list;
|
||||
|
||||
public TupleMetadata(Map<TupleElement<?>, Integer> index) {
|
||||
this.index = index;
|
||||
public TupleMetadata(TupleElement<?>[] elements, String[] aliases) {
|
||||
this.elements = elements;
|
||||
this.aliases = aliases;
|
||||
}
|
||||
|
||||
public Integer get(TupleElement<?> tupleElement) {
|
||||
return index.get( tupleElement );
|
||||
public Integer get(TupleElement<?> element) {
|
||||
if ( elementIndex == null ) {
|
||||
final Map<TupleElement<?>, Integer> map = new IdentityHashMap<>( elements.length );
|
||||
for (int i = 0; i < elements.length; i++ ) {
|
||||
map.put( elements[i], i );
|
||||
}
|
||||
elementIndex = unmodifiableMap( map );
|
||||
}
|
||||
return elementIndex.get( element );
|
||||
}
|
||||
|
||||
public Integer get(String name) {
|
||||
Map<String, Integer> nameIndex = this.nameIndex;
|
||||
if ( nameIndex == null ) {
|
||||
nameIndex = new HashMap<>( index.size() );
|
||||
for ( Map.Entry<TupleElement<?>, Integer> entry : index.entrySet() ) {
|
||||
nameIndex.put( entry.getKey().getAlias(), entry.getValue() );
|
||||
final Map<String, Integer> map = new HashMap<>( aliases.length );
|
||||
for ( int i = 0; i < aliases.length; i++ ) {
|
||||
map.put( aliases[i], i );
|
||||
}
|
||||
this.nameIndex = nameIndex = Collections.unmodifiableMap( nameIndex );
|
||||
nameIndex = unmodifiableMap( map );
|
||||
}
|
||||
return nameIndex.get( name );
|
||||
}
|
||||
|
||||
public List<TupleElement<?>> getList() {
|
||||
List<TupleElement<?>> list = this.list;
|
||||
if ( list == null ) {
|
||||
final TupleElement<?>[] array = new TupleElement[index.size()];
|
||||
for ( Map.Entry<TupleElement<?>, Integer> entry : index.entrySet() ) {
|
||||
array[entry.getValue()] = entry.getKey();
|
||||
}
|
||||
this.list = list = Collections.unmodifiableList( Arrays.asList( array ) );
|
||||
list = List.of( elements );
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue