/
ParameterTranslationsImpl.java
160 lines (139 loc) · 5.31 KB
/
ParameterTranslationsImpl.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/*
* 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.hql.internal.ast;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hibernate.hql.spi.ParameterTranslations;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.param.NamedParameterSpecification;
import org.hibernate.param.ParameterSpecification;
import org.hibernate.param.PositionalParameterSpecification;
import org.hibernate.type.Type;
/**
* Defines the information available for parameters encountered during
* query translation through the antlr-based parser.
*
* @author Steve Ebersole
*/
public class ParameterTranslationsImpl implements ParameterTranslations {
private final Map<String,ParameterInfo> namedParameters;
private final ParameterInfo[] ordinalParameters;
@Override
public boolean supportsOrdinalParameterMetadata() {
return true;
}
@Override
public int getOrdinalParameterCount() {
return ordinalParameters.length;
}
public ParameterInfo getOrdinalParameterInfo(int ordinalPosition) {
// remember that ordinal parameters numbers are 1-based!!!
return ordinalParameters[ordinalPosition - 1];
}
@Override
public int getOrdinalParameterSqlLocation(int ordinalPosition) {
return getOrdinalParameterInfo( ordinalPosition ).getSqlLocations()[0];
}
@Override
public Type getOrdinalParameterExpectedType(int ordinalPosition) {
return getOrdinalParameterInfo( ordinalPosition ).getExpectedType();
}
@Override
public Set getNamedParameterNames() {
return namedParameters.keySet();
}
public ParameterInfo getNamedParameterInfo(String name) {
return namedParameters.get( name );
}
@Override
public int[] getNamedParameterSqlLocations(String name) {
return getNamedParameterInfo( name ).getSqlLocations();
}
@Override
public Type getNamedParameterExpectedType(String name) {
return getNamedParameterInfo( name ).getExpectedType();
}
/**
* Constructs a parameter metadata object given a list of parameter
* specifications.
* </p>
* Note: the order in the incoming list denotes the parameter's
* psudeo-position within the resulting sql statement.
*
* @param parameterSpecifications The parameter specifications
*/
public ParameterTranslationsImpl(List<ParameterSpecification> parameterSpecifications) {
class NamedParamTempHolder {
String name;
Type type;
List<Integer> positions = new ArrayList<Integer>();
}
final int size = parameterSpecifications.size();
final List<ParameterInfo> ordinalParameterList = new ArrayList<ParameterInfo>();
final Map<String,NamedParamTempHolder> namedParameterMap = new HashMap<String,NamedParamTempHolder>();
for ( int i = 0; i < size; i++ ) {
final ParameterSpecification spec = parameterSpecifications.get( i );
if ( PositionalParameterSpecification.class.isInstance( spec ) ) {
final PositionalParameterSpecification ordinalSpec = (PositionalParameterSpecification) spec;
ordinalParameterList.add( new ParameterInfo( i, ordinalSpec.getExpectedType() ) );
}
else if ( NamedParameterSpecification.class.isInstance( spec ) ) {
final NamedParameterSpecification namedSpec = (NamedParameterSpecification) spec;
NamedParamTempHolder paramHolder = namedParameterMap.get( namedSpec.getName() );
if ( paramHolder == null ) {
paramHolder = new NamedParamTempHolder();
paramHolder.name = namedSpec.getName();
paramHolder.type = namedSpec.getExpectedType();
namedParameterMap.put( namedSpec.getName(), paramHolder );
}
else if ( paramHolder.type == null && namedSpec.getExpectedType() != null ) {
// previous reference to the named parameter did not have type determined;
// this time, it can be determined by namedSpec.getExpectedType().
paramHolder.type = namedSpec.getExpectedType();
}
paramHolder.positions.add( i );
}
// don't care about other param types here, just those explicitly user-defined...
}
ordinalParameters = ordinalParameterList.toArray( new ParameterInfo[ordinalParameterList.size()] );
if ( namedParameterMap.isEmpty() ) {
namedParameters = java.util.Collections.emptyMap();
}
else {
final Map<String,ParameterInfo> namedParametersBacking = new HashMap<String,ParameterInfo>( namedParameterMap.size() );
for ( NamedParamTempHolder holder : namedParameterMap.values() ) {
namedParametersBacking.put(
holder.name,
new ParameterInfo( ArrayHelper.toIntArray( holder.positions ), holder.type )
);
}
namedParameters = java.util.Collections.unmodifiableMap( namedParametersBacking );
}
}
public static class ParameterInfo implements Serializable {
private final int[] sqlLocations;
private final Type expectedType;
public ParameterInfo(int[] sqlPositions, Type expectedType) {
this.sqlLocations = sqlPositions;
this.expectedType = expectedType;
}
public ParameterInfo(int sqlPosition, Type expectedType) {
this.sqlLocations = new int[] { sqlPosition };
this.expectedType = expectedType;
}
public int[] getSqlLocations() {
return sqlLocations;
}
public Type getExpectedType() {
return expectedType;
}
}
}