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,