You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@metamodel.apache.org by ka...@apache.org on 2015/12/07 14:44:49 UTC
metamodel git commit: METAMODEL-216: Fixed
Repository: metamodel
Updated Branches:
refs/heads/master a8ab3c5a8 -> 300e6b67c
METAMODEL-216: Fixed
Fixes #74
Project: http://git-wip-us.apache.org/repos/asf/metamodel/repo
Commit: http://git-wip-us.apache.org/repos/asf/metamodel/commit/300e6b67
Tree: http://git-wip-us.apache.org/repos/asf/metamodel/tree/300e6b67
Diff: http://git-wip-us.apache.org/repos/asf/metamodel/diff/300e6b67
Branch: refs/heads/master
Commit: 300e6b67c33cb04feecef7dbf99beb3bc19ffc45
Parents: a8ab3c5
Author: Kasper Sørensen <i....@gmail.com>
Authored: Mon Dec 7 14:41:26 2015 +0100
Committer: Kasper Sørensen <i....@gmail.com>
Committed: Mon Dec 7 14:41:26 2015 +0100
----------------------------------------------------------------------
CHANGES.md | 1 +
.../metamodel/query/FirstAggregateBuilder.java | 43 ++++++++++++
.../metamodel/query/FirstAggregateFunction.java | 35 ++++++++++
.../apache/metamodel/query/FunctionType.java | 3 +
.../metamodel/query/FunctionTypeFactory.java | 7 ++
.../metamodel/query/LastAggregateBuilder.java | 43 ++++++++++++
.../metamodel/query/LastAggregateFunction.java | 35 ++++++++++
.../metamodel/query/RandomAggregateBuilder.java | 55 +++++++++++++++
.../query/RandomAggregateFunction.java | 35 ++++++++++
.../QueryPostprocessDataContextTest.java | 18 +++++
.../query/FirstAggregateFunctionTest.java | 51 ++++++++++++++
.../query/LastAggregateFunctionTest.java | 51 ++++++++++++++
.../query/RandomAggregateBuilderTest.java | 71 ++++++++++++++++++++
.../query/RandomAggregateFunctionTest.java | 55 +++++++++++++++
.../apache/metamodel/jdbc/JdbcDataContext.java | 9 +++
.../jdbc/dialects/DefaultQueryRewriter.java | 20 +++++-
.../metamodel/jdbc/dialects/IQueryRewriter.java | 13 ++++
.../metamodel/jdbc/JdbcDataContextTest.java | 12 ++++
18 files changed, 556 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/metamodel/blob/300e6b67/CHANGES.md
----------------------------------------------------------------------
diff --git a/CHANGES.md b/CHANGES.md
index 6df60a6..e739b5f 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -3,6 +3,7 @@
* [METAMODEL-212] - New module for ElasticSearch via REST client.
* [METAMODEL-207] - Ensured the serializability of the SingleLineCsvRow class.
* [METAMODEL-211] - Fixed a bug related to lookup by primary key (_id) on MongoDB.
+ * [METAMODEL-216] - Added new aggregate functions: FIRST, LAST and RANDOM.
* [METAMODEL-15] - Query parser support for table names with space. Delimitters can be double quote or square brackets.
* [METAMODEL-215] - Improved the capability of NumberComparator to support Integer, Long, Double, BigInteger and other built-in Number classes.
http://git-wip-us.apache.org/repos/asf/metamodel/blob/300e6b67/core/src/main/java/org/apache/metamodel/query/FirstAggregateBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/FirstAggregateBuilder.java b/core/src/main/java/org/apache/metamodel/query/FirstAggregateBuilder.java
new file mode 100644
index 0000000..2002076
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/FirstAggregateBuilder.java
@@ -0,0 +1,43 @@
+/**
+ * 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.metamodel.query;
+
+import org.apache.metamodel.util.AggregateBuilder;
+
+public class FirstAggregateBuilder implements AggregateBuilder<Object> {
+
+ private Object _result;
+
+ public FirstAggregateBuilder() {
+ _result = null;
+ }
+
+ @Override
+ public void add(Object o) {
+ if (_result == null) {
+ _result = o;
+ }
+ }
+
+ @Override
+ public Object getAggregate() {
+ return _result;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/metamodel/blob/300e6b67/core/src/main/java/org/apache/metamodel/query/FirstAggregateFunction.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/FirstAggregateFunction.java b/core/src/main/java/org/apache/metamodel/query/FirstAggregateFunction.java
new file mode 100644
index 0000000..b83f2e1
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/FirstAggregateFunction.java
@@ -0,0 +1,35 @@
+/**
+ * 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.metamodel.query;
+
+import org.apache.metamodel.util.AggregateBuilder;
+
+public class FirstAggregateFunction extends DefaultAggregateFunction<Object> {
+
+ @Override
+ public AggregateBuilder<?> createAggregateBuilder() {
+ return new FirstAggregateBuilder();
+ }
+
+ @Override
+ public String getFunctionName() {
+ return "FIRST";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/metamodel/blob/300e6b67/core/src/main/java/org/apache/metamodel/query/FunctionType.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/FunctionType.java b/core/src/main/java/org/apache/metamodel/query/FunctionType.java
index 0ef259a..bb4a11b 100644
--- a/core/src/main/java/org/apache/metamodel/query/FunctionType.java
+++ b/core/src/main/java/org/apache/metamodel/query/FunctionType.java
@@ -32,6 +32,9 @@ public interface FunctionType {
public static final AggregateFunction SUM = new SumAggregateFunction();
public static final AggregateFunction MAX = new MaxAggregateFunction();
public static final AggregateFunction MIN = new MinAggregateFunction();
+ public static final AggregateFunction RANDOM = new RandomAggregateFunction();
+ public static final AggregateFunction FIRST = new FirstAggregateFunction();
+ public static final AggregateFunction LAST = new LastAggregateFunction();
public static final ScalarFunction TO_STRING = new ToStringFunction();
public static final ScalarFunction TO_NUMBER = new ToNumberFunction();
public static final ScalarFunction TO_DATE = new ToDateFunction();
http://git-wip-us.apache.org/repos/asf/metamodel/blob/300e6b67/core/src/main/java/org/apache/metamodel/query/FunctionTypeFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/FunctionTypeFactory.java b/core/src/main/java/org/apache/metamodel/query/FunctionTypeFactory.java
index c021ae3..be98f07 100644
--- a/core/src/main/java/org/apache/metamodel/query/FunctionTypeFactory.java
+++ b/core/src/main/java/org/apache/metamodel/query/FunctionTypeFactory.java
@@ -42,6 +42,13 @@ public class FunctionTypeFactory {
return FunctionType.MAX;
case "MIN":
return FunctionType.MIN;
+ case "RANDOM":
+ case "RAND":
+ return FunctionType.RANDOM;
+ case "FIRST":
+ return FunctionType.FIRST;
+ case "LAST":
+ return FunctionType.LAST;
case "TO_NUMBER":
case "NUMBER":
case "TO_NUM":
http://git-wip-us.apache.org/repos/asf/metamodel/blob/300e6b67/core/src/main/java/org/apache/metamodel/query/LastAggregateBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/LastAggregateBuilder.java b/core/src/main/java/org/apache/metamodel/query/LastAggregateBuilder.java
new file mode 100644
index 0000000..beac269
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/LastAggregateBuilder.java
@@ -0,0 +1,43 @@
+/**
+ * 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.metamodel.query;
+
+import org.apache.metamodel.util.AggregateBuilder;
+
+public class LastAggregateBuilder implements AggregateBuilder<Object> {
+
+ private Object _result;
+
+ public LastAggregateBuilder() {
+ _result = null;
+ }
+
+ @Override
+ public void add(Object o) {
+ if (o != null) {
+ _result = o;
+ }
+ }
+
+ @Override
+ public Object getAggregate() {
+ return _result;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/metamodel/blob/300e6b67/core/src/main/java/org/apache/metamodel/query/LastAggregateFunction.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/LastAggregateFunction.java b/core/src/main/java/org/apache/metamodel/query/LastAggregateFunction.java
new file mode 100644
index 0000000..4fa532e
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/LastAggregateFunction.java
@@ -0,0 +1,35 @@
+/**
+ * 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.metamodel.query;
+
+import org.apache.metamodel.util.AggregateBuilder;
+
+public class LastAggregateFunction extends DefaultAggregateFunction<Object> {
+
+ @Override
+ public AggregateBuilder<?> createAggregateBuilder() {
+ return new LastAggregateBuilder();
+ }
+
+ @Override
+ public String getFunctionName() {
+ return "LAST";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/metamodel/blob/300e6b67/core/src/main/java/org/apache/metamodel/query/RandomAggregateBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/RandomAggregateBuilder.java b/core/src/main/java/org/apache/metamodel/query/RandomAggregateBuilder.java
new file mode 100644
index 0000000..3fe9427
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/RandomAggregateBuilder.java
@@ -0,0 +1,55 @@
+/**
+ * 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.metamodel.query;
+
+import java.util.Random;
+
+import org.apache.metamodel.util.AggregateBuilder;
+
+public class RandomAggregateBuilder implements AggregateBuilder<Object> {
+
+ private Object _result;
+ private long _count;
+ private final Random _random;
+
+ public RandomAggregateBuilder() {
+ _result = null;
+ _count = 0;
+ _random = new Random();
+ }
+
+ @Override
+ public void add(Object o) {
+ if (o == null) {
+ return;
+ }
+
+ _count++;
+
+ if (_random.nextDouble() < (1d / _count)) {
+ _result = o;
+ }
+ }
+
+ @Override
+ public Object getAggregate() {
+ return _result;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/metamodel/blob/300e6b67/core/src/main/java/org/apache/metamodel/query/RandomAggregateFunction.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/RandomAggregateFunction.java b/core/src/main/java/org/apache/metamodel/query/RandomAggregateFunction.java
new file mode 100644
index 0000000..1a53816
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/RandomAggregateFunction.java
@@ -0,0 +1,35 @@
+/**
+ * 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.metamodel.query;
+
+import org.apache.metamodel.util.AggregateBuilder;
+
+public class RandomAggregateFunction extends DefaultAggregateFunction<Object> {
+
+ @Override
+ public AggregateBuilder<?> createAggregateBuilder() {
+ return new RandomAggregateBuilder();
+ }
+
+ @Override
+ public String getFunctionName() {
+ return "RANDOM";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/metamodel/blob/300e6b67/core/src/test/java/org/apache/metamodel/QueryPostprocessDataContextTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/metamodel/QueryPostprocessDataContextTest.java b/core/src/test/java/org/apache/metamodel/QueryPostprocessDataContextTest.java
index d8d046c..7dcaa12 100644
--- a/core/src/test/java/org/apache/metamodel/QueryPostprocessDataContextTest.java
+++ b/core/src/test/java/org/apache/metamodel/QueryPostprocessDataContextTest.java
@@ -185,6 +185,24 @@ public class QueryPostprocessDataContextTest extends MetaModelTestCase {
dataSet.close();
}
+ public void testNewAggregateFunctions() throws Exception {
+ MockDataContext dc = new MockDataContext("sch", "tab", null);
+ Table table = dc.getDefaultSchema().getTables()[0];
+ DataSet dataSet = dc.query().from(table).select(FunctionType.FIRST, "foo").select(FunctionType.LAST, "foo")
+ .select(FunctionType.RANDOM, "foo").execute();
+ assertTrue(dataSet.next());
+
+ final Row row = dataSet.getRow();
+ assertEquals("1", row.getValue(0));
+ assertEquals("4", row.getValue(1));
+
+ final Object randomValue = row.getValue(2);
+ assertTrue(Arrays.asList("1", "2", "3", "4").contains(randomValue));
+
+ assertFalse(dataSet.next());
+ dataSet.close();
+ }
+
public void testAggregateQueryWhereClauseExcludingAll() throws Exception {
MockDataContext dc = new MockDataContext("sch", "tab", "1");
assertSingleRowResult("Row[values=[0]]",
http://git-wip-us.apache.org/repos/asf/metamodel/blob/300e6b67/core/src/test/java/org/apache/metamodel/query/FirstAggregateFunctionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/metamodel/query/FirstAggregateFunctionTest.java b/core/src/test/java/org/apache/metamodel/query/FirstAggregateFunctionTest.java
new file mode 100644
index 0000000..f29e5c4
--- /dev/null
+++ b/core/src/test/java/org/apache/metamodel/query/FirstAggregateFunctionTest.java
@@ -0,0 +1,51 @@
+/**
+ * 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.metamodel.query;
+
+import static org.junit.Assert.*;
+
+import org.apache.metamodel.schema.ColumnType;
+import org.apache.metamodel.util.AggregateBuilder;
+import org.junit.Test;
+
+public class FirstAggregateFunctionTest {
+
+ private static final AggregateFunction FUNCTION = FunctionType.FIRST;
+
+ @Test
+ public void testGetName() throws Exception {
+ assertEquals("FIRST", FUNCTION.getFunctionName());
+ assertEquals("FIRST", FUNCTION.toString());
+ }
+
+ @Test
+ public void testDataType() throws Exception {
+ assertEquals(ColumnType.BIGINT, FUNCTION.getExpectedColumnType(ColumnType.BIGINT));
+ assertEquals(ColumnType.STRING, FUNCTION.getExpectedColumnType(ColumnType.STRING));
+ }
+
+ @Test
+ public void testBuildAggregate() throws Exception {
+ final AggregateBuilder<?> aggregateBuilder = FUNCTION.createAggregateBuilder();
+ aggregateBuilder.add("1");
+ aggregateBuilder.add("2");
+ aggregateBuilder.add("3");
+ assertEquals("1", aggregateBuilder.getAggregate());
+ }
+}
http://git-wip-us.apache.org/repos/asf/metamodel/blob/300e6b67/core/src/test/java/org/apache/metamodel/query/LastAggregateFunctionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/metamodel/query/LastAggregateFunctionTest.java b/core/src/test/java/org/apache/metamodel/query/LastAggregateFunctionTest.java
new file mode 100644
index 0000000..1c26b78
--- /dev/null
+++ b/core/src/test/java/org/apache/metamodel/query/LastAggregateFunctionTest.java
@@ -0,0 +1,51 @@
+/**
+ * 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.metamodel.query;
+
+import static org.junit.Assert.*;
+
+import org.apache.metamodel.schema.ColumnType;
+import org.apache.metamodel.util.AggregateBuilder;
+import org.junit.Test;
+
+public class LastAggregateFunctionTest {
+
+ private static final AggregateFunction FUNCTION = FunctionType.LAST;
+
+ @Test
+ public void testGetName() throws Exception {
+ assertEquals("LAST", FUNCTION.getFunctionName());
+ assertEquals("LAST", FUNCTION.toString());
+ }
+
+ @Test
+ public void testDataType() throws Exception {
+ assertEquals(ColumnType.BIGINT, FUNCTION.getExpectedColumnType(ColumnType.BIGINT));
+ assertEquals(ColumnType.STRING, FUNCTION.getExpectedColumnType(ColumnType.STRING));
+ }
+
+ @Test
+ public void testBuildAggregate() throws Exception {
+ final AggregateBuilder<?> aggregateBuilder = FUNCTION.createAggregateBuilder();
+ aggregateBuilder.add("1");
+ aggregateBuilder.add("2");
+ aggregateBuilder.add("3");
+ assertEquals("3", aggregateBuilder.getAggregate());
+ }
+}
http://git-wip-us.apache.org/repos/asf/metamodel/blob/300e6b67/core/src/test/java/org/apache/metamodel/query/RandomAggregateBuilderTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/metamodel/query/RandomAggregateBuilderTest.java b/core/src/test/java/org/apache/metamodel/query/RandomAggregateBuilderTest.java
new file mode 100644
index 0000000..005da55
--- /dev/null
+++ b/core/src/test/java/org/apache/metamodel/query/RandomAggregateBuilderTest.java
@@ -0,0 +1,71 @@
+/**
+ * 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.metamodel.query;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.junit.Test;
+
+public class RandomAggregateBuilderTest {
+
+ @Test
+ public void testOnlyOne() throws Exception {
+ RandomAggregateBuilder aggregateBuilder = new RandomAggregateBuilder();
+ aggregateBuilder.add("foo");
+ assertEquals("foo", aggregateBuilder.getAggregate());
+ }
+
+ @Test
+ public void testRandomBehaviour() throws Exception {
+ // run 1000 tests with 3 values to ensure that there is at least an
+ // approximate fair distribution of randomized results
+ final int samples = 10000;
+ final int minimumExpectation = samples / 5;
+
+ final Map<String, AtomicInteger> counterMap = new HashMap<>();
+ counterMap.put("foo", new AtomicInteger());
+ counterMap.put("bar", new AtomicInteger());
+ counterMap.put("baz", new AtomicInteger());
+
+ for (int i = 0; i < samples; i++) {
+ final RandomAggregateBuilder aggregateBuilder = new RandomAggregateBuilder();
+ aggregateBuilder.add("foo");
+ aggregateBuilder.add(null);
+ aggregateBuilder.add("bar");
+ aggregateBuilder.add("baz");
+
+ counterMap.get(aggregateBuilder.getAggregate()).incrementAndGet();
+ }
+
+ final String messageString = "got: " + counterMap.toString();
+ final Set<Entry<String, AtomicInteger>> entries = counterMap.entrySet();
+ for (Entry<String, AtomicInteger> entry : entries) {
+ final int count = entry.getValue().get();
+ if (count < minimumExpectation) {
+ assertEquals(messageString, minimumExpectation, count);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/metamodel/blob/300e6b67/core/src/test/java/org/apache/metamodel/query/RandomAggregateFunctionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/metamodel/query/RandomAggregateFunctionTest.java b/core/src/test/java/org/apache/metamodel/query/RandomAggregateFunctionTest.java
new file mode 100644
index 0000000..a6bf6c4
--- /dev/null
+++ b/core/src/test/java/org/apache/metamodel/query/RandomAggregateFunctionTest.java
@@ -0,0 +1,55 @@
+/**
+ * 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.metamodel.query;
+
+import static org.junit.Assert.*;
+
+import java.util.Arrays;
+
+import org.apache.metamodel.schema.ColumnType;
+import org.apache.metamodel.util.AggregateBuilder;
+import org.junit.Test;
+
+public class RandomAggregateFunctionTest {
+
+ private static final AggregateFunction FUNCTION = FunctionType.RANDOM;
+
+ @Test
+ public void testGetName() throws Exception {
+ assertEquals("RANDOM", FUNCTION.getFunctionName());
+ assertEquals("RANDOM", FUNCTION.toString());
+ }
+
+ @Test
+ public void testDataType() throws Exception {
+ assertEquals(ColumnType.BIGINT, FUNCTION.getExpectedColumnType(ColumnType.BIGINT));
+ assertEquals(ColumnType.STRING, FUNCTION.getExpectedColumnType(ColumnType.STRING));
+ }
+
+ @Test
+ public void testBuildAggregate() throws Exception {
+ final AggregateBuilder<?> aggregateBuilder = FUNCTION.createAggregateBuilder();
+ aggregateBuilder.add("foo");
+ aggregateBuilder.add("bar");
+ aggregateBuilder.add("baz");
+ final Object aggregate = aggregateBuilder.getAggregate();
+
+ assertTrue(Arrays.asList("foo", "bar", "baz").contains(aggregate));
+ }
+}
http://git-wip-us.apache.org/repos/asf/metamodel/blob/300e6b67/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcDataContext.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcDataContext.java b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcDataContext.java
index 27f638b..84254f9 100644
--- a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcDataContext.java
+++ b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcDataContext.java
@@ -55,6 +55,7 @@ import org.apache.metamodel.jdbc.dialects.OracleQueryRewriter;
import org.apache.metamodel.jdbc.dialects.PostgresqlQueryRewriter;
import org.apache.metamodel.jdbc.dialects.SQLServerQueryRewriter;
import org.apache.metamodel.jdbc.dialects.SQLiteQueryRewriter;
+import org.apache.metamodel.query.AggregateFunction;
import org.apache.metamodel.query.CompiledQuery;
import org.apache.metamodel.query.Query;
import org.apache.metamodel.query.SelectItem;
@@ -353,6 +354,14 @@ public class JdbcDataContext extends AbstractDataContext implements UpdateableDa
+ query);
}
+ for (SelectItem selectItem : selectItems) {
+ final AggregateFunction aggregateFunction = selectItem.getAggregateFunction();
+ if (aggregateFunction != null && !_queryRewriter.isAggregateFunctionSupported(aggregateFunction)) {
+ throw new MetaModelException("Aggregate function '" + aggregateFunction.getFunctionName()
+ + "' is not supported on this JDBC database. Query rejected: " + query);
+ }
+ }
+
if (_databaseProductName.equals(DATABASE_PRODUCT_POSTGRESQL)) {
try {
// this has to be done in order to make a result set not load
http://git-wip-us.apache.org/repos/asf/metamodel/blob/300e6b67/jdbc/src/main/java/org/apache/metamodel/jdbc/dialects/DefaultQueryRewriter.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/metamodel/jdbc/dialects/DefaultQueryRewriter.java b/jdbc/src/main/java/org/apache/metamodel/jdbc/dialects/DefaultQueryRewriter.java
index 13db9df..cbdb3c5 100644
--- a/jdbc/src/main/java/org/apache/metamodel/jdbc/dialects/DefaultQueryRewriter.java
+++ b/jdbc/src/main/java/org/apache/metamodel/jdbc/dialects/DefaultQueryRewriter.java
@@ -19,16 +19,26 @@
package org.apache.metamodel.jdbc.dialects;
import java.sql.Timestamp;
+import java.util.Arrays;
+import java.util.HashSet;
import java.util.List;
import java.util.ListIterator;
+import java.util.Set;
import org.apache.metamodel.jdbc.JdbcDataContext;
+import org.apache.metamodel.query.AggregateFunction;
+import org.apache.metamodel.query.AverageAggregateFunction;
+import org.apache.metamodel.query.CountAggregateFunction;
import org.apache.metamodel.query.FilterItem;
import org.apache.metamodel.query.FromItem;
+import org.apache.metamodel.query.FunctionType;
+import org.apache.metamodel.query.MaxAggregateFunction;
+import org.apache.metamodel.query.MinAggregateFunction;
import org.apache.metamodel.query.OperatorType;
import org.apache.metamodel.query.Query;
import org.apache.metamodel.query.ScalarFunction;
import org.apache.metamodel.query.SelectItem;
+import org.apache.metamodel.query.SumAggregateFunction;
import org.apache.metamodel.schema.ColumnType;
import org.apache.metamodel.util.CollectionUtils;
@@ -39,6 +49,9 @@ import org.apache.metamodel.util.CollectionUtils;
public class DefaultQueryRewriter extends AbstractQueryRewriter {
private static final String SPECIAL_ALIAS_CHARACTERS = "- ,.|*%()!#¤/\\=?;:~";
+ private static final Set<Class<? extends FunctionType>> SUPPORTED_FUNCTION_CLASSES = new HashSet<>(
+ Arrays.<Class<? extends FunctionType>> asList(CountAggregateFunction.class, SumAggregateFunction.class,
+ MaxAggregateFunction.class, MinAggregateFunction.class, AverageAggregateFunction.class));
public DefaultQueryRewriter(JdbcDataContext dataContext) {
super(dataContext);
@@ -184,7 +197,12 @@ public class DefaultQueryRewriter extends AbstractQueryRewriter {
@Override
public boolean isScalarFunctionSupported(ScalarFunction function) {
- return false;
+ return SUPPORTED_FUNCTION_CLASSES.contains(function.getClass());
+ }
+
+ @Override
+ public boolean isAggregateFunctionSupported(AggregateFunction function) {
+ return SUPPORTED_FUNCTION_CLASSES.contains(function.getClass());
}
@Override
http://git-wip-us.apache.org/repos/asf/metamodel/blob/300e6b67/jdbc/src/main/java/org/apache/metamodel/jdbc/dialects/IQueryRewriter.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/metamodel/jdbc/dialects/IQueryRewriter.java b/jdbc/src/main/java/org/apache/metamodel/jdbc/dialects/IQueryRewriter.java
index 9562b67..f867cb1 100644
--- a/jdbc/src/main/java/org/apache/metamodel/jdbc/dialects/IQueryRewriter.java
+++ b/jdbc/src/main/java/org/apache/metamodel/jdbc/dialects/IQueryRewriter.java
@@ -21,6 +21,7 @@ package org.apache.metamodel.jdbc.dialects;
import java.sql.Types;
import org.apache.metamodel.jdbc.JdbcDataContext;
+import org.apache.metamodel.query.AggregateFunction;
import org.apache.metamodel.query.FilterItem;
import org.apache.metamodel.query.FromItem;
import org.apache.metamodel.query.Query;
@@ -75,6 +76,18 @@ public interface IQueryRewriter {
public boolean isScalarFunctionSupported(ScalarFunction function);
/**
+ * Determines whether a specific aggregate function is supported by the
+ * database or not.
+ *
+ * If the function is not supported then MetaModel will handle the function
+ * on the client side.
+ *
+ * @param function
+ * @return
+ */
+ public boolean isAggregateFunctionSupported(AggregateFunction function);
+
+ /**
* Escapes the quotes within a String literal of a query item.
*
* @return String item with quotes escaped.
http://git-wip-us.apache.org/repos/asf/metamodel/blob/300e6b67/jdbc/src/test/java/org/apache/metamodel/jdbc/JdbcDataContextTest.java
----------------------------------------------------------------------
diff --git a/jdbc/src/test/java/org/apache/metamodel/jdbc/JdbcDataContextTest.java b/jdbc/src/test/java/org/apache/metamodel/jdbc/JdbcDataContextTest.java
index 63af5d3..17b86fa 100644
--- a/jdbc/src/test/java/org/apache/metamodel/jdbc/JdbcDataContextTest.java
+++ b/jdbc/src/test/java/org/apache/metamodel/jdbc/JdbcDataContextTest.java
@@ -261,6 +261,18 @@ public class JdbcDataContextTest extends JdbcTestCase {
}
}
+ public void testUnsupportedAggregateFunction() throws Exception {
+ final Connection connection = getTestDbConnection();
+ final JdbcDataContext dataContext = new JdbcDataContext(connection);
+ try {
+ dataContext.query().from("customers").select(FunctionType.RANDOM, "customernumber").execute();
+ fail("Exception expected");
+ } catch (MetaModelException e) {
+ assertEquals("Aggregate function 'RANDOM' is not supported on this JDBC database. Query rejected: "
+ + "SELECT RANDOM(\"CUSTOMERS\".\"CUSTOMERNUMBER\") FROM PUBLIC.\"CUSTOMERS\"", e.getMessage());
+ }
+ }
+
public void testExecuteQueryWithComparisonGreaterThanOrEquals() throws Exception {
Connection connection = getTestDbConnection();
JdbcDataContext dataContext = new JdbcDataContext(connection,