You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by nt...@apache.org on 2017/08/16 15:36:59 UTC
[07/13] cayenne git commit: CAY-2345 Own template renderer as a
replacement for Velocity - final version of render with cache and parser pool
CAY-2345 Own template renderer as a replacement for Velocity
- final version of render with cache and parser pool
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/54feb976
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/54feb976
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/54feb976
Branch: refs/heads/master
Commit: 54feb9762ef0356edc20def754bca65749451bec
Parents: e45f41f
Author: Nikita Timofeev <st...@gmail.com>
Authored: Wed Aug 9 16:41:21 2017 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Wed Aug 16 18:29:54 2017 +0300
----------------------------------------------------------------------
.../template/CayenneSQLTemplateProcessor.java | 16 +++--
.../org/apache/cayenne/template/Context.java | 16 ++++-
.../cayenne/template/TemplateParserPool.java | 60 ++++++++++++++++
.../apache/cayenne/template/directive/Bind.java | 21 +++---
.../cayenne/template/directive/BindEqual.java | 6 +-
.../template/directive/BindNotEqual.java | 6 +-
.../template/directive/BindObjectEqual.java | 32 ++++-----
.../template/directive/BindObjectNotEqual.java | 12 ++--
.../cayenne/template/directive/Directive.java | 2 +-
.../cayenne/template/directive/Result.java | 16 ++---
.../cayenne/template/parser/ASTArray.java | 7 +-
.../cayenne/template/parser/ASTBlock.java | 9 +--
.../cayenne/template/parser/ASTDirective.java | 6 +-
.../cayenne/template/parser/ASTExpression.java | 13 +++-
.../cayenne/template/parser/ASTIfElse.java | 7 +-
.../cayenne/template/parser/ASTMethod.java | 15 ++--
.../cayenne/template/parser/ASTVariable.java | 14 ++--
.../cayenne/template/parser/ExpressionNode.java | 2 +
.../parser/JJTSQLTemplateParserState.java | 20 +++---
.../cayenne/template/parser/JavaCharStream.java | 23 +++++--
.../apache/cayenne/template/parser/Node.java | 14 +---
.../template/parser/SQLTemplateParser.java | 9 +--
.../cayenne/template/parser/ScalarNode.java | 10 ++-
.../cayenne/template/parser/SimpleNode.java | 12 ++--
.../template/parser/SQLTemplateParser.jjt | 12 ++--
.../org/apache/cayenne/query/SQLTemplateIT.java | 4 --
.../template/TemplateParserPoolTest.java | 72 ++++++++++++++++++++
.../template/parser/SQLTemplateParserTest.java | 10 +--
28 files changed, 302 insertions(+), 144 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cayenne/blob/54feb976/cayenne-server/src/main/java/org/apache/cayenne/template/CayenneSQLTemplateProcessor.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/CayenneSQLTemplateProcessor.java b/cayenne-server/src/main/java/org/apache/cayenne/template/CayenneSQLTemplateProcessor.java
index 0352417..2d80523 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/template/CayenneSQLTemplateProcessor.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/CayenneSQLTemplateProcessor.java
@@ -19,8 +19,7 @@
package org.apache.cayenne.template;
-import java.io.BufferedReader;
-import java.io.StringReader;
+import java.io.ByteArrayInputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -43,6 +42,8 @@ public class CayenneSQLTemplateProcessor implements SQLTemplateProcessor {
ConcurrentLinkedHashMap<String, Node> templateCache = new ConcurrentLinkedHashMap
.Builder<String, Node>().maximumWeightedCapacity(100).build();
+ TemplateParserPool parserPool = new TemplateParserPool();
+
@Override
public SQLStatement processTemplate(String template, Map<String, ?> parameters) {
Context context = new Context();
@@ -65,16 +66,21 @@ public class CayenneSQLTemplateProcessor implements SQLTemplateProcessor {
protected SQLStatement process(String template, Context context) {
Node node = templateCache.get(template);
if(node == null) {
- SQLTemplateParser parser = new SQLTemplateParser(new BufferedReader(new StringReader(template)));
+ SQLTemplateParser parser = parserPool.get();
try {
+ parser.ReInit(new ByteArrayInputStream(template.getBytes()));
node = parser.template();
} catch (ParseException | TokenMgrError ex) {
throw new CayenneRuntimeException("Error parsing template '%s' : %s", template, ex.getMessage());
+ } finally {
+ parserPool.put(parser);
}
+ // can ignore case when someone resolved this template concurrently, it has no side effects
templateCache.put(template, node);
}
- String sql = node.evaluate(context);
- return new SQLStatement(sql, context.getColumnDescriptors(), context.getParameterBindings());
+ node.evaluate(context);
+
+ return new SQLStatement(context.buildTemplate(), context.getColumnDescriptors(), context.getParameterBindings());
}
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/54feb976/cayenne-server/src/main/java/org/apache/cayenne/template/Context.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/Context.java b/cayenne-server/src/main/java/org/apache/cayenne/template/Context.java
index 61c37b2..bb528d2 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/template/Context.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/Context.java
@@ -34,7 +34,6 @@ import org.apache.cayenne.template.directive.BindObjectEqual;
import org.apache.cayenne.template.directive.BindObjectNotEqual;
import org.apache.cayenne.template.directive.Directive;
import org.apache.cayenne.template.directive.Result;
-import org.apache.cayenne.velocity.SQLTemplateRenderingUtils;
/**
* @since 4.1
@@ -51,6 +50,8 @@ public class Context {
List<ColumnDescriptor> columnDescriptors = new ArrayList<>();
+ StringBuilder builder = new StringBuilder();
+
boolean positionalMode;
int counter;
@@ -78,6 +79,19 @@ public class Context {
return directives.get(name);
}
+ public StringBuilder getBuilder() {
+ return builder;
+ }
+
+ public String buildTemplate() {
+ if(positionalMode) {
+ if(counter <= objects.size() - 2) {
+ throw new CayenneRuntimeException("Too many parameters to bind template: " + (objects.size() - 1));
+ }
+ }
+ return builder.toString();
+ }
+
public Object getObject(String name) {
Object object = objects.get(name);
if(object != null) {
http://git-wip-us.apache.org/repos/asf/cayenne/blob/54feb976/cayenne-server/src/main/java/org/apache/cayenne/template/TemplateParserPool.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/TemplateParserPool.java b/cayenne-server/src/main/java/org/apache/cayenne/template/TemplateParserPool.java
new file mode 100644
index 0000000..eff632e
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/TemplateParserPool.java
@@ -0,0 +1,60 @@
+/*****************************************************************
+ * 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.cayenne.template;
+
+import java.io.ByteArrayInputStream;
+import java.util.concurrent.ArrayBlockingQueue;
+
+import org.apache.cayenne.template.parser.SQLTemplateParser;
+
+/**
+ * @since 4.1
+ */
+class TemplateParserPool {
+
+ final static int INITIAL_POOL_SIZE = 4;
+ final static int MAX_POOL_SIZE = 20;
+
+ private ArrayBlockingQueue<SQLTemplateParser> parsers = new ArrayBlockingQueue<>(MAX_POOL_SIZE);
+
+ TemplateParserPool() {
+ for(int i=0; i<INITIAL_POOL_SIZE; i++) {
+ parsers.offer(createNewParser());
+ }
+ }
+
+ SQLTemplateParser get() {
+ SQLTemplateParser parser = parsers.poll();
+ if(parser == null) {
+ parser = createNewParser();
+ }
+ return parser;
+ }
+
+ void put(SQLTemplateParser parser) {
+ parser.ReInit(new ByteArrayInputStream("\n".getBytes()));
+ parsers.offer(parser);
+ }
+
+ SQLTemplateParser createNewParser() {
+ return new SQLTemplateParser(new ByteArrayInputStream("\n".getBytes()));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/54feb976/cayenne-server/src/main/java/org/apache/cayenne/template/directive/Bind.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/directive/Bind.java b/cayenne-server/src/main/java/org/apache/cayenne/template/directive/Bind.java
index 8d2138f..23bcf43 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/template/directive/Bind.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/directive/Bind.java
@@ -35,13 +35,13 @@ public class Bind implements Directive {
public static final Bind INSTANCE = new Bind();
@Override
- public String apply(Context context, ASTExpression... expressions) {
- if(expressions.length < 1) {
+ public void apply(Context context, ASTExpression... expressions) {
+ if (expressions.length < 1) {
throw new IllegalArgumentException();
}
Object value = expressions[0].evaluateAsObject(context);
- String jdbcTypeName = expressions.length < 2 ? null : expressions[1].evaluate(context);
+ String jdbcTypeName = expressions.length < 2 ? null : expressions[1].evaluateAsString(context);
int jdbcType;
if (jdbcTypeName != null) {
@@ -51,26 +51,23 @@ public class Bind implements Directive {
} else {
jdbcType = TypesMapping.getSqlTypeByName(TypesMapping.SQL_NULL);
}
- int scale = expressions.length < 3 ? -1 : (int)expressions[2].evaluateAsLong(context);
+ int scale = expressions.length < 3 ? -1 : (int) expressions[2].evaluateAsLong(context);
- StringBuilder builder = new StringBuilder();
if (value instanceof Collection) {
Iterator<?> it = ((Collection) value).iterator();
while (it.hasNext()) {
- processBinding(context, builder, new ParameterBinding(it.next(), jdbcType, scale));
+ processBinding(context, new ParameterBinding(it.next(), jdbcType, scale));
if (it.hasNext()) {
- builder.append(',');
+ context.getBuilder().append(',');
}
}
} else {
- processBinding(context, builder, new ParameterBinding(value, jdbcType, scale));
+ processBinding(context, new ParameterBinding(value, jdbcType, scale));
}
-
- return builder.toString();
}
- protected void processBinding(Context context, StringBuilder builder, ParameterBinding binding) {
+ protected void processBinding(Context context, ParameterBinding binding) {
context.addParameterBinding(binding);
- builder.append('?');
+ context.getBuilder().append('?');
}
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/54feb976/cayenne-server/src/main/java/org/apache/cayenne/template/directive/BindEqual.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/directive/BindEqual.java b/cayenne-server/src/main/java/org/apache/cayenne/template/directive/BindEqual.java
index 1153675..e343fe8 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/template/directive/BindEqual.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/directive/BindEqual.java
@@ -30,12 +30,12 @@ public class BindEqual extends Bind {
public static final BindEqual INSTANCE = new BindEqual();
@Override
- protected void processBinding(Context context, StringBuilder builder, ParameterBinding binding) {
+ protected void processBinding(Context context, ParameterBinding binding) {
if (binding.getValue() != null) {
context.addParameterBinding(binding);
- builder.append("= ?");
+ context.getBuilder().append("= ?");
} else {
- builder.append("IS NULL");
+ context.getBuilder().append("IS NULL");
}
}
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/54feb976/cayenne-server/src/main/java/org/apache/cayenne/template/directive/BindNotEqual.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/directive/BindNotEqual.java b/cayenne-server/src/main/java/org/apache/cayenne/template/directive/BindNotEqual.java
index 09f70ed..e58200f 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/template/directive/BindNotEqual.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/directive/BindNotEqual.java
@@ -30,12 +30,12 @@ public class BindNotEqual extends Bind {
public static final BindEqual INSTANCE = new BindEqual();
@Override
- protected void processBinding(Context context, StringBuilder builder, ParameterBinding binding) {
+ protected void processBinding(Context context, ParameterBinding binding) {
if (binding.getValue() != null) {
context.addParameterBinding(binding);
- builder.append("<> ?");
+ context.getBuilder().append("<> ?");
} else {
- builder.append("IS NOT NULL");
+ context.getBuilder().append("IS NOT NULL");
}
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/54feb976/cayenne-server/src/main/java/org/apache/cayenne/template/directive/BindObjectEqual.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/directive/BindObjectEqual.java b/cayenne-server/src/main/java/org/apache/cayenne/template/directive/BindObjectEqual.java
index cea8b4f..bbf1605 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/template/directive/BindObjectEqual.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/directive/BindObjectEqual.java
@@ -24,13 +24,13 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Map;
+import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.ObjectId;
import org.apache.cayenne.Persistent;
import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.dba.TypesMapping;
import org.apache.cayenne.template.Context;
import org.apache.cayenne.template.parser.ASTExpression;
-import org.apache.velocity.exception.ParseErrorException;
/**
* @since 4.1
@@ -40,7 +40,7 @@ public class BindObjectEqual implements Directive {
public static final BindObjectEqual INSTANCE = new BindObjectEqual();
@Override
- public String apply(Context context, ASTExpression... expressions) {
+ public void apply(Context context, ASTExpression... expressions) {
Object object = expressions[0].evaluateAsObject(context);
Map<String, Object> idMap = toIdMap(object);
@@ -57,7 +57,7 @@ public class BindObjectEqual implements Directive {
if (idMap == null) {
// assume null object, and bind all null values
if (sqlColumns == null || idColumns == null) {
- throw new ParseErrorException("Invalid parameters. "
+ throw new CayenneRuntimeException("Invalid parameters. "
+ "Either object has to be set or sqlColumns and idColumns or both.");
}
@@ -72,37 +72,33 @@ public class BindObjectEqual implements Directive {
String[] idColumnsArray = toArray(idColumns);
if (sqlColumnsArray.length != idColumnsArray.length) {
- throw new ParseErrorException(
+ throw new CayenneRuntimeException(
"SQL columns and ID columns arrays have different sizes.");
}
- StringBuilder builder = new StringBuilder();
-
for (int i = 0; i < sqlColumnsArray.length; i++) {
Object value = idMap.get(idColumnsArray[i]);
int jdbcType = (value != null) ? TypesMapping.getSqlTypeByJava(value.getClass()) : Types.INTEGER;
- renderColumn(sqlColumnsArray[i], i, builder);
- render(context, builder, new ParameterBinding(value, jdbcType, -1));
+ renderColumn(context, sqlColumnsArray[i], i);
+ render(context, new ParameterBinding(value, jdbcType, -1));
}
-
- return builder.toString();
}
- protected void renderColumn(String columnName, int columnIndex, StringBuilder builder) {
+ protected void renderColumn(Context context, String columnName, int columnIndex) {
if (columnIndex > 0) {
- builder.append(" AND ");
+ context.getBuilder().append(" AND ");
}
- builder.append(columnName).append(' ');
+ context.getBuilder().append(columnName).append(' ');
}
- protected void render(Context context, StringBuilder builder, ParameterBinding binding) {
+ protected void render(Context context, ParameterBinding binding) {
if (binding.getValue() != null) {
context.addParameterBinding(binding);
- builder.append("= ?");
+ context.getBuilder().append("= ?");
} else {
- builder.append("IS NULL");
+ context.getBuilder().append("IS NULL");
}
}
@@ -128,7 +124,7 @@ public class BindObjectEqual implements Directive {
}
@SuppressWarnings("unchecked")
- protected Map<String, Object> toIdMap(Object object) throws ParseErrorException {
+ protected Map<String, Object> toIdMap(Object object) {
if (object instanceof Persistent) {
return ((Persistent) object).getObjectId().getIdSnapshot();
} else if (object instanceof ObjectId) {
@@ -136,7 +132,7 @@ public class BindObjectEqual implements Directive {
} else if(object instanceof Map) {
return (Map<String, Object>) object;
} else if (object != null) {
- throw new ParseErrorException(
+ throw new CayenneRuntimeException(
"Invalid object parameter, expected Persistent or ObjectId or null: " + object);
} else {
return null;
http://git-wip-us.apache.org/repos/asf/cayenne/blob/54feb976/cayenne-server/src/main/java/org/apache/cayenne/template/directive/BindObjectNotEqual.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/directive/BindObjectNotEqual.java b/cayenne-server/src/main/java/org/apache/cayenne/template/directive/BindObjectNotEqual.java
index 2e8879d..74c7e97 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/template/directive/BindObjectNotEqual.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/directive/BindObjectNotEqual.java
@@ -30,21 +30,21 @@ public class BindObjectNotEqual extends BindObjectEqual {
public static final BindObjectNotEqual INSTANCE = new BindObjectNotEqual();
@Override
- protected void renderColumn(String columnName, int columnIndex, StringBuilder builder) {
+ protected void renderColumn(Context context, String columnName, int columnIndex) {
if (columnIndex > 0) {
- builder.append(" OR ");
+ context.getBuilder().append(" OR ");
}
- builder.append(columnName).append(' ');
+ context.getBuilder().append(columnName).append(' ');
}
@Override
- protected void render(Context context, StringBuilder builder, ParameterBinding binding) {
+ protected void render(Context context, ParameterBinding binding) {
if (binding.getValue() != null) {
context.addParameterBinding(binding);
- builder.append("<> ?");
+ context.getBuilder().append("<> ?");
} else {
- builder.append("IS NOT NULL");
+ context.getBuilder().append("IS NOT NULL");
}
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/54feb976/cayenne-server/src/main/java/org/apache/cayenne/template/directive/Directive.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/directive/Directive.java b/cayenne-server/src/main/java/org/apache/cayenne/template/directive/Directive.java
index be2d6c9..cdc5da4 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/template/directive/Directive.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/directive/Directive.java
@@ -27,6 +27,6 @@ import org.apache.cayenne.template.parser.ASTExpression;
*/
public interface Directive {
- String apply(Context context, ASTExpression... expressions);
+ void apply(Context context, ASTExpression... expressions);
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/54feb976/cayenne-server/src/main/java/org/apache/cayenne/template/directive/Result.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/directive/Result.java b/cayenne-server/src/main/java/org/apache/cayenne/template/directive/Result.java
index dfcdd6f..967bb2c 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/template/directive/Result.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/directive/Result.java
@@ -73,26 +73,26 @@ public class Result implements Directive {
}
@Override
- public String apply(Context context, ASTExpression... expressions) {
+ public void apply(Context context, ASTExpression... expressions) {
ColumnDescriptor columnDescriptor = new ColumnDescriptor();
- String column = expressions[0].evaluate(context);
+ String column = expressions[0].evaluateAsString(context);
columnDescriptor.setName(column);
if (expressions.length > 1) {
- String type = expressions[1].evaluate(context);
+ String type = expressions[1].evaluateAsString(context);
columnDescriptor.setJavaClass(guessType(type));
}
String alias = null;
if (expressions.length > 2) {
- alias = expressions[2].evaluate(context);
+ alias = expressions[2].evaluateAsString(context);
}
String dataRowKey = null;
if (expressions.length > 3) {
- dataRowKey = expressions[3].evaluate(context);
+ dataRowKey = expressions[3].evaluateAsString(context);
}
// determine what we want to name this column in a resulting DataRow...
@@ -106,12 +106,10 @@ public class Result implements Directive {
context.addColumnDescriptor(columnDescriptor);
- String result = column;
+ context.getBuilder().append(column);
if (!Util.isEmptyString(alias) && !alias.equals(column)) {
- result += " AS " + alias;
+ context.getBuilder().append(" AS ").append(alias);
}
-
- return result;
}
/**
http://git-wip-us.apache.org/repos/asf/cayenne/blob/54feb976/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTArray.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTArray.java b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTArray.java
index 3aed8ba..dbb9299 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTArray.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTArray.java
@@ -30,7 +30,12 @@ public class ASTArray extends ASTExpression {
}
@Override
- public String evaluate(Context context) {
+ public void evaluate(Context context) {
+ context.getBuilder().append(evaluateAsString(context));
+ }
+
+ @Override
+ public String evaluateAsString(Context context) {
return Arrays.toString(evaluateAsArray(context));
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/54feb976/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTBlock.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTBlock.java b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTBlock.java
index 743756f..0f50dff 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTBlock.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTBlock.java
@@ -34,11 +34,12 @@ public class ASTBlock extends SimpleNode {
}
@Override
- public String evaluate(Context context) {
- StringBuilder builder = new StringBuilder();
+ public void evaluate(Context context) {
+ if(children == null) {
+ return;
+ }
for(Node node : children) {
- builder.append(node.evaluate(context));
+ node.evaluate(context);
}
- return builder.toString();
}
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/54feb976/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTDirective.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTDirective.java b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTDirective.java
index 3522123..cd3b656 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTDirective.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTDirective.java
@@ -32,10 +32,10 @@ public class ASTDirective extends IdentifierNode {
}
@Override
- public String evaluate(Context context) {
+ public void evaluate(Context context) {
Directive directive = context.getDirective(getIdentifier());
if(directive == null) {
- return "";
+ return;
}
ASTExpression[] expressions = new ASTExpression[children.length];
@@ -43,6 +43,6 @@ public class ASTDirective extends IdentifierNode {
expressions[i] = (ASTExpression)children[i];
}
- return directive.apply(context, expressions);
+ directive.apply(context, expressions);
}
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/54feb976/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTExpression.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTExpression.java b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTExpression.java
index 7ff1858..a789156 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTExpression.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTExpression.java
@@ -35,8 +35,17 @@ public class ASTExpression extends SimpleNode implements ExpressionNode {
}
@Override
- public String evaluate(Context context) {
- return jjtGetChild(0).evaluate(context);
+ public void evaluate(Context context) {
+ jjtGetChild(0).evaluate(context);
+ }
+
+ @Override
+ public String evaluateAsString(Context context) {
+ Object object = evaluateAsObject(context);
+ if(object != null) {
+ return object.toString();
+ }
+ return "";
}
@Override
http://git-wip-us.apache.org/repos/asf/cayenne/blob/54feb976/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTIfElse.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTIfElse.java b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTIfElse.java
index d117777..56bec44 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTIfElse.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTIfElse.java
@@ -31,16 +31,15 @@ public class ASTIfElse extends SimpleNode {
}
@Override
- public String evaluate(Context context) {
+ public void evaluate(Context context) {
ASTExpression condition = (ASTExpression)jjtGetChild(0);
if (condition.evaluateAsBoolean(context)) {
- return jjtGetChild(1).evaluate(context);
+ jjtGetChild(1).evaluate(context);
} else {
// else is optional
if(jjtGetNumChildren() > 2) {
- return jjtGetChild(2).evaluate(context);
+ jjtGetChild(2).evaluate(context);
}
- return "";
}
}
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/54feb976/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTMethod.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTMethod.java b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTMethod.java
index 51e7358..c4b96a0 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTMethod.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTMethod.java
@@ -30,20 +30,14 @@ import org.apache.cayenne.template.Context;
*/
public class ASTMethod extends IdentifierNode {
- protected Object parentObject;
-
public ASTMethod(int id) {
super(id);
}
- protected void setParentObject(Object parentObject) {
- this.parentObject = Objects.requireNonNull(parentObject);
- }
-
/**
* Evaluate method call to an Object
*/
- public Object evaluateAsObject(Context context) {
+ public Object evaluateAsObject(Context context, Object parentObject) {
if(parentObject == null) {
throw new IllegalStateException("To evaluate method node parent object should be set.");
}
@@ -65,7 +59,7 @@ public class ASTMethod extends IdentifierNode {
for(Class<?> parameterType : m.getParameterTypes()) {
ASTExpression child = (ASTExpression)jjtGetChild(i);
if(parameterType.isAssignableFrom(String.class)) {
- arguments[i] = child.evaluate(context);
+ arguments[i] = child.evaluateAsString(context);
} else if(parameterType.isAssignableFrom(Double.class)) {
arguments[i] = child.evaluateAsDouble(context);
} else if(parameterType.isAssignableFrom(Long.class)) {
@@ -94,9 +88,8 @@ public class ASTMethod extends IdentifierNode {
}
@Override
- public String evaluate(Context context) {
- Object object = evaluateAsObject(context);
- return object == null ? "" : object.toString();
+ public void evaluate(Context context) {
+ throw new UnsupportedOperationException("Unable evaluate method directly, must be solved via ASTVariable");
}
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/54feb976/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTVariable.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTVariable.java b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTVariable.java
index f45f1f8..3d2f60b 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTVariable.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTVariable.java
@@ -33,6 +33,12 @@ public class ASTVariable extends IdentifierNode implements ExpressionNode {
}
@Override
+ public String evaluateAsString(Context context) {
+ Object object = evaluateAsObject(context);
+ return object == null ? "" : object.toString();
+ }
+
+ @Override
public Object evaluateAsObject(Context context) {
Object object = context.getObject(getIdentifier());
if(object == null) {
@@ -40,8 +46,7 @@ public class ASTVariable extends IdentifierNode implements ExpressionNode {
}
for(int i=0; i<jjtGetNumChildren(); i++) {
ASTMethod method = (ASTMethod)jjtGetChild(i);
- method.setParentObject(object);
- object = method.evaluateAsObject(context);
+ object = method.evaluateAsObject(context, object);
if(object == null) {
return null;
}
@@ -50,9 +55,8 @@ public class ASTVariable extends IdentifierNode implements ExpressionNode {
}
@Override
- public String evaluate(Context context) {
- Object object = evaluateAsObject(context);
- return object == null ? "" : object.toString();
+ public void evaluate(Context context) {
+ context.getBuilder().append(evaluateAsString(context));
}
@Override
http://git-wip-us.apache.org/repos/asf/cayenne/blob/54feb976/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ExpressionNode.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ExpressionNode.java b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ExpressionNode.java
index 735badf..e9b1bd5 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ExpressionNode.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ExpressionNode.java
@@ -26,6 +26,8 @@ import org.apache.cayenne.template.Context;
*/
public interface ExpressionNode {
+ String evaluateAsString(Context context);
+
Object evaluateAsObject(Context context);
long evaluateAsLong(Context context);
http://git-wip-us.apache.org/repos/asf/cayenne/blob/54feb976/cayenne-server/src/main/java/org/apache/cayenne/template/parser/JJTSQLTemplateParserState.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/JJTSQLTemplateParserState.java b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/JJTSQLTemplateParserState.java
index 667462e..85f9ab7 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/JJTSQLTemplateParserState.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/JJTSQLTemplateParserState.java
@@ -19,17 +19,23 @@
package org.apache.cayenne.template.parser;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @since 4.1
+ */
public class JJTSQLTemplateParserState {
- private java.util.List<Node> nodes;
- private java.util.List<Integer> marks;
+ private List<Node> nodes;
+ private List<Integer> marks;
private int sp; // number of nodes on stack
private int mk; // current mark
private boolean node_created;
public JJTSQLTemplateParserState() {
- nodes = new java.util.ArrayList<>();
- marks = new java.util.ArrayList<>();
+ nodes = new ArrayList<>();
+ marks = new ArrayList<>();
sp = 0;
mk = 0;
}
@@ -82,7 +88,6 @@ public class JJTSQLTemplateParserState {
return sp - mk;
}
-
public void clearNodeScope(Node n) {
while (sp > mk) {
popNode();
@@ -90,14 +95,11 @@ public class JJTSQLTemplateParserState {
mk = marks.remove(marks.size() - 1);
}
-
public void openNodeScope(Node n) {
marks.add(mk);
mk = sp;
- n.jjtOpen();
}
-
/* A definite node is constructed from a specified number of
children. That number of nodes are popped from the stack and
made the children of the definite node. Then the definite node
@@ -109,7 +111,6 @@ public class JJTSQLTemplateParserState {
c.jjtSetParent(n);
n.jjtAddChild(c, num);
}
- n.jjtClose();
pushNode(n);
node_created = true;
}
@@ -129,7 +130,6 @@ public class JJTSQLTemplateParserState {
c.jjtSetParent(n);
n.jjtAddChild(c, a);
}
- n.jjtClose();
pushNode(n);
node_created = true;
} else {
http://git-wip-us.apache.org/repos/asf/cayenne/blob/54feb976/cayenne-server/src/main/java/org/apache/cayenne/template/parser/JavaCharStream.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/JavaCharStream.java b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/JavaCharStream.java
index d9e6eb5..3373be4 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/JavaCharStream.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/JavaCharStream.java
@@ -19,6 +19,8 @@
package org.apache.cayenne.template.parser;
+import java.io.IOException;
+
/**
* An implementation of interface CharStream, where the stream is assumed to
* contain only ASCII characters (with java-like unicode escape processing).
@@ -27,6 +29,14 @@ package org.apache.cayenne.template.parser;
*/
public class JavaCharStream {
+ private static final IOException END_OF_STREAM_EXCEPTION = new IOException() {
+
+ @Override
+ public synchronized Throwable fillInStackTrace() {
+ return this;
+ }
+ };
+
/**
* Whether parser is static.
*/
@@ -102,6 +112,7 @@ public class JavaCharStream {
protected int nextCharInd = -1;
protected int inBuf = 0;
protected int tabSize = 8;
+ private boolean closed;
protected void ExpandBuff(boolean wrapAround) {
char[] newbuffer = new char[bufsize + 2048];
@@ -145,14 +156,17 @@ public class JavaCharStream {
protected void FillBuff() throws java.io.IOException {
int i;
- if (maxNextCharInd == 4096)
+ if (maxNextCharInd == nextCharBuf.length)
maxNextCharInd = nextCharInd = 0;
try {
- if ((i = inputStream.read(nextCharBuf, maxNextCharInd,
- 4096 - maxNextCharInd)) == -1) {
+ // check for closed status to prevent the underlying Reader from
+ // throwing IOException that causes performance degradation
+ if (closed || (i = inputStream.read(nextCharBuf, maxNextCharInd,
+ nextCharBuf.length - maxNextCharInd)) == -1) {
inputStream.close();
- throw new java.io.IOException();
+ closed = true;
+ throw END_OF_STREAM_EXCEPTION;
} else
maxNextCharInd += i;
} catch (java.io.IOException e) {
@@ -412,6 +426,7 @@ public class JavaCharStream {
prevCharIsLF = prevCharIsCR = false;
tokenBegin = inBuf = maxNextCharInd = 0;
nextCharInd = bufpos = -1;
+ closed = false;
}
/**
http://git-wip-us.apache.org/repos/asf/cayenne/blob/54feb976/cayenne-server/src/main/java/org/apache/cayenne/template/parser/Node.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/Node.java b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/Node.java
index 15d5b1a..eb40295 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/Node.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/Node.java
@@ -30,18 +30,6 @@ import org.apache.cayenne.template.Context;
public interface Node {
/**
- * This method is called after the node has been made the current
- * node. It indicates that child nodes can now be added to it.
- */
- void jjtOpen();
-
- /**
- * This method is called after all the child nodes have been
- * added.
- */
- void jjtClose();
-
- /**
* This pair of methods are used to inform the node of its
* parent.
*/
@@ -66,5 +54,5 @@ public interface Node {
*/
int jjtGetNumChildren();
- String evaluate(Context context);
+ void evaluate(Context context);
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/54feb976/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParser.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParser.java b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParser.java
index a175ae9..46ebe43 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParser.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParser.java
@@ -114,21 +114,18 @@ public class SQLTemplateParser/*@bgen(jjtree)*/implements SQLTemplateParserTreeC
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
case TEXT:
t = jj_consume_token(TEXT);
- jjtree.closeNodeScope(jjtn000, true);
- jjtc000 = false;
- jjtn000.setValue(t.image);
break;
case TEXT_OTHER:
t = jj_consume_token(TEXT_OTHER);
- jjtree.closeNodeScope(jjtn000, true);
- jjtc000 = false;
- jjtn000.setValue(t.image);
break;
default:
jj_la1[2] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
+ jjtree.closeNodeScope(jjtn000, true);
+ jjtc000 = false;
+ jjtn000.setValue(t.image);
} finally {
if (jjtc000) {
jjtree.closeNodeScope(jjtn000, true);
http://git-wip-us.apache.org/repos/asf/cayenne/blob/54feb976/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ScalarNode.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ScalarNode.java b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ScalarNode.java
index ba2a39a..106dd06 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ScalarNode.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ScalarNode.java
@@ -41,10 +41,14 @@ public class ScalarNode<V> extends SimpleNode implements ExpressionNode {
}
@Override
- public String evaluate(Context context) {
- if(value == null) {
- return "";
+ public void evaluate(Context context) {
+ if(value != null) {
+ context.getBuilder().append(value.toString());
}
+ }
+
+ @Override
+ public String evaluateAsString(Context context) {
return value.toString();
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/54feb976/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SimpleNode.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SimpleNode.java b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SimpleNode.java
index df4fc8a..12116fb 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SimpleNode.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SimpleNode.java
@@ -32,20 +32,17 @@ public abstract class SimpleNode implements Node {
id = i;
}
- public void jjtOpen() {
- }
-
- public void jjtClose() {
- }
-
+ @Override
public void jjtSetParent(Node n) {
parent = n;
}
+ @Override
public Node jjtGetParent() {
return parent;
}
+ @Override
public void jjtAddChild(Node n, int i) {
if (children == null) {
children = new Node[i + 1];
@@ -57,14 +54,17 @@ public abstract class SimpleNode implements Node {
children[i] = n;
}
+ @Override
public Node jjtGetChild(int i) {
return children[i];
}
+ @Override
public int jjtGetNumChildren() {
return (children == null) ? 0 : children.length;
}
+ @Override
public String toString() {
return SQLTemplateParserTreeConstants.jjtNodeName[id];
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/54feb976/cayenne-server/src/main/jjtree/org/apache/cayenne/template/parser/SQLTemplateParser.jjt
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/jjtree/org/apache/cayenne/template/parser/SQLTemplateParser.jjt b/cayenne-server/src/main/jjtree/org/apache/cayenne/template/parser/SQLTemplateParser.jjt
index ceeb0f4..b4114bc 100644
--- a/cayenne-server/src/main/jjtree/org/apache/cayenne/template/parser/SQLTemplateParser.jjt
+++ b/cayenne-server/src/main/jjtree/org/apache/cayenne/template/parser/SQLTemplateParser.jjt
@@ -99,7 +99,8 @@ Node template() : {}
*/
void block() #Block : {}
{
- ( ifElse()
+ (
+ ifElse()
| directive()
| variable()
| text()
@@ -113,11 +114,10 @@ void text() #Text : {
Token t;
}
{
- t = <TEXT> {
- jjtThis.setValue(t.image);
- }
- |
- t = <TEXT_OTHER> {
+ (
+ t = <TEXT>
+ | t = <TEXT_OTHER>
+ ) {
jjtThis.setValue(t.image);
}
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/54feb976/cayenne-server/src/test/java/org/apache/cayenne/query/SQLTemplateIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/SQLTemplateIT.java b/cayenne-server/src/test/java/org/apache/cayenne/query/SQLTemplateIT.java
index be882b9..902ff04 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/query/SQLTemplateIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/query/SQLTemplateIT.java
@@ -148,15 +148,11 @@ public class SQLTemplateIT extends ServerCase {
SQLTemplate q1 = new SQLTemplate(Painting.class, sql);
q1.setParamsArray(11, "The Fiddler", 2345, 333);
- context.performNonSelectingQuery(q1);
- // TODO: new template render doesn't throw expetion in this case
- /*
try {
context.performNonSelectingQuery(q1);
fail("Exception not thrown on parameter length mismatch");
} catch (CayenneRuntimeException e) {
// expected
}
- */
}
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/54feb976/cayenne-server/src/test/java/org/apache/cayenne/template/TemplateParserPoolTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/template/TemplateParserPoolTest.java b/cayenne-server/src/test/java/org/apache/cayenne/template/TemplateParserPoolTest.java
new file mode 100644
index 0000000..dce5efd
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/template/TemplateParserPoolTest.java
@@ -0,0 +1,72 @@
+/*****************************************************************
+ * 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.cayenne.template;
+
+import java.io.ByteArrayInputStream;
+
+import org.apache.cayenne.template.parser.SQLTemplateParser;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @since 4.1
+ */
+public class TemplateParserPoolTest {
+
+ TemplateParserPool parserPool;
+
+ @Before
+ public void createPool() {
+ parserPool = new TemplateParserPool();
+ }
+
+ @Test
+ public void get() throws Exception {
+ for(int i=0; i<TemplateParserPool.MAX_POOL_SIZE + 10; i++) {
+ SQLTemplateParser parser = parserPool.get();
+ assertNotNull(parser);
+ }
+ }
+
+ @Test
+ public void put() throws Exception {
+ SQLTemplateParser parser = new SQLTemplateParser(new ByteArrayInputStream("".getBytes()));
+
+ parserPool.put(parser);
+
+ for(int i=0; i<TemplateParserPool.INITIAL_POOL_SIZE; i++) {
+ SQLTemplateParser parser1 = parserPool.get();
+ assertNotNull(parser1);
+ assertNotSame(parser, parser1);
+ }
+
+ SQLTemplateParser parser1 = parserPool.get();
+ assertSame(parser, parser1);
+ }
+
+ @Test
+ public void createNewParser() throws Exception {
+ SQLTemplateParser parser = parserPool.createNewParser();
+ assertNotNull(parser);
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne/blob/54feb976/cayenne-server/src/test/java/org/apache/cayenne/template/parser/SQLTemplateParserTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/template/parser/SQLTemplateParserTest.java b/cayenne-server/src/test/java/org/apache/cayenne/template/parser/SQLTemplateParserTest.java
index 9d74f56..6d26b20 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/template/parser/SQLTemplateParserTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/template/parser/SQLTemplateParserTest.java
@@ -19,6 +19,7 @@
package org.apache.cayenne.template.parser;
+import java.io.ByteArrayInputStream;
import java.io.StringReader;
import org.apache.cayenne.template.Context;
@@ -158,6 +159,8 @@ public class SQLTemplateParserTest {
String sql = parseString(template, context);
assertEquals("\"val\"", sql);
+ context = new Context();
+ context.addParameter("a", "val");
template = "'$a'";
sql = parseString(template, context);
assertEquals("'val'", sql);
@@ -172,10 +175,9 @@ public class SQLTemplateParserTest {
assertEquals("val,val", sql);
}
- private String parseString(String template, Context context) throws ParseException {
- SQLTemplateParser parser = new SQLTemplateParser(new StringReader(template));
- Node block = parser.template();
- return block.evaluate(context);
+ private String parseString(String tpl, Context context) throws ParseException {
+ new SQLTemplateParser(new ByteArrayInputStream(tpl.getBytes())).template().evaluate(context);
+ return context.buildTemplate();
}
}
\ No newline at end of file