Repository: qpid-broker-j Updated Branches: refs/heads/master 0fe98f847 -> 9704e609d
QPID-8104: [Broker-J] [Query] Support the use of aliases in order by clauses Project: http://git-wip-us.apache.org/repos/asf/qpid-broker-j/repo Commit: http://git-wip-us.apache.org/repos/asf/qpid-broker-j/commit/9704e609 Tree: http://git-wip-us.apache.org/repos/asf/qpid-broker-j/tree/9704e609 Diff: http://git-wip-us.apache.org/repos/asf/qpid-broker-j/diff/9704e609 Branch: refs/heads/master Commit: 9704e609db36102d40d074a866799d0fe3930ffa Parents: 0fe98f8 Author: Keith Wall <[email protected]> Authored: Wed Feb 21 22:19:56 2018 +0000 Committer: Keith Wall <[email protected]> Committed: Thu Feb 22 15:20:01 2018 +0000 ---------------------------------------------------------------------- .../qpid/server/filter/NamedExpression.java | 26 ++++++ .../qpid/server/filter/OrderByExpression.java | 10 +++ .../grammar/ConfiguredObjectFilterParser.jj | 1 + .../ConfiguredObjectExpressionFactory.java | 1 + .../query/ConfiguredObjectFilterParser.java | 1 + .../servlet/query/ConfiguredObjectQuery.java | 41 ++++++++-- .../plugin/servlet/query/NamedExpression.java | 28 ------- .../query/ConfiguredObjectQueryTest.java | 85 +++++++++++++++----- 8 files changed, 136 insertions(+), 57 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/9704e609/broker-core/src/main/java/org/apache/qpid/server/filter/NamedExpression.java ---------------------------------------------------------------------- diff --git a/broker-core/src/main/java/org/apache/qpid/server/filter/NamedExpression.java b/broker-core/src/main/java/org/apache/qpid/server/filter/NamedExpression.java new file mode 100644 index 0000000..9970f89 --- /dev/null +++ b/broker-core/src/main/java/org/apache/qpid/server/filter/NamedExpression.java @@ -0,0 +1,26 @@ +/* + * + * 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.qpid.server.filter; + +public interface NamedExpression<E> extends Expression<E> +{ + String getName(); +} http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/9704e609/broker-core/src/main/java/org/apache/qpid/server/filter/OrderByExpression.java ---------------------------------------------------------------------- diff --git a/broker-core/src/main/java/org/apache/qpid/server/filter/OrderByExpression.java b/broker-core/src/main/java/org/apache/qpid/server/filter/OrderByExpression.java index 87d45d1..20120dc 100644 --- a/broker-core/src/main/java/org/apache/qpid/server/filter/OrderByExpression.java +++ b/broker-core/src/main/java/org/apache/qpid/server/filter/OrderByExpression.java @@ -58,4 +58,14 @@ public class OrderByExpression implements Expression { return ((Number)((ConstantExpression)_expression).getValue()).intValue(); } + + public boolean isNamed() + { + return (_expression instanceof NamedExpression); + } + + public String getName() + { + return ((NamedExpression) _expression).getName(); + } } http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/9704e609/broker-plugins/management-http/src/main/grammar/ConfiguredObjectFilterParser.jj ---------------------------------------------------------------------- diff --git a/broker-plugins/management-http/src/main/grammar/ConfiguredObjectFilterParser.jj b/broker-plugins/management-http/src/main/grammar/ConfiguredObjectFilterParser.jj index be1aafb..d8e7536 100644 --- a/broker-plugins/management-http/src/main/grammar/ConfiguredObjectFilterParser.jj +++ b/broker-plugins/management-http/src/main/grammar/ConfiguredObjectFilterParser.jj @@ -77,6 +77,7 @@ import org.apache.qpid.filter.Expression; import org.apache.qpid.filter.OrderByExpression; import org.apache.qpid.filter.LogicExpression; import org.apache.qpid.filter.UnaryExpression; +import org.apache.qpid.filter.NamedExpression; import org.apache.qpid.server.model.ConfiguredObject; http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/9704e609/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/query/ConfiguredObjectExpressionFactory.java ---------------------------------------------------------------------- diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/query/ConfiguredObjectExpressionFactory.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/query/ConfiguredObjectExpressionFactory.java index 0c31a11..85e3a34 100644 --- a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/query/ConfiguredObjectExpressionFactory.java +++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/query/ConfiguredObjectExpressionFactory.java @@ -37,6 +37,7 @@ import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.Duration; import org.apache.qpid.server.filter.Expression; +import org.apache.qpid.server.filter.NamedExpression; import org.apache.qpid.server.model.ConfiguredObject; public class ConfiguredObjectExpressionFactory http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/9704e609/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/query/ConfiguredObjectFilterParser.java ---------------------------------------------------------------------- diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/query/ConfiguredObjectFilterParser.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/query/ConfiguredObjectFilterParser.java index 1de4930..3e4e57e 100644 --- a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/query/ConfiguredObjectFilterParser.java +++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/query/ConfiguredObjectFilterParser.java @@ -33,6 +33,7 @@ import org.apache.qpid.server.filter.BooleanExpression; import org.apache.qpid.server.filter.ComparisonExpression; import org.apache.qpid.server.filter.ConstantExpression; import org.apache.qpid.server.filter.Expression; +import org.apache.qpid.server.filter.NamedExpression; import org.apache.qpid.server.filter.OrderByExpression; import org.apache.qpid.server.filter.LogicExpression; import org.apache.qpid.server.filter.UnaryExpression; http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/9704e609/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/query/ConfiguredObjectQuery.java ---------------------------------------------------------------------- diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/query/ConfiguredObjectQuery.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/query/ConfiguredObjectQuery.java index 7fb7fac..1b22da0 100644 --- a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/query/ConfiguredObjectQuery.java +++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/query/ConfiguredObjectQuery.java @@ -54,6 +54,8 @@ public final class ConfiguredObjectQuery { List<String> getHeaders(); List<Expression> getValueExpressions(); + boolean hasHeader(String name); + Expression getValueExpressionForHeader(String name); } public ConfiguredObjectQuery(List<ConfiguredObject<?>> objects, String selectClause, String whereClause) @@ -84,7 +86,7 @@ public final class ConfiguredObjectQuery List<ConfiguredObject<?>> filteredObjects = whereClause == null ? objects : filterObjects(objects, whereClause); List<ConfiguredObject<?>> orderedObjects = orderByClause == null ? filteredObjects : orderObjects(filteredObjects, orderByClause, - headersAndValueExpressions.getValueExpressions()); + headersAndValueExpressions); List<ConfiguredObject<?>> limitedOrderedObjects = applyLimitAndOffset(orderedObjects, limit, offset); _headers = headersAndValueExpressions.getHeaders(); @@ -161,13 +163,31 @@ public final class ConfiguredObjectQuery @Override public List<String> getHeaders() { - return headers; + return Collections.unmodifiableList(headers); } @Override public List<Expression> getValueExpressions() { - return valueExpressions; + return Collections.unmodifiableList(valueExpressions); + } + + @Override + public boolean hasHeader(final String headerName) + { + return headers.contains(headerName); + } + + @Override + public Expression getValueExpressionForHeader(final String headerName) + { + final int i = headers.indexOf(headerName); + if (i < 0) + { + throw new IllegalStateException(String.format("No expression found for header '%s'", headerName)); + } + + return valueExpressions.get(i); } }; } @@ -246,8 +266,9 @@ public final class ConfiguredObjectQuery private final List<OrderByExpression> _orderByExpressions; public OrderByComparator(final List<OrderByExpression> orderByExpressions, - final List<Expression> valueExpressions) + final HeadersAndValueExpressions headersAndValue) { + final List<Expression> valueExpressions = headersAndValue.getValueExpressions(); _orderByExpressions = new ArrayList<>(orderByExpressions); for (ListIterator<OrderByExpression> iterator = _orderByExpressions.listIterator(); iterator.hasNext(); ) { @@ -266,6 +287,12 @@ public final class ConfiguredObjectQuery iterator.set(orderByExpression); } } + else if (orderByExpression.isNamed() && headersAndValue.hasHeader(orderByExpression.getName())) + { + Expression expression = headersAndValue.getValueExpressionForHeader(orderByExpression.getName()); + orderByExpression = new OrderByExpression(expression, orderByExpression.getOrder()); + iterator.set(orderByExpression); + } } } @@ -313,13 +340,13 @@ public final class ConfiguredObjectQuery } private List<ConfiguredObject<?>> orderObjects(final List<ConfiguredObject<?>> unorderedResults, - String orderByClause, - final List<Expression> valueExpressions) + final String orderByClause, + final HeadersAndValueExpressions headersAndValue) { List<OrderByExpression> orderByExpressions = parseOrderByClause(orderByClause); List<ConfiguredObject<?>> orderedObjects = new ArrayList<>(unorderedResults.size()); orderedObjects.addAll(unorderedResults); - Comparator<Object> comparator = new OrderByComparator(orderByExpressions, valueExpressions); + Comparator<Object> comparator = new OrderByComparator(orderByExpressions, headersAndValue); Collections.sort(orderedObjects, comparator); return orderedObjects; } http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/9704e609/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/query/NamedExpression.java ---------------------------------------------------------------------- diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/query/NamedExpression.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/query/NamedExpression.java deleted file mode 100644 index 00b42d5..0000000 --- a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/query/NamedExpression.java +++ /dev/null @@ -1,28 +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.qpid.server.management.plugin.servlet.query; - -import org.apache.qpid.server.filter.Expression; - -public interface NamedExpression<E> extends Expression<E> -{ - String getName(); -} http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/9704e609/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/query/ConfiguredObjectQueryTest.java ---------------------------------------------------------------------- diff --git a/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/query/ConfiguredObjectQueryTest.java b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/query/ConfiguredObjectQueryTest.java index 61053bc..b903a41 100644 --- a/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/query/ConfiguredObjectQueryTest.java +++ b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/query/ConfiguredObjectQueryTest.java @@ -61,7 +61,7 @@ public class ConfiguredObjectQueryTest extends QpidTestCase private final List<ConfiguredObject<?>> _objects = new ArrayList<>(); private ConfiguredObjectQuery _query; - public void testNoClauses_SingleResult() throws Exception + public void testNoClauses_SingleResult() { final UUID objectUuid = UUID.randomUUID(); final String objectName = "obj1"; @@ -86,7 +86,7 @@ public class ConfiguredObjectQueryTest extends QpidTestCase assertEquals("Unexpected row", Lists.newArrayList(objectUuid, objectName), row); } - public void testArithmeticStatementInOrderBy() throws Exception + public void testArithmeticStatementInOrderBy() { final List<OrderByExpression> orderByExpressions; String orderByClause = "a + b"; @@ -104,15 +104,14 @@ public class ConfiguredObjectQueryTest extends QpidTestCase } - public void testInvalidStatementInOrderBy() throws Exception + public void testInvalidStatementInOrderBy() { - final List<OrderByExpression> orderByExpressions; String orderByClause = "a + b foo"; ConfiguredObjectFilterParser parser = new ConfiguredObjectFilterParser(); parser.setConfiguredObjectExpressionFactory(new ConfiguredObjectExpressionFactory()); try { - orderByExpressions = parser.parseOrderBy(orderByClause); + parser.parseOrderBy(orderByClause); fail("Invalid expression was parsed without exception"); } catch (ParseException | TokenMgrError e) @@ -121,7 +120,7 @@ public class ConfiguredObjectQueryTest extends QpidTestCase } } - public void testNoClauses_TwoResult() throws Exception + public void testNoClauses_TwoResult() { final UUID object1Uuid = UUID.randomUUID(); final String object1Name = "obj1"; @@ -158,7 +157,7 @@ public class ConfiguredObjectQueryTest extends QpidTestCase assertEquals("Unexpected row", Lists.newArrayList(object2Uuid, object2Name), row2); } - public void testSelectClause() throws Exception + public void testSelectClause() { final UUID objectUuid = UUID.randomUUID(); @@ -185,7 +184,7 @@ public class ConfiguredObjectQueryTest extends QpidTestCase assertEquals("Unexpected row", Lists.newArrayList(objectUuid, 1234), row); } - public void testSelectClause_NonExistingColumn() throws Exception + public void testSelectClause_NonExistingColumn() { ConfiguredObject obj = createCO(new HashMap<String, Object>() {{ @@ -193,14 +192,14 @@ public class ConfiguredObjectQueryTest extends QpidTestCase }}); _objects.add(obj); - _query = new ConfiguredObjectQuery(_objects, String.format("foo"), null); + _query = new ConfiguredObjectQuery(_objects, "foo", null); List<List<Object>> results = _query.getResults(); assertEquals("Unexpected number of results", 1, results.size()); assertEquals("Unexpected headers", Collections.singletonList("foo"), _query.getHeaders()); assertEquals("Unexpected row", Collections.singletonList(null), results.get(0)); } - public void testSelectClause_ColumnAliases() throws Exception + public void testSelectClause_ColumnAliases() { final UUID objectUuid = UUID.randomUUID(); @@ -228,7 +227,7 @@ public class ConfiguredObjectQueryTest extends QpidTestCase assertEquals("Unexpected row", Lists.newArrayList(objectUuid, "myObj1234"), row); } - public void testQuery_StringEquality() throws Exception + public void testQuery_StringEquality() { final UUID objectUuid = UUID.randomUUID(); final String objectName = "obj2"; @@ -261,7 +260,7 @@ public class ConfiguredObjectQueryTest extends QpidTestCase assertEquals("Unexpected row", objectUuid, row.get(0)); } - public void testQuery_DateInequality() throws Exception + public void testQuery_DateInequality() { final long now = System.currentTimeMillis(); final UUID objectUuid = UUID.randomUUID(); @@ -296,7 +295,7 @@ public class ConfiguredObjectQueryTest extends QpidTestCase assertEquals("Unexpected row", objectUuid, row.get(0)); } - public void testQuery_DateEquality() throws Exception + public void testQuery_DateEquality() { final long now = System.currentTimeMillis(); final Calendar calendar = Calendar.getInstance(); @@ -333,7 +332,7 @@ public class ConfiguredObjectQueryTest extends QpidTestCase assertEquals("Unexpected row", objectUuid, row.get(0)); } - public void testQuery_DateExpressions() throws Exception + public void testQuery_DateExpressions() { final UUID objectUuid = UUID.randomUUID(); @@ -360,7 +359,7 @@ public class ConfiguredObjectQueryTest extends QpidTestCase assertEquals("Unexpected row", objectUuid, row.get(0)); } - public void testDateToString() throws Exception + public void testDateToString() { final UUID objectUuid = UUID.randomUUID(); @@ -384,7 +383,7 @@ public class ConfiguredObjectQueryTest extends QpidTestCase assertEquals("Unexpected row", Lists.newArrayList(objectUuid, "1970-01-01T00:00:00Z"), row); } - public void testDateToFormattedString() throws Exception + public void testDateToFormattedString() { final UUID objectUuid = UUID.randomUUID(); @@ -411,7 +410,7 @@ public class ConfiguredObjectQueryTest extends QpidTestCase assertEquals("Unexpected row", Lists.newArrayList(objectUuid, "1970-01-01 UTC"), row); } - public void testQuery_EnumEquality() throws Exception + public void testQuery_EnumEquality() { final UUID objectUuid = UUID.randomUUID(); @@ -460,7 +459,7 @@ public class ConfiguredObjectQueryTest extends QpidTestCase } - public void testQuery_EnumEquality_InExpresssions() throws Exception + public void testQuery_EnumEquality_InExpresssions() { final UUID objectUuid = UUID.randomUUID(); @@ -497,7 +496,7 @@ public class ConfiguredObjectQueryTest extends QpidTestCase assertEquals("Unexpected number of results - attribute within the set", 1, results.size()); } - public void testFunctionActualParameterMismatch() throws Exception + public void testFunctionActualParameterMismatch() { try { @@ -512,7 +511,7 @@ public class ConfiguredObjectQueryTest extends QpidTestCase } } - public void testSingleOrderByClause() throws Exception + public void testSingleOrderByClause() { final int NUMBER_OF_OBJECTS = 3; @@ -548,7 +547,49 @@ public class ConfiguredObjectQueryTest extends QpidTestCase assertQueryResults(new Object[][]{{null}, {0}, {1}, {2}}, results); } - public void testTwoOrderByClauses() throws Exception + public void testAliasInOrderByClause() + { + _objects.add(createCO(new HashMap<String, Object>() + {{ + put("foo", 2); + }})); + + _objects.add(createCO(new HashMap<String, Object>() + {{ + put("foo", 1); + }})); + + _objects.add(createCO(new HashMap<String, Object>() + {{ + put("foo", 4); + }})); + + _query = new ConfiguredObjectQuery(_objects, "foo AS bar", null, "bar ASC"); + assertQueryResults(new Object[][]{{1}, {2}, {4}}, _query.getResults()); + } + + public void testDelimitedAliasInOrderByClause() + { + _objects.add(createCO(new HashMap<String, Object>() + {{ + put("foo", 2); + }})); + + _objects.add(createCO(new HashMap<String, Object>() + {{ + put("foo", 1); + }})); + + _objects.add(createCO(new HashMap<String, Object>() + {{ + put("foo", 4); + }})); + + _query = new ConfiguredObjectQuery(_objects, "foo AS \"yogi bear\"", null, "\"yogi bear\" DESC"); + assertQueryResults(new Object[][]{{4}, {2}, {1}}, _query.getResults()); + } + + public void testTwoOrderByClauses() { ConfiguredObject object; @@ -634,7 +675,7 @@ public class ConfiguredObjectQueryTest extends QpidTestCase } - public void testLimitWithoutOffset() throws Exception + public void testLimitWithoutOffset() { int numberOfTestObjects = 3; for(int i=0;i<numberOfTestObjects;i++) --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
