[OLINGO-1262] Parameter mismatch when multiple queries are executed in
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata2/repo Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata2/commit/53b631bf Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata2/tree/53b631bf Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata2/diff/53b631bf Branch: refs/heads/master Commit: 53b631bffb2b4e5194bdb1d44553b3f43163e2dc Parents: 2e18476 Author: ramya vasanth <ramya.vasa...@sap.com> Authored: Mon May 21 10:01:46 2018 +0530 Committer: ramya vasanth <ramya.vasa...@sap.com> Committed: Mon May 21 10:01:46 2018 +0530 ---------------------------------------------------------------------- .../jpa/processor/api/jpql/JPQLContext.java | 18 +- .../jpa/processor/api/jpql/JPQLContextView.java | 12 + .../api/jpql/JPQLSelectContextView.java | 8 + .../api/jpql/JPQLSelectSingleContextView.java | 8 + .../processor/core/ODataExpressionParser.java | 125 ++++--- .../ODataParameterizedWhereExpressionUtil.java | 56 --- .../core/access/data/JPAProcessorImpl.java | 36 -- .../core/access/data/JPAQueryBuilder.java | 110 +++++- .../core/jpql/JPQLJoinSelectContext.java | 22 +- .../core/jpql/JPQLJoinSelectSingleContext.java | 18 +- .../JPQLJoinSelectSingleStatementBuilder.java | 5 +- .../core/jpql/JPQLJoinStatementBuilder.java | 5 +- .../processor/core/jpql/JPQLSelectContext.java | 32 +- .../core/jpql/JPQLSelectSingleContext.java | 27 +- .../jpql/JPQLSelectSingleStatementBuilder.java | 21 +- .../core/jpql/JPQLSelectStatementBuilder.java | 5 +- .../core/ODataFilterExpressionParserTest.java | 5 +- .../core/access/data/JPAProcessorImplTest.java | 2 +- .../core/access/data/JPAQueryBuilderTest.java | 343 ++++++++++++++++++- ...PQLJoinSelectSingleStatementBuilderTest.java | 3 + .../core/jpql/JPQLJoinStatementBuilderTest.java | 6 + .../JPQLSelectSingleStatementBuilderTest.java | 21 +- .../core/mock/ODataJPAContextMock.java | 13 +- 23 files changed, 690 insertions(+), 211 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/53b631bf/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLContext.java ---------------------------------------------------------------------- diff --git a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLContext.java b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLContext.java index 672f808..f81c49a 100644 --- a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLContext.java +++ b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLContext.java @@ -53,6 +53,7 @@ public abstract class JPQLContext implements JPQLContextView { */ protected JPQLContextType type; protected boolean pagingRequested = false; + protected static final ThreadLocal<JPQLContext> jpqlContext = new ThreadLocal<JPQLContext>(); /** * sets JPA Entity Name into the context @@ -91,7 +92,7 @@ public abstract class JPQLContext implements JPQLContextView { protected final void setType(final JPQLContextType type) { this.type = type; } - + /** * gets the JPA entity name set into the context */ @@ -111,7 +112,7 @@ public abstract class JPQLContext implements JPQLContextView { protected void isPagingRequested(final boolean pagingRequested) { this.pagingRequested = pagingRequested; } - + /** * the method returns an instance of type * {@link org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContext.JPQLContextBuilder} based on the @@ -150,7 +151,18 @@ public abstract class JPQLContext implements JPQLContextView { throws ODataJPARuntimeException { return JPQLContextBuilder.create(contextType, resultsView, withPaging); } - + + protected static void setJPQLContext(JPQLContext context) { + jpqlContext.set(context); + } + + public final static JPQLContext getJPQLContext() { + return jpqlContext.get(); + } + + public final static void removeJPQLContext() { + jpqlContext.remove(); + } /** * The abstract class is extended by specific JPQLContext builder for * building JPQLContexts. http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/53b631bf/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLContextView.java ---------------------------------------------------------------------- diff --git a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLContextView.java b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLContextView.java index bee9c39..a37df47 100644 --- a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLContextView.java +++ b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLContextView.java @@ -50,4 +50,16 @@ public interface JPQLContextView { * @return an instance of type {@link org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContextType} */ public JPQLContextType getType(); + + /** + * Set the JPQL Statement to the context + * @param jpqlStatement + */ + public void setJPQLStatement(String jpqlStatement); + + /** + * Return the JPQL Statement set in context + * @return String JPQLStatement + */ + public String getJPQLStatement(); } http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/53b631bf/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLSelectContextView.java ---------------------------------------------------------------------- diff --git a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLSelectContextView.java b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLSelectContextView.java index 2fcc897..c62f700 100644 --- a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLSelectContextView.java +++ b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLSelectContextView.java @@ -18,6 +18,7 @@ ******************************************************************************/ package org.apache.olingo.odata2.jpa.processor.api.jpql; +import java.util.Map; /** * The interface provide a view on JPQL select context.The interface provides @@ -62,4 +63,11 @@ public interface JPQLSelectContextView extends JPQLContextView { * @return a String representing a WHERE condition in JPQL */ public String getWhereExpression(); + + /** + * Key in the map is the JPA query and value is a map with key being index and + * value being parameter value + * @return a map of String and value is another map of Integer and Object + */ + public Map<String, Map<Integer, Object>> getParameterizedQueryMap(); } http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/53b631bf/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLSelectSingleContextView.java ---------------------------------------------------------------------- diff --git a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLSelectSingleContextView.java b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLSelectSingleContextView.java index 2a4ca0c..5880dab 100644 --- a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLSelectSingleContextView.java +++ b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLSelectSingleContextView.java @@ -19,6 +19,7 @@ package org.apache.olingo.odata2.jpa.processor.api.jpql; import java.util.List; +import java.util.Map; import org.apache.olingo.odata2.api.uri.KeyPredicate; @@ -50,4 +51,11 @@ public interface JPQLSelectSingleContextView extends JPQLContextView { * @return a list of key predicates */ public List<KeyPredicate> getKeyPredicates(); + + /** + * Key in the map is the JPA query and value is a map with key being index and + * value being parameter value + * @return a map of String and value is another map of Integer and Object + */ + public Map<String, Map<Integer, Object>> getParameterizedQueryMap(); } http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/53b631bf/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/ODataExpressionParser.java ---------------------------------------------------------------------- diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/ODataExpressionParser.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/ODataExpressionParser.java index 3ccb290..18d581b 100644 --- a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/ODataExpressionParser.java +++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/ODataExpressionParser.java @@ -23,10 +23,12 @@ import java.math.BigInteger; import java.sql.Time; import java.util.ArrayList; import java.util.Calendar; -import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; +import java.util.TreeMap; +import java.util.concurrent.ConcurrentHashMap; import org.apache.olingo.odata2.api.edm.EdmException; import org.apache.olingo.odata2.api.edm.EdmLiteral; @@ -70,24 +72,30 @@ public class ODataExpressionParser { public static final String EMPTY = ""; //$NON-NLS-1$ public static final ThreadLocal<Integer> methodFlag = new ThreadLocal<Integer>(); public static final Character[] EMPTY_CHARACTER_ARRAY = new Character[0]; - private static int index = 1; - private static Map<Integer, Object> positionalParameters = new HashMap<Integer, Object>(); + public static final ThreadLocal<Map<Integer, Object>> positionalParameters = new ThreadLocal<Map<Integer,Object>>(); /** * This method returns the parsed where condition corresponding to the filter input in the user query. * * @param whereExpression + * @param concurrentHashMap + * @param index * * @return Parsed where condition String * @throws ODataException */ - public static String parseToJPAWhereExpression(final CommonExpression whereExpression, final String tableAlias) throws ODataException { + return parseToJPAWhereExpression(whereExpression, tableAlias, 1, new ConcurrentHashMap<Integer,Object>()); + } + + public static String parseToJPAWhereExpression(final CommonExpression whereExpression, final String tableAlias, + int index, ConcurrentHashMap<Integer,Object> positionalParameters) throws ODataException { switch (whereExpression.getKind()) { case UNARY: final UnaryExpression unaryExpression = (UnaryExpression) whereExpression; - final String operand = parseToJPAWhereExpression(unaryExpression.getOperand(), tableAlias); + final String operand = parseToJPAWhereExpression(unaryExpression.getOperand(), tableAlias, + index, positionalParameters); switch (unaryExpression.getOperator()) { case NOT: @@ -100,12 +108,12 @@ public class ODataExpressionParser { return "-" + operand; //$NON-NLS-1$ } default: - reInitializePositionalParameters(); throw new ODataNotImplementedException(); } case FILTER: - return parseToJPAWhereExpression(((FilterExpression) whereExpression).getExpression(), tableAlias); + return parseToJPAWhereExpression(((FilterExpression) whereExpression).getExpression(), tableAlias, + index, positionalParameters); case BINARY: final BinaryExpression binaryExpression = (BinaryExpression) whereExpression; MethodOperator operator = null; @@ -118,16 +126,16 @@ public class ODataExpressionParser { methodFlag.set(1); } } - final String left = parseToJPAWhereExpression(binaryExpression.getLeftOperand(), tableAlias); - index++; - final String right = parseToJPAWhereExpression(binaryExpression.getRightOperand(), tableAlias); + final String left = parseToJPAWhereExpression(binaryExpression.getLeftOperand(), tableAlias, + getIndexValue(positionalParameters), positionalParameters); + final String right = parseToJPAWhereExpression(binaryExpression.getRightOperand(), tableAlias, + getIndexValue(positionalParameters), positionalParameters); // Special handling for STARTSWITH and ENDSWITH method expression if (operator != null && (operator == MethodOperator.STARTSWITH || operator == MethodOperator.ENDSWITH)) { if (!binaryExpression.getOperator().equals(BinaryOperator.EQ) && !(binaryExpression.getRightOperand() instanceof LiteralExpression) && ("true".equals(right) || "false".equals(right))) { - reInitializePositionalParameters(); throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.OPERATOR_EQ_NE_MISSING .addContent(binaryExpression.getOperator().toString()), null); } else if (binaryExpression.getOperator().equals(BinaryOperator.EQ)) { @@ -185,10 +193,8 @@ public class ODataExpressionParser { + JPQLStatement.Operator.GE + JPQLStatement.DELIMITER.SPACE + right + JPQLStatement.DELIMITER.PARENTHESIS_RIGHT; case PROPERTY_ACCESS: - reInitializePositionalParameters(); throw new ODataNotImplementedException(); default: - reInitializePositionalParameters(); throw new ODataNotImplementedException(); } @@ -220,19 +226,19 @@ public class ODataExpressionParser { final LiteralExpression literal = (LiteralExpression) whereExpression; final EdmSimpleType literalType = (EdmSimpleType) literal.getEdmType(); EdmLiteral uriLiteral = EdmSimpleTypeKind.parseUriLiteral(literal.getUriLiteral()); - return evaluateComparingExpression(uriLiteral.getLiteral(), literalType, null); + return evaluateComparingExpression(uriLiteral.getLiteral(), literalType, null, + positionalParameters, index); case METHOD: final MethodExpression methodExpression = (MethodExpression) whereExpression; - String first = parseToJPAWhereExpression(methodExpression.getParameters().get(0), tableAlias); - index++; + String first = parseToJPAWhereExpression(methodExpression.getParameters().get(0), tableAlias, + getIndexValue(positionalParameters), positionalParameters); String second = methodExpression.getParameterCount() > 1 ? parseToJPAWhereExpression(methodExpression.getParameters().get(1), - tableAlias) : null; - index++; + tableAlias, getIndexValue(positionalParameters), positionalParameters) : null; String third = methodExpression.getParameterCount() > 2 ? parseToJPAWhereExpression(methodExpression.getParameters().get(2), - tableAlias) : null; + tableAlias, getIndexValue(positionalParameters), positionalParameters) : null; switch (methodExpression.getMethod()) { case SUBSTRING: @@ -256,7 +262,6 @@ public class ODataExpressionParser { case ENDSWITH: return String.format("%s LIKE CONCAT('%%',%s) ESCAPE '\\'", first, second); default: - reInitializePositionalParameters(); throw new ODataNotImplementedException(); } @@ -265,13 +270,12 @@ public class ODataExpressionParser { } } - public static Map<Integer, Object> getPositionalParameters() { - return positionalParameters; - } - - public static void reInitializePositionalParameters() { - index = 1; - positionalParameters = new HashMap<Integer, Object>(); + private static int getIndexValue(Map<Integer, Object> map) { + int index = 1; + for (Entry<Integer, Object> entry : map.entrySet()) { + index = entry.getKey(); + } + return index + 1; } /** @@ -349,7 +353,8 @@ public class ODataExpressionParser { try { if (orderBy.getExpression().getKind() == ExpressionKind.MEMBER) { - orderByField = parseToJPAWhereExpression(orderBy.getExpression(), tableAlias); + orderByField = parseToJPAWhereExpression(orderBy.getExpression(), tableAlias, 1, + new ConcurrentHashMap<Integer, Object>()); } else { orderByField = tableAlias + JPQLStatement.DELIMITER.PERIOD + getPropertyName(orderBy.getExpression()); } @@ -383,6 +388,7 @@ public class ODataExpressionParser { public static String parseKeyPredicates(final List<KeyPredicate> keyPredicates, final String tableAlias) throws ODataJPARuntimeException { + Map<Integer, Object> positionalParameters = new ConcurrentHashMap<Integer, Object>(); String literal = null; String propertyName = null; EdmSimpleType edmSimpleType = null; @@ -390,6 +396,9 @@ public class ODataExpressionParser { StringBuilder keyFilters = new StringBuilder(); int i = 0; for (KeyPredicate keyPredicate : keyPredicates) { + int index = null == getPositionalParametersThreadLocal() || + getPositionalParametersThreadLocal().size() == 0 ? 1 : + getIndexValue(getPositionalParametersThreadLocal()); if (i > 0) { keyFilters.append(JPQLStatement.DELIMITER.SPACE + JPQLStatement.Operator.AND + JPQLStatement.DELIMITER.SPACE); } @@ -403,7 +412,7 @@ public class ODataExpressionParser { throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e); } - literal = evaluateComparingExpression(literal, edmSimpleType, edmMappedType); + literal = evaluateComparingExpression(literal, edmSimpleType, edmMappedType, positionalParameters, index); if(edmSimpleType == EdmSimpleTypeKind.String.getEdmSimpleTypeInstance()){ keyFilters.append(tableAlias + JPQLStatement.DELIMITER.PERIOD + propertyName + JPQLStatement.DELIMITER.SPACE @@ -415,10 +424,6 @@ public class ODataExpressionParser { } } if (keyFilters.length() > 0) { - Map<String, Map<Integer, Object>> parameterizedExpressionMap = - new HashMap<String, Map<Integer,Object>>(); - parameterizedExpressionMap.put(keyFilters.toString(), ODataExpressionParser.getPositionalParameters()); - ODataParameterizedWhereExpressionUtil.setParameterizedQueryMap(parameterizedExpressionMap); return keyFilters.toString(); } else { return null; @@ -470,25 +475,25 @@ public class ODataExpressionParser { * @param uriLiteral * @param edmSimpleType * @param edmMappedType + * @param index + * @param positionalParameter * @return the evaluated expression * @throws ODataJPARuntimeException */ private static String evaluateComparingExpression(String uriLiteral, final EdmSimpleType edmSimpleType, - Class<?> edmMappedType) throws ODataJPARuntimeException { - + Class<?> edmMappedType, Map<Integer, Object> positionalParameters, int index) throws ODataJPARuntimeException { if (EdmSimpleTypeKind.String.getEdmSimpleTypeInstance().isCompatible(edmSimpleType) || EdmSimpleTypeKind.Guid.getEdmSimpleTypeInstance().isCompatible(edmSimpleType)) { uriLiteral = uriLiteral.replaceAll("'", "''"); uriLiteral = updateValueIfWildcards(uriLiteral); if (!positionalParameters.containsKey(index)) { if(edmMappedType != null){ - evaluateExpressionForString(uriLiteral, edmMappedType); + evaluateExpressionForString(uriLiteral, edmMappedType, positionalParameters, index); }else{ positionalParameters.put(index, String.valueOf(uriLiteral)); } } uriLiteral = "?" + index; - index++; } else if (EdmSimpleTypeKind.DateTime.getEdmSimpleTypeInstance().isCompatible(edmSimpleType) || EdmSimpleTypeKind.DateTimeOffset.getEdmSimpleTypeInstance().isCompatible(edmSimpleType)) { try { @@ -500,7 +505,6 @@ public class ODataExpressionParser { positionalParameters.put(index, datetime); } uriLiteral = "?" + index; - index++; } catch (EdmSimpleTypeException e) { throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e); @@ -522,43 +526,44 @@ public class ODataExpressionParser { positionalParameters.put(index, Time.valueOf(uriLiteral)); } uriLiteral = "?" + index; - index++; } catch (EdmSimpleTypeException e) { throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e); } - } else { - uriLiteral = evaluateExpressionForNumbers(uriLiteral, edmSimpleType, edmMappedType); + uriLiteral = evaluateExpressionForNumbers(uriLiteral, edmSimpleType, edmMappedType, + positionalParameters, index); } + removePositionalParametersThreadLocal(); + setPositionalParametersThreadLocal(positionalParameters); return uriLiteral; } private static String evaluateExpressionForNumbers(String uriLiteral, EdmSimpleType edmSimpleType, - Class<?> edmMappedType) { + Class<?> edmMappedType, Map<Integer, Object> positionalParameters, int index) { Class<? extends Object> type = edmMappedType==null? edmSimpleType.getDefaultType(): edmMappedType; int size = positionalParameters.size(); - if (Long.class.equals(type)) { + if (Long.class.equals(type) || long.class.equals(type)) { if (!positionalParameters.containsKey(index)) { positionalParameters.put(index, Long.valueOf(uriLiteral)); } - } else if (Double.class.equals(type)) { + } else if (Double.class.equals(type) || double.class.equals(type)) { if (!positionalParameters.containsKey(index)) { positionalParameters.put(index, Double.valueOf(uriLiteral)); } - } else if (Integer.class.equals(type)) { + } else if (Integer.class.equals(type) || int.class.equals(type)) { if (!positionalParameters.containsKey(index)) { positionalParameters.put(index, Integer.valueOf(uriLiteral)); } - } else if (Byte.class.equals(type)) { + } else if (Byte.class.equals(type) || byte.class.equals(type)) { if (!positionalParameters.containsKey(index)) { positionalParameters.put(index, Byte.valueOf(uriLiteral)); } - } else if (Byte[].class.equals(type)) { + } else if (Byte[].class.equals(type) || byte[].class.equals(type)) { if (!positionalParameters.containsKey(index)) { positionalParameters.put(index, toByteArray(uriLiteral)); } - } else if (Short.class.equals(type)) { + } else if (Short.class.equals(type) || short.class.equals(type)) { if (!positionalParameters.containsKey(index)) { positionalParameters.put(index, Short.valueOf(uriLiteral)); } @@ -570,20 +575,19 @@ public class ODataExpressionParser { if (!positionalParameters.containsKey(index)) { positionalParameters.put(index, new BigInteger(uriLiteral)); } - } else if (Float.class.equals(type)) { + } else if (Float.class.equals(type) || float.class.equals(type)) { if (!positionalParameters.containsKey(index)) { positionalParameters.put(index, Float.valueOf(uriLiteral)); } } if(size+1 == positionalParameters.size()){ uriLiteral = "?" + index; - index++; } return uriLiteral; } - private static void evaluateExpressionForString(String uriLiteral, Class<?> edmMappedType) { - + private static void evaluateExpressionForString(String uriLiteral, Class<?> edmMappedType, + Map<Integer, Object> positionalParameters, int index) { if(edmMappedType.equals(char[].class)){ positionalParameters.put(index, uriLiteral.toCharArray()); }else if(edmMappedType.equals(char.class)){ @@ -597,7 +601,6 @@ public class ODataExpressionParser { }else { positionalParameters.put(index, String.valueOf(uriLiteral)); } - } private static String getPropertyName(final CommonExpression whereExpression) throws EdmException, @@ -616,4 +619,20 @@ public class ODataExpressionParser { return mapping != null ? mapping.getInternalName() : edmProperty.getName(); } + public static void setPositionalParametersThreadLocal(final Map<Integer, Object> parameter) { + if (null != getPositionalParametersThreadLocal() && + getPositionalParametersThreadLocal().size() > 0) { + parameter.putAll(getPositionalParametersThreadLocal()); + } + TreeMap<Integer, Object> map = new TreeMap<Integer, Object>(parameter); + positionalParameters.set(map); + } + + public static Map<Integer, Object> getPositionalParametersThreadLocal() { + return positionalParameters.get(); + } + + public static void removePositionalParametersThreadLocal() { + positionalParameters.remove(); + } } http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/53b631bf/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/ODataParameterizedWhereExpressionUtil.java ---------------------------------------------------------------------- diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/ODataParameterizedWhereExpressionUtil.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/ODataParameterizedWhereExpressionUtil.java deleted file mode 100644 index 2ba6026..0000000 --- a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/ODataParameterizedWhereExpressionUtil.java +++ /dev/null @@ -1,56 +0,0 @@ -/******************************************************************************* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - ******************************************************************************/ -package org.apache.olingo.odata2.jpa.processor.core; - -import java.util.HashMap; -import java.util.Map; - -public class ODataParameterizedWhereExpressionUtil { - /** - * Map includes where expression clause as the key and the - * ODataParameterizedWhereExpression as the value - */ - private static Map<String, Map<Integer, Object>> parameterizedQueryMap = new - HashMap<String, Map<Integer,Object>>(); - - private static String jpqlStatement = null; - - /** - * @return the parameterizedQueryMap - */ - public static Map<String, Map<Integer, Object>> getParameterizedQueryMap() { - return parameterizedQueryMap; - } - - /** - * @param parameterizedQueryMap the parameterizedQueryMap to set - */ - public static void setParameterizedQueryMap(Map<String, Map<Integer, Object>> parameterizedQueryMap) { - ODataParameterizedWhereExpressionUtil.parameterizedQueryMap = parameterizedQueryMap; - } - - public static void setJPQLStatement(String jpqlStatement) { - ODataParameterizedWhereExpressionUtil.jpqlStatement = jpqlStatement; - } - - public static String getJPQLStatement() { - return jpqlStatement; - } - -} http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/53b631bf/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImpl.java ---------------------------------------------------------------------- diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImpl.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImpl.java index 646d8d6..f2caceb 100644 --- a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImpl.java +++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImpl.java @@ -21,18 +21,13 @@ package org.apache.olingo.odata2.jpa.processor.core.access.data; import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.sql.Time; -import java.sql.Timestamp; import java.util.ArrayList; -import java.util.Calendar; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import javax.persistence.EntityManager; import javax.persistence.PersistenceException; import javax.persistence.Query; -import javax.persistence.TemporalType; import org.apache.olingo.odata2.api.commons.InlineCount; import org.apache.olingo.odata2.api.edm.EdmEntitySet; @@ -65,7 +60,6 @@ import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeExcep import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContextType; import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmMapping; import org.apache.olingo.odata2.jpa.processor.core.ODataEntityParser; -import org.apache.olingo.odata2.jpa.processor.core.ODataParameterizedWhereExpressionUtil; import org.apache.olingo.odata2.jpa.processor.core.access.data.JPAPage.JPAPageBuilder; import org.apache.olingo.odata2.jpa.processor.core.access.data.JPAQueryBuilder.JPAQueryInfo; @@ -153,7 +147,6 @@ public class JPAProcessorImpl implements JPAProcessor { JPAQueryBuilder queryBuilder = new JPAQueryBuilder(oDataJPAContext); JPAQueryInfo queryInfo = queryBuilder.build(uriParserResultView); Query query = queryInfo.getQuery(); - setPositionalParametersToQuery(query); ODataJPATombstoneEntityListener listener = queryBuilder.getODataJPATombstoneEntityListener((UriInfo) uriParserResultView); Map<String, String> customQueryOptions = uriParserResultView.getCustomQueryOptions(); @@ -188,33 +181,6 @@ public class JPAProcessorImpl implements JPAProcessor { } } - /** - * @param query - */ - private void setPositionalParametersToQuery(Query query) { - Map<String, Map<Integer, Object>> parameterizedMap = ODataParameterizedWhereExpressionUtil. - getParameterizedQueryMap(); - if (parameterizedMap != null && parameterizedMap.size() > 0) { - for (Entry<String, Map<Integer, Object>> parameterEntry : parameterizedMap.entrySet()) { - if (ODataParameterizedWhereExpressionUtil.getJPQLStatement().contains(parameterEntry.getKey())) { - Map<Integer, Object> positionalParameters = parameterEntry.getValue(); - for (Entry<Integer, Object> param : positionalParameters.entrySet()) { - if (param.getValue() instanceof Calendar || param.getValue() instanceof Timestamp) { - query.setParameter(param.getKey(), (Calendar) param.getValue(), TemporalType.TIMESTAMP); - } else if (param.getValue() instanceof Time) { - query.setParameter(param.getKey(), (Time) param.getValue(), TemporalType.TIME); - } else { - query.setParameter(param.getKey(), param.getValue()); - } - } - parameterizedMap.remove(parameterEntry.getKey()); - ODataParameterizedWhereExpressionUtil.setJPQLStatement(null); - break; - } - } - } - } - /* Process Get Entity Request (Read) */ @Override public <T> Object process(GetEntityUriInfo uriParserResultView) @@ -229,7 +195,6 @@ public class JPAProcessorImpl implements JPAProcessor { JPAQueryBuilder queryBuilder = new JPAQueryBuilder(oDataJPAContext); Query query = queryBuilder.build(resultsView); - setPositionalParametersToQuery(query); List<?> resultList = query.getResultList(); if (resultList != null && resultList.size() == 1) { return Long.valueOf(resultList.get(0).toString()); @@ -244,7 +209,6 @@ public class JPAProcessorImpl implements JPAProcessor { JPAQueryBuilder queryBuilder = new JPAQueryBuilder(oDataJPAContext); Query query = queryBuilder.build(resultsView); - setPositionalParametersToQuery(query); List<?> resultList = query.getResultList(); if (resultList != null && resultList.size() == 1) { return Long.valueOf(resultList.get(0).toString()); http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/53b631bf/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAQueryBuilder.java ---------------------------------------------------------------------- diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAQueryBuilder.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAQueryBuilder.java index b1d1a99..b3ed847 100644 --- a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAQueryBuilder.java +++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAQueryBuilder.java @@ -25,6 +25,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -49,9 +50,15 @@ import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPAModelExcepti import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException; import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContext; import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContextType; +import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContextView; +import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLJoinContextView; +import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLJoinSelectSingleContextView; +import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLSelectContextView; +import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLSelectSingleContextView; import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLStatement; import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmMapping; -import org.apache.olingo.odata2.jpa.processor.core.ODataParameterizedWhereExpressionUtil; +import org.apache.olingo.odata2.jpa.processor.core.ODataExpressionParser; +import org.apache.olingo.odata2.jpa.processor.core.jpql.JPQLSelectContext; public class JPAQueryBuilder { @@ -79,6 +86,8 @@ public class JPAQueryBuilder { ODataJPATombstoneEntityListener listener = getODataJPATombstoneEntityListener((UriInfo) uriInfo); if (listener != null) { query = listener.getQuery(uriInfo, em); + JPQLContext jpqlContext = JPQLContext.getJPQLContext(); + query = getParameterizedQueryForListeners(jpqlContext, query); } if (query == null) { query = buildQuery((UriInfo) uriInfo, UriInfoType.GetEntitySet); @@ -88,6 +97,9 @@ public class JPAQueryBuilder { } catch (Exception e) { throw ODataJPARuntimeException.throwException( ODataJPARuntimeException.ERROR_JPQL_QUERY_CREATE, e); + } finally { + JPQLContext.removeJPQLContext(); + ODataExpressionParser.removePositionalParametersThreadLocal(); } queryInfo.setQuery(query); return queryInfo; @@ -99,6 +111,8 @@ public class JPAQueryBuilder { ODataJPAQueryExtensionEntityListener listener = getODataJPAQueryEntityListener((UriInfo) uriInfo); if (listener != null) { query = listener.getQuery(uriInfo, em); + JPQLContext jpqlContext = JPQLContext.getJPQLContext(); + query = getParameterizedQueryForListeners(jpqlContext, query); } if (query == null) { query = buildQuery((UriInfo) uriInfo, UriInfoType.GetEntity); @@ -106,6 +120,9 @@ public class JPAQueryBuilder { } catch (Exception e) { throw ODataJPARuntimeException.throwException( ODataJPARuntimeException.ERROR_JPQL_QUERY_CREATE, e); + } finally { + JPQLContext.removeJPQLContext(); + ODataExpressionParser.removePositionalParametersThreadLocal(); } return query; } @@ -116,6 +133,8 @@ public class JPAQueryBuilder { ODataJPAQueryExtensionEntityListener listener = getODataJPAQueryEntityListener((UriInfo) uriInfo); if (listener != null) { query = listener.getQuery(uriInfo, em); + JPQLContext jpqlContext = JPQLContext.getJPQLContext(); + query = getParameterizedQueryForListeners(jpqlContext, query); } if (query == null) { query = buildQuery((UriInfo) uriInfo, UriInfoType.GetEntitySetCount); @@ -123,6 +142,9 @@ public class JPAQueryBuilder { } catch (Exception e) { throw ODataJPARuntimeException.throwException( ODataJPARuntimeException.ERROR_JPQL_QUERY_CREATE, e); + } finally { + JPQLContext.removeJPQLContext(); + ODataExpressionParser.removePositionalParametersThreadLocal(); } return query; } @@ -133,6 +155,8 @@ public class JPAQueryBuilder { ODataJPAQueryExtensionEntityListener listener = getODataJPAQueryEntityListener((UriInfo) uriInfo); if (listener != null) { query = listener.getQuery(uriInfo, em); + JPQLContext jpqlContext = JPQLContext.getJPQLContext(); + query = getParameterizedQueryForListeners(jpqlContext, query); } if (query == null) { query = buildQuery((UriInfo) uriInfo, UriInfoType.GetEntityCount); @@ -140,6 +164,9 @@ public class JPAQueryBuilder { } catch (Exception e) { throw ODataJPARuntimeException.throwException( ODataJPARuntimeException.ERROR_JPQL_QUERY_CREATE, e); + } finally { + JPQLContext.removeJPQLContext(); + ODataExpressionParser.removePositionalParametersThreadLocal(); } return query; } @@ -150,6 +177,8 @@ public class JPAQueryBuilder { ODataJPAQueryExtensionEntityListener listener = getODataJPAQueryEntityListener((UriInfo) uriInfo); if (listener != null) { query = listener.getQuery(uriInfo, em); + JPQLContext jpqlContext = JPQLContext.getJPQLContext(); + query = getParameterizedQueryForListeners(jpqlContext, query); } if (query == null) { query = buildQuery((UriInfo) uriInfo, UriInfoType.Delete); @@ -157,6 +186,9 @@ public class JPAQueryBuilder { } catch (Exception e) { throw ODataJPARuntimeException.throwException( ODataJPARuntimeException.ERROR_JPQL_QUERY_CREATE, e); + } finally { + JPQLContext.removeJPQLContext(); + ODataExpressionParser.removePositionalParametersThreadLocal(); } return query; } @@ -167,6 +199,8 @@ public class JPAQueryBuilder { ODataJPAQueryExtensionEntityListener listener = getODataJPAQueryEntityListener((UriInfo) uriInfo); if (listener != null) { query = listener.getQuery(uriInfo, em); + JPQLContext jpqlContext = JPQLContext.getJPQLContext(); + query = getParameterizedQueryForListeners(jpqlContext, query); } if (query == null) { query = buildQuery((UriInfo) uriInfo, UriInfoType.PutMergePatch); @@ -174,6 +208,9 @@ public class JPAQueryBuilder { } catch (Exception e) { throw ODataJPARuntimeException.throwException( ODataJPARuntimeException.ERROR_JPQL_QUERY_CREATE, e); + } finally { + JPQLContext.removeJPQLContext(); + ODataExpressionParser.removePositionalParametersThreadLocal(); } return query; } @@ -185,10 +222,30 @@ public class JPAQueryBuilder { JPQLContextType contextType = determineJPQLContextType(uriParserResultView, type); JPQLContext jpqlContext = buildJPQLContext(contextType, uriParserResultView); JPQLStatement jpqlStatement = JPQLStatement.createBuilder(jpqlContext).build(); - + Query query = em.createQuery(normalizeMembers(em, jpqlStatement.toString())); - Map<String, Map<Integer, Object>> parameterizedMap = ODataParameterizedWhereExpressionUtil. - getParameterizedQueryMap(); + getParameterizedQuery(contextType, jpqlContext, jpqlStatement, query); + return query; + } + + /** + * @param contextType + * @param jpqlContext + * @param jpqlStatement + * @param query + */ + private Query getParameterizedQuery(JPQLContextType contextType, JPQLContext jpqlContext, JPQLStatement jpqlStatement, + Query query) { + Map<String, Map<Integer, Object>> parameterizedMap = null; + if (contextType == JPQLContextType.JOIN || contextType == JPQLContextType.JOIN_COUNT) { + parameterizedMap = ((JPQLJoinContextView) jpqlContext).getParameterizedQueryMap(); + } else if (contextType == JPQLContextType.JOIN_SINGLE) { + parameterizedMap = ((JPQLJoinSelectSingleContextView) jpqlContext).getParameterizedQueryMap(); + } else if (contextType == JPQLContextType.SELECT || contextType == JPQLContextType.SELECT_COUNT) { + parameterizedMap = ((JPQLSelectContextView) jpqlContext).getParameterizedQueryMap(); + } else if (contextType == JPQLContextType.SELECT_SINGLE) { + parameterizedMap = ((JPQLSelectSingleContextView) jpqlContext).getParameterizedQueryMap(); + } if (parameterizedMap != null && parameterizedMap.size() > 0) { for (Entry<String, Map<Integer, Object>> parameterEntry : parameterizedMap.entrySet()) { if (jpqlStatement.toString().contains(parameterEntry.getKey())) { @@ -202,16 +259,46 @@ public class JPAQueryBuilder { query.setParameter(param.getKey(), param.getValue()); } } - parameterizedMap.remove(parameterEntry.getKey()); - ODataParameterizedWhereExpressionUtil.setJPQLStatement(null); - break; } } - } + } return query; } - + private Query getParameterizedQueryForListeners(JPQLContext jpqlContext, Query query) { + Map<String, Map<Integer, Object>> parameterizedMap = null; + String jpqlStatement = null; + if (jpqlContext instanceof JPQLJoinContextView) { + parameterizedMap = ((JPQLJoinContextView) jpqlContext).getParameterizedQueryMap(); + jpqlStatement = ((JPQLJoinContextView) jpqlContext).getJPQLStatement(); + } else if (jpqlContext instanceof JPQLJoinSelectSingleContextView) { + parameterizedMap = ((JPQLJoinSelectSingleContextView) jpqlContext).getParameterizedQueryMap(); + jpqlStatement = ((JPQLJoinSelectSingleContextView) jpqlContext).getJPQLStatement(); + } else if (jpqlContext instanceof JPQLSelectContextView) { + parameterizedMap = ((JPQLSelectContextView) jpqlContext).getParameterizedQueryMap(); + jpqlStatement = ((JPQLSelectContextView) jpqlContext).getJPQLStatement(); + } else if (jpqlContext instanceof JPQLSelectSingleContextView) { + parameterizedMap = ((JPQLSelectSingleContextView) jpqlContext).getParameterizedQueryMap(); + jpqlStatement = ((JPQLSelectSingleContextView) jpqlContext).getJPQLStatement(); + } + if (parameterizedMap != null && parameterizedMap.size() > 0) { + for (Entry<String, Map<Integer, Object>> parameterEntry : parameterizedMap.entrySet()) { + if (jpqlStatement.contains(parameterEntry.getKey())) { + Map<Integer, Object> positionalParameters = parameterEntry.getValue(); + for (Entry<Integer, Object> param : positionalParameters.entrySet()) { + if (param.getValue() instanceof Calendar || param.getValue() instanceof Timestamp) { + query.setParameter(param.getKey(), (Calendar) param.getValue(), TemporalType.TIMESTAMP); + } else if (param.getValue() instanceof Time) { + query.setParameter(param.getKey(), (Time) param.getValue(), TemporalType.TIME); + } else { + query.setParameter(param.getKey(), param.getValue()); + } + } + } + } + } + return query; + } public ODataJPAQueryExtensionEntityListener getODataJPAQueryEntityListener(UriInfo uriInfo) throws EdmException, InstantiationException, IllegalAccessException { @@ -226,7 +313,7 @@ public class JPAQueryBuilder { public ODataJPATombstoneEntityListener getODataJPATombstoneEntityListener(UriInfo uriParserResultView) throws InstantiationException, IllegalAccessException, EdmException { JPAEdmMapping mapping = (JPAEdmMapping) uriParserResultView.getTargetEntitySet().getEntityType().getMapping(); - if (mapping.getODataJPATombstoneEntityListener() != null) { + if (null != mapping && mapping.getODataJPATombstoneEntityListener() != null) { return (ODataJPATombstoneEntityListener) mapping.getODataJPATombstoneEntityListener().newInstance(); } return null; @@ -244,7 +331,8 @@ public class JPAQueryBuilder { public JPQLContextType determineJPQLContextType(UriInfo uriParserResultView, UriInfoType type) { JPQLContextType contextType = null; - if (!uriParserResultView.getNavigationSegments().isEmpty()) { + if (uriParserResultView.getNavigationSegments() != null && + !uriParserResultView.getNavigationSegments().isEmpty()) { if (type == UriInfoType.GetEntitySet) { contextType = JPQLContextType.JOIN; } else if (type == UriInfoType.Delete || type == UriInfoType.GetEntity http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/53b631bf/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectContext.java ---------------------------------------------------------------------- diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectContext.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectContext.java index 9812327..59e124c 100644 --- a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectContext.java +++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectContext.java @@ -19,7 +19,9 @@ package org.apache.olingo.odata2.jpa.processor.core.jpql; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.apache.olingo.odata2.api.edm.EdmEntityType; import org.apache.olingo.odata2.api.edm.EdmException; @@ -79,10 +81,14 @@ public class JPQLJoinSelectContext extends JPQLSelectContext implements JPQLJoin setSelectExpression(generateSelectExpression()); setWhereExpression(generateWhereExpression()); + + setJPQLContext(JPQLJoinSelectContext.this); } catch (ODataException e) { throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e); } + + return JPQLJoinSelectContext.this; } @@ -92,9 +98,16 @@ public class JPQLJoinSelectContext extends JPQLSelectContext implements JPQLJoin List<JPAJoinClause> jpaOuterJoinClauses = new ArrayList<JPAJoinClause>(); JPAJoinClause jpaOuterJoinClause = null; String joinCondition = null; + Map<String, Map<Integer, Object>> parameterizedExpressionMap = + new HashMap<String, Map<Integer,Object>>(); String entityAlias = generateJPAEntityAlias(); joinCondition = ODataExpressionParser.parseKeyPredicates(entitySetView.getKeyPredicates(), entityAlias); - + + if (joinCondition != null) { + parameterizedExpressionMap.put(joinCondition, + ODataExpressionParser.getPositionalParametersThreadLocal()); + } + EdmEntityType entityType = entitySetView.getStartEntitySet().getEntityType(); Mapping mapping = (Mapping) entityType.getMapping(); String entityTypeName = null; @@ -118,6 +131,11 @@ public class JPQLJoinSelectContext extends JPQLSelectContext implements JPQLJoin joinCondition = ODataExpressionParser.parseKeyPredicates(navigationSegment.getKeyPredicates(), relationShipAlias); + if (joinCondition != null) { + parameterizedExpressionMap.put(joinCondition, + ODataExpressionParser.getPositionalParametersThreadLocal()); + } + jpaOuterJoinClause = new JPAJoinClause(getFromEntityName(navigationProperty), entityAlias, getRelationShipName(navigationProperty), relationShipAlias, joinCondition, JPAJoinClause.JOIN.INNER); @@ -125,7 +143,7 @@ public class JPQLJoinSelectContext extends JPQLSelectContext implements JPQLJoin jpaOuterJoinClauses.add(jpaOuterJoinClause); } - + setParameterizedQueryMap(parameterizedExpressionMap); return jpaOuterJoinClauses; } http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/53b631bf/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleContext.java ---------------------------------------------------------------------- diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleContext.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleContext.java index 3ebf1c6..1bdae36 100644 --- a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleContext.java +++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleContext.java @@ -19,7 +19,9 @@ package org.apache.olingo.odata2.jpa.processor.core.jpql; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.apache.olingo.odata2.api.edm.EdmEntityType; import org.apache.olingo.odata2.api.edm.EdmException; @@ -63,7 +65,7 @@ public class JPQLJoinSelectSingleContext extends JPQLSelectSingleContext impleme setSelectExpression(generateSelectExpression()); - ODataExpressionParser.reInitializePositionalParameters(); + setJPQLContext(JPQLJoinSelectSingleContext.this); } catch (EdmException e) { throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL, e); @@ -77,9 +79,16 @@ public class JPQLJoinSelectSingleContext extends JPQLSelectSingleContext impleme List<JPAJoinClause> jpaOuterJoinClauses = new ArrayList<JPAJoinClause>(); JPAJoinClause jpaOuterJoinClause = null; String joinCondition = null; + Map<String, Map<Integer, Object>> parameterizedExpressionMap = + new HashMap<String, Map<Integer,Object>>(); String entityAlias = generateJPAEntityAlias(); joinCondition = ODataExpressionParser.parseKeyPredicates(entityView.getKeyPredicates(), entityAlias); + if (joinCondition != null) { + parameterizedExpressionMap.put(joinCondition, + ODataExpressionParser.getPositionalParametersThreadLocal()); + } + EdmEntityType entityType = entityView.getStartEntitySet().getEntityType(); Mapping mapping = (Mapping) entityType.getMapping(); String entityTypeName = null; @@ -103,6 +112,11 @@ public class JPQLJoinSelectSingleContext extends JPQLSelectSingleContext impleme joinCondition = ODataExpressionParser.parseKeyPredicates(navigationSegment.getKeyPredicates(), relationShipAlias); + if (joinCondition != null) { + parameterizedExpressionMap.put(joinCondition, + ODataExpressionParser.getPositionalParametersThreadLocal()); + } + jpaOuterJoinClause = new JPAJoinClause(getFromEntityName(navigationProperty), entityAlias, getRelationShipName(navigationProperty), relationShipAlias, joinCondition, JPAJoinClause.JOIN.INNER); @@ -110,7 +124,7 @@ public class JPQLJoinSelectSingleContext extends JPQLSelectSingleContext impleme jpaOuterJoinClauses.add(jpaOuterJoinClause); } - + setParameterizedQueryMap(parameterizedExpressionMap); return jpaOuterJoinClauses; } http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/53b631bf/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleStatementBuilder.java ---------------------------------------------------------------------- diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleStatementBuilder.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleStatementBuilder.java index da66916..9479dc9 100644 --- a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleStatementBuilder.java +++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleStatementBuilder.java @@ -26,8 +26,6 @@ import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContextView; import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLJoinSelectSingleContextView; import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLStatement; import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLStatement.JPQLStatementBuilder; -import org.apache.olingo.odata2.jpa.processor.core.ODataExpressionParser; -import org.apache.olingo.odata2.jpa.processor.core.ODataParameterizedWhereExpressionUtil; public class JPQLJoinSelectSingleStatementBuilder extends JPQLStatementBuilder { @@ -41,8 +39,7 @@ public class JPQLJoinSelectSingleStatementBuilder extends JPQLStatementBuilder { @Override public JPQLStatement build() throws ODataJPARuntimeException { jpqlStatement = createStatement(createJPQLQuery()); - ODataParameterizedWhereExpressionUtil.setJPQLStatement(jpqlStatement.toString()); - ODataExpressionParser.reInitializePositionalParameters(); + this.context.setJPQLStatement(jpqlStatement.toString()); return jpqlStatement; } http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/53b631bf/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinStatementBuilder.java ---------------------------------------------------------------------- diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinStatementBuilder.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinStatementBuilder.java index 4e87f05..e86e9db 100644 --- a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinStatementBuilder.java +++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinStatementBuilder.java @@ -27,8 +27,6 @@ import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContextView; import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLJoinContextView; import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLStatement; import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLStatement.JPQLStatementBuilder; -import org.apache.olingo.odata2.jpa.processor.core.ODataExpressionParser; -import org.apache.olingo.odata2.jpa.processor.core.ODataParameterizedWhereExpressionUtil; public class JPQLJoinStatementBuilder extends JPQLStatementBuilder { @@ -42,8 +40,7 @@ public class JPQLJoinStatementBuilder extends JPQLStatementBuilder { @Override public JPQLStatement build() throws ODataJPARuntimeException { jpqlStatement = createStatement(createJPQLQuery()); - ODataParameterizedWhereExpressionUtil.setJPQLStatement(jpqlStatement.toString()); - ODataExpressionParser.reInitializePositionalParameters(); + this.context.setJPQLStatement(jpqlStatement.toString()); return jpqlStatement; } http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/53b631bf/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectContext.java ---------------------------------------------------------------------- diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectContext.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectContext.java index 33921f4..e54ef68 100644 --- a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectContext.java +++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectContext.java @@ -32,13 +32,14 @@ import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContext; import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContextType; import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLSelectContextView; import org.apache.olingo.odata2.jpa.processor.core.ODataExpressionParser; -import org.apache.olingo.odata2.jpa.processor.core.ODataParameterizedWhereExpressionUtil; public class JPQLSelectContext extends JPQLContext implements JPQLSelectContextView { protected String selectExpression; protected String orderByCollection; protected String whereCondition; + protected Map<String, Map<Integer, Object>> parameterizedQueryMap; + protected String jpqlStatement; protected boolean isCountOnly = false;// Support for $count @@ -53,6 +54,11 @@ public class JPQLSelectContext extends JPQLContext implements JPQLSelectContextV protected final void setWhereExpression(final String filterExpression) { whereCondition = filterExpression; } + + protected final void setParameterizedQueryMap( + final Map<String, Map<Integer, Object>> parameterizedQueryMap) { + this.parameterizedQueryMap = parameterizedQueryMap; + } protected final void setSelectExpression(final String selectExpression) { this.selectExpression = selectExpression; @@ -109,6 +115,9 @@ public class JPQLSelectContext extends JPQLContext implements JPQLSelectContextV setSelectExpression(generateSelectExpression()); setWhereExpression(generateWhereExpression()); + + setJPQLContext(JPQLSelectContext.this); + } catch (ODataException e) { throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e); } @@ -162,14 +171,27 @@ public class JPQLSelectContext extends JPQLContext implements JPQLSelectContextV entitySetView.getFilter(), getJPAEntityAlias()); Map<String, Map<Integer, Object>> parameterizedExpressionMap = new HashMap<String, Map<Integer,Object>>(); - parameterizedExpressionMap.put(whereExpression, ODataExpressionParser.getPositionalParameters()); - ODataParameterizedWhereExpressionUtil.setParameterizedQueryMap(parameterizedExpressionMap); - ODataExpressionParser.reInitializePositionalParameters(); + parameterizedExpressionMap.put(whereExpression, + ODataExpressionParser.getPositionalParametersThreadLocal()); + setParameterizedQueryMap(parameterizedExpressionMap); return whereExpression; } - ODataExpressionParser.reInitializePositionalParameters(); return null; } } + @Override + public Map<String, Map<Integer, Object>> getParameterizedQueryMap() { + return parameterizedQueryMap; + } + + @Override + public void setJPQLStatement(String jpqlStatement) { + this.jpqlStatement = jpqlStatement; + } + + @Override + public String getJPQLStatement() { + return jpqlStatement; + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/53b631bf/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectSingleContext.java ---------------------------------------------------------------------- diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectSingleContext.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectSingleContext.java index 99715223..34212f8 100644 --- a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectSingleContext.java +++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectSingleContext.java @@ -19,6 +19,7 @@ package org.apache.olingo.odata2.jpa.processor.core.jpql; import java.util.List; +import java.util.Map; import org.apache.olingo.odata2.api.edm.EdmEntityType; import org.apache.olingo.odata2.api.edm.EdmException; @@ -35,6 +36,8 @@ public class JPQLSelectSingleContext extends JPQLContext implements JPQLSelectSi private String selectExpression; private List<KeyPredicate> keyPredicates; + protected Map<String, Map<Integer, Object>> parameterizedQueryMap; + protected String jpqlStatement; protected void setKeyPredicates(final List<KeyPredicate> keyPredicates) { this.keyPredicates = keyPredicates; @@ -49,11 +52,21 @@ public class JPQLSelectSingleContext extends JPQLContext implements JPQLSelectSi this.selectExpression = selectExpression; } + protected final void setParameterizedQueryMap( + final Map<String, Map<Integer, Object>> parameterizedQueryMap) { + this.parameterizedQueryMap = parameterizedQueryMap; + } + @Override public String getSelectExpression() { return selectExpression; } + @Override + public Map<String, Map<Integer, Object>> getParameterizedQueryMap() { + return parameterizedQueryMap; + } + public class JPQLSelectSingleContextBuilder extends org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContext.JPQLContextBuilder { @@ -80,7 +93,9 @@ public class JPQLSelectSingleContext extends JPQLContext implements JPQLSelectSi setKeyPredicates(entityView.getKeyPredicates()); setSelectExpression(generateSelectExpression()); - + + setJPQLContext(JPQLSelectSingleContext.this); + } catch (EdmException e) { throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e); } @@ -106,4 +121,14 @@ public class JPQLSelectSingleContext extends JPQLContext implements JPQLSelectSi return getJPAEntityAlias(); } } + + @Override + public void setJPQLStatement(String jpqlStatement) { + this.jpqlStatement = jpqlStatement; + } + + @Override + public String getJPQLStatement() { + return jpqlStatement; + } } http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/53b631bf/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectSingleStatementBuilder.java ---------------------------------------------------------------------- diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectSingleStatementBuilder.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectSingleStatementBuilder.java index e1b0910..9c0597f 100644 --- a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectSingleStatementBuilder.java +++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectSingleStatementBuilder.java @@ -18,13 +18,15 @@ ******************************************************************************/ package org.apache.olingo.odata2.jpa.processor.core.jpql; +import java.util.HashMap; +import java.util.Map; + import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException; import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContextView; import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLSelectSingleContextView; import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLStatement; import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLStatement.JPQLStatementBuilder; import org.apache.olingo.odata2.jpa.processor.core.ODataExpressionParser; -import org.apache.olingo.odata2.jpa.processor.core.ODataParameterizedWhereExpressionUtil; public class JPQLSelectSingleStatementBuilder extends JPQLStatementBuilder { @@ -34,12 +36,11 @@ public class JPQLSelectSingleStatementBuilder extends JPQLStatementBuilder { public JPQLSelectSingleStatementBuilder(final JPQLContextView context) { this.context = (JPQLSelectSingleContextView) context; } - + @Override public JPQLStatement build() throws ODataJPARuntimeException { jpqlStatement = createStatement(createJPQLQuery()); - ODataParameterizedWhereExpressionUtil.setJPQLStatement(jpqlStatement.toString()); - ODataExpressionParser.reInitializePositionalParameters(); + this.context.setJPQLStatement(jpqlStatement.toString()); return jpqlStatement; } @@ -58,8 +59,16 @@ public class JPQLSelectSingleStatementBuilder extends JPQLStatementBuilder { if (context.getKeyPredicates() != null && !context.getKeyPredicates().isEmpty()) { jpqlQuery.append(JPQLStatement.DELIMITER.SPACE); jpqlQuery.append(JPQLStatement.KEYWORD.WHERE).append(JPQLStatement.DELIMITER.SPACE); - jpqlQuery.append(ODataExpressionParser - .parseKeyPredicates(context.getKeyPredicates(), context.getJPAEntityAlias())); + String keyString = ODataExpressionParser + .parseKeyPredicates(context.getKeyPredicates(), context.getJPAEntityAlias()); + Map<String, Map<Integer, Object>> parameterizedExpressionMap = + new HashMap<String, Map<Integer,Object>>(); + if (keyString != null) { + parameterizedExpressionMap.put(keyString, + ODataExpressionParser.getPositionalParametersThreadLocal()); + ((JPQLSelectSingleContext)this.context).setParameterizedQueryMap(parameterizedExpressionMap); + } + jpqlQuery.append(keyString); } return jpqlQuery.toString(); http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/53b631bf/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectStatementBuilder.java ---------------------------------------------------------------------- diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectStatementBuilder.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectStatementBuilder.java index 1276238..6e519e0 100644 --- a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectStatementBuilder.java +++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectStatementBuilder.java @@ -24,8 +24,6 @@ import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContextView; import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLSelectContextView; import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLStatement; import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLStatement.JPQLStatementBuilder; -import org.apache.olingo.odata2.jpa.processor.core.ODataExpressionParser; -import org.apache.olingo.odata2.jpa.processor.core.ODataParameterizedWhereExpressionUtil; public class JPQLSelectStatementBuilder extends JPQLStatementBuilder { @@ -39,8 +37,7 @@ public class JPQLSelectStatementBuilder extends JPQLStatementBuilder { @Override public JPQLStatement build() throws ODataJPARuntimeException { jpqlStatement = createStatement(createJPQLQuery()); - ODataParameterizedWhereExpressionUtil.setJPQLStatement(jpqlStatement.toString()); - ODataExpressionParser.reInitializePositionalParameters(); + this.context.setJPQLStatement(jpqlStatement.toString()); return jpqlStatement; } http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/53b631bf/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/ODataFilterExpressionParserTest.java ---------------------------------------------------------------------- diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/ODataFilterExpressionParserTest.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/ODataFilterExpressionParserTest.java index f964d7d..e17a779 100644 --- a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/ODataFilterExpressionParserTest.java +++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/ODataFilterExpressionParserTest.java @@ -273,7 +273,7 @@ public class ODataFilterExpressionParserTest { assertEquals(EXPRESSION_BINARY_AND[OUTPUT], whereExpression); } - @Test + @Test public void testBinaryOr() { String whereExpression = parseWhereExpression(EXPRESSION_BINARY_OR[INPUT], false); whereExpression = replacePositionalParameters(whereExpression); @@ -387,7 +387,7 @@ public class ODataFilterExpressionParserTest { } private String replacePositionalParameters(String whereExpression) { - Map<Integer, Object> positionalParameters = ODataExpressionParser.getPositionalParameters(); + Map<Integer, Object> positionalParameters = ODataExpressionParser.getPositionalParametersThreadLocal(); for (Entry<Integer, Object> param : positionalParameters.entrySet()) { Integer key = param.getKey(); if (param.getValue() instanceof String) { @@ -412,7 +412,6 @@ public class ODataFilterExpressionParserTest { whereExpression = whereExpression.replaceAll("\\?" + String.valueOf(key), param.getValue().toString()); } } - ODataExpressionParser.reInitializePositionalParameters(); return whereExpression; } http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/53b631bf/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImplTest.java ---------------------------------------------------------------------- diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImplTest.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImplTest.java index 6422a97..7e8fccd 100644 --- a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImplTest.java +++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImplTest.java @@ -167,7 +167,7 @@ public class JPAProcessorImplTest { EasyMock.expect(objUriInfo.getFilter()).andStubReturn(getFilter()); EasyMock.expect(objUriInfo.getKeyPredicates()).andStubReturn(getKeyPredicates()); EasyMock.expect(objUriInfo.isLinks()).andStubReturn(false); - EasyMock.expect(objUriInfo.getNavigationSegments()).andReturn(new ArrayList<NavigationSegment>()); + EasyMock.expect(objUriInfo.getNavigationSegments()).andStubReturn(new ArrayList<NavigationSegment>()); EasyMock.replay(objUriInfo); return objUriInfo; }