HHH-16214 Use a more efficient Map implementation in SqmFunctionRegistry
This commit is contained in:
parent
dd5a8c97af
commit
ac9f47ae43
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.internal.util.collections;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
|
import org.hibernate.Internal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps a ConcurrentHashMap having all keys as Strings
|
||||||
|
* and ensures all keys are lowercased.
|
||||||
|
* It does assume keys and arguments are never null, preferring to throw a NPE
|
||||||
|
* over adding unnecessary checks.
|
||||||
|
* The public exposed methods are similar to the ones on Map, but
|
||||||
|
* not all Map methods are exposed - only a selection we actually need; this
|
||||||
|
* implies it doesn't implement Map; nothing stops us to make it implement Map
|
||||||
|
* but at time of writing it seems unnecessary for our purposes.
|
||||||
|
* @param <V> the type for the stored values.
|
||||||
|
*/
|
||||||
|
@Internal
|
||||||
|
public final class CaseInsensitiveDictionary<V> {
|
||||||
|
|
||||||
|
private final Map<String, V> map = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public V get(final String key) {
|
||||||
|
return map.get( trueKey( key ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contrary to traditional Map, we make the return unmodifiable.
|
||||||
|
* @return the map's keySet
|
||||||
|
*/
|
||||||
|
public Set<String> unmodifiableKeySet() {
|
||||||
|
return Collections.unmodifiableSet( map.keySet() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contrary to traditional Map, we make the return unmodifiable.
|
||||||
|
* @return the map's entrySet
|
||||||
|
*/
|
||||||
|
public Set<Map.Entry<String, V>> unmodifiableEntrySet() {
|
||||||
|
return Collections.unmodifiableSet( map.entrySet() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public V put(final String key, V value) {
|
||||||
|
return map.put( trueKey( key ), value );
|
||||||
|
}
|
||||||
|
|
||||||
|
public V remove(final String key) {
|
||||||
|
return map.remove( trueKey( key ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsKey(final String key) {
|
||||||
|
return map.containsKey( trueKey( key ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String trueKey(final String key) {
|
||||||
|
return key.toLowerCase( Locale.ROOT );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
map.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void forEach(final BiConsumer<? super String, ? super V> action) {
|
||||||
|
map.forEach( action );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -6,11 +6,12 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.query.sqm.function;
|
package org.hibernate.query.sqm.function;
|
||||||
|
|
||||||
import java.util.AbstractMap;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.hibernate.internal.util.collections.CaseInsensitiveDictionary;
|
||||||
import org.hibernate.query.sqm.produce.function.FunctionParameterType;
|
import org.hibernate.query.sqm.produce.function.FunctionParameterType;
|
||||||
import org.hibernate.query.sqm.produce.function.NamedFunctionDescriptorBuilder;
|
import org.hibernate.query.sqm.produce.function.NamedFunctionDescriptorBuilder;
|
||||||
import org.hibernate.query.sqm.produce.function.PatternFunctionDescriptorBuilder;
|
import org.hibernate.query.sqm.produce.function.PatternFunctionDescriptorBuilder;
|
||||||
|
@ -35,27 +36,31 @@ import static org.hibernate.query.sqm.produce.function.StandardFunctionReturnTyp
|
||||||
public class SqmFunctionRegistry {
|
public class SqmFunctionRegistry {
|
||||||
private static final Logger log = Logger.getLogger( SqmFunctionRegistry.class );
|
private static final Logger log = Logger.getLogger( SqmFunctionRegistry.class );
|
||||||
|
|
||||||
private final Map<String, SqmFunctionDescriptor> functionMap = new TreeMap<>( CASE_INSENSITIVE_ORDER );
|
private final CaseInsensitiveDictionary<SqmFunctionDescriptor> functionMap = new CaseInsensitiveDictionary<>();
|
||||||
private final Map<String,String> alternateKeyMap = new TreeMap<>( CASE_INSENSITIVE_ORDER );
|
private final CaseInsensitiveDictionary<String> alternateKeyMap = new CaseInsensitiveDictionary<>();
|
||||||
|
|
||||||
public SqmFunctionRegistry() {
|
public SqmFunctionRegistry() {
|
||||||
log.trace( "SqmFunctionRegistry created" );
|
log.trace( "SqmFunctionRegistry created" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, SqmFunctionDescriptor> getFunctions() {
|
public Set<String> getValidFunctionKeys() {
|
||||||
return functionMap;
|
return functionMap.unmodifiableKeySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Useful for diagnostics - not efficient: do not use in production code.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public Stream<Map.Entry<String, SqmFunctionDescriptor>> getFunctionsByName() {
|
public Stream<Map.Entry<String, SqmFunctionDescriptor>> getFunctionsByName() {
|
||||||
return Stream.concat(
|
final Map<String, SqmFunctionDescriptor> sortedFunctionMap = new TreeMap<>( CASE_INSENSITIVE_ORDER );
|
||||||
functionMap.entrySet().stream(),
|
for ( Map.Entry<String, SqmFunctionDescriptor> e : functionMap.unmodifiableEntrySet() ) {
|
||||||
alternateKeyMap.entrySet().stream().map(
|
sortedFunctionMap.put( e.getKey(), e.getValue() );
|
||||||
entry -> new AbstractMap.SimpleEntry<>(
|
}
|
||||||
entry.getKey(),
|
for ( Map.Entry<String, String> e : alternateKeyMap.unmodifiableEntrySet() ) {
|
||||||
functionMap.get( entry.getValue() )
|
sortedFunctionMap.put( e.getKey(), functionMap.get( e.getValue() ) );
|
||||||
)
|
}
|
||||||
)
|
return sortedFunctionMap.entrySet().stream();
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -35,8 +35,7 @@ public abstract class SpatialSessionFactoryAware extends SpatialTestDataProvider
|
||||||
this.supportedFunctions = scope.getSessionFactory()
|
this.supportedFunctions = scope.getSessionFactory()
|
||||||
.getQueryEngine()
|
.getQueryEngine()
|
||||||
.getSqmFunctionRegistry()
|
.getSqmFunctionRegistry()
|
||||||
.getFunctions()
|
.getValidFunctionKeys();
|
||||||
.keySet();
|
|
||||||
if ( DialectContext.getDialect() instanceof H2Dialect ) {
|
if ( DialectContext.getDialect() instanceof H2Dialect ) {
|
||||||
initH2GISExtensionsForInMemDb();
|
initH2GISExtensionsForInMemDb();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue